I'd like to turn a bunch of images into a video (video video1.mp4 is made from the files video1/*.mjpg), using a Makefile. I tried:
SOURCES=video1.mp4 video2.mp4
all: $(SOURCES)
%.mp4: $(shell find % -type f)
ffmpeg -framerate 24 -pattern_type glob -i '$*/*.jpg' -c:v libx264 -pix_fmt yuv420p $#
but it does not work, the % is not turned into the video1-like prefix. Any idea how to make it work?
You have to add the dependencies in another way as % is indeed not handled as you would like. Something like this (replacing the cat by an adequate ffmpeg call) should do the trick:
DESTS=video1.mp4 video2.mp4
all: $(DESTS)
define add_dependencies
$(1): $(wildcard $(1:.mp4=)/*.jpg)
endef
$(foreach dst,$(DESTS),$(eval $(call add_dependencies,$(dst))))
%.mp4:
cat $^ > $#
Note:
I'm using the built-in wildcard instead of find. The way I'm using it, I don't recurse in sub-directories, but your call to ffmpeg hints to me that wasn't desired.
I'd suggest if possible using $^ instead of doing the file matching a second time in ffmpeg.
This is for GNU make, but I don't think other makes accept the $(shell) syntax if they aren't targeting a wide GNU make compatibility.
Related
I have Makefile from an older project which I have to modify for a new system. It has the following global definitions for its source and object files:
SRCFILES = $(wildcard *.c) $(wildcard tasks/*.c)
SRCDIR = .
OBJDIR = objdir
OBJFILES = $(SRCFILES:%.c=${OBJDIR}/%.o)
The Makefile was a mess and I had to modify it heavily. I manged to compile the code and generate the .o files from the .c source code. The expected .elf file is also compiled correctly.
the problem is that I can do not understand what the code is doing in the following lines I searched so many websites but no luck. any ideas?
sed 's,^\(.*\)\.o[ :]*,$(#D)/\1.o $(#D)/\1.d : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
The makefile is as follows
lwip.elf: build_echo $(OBJFILES)
#set -e; echo Linking the object files...; \
sparc-elf-gcc $(OBJFILES) -o $#;
#echo Successfully linked the files
#echo lwip.elf file ready to load...
build_echo: httpserver_raw/fsdata.c
#echo Building the source files first...
#echo The Modified or New source code to be build are :
clean:
- rm -f lwip.elf
$(OBJDIR)/%.o: $(SRCDIR)/%.c
#set -e; echo ' $<'; \
sparc-elf-gcc-4.4.2 -Wall -O2 -g -msoft-float -mcpu=v8 -c -o $# $(CFLAGS) -I. -I lwip/include -I lwip/include/ipv4 -I lwip/leon3 $<
$(OBJDIR)/%.d: $(SRCDIR)/%.c
#set -e; rm -f $#; mkdir -p $(#D); \
sparc-elf-gcc -MM -I. -I lwip/include -I lwip/include/ipv4 -I lwip/leon3 $< > $#.$$$$; \
sed 's,^\(.*\)\.o[ :]*,$(#D)/\1.o $(#D)/\1.d : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
-include $(patsubst %.c,$(OBJDIR)/%.d,$(SRCFILES))
Note: The sparc-elf-gcc is a special cross-compiler used for the sparcV8 architecture.
There's a lot going on in there:
sed 's,^\(.*\)\.o[ :]*,$(#D)/\1.o $(#D)/\1.d : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
Let's break it down.
There's the sed command itself: sed 's,^\(.*\)\.o[ :]*,$(#D)/\1.o $(#D)/\1.d : ,g',
whose input is redirected (<) from a file designated by #.$$$$, and
whose output is redirected (>) to a file designated by $#, then
there's a second command, rm -f $#.$$$$.
Furthermore, that's in the context of a larger list of commands, which set it up with
#set -e; rm -f $#; mkdir -p $(#D); \
sparc-elf-gcc -MM -I. -I lwip/include -I lwip/include/ipv4 -I lwip/leon3 $< > $#.$$$$;
In interpreting that, you have to first recognize several make implicit variables:
$#, which represents the name of the target of the rule
$(#D), which represents the directory of the target name (i.e. the target's dirname)
$<, which represents the first prerequisite
Next, you need to recognize that the dollar sign has special meaning to make, so if you want a literal $ you need to double it. The $$$$ simply repeat this, so that what gets passed to the shell is just two dollar signs ($$). The shell, in turn, replaces that with its own process ID -- a relatively common (but nevertheless insecure) idiom for generating unique file names.
So, the part of the command that you omitted from your callout ensures that the target's destination directory exists, then runs a (cross-?) gcc with flags that cause it to emit information about header dependencies. These are captured in a file, something like objdir/src.d.12345, then in the part you called out, that file is redirected into sed, with the output going to the final target, something like objdir/src.d, after which the intermediate file is removed.
The sed command itself is performing a substitution (s) on all lines, replacing every occurrence (g) of the pattern ^\(.*\)\.o[ :]* with a replacement that I'll come back to in a moment. First the pattern. The ^ anchors the pattern to the beginning of a line. The \(\) are metacharacters delimiting a capturing group, and the .* inside matches any number of any characters. Following that must be a literal decimal point, \., an o, and zero or more occurrences or the space and colon characters ([ :]*). For example, that would match this, up to but not including the header name:
objdir/tasks/t1.o : my_header.h
The replacement uses the aforementioned $(#D) -- which is expanded by make, not the shell or sed -- and \1, which sed expands to the text matched by the first capturing group. Thus, that would transform the above example line to this:
objdir/tasks/t1.o objdir/tasks/t1.d : my_header.h
In short, then, all that to say that it munges the computed dependency list to make the dependency file that is the target of the rule list itself as depending on all the same files that the corresponding object file does.
I have the following Makefile, which is supposed to fetch a bunch of soundfiles in mp3 format, based on a list of sound ids, and then convert them into .wav files. I am not so familiar with GNU make so please bear with me.
What I need as a result is a bunch of .wav files, so, I have made an "all" target, which expects these .wav files. This Makefile, when run, will download normally the .mp3 files and then convert them into .wav files. Afterwards, it will delete all .mp3 files (since I have flagged them as .INTERMEDIATE). My problem is that if I re-run this Makefile, it will try to re-download the mp3 files and re-convert them into .wav files, even though, the .wav files are already present.
I can't understand why the "all" target gets re-triggered even though it should be satisfied since all its requirements have already been met.
How can I fix that?
BASE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
BASE_DIR := $(BASE_DIR:/=)
BUILD := $(BASE_DIR)/build
AUDIO := $(BUILD)/audio
SOUND_IDS_FILE := $(BASE_DIR)/sound_ids.txt
SOUND_IDS:=$(shell cat ${SOUND_IDS_FILE})
MP3_FILES:=$(patsubst %, $(AUDIO)/%.mp3, $(SOUND_IDS))
WAV_FILES:=$(patsubst %, $(AUDIO)/%.wav, $(SOUND_IDS))
.PHONY: all clean
.INTERMEDIATE: $(MP3_FILES)
# Main Rules:
all: $(WAV_FILES)
clean:
rm -rf $(BUILD)
# Dir Rules:
$(BUILD):
mkdir -p $#
$(AUDIO):
mkdir -p $#
$(WAV_FILES): $(MP3_FILES)
#echo "Converting $< into $# ..."
ffmpeg -i $< -acodec pcm_s16le -ac 1 -ar 16000 $#
$(MP3_FILES): $(AUDIO)
#echo "Downloading file: $# ..."
sound_fetcher -i $(patsubst %.mp3,%,$(#F)) -o $(AUDIO) -format mp3
I Have a folder structure like this.
Gif_Utility
-> Makefile
-> include ( all .h files are over here)
-> Src ( all .c files are over here).
I am writing a makefile.
Makefile
VPATH = src:include
INC = -I ./include
gif_objects = gif_display.o \
gif_lzw.o \
gif_read.o \
sysm.o \
x86_main.o
gif_display.0 : gif_display.c
gcc -I /export/home/joshis1/MakeTutorial/GIF_Utility/include -c $<
#gif_lzw.0 : gif_lzw.c
# gcc $(INC) -c src/gif_lzw.c
#gif_read.0 : gif_read.c
# gcc -I ./include/ -c $<
#sysm_main.0 : sysm_main.c
# gcc -I ./include/ -c $<
#x86_main.0 : x86_main.c
# gcc -I ./include/ -c $<
On command prompt:
$ make gif_display.o
cc -c -o gif_display.o src/gif_display.c
src/gif_display.c:2:17: fatal error: sysm.h: No such file or directory
compilation terminated.
make: *** [gif_display.o] Error 1
On the other hand, If i do like this it compiles fine
$make
-> this creates the gif_display.o
I don't know why it is throwing error on specifying the rule. Am I missing something, please help.
I am using Ubuntu machine to build my code.
Your makefile has a .0 (zero) suffix instead of the correct .o (letter oh).
When you run just make it attempts to build the first target in the Makefile, and so runs the recipe which contains the correct -I include path. The fact that it produces an .o file, not a .0 file, is acceptable to make, although I suppose it could at least print a warning in this scenario.
When you run make gif_display.o it uses Make's built-in productions for .o files, which do not contain your include path.
Given that make already has built-in rules for .o files, your rules are basically superfluous. It would be better to just add the -I include parameter to the default rules, with something like
CFLAGS += -I include
So the entire Makefile could be as simple as this:
VPATH = src:include
CFLAGS += -I ./include
gif_objects = gif_display.o \
gif_lzw.o \
gif_read.o \
sysm.o \
x86_main.o
I don't see anything to alert your Makefile to changes in .h files, so you might want to add a separate dependency for that. If you just have a few shared header files between all your object files, maybe this will be all you need:
$(gif_objects): $(wildcard include/*.h)
This basically makes the include component of the VPATH superfluous.
I have some trouble with my Makefile:
# Manage rendering of images
.PHONY: explode
all: explode anime.apng
out.ppm: file.code
./pgm -f $<
explode: out.ppm
split -d -a 3 --lines=$(N) --additional-suffix=.ppm $< frame
# Convert to multiple png
%.png: %.ppm
convert $< $#
optipng $#
# Assemble in one animated png
anime.apng: %.png
apngasm $# frame000.png
My problem is: I don't know how many intermediate files I will have to produce my final target, so I can't specify them in advance. Schematically:
1 file.code -> 1 out.ppm |> LOADS of .ppm |> LOADS of .png -> 1 anime.apng
+> … +> …
+> … +> …
For that I use an implicit rule %.png: %.ppm. But then I cannot specify a prerequisite for my last merge step! Any ideas? With another tool than make? Anything elegant?
I think a simple and rather clean approach would be to have a variable record the list of those 'LOADS' of ppm, in my example it's variable STEP2.
Surely you can use the program that gets you from '1 out.ppm' to 'LOADS of .ppm' to list the .ppm files that you will obtain.
With a very trivial exemple where out.ppm would be a text file listing the names of the .ppm to produce, you would write something like :
SOURCE = file.code
STEP1 = out.ppm
STEP2 = $(shell cat $(STEP1))
STEP3 = $(STEP2:%.ppm=%.png)
TARGET = anime.apng
Then you'll need to write a rule to get all the files listed in STEP2 from the file $(STEP1). This is done file by file as if it was an implicit rule with a % pattern, assuming your program is called 'extractor' :
$(STEP2): $(STEP1)
extractor $^ $#
This rule will be applied once for each file listed in STEP2. This assumes that your program only wants the names of the source and output files. Should you prefer to pass the stem of the output file, you can still use a plain ol' implicit rule :
$(STEP2):%.ppm: $(STEP1)
extractor $^ $*
(The $(STEP2): at the begining is to prevent make from using this rule to generate out.ppm)
Then, everything is as usual when it comes to compilation and you can adapt rules for compiling and linking any C projet. The %.ppm -> %.png step is like compiling %.c to %.o :
%.png: %.ppm
convert $< $#
optipng $#
To group everything at the end (equivalent of linking several %.o into only one binary) :
$(TARGET): $(STEP3)
apngasm $# $^
I'm assuming here that apngasm can take the list of everything to put together as arguments à la tar.
Hope it's clear and helpful enough.
A temporary workaround would be to take inspiration from a close question and render the images in a subfolder with a sub-make call. Something like:
Makefile:
# Manage rendering of images
.PHONY: explode
all: explode anime.apng
out.ppm: file.code
./pgm -f $<
explode: out.ppm
split -d -a 3 --lines=$(N) --additional-suffix=.ppm $< subfolder/frame
ppm2png: explode
$(MAKE) -C subfolder
# Assemble in one animated png
anime.apng: ppm2png
apngasm $# subfolder/frame000.png
temp/Makefile:
SOURCES := $(wildcard *.ppm)
OUTPUTS = $(patsub %.ppm,%.png,%(SOURCES))
.PHONY: all
all: $(OUTPUTS)
# Convert to multiple png
%.png: %.ppm
convert $< $#
optipng $#
I'm sure better can be done. With another tool than make?
I have a piece of makefile to generate .pdf, .ps, .dvi from .tex:
...
$(FILE).pdf: $(FILE).tex $(SRC) $(DEPS)
latex $(FILE).tex && \
bibtex --min-crossrefs=500 $(FILE) && \
latex $(FILE).tex && \
latex $(FILE).tex && \
dvips $(FILE).dvi -o $(FILE).ps && \
ps2pdf $(FILE).ps $(FILE).pdf
...
I would like to get $(FILE) directly from the command line, as the first argument following make. For instance, make paper compiles paper.tex and generates paper.pdf. Also, I don't want to permit make or make all as a command, where no file name is specified.
Could anyone tell me how to pass the first argument following make to $(FILE)?
You have a couple of options here, depending on exactly what behavior you want. (And I'm not sure I entirely understand your command-- I don't think there's any reason to have it as one wrapped line-- but never mind.)
If you want to allow only targets from a list known beforehand:
FILES = scissors paper rock
$(FILES): % : %.tex $(SRC) $(DEPS)
latex $*.tex && \
...
If you want to allow only targets for which .tex files exist:
% : %.tex $(SRC) $(DEPS)
latex $*.tex && \
...
Now for what to do about unwanted targets. If a warning is enough:
all:
#echo $# is not a valid target
(real rule)
%:
#echo $# is not a valid target
If you want Make to abort entirely, I think it's possible but I'll have to think it over some more...
This is not how make works. Perhaps you want to use a shell script which accepts a parameter, validates it, and invokes make with your Makefile, passing the file in as a make variable; that is, something like
make -f tex.mk FILE="$validated_filename"