👹
Carlos's Tech Blog
  • 🧔ECUs
    • ZYNQ_Documents
      • [ZYNQ] 构建ZYNQ的BSP工程
      • [ZYNQ] 启动流程
      • [ZYNQ] Secure Boot Flow
      • [ZYNQ] Provisioning Guideline
      • [ZYNQ] Decrypting Partition by the Decrypt Agent Using PUF key
      • [ZYNQ] enabling the cryptsetup on ramdisk
      • [ZYNQ] Encrypt external files based on file system using PUF key
      • [ZYNQ] Loading an Encrypted Linux kernel at U-Boot with a KUP Key
      • [ZYNQ] cross-compile the cryptsetup on Xilinx ZYNQ aarch64 platform
      • [ZYNQ] Linux Linaro系统镜像制作SD卡启动
    • S32G_Documents
      • [S32G] Going through the s32g hard/soft platform
      • [S32G] S32g247's Secure Boot using HSE firmware
        • S32g2 HSE key config
        • How S32g verify secure boot image
        • S32g secure boot signature generation
        • How to download and build S32g Secure boot image
        • [S32G] OTA with Secure Boot
    • RT117x_Documents
      • [RT-117x]IMX RT1170 Provisioning Guideline
      • [RT-117x] Going through the MX-RT1170 hard/soft platform
      • [RT-117x] i.MX-RT1170's Secure Boot
        • [RT-117x]Signing image with the HSM (SignServer)
    • LS104x_Documents
      • [LS104x] bsp project
      • [LS104x] boot flow
      • [LS104x] secure boot
      • [LS104x] Application Note, Using the PKCS#11 in TCU platform
      • [LS104x] 使用ostree更新rootfs
      • [LS104x] ostree的移植
      • [LS104x] Starting with Yocto
      • [LS104x] 使用FIT的kernel格式和initramfs
    • IMX6/8_Documents
      • [IMX6] Defining A U-Boot Command
      • NXP IMX6 嵌入式板子一些笔记
      • NXP-imx6 initialization
    • Vehicle_Apps
      • [SecOC] Tree
        • [SecOC] SecOC Freshness and MAC Truncation
  • 😾TECH
    • Rust Arm OS
      • ARMv7m_Using_The_RUST_Cross_Compiler
    • ARM
      • ARM-v7-M
        • 01_ARMv7-M_处理器架构技术综述
        • 02_ARMv7-M_编程模型与模式
        • 03_ARMv7-M_存储系统结构
        • 04_ARMv7-M_异常处理及中断处理
      • ARM-v8-A
        • 02_ARMv8_基本概念
        • 03_ARMv8_指令集介绍_加载指令集和存储指令集
        • 04_ARMv8_指令集_运算指令集
        • 05_ARMv8_指令集_跳转_比较与返回指令
        • 06_ARMv8_指令集_一些重要的指令
        • 0X_ARMv8_指令集_基于汇编的UART驱动
        • 07_ARMv8_汇编器Using as
        • 08_ARMv8_链接器和链接脚本
        • 09_ARMv8_内嵌汇编(内联汇编)Inline assembly
        • 10_ARMv8_异常处理(一) - 入口与返回、栈选择、异常向量表
        • 11_ARMv8_异常处理(二)- Legacy 中断处理
        • 12_ARMv8_异常处理(三)- GICv1/v2中断处理
        • 13_ARMv8_内存管理(一)-内存管理要素
        • 14_ARMv8_内存管理(二)-ARM的MMU设计
        • 15_ARMv8_内存管理(三)-MMU恒等映射及Linux实现
        • 16_ARMv8_高速缓存(一)cache要素
        • 17_ARMv8_高速缓存(二)ARM cache设计
        • 18_ARMv8_高速缓存(三)多核与一致性要素
        • 19_ARMv8_TLB管理(Translation Lookaside buffer)
        • 20_ARMv8_barrier(一)流水线和一致性模型
        • 21_ARMv8_barrier(二)内存屏障案例
      • ARM Boot Flow
        • 01_Embedded_ARMv7/v8 non-secure Boot Flow
        • 02_Embedded_ARMv8 ATF Secure Boot Flow (BL1/BL2/BL31)
        • 03_Embedded_ARMv8 BL33 Uboot Booting Flow
      • ARM Compiler
        • Compiler optimization and the volatile keyword
      • ARM Development
        • 在MACBOOK上搭建ARMv8架构的ARM开发环境
        • Starting with JLink debugger or QEMU
    • Linux
      • Kernel
        • 0x01_LinuxKernel_内核的启动(一)之启动前准备
        • 0x02_LinuxKernel_内核的启动(二)SMP多核处理器启动过程分析
        • 0x21_LinuxKernel_内核活动(一)之系统调用
        • 0x22_LinuxKernel_内核活动(二)中断体系结构(中断上文)
        • 0x23_LinuxKernel_内核活动(三)中断体系结构(中断下文)
        • 0x24_LinuxKernel_进程(一)进程的管理(生命周期、进程表示)
        • 0x25_LinuxKernel_进程(二)进程的调度器的实现
        • 0x26_LinuxKernel_设备驱动(一)综述与文件系统关联
        • 0x27_LinuxKernel_设备驱动(二)字符设备操作
        • 0x28_LinuxKernel_设备驱动(三)块设备操作
        • 0x29_LinuxKernel_设备驱动(四)资源与总线系统
        • 0x30_LinuxKernel_设备驱动(五)模块
        • 0x31_LinuxKernel_内存管理(一)物理页面、伙伴系统和slab分配器
        • 0x32_LinuxKernel_内存管理(二)虚拟内存管理、缺页与调试工具
        • 0x33_LinuxKernel_同步管理_原子操作_内存屏障_锁机制等
        • 01_LinuxDebug_调试理论和基础综述
      • Userspace
        • Linux-用户空间-多线程与同步
        • Linux进程之间的通信-管道(上)
        • Linux进程之间的通信-管道(下)
        • Linux进程之间的通信-信号量(System V)
        • Linux进程之间的通信-内存共享(System V)
        • Linux进程之间的通信-消息队列(System V)
        • Linux应用调试(一)方法、技巧和工具 - 综述
        • Linux应用调试(二)工具之coredump
        • Linux应用调试(三)工具之Valgrind
        • Linux机制之内存池
        • Linux机制之对象管理和引用计数(kobject/ktype/kset)
        • Linux机制copy_{to, from}_user
        • Linux设备树 - DTS语法、节点、设备树解析等
        • Linux System : Managing Linux Services - inittab & init.d
        • Linux System : Managing Linux Services - initramfs
      • Kernel Examples
        • Linux Driver - GPIO键盘驱动开发记录_OMAPL138
        • 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(一)之miscdevice和ioctl
        • 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(二)之cdev与read、write
        • 基于OMAPL138的字符驱动_GPIO驱动AD9833(三)之中断申请IRQ
        • Linux内核调用SPI驱动_实现OLED显示功能
        • Linux内核调用I2C驱动_驱动嵌套驱动方法MPU6050
    • OPTEE
      • 01_OPTEE-OS_基础之(一)功能综述、简要介绍
      • 02_OPTEE-OS_基础之(二)TrustZone和ATF功能综述、简要介绍
      • 03_OPTEE-OS_系统集成之(一)编译、实例、在QEMU上执行
      • 05_OPTEE-OS_系统集成之(三)ATF启动过程
      • 06_OPTEE-OS_系统集成之(四)OPTEE镜像启动过程
      • 07_OPTEE-OS_系统集成之(五)REE侧上层软件
      • 08_OPTEE-OS_系统集成之(六)TEE的驱动
      • 09_OPTEE-OS_内核之(一)ARM核安全态和非安全态的切换
      • 10_OPTEE-OS_内核之(二)对安全监控模式的调用的处理
      • 11_OPTEE-OS_内核之(三)中断与异常的处理
      • 12_OPTEE-OS_内核之(四)对TA请求的处理
      • 13_OPTEE-OS_内核之(五)内存和cache管理
      • 14_OPTEE-OS_内核之(六)线程管理与并发
      • 15_OPTEE-OS_内核之(七)系统调用及IPC机制
      • 16_OPTEE-OS_应用之(一)TA镜像的签名和加载
      • 17_OPTEE-OS_应用之(二)密码学算法和安全存储
      • 18_OPTEE-OS_应用之(三)可信应用的开发
      • 19_OPTEE-OS_应用之(四)安全驱动开发
      • 20_OPTEE-OS_应用之(五)终端密钥在线下发系统
    • Binary
      • 01_ELF文件_目标文件格式
      • 02_ELF文件结构_浅析内部文件结构
      • 03_ELF文件_静态链接
      • 04_ELF文件_加载进程虚拟地址空间
      • 05_ELF文件_动态链接
      • 06_Linux的动态共享库
      • 07_ELF文件_堆和栈调用惯例以ARMv8为例
      • 08_ELF文件_运行库(入口、库、多线程)
      • 09_ELF文件_基于ARMv7的Linux系统调用原理
      • 10_ELF文件_ARM的镜像文件(.bin/.hex/.s19)
    • Build
      • 01_Script_makefile_summary
    • Rust
      • 02_SYS_RUST_文件IO
    • Security
      • Crypto
        • 1.0_Security_计算机安全概述及安全需求
        • 2.0_Security_随机数(伪随机数)
        • 3.0_Security_对称密钥算法加解密
        • 3.1_Security_对称密钥算法之AES
        • 3.2_Security_对称密钥算法之MAC(CMAC/HMAC)
        • 3.3_Security_对称密钥算法之AEAD
        • 8.0_Security_pkcs7(CMS)_embedded
        • 9.0_Security_pkcs11(HSM)_embedded
      • Tools
        • Openssl EVP to implement RSA and SM2 en/dec sign/verify
        • 基于Mac Silicon M1 的OpenSSL 编译
        • How to compile mbedtls library on Linux/Mac/Windows
    • Embedded
      • eMMC启动介质
  • 😃Design
    • Secure Boot
      • JY Secure Boot Desgin
    • FOTA
      • [FOTA] Module of ECUs' FOTA unit design
        • [FOTA] Tech key point: OSTree Deployment
        • [FOTA] Tech key point: repositories role for onboard
        • [FOTA] Tech key point: metadata management
        • [FOTA] Tech key point: ECU verifying and Decrpting
        • [FOTA] Tech key point: time server
      • [FOTA] Local-OTA for Embedded Linux System
    • Provisioning
      • [X-Shield] Module of the Embedded Boards initialization
    • Report
