Я работаю над библиотекой (более или менее случайных) функций, которые я использую в проектах. В предыдущем воплощении каждый файл .c, .o был перечислен и скомпилирован вручную в target:
$(CC) $(SRCDIR)/somefoo.c $(CFLAGS) ... -c -o $(OBJDIR)/somefoo.o
Это стало утомительным, неточным и мучительным, и я хотел создать более дружественный, лучший Makefile, который я мог бы использовать для любого проекта. После поиска в Google прочитал («Управление проектами с помощью GNU Make» О'Рейли) и подумал, что я придумал:
BIN = /usr/bin
SH = $(BIN)/bash
CC = $(BIN)/cc
AR = $(BIN)/ar
RL = $(BIN)/ranlib
RM = $(BIN)/rm
CP = $(BIN)/cp
RL = $(BIN)/ranlib
TC = $(BIN)/touch
MK = $(BIN)/make
FND = $(BIN)/find
TAR = $(BIN)/tar
RM = $(BIN)/rm
CFLAGS = -Wall -Wextra -Wpedanitc -pedanitc-errors\
-w -Waddress -Walloc-zero -Walloca -Warray-bounds\
-Wno-deprecated -Wno-div-by-zero -Werror -Wfatal-errors\
-Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wdouble-promotion\
-Wrestrict -Wnull-dereference -Wjump-misses-init -Wshadow\
-Wformat=2 -Wformat -Wformat-security -pedantic --std=c99 --march=native
DEBUG = -g -ggdb -gstabs
OPTIM = -faggressive-loop-optimizations -fassociative-math -O3
LIBS = -lm -lcommonC #add more here
INC = -I/usr/include -I/usr/local/include -I$(INCDIR)
LIBPATH = -L/usr/lib -L/usr/lib64 -L/usr/local/lib -L/usr/local/lib64 -L$(LIBDIR)
MKFLAG = -f
PACK = $(TAR) -cvs
EXTRACT = $(TAR) -xf
PREFIX = /path/to/project #root directory of the project
BINDIR = $(PREFIX)/bin #stores Makefile, shell scripts, README, LICENSE, data files...
INCIDR = $(PREFIX)/include #holds .h files for the project
SRCDIR = $(PREFIX)/src #holds source files
OBJDIR = $(PREFIX)/obj #holds generated object files
LIBDIR = $(PREFIX)/lib #holds generated or included .a files
EXEDIR = $(PREFIX)/exe #generated executable(s)
DESTDIR ?= #where the tar file will be unpacked, user defined.
SRC = $(wildcard $(SRCDIR)/*.c) #all .c source files
OBJ = $(patsubst %.c,%.o,$(wildcard *.c)) #.o files
LIB ?= $(wildcard $(LIBDIR)/*.a) #the .a
EXE = $(EXEDIR)/project #generated executable
MKE = $(BINDIR)/Makefile #Makefile, used for cleaning before packing the project
TARF ?= #tar file for project.tar, user defined
.PHONY: obj exe update test clean pack install
# up to $(EXE) updated thanks to "Renaud Pacalet"
obj: $(OBJ)
exe: $(EXE)
$(OBJ): %.o: %.c
$(CC) $< $(CFLAGS) $(LIB) $(INC) $(LIBPATH) $(LIBS) $(OPTIM) -c -o $@
$(EXE): $(OBJ)
$(CC) $^ $(CFLAGS) $(LIB) $(INC) $(LIBPATH) $(LIBS) $(OPTIM) -o $@
update: $(SRC)
$(TC) $(SRC)
clean:
$(RM) $(OBJ) $(EXE) $(LIB)
pack:
$(MK) $(MKFLAG) $(MKE) clean && $(PACK) $(PREFIX) $(TARF)
install:
cd $(DESTDIR) && $(TAR) $(EXTRACT) $(TARF)
У меня вопрос с объявлением SRC, OBJ и цели для компиляции .c -> .o SRC = ... работает нормально, но по какой-то причине соответствующий файл obj не генерируется? Спасибо за любой вклад.
Обновление: благодаря Renaud Pacalet у меня есть переменные OBJ / SRC. Я получаю сообщение об ошибке:
make: Nothing to be done for 'obj'
Что обычно означает, что цели обновлены. Мне стало известно, что в моей организации недостаточно подробностей, поэтому я добавил комментарии, описывающие, на что ссылается каждая переменная. Я использовал эту схему организации ранее для большинства своих проектов, и до сих пор у меня не было проблем с этим.
Спасибо за любой вклад.
-. Джордан
- Иордания.