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

  1. Project directory:
    …\src\app
    …\src\lib
    …\src\obj

  2. Compile command:

    make clean
    make
    ./obj/XXX_YYY

  3. Compilation instructions:
    first compile lib, then compile app, and finally compile obj

  4. 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

  1. CC specifies the compiler
    cc is the compile command used under Unix;
    gcc is the compile command used under linux;

  2. CFLAGS represents the options for the C compiler, for example: -W -Wall -g
    CXXFLAGS represents the options for the C++ compiler.

  3. 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.

  4. LIBS tells the linker which library files to link with
    LDFLAGS Specify -L although the linker can find the library for linking

  5. 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

  6. 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)

  7. clean rules for clearing target files (.o and execution files)

  8. notdir: remove path
    patsubst: replace wildcard

  9. @ 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

  10. A sign of the command COMPILE, you can name it arbitrarily

  11. 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

  12. 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.

Guess you like

Origin blog.csdn.net/lqy971966/article/details/108375191