由 GitBook 提供支持
在本页
  • 01_Makefile_makefile_summary
  • 1. grammer
  • 1.1 basic
  • 1.2 common options
  • 1.3 using a common include make
  • 1.4 using the linux shell within makefile
  • 1.5 using the nesting function of makefile
  • 1.6 using condition define
  • 1.7 using the foreach
  • 1.8 using the function
  • 2. make val
  • 2.1 using user env
  • 2.2 using sys env
  • 2.3 using build env
  • 2.4 phony object
  • 2.5 mode matching
  • 3. Using libraries
  • 3.1 Using the dynamic library
  • 3.2 Using the static library
  • 4. Make Note
  • 4.1 ignore an error
  • 4. Ref
  1. TECH
  2. Build

01_Script_makefile_summary

https://github.com/carloscn/blog/issues/167

01_Makefile_makefile_summary

A project has innumerable source files that are organized along various paths based on type, function, and module. The rules in the makefile state which files should be rebuilt, which files should be built later, and which files should be constructed first. The makefile prefers a shell with sophisticated functions.

1. grammer

1.1 basic

object:dependence
	<TAB> command line
  • The object is the target to be compiled or an action.

  • The dependence is a pre-item performing the object depended.

    • One object allows having multiple dependencies.

  • The command is the specific command under the performing object.

    • Each command occupies one line.

  • By default, the first object will be executed when no option is specified.

