[英]Makefile automatic variables
我正在开发在项目中使用的(或多或少随机的)c函数库。 它的前一个版本列出了每个.c,.o文件,并在目标中对其进行了手动编译:
$(CC) $(SRCDIR)/somefoo.c $(CFLAGS) ... -c -o $(OBJDIR)/somefoo.o
这变得很累,不准确并且很痛苦,我想创建一个可以用于任何项目的友好,更好的Makefile。 谷歌搜索后,阅读(O'Reily的“使用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'
这通常意味着目标是最新的。 引起我注意的是,我的组织缺乏详细信息,因此我添加了描述每个变量引用内容的注释。 我以前在大多数项目中都使用过这种组织方案,但是到目前为止,我还没有遇到任何问题。
感谢您的所有投入。
- 约旦。
乔丹
编译规则创建的结果是$@
扩展的结果,它是规则的目标,即... obj
。 因此,您可能有一个名为obj
的文件,其中包含$(SRC)
第一个源的编译结果( $<
扩展)。 使用模式规则 :
SRC = $(wildcard $(SRCDIR)/*.c)
OBJ = $(patsubst %.c,%.o,$(SRC))
%.o: %.c
$(CC) $< $(CFLAGS) $(LIB) $(INC) $(LIBPATH) $(LIBS) $(OPTIM) -c -o $@
或静态模式规则 :
$(OBJ): %.o: %.c
$(CC) $< $(CFLAGS) $(LIB) $(INC) $(LIBPATH) $(LIBS) $(OPTIM) -c -o $@
如果您想要的是用于编译所有源代码的简写obj
,则可以定义一个虚假目标 :
.PHONY: obj
obj: $(OBJ)
并调用:
make obj
同样,将exe
定义为phony并编写明确创建文件的规则可能会更好。 当创建世界的食谱由创建文件的配方组成时,Make总是会更快乐:
.PHONY: exe
exe: $(EXE)
$(EXE): $(OBJ)
$(CC) $^ $(CFLAGS) $(LIB) $(INC) $(LIBPATH) $(LIBS) $(OPTIM) -o $@
最后一点:通过一个MK
自定义变量在一个配方( pack
)中使用make
。 您应该真正考虑用已经定义的MAKE
make变量替换MK
:
pack:
$(MAKE) $(MKFLAG) $(MKE) clean && $(PACK) $(PREFIX) $(TARF)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.