1 Introduction
This tutorial shows a relatively complete enterprise project-level Makefile, including: version number, dynamic library, macro definition, etc.
2. Program display
The program directory structure of this routine is often seen in enterprise projects, that is: all .c files are placed in a src directory, all .h files are placed in a .h directory, and the generated targets are placed in an output directory independently (Dynamic generation).
The source code can be obtained from here .
The directory structure is as follows:
The source program is:
//fun1.h void fun1(); //fun1.c void fun1() { printf("this is fun1\n"); } //fun2.h void fun2(); //fun2.c void fun2() { printf("this is fun2\n"); } //dylib.h void dynamic_lib_call(); //main.c intmain() { printf("hello world\n"); fun1(); fun2(); #ifdef _MACRO printf("macro test\n"); #endif dynamic_lib_call(); }
The Makefile is:
VERSION = 1.0.0 #Program version number SOURCE = $(wildcard ./src/*.c) #Get all .c files OBJ = $(patsubst %.c, %.o, $(SOURCE)) # Convert .c files to .o files INCLUDES = -I./h #Header file path LIBS = -ldylib #Library file name LIB_PATH = -L./lib #Library file address DEBUG = -D_MACRO #macro definition CFLAGS = -Wall -c #Compile flags TARGET = app CC = gcc $(TARGET): $(OBJ) @mkdir -p output/ #Create a directory to store compiled targets $(CC) $(OBJ) $(LIB_PATH) $(LIBS) -o output/$(TARGET).$(VERSION) %.o: %.c $(CC) $(INCLUDES) $(DEBUG) $(CFLAGS) $< -o $@ .PHONY: clean clean: rm -rf $(OBJ) output/
Library file description:
The name of the library file is libdylib.so, and there is only one function in it: dynamic_lib_call(), which outputs a sentence: this is a function in dynamic library.
3. Contents of Makefile
3.1 Program version
In the process of software development, multiple versions of programs are generated, and a version number suffix is usually added to the end of the program.
VERSION = 1.0.0 #define $(CC) $(OBJ) $(LIB_PATH) $(LIBS) -o output/$(TARGET).$(VERSION) #使用
3.2 Header files
Since the .c file is separated from the .h file in a different directory, the header file path should be specified.
INCLUDES = -I./h
3.3 Macro Definition
In the process of code debugging, we usually add a macro definition to control whether this code is compiled or not, for example:
#ifdef _MACRO printf("macro test\n"); #endif
We do not need to define specific macros in the code, but specify them in the Makefile, for example:
DEBUG=-D_MACRO #define $(CC) $(INCLUDES) $(DEBUG) $(CFLAGS) $< -o $@ #使用
3.4 Compilation options
When there are many compilation options, we usually take it out separately, such as:
CFLAGS = -Wall -c #define $(CC) $(INCLUDES) $(DEBUG) $(CFLAGS) $< -o $@ #使用
3.5 Libraries
If we want to use the library in the code, we can take out the library name and path separately, for example:
LIBS = -ldylib #Library file name LIB_PATH = -L./lib #库文件地址 $(CC) $(OBJ) $(LIB_PATH) $(LIBS) -o output/$(TARGET).$(VERSION) #使用
3.6 output目录
如果不想把生成的程序与源文件混在一起,可将生成的程序单独放在一个output目录,比如:
$(TARGET): $(OBJ) @mkdir -p output/ #创建一个目录,用于存放已编译的目标 $(CC) $(OBJ) $(LIB_PATH) $(LIBS) -o output/$(TARGET).$(VERSION)4. 编译执行结果