Examples: https://github.com/carloscn/clab/blob/master/macos/test_makefile/single/Makefile.hello

a:
	@echo "a"

b:
	@echo "b"

hello:
	@echo "hello world!"

clean:
	@rm -rf *.out

1.2 common options

make [-f file] [options] [target]

By default, make command search GUNmakefile makefiles Makefile in current directory using as the make input file, except for that use option-f to specify a make file by filename.

  • -f: specify a make file by file path

  • -v: show the version number

  • -n: perform the makefile, output commands record only, don't perform.

  • -s: perform the makefile, don't show commands record.

  • -w: show paths before and after execution.

  • -C: show paths where the makefile is located.

1.3 using a common include make

We can use a makefile as a public makefile liking as the function #include in C language.

TARGET = z
OBJ = a.o

include ../makefile.common

Note, the = and :=:

  • = : the final value assignment, whatever the calling before the assigning value or behind the assigning value.

  • :=

There is a example for describing the difference between = and :=:

#### example 1:

a = 123
b = $(a)

a:
	echo $(a) $(b) $(c)

a = 456
c = 789


#### example 2:
x = 789
y = $(x)
y = $(y)

b:
	echo $(x) $(y)

The make aoutput is 456 456 789, and the make b output is an error, becasue the object b cannot ensure the y value that referenced itself.

