Search code examples
c++makefile

Makefile linking advice for a beginner


all. Some of you who have helped me in the past might already know that my code is pretty messed up because of all of my #include statements including .cpp files. My question is, how am I supposed to correctly implement the make file to link everything together correctly?

What I currently have:

CC = g++

# Compiler flags:
# -g     - debugging info.
# -Wall  - used to turn on most compiler warnings.
CFLAGS = -g -Wall

# The build target
TARGET = icbins

# To bring exe up to date:

$(TARGET): main.o m1/cell.o m1/abstractions.o m1/expression.o m1/arithmetic.o m1/logic.o m1/cell.o m1/grid.o parsing/token.o parsing/lexer.o parsing/parser.o interface/icbins.o
    $(CC) $(CFLAGS) -o $(TARGET) main.o m1/cell.o m1/abstractions.o m1/expression.o m1/arithmetic.o m1/logic.o m1/cell.o m1/grid.o parsing/token.o -lncurses

main.o: main.cpp
    $(CC) $(CFLAGS) -c main.cpp

clean:
            $(RM) $(TARGET)

Yeeeah. not the best. I don't really know what I am doing with this, so any help is appreciated. My current folder structure:

project -
     main.cpp
     
     interface -
          icbins.cpp
     m1-
          abstractions.cpp
          arithmetic.cpp
          cell.cpp 
          expression.cpp 
          grid.cpp 
          logic.cpp
     parsing-
          lexer.cpp 
          parser.cpp 
          token.cpp 
     types.h

The main.cpp is supposed to be the driver and ./icbins is the executable file.

My current makefile "works", but not well...


Solution

  • Some of you who have helped me in the past might already know that my code is pretty messed up because of all of my #include statements including .cpp files. My question is, how am I supposed to correctly implement the make file to link everything together correctly?

    Linking is not really the issue. Your code structure with all the .cpp #includes is. There is good reason for the conventions that have grown up around headers and use of #include.

    But perhaps the issue is not so much the includes as understanding what a header is. In particular, I wonder whether some or all of your .cpp files are really misnamed headers. class definitions go in headers, whereas non-inline function definitions and external object definitions go in .cpp files. Any .cpp files that don't contain anything from the latter categories are really headers, and should be named as such (and should have appropriate multiple-inclusion guards).

    Anyway, to link everything together, you need to find a set of object files that collectively define all the methods and objects required by the program, exactly once each. Those, and only those, are the objects you link. In fact, those are the only ones you even need to build.

    If you don't want to change your code, then you can try choosing the appropriate set of objects this way:

    • Start with one object X.o for each X.cpp source file
    • Look at all the #include directives in your sources. For every Y.cpp file that is #included by another .cpp file, remove Y.o from the set of objects to build or link.

    It may be that main.o is the only object left, which would be fine, but if no objects remain then you need to restructure your code. And if you (still) get multiple definition errors when you try to link, then again, you need to restructure your code.

    Supposing that you can use built-in rules for compiling the object files, as the code in the question implies, the resulting makefile would look something like this:

    CXXFLAGS = -g -Wall
    
    TARGET = icbins
    TARGET_OBJS = main.o other/foo.o other2/bar.o ...
    
    $(TARGET): $(TARGET_OBJS)
            $(CXX) $(CXXFLAGS) -o $(TARGET) $^ -lncurses
    
    clean:
            rm -f $(TARGET) $(TARGET_OBJS)
    
    .PHONY: clean