Search code examples
c++makefilerules

Substitute all chess pieces in a .o file makefile


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?


Solution

  • 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