Detailed makefile and complete project examples
1. Makefile introduction
This part is summarized from "Write Makefile with Me"
1.1 What is a makefile?
The source files in a code project are not counted. They are placed in several directories according to type, function, and module.
Makefile defines a series of rules to specify which files need to be compiled first, which files need to be compiled later, which files need to be recompiled, and even more complex functional operations.
Because the makefile is like a shell script, which can also execute operating system commands.
1.2. Makefile advantages
The benefit of makefile is "automatic compilation". Once it is written,
only one make command is needed, and the entire project is completely compiled automatically, which greatly improves the efficiency of software development.
1.3. What is make?
make is a command tool, a command tool that interprets the instructions in the makefile.
Nmake of Visual C++,
make of GNU under Linux
The make command will automatically and intelligently determine which files need to be recompiled according to the current file modification, so as to compile the required files and link the target program.
1.4 Makefile rules
target ... : prerequisites ...
command
...
...
target is a target file, which can be an Object File or an execution file.
Prerequisites are the files or targets needed to generate that target.
command is the command that make needs to execute.
This is a file dependency, that is, one or more target files of target depend on files in prerequisites, and the generation rules are defined in command.
2. Code example
2.1 Project catalog and description
-
Project directory:
…\src\app
…\src\lib
…\src\obj -
Compile command:
make clean
make
./obj/XXX_YYY -
Compilation instructions:
first compile lib, then compile app, and finally compile obj -
Compilation result: process XXX_YYY
…\src\obj\XXX_YYY
2.2 Compile lib
######makefile for XXX/src/lib##########
CC=gcc
AR=ar
LIBRARY= libmsg.a
SOURCE=${wildcard *.c}
LIB_OBJS =${patsubst %.c, %.o, $(SOURCE)}
ifeq ($(MODE), DEBUG)
CFLAGS = -g -O2 -fstack-protector-all -fno-omit-frame-pointer
endif
CFLAGS += -W -Wall -Wno-unused-parameter -fexceptions
CFLAGS += -Isrc/lib
COMPILE = $(CC) $(CFLAGS) -fPIC -c $^ -o $@
all: $(LIBRARY)
$(LIBRARY): $(LIB_OBJS)
rm -f $@
$(AR) -crs $@ $^
%.o: $.c
$(COMPILE)
clean:
rm -rf *.o
rm -rf *.a
rm -rf *.d
rm -f *~
2.3 Compile the app
######makefile for XXX/src/app##########
CC=gcc
AR=ar
TARGET=XXX_YYY
SOURCE=${wildcard *.c}
TARGET_OBJS =${patsubst %.c, %.o, $(SOURCE)}
LIB_OBJ=../lib/libmsg.a
ifeq ($(MODE), DEBUG)
CFLAGS = -g -O2 -fstack-protector-all -fno-omit-frame-pointer
endif
CFLAGS += -W -Wall -Wno-unused-parameter -fexceptions
CFLAGS += -I$(TOPDIR)/lib
LIBPATH = /usr/lib/
LDFLAGS = -L$(LIBPATH) -L$(TOPDIR)/lib
LDFLAGS += -g -lm -ldl -lutil -pthread -lpython3.7m
COMPILE= $(CC) $(CFLAGS) -c $^ -o $@
all: $(TARGET)
$(TARGET): $(TARGET_OBJS) $(LIB_OBJ)
$(CC) $^ $(LDFLAGS) $(CFLAGS) -o $@
%.o: $.c
$(COMPILE)
clean:
rm -rf *.o
rm -rf *.a
rm -rf *.d
rm -f *~
2.4 Compile the target program XXX_YYY
######makefile for XXX/src##########
TOPDIR:=$(shell pwd)
OBJDIR=$(TOPDIR)/obj
TARGET=XXX_YYY
all:
mkdir -p $(OBJDIR)
make -C lib
make -C app
mv $(TOPDIR)/app/$(TARGET) $(OBJDIR)/
clean:
make -C app clean
make -C lib clean
rm -rf $(OBJDIR)
Compilation result: process XXX_YYY
…\src\obj\XXX_YYY
3. Compile option description
3.1 Compile option description
-
CC specifies the compiler
cc is the compile command used under Unix;
gcc is the compile command used under linux; -
CFLAGS represents the options for the C compiler, for example: -W -Wall -g
CXXFLAGS represents the options for the C++ compiler. -
Compilation parameter
-Wall: display warning message
-g GDB can read
-c compile but not link
-lm math library
-lpthread multithread
-ldl explicitly load the dynamic function library of the dynamic library
-fPIC acts on the compilation stage and tells the compiler Generate position-independent code (Position-Independent Code), there is no absolute address in the generated code, all relative addresses are used, so the code can be loaded by the loader to any location in the memory and can be executed correctly. This is exactly what the shared library requires. When the shared library is loaded, its location in memory is not fixed. -
LIBS tells the linker which library files to link with
LDFLAGS Specify -L although the linker can find the library for linking -
AR=ar is packaged into lib, such as libmsg.a in the project.
$(AR) -crs $@ $^
c: Create a library. Regardless of whether the library exists, it will create
s: write an object file index to the library, or update an existing object file index
r: insert a module in the library (replace). When the inserted module name already exists in the library, replace the
linux ar command with the same name.
Reference:
https://www.runoob.com/linux/linux-comm-ar.html -
SOURCE=${wildcard *.c}
wildcard: Expand wildcard to specify the directory./ and ./sub/ All files with the suffix c are expanded
SRC = $(wildcard *.c)
is equal to the specified compilation of all .c in the current directory File, if there is a subdirectory, for example, the subdirectory is inc, add a wildcard function, like this:
SRC = $(wildcard .c) $(wildcard inc/ .c) -
clean rules for clearing target files (.o and execution files)
-
notdir: remove path
patsubst: replace wildcard -
@ Means goal, @ means goal, @ Table shows entry standard , ^ represents a dependency list.
For example:
edit: main.o kbd.o command.o display.o insert.o search.o files.o utils.o
$@ is edit
$^ is main.o kbd.o command.o display.o insert.o search.o files.o utils.o -
A sign of the command COMPILE, you can name it arbitrarily
-
Make parameters
-C DIR, -directory=DIR Before reading the Makefile, enter the directory DIR, and then execute make.
make clean Clear the compilation results
Clear the object files (files with suffix ".o") and executable files generated by the last make command.
Reference: A
summary of make command parameters and options
http://c.biancheng.net/view /7126.html -
all
this is usually a virtual target, it does not create any files, but only depends on other files. Such as: all: $(TARGET) The
all target is usually the first target in the makefile, because if you just write make on the command line without specifying the target, it will build the first target.