如何将源目录中的所有cpp文件编译为对象到单独的构建目录中

时间:2014-06-03 17:55:18

标签: c++ build makefile

我的问题是问题Can I compile all .cpp files in src/ to .o's in obj/, then link to binary in ./?

的扩展

我的项目具有类似的结构,但我有一个src文件夹,包括文件夹,在我的root / project目录之外:

/somedir
  /project
    Makefile
    main
    /src1
      main.cpp
      foo.cpp
      foo.h
    /src2
      bar.cpp
      bar.h
    ...
    /srcn
      baz.cpp
      baz.cpp
    /obj
      main.o
      foo.o
      bar.o
      ...
      baz.o
      alpha.o
      betta.o
      ...
      zetta.o
  /ext_src1
    alpha.cpp
  /ext_src2
    betta.cpp
  ...
  /ext_srcn
    zetta.cpp

在我的Makefile中,我列出了我需要的所有cpp,部分手动收集,部分借助于通配符。我假设,所有cpp文件的名称都不同(并且它们的对象可以安全地放入一个目录中)。现在,我怎样才能将它们编译到我的obj文件夹中?

我设法以下列方式做了我想要的事情:

SOURCES=${wildcard src1/*.cpp} 
SOURCES+=${wildcard src2/*.cpp} 
...
SOURCES+=../ext_srcn/zetta.cpp 

OBJECTS=$(SOURCES:.cpp=.o)

main: $(OBJECTS)
    $(CC) $(LD_FLAGS) -o $@ $^

.cpp.o:
    $(CC) $(CFLAGS) -c $< $(INCLUDES) -o $(addprefix obj/,$(notdir $@))

但是现在,当然,即使没有进行任何更改,每次都会重新编译所有源代码。太糟糕了。如何在obj上跟踪我的.o目标的来源?或者可能有另一种方法来解决我的任务?

1 个答案:

答案 0 :(得分:1)

您可以将源路径保留在obj目录中:

TOP := $(realpath ../)
SOURCES := $(wildcard $(TOP)/project/src1/*.cpp)
SOURCES += $(wildcard $(TOP)/project/src2/*.cpp)
...
SOURCES += $(TOP)/ext_srcn/zetta.cpp 

OBJECTS := $(addprefix $(TOP)/project/obj,$(patsubst $(TOP),,$(SOURCES:%.cpp=%.o)))

main: $(OBJECTS)
    $(CC) $(LD_FLAGS) -o $@ $^

$(OBJECTS): $(TOP)/project/obj/%.o: $(TOP)/%.cpp
    $(CC) $(CFLAGS) -c $< $(INCLUDES) -o $@

这样你就会有这样的事情:

/somedir
  /project
    Makefile
    main.cpp
    /src1
      foo.cpp
      foo.h
    /src2
      bar.cpp
      bar.h
    ...
    /srcn
      baz.cpp
      baz.h
    /obj
      /project
        main.o
        /src1
          foo.o
        /src2
          baz.o
        ...
        /srcn
          baz.o
      /ext_src1
        alpha.o
      /ext_src2
        beta.o
      ...
      /ext_srcn
        zetta.o
  /ext_src1
    alpha.cpp
  /ext_src2
    betta.cpp
  ...
  /ext_srcn
    zetta.cpp

而且, - 通常 - 依赖项运行良好。