16

我有一些 C++ 类,每个类都放入他自己的文件夹中,其中包含一个 makefile、test.cpp 用于测试目的等。

Main folder
 |-> Class1 folder
 |-> Class2 folder
      |-> Class2.1 folder
 |-> Class2 folder

我有一个主要项目,必须包括这些类。我正在尝试将所有子 makefile 包含到主 makefile 中。

我试过“INCLUDE POO/makefile”,但这个解决方案有两个问题:

  • 子 makefile 的路径不正确,因此找不到文件(“没有构建目标 'Vector3D.cpp' 的规则”)。
  • “test.cpp”文件被覆盖,可能是因为路径问题。(“警告:覆盖目标的配方......”)

我希望所有makefile都独立,所以我可以将类文件夹复制/粘贴到一个新项目中并且它仍然可以工作,或者我可以单独执行makefile而不对其进行更改。

所以问题是:如何(正确地)将一个makefile包含到另一个makefile中?

示例,仅用于测试目的。

主生成文件(简化)

include Vector3D/makefile
include Color/makefile

CPP      = g++
CXXFLAGS = $(CXXINCS) -Wall -O0

all: main

main: main.o Vector3D.o Color.o
    $(CPP) main.o Vector3D.o Color.o -o main

main.o: main.cpp
    $(CPP) -c main.cpp -o main.o $(CXXFLAGS)

子makefile示例(简化)

#Vector3D
CPP      = g++
CXXFLAGS = $(CXXINCS) -Wall -O0


all: test

test: Vector3D.o test.o
    $(CPP) Vector3D.o test.o -o test

Vector3D/test.o: test.cpp
    $(CPP) -c test.cpp -o test.o $(CXXFLAGS)

Vector3D.o: Vector3D.cpp Vector3D.hpp
    $(CPP) -c Vector3D.cpp -o Vector3D.o $(CXXFLAGS)

Color/makefile 与 Vector3D 类似。

4

2 回答 2

9

我希望所有makefile都独立,因此我可以将类文件夹复制/粘贴到一个新项目中并且它仍然可以工作,或者我可以单独执行makefile而不对其进行更改。

我很确定这是不可能的。您的 makefile 要么需要是独立的,在这种情况下,您可以使顶级文件make在较低级别的目录中递归调用(所以不要这样做include,或者您可以通过包含其他 makefile 形成单个非递归 makefile。我不认为两者都可以。

如何将一个makefile(正确地)包含到另一个makefile中?

唯一有效的答案是“使用include指令”(除了通常的“它取决于”。)任何其他建议都取决于生成文件的结构。设计为包含的Makefile显然更容易包含。只包括一些随机的 makefile 并希望它能够工作......不会工作。查看实现非递归 makeBoilermake,了解如何使非递归 makefile 工作。

请注意,不需要将它们包含在文件的顶部,这样做可能不是一个好主意,因为默认目标成为包含文件中的第一个目标。

于 2013-10-10T22:44:32.937 回答
5

感谢@Jonathan-wakely 提供了这个解决方案的初始概念。

可能有很多事情可以改进,但它确实有效。

需求总结:

  • Makefiles 应该独立工作
  • 主 makefile 将包含子 makefile
  • 不会出现冲突或路径问题。

一个简单的解决方案是递归调用 makefile:

  • 为叶生成文件创建一个“正常”脚本
  • 使用空目标允许执行总是进行调用,例如“sub-make:”,在“:”之后没有任何要求
  • 使用“ -C ”参数设置 make 调用的根目录。
  • 使用子生成文件创建的二进制文件创建最终链接。

主 makefile 的示例:

#all make recursive calls
sub-make:
    make -C Vector3D
    make -C Color

#final linking
CPP      = g++
FLAGS = $(CXXINCS) -Wall -O0

all: main

main: main.o Vector3D/Vector3D.o Color/Color.o
    $(CPP) main.o Vector3D/Vector3D.o Color/Color.o -o main

main.o: main.cpp
    $(CPP) -c main.cpp -o main.o $(FLAGS)

可能有更好的方法来向链接器提供 *.o 二进制文件,而无需编写所有完整路径,但这是另一个问题。

创建干净的目标。对于叶子makefile,没有什么特别的考虑,但是对于主makefile,它必须调用sub-clean规则。

clean:
    make -C Vector3D clean
    make -C Color clean
    rm -f *.o main

编辑:

这是我所做的makefile结构,如果它可能对任何人有用。

要工作,所有类必须在它自己的文件夹中:

  • .hpp 标头
  • .cpp 代码
  • 用于测试的 main.cpp
  • 所需的类 (LIBS) 目录使用与此 makefile 相关的“$(LIBSPATH)LibName”指定。

生成文件

#Following configuration may be set with a parameter:
#   e.g: make FLAGS="-Wall -O0"
FLAGS = $(CXXINCS) -Wall -O0

#Configurable variables
EXEC     = main
CLASS    = World
LIBS     = Color Vector3D Triangle
LIBSPATH = ../

#Static content
CPP      = g++
OBJS     = $(foreach dir, $(LIBS), $(LIBSPATH)$(dir)/$(dir))

all: $(EXEC)

clean: 
    rm -f *.o $(EXEC)
    $(foreach dir,$(LIBS),make clean --no-print-directory -C $(LIBSPATH)$(dir);)

$(EXEC): $(CLASS).o $(EXEC).o $(OBJS:=.o)
    $(CPP) $(CLASS).o $(OBJS:=.o) $(EXEC).o -o $(EXEC)

$(EXEC).o: $(EXEC).cpp
    $(CPP) -c $(EXEC).cpp -o $(EXEC).o $(CXXFLAGS)

$(CLASS).o: $(CLASS).cpp $(CLASS).hpp
    $(CPP) -c $(CLASS).cpp -o $(CLASS).o $(CXXFLAGS)

$(OBJS:=.o): $(OBJS:=.cpp) $(OBJS:=.hpp)
    make --no-print-directory -C $(LIBSPATH)$(strip $(foreach dir,$(LIBS),$(if $(findstring $(dir),$@),$(dir))))
于 2013-10-11T10:57:22.517 回答