Now, we replaced the = to :=:

#### example 1:

a = 123
b := $(a)

a:
	echo $(a) $(b) $(c)

a = 456
c = 789


#### example 2:
x = 789
y = $(x)
y := $(y)

b:
	echo $(x) $(y)

The make a output is 456 123 789, and the make b is no longer an error, rather then 789 789.

1.4 using the linux shell within makefile

https://github.com/carloscn/clab/blob/master/macos/test_makefile/Makefile.shll


.PHONY: clean

file = test.txt
A := $(shell ls)
B := $(shell pwd)
C := $(shell (if [ ! -f $(file) ];then touch $(file); fi;))

show:
	echo $(A)
	echo $(B)
	echo $(C)

clean:
	$(RM) $(file)

1.5 using the nesting function of makefile

https://github.com/carloscn/clab/blob/master/macos/test_makefile/multi/src/Makefile


.PHONY: clean algo print

algo:
	make -C ./algo

print:
	make -C ./print

clean:
	make -C ./algo clean
	make -C ./print clean
	rm -rf $(OBJ) *.elf

1.6 using condition define

https://github.com/carloscn/clab/blob/master/macos/test_makefile/Makefile


A = 123
B = default
C := $(B)

ifeq ($(A), 123)
	B := yes
else
	B := no
endif

ifneq ($(A), 123)
	C := yes
else
	C := no
endif

show:
	echo $(A)
	echo $(B)
	echo $(C)
ifdef A
	@echo "ifdef A : the A defined"
endif

ifndef A
	@echo "ifndef A: THE A not defined"
endif

This is always combined gcc -D with ifdef. Sometimes, we want to use some variables of the makefile in a C source file, different variables different flows, such as using the debug, and setting the version number. Using the gcc -D is equal to defining a macro by #define.

version=0.0.2
release_number=2
 
all: test
 
test: test.c
	$(CC) -o $@ $^ -DDEBUG_PRINT -D VERSION='"$(version)"' -D RELEASE_NUMBER=$(release_number)
 
.PHONY: clean
 
clean:
	rm test

And the test.c is :

#include <stdio.h>
 
