User Tools

Site Tools


makefiles

Makefiles

Make is the ultimate build tool on Unix systems. It handles complicated dependencies and reduces your work as a programmer. For example, with Make, instead of typing this whole thing:

   gcc -D__KERNEL__ -I/usr/src/linux-2.4.18-17.8.0/include -Wall -Wstrict-prototypes
  -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer -pipe
  -mpreferred-stack-boundary=2 -march=i686   -nostdinc -I /usr/lib/gcc-lib/i386-redhat-linux/3.2/include
  -DKBUILD_BASENAME=serial  -DEXPORT_SYMTAB -c serial.c

You can simply type this instead:

   make
   

With a properly defined Makefile, you can compile all or part of your project without getting tangled up in a web of dependencies. It works with C/C++, Java, and any other language. The making of a Makefile

A Makefile is much like a shell script in that you can use variables and issue executable commands. Generally, a Makefile consists of two sections: variables (technically called “macros”) and targets.

Variable Definitions

This section is where you define variables for use in the Makefile. This is very convenient since you often want to make a change to the way that all your files are compiled. Variables let you do this with minimal effort. Almost every Makefile defines the CC variable to be the compiler for the system. For example:

   CC = g++

Other common variables are FLAGS and LINK_FLAGS:

   FLAGS = -pipe -O3 -g
   LINK_FLAGS = -lnsl -lpthread

Once you've created a variable, you can access it by surrounding it with parentheses and the “dollar” sign. The following example will print the contents of the FLAGS variable to the screen:

  @echo FLAGS is: $(FLAGS)

Targets (dependencies)

Targets consist of the target name followed by a list of dependencies, and the action to perform. Here is an example:

   main.o: main.h main.cpp
       g++ -c main.cpp -o main.o

In English, here's what this target definition states:

  "To build main.o, check main.h and main.cpp. If either have changed since the last time we built main.o,
  then we need to rebuild it. Otherwise, no changes are necessary. If we decide we need to build main.o,
  run the command g++ -c main.cpp -o main.o."

If that's not enough explanation for you, here's a graphic explaining the four different parts of the target:

makefile_diagram.jpg

Generally, a Makefile will contain several of these targets. The first target listed is the default, and is the only one that will be executed when you issue the make command with no options. You can also tell make to build a certain target. In the preceding example, we could say make main.o to only build that target.

Targets can depend on more than just files. They can depend on other make targets. Consider, for example, the following Makefile:

  main.o: main.h main.cpp word.o
      g++ -c main.cpp -o main.o
  word.o: word.h word.cpp
      g++ -c word.cpp -o word.o

Notice that the target main.o depends on the target word.o (in addition to main.h and main.cpp). When you run make, it will start to execute the default target (main.o). When it notices that main.o depends on word.o, it will jump to that target and execute it in the normal way as well. This is the real magic of make. If, for example, word.o had not been altered, make would not have re-built it unnecessarily. This means that when you alter a single file, make won't naively recompile every file in the project.

Sample Makefiles

Here I present three Makefiles that you can adjust to taste.

Sample C++ Makefile

This Makefile builds an executable called chess based on a set of three C++ files. There are four build targets. The default target is named after the variable EXE_NAME which you can name in the variables section. Notice that the default target depends only on three other targets. This means that the executable will be rebuilt every time you edit any of the files in the project. However, make will not rebuild unaffected object files.

  ## Variables
  CC = g++
  FLAGS = -g
  EXE_NAME = chess
  GTK_FLAGS = `gtkmm-config --cflags --libs`
  
  ## Build targets
  
  # Default target (builds the final executable)
  $(EXE_NAME): chessgui.o chess.o messagebox.o
  $(CC) $(FLAGS) -o $(EXE_NAME) $(GTK_FLAGS)
  # Three other targets (build object files)
  chessgui.o: chessgui.h chessgui.cpp
  $(CC) $(FLAGS) -c chessgui.cpp $(GTK_FLAGS)
  
  chess.o: chess.h chess.cpp
  $(CC) $(FLAGS) -c chess.cpp $(GTK_FLAGS)
  
  messagebox.o: messagebox.h messagebox.cpp
  $(CC) $(FLAGS) -c messagebox.cpp $(GTK_FLAGS)
  

Magic generic Makefile for any C++ project

This example will automagically find and compile your files for you, and all you have to do is specify the program name and the list of .o files. It assumes that if you want to build myfile.o then there must also exist a myfile.c (or some variant: .cpp or .cc)

  # change this to your program name
  EXE_NAME = my_program
  # list your object files
  OBJS = file1.o file2.o file3.o
  CC = g++
  FLAGS = -g
  
  # No need to alter anything below this
  
  .C.o:
  $(CC) $< -c $(FLAGS) $(INC)
  
  $(EXE_NAME): $(OBJS)
  $(CC) -o $@ $(OBJS) $(FLAGS) $(INC) $(LIBS) $(XLIBS) -lm

Java Makefile

Makefiles aren't just for C/C++. Any language can benefit from their magic. This Makefile will rebuild .class files as need from source .java files.

  # This Makefile will build a jar file (Chat.jar) out of a set of
  # three class files. This is the coolest way to rebuild your java
  # files selectively after making some changes. Just type 'make'.
  
  JAVAC = javac
  CLASS_FILES = ChatClient.class ChatServer.class GUI.class
  JAR_CMD = jar cvf
  JAR_NAME = Chat.jar
  
  Default: $(CLASS_FILES)
  $(JAR_CMD) $(JAR_NAME) $(CLASS_FILES)
  
  %.class: %.java
  $(JAVAC) $<
  

Cool Makefile hacks

You can use make for more than just compiling your C/C++ projects.

You could also use it to…

Update web-pages

You can maintain a set of html pages in a directory off-line. You can tell make to ftp the changed files to your web-server automatically. Instant web updates!

Commit changes to config files

You can have a make target depend on the config file for a server on your system. When you run make, if the config file has changed, it can restart the server. Here is an example with apache on RedHat systems:

  apache.last_restarted: httpd.conf
  @echo Config file has been altered, restarting Apache...
  @touch apache.last_restarted
  @service httpd restart
  

Just run make after changing your config file. If there were changes, make will automagically restart Apache for you.

Restart system services that depend on each other

Other resources
makefiles.txt · Last modified: 2017/06/29 15:51 by nesretep