General Makefile Templates for Development

Follow and star our public account for more exciting content
General Makefile Templates for Development

Original article: https://blog.csdn.net/qq_20553613/article/details/90649734

1. Introduction

For development on Windows, many IDEs integrate compilers, such as Visual Studio, providing a “one-click compile” feature, allowing a single operation to complete the compilation, linking, and generation of target files after coding.

Linux development differs from Windows; the gcc/g++ compiler is commonly used on Linux. If developing Linux programs for ARM, the arm-linux-gcc/arm-linux-g++ cross-compiler is also needed.

Linux can also achieve a “one-click compile” function, requiring a compilation script called a “Makefile.” Makefiles can be written manually or generated using automation build tools (such as scons, CMake). Writing Makefiles manually is one of the distinctions between Linux and Windows programmers. Generally, a generic Makefile can suit most Linux project programs.

2. Three Makefile Templates

2.1 Makefile for Compiling Executable Files

VERSION  =1.00
CC       =gcc
DEBUG    =-DUSE_DEBUG
CFLAGS   =-Wall
SOURCES  =$(wildcard ./source/*.c)
INCLUDES =-I./include
LIB_NAMES=-lfun_a -lfun_so
LIB_PATH =-L./lib
OBJ      =$(patsubst %.c, %.o, $(SOURCES))
TARGET   =app

#links
$(TARGET):$(OBJ)
 @mkdir -p output
 $(CC) $(OBJ) $(LIB_PATH) $(LIB_NAMES) -o output/$(TARGET)$(VERSION)
 @rm -rf $(OBJ)
 
#compile
%.o: %.c
 $(CC) $(INCLUDES) $(DEBUG) -c $(CFLAGS) $< -o $@

.PHONY:clean
clean:
 @echo "Remove linked and compiled files......"
 rm -rf $(OBJ) $(TARGET) output

Key Points:

1. Program Version

During the development and debugging process, multiple program versions may be generated; a version number can be added to the target file name.

VERSION = 1.00
$(CC) $(OBJ) $(LIB_PATH) $(LIB_NAMES) -o output/$(TARGET)$(VERSION)

2. Compiler Selection

On Linux, use gcc/g++; for ARM, use arm-linux-gcc; the names of customized cross-compilers provided by different CPU manufacturers may vary, such as Hisilicon’s “arm-hisiv300-linux-gcc”.

CC = gcc

3. Macro Definitions

During development, special code generally adds macro conditions to choose whether to compile, such as debug print output code. -D is the identifier, followed by the “macro”.

DEBUG =-DUSE_DEBUG

4. Compilation Options

Compilation conditions can be specified, such as displaying warnings (-Wall) and optimization levels (-O).

CFLAGS =-Wall -O

5. Source Files

Specify the source file paths, using “wildcard” to obtain all dependent source files in the path.

SOURCES =$(wildcard ./source/*.c)

6. Header Files

Include dependent header files, including those for source files and libraries.

INCLUDES =-I./include

7. Library File Names

Specify library file names, which have a fixed format: static libraries are named libxxx.a; dynamic libraries are named libxxx.so. To specify a library file name, only write the “xxx” part.

LIB_NAMES =-lfun_a -lfun_so

8. Library File Paths

Specify the storage path for dependent library files. Note that if dynamic libraries are referenced, they may need to be copied to the “/lib” or “/usr/lib” directories. When executing the application, the system defaults to indexing dynamic libraries from these paths.

LIB_PATH =-L./lib

9. Target Files

Use “patsubst” to compile source files (.c) into target files (.o).

OBJ =$(patsubst %.c, %.o, $(SOURCES))

10. Executable File

Executable file name.

TARGET =app

11. Compilation

%.o: %.c
 $(CC) $(INCLUDES) $(DEBUG) $(CFLAGS) $< -o $@

12. Linking

A folder named “output” can be created to store the target executable file. After linking, the output target executable file can delete the temporary files generated during compilation (.o).

$(TARGET):$(OBJ)
 @mkdir -p output
 $(CC) $(OBJ) $(LIB_PATH) $(LIB_NAMES) -o output/$(TARGET)$(VERSION)
 @rm -rf $(OBJ)

13. Clean Compilation Information

Execute “make clean” to remove temporary files generated during compilation.

.PHONY:clean
clean:
 @echo "Remove linked and compiled files......"
 rm -rf $(OBJ) $(TARGET) output

2.2 Makefile for Compiling Static Libraries

VERSION     =
CC          =gcc
DEBUG       =
CFLAGS      =-Wall
AR          =ar
ARFLAGS     =rv
SOURCES     =$(wildcard *.c)
INCLUDES    =-I.
LIB_NAMES   =
LIB_PATH    =
OBJ         =$(patsubst %.c, %.o, $(SOURCES))
TARGET      =libfun_a

#link
$(TARGET):$(OBJ)
 @mkdir -p output
 $(AR) $(ARFLAGS) output/$(TARGET)$(VERSION).a $(OBJ)
 @rm -rf $(OBJ)

#compile
%.o: %.c
 $(CC) $(INCLUDES) $(DEBUG) -c $(CFLAGS) $< -o $@
  
.PHONY:clean
clean:
 @echo "Remove linked and compiled files......"
 rm -rf $(OBJ) $(TARGET) output

Key Points:

The basic format is similar to the “Makefile for Compiling Executable Files,” with the following differences.

1. Uses the “ar” command to link target files (.o) into a static library file (.a). The naming format for static library files is fixed: libxxx.a.

2.3 Makefile for Compiling Dynamic Libraries

VERSION   =
CC        =gcc
DEBUG     =
CFLAGS    =-fPIC -shared 
LFLAGS    =-fPIC -shared 
SOURCES   =$(wildcard *.c)
INCLUDES  =-I.
LIB_NAMES =
LIB_PATH  =
OBJ       =$(patsubst %.c, %.o, $(SOURCES))
TARGET    =libfun_so

#link
$(TARGET):$(OBJ)
 @mkdir -p output
 $(CC) $(OBJ) $(LIB_PATH) $(LIB_NAMES) $(LFLAGS) -o output/$(TARGET)$(VERSION).so
 @rm -rf $(OBJ)
 
#compile
%.o: %.c
 $(CC) $(INCLUDES) $(DEBUG) -c $(CFLAGS) $< -o $@

.PHONY:clean
clean:
 @echo "Remove linked and compiled files......"
 rm -rf $(OBJ) $(TARGET) output

Key Points:

The basic format is similar to the “Makefile for Compiling Executable Files,” with the following differences.

1. Compilation and linking options include “-fPIC -shared”. The naming format for dynamic library files is fixed as libxxx.so.

3. Demo

3.1 Compiling Applications

Write test routines, with the file storage directory structure as follows: header files stored in the “include” directory, library files stored in the “lib” directory, source files stored in the “source” directory, and the Makefile in the current directory.

General Makefile Templates for Development

Source code 1:

/*Header File*/
#ifndef _FUN0_H_
#define _FUN0_H_
#endif

extern void fun0_printf(void);
extern void fun1_printf(void);

/*Source File*/
#include <stdio.h>
#include "fun0.h"

void fun0_printf(void)
{
    printf("Call 'fun0'. \r\n");
}

Source code 2:

/*Header File*/
#ifndef _FUN1_H_
#define _FUN1_H_
#endif

extern void fun1_printf(void);

/*Source File*/
#include <stdio.h>
#include "fun1.h"

void fun1_printf(void)
{
    printf("Call 'fun1'.\r\n");
}

Main function source code:

/*Source File*/
#include <stdio.h>
#include "fun0.h"
#include "fun1.h"
#include "fun_lib_a.h"
#include "fun_lib_so.h"

int main(void)
{
    #ifdef USE_DEBUG
        printf("Debug Application startup.\r\n");
    #endif
    
        fun0_printf();
        fun1_printf();
        fun_lib_a_printf();
        fun_lib_so_printf();
        return 0;
}

Library files: two library files are stored in the “./lib” directory, one static library libfun_a.a, and one dynamic library libfun_so.so.

The Makefile file is the same as the Makefile template in section “2.1”.

Test run:

General Makefile Templates for Development

If the executable file indicates that “libfun_so.so” is missing, it needs to be copied to the root directory’s “/lib” or “/usr/lib” directory because the system executes programs, defaulting to pulling dynamic libraries from these paths.

3.2 Generating Static Libraries

Write test routines, the generated library file is the one called in section “3.1” (libfun_a.a). The file storage directory structure is as follows:

General Makefile Templates for Development

Source code:

/*Header File*/
#ifndef _FUN_LIB_A_H_
#define _FUN_LIB_A_H_
#endif

extern void fun_lib_a_printf(void);

/*Source File*/
#include <stdio.h>
#include "fun_lib_a.h"

void fun_lib_a_printf(void)
{
    printf("Call 'fun_lib_a'.\r\n");
}

The Makefile file is the same as the Makefile template in section “2.2”.

Compile to generate the static library:

General Makefile Templates for Development

3.3 Generating Dynamic Libraries

Write test routines, the generated library file is the one called in section “3.1” (libfun_so.so). The file storage directory structure is as follows:

General Makefile Templates for Development

Source code:

/*Header File*/
#ifndef _FUN_LIB_SO_H_
#define _FUN_LIB_SO_H_
#endif

extern void fun_lib_so_printf(void);

/*Source File*/
#include <stdio.h>
#include "fun_lib_so.h"

void fun_lib_so_printf(void)
{
    printf("Call 'fun_lib_so'.\r\n");
}

Compile to generate the dynamic library:

General Makefile Templates for Development

‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧ END ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

Follow my public WeChat account, reply 'join group' to join the technical exchange group as per the rules.

Click 'Read the original text' for more shares, feel free to share, collect, like, and view.

Leave a Comment