Makefile:其他目录中的自动目标

Makefile:其他目录中的自动目标,makefile,Makefile,在当前的C项目中,我们有一个坏主意,就是将所有对象文件从源文件放到不同的文件夹中。起初管理起来并不复杂,但现在我们需要在一个特定的文件夹中编译一些文件,在另一个文件夹中编译另一些文件 树木生长情况如下所示: objs1 objs2 src 文件1.c 文件2.c 运行make后,我希望树状图修改为: objs1 文件1.o objs2 文件1.o 文件2.o 起初,makefile是这样的: CSRC = $(wildcard *.c) OBJS = $(CSRC:%.c=%

在当前的C项目中,我们有一个坏主意,就是将所有对象文件从源文件放到不同的文件夹中。起初管理起来并不复杂,但现在我们需要在一个特定的文件夹中编译一些文件,在另一个文件夹中编译另一些文件

树木生长情况如下所示:

  • objs1
  • objs2
  • src
    • 文件1.c
    • 文件2.c
运行
make
后,我希望树状图修改为:

  • objs1
    • 文件1.o
  • objs2
    • 文件1.o
    • 文件2.o
起初,makefile是这样的:

CSRC = $(wildcard *.c)
OBJS = $(CSRC:%.c=%.o)

objs1/%.o : %.c
  gcc -c -o $@ $<
但它的行为就像源文件在objs1中一样,事实并非如此

那么,如何将通用规则与指定位置相结合呢


谢谢

您可能需要手动指定对象,因为您需要在特定目录中编译特定文件:

objs1 := objs1/file1.o
objs2 := objs2/file1.o objs2/file2.o

$(objs1): CFLAGS += blah1
$(objs2): CFLAGS += blah2

$(objs1): objs1/%.o: src/%.c
$(objs2): objs2/%.o: src/%.c

$(objs1) $(objs2):
    $(COMPILE.c) $(OUTPUT_OPTION) $<
objs1:=objs1/file1.o
objs2:=objs2/file1.o objs2/file2.o
$(objs1):CFLAGS+=blah1
$(objs2):CFLAGS+=blah2
$(objs1):objs1/%.o:src/%.c
$(objs2):objs2/%.o:src/%.c
$(objs1)$(objs2):
$(COMPILE.c)$(输出选项)$<
如果少量的复制使您烦恼,您可以改用二次扩展

.SECONDEXPANSION:
$(objs1) $(objs2): %.o: src/$$(notdir $$*).c
    $(COMPILE.c) $(OUTPUT_OPTION) $<
。第二次扩展:
$(objs1)$(objs2):%.o:src/$$(notdir$$$*).c
$(COMPILE.c)$(输出选项)$<

如果允许递归make,则可以创建相应的子目录 对象文件的配额,只需在子目录中使用 适当的
CFLAGS
CPPFLAGS
和 在这种情况下,根本不需要编写任何编译方法,例如

Makefile

export CC := gcc
objs1: OBJS := file1.o
objs2: OBJS := file1.o file2.o
objs1: CFLAGS := -g
objs1: CPPFLAGS := -I../include  
objs2: CFLAGS = -O2
objs2: CPPFLAGS := -I../include -DNDEBUG

.PHONY: all clean objs1 objs2

all: objs1 objs2

objs1 objs2:
    mkdir -p $@
    $(MAKE) -C $@ $(OBJS) CFLAGS='$(CFLAGS)' CPPFLAGS='$(CPPFLAGS)' VPATH=../src

clean:
    rm -fr objs1 objs2 
其运行方式如下:

$ make
mkdir -p objs1
make -C objs1 file1.o CFLAGS='-g' CPPFLAGS='-I../include  ' VPATH=../src
make[1]: Entering directory '/home/imk/develop/scrap/objs1'
gcc -g -I../include    -c -o file1.o ../src/file1.c
make[1]: Leaving directory '/home/imk/develop/scrap/objs1'
mkdir -p objs2
make -C objs2 file1.o file2.o CFLAGS='-O2' CPPFLAGS='-I../include -DNDEBUG' VPATH=../src
make[1]: Entering directory '/home/imk/develop/scrap/objs2'
gcc -O2 -I../include -DNDEBUG  -c -o file1.o ../src/file1.c
gcc -O2 -I../include -DNDEBUG  -c -o file2.o ../src/file2.c
make[1]: Leaving directory '/home/imk/develop/scrap/objs2'
重要的是子目录是
.PHONY
。否则,
make

认为它们的存在意味着无事可做。

如果从同一源文件编译,那么
objs1/file1.o
objs2/file1.o
有什么不同?它们是否遵循不同的选项?是的,一个编译为标准对象,另一个编译时先绑定到JNI,然后作为库。
$ make
mkdir -p objs1
make -C objs1 file1.o CFLAGS='-g' CPPFLAGS='-I../include  ' VPATH=../src
make[1]: Entering directory '/home/imk/develop/scrap/objs1'
gcc -g -I../include    -c -o file1.o ../src/file1.c
make[1]: Leaving directory '/home/imk/develop/scrap/objs1'
mkdir -p objs2
make -C objs2 file1.o file2.o CFLAGS='-O2' CPPFLAGS='-I../include -DNDEBUG' VPATH=../src
make[1]: Entering directory '/home/imk/develop/scrap/objs2'
gcc -O2 -I../include -DNDEBUG  -c -o file1.o ../src/file1.c
gcc -O2 -I../include -DNDEBUG  -c -o file2.o ../src/file2.c
make[1]: Leaving directory '/home/imk/develop/scrap/objs2'