C++ - Makefile using g++

27,714

Solution 1

This Makefile uses implicit rules which are a great way to reduce duplication.

By default the first target will be built, here all. It depends on a number of object files listed in a variable $OBJECTS, e.g. Proj2.o who's dependencies aren't listed in the Makefile. Now if make sees an input file in the current directory with a matching name, e.g. Proj2.cpp it will try to build Proj2.o from it (there are other implicit rules for sources in other languages). Proj2.o would then be built by default with the command

$(CXX) $(CXXFLAGS) -c -o Proj2.o

where $(CXX) the name of the C++ compiler (g++ in your case).

The explicit build step for all assembles all the object files into the target executable.

Looking at above build command you'll notice a small problem in your Makefile. Since the flags to the C++ compiler are given in a variable FLAGS and not the standard CXXFLAGS no warnings will be emitted when building the object files. Using the standard name would fix this (you do want warnings, maybe even more than -Wall gives you).

Solution 2

Make has a set of implicit rules (see here for a reference). For instance

Compiling C++ programs
`n.o' is made automatically from `n.cc' or `n.C' with a command of the form 
`$(CXX) -c $(CPPFLAGS)   $(CXXFLAGS)'. 

Most make's will also use this rule for .cpp files. When make sees there's a x.o requirement for one of your targets, it will try to see if it can generate x.o using implicit rules, and in your case find it can do it starting from a .cpp file.

Share:
27,714
BigBerger
Author by

BigBerger

Updated on March 22, 2020

Comments

  • BigBerger
    BigBerger about 4 years

    I have made a Makefile for my CMSC 202 course project, 'Blackjack'. It does everything I need it to and it works perfectly. You may be asking why I posted here then, this is because I have no idea how it works and I didn't use any other resources but myself to create it.

    Here is my Makefile code.

    # Object files to either reference or create                          
    OBJECTS = Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o           
    # The executable file that will be created at the end                 
    EXEC = Proj2.out                                                      
    # The flags to use for compilation                                    
    FLAGS = -Wall                                                         
    # The code compiler to use for compilation                            
    CC = g++                                                              
    
    # Perform action on all object files (May or may not exist)           
    all: $(OBJECTS)                                                       
            $(CC) $(FLAGS) -o $(EXEC) $(OBJECTS)
    

    Here is the terminal output when I call make in the terminal.

    g++    -c -o Proj2.o Proj2.cpp
    g++    -c -o Blackjack.o Blackjack.cpp
    g++    -c -o Deck.o Deck.cpp
    g++    -c -o Card.o Card.cpp
    g++    -c -o Hand.o Hand.cpp
    g++    -c -o Player.o Player.cpp
    g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
    

    Can anyone tell me how the .o files are being compiled? It does not look like they are being prompted to be compiled with that g++ -c -o $.o $.cpp command anywhere in the Makefile. Nor did I state to use any .cpp files.

    Thank you in advance for your help.

    Edit

    Thanks to all your great help, this is now the terminal output I receive when using make.

    g++ -Wall   -c -o Proj2.o Proj2.cpp
    g++ -Wall   -c -o Blackjack.o Blackjack.cpp
    g++ -Wall   -c -o Deck.o Deck.cpp
    g++ -Wall   -c -o Card.o Card.cpp
    g++ -Wall   -c -o Hand.o Hand.cpp
    g++ -Wall   -c -o Player.o Player.cpp
    g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
    

    Thank you so much to all of you who have contributed.

    • user26347
      user26347 about 10 years
      You're -Wall flag isn't working by the way, you can see it's not being passed to g++ when compiling, which is when you need it.
    • DevSolar
      DevSolar about 10 years
      ...and putting it in CFLAGS instead of FLAGS fixes it. (Although it should be CXXFLAGS, and CXX, as it's C++, not C... strange.)
    • BigBerger
      BigBerger about 10 years
      Thanks for the CXXFLAGS tip! Everything works even better now, the compiler links the CXXFLAGS just like you said :)
    • BigBerger
      BigBerger about 10 years
      Will changing CC to CXX make the Makefile use the compiler linked in CXX instead of finding it's own? I know it works now, just wondering.
  • BigBerger
    BigBerger about 10 years
    Awesome thank you for the comment! Aside from this, going on what you wrote "$(CC) $(CFLAGS) -c -o Proj2.o". I have changed my "FLAGS" variable to "CFLAGS" and I used the command "make" again, but the compiler did not use the CFLAGS flag's variables in making the .o objects. Is there a way to have it implicitly use flags without much overhead? Thank you in advance for your time.
  • Benjamin Bannier
    Benjamin Bannier about 10 years
    @UnmercifulTurtle: I was editing in the meantime. CFLAGS is for the C compiler, CXXFLAGS for the C++ compiler. Since you compile C++ sources you'll need the latter. Also interesting is LDFLAGS which are the flags for the linker (but you have that step explicit in above example).
  • BigBerger
    BigBerger about 10 years
    Thank you for the tip! Just made the changes and it works even better now, thanks :)
  • Benjamin Bannier
    Benjamin Bannier about 10 years
    Great it helped. Since you are cleaning up why not rename CC to CXX as well since it points to a C++ compiler? With that I'd call that Makefile clean.
  • BigBerger
    BigBerger about 10 years
    Awesome, just did that! This Makefile is certainly the best I've used, I will be using this format from here on out. If I could check-mark everyone in this thread I would, best cooperation on StackOverflow I've seen in a while :)
  • DevSolar
    DevSolar about 10 years
    @UnmercifulTurtle: If that's the best you've seen so far, you have seen nothing yet. If you excuse me shamelessly advertising my own work, take a look at OSDev Wiki: Makefile tutorial, and once you're done, switch to my preconfigured CMake setup and never look back. ;-)
  • doug65536
    doug65536 about 2 years
    How does it know to use $(CXX) to link? Won't implicit rules just use $(CC)? It's just a bunch of object files, right?
  • Benjamin Bannier
    Benjamin Bannier about 2 years
    @doug65536: The snippet in the answer is about the implicit rule creating the object files. The link step was explicit in the question and is using $(CC) (which is actually g++).