【问题标题】:How do I rewrite my makefile so that I can restructure the directories of my project?如何重写我的 makefile 以便我可以重构我的项目的目录?
【发布时间】:2021-04-08 13:25:18
【问题描述】:

我一直在开发一个完全用 C++ 编写的小游戏,使用 SDL 来处理图形和音频。到目前为止,我的所有源文件和头文件都与我的可执行文件位于同一目录中,但我想将它们移动到 ./src 和 ./include 文件夹中。

但是,我真的很困惑 makefile 语法以及如何告诉编译器在哪里可以找到源文件和头文件。

如何告诉 makefile 在子目录中查找源/标题/对象?我的 makefile 有什么改进/错误吗?

这是我当前的makefile:

OBJS = main.o Window.o Entity.o Player.o Tile.o BoundingBox.o\
     MapReader.o Button.o Zombie.o Projectile.o Pathfinder.o
CPP = g++
CPPFLAGS = -c -g
LDFLAGS = -lmingw32 -lSDL2main -lSDL2 -lSDL2_image -lSDL2_mixer -mwindows

ZombieAttack: $(OBJS)
    $(CPP) -o ZombieAttack $(OBJS) $(LDFLAGS)

main.o: main.cpp
    $(CPP) $(CPPFLAGS) main.cpp

Window.o: Window.cpp
    $(CPP) $(CPPFLAGS) Window.cpp

Entity.o: Entity.cpp
    $(CPP) $(CPPFLAGS) Entity.cpp

Player.o: Player.cpp
    $(CPP) $(CPPFLAGS) Player.cpp

Tile.o: Tile.cpp
    $(CPP) $(CPPFLAGS) Tile.cpp

BoundingBox.o: BoundingBox.cpp
    $(CPP) $(CPPFLAGS) BoundingBox.cpp

MapReader.o: MapReader.cpp
    $(CPP) $(CPPFLAGS) MapReader.cpp

Button.o: Button.cpp
    $(CPP) $(CPPFLAGS) Button.cpp

Zombie.o: Zombie.cpp
    $(CPP) $(CPPFLAGS) Zombie.cpp

Projectile.o: Projectile.cpp
    $(CPP) $(CPPFLAGS) Projectile.cpp

Pathfinder.o: Pathfinder.cpp
    $(CPP) $(CPPFLAGS) Pathfinder.cpp

clean:
    del *.o

我正在使用 mingw 进行编译和 mingw32-make

【问题讨论】:

    标签: c++ makefile mingw sdl subdirectory


    【解决方案1】:

    如果您希望二进制文件位于最高级别目录中,而 .h / .cpp 文件位于该目录的子目录中,您只需在要访问的文件前面加上目标目录/文件名即可

    例如:

    MapReader.o: MapReader.cpp
        $(CPP) $(CPPFLAGS) MapReader.cpp
    

    变成

    MapReader.o: src/MapReader.cpp
        $(CPP) $(CPPFLAGS) src/MapReader.cpp
    

    【讨论】:

      【解决方案2】:

      一般来说,最好在发布到 SO 之前尝试自己解决问题。然后,当您遇到无法解决的问题时,您应该具体询问该问题,而不是像这样广泛的问题。

      不过,过年了!!

      首先,make 与编译器不同。仅仅教 make 在哪里找到你的文件是不够的,你还必须教编译器在哪里找到你的文件。如果您要将头文件放在源文件之外的其他目录中,那么您必须为编译器提供选项,告诉它在哪里可以找到这些头文件。只是告诉 make 在哪里可以找到它们不会对编译器有任何帮助。

      其次,除非你真的有迫切的需要,否则你应该将standard variables 用于 C++ 编译器(CXX 不是CPP)和它的标志(CXXFLAGS 不是CPPFLAGS)。您也不应该将选择输出类型的选项 (-c) 放入通用标志变量中:它应该进入规则。最后,您应该确保区分链接器的标志LDFLAGS 和链接库的LDLIBS。在这里,您将所有要链接到 LDFLAGS 的库。

      第三,你可以尽可能使用automatic variables来减少重复。

      第四,您可以使用pattern rule 大大简化您的makefile。事实上,GNU make 提供了default pattern rules 可以正确构建 C++ 文件,如果您使用上述正确的变量,那么您甚至不必定义自己的变量。

      这是您原始 makefile 的一个版本,修复了上述变量并使用内置规则来减少重复:

      OBJS = main.o Window.o Entity.o Player.o Tile.o BoundingBox.o \
           MapReader.o Button.o Zombie.o Projectile.o Pathfinder.o
      
      CXX = g++
      CXXFLAGS = -g
      LDFLAGS = -mwindows
      LDLIBS = -lmingw32 -lSDL2main -lSDL2 -lSDL2_image -lSDL2_mixer 
      
      ZombieAttack: $(OBJS)
              $(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS)
      
      clean:
              del *.o
      

      如果所有文件都在同一个目录中,则该 makefile 的执行方式应该与您的原始 makefile 完全相同。

      现在,如果你想移动一些东西,那么你需要先向编译器解释在哪里可以找到你的头文件,方法是在编译行添加一个-I 选项。如果您的标头现在位于 include 子目录中,您可以这样做:

      CXXFLAGS = -g -Iinclude
      

      现在,如果您愿意将目标文件与源文件放在同一目录中,那么您可以更改上面的 makefile 以告诉 make 在哪里构建它们,如下所示:

      BASE_OBJS = main.o Window.o Entity.o Player.o Tile.o BoundingBox.o \
           MapReader.o Button.o Zombie.o Projectile.o Pathfinder.o
      
      SRC = src
      OBJS = $(addprefix $(SRC)/,$(BASE_OBJS))
      

      加上上面的更改,应该可以让它工作。

      如果你想将目标文件放在源文件以外的其他目录中,那么你将不再能够使用 make 的内置规则,因为 make 不知道你想把东西放在哪里,所以你会有编写自己的模式规则。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-02
        • 1970-01-01
        • 1970-01-01
        • 2021-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-13
        相关资源
        最近更新 更多