0

我有一个关于国际象棋项目的生成文件。当前make Chess规则如下所示

Chess: main.o board.o player.o chess.o square.o piece.o position.o pawn.o rook.o king.o queen.o bishop.o knight.o
    $(CC) main.o board.o player.o chess.o square.o piece.o position.o pawn.o rook.o king.o queen.o bishop.o knight.o $(OUTPUT)

我想用这样的东西代替它

Chess: main.o board.o player.o chess.o square.o piece.o position.o chesspieces.o
    $(CC) main.o board.o player.o chess.o square.o piece.o position.o  chesspieces.o $(OUTPUT)

我尝试了什么:

chesspieces.o: ./src/pieces/king.cc ./src/pieces/knight.cc ./src/pieces/bishop.cc ./src/pieces/queen.cc ./src/pieces/pawn.cc ./src/pieces/rook.cc ./src/pieces/piece.cc
    $(CC) $(INCLUDES) ./src/pieces/king.cc ./src/pieces/knight.cc ./src/pieces/bishop.cc ./src/pieces/queen.cc ./src/pieces/pawn.cc ./src/pieces/rook.cc ./src/pieces/piece.cc

给了我一堆未定义的引用Position, Square, Board。棋子是每个棋子继承的抽象类,它包括一个Color和一个Position类,但我已经为规则中的那些添加了Chess规则。我应该再次添加它们吗?还有一个额外的问题:我想将我的目标文件存储在一个单独的文件夹中,这会导致任何问题吗?

4

1 回答 1

3

我不确定是否有可能在不使用奇怪的技巧的情况下将许多源文件组合成一个对象。.o文件是单独的编译单元,它的链接器工作将它们合并以创建二进制文件(例如库)。

您获得未定义的引用是因为您实际所做的chesspieces.o是生成一个名为的可执行文件a.out(如果您使用 gcc)。用于-c生成目标文件(每个输入.cc文件一个)。

您可能想要重新组织您的 make 目标,通常每个生成的二进制文件都有一个目标。例如,如果您制作了一个名为的静态库foo

# Rules for pieces/king.o, etc 

foo.a: pieces/king.o pieces/knight.o pieces/bishop.o # ...
  # Combine the object files 
  ar rcs $@ $^

所以要结合你的棋子:


chesspieces.a: # pieces/king.o ...
    ar rcs $@ $^

Chess: ... chesspieces.a
    $(CXX) ... -lchesspieces -L<dir where chesspieces.a is stored> # Links your chesspiece lib to your Chess executable

请注意,在 Linux 上,静态库基本上只是目标文件的存档,因此我们使用arwithrcs来生成静态库。我使用$@了“魔术”制作变量(目标名称)和$^(目标依赖项)。此外,我们必须传递-lchesspieces-L<dir>进行最终编译,Chess以便链接器可以找到.o文件中定义的所有符号,这些符号是chesspieces.a

通常在构建期间.o为每个源 ( .cc) 文件生成一个文件,作为编译和链接之间的中间步骤

注意:您将您的问题标记为“cpp”,所以我改为CC, CXXis CCthe C compiler CXXis the c++ compiler

于 2021-09-25T11:30:31.570 回答