в опубликованном make-файле отсутствуют некоторые детали
Примечание: (почти) всегда лучше отделить этап компиляции от этапа связывания
следующий make-файл исправляет эти детали
Примечание:
означает использование клавиши табуляции в самом make-файле.
RM := /usr/bin/rm
LFLAGS += `pkg-config wayland-client --libs`
CFLAGS := -std=c11 -Wall -Werror -O3 -fvisibility=hidden
CFLAGS += `pkg-config wayland-client --cflags`
OBJS := hello_wayland.o helpers.o
HDRS := helpers.h
TARGET := hello_wayland
.PHONY: all
all: $(TARGET)
$(TARGET): $(OBJS) images.bin
<tab>$(CC) -o hello_wayland *.o $(LFLAGS) -lrt
%.o:%.c $(HDRS)
<tab>$(CC) $(CFLAGS)-c $< -o $@ -I.
images.bin: images/convert.py images/window.png images/fish.png
<tab>images/convert.py
<tab>cat window.bin fish.bin > images.bin
.PHONY: clean
clean:
<tab>$(RM) *.o fish.bin window.bin hello_wayland
Вы спрашиваете, что не так с исходным make-файлом:
вот некоторые наблюдения:
-- macros in a make file are of two types:
those evaluated only once using `:=`
those evaluated every time they are referenced `=`
WAYLAND=`pkg-config wayland-client --cflags --libs`
== WAYLAND will be re-evaluated every time referenced
CFLAGS?=-std=c11 -Wall -Werror -O3 -fvisibility=hidden
== invalid format for macro. `?=` should be `:=`
== in a makefile, typical usage is `make all` but this makefile is missing that target (which should be the first target so `make` by itself, will execute the first target)
== `targets` for a link step should not be the actual file name
==== but rather a macro name where that macro contains the target name
==== This usage of a macro also makes it easy to set the resulting executable file name at the invocation of `make`
==== while either way will work, for flexability it is best to create a macro
==== this is expecially true when writing a recursive makefile or multiple different executables
hello_wayland: hello_wayland.o helpers.o helpers.h images.bin
== this is a link step, with hidden compiles, using the default recipe, which knows nothing about any specific header file
==== so the hidden compiles will not be done if the header file changes
== and a header file `helpers.h` should never be in a link step
== the `*.o` is a `glob` operation, which should not be used in makefiles
==== instead use the make facilties:
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
== the 'target' is properly referenced by `$@` and there can be no keypunch errors if the `$@` is used.
$(CC) -o hello_wayland *.o $(WAYLAND) -lrt
images.bin: images/convert.py images/window.png images/fish.png
images/convert.py
cat window.bin fish.bin > images.bin
== when a `target` is not the name of a produced file,
==== especially in older versions of `make`
==== then the target needs to be preceeded by a
.PHONY: <list of target names that produce no actual output file>
== using a `glob` operation in a makefile is a bad idea
==== instead use the appropriate macro
==== like the $(OBJS) macro listed above
clean:
$(RM) *.o fish.bin window.bin hello_wayland
Итак, почему исходный make-файл не работал? комбинация вещей, которые накапливаются в отказе. Вот более очевидные причины:
1) the incorrect setting of the CFLAGS macro
2) the combining of the link operation with the compile operations
3) the missing .PHONY: statement
4) the use of the `glob` statements
Если у вас есть дата GNU (, распространенная в Linux ), тогда флаг -d
будет делать то, что вы хотите:
% date -d 'Sun Mar 31 01:05:19 CDT 2019' +%s
1554012319