【问题标题】:Substitute all chess pieces in a .o file makefile替换 .o 文件 makefile 中的所有棋子
【发布时间】:2021-09-25 10:49:04
【问题描述】:

我有一个关于国际象棋项目的生成文件。当前的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 的未定义引用。 Piece 是每个棋子继承自的抽象类,它包括 ColorPosition 类,但我已经在 Chess 规则中添加了规则。我应该再次添加它们吗?还有一个额外的问题:我想将我的目标文件存储在一个单独的文件夹中,这会导致任何问题吗?

【问题讨论】:

  • 为什么要进行此更改?每个.cc 文件都有一个目标文件是非常不寻常的。
  • @HolyBlackCat 将它们全部添加到 .o 文件中对我来说很有意义。也会使国际象棋规则更清晰
  • @EdwardKoulakidis 为什么你有一个班级的单一规则?通常你会希望每个生成的二进制文件都有一个规则,例如一个用于库输出一个用于 exe
  • 基本上,每个源文件(问题中的.cc)都被编译成相应的目标文件(问题中的.o)。就是这样。您可以将目标文件组合成一个库,但库不是目标文件。

标签: c++ makefile rules


【解决方案1】:

我不确定是否可以在不使用奇怪的技巧的情况下将许多源文件组合成一个对象。 .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 上,静态库基本上只是目标文件的存档,因此我们使用 arrcs 来生成静态库。我使用了“魔法”使变量$@(目标名称)和$^(目标依赖项)。此外,我们必须将-lchesspieces-L&lt;dir&gt; 传递给Chess 的最终编译,以便链接器可以找到.o 文件中定义的所有符号,这些符号是chesspieces.a 的一部分

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

注意:您将问题标记为“cpp”,所以我将 CC 更改为 CXXCC 是 C 编译器 CXX 是 c++ 编译器

【讨论】:

  • 很酷,谢谢。移动 obj 目录中的所有 .o 文件会导致任何问题吗?
  • @EdwardKoulakidis 不,只要你为编译器指定.o文件的正确路径就可以了
  • 我在国际象棋规则链接之后添加了这一行来帮助我移动它们:; mv *.o obj。我应该将国际象棋规则中的每条路径都更改为 ./obj/*.o 吗?例如。 :$(CC) ./obj/main.o ./obj/board.o ... $(OUTPUT) ; mv *.o obj
  • @EdwardKoulakidis 我通常做的只是有一个obj 目录,在该目录中调用编译器并且其中充满了混乱。然后最终将生成的二进制文件复制出来。您可以使用 $^ 而不是重复依赖列表 btw :)
  • 谢谢你的时间,祝你有美好的一天!
猜你喜欢
  • 2015-04-18
  • 1970-01-01
  • 2013-05-30
  • 1970-01-01
  • 2015-01-16
  • 2014-12-26
  • 2013-08-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多