Common Makefile Templates for Linux Development

Common Makefile Templates for Linux Development

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

1. Introduction

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

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

Linux can also achieve a “one-click compile” feature, necessitating a compilation script, the Makefile. The Makefile can be manually written or generated using automated build tools (such as scons, CMake). Manually writing a Makefile is one distinction between Linux and Windows programmers; generally, a universal Makefile can fit most Linux project programs.

2. Three Makefile Templates

2.1 Compile Executable File Makefile

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

Multiple program versions may be generated during development and debugging; a version number can be added after (or before) the target file.

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; different CPU vendors may provide custom cross-compiler names, such as Hisilicon’s arm-hisiv300-linux-gcc.

CC = gcc

3. Macro Definitions

During development, special code often adds macro conditions to choose whether to compile, such as debugging print output code. -D is a marker, followed by the macro.

DEBUG =-DUSE_DEBUG

4. Compilation Options

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

CFLAGS =-Wall -O

5. Source Files

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

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

6. Header Files

Include the necessary header files, including those for source files and libraries.

INCLUDES =-I./include

7. Library File Names

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

LIB_NAMES =-lfun_a -lfun_so

8. Library File Paths

Specify the storage path for dependent library files. Note that if a dynamic library is referenced, it may need to be copied to the /lib or /usr/lib directory, as the system defaults to indexing dynamic libraries from that path when executing applications.

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

Specify the 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 and outputting the target executable file, temporary files (.o) generated during compilation can be deleted.

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

13. Clear Compilation Information

Execute make clean to clear temporary files generated during compilation.

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

2.2 Compile Static Library Makefile

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 consistent with the “Compile Executable Makefile”; the differences include the following.

1. Using the “ar” command to link target files (.o) into a static library file (.a). Static library files have a fixed naming format: libxxx.a.

2.3 Compile Dynamic Library Makefile

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 consistent with the “Compile Executable Makefile”; the differences include the following.

1. Compilation options and linking options add -fPIC -shared. Dynamic library files have a fixed naming format: libxxx.so.

3. Demo

3.1 Compile Application Program

Write a test routine, with the file storage directory structure as follows: header files in the include directory, library files in the lib directory, source files in the source directory, and the Makefile in the current directory.

Common Makefile Templates for Linux 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");
}
</stdio.h>

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");
}
</stdio.h>

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;
}
</stdio.h>

Library files, with one static library libfun_a.a and one dynamic library libfun_so.so stored in the ./lib directory.

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

Test run:

Common Makefile Templates for Linux Development

[If the executable file prompts that there is no libfun_so.so, it needs to copy libfun_so.so to the /lib or /usr/lib directory, as the system executes the program, defaulting to pull dynamic libraries from that path]

3.2 Generate Static Library

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

Common Makefile Templates for Linux 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");
}
</stdio.h>

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

Compile to generate static library:

Common Makefile Templates for Linux Development

3.3 Generate Dynamic Library

Write a test routine, the generated library file is the same as the library file called in section 3.1 (libfun_so.so). The file storage directory structure is as follows:

Common Makefile Templates for Linux Development

Source Code:

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

extern void fun_lib_so_printf(void);

/*Header file*/

#include <stdio.h>
#include "fun_lib_so.h"

void fun_lib_so_printf(void)
{
    printf("Call 'fun_lib_so'.\r\n");
}
</stdio.h>

Compile to generate dynamic library:

Common Makefile Templates for Linux Development

This article is sourced from the internet, freely conveying knowledge, and the copyright belongs to the original author. If there are copyright issues, please contact me for deletion.

Previous Recommendations

“Complete Embedded Linux Driver”

Reply 1024 in the WeChat public account chat interface to obtain embedded resources.

Leave a Comment