[FFmpeg-devel] [PATCH v3 1/2] fftools/resources: clean up and improve resource manager build system

Ramiro Polla ramiro.polla at gmail.com
Fri May 30 13:52:05 EEST 2025


- move .gitignore entries to main .gitignore;
- move vpath directives to main Makefile;
- remove superfluous comments;
- turn css minification sed command into a one-liner;
- deduplicate targets depending on CONFIG_RESOURCE_COMPRESSION;
- introduce common .res pattern for resource files;
- remove RESOURCEOBJS noop from common.mak (it was never populated);
- add fftools/graph/Makefile;
- rename OBJS-resman to RESMAN-OBJS for consistency;
- move graph.{css,html} to fftools/graph/graphprint.{css,html};
- disable dependency checking for resource files, to prevent spurious
  rebuilds;
- generate resources list at build-time based on all resource files;
- the resource manager now uses the resource filename instead of an ID.

Adding resource files now works from any subdir. Suppose you want to
add a resource file named "foo.html", then all you have to do is:

OBJS-$(CONDITION) += foo.html.res.o

To access the resource, you retrieve it by its name:

data = ff_resman_get_string("foo.html");
---
 .gitignore                                    |  3 ++
 Makefile                                      |  2 +
 ffbuild/common.mak                            | 43 +++----------------
 fftools/Makefile                              |  5 ++-
 fftools/graph/Makefile                        |  8 ++++
 fftools/graph/graphprint.c                    |  4 +-
 .../graph.css => graph/graphprint.css}        |  0
 .../graph.html => graph/graphprint.html}      |  0
 fftools/resources/.gitignore                  |  7 +--
 fftools/resources/Makefile                    | 25 +++++++----
 fftools/resources/resman.c                    | 19 +++-----
 fftools/resources/resman.h                    |  8 +---
 12 files changed, 49 insertions(+), 75 deletions(-)
 create mode 100644 fftools/graph/Makefile
 rename fftools/{resources/graph.css => graph/graphprint.css} (100%)
 rename fftools/{resources/graph.html => graph/graphprint.html} (100%)

diff --git a/.gitignore b/.gitignore
index 59c89da5e0..af5dcdf322 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,6 +26,9 @@
 *.ptx
 *.ptx.c
 *.ptx.gz
+*.css.min
+*.res.c
+*.res.gz
 *_g
 \#*
 .\#*
diff --git a/Makefile b/Makefile
index 877b0071f6..ed456cf071 100644
--- a/Makefile
+++ b/Makefile
@@ -14,6 +14,8 @@ vpath %.texi $(SRC_PATH)
 vpath %.cu   $(SRC_PATH)
 vpath %.ptx  $(SRC_PATH)
 vpath %.metal $(SRC_PATH)
+vpath %.html $(SRC_PATH)
+vpath %.css  $(SRC_PATH)
 vpath %/fate_config.sh.template $(SRC_PATH)
 
 TESTTOOLS   = audiogen videogen rotozoom tiny_psnr tiny_ssim base64 audiomatch
diff --git a/ffbuild/common.mak b/ffbuild/common.mak
index ddf48923ea..aa4e563386 100644
--- a/ffbuild/common.mak
+++ b/ffbuild/common.mak
@@ -139,46 +139,17 @@ else
 	$(BIN2C) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) $@ $(subst .,_,$(basename $(notdir $@)))
 endif
 
-# 1) Preprocess CSS to a minified version
 %.css.min: TAG = SED
 %.css.min: %.css
-	$(M)sed 's!/\\*.*\\*/!!g' $< \
-	| tr '\n' ' ' \
-	| tr -s ' ' \
-	| sed 's/^ //; s/ $$//' \
-	> $@
+	$(M)sed 's!/\\*.*\\*/!!g' $< | tr '\n' ' ' | tr -s ' ' | sed 's/^ //; s/ $$//' > $@
 
-ifdef CONFIG_RESOURCE_COMPRESSION
-
-# 2) Gzip the minified CSS
-%.css.min.gz: TAG = GZIP
-%.css.min.gz: %.css.min
-	$(M)gzip -nc9 $< > $@
-
-# 3) Convert the gzipped CSS to a .c array
-%.css.c: %.css.min.gz $(BIN2CEXE)
-	$(BIN2C) $< $@ $(subst .,_,$(basename $(notdir $@)))
-
-# 4) Gzip the HTML file (no minification needed)
-%.html.gz: TAG = GZIP
-%.html.gz: %.html
+%.res.gz: TAG = GZIP
+%.res.gz: %
 	$(M)gzip -nc9 $< > $@
 
-# 5) Convert the gzipped HTML to a .c array
-%.html.c: %.html.gz $(BIN2CEXE)
+%.res.c: %$(CONFIG_RESOURCE_COMPRESSION:yes=.res.gz) $(BIN2CEXE)
 	$(BIN2C) $< $@ $(subst .,_,$(basename $(notdir $@)))
 
-else   # NO COMPRESSION
-
-# 2) Convert the minified CSS to a .c array
-%.css.c: %.css.min $(BIN2CEXE)
-	$(BIN2C) $< $@ $(subst .,_,$(basename $(notdir $@)))
-
-# 3) Convert the plain HTML to a .c array
-%.html.c: %.html $(BIN2CEXE)
-	$(BIN2C) $< $@ $(subst .,_,$(basename $(notdir $@)))
-endif
-
 clean::
 	$(RM) $(BIN2CEXE) $(CLEANSUFFIXES:%=ffbuild/%)
 
@@ -218,6 +189,7 @@ TOOLS     += $(TOOLS-yes)
 TOOLOBJS  := $(TOOLS:%=tools/%.o)
 TOOLS     := $(TOOLS:%=tools/%$(EXESUF))
 HEADERS   += $(HEADERS-yes)
+RESOBJS   := $(RESOBJS) $(filter %.res.o,$(OBJS))
 
 PATH_LIBNAME = $(foreach NAME,$(1),lib$(NAME)/$($(2)LIBNAME))
 DEP_LIBS := $(foreach lib,$(FFLIBS),$(call PATH_LIBNAME,$(lib),$(CONFIG_SHARED:yes=S)))
@@ -229,10 +201,9 @@ SKIPHEADERS += $(ARCH_HEADERS:%=$(ARCH)/%) $(SKIPHEADERS-)
 SKIPHEADERS := $(SKIPHEADERS:%=$(SUBDIR)%)
 HOBJS        = $(filter-out $(SKIPHEADERS:.h=.h.o),$(ALLHEADERS:.h=.h.o))
 PTXOBJS      = $(filter %.ptx.o,$(OBJS))
-RESOURCEOBJS = $(filter %.css.o %.html.o,$(OBJS))
 $(HOBJS):     CCFLAGS += $(CFLAGS_HEADERS)
 checkheaders: $(HOBJS)
-.SECONDARY:   $(HOBJS:.o=.c) $(PTXOBJS:.o=.c) $(PTXOBJS:.o=.gz) $(PTXOBJS:.o=) $(RESOURCEOBJS:.o=.c) $(RESOURCEOBJS:%.css.o=%.css.min) $(RESOURCEOBJS:%.css.o=%.css.min.gz) $(RESOURCEOBJS:%.html.o=%.html.gz) $(RESOURCEOBJS:.o=)
+.SECONDARY:   $(HOBJS:.o=.c) $(PTXOBJS:.o=.c) $(PTXOBJS:.o=.gz) $(PTXOBJS:.o=)
 
 alltools: $(TOOLS)
 
@@ -252,7 +223,7 @@ $(TOOLOBJS): | tools
 
 OUTDIRS := $(OUTDIRS) $(dir $(OBJS) $(HOBJS) $(HOSTOBJS) $(SHLIBOBJS) $(STLIBOBJS) $(TESTOBJS))
 
-CLEANSUFFIXES     = *.d *.gcda *.gcno *.h.c *.ho *.map *.o *.objs *.pc *.ptx *.ptx.gz *.ptx.c *.ver *.version *.html.gz *.html.c *.css.gz *.css.c  *$(DEFAULT_X86ASMD).asm *~ *.ilk *.pdb
+CLEANSUFFIXES     = *.d *.gcda *.gcno *.h.c *.ho *.map *.o *.objs *.pc *.ptx *.ptx.gz *.ptx.c *.ver *.version *.css.min *.res.gz *.res.c *$(DEFAULT_X86ASMD).asm *~ *.ilk *.pdb
 LIBSUFFIXES       = *.a *.lib *.so *.so.* *.dylib *.dll *.def *.dll.a
 
 define RULES
diff --git a/fftools/Makefile b/fftools/Makefile
index c1eba733da..b6f3438e11 100644
--- a/fftools/Makefile
+++ b/fftools/Makefile
@@ -9,6 +9,7 @@ AVBASENAMES  = ffmpeg ffplay ffprobe
 ALLAVPROGS   = $(AVBASENAMES:%=%$(PROGSSUF)$(EXESUF))
 ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF))
 
+include $(SRC_PATH)/fftools/graph/Makefile
 include $(SRC_PATH)/fftools/resources/Makefile
 
 OBJS-ffmpeg +=                  \
@@ -21,7 +22,6 @@ OBJS-ffmpeg +=                  \
     fftools/ffmpeg_mux_init.o   \
     fftools/ffmpeg_opt.o        \
     fftools/ffmpeg_sched.o      \
-    fftools/graph/graphprint.o        \
     fftools/sync_queue.o        \
     fftools/thread_queue.o      \
     fftools/textformat/avtextformat.o \
@@ -35,7 +35,8 @@ OBJS-ffmpeg +=                  \
     fftools/textformat/tw_avio.o      \
     fftools/textformat/tw_buffer.o    \
     fftools/textformat/tw_stdout.o    \
-    $(OBJS-resman)                    \
+    $(GRAPHPRINT-OBJS)                \
+    $(RESMAN-OBJS)                    \
 
 OBJS-ffprobe +=                       \
     fftools/textformat/avtextformat.o \
diff --git a/fftools/graph/Makefile b/fftools/graph/Makefile
new file mode 100644
index 0000000000..0aef14808f
--- /dev/null
+++ b/fftools/graph/Makefile
@@ -0,0 +1,8 @@
+clean::
+	$(RM) $(CLEANSUFFIXES:%=fftools/graph/%)
+
+GRAPHPRINT-OBJS += fftools/graph/graphprint.css.min.res.o
+GRAPHPRINT-OBJS += fftools/graph/graphprint.html.res.o
+GRAPHPRINT-OBJS += fftools/graph/graphprint.o
+
+RESOBJS += $(filter %.res.o,$(GRAPHPRINT-OBJS))
diff --git a/fftools/graph/graphprint.c b/fftools/graph/graphprint.c
index 852a8f6c0c..00601c82dc 100644
--- a/fftools/graph/graphprint.c
+++ b/fftools/graph/graphprint.c
@@ -940,10 +940,10 @@ static int init_graphprint(GraphPrintContext **pgpc, AVBPrint *target_buf)
     }
 
     if (!strcmp(text_formatter->name, "mermaid") || !strcmp(text_formatter->name, "mermaidhtml")) {
-        gpc->diagram_config.diagram_css = ff_resman_get_string(FF_RESOURCE_GRAPH_CSS);
+        gpc->diagram_config.diagram_css = ff_resman_get_string("graphprint.css.min");
 
         if (!strcmp(text_formatter->name, "mermaidhtml"))
-            gpc->diagram_config.html_template = ff_resman_get_string(FF_RESOURCE_GRAPH_HTML);
+            gpc->diagram_config.html_template = ff_resman_get_string("graphprint.html");
 
         av_diagram_init(tfc, &gpc->diagram_config);
     }
diff --git a/fftools/resources/graph.css b/fftools/graph/graphprint.css
similarity index 100%
rename from fftools/resources/graph.css
rename to fftools/graph/graphprint.css
diff --git a/fftools/resources/graph.html b/fftools/graph/graphprint.html
similarity index 100%
rename from fftools/resources/graph.html
rename to fftools/graph/graphprint.html
diff --git a/fftools/resources/.gitignore b/fftools/resources/.gitignore
index bda2c59a1c..ba5d49f24f 100644
--- a/fftools/resources/.gitignore
+++ b/fftools/resources/.gitignore
@@ -1,6 +1 @@
-*.html.c
-*.css.c
-*.html.gz
-*.css.gz
-*.min
-*.min.gz
+/resources_list.c
diff --git a/fftools/resources/Makefile b/fftools/resources/Makefile
index 8579a52678..7628adbd58 100644
--- a/fftools/resources/Makefile
+++ b/fftools/resources/Makefile
@@ -1,13 +1,22 @@
 clean::
 	$(RM) $(CLEANSUFFIXES:%=fftools/resources/%)
+	$(RM) fftools/resources/resources_list.c
 
-vpath %.html $(SRC_PATH)
-vpath %.css  $(SRC_PATH)
+RESMAN-OBJS += fftools/resources/resman.o
 
-# Uncomment to prevent deletion during build
-#.PRECIOUS: %.css.c %.css.min %.css.gz %.css.min.gz %.html.gz %.html.c
+fftools/resources/resources_list.c: $(RESOBJS)
+	$(RM) $@
+	$(M)$(foreach R,$(notdir $(RESOBJS:.o=)),echo 'extern const unsigned char ff_$(subst .,_,$(R))_data[];' >> $@;)
+	$(Q)$(foreach R,$(notdir $(RESOBJS:.o=)),echo 'extern const unsigned int ff_$(subst .,_,$(R))_len;' >> $@;)
+	$(Q)echo 'static const FFResourceDefinition resource_definitions[] = {' >> $@
+	$(Q)$(foreach R,$(notdir $(RESOBJS:.o=)),echo '    { "$(R:.res=)", &ff_$(subst .,_,$(R))_data[0], &ff_$(subst .,_,$(R))_len },' >> $@;)
+	$(Q)echo '};' >> $@
+
+fftools/resources/resman.o: fftools/resources/resources_list.c
 
-OBJS-resman +=                     \
-    fftools/resources/resman.o     \
-    fftools/resources/graph.html.o \
-    fftools/resources/graph.css.o  \
+# Disable dependency checking to prevent spurious rebuilds
+$(RESOBJS): CCDEP       =
+$(RESOBJS): CC_DEPFLAGS =
+
+# Uncomment to prevent deletion during build
+#.SECONDARY: $(RESOBJS:.o=.gz) $(RESOBJS:.o=.c) $(RESOBJS:.res.o=)
diff --git a/fftools/resources/resman.c b/fftools/resources/resman.c
index a9e21626fa..4f60044843 100644
--- a/fftools/resources/resman.c
+++ b/fftools/resources/resman.c
@@ -38,16 +38,7 @@
 #include "libavutil/dict.h"
 #include "libavutil/common.h"
 
-extern const unsigned char ff_graph_html_data[];
-extern const unsigned int ff_graph_html_len;
-
-extern const unsigned char ff_graph_css_data[];
-extern const unsigned ff_graph_css_len;
-
-static const FFResourceDefinition resource_definitions[] = {
-    [FF_RESOURCE_GRAPH_CSS]   = { FF_RESOURCE_GRAPH_CSS,   "graph.css",   &ff_graph_css_data[0],   &ff_graph_css_len   },
-    [FF_RESOURCE_GRAPH_HTML]  = { FF_RESOURCE_GRAPH_HTML,  "graph.html",  &ff_graph_html_data[0],  &ff_graph_html_len  },
-};
+#include "fftools/resources/resources_list.c"
 
 
 static const AVClass resman_class = {
@@ -156,7 +147,7 @@ void ff_resman_uninit(void)
 }
 
 
-char *ff_resman_get_string(FFResourceId resource_id)
+char *ff_resman_get_string(const char *name)
 {
     ResourceManagerContext *ctx               = get_resman_context();
     FFResourceDefinition resource_definition = { 0 };
@@ -168,14 +159,14 @@ char *ff_resman_get_string(FFResourceId resource_id)
 
     for (unsigned i = 0; i < FF_ARRAY_ELEMS(resource_definitions); ++i) {
         FFResourceDefinition def = resource_definitions[i];
-        if (def.resource_id == resource_id) {
+        if (!strcmp(def.name, name)) {
             resource_definition = def;
             break;
         }
     }
 
     if (!resource_definition.name) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to find resource with ID %d\n", resource_id);
+        av_log(ctx, AV_LOG_ERROR, "Unable to find resource with name \"%s\"\n", name);
         return NULL;
     }
 
@@ -194,7 +185,7 @@ char *ff_resman_get_string(FFResourceId resource_id)
         int ret = decompress_gzip(ctx, (uint8_t *)resource_definition.data, *resource_definition.data_len, &out, &out_len);
 
         if (ret) {
-            av_log(NULL, AV_LOG_ERROR, "Unable to decompress the resource with ID %d\n", resource_id);
+            av_log(NULL, AV_LOG_ERROR, "Unable to decompress the resource with name \"%s\"\n", name);
             goto end;
         }
 
diff --git a/fftools/resources/resman.h b/fftools/resources/resman.h
index 6485db5091..c2f2fd34b4 100644
--- a/fftools/resources/resman.h
+++ b/fftools/resources/resman.h
@@ -29,13 +29,7 @@
 #include "libavutil/bprint.h"
 #include "fftools/textformat/avtextformat.h"
 
-typedef enum {
-    FF_RESOURCE_GRAPH_CSS,
-    FF_RESOURCE_GRAPH_HTML,
-} FFResourceId;
-
 typedef struct FFResourceDefinition {
-    FFResourceId resource_id;
     const char *name;
 
     const unsigned char *data;
@@ -45,6 +39,6 @@ typedef struct FFResourceDefinition {
 
 void ff_resman_uninit(void);
 
-char *ff_resman_get_string(FFResourceId resource_id);
+char *ff_resman_get_string(const char *name);
 
 #endif /* FFTOOLS_RESOURCES_RESMAN_H */
-- 
2.39.5



More information about the ffmpeg-devel mailing list