int main(int argc, char **argv) {
	if (DEBUG_PRINT) {
		printf("%s (version: " VERSION ", release number: %d)\n", 
				argv[0], RELEASE_NUMBER);
	}
 
	return 0;
}

So, we can utilize the ifdef of makefile and -D of gcc to do something.

1.7 using the foreach

In a makefile, the foreach can provide the loop function for us. We can make use of the foreach to create a directory or something.

https://github.com/carloscn/clab/blob/master/macos/test_makefile/Makefile

TARGET=a b c d

loop:
	mkdir $(foreach v, $(TARGET), $v.txt)

clean:
	rm -rf $(foreach v, $(TARGET), $v.txt)

1.8 using the function

https://github.com/carloscn/clab/blob/master/macos/test_makefile/Makefile


define func_1
	return 123
endef

define func_2
	return $(1)
endef

call:
	echo $(call func_1)
	echo $(call func_2, 9999)

2. make val

We need to set up a C build environment shown in the following picture, and you can find the original source code in https://github.com/carloscn/clab/tree/master/macos/test_makefile/single

The main.c file depends on add.c div.c mul.c sub.c, and the main.c is implement simple add or div functions by calling the sub-functions.

We written the makefile as follow:

main :
	gcc add.c div.c sub.c mul.c main.c -o main.elf

clean :
	rm -rf *.o *.elf

It has a very basic makefile and appears quite silly. All the objects would be recompiled when we altered a single file. If the project is particularly large, compiling will take a lot of your time.

So we need to optimize the makefile and make it easier and more convenient.

# make -o to dump the VAL

OBJ = add.o div.o sub.o mul.o main.o
TARGET = main

$(TARGET).elf : $(OBJ)
	gcc $(OBJ) -o $(TARGET).elf

main.o : main.c
	gcc -c main.c -o main.o

add.o : add.c
	gcc -c add.c -o add.o

div.o : div.c
	gcc -c div.c -o div.o

sub.o : sub.c
	gcc -c sub.c -o sub.o

mul.o : mul.c
	gcc -c mul.c -o mul.o

clean :
	@rm -rf *.o *.elf
	@echo "make clean finish"

When one of these files changed, the optimized makefile would re-compile the changed .c file.

2.1 using user env

Based on the simple makefile, we replaced *.o files with OBJ by user environment. The difference between the simple makefile and the new makefile is shown in the following figure:

2.2 using sys env

  • $*: the object name that does not include the extension name.

  • $+: all the dependence files, seperated by space.

  • $<: the first condition in rules.

  • $?: the dependence files that the time later than object.

  • $^: all the dependence files are not repeated.

  • $%: if the object is an archive member, the variable indicates the member name of the object.

Based on the user env makefile, we replaced OBJ and TARGET with $^ and ^@ by the system environment.

# make -p to dump the VAL

OBJ = add.o div.o sub.o mul.o main.o
TARGET = main

$(TARGET).elf : $(OBJ)
	gcc $(OBJ) -o $@

main.o : main.c
	gcc -c $^ -o $@

add.o : add.c
	gcc -c $^ -o $@

div.o : div.c
	gcc -c $^ -o $@

sub.o : sub.c
	gcc -c $^ -o $@

mul.o : mul.c
	gcc -c $^ -o $@

clean :
	@rm -rf $(OBJ) $(TARGET).elf
	@echo "make clean finish"

The difference between these makefiles is shown in the following figure:

2.3 using build env

The build env can be shown by make -p.

  • AS: as

  • CC: gcc

  • CPP: cc

  • CXX: g++ or c++

  • RM: rm -rf

Based on the system env makefile, we replaced gcc to $(CC)by build environment.

2.4 phony object

.PHONY clean hello

The phony object is that whether the file is changed or not, the object declared by phony must be performed.

If there is a hello file on your makefile path, and hello is still an object in your makefile. When the hello is not declared by phony:

If the hello is declared by .PHONY, the object will be performed by making command whether the file with the same name exists in the directory or not.

2.5 mode matching

  • %.*:%.c: .o files depend on .c files corresponding.

  • wildcard: $(wildcard ./*.c) obtain the all .c file in the current directory.

  • patsubst:$(patsubst %.c, %.o, $(wildcard *.c)) replace .c to .o corresponding.

.PHONY: clean hello

OBJ = add.o div.o sub.o mul.o main.o
TARGET = main

$(TARGET).elf : $(OBJ)
	$(CC) $(OBJ) -o $@

%.o : %.c
	$(CC) -c $^ -o $@

hello :
	@echo "hello test"

clean :
	@$(RM) $(OBJ) $(TARGET).elf
	@echo "make clean finish"

using the wildcard

.PHONY: clean hello

OBJ = $(patsubst %.c, %.o, $(wildcard *.c))
TARGET = main

$(TARGET).elf : $(OBJ)
	$(CC) $(OBJ) -o $@

%.o : %.c
	$(CC) -c $^ -o $@

hello :
	@echo "hello test"

show:
	@echo $(wildcard *.c)
	@echo $(patsubst %.c, %.o, $(wildcard *.c))

clean :
	@$(RM) $(OBJ) $(TARGET).elf
	@echo "make clean finish"

3. Using libraries

3.1 Using the dynamic library

When we generate a dynamic library on Linux:

  • -fPIC: this is the position-independent code

  • -shared: this is specifying the type of dynamic library.

When we use a dynamic library on Linux:

  • -l: this is specifying the dynamic library name

  • -L: this is specifying the path of the dynamic library.

  • -I: this is specifying the path of included files.

Now, we create files shown in the following figure:

cacu.c:

#include "cacu.h"
// gcc -fPIC -shared -o libcacu.so cacu.c

int cacu(int a, int b) {
    return a * b + a + b;
}

cacu.h:

int cacu(int a, int b);

Makefile:

.PHONY: clean

SOURCE = $(wildcard *.c)
TARGET = libcacu.so
LD = -fPIC -shared

$(TARGET):
	$(CC) $(LD) -o $@ $(SOURCE)

clean:
	rm -rf *.so

3.2 Using the static library

As we compile a static library:

  • gcc -c hello.c -o hello.o

  • ar -r libhello.a hello.o

As we use a static library:

  • gcc -lhello -L./ main.c -o main.elf

Example:

Touch a mod.c

#include "mod.h"

int mod(int a, int b) {
    return a % b;
}

Touch a mod.h

int mod(int a, int b);

The makefile is:

.PHONY: clean

SOURCE = $(wildcard *.c)
TARGET = libmod.a
OBJ = mod.o

$(TARGET): $(OBJ)
	$(AR) -r $@ -o $^

mod.o:
	$(CC) -c -o $@ $(SOURCE)

clean:
	rm -rf $(OBJ) $(TARGET)

4. Make Note

There are some notes of the make tool.

4.1 ignore an error

Prevent the make command from stopping when the script runs into an error. If the make command captured the non-zero return value, the make script would halt and return this error. However, some errors in the process returned are meaningless. We can enable the function of make ignoring errors in your makefile script.

  • make -i: ignore all errors during the making.

  • phony object can be set to .IGNORE

  • put the - before one command line.

4. Ref

上一页Build下一页Rust

最后更新于1年前

We need to review that how to comiple and use dynamic library using the gcc. Please refer to section 1 of .

We can make a static library compiling within a makefile. Compared with a dynamic library, the static library needs not original library files during the application running, in other words, the static library has been inserted into the object file, which leads to the application being bigger than the one compiled by the dynamic library. For a static library generation, we can refer to section 3 of . The common commands summary is as follows:

😾
05_ELF文件_动态链接
# 03_ELF文件_静态链接
makefile从入门到项目编译实战