BogoToBogo
  • Home
  • About
  • Big Data
  • Machine Learning
  • AngularJS
  • Python
  • C++
  • go
  • DevOps
  • Kubernetes
  • Algorithms
  • More...
    • Qt 5
    • Linux
    • FFmpeg
    • Matlab
    • Django 1.8
    • Ruby On Rails
    • HTML5 & CSS

C++ Tutorial - gnu make - 2020

cplusplus_icon.png




Bookmark and Share





bogotobogo.com site search:




make

A simple makefile consists of rules with the following syntax:


     target ... : prerequisites (dependencies) ...
             recipe (system command)
             ...

By default, when make looks for the makefile, it tries the following names, in order: GNUmakefile, makefile and Makefile.

Let's start Makefile with 4 files:

myprogram : main.o aa.o bb.o cc.o
	g++ -o myprogram main.o aa.o bb.o cc.o

main.o : main.cpp header1.h
	g++ -c main.cpp	
aa.o : aa.cpp header1.h header2.h
	g++ -c aa.cpp
bb.o : bb.cpp header2.h
	g++ -c bb.cpp
cc.o : cc.cpp header3.h
	g++ -c cc.cpp
clean :
	rm myprogram \
	main.o aa.o bb.o cc.

The make starts with the first target (not targets whose names start with "."). In the example above, the default goal is to update the executable program myprogram; therefore, we put that rule first. When we issue the command:

     make
make reads the makefile in the current directory and starts by processing the first rule. In our case, this rule is for relinking myprogram. However, before make can fully process this rule, it must process the rules for the files that myprogram depends on, which in this case are the object files. Each of these files is processed according to its own rule. These rules are updating each .o file by compiling its source file. The recompilation should be done if the source file, or any of the header files named as prerequisites, is more recent than the object file, or if the object file does not exist.

The other rules are processed because their targets appear as prerequisites of the goal. If some other rule is not depended on by the goal, that rule is not processed, unless we tell make to do so with a command such as make clean.

After recompiling whichever object files needed, make decides whether to relink myprogram. This must be done if the file does not exist, or if any of the object files are newer than it. If an object file was just recompiled, it is now newer than myprogram, so myprogram is relinked. Thus, if we change the file aa.cpp and run make, make will compile that file to update aa.o, and then link myprogram. If we change the file header2.h and run make, make will recompile the object files aa.o and bb.o and then link the file myprogram.

In short, to update myprogram, we just issue make, to clean *.o and myprogram, we issue make clean.

But there are repeated files, and this makes the make error prone when other files are added later. So, we need to use variables:

#Makefile case 1
OBJECTS = main.o aa.o bb.o cc.o
myprogram : $(OBJECTS)
	g++ -o myprogram $(OBJECTS)

main.o : main.cpp header1.h
	g++ -c main.cpp	
aa.o : aa.cpp header1.h header2.h
	g++ -c aa.cpp
bb.o : bb.cpp header2.h
	g++ -c bb.cpp
cc.o : cc.cpp header3.h
	g++ -c cc.cpp
clean :
	rm myprogram \
	$(OBJECTS)


KwhaChunMusium2.png

Acutally, make has an implicit rule (when and how to remake files based on their names) for updating a *.o file from a correspondingly named *.cpp file, we do not have to put recipes for the compiler. For example, to make main.o we do not have to specify g++ -c main.cpp:

#Makefile case 2
OBJECTS = main.o aa.o bb.o cc.o
myprogram : $(OBJECTS)
	g++ -o myprogram $(OBJECTS)
main.o : header1.h
aa.o :  header1.h header2.h
bb.o : header2.h
cc.o : header3.h
clean : rm myprogram \
	$(OBJECTS)

To prevent make from getting confused by an actual file called clean, me may use .PHONY:

#Makefile case 3
OBJECTS = main.o aa.o bb.o cc.o
myprogram : $(OBJECTS)
	g++ -o myprogram $(OBJECTS)
main.o : header1.h
aa.o :  header1.h header2.h
bb.o : header2.h
cc.o : header3.h
.PHONY : clean
clean : -rm myprogram $(OBJECTS)

The "-" in -rm causes make to continue in spite of errors from rm.


The following Makefile is using more variables including automatic variables.

#Makefile case 4
CC = g++
CFLAGS = -c
SOURCES =  main.cpp aa.cpp bb.cpp cc.cpp
OBJECTS = $(SOURCES:.cpp=.o)
EXECUTABLE = myprogram

all: $(OBJECTS) $(EXECUTABLE)

$(EXECUTABLE) : $(OBJECTS)
		$(CC) $(OBJECTS) -o $@  

.cpp.o: *.h
	$(CC) $(CFLAGS) $< -o $@

clean :
	-rm -f $(OBJECTS) $(EXECUTABLE)

.PHONY: all clean

If we do make or make all, we get:

main.cpp -o main.o
g++ -c aa.cpp -o aa.o
g++ -c bb.cpp -o bb.o
g++ -c cc.cpp -o cc.o
g++ main.o aa.o bb.o cc.o -o myprogram

If we do not specify all in the makefile, the make will only work on the first target it encounters in the makefile.

For detail explanation, please see Makefile example from Google AI Ants, and samples are available, makefile_sample.tar.gz.




If the name of the above file is neither makefile nor , the make will give the error looks like this:

$ make
make: *** No targets specified and no makefile found.  Stop.

Suppose the make file name is Makefile1, we should use -f:

$ make -f Makefile1


make with shell script

Here we added install option to the Makefile:

# compiler
CC = g++
# install dir
INSTDIR = /usr/local/bin
# include dir
INCLUDE = .
# for debug
CFLAGS = -g -c -Wall
# for release
# CFLAGS = -O -c -Wall

SOURCES =  main.cpp aa.cpp bb.cpp cc.cpp
OBJECTS = $(SOURCES:.cpp=.o)
EXECUTABLE = myprogram

all: $(OBJECTS) $(EXECUTABLE)

$(EXECUTABLE) : $(OBJECTS)
                $(CC) $(OBJECTS) -o $@

.cpp.o: *.h
        $(CC) $(CFLAGS) $< -o $@

clean :
        -rm -f $(OBJECTS) $(EXECUTABLE)

.PHONY: all clean

install: $(EXECUTABLE)
        @ if [ -d $(INSTDIR) ]; then \
           cp $(EXECUTABLE) $(INSTDIR); \
           chmod a+x $(INSTDIR)/$(EXECUTABLE); \
           chmod og-w $(INSTDIR)/$(EXECUTABLE); \
           echo "$(EXECUTABLE) is installed in $(INSTDIR)"; \
        else \
           echo "Warning! $(INSTDIR) does not exist"; \
        fi                                         

The make knows dependency, it should do something about the files that myprogram depends upon before install the target. The rule for install is written in shell script. To execute the rules specified by the shell script, make invokes a shell for each rule (recipe). The @ in front of the if statement, blocks echo for each command. Actually the back slash(\) makes enables the one time invoke of the shell by making the script one line.

$ make install
g++ -g -c -Wall main.cpp -o main.o
g++ -g -c -Wall aa.cpp -o aa.o
g++ -g -c -Wall bb.cpp -o bb.o
g++ -g -c -Wall cc.cpp -o cc.o
g++ main.o aa.o bb.o cc.o -o myprogram  
myprogram is installed in /usr/local/bin

If we want to constrain the execution of script, i.e., for conditional execution, we can use &&:

install: $(EXECUTABLE)
        @ if [ -d $(INSTDIR) ]; \
        then \
           cp $(EXECUTABLE) $(INSTDIR) && \
           chmod a+x $(INSTDIR)/$(EXECUTABLE) && \
           chmod og-w $(INSTDIR)/$(EXECUTABLE) && \
           echo "$(EXECUTABLE) is installed in $(INSTDIR)"; \
        else \
           echo "Warning! $(INSTDIR) does not exist"; \
        fi


Inference rule of make

Let's use make with no Makefile.

/* main.cpp */

#include <stdio.h>
int main(int argc, char* argv[])
{
   return 0;
}

If we run make:

$ make main
g++    -c -o main.o main.cpp
cc   main.o   -o main

No problem!

That's because make has lots of internal rules, and it knows how to invoke compiler as we see from the example above. It is called inference rule. Since the rules use macro, we can change the behavior by assigning a new value to the macro.

Let's look into the internal things using make -p:

$ make -p
...
# default
LINK.o = $(CC) $(LDFLAGS) $(TARGET_ARCH)
# default
OUTPUT_OPTION = -o $@
# default
COMPILE.cpp = $(COMPILE.cc)
# makefile
MAKEFILE_LIST := 
# automatic
@F = $(notdir $@)
# environment
HISTCONTROL = ignoredups
# environment
USERNAME = KHong
# default
LINK.p = $(PC) $(PFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
# environment
DBUS_SESSION_BUS_ADDRESS = unix:abstract=/tmp/dbus-RoRanvDlfE,guid=c1626f5713375
4705bb66b075169bb24
# default
CC = cc
# default
CHECKOUT,v = +$(if $(wildcard $@),,$(CO) $(COFLAGS) $< $@)
...




Suffix and pattern

In the previous section, we used the following:

SOURCES =  main.cpp aa.cpp bb.cpp cc.cpp
OBJECTS = $(SOURCES:.cpp=.o)

It enables generating .o files from .cpp files.



SNU





Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization

YouTubeMy YouTube channel

Sponsor Open Source development activities and free contents for everyone.

Thank you.

- K Hong






Sponsor Open Source development activities and free contents for everyone.

Thank you.

- K Hong






C++ Tutorials

C++ Home

Algorithms & Data Structures in C++ ...

Application (UI) - using Windows Forms (Visual Studio 2013/2012)

auto_ptr

Binary Tree Example Code

Blackjack with Qt

Boost - shared_ptr, weak_ptr, mpl, lambda, etc.

Boost.Asio (Socket Programming - Asynchronous TCP/IP)...

Classes and Structs

Constructor

C++11(C++0x): rvalue references, move constructor, and lambda, etc.

C++ API Testing

C++ Keywords - const, volatile, etc.

Debugging Crash & Memory Leak

Design Patterns in C++ ...

Dynamic Cast Operator

Eclipse CDT / JNI (Java Native Interface) / MinGW

Embedded Systems Programming I - Introduction

Embedded Systems Programming II - gcc ARM Toolchain and Simple Code on Ubuntu and Fedora

Embedded Systems Programming III - Eclipse CDT Plugin for gcc ARM Toolchain

Exceptions

Friend Functions and Friend Classes

fstream: input & output

Function Overloading

Functors (Function Objects) I - Introduction

Functors (Function Objects) II - Converting function to functor

Functors (Function Objects) - General



Git and GitHub Express...

GTest (Google Unit Test) with Visual Studio 2012

Inheritance & Virtual Inheritance (multiple inheritance)

Libraries - Static, Shared (Dynamic)

Linked List Basics

Linked List Examples

make & CMake

make (gnu)

Memory Allocation

Multi-Threaded Programming - Terminology - Semaphore, Mutex, Priority Inversion etc.

Multi-Threaded Programming II - Native Thread for Win32 (A)

Multi-Threaded Programming II - Native Thread for Win32 (B)

Multi-Threaded Programming II - Native Thread for Win32 (C)

Multi-Threaded Programming II - C++ Thread for Win32

Multi-Threaded Programming III - C/C++ Class Thread for Pthreads

MultiThreading/Parallel Programming - IPC

Multi-Threaded Programming with C++11 Part A (start, join(), detach(), and ownership)

Multi-Threaded Programming with C++11 Part B (Sharing Data - mutex, and race conditions, and deadlock)

Multithread Debugging

Object Returning

Object Slicing and Virtual Table

OpenCV with C++

Operator Overloading I

Operator Overloading II - self assignment

Pass by Value vs. Pass by Reference

Pointers

Pointers II - void pointers & arrays

Pointers III - pointer to function & multi-dimensional arrays

Preprocessor - Macro

Private Inheritance

Python & C++ with SIP

(Pseudo)-random numbers in C++

References for Built-in Types

Socket - Server & Client

Socket - Server & Client 2

Socket - Server & Client 3

Socket - Server & Client with Qt (Asynchronous / Multithreading / ThreadPool etc.)

Stack Unwinding

Standard Template Library (STL) I - Vector & List

Standard Template Library (STL) II - Maps

Standard Template Library (STL) II - unordered_map

Standard Template Library (STL) II - Sets

Standard Template Library (STL) III - Iterators

Standard Template Library (STL) IV - Algorithms

Standard Template Library (STL) V - Function Objects

Static Variables and Static Class Members

String

String II - sstream etc.

Taste of Assembly

Templates

Template Specialization

Template Specialization - Traits

Template Implementation & Compiler (.h or .cpp?)

The this Pointer

Type Cast Operators

Upcasting and Downcasting

Virtual Destructor & boost::shared_ptr

Virtual Functions



Programming Questions and Solutions ↓

Strings and Arrays

Linked List

Recursion

Bit Manipulation

Small Programs (string, memory functions etc.)

Math & Probability

Multithreading

140 Questions by Google



Qt 5 EXPRESS...

Win32 DLL ...

Articles On C++

What's new in C++11...

C++11 Threads EXPRESS...

Go Tutorial

OpenCV...








Contact

BogoToBogo
contactus@bogotobogo.com

Follow Bogotobogo

About Us

contactus@bogotobogo.com

YouTubeMy YouTube channel
Pacific Ave, San Francisco, CA 94115

Pacific Ave, San Francisco, CA 94115

Copyright © 2024, bogotobogo
Design: Web Master