【问题标题】:Makefile automatic variablesMakefile 自动变量
【发布时间】:2018-08-31 01:08:16
【问题描述】:

我正在开发一个我在项目中使用的(或多或少随机的)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'

这通常意味着目标是最新的。我注意到我的组织缺乏细节,所以我添加了 cmets 来描述每个变量引用的内容。我之前的大部分项目都使用过这个组织方案,直到现在我都没有遇到过这个问题。

感谢您的所有意见。

--约旦。

-- 乔丹。

【问题讨论】:

    标签: makefile gnu-make


    【解决方案1】:

    你的编译规则创建的是$@扩展的结果,也就是规则的目标,即...obj。所以你可能有一个名为obj 的文件,其中包含$(SRC) 中第一个源的编译结果($&lt; 的扩展)。请改用pattern rule

    SRC = $(wildcard $(SRCDIR)/*.c)
    OBJ = $(patsubst %.c,%.o,$(SRC))
    
    %.o: %.c
        $(CC) $< $(CFLAGS) $(LIB) $(INC) $(LIBPATH) $(LIBS) $(OPTIM) -c -o $@
    

    static pattern rule

    $(OBJ): %.o: %.c
        $(CC) $< $(CFLAGS) $(LIB) $(INC) $(LIBPATH) $(LIBS) $(OPTIM) -c -o $@
    

    如果您想要的是一个名为 obj 的简写,用于编译所有源代码,您可以定义一个 phony target

    .PHONY: obj
    
    obj: $(OBJ)
    

    并调用:

    make obj
    

    同样,最好将exe 定义为假的,并编写一个显式创建文件的规则。当它看到的世界是由创建文件的食谱组成时,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)
    

    【讨论】:

    • 谢谢。不幸的是,它只是一直在说“对 obj 无能为力”。我将目录重命名为对象,因此没有名称冲突。
    • 一个object 目录?我错过了什么还是你第一次提到这个?
    • 我的项目目录树通常有一个名为 bin(用于 Makefile、脚本等)、src(源文件)、obj(目标文件)、exe(可执行文件)、lib(包含/生成的库),包括(对于 .h 文件)
    • @Jordan:您的组织看起来又好又干净。因为它对 make 的行为以及如何编写 Makefile 有很大的影响,所以您可以将所有缺失的信息添加到您的问题中。了解为什么it just keeps saying "nothing to be done for obj" 对文件组织的完整描述会更容易,您可以从其中调用 make...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多