I have a makefile about a chess project. The current make Chess
rule looks like this
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)
and I want to replace it with something like this
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)
What I tried :
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
Gives me a bunch of undefined references to Position, Square, Board
. Piece is the abstract class which every chess piece inherits from and it includes a Color
and a Position
class, but I already added rules for those in the Chess
rule. Should I add them again? Also an extra question: I want to store my object files in a separate folder, will this cause any issues?
CodePudding user response:
I'm not sure if its even possible to combine many source files into a single object without using weird hacks. .o
files are separate compilation units and its the linkers job to merge them to create binaries (e.g. libraries).
Your getting undefined references because what your actually doing for chesspieces.o
is generating an executable called a.out
(if your using gcc). Use -c
to generate object files (one per input .cc
file).
You might want to reorganize your make targets instead, usually you'd have one target per produced binary. e.g. if your making a static library called foo
:
# Rules for pieces/king.o, etc
foo.a: pieces/king.o pieces/knight.o pieces/bishop.o # ...
# Combine the object files
ar rcs $@ $^
So to combine your chesspieces:
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
Note that on Linux static libs are basically just archives of object files so we use ar
with rcs
to generate a static library. I've used "magic" make variables $@
(the target name) and $^
(the target dependencies). Also we have to pass -lchesspieces
and -L<dir>
to the final compilation of Chess
so the linker can find all the symbols defined in the .o
files that are part of chesspieces.a
Generally during the build a .o
file is generated for every source (.cc
) file as an intermediate step between compiling and linking
Note: You tagged your question "cpp" so I changed CC
to CXX
, CC
is the C compiler CXX
is the c compiler