CMake入门,实例与模板

CMake 入门,实例与模板

什么是 CMake

CMake 允许开发者编写一种平台无关的 CMakeList.txt 文件来定制整个编译流程,然后再根据目标用户的平台进一步生成所需的本地化 Makefile 和工程文件,如 Unix 的 Makefile 或 Windows 的 Visual Studio 工程。从而做到“Write once, run everywhere”。

在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下:

  1. 编写 CMake 配置文件 CMakeLists.txt 。
  2. 执行命令 cmake PATH 或者 ccmake PATH 生成 Makefile(ccmake 和 cmake 的区别在于前者提供了一个交互式的界面)。其中, PATH 是 CMakeLists.txt 所在的目录。
1
2
3
4
5
# 一般是创建一个build目录进行编译,CMakeLists.txt在build目录的上一层
mkdir ./build
cd build
cmake ..
make
  1. 使用 make 命令进行编译。

模板1 单一源文件

适用于编译某一目录中的指定源文件(test01.cpp),且没有调用第三方库,最终编译成一个可执行文件的情况。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 1,设置工程名称,叫“Demo1”,在Linux下可以随便设置
project( Demo1 )

# 2,设置 CMake 最低版本号,我电脑装的是3.5
cmake_minimum_required( VERSION 3.5 )

# 3,设定编译参数
set(CMAKE_CXX_STANDARD    11)  # 指定 C++ 版本
set(CMAKE_BUILD_TYPE "Release")  # 调试使用Debug,可以查看中间变量;发布使用Release,运行速度快

# 4,把源码编译成一个可执行文件,文件名为test01(可以随便取名),会保存在当前目录下
add_executable( test01 test01.cpp )
1
2
3
├── template1
│    ├── CMakeLists.txt
│    └── test02.cpp

运行过程

1
2
3
4
5
cd template1
mkdir ./build
cd build
cmake ..
make

会在build目录下 生成 可执行文件 test01

模板2 多个源文件在一个目录

适用于编译同一目录中的多个源文件,且没有调用第三方库,最终编译成一个可执行文件的情况。 源文件 .c .cpp .cc 和 include文件都放在一个目录下,只有一个目录,没有子目录。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 1,设置工程名称,叫“Demo2”(在Linux下可以随便设置)
project( Demo2 )

# 2,设置 CMake 最低版本号,我电脑装的是3.5
cmake_minimum_required( VERSION 3.5 )

# 3,设定编译参数
set(CMAKE_CXX_STANDARD    11)  # 指定 C++ 版本
set(CMAKE_BUILD_TYPE "Release")  # 调试使用Debug,可以查看中间变量;发布使用Release,运行速度快

# 4,把当前文件夹下的源码列表(文件后缀匹配的那些文件)存到变量 SRCS 中
file( GLOB SRCS *.c *.cpp *.cc *.h *.hpp )

# 5,把源码编译成一个可执行文件,文件名为test02(可以随便取名),会保存在当前目录下
add_executable( test02 ${SRCS} )
1
2
3
4
├── template2
│    ├── CMakeLists.txt
│    ├── test02.cpp
│    └── test02.h

可以有更多源文件和include文件,只要放在一个目录下就可以

运行过程

1
2
3
4
5
cd template2
mkdir ./build
cd build
cmake ..
make

会在build目录下 生成 可执行文件 test02

模板3 源文件和include文件在不同的目录

适用于cpp文件在一个文件夹(src/中),头文件在另一个文件夹内(include/中),且没有调用第三方库,最终编译成一个可执行文件的情况。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 1,设置工程名称,叫“Demo3”,在Linux下可以随便设置
project( Demo3 )

# 2,设置 CMake 最低版本号,我电脑装的是3.5
cmake_minimum_required( VERSION 3.5 )

# 3,设定编译参数
set(CMAKE_CXX_STANDARD    11)  # 指定 C++ 版本
set(CMAKE_BUILD_TYPE "Release")  # 调试使用Debug,可以查看中间变量;发布使用Release,运行速度快

# 4,设定源码列表,查找指定目录下的所有源文件,并将名称保存到 DIR_SRCS 变量中
aux_source_directory(./src/ DIR_SRC)

# 5,设定头文件路径
include_directories(./include/)

# 6,把源码编译成一个可执行文件,文件名为test03(可以随便取名),会保存在当前目录下
add_executable( test03 ${DIR_SRC} )

目录结构

1
2
3
4
5
6
7
├── template3
│   ├── CMakeLists.txt
│   ├── include
│   │   └── count.h
│   └── src
│       ├── count.cpp
│       └── test03.cpp

运行过程

1
2
3
4
5
cd template3
mkdir ./build
cd build
cmake ..
make

会在build目录下 生成 可执行文件 test03

模板4 源文件和include文件在不同的目录,调用安装在系统中的第三方库

适用于cpp文件在一个文件夹(src/中),头文件在另一个文件夹内(include/中),且调用了第三方库(比如已经安装在系统中的opencv),最终编译成一个可执行文件的情况。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 1,设置工程名称,叫“Demo4”,在Linux下可以随便设置
project( Demo4 )

# 2,设置 CMake 最低版本号,我电脑装的是3.5
cmake_minimum_required( VERSION 3.5 )

# 3,设定编译参数
set(CMAKE_CXX_STANDARD    11)  # 指定 C++ 版本
set(CMAKE_BUILD_TYPE "Release")  # 调试使用Debug,可以查看中间变量;发布使用Release,运行速度快

# 4,设定源码列表,查找指定目录(都放在./src/中)中的所有源文件,并将名称保存到 DIR_SRCS 变量中
aux_source_directory(./src/ DIR_SRC)

# 5,设定头文件路径(还可以增加其他第三方库的头文件路径)
include_directories(./include/)

# 6,查找并添加OpenCV的头文件目录
find_package(OpenCV REQUIRED)  
# message( STATUS "    version: ${OpenCV_VERSION}" )  # 我电脑上装的是opencv3.3.1
# message( STATUS "    include path: ${OpenCV_INCLUDE_DIRS}" )
include_directories(${OpenCV_INCLUDE_DIRS})

# 7,把源码编译成一个可执行文件,文件名为test04(可以随便取名),会保存在当前目录下
add_executable( test04 ${DIR_SRC} )
target_link_libraries( test04 ${OpenCV_LIBS} )  # 可执行文件名 链接 OpenCV库
1
2
3
4
5
6
├── template4
│   ├── CMakeLists.txt
│   ├── include
│   │   └── test04.h
│   └── src
│       └── test04.cpp

运行过程

1
2
3
4
5
6
7
## 要先安装 opencv ubuntu下
sudo apt install libopencv-dev
cd template4
mkdir ./build
cd build
cmake ..
make

会在build目录下 生成 可执行文件 test04

模板5 分成多个子模块,每个子模块有自己的CMakeLists.txt, 生成执行文件,静态库,动态库

使用cmake构建一个工程,每个子模块都有自己的cmakelists,该工程创建了两个静态库和一个动态库,另外生成一个调用这些库的可执行文件。 CMakeLists.txt

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
cmake_minimum_required(VERSION 3.5)  # cmake版本最低要求
project(test5)  # 设置工程名称

set(CMAKE_CXX_STANDARD 11)  # 指定 C++ 版本
set(CMAKE_BUILD_TYPE Release)  # 调试使用Debug,可以查看中间变量;发布使用Release,运行速度快

message("${PROJECT_SOURCE_DIR}=" ${PROJECT_SOURCE_DIR})

# 这里设置好路径后,进入子模块的cmake时不用再次设置
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)  # 设置可执行文件的输出目录
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)	   # 设置库文件的输出目录

ADD_SUBDIRECTORY(${PROJECT_SOURCE_DIR}/source/add)     # 会调用该目录中的CMakeLists.txt进行编译生成静态库
ADD_SUBDIRECTORY(${PROJECT_SOURCE_DIR}/source/sub)     # 会调用该目录中的CMakeLists.txt进行编译生成静态库
ADD_SUBDIRECTORY(${PROJECT_SOURCE_DIR}/source/mul)     # 会调用该目录中的CMakeLists.txt进行编译生成动态库
ADD_SUBDIRECTORY(${PROJECT_SOURCE_DIR}/source/main)    # 会调用该目录中的CMakeLists.txt进行编译生成可执行文件

add/CMakeLists.txt

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 编译成静态库, libadd.a
# 方法一:逐个添加cpp源文件,适用于文件数量少的情况
# add_library(add ${CMAKE_CURRENT_SOURCE_DIR}/add.cpp ${CMAKE_CURRENT_SOURCE_DIR}/add3.cpp)

# 方法二:搜索有的cpp源文件,并将列表存储在一个变量中,适用于文件多的情况
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SRC_LIST)
add_library(add ${SRC_LIST})

# 方法三:递归遍历目录,获取所有的CPP文件,适用于多级目录的情况
# file(GLOB_RECURSE cpp_files  ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)  # GLOB是不递归
# add_library(add ${cpp_files})

mul/CMakeLists.txt

1
2
# 编译成动态库libmul.so
add_library(mul SHARED ${CMAKE_CURRENT_SOURCE_DIR}/mul.cpp)

sub/CMakeLists.txt

1
2
# 编译成静态库, libsub.a
add_library(sub ${CMAKE_CURRENT_SOURCE_DIR}/sub.cpp)

main/CMakeLists.txt

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 添加头文件路径,会检索目录中的所有头文件
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../add
                    ${CMAKE_CURRENT_SOURCE_DIR}/../sub
                    ${CMAKE_CURRENT_SOURCE_DIR}/../mul
                    ${CMAKE_CURRENT_SOURCE_DIR}/../main)

# 把源码编译成一个可执行文件
add_executable(main ./main.cpp)
# 添加链接库,动态和静态都行
target_link_libraries(main add sub mul)

目录结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
├── template5
│   ├── CMakeLists.txt
│   ├── readme.md
│   ├── run.sh
│   └── source
│       ├── add
│       │   ├── add3.cpp
│       │   ├── add3.h
│       │   ├── add.cpp
│       │   ├── add.h
│       │   └── CMakeLists.txt
│       ├── main
│       │   ├── CMakeLists.txt
│       │   └── main.cpp
│       ├── mul
│       │   ├── CMakeLists.txt
│       │   ├── mul.cpp
│       │   └── mul.h
│       └── sub
│           ├── CMakeLists.txt
│           ├── sub.cpp
│           └── sub.h

运行过程

1
2
3
4
5
6
7
8
cd template5
rm -rf build
mkdir build
cd build/
cmake ..
make  
cd ../bin
./main

模板6 分成多个子模块,只有1个CMakeLists.txt, 生成执行文件,静态库,动态库

使用cmake构建一个工程,包含多个子模块,但子模块没有自己的cmakelists,整个项目只有一个CMakeLists.txt, 该工程创建了两个静态库和一个动态库,另外生成一个调用这些库的可执行文件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
cmake_minimum_required(VERSION 3.5)  # cmake版本最低要求
project(test6)  # 设置工程名称

set(CMAKE_CXX_STANDARD 11)  # 指定 C++ 版本
set(CMAKE_BUILD_TYPE Release)  # 调试使用Debug,可以查看中间变量;发布使用Release,运行速度快

message("${PROJECT_SOURCE_DIR}=" ${PROJECT_SOURCE_DIR})

# 这里设置好路径后,进入子模块的cmake时不用再次设置
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)  # 设置可执行文件的输出目录
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)	   # 设置库文件的输出目录

# 编译add,生成静态库
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/source/add ADD_SRC_LIST)
add_library(add ${ADD_SRC_LIST})

# 编译sub,生成静态库
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/source/sub SUB_SRC_LIST)
add_library(sub ${SUB_SRC_LIST})

# 编译mul,生成动态库
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/source/mul MUL_SRC_LIST)
add_library(mul SHARED ${MUL_SRC_LIST})

# 添加头文件路径,用于编译可执行文件
include_directories(./source/add
                    ./source/sub
                    ./source/mul)

# 编译main,生成可执行文件
add_executable(main ${CMAKE_CURRENT_SOURCE_DIR}/source/main/main.cpp)
target_link_libraries(main add sub mul)  # 链接所有库

目录结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
├── template6
│   ├── CMakeLists.txt
│   ├── readme.md
│   ├── run.sh
│   └── source
│       ├── add
│       │   ├── add3.cpp
│       │   ├── add3.h
│       │   ├── add.cpp
│       │   └── add.h
│       ├── main
│       │   └── main.cpp
│       ├── mul
│       │   ├── mul.cpp
│       │   └── mul.h
│       └── sub
│           ├── sub.cpp
│           └── sub.h

运行过程

1
2
3
4
5
6
7
8
cd template6
rm -rf build
mkdir build
cd build/
cmake ..
make 
cd ../bin
./main

常用命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Note:cmake中不区分大小写。

# 设置变量,方便后面自动配置,进入子模块的cmake时不用再次设置
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)  # 设置可执行文件的输出目录
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)	   # 设置库文件的输出目录

# 设定源码列表,查找指定目录下的所有源文件,并将名称保存到 DIR_SRCS 变量中
aux_source_directory(./src/ DIR_SRC)

# 设定头文件查找路径,可以将所有头文件路径都添加到这里面
include_directories(./include/
                    ./source/sub)

# 查找并添加OpenCV的头文件目录,在target_link_libraries()中需要进行动态链接
find_package(OpenCV REQUIRED) 

# 编译子模块,会自动调用子模块中的Cmakelists.txt进行编译
add_subdirectory(sub)

# 将${ADD_SRC_LIST}中的所有源码编译生成静态库add
add_library(add ${ADD_SRC_LIST})

# 将${SRCS}中的所有源码编译成一个可执行文件,文件名为main
add_executable( main ${SRCS} )
# 编译可执行文件之后,添加动态链接库,会链接静态库subadd和opencv库
target_link_libraries(main subadd ${OpenCV_LIBS})

# 打印一些日志信息
message("PROJECT_SOURCE_DIR=" ${PROJECT_SOURCE_DIR})

常用变量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Note:cmake中不区分大小写。

# 工程顶层目录
${CMAKE_SOURCE_DIR} ${PROJECT_SOURCE_DIR}

# 当前处理的 CMakeLists.txt 所在路径
${CMAKE_CURRENT_SOURCE_DIR}

# 返回Cmakelists.txt开头通过 PROJECT 指令定义的项目名称
${PROJECT_NAME}

# 分别用来重新定义最终结果(可执行文件、动静态库文件)的存放目录
${EXECUTABLE_OUTPUT_PATH} ${LIBRARY_OUTPUT_PATH}

附加1 交叉编译 CH32V203

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
cmake_minimum_required(VERSION 3.20)

# 工具链设置
set(TOOLPATH  D:/0wch/toolchain/RISCVEmbeddedGCC/bin/riscv-none-embed-)

if (WIN32)
	MESSAGE(STATUS "Now is windows!")
    set(CMAKE_C_COMPILER ${TOOLPATH}gcc.exe)
    set(CMAKE_CXX_COMPILER ${TOOLPATH}g++.exe)
    set(CMAKE_ASM_COMPILER ${TOOLPATH}gcc.exe)
    set(CMAKE_AR ${TOOLPATH}ar.exe)
    set(CMAKE_OBJCOPY ${TOOLPATH}objcopy.exe)
    set(CMAKE_OBJDUMP ${TOOLPATH}objdump.exe)
    set(SIZE ${TOOLPATH}size.exe)
elseif (UNIX)
	MESSAGE(STATUS "Now is UNIX-like OS!")
    set(CMAKE_C_COMPILER ${TOOLPATH}gcc)
    set(CMAKE_CXX_COMPILER ${TOOLPATH}g++)
    set(CMAKE_ASM_COMPILER ${TOOLPATH}gcc)
    set(CMAKE_AR ${TOOLPATH}ar)
    set(CMAKE_OBJCOPY ${TOOLPATH}objcopy)
    set(CMAKE_OBJDUMP ${TOOLPATH}objdump)
    set(SIZE ${TOOLPATH}size)
else ()
    MESSAGE(STATUS "Unsupported system!")
endif ()

# 项目设置
project(ch32v203-ninja C CXX ASM)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_STANDARD 99)

# 编译参数 一般不用改
add_compile_options(-march=rv32imac -mabi=ilp32 -mcmodel=medany -msmall-data-limit=8 -mno-save-restore)
add_compile_options(-fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-common)

# 编译等级
add_compile_options(-O2)

# 编译信息等级
add_compile_options(-Wall)

# 头文件路径
include_directories(APP
                    Core
                    Debug 
                    Peripheral/inc)

# 宏定义
# add_definitions(-DDEBUG=1)

# 源码文件
file(GLOB_RECURSE SOURCES 
                "APP/*.c"
                "Core/core_riscv.c" 
                "Debug/debug.c"
                "Peripheral/src/*.c" 
                "Startup/startup_ch32v20x_D6.S"
                )

# 链接参数
set(LINKER_SCRIPT  ${CMAKE_SOURCE_DIR}/Ld/Link.ld)
add_link_options(
                -march=rv32imac -mabi=ilp32
                -nostartfiles 
                -Xlinker --gc-sections  
                -Wl,--print-memory-usage
                -Wl,-Map,${PROJECT_NAME}.map 
                --specs=nano.specs 
                --specs=nosys.specs)
add_link_options(-T ${LINKER_SCRIPT})

# 编译可执行文件
add_executable(${PROJECT_NAME}.elf ${SOURCES} ${LINKER_SCRIPT})

# 链接静态库
# target_link_libraries(${PROJECT_NAME}.elf printfloat)

# 输出hex和bin
set(HEX_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex)
set(BIN_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin)
set(LST_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.lst)
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
        COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}.elf> ${HEX_FILE}
        COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJECT_NAME}.elf> ${BIN_FILE}
        COMMAND ${CMAKE_OBJDUMP} --all-headers --demangle --disassemble $<TARGET_FILE:${PROJECT_NAME}.elf> > ${LST_FILE}
        COMMAND ${SIZE} --format=berkeley $<TARGET_FILE:${PROJECT_NAME}.elf>
)

Link.ld文件

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
ENTRY( _start )

__stack_size = 2048;

PROVIDE( _stack_size = __stack_size );


MEMORY
{  
/* CH32V20x_D6 - CH32V203F6-CH32V203G6-CH32V203K6-CH32V203C6 */
	FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 32K
	RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 10K

/* CH32V20x_D6 - CH32V203K8-CH32V203C8-CH32V203G8-CH32V203F8 */
	/* FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K
	RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K */
 
/* CH32V20x_D8 - CH32V203RB
   CH32V20x_D8W - CH32V208x
   FLASH + RAM supports the following configuration
   FLASH-128K + RAM-64K
   FLASH-144K + RAM-48K
   FLASH-160K + RAM-32K

	FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 160K
	RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
*/
}


SECTIONS
{

	.init :
	{
		_sinit = .;
		. = ALIGN(4);
		KEEP(*(SORT_NONE(.init)))
		. = ALIGN(4);
		_einit = .;
	} >FLASH AT>FLASH

  .vector :
  {
      *(.vector);
	  . = ALIGN(64);
  } >FLASH AT>FLASH

	.text :
	{
		. = ALIGN(4);
		*(.text)
		*(.text.*)
		*(.rodata)
		*(.rodata*)
		*(.glue_7)
		*(.glue_7t)
		*(.gnu.linkonce.t.*)
		. = ALIGN(4);
	} >FLASH AT>FLASH 

	.fini :
	{
		KEEP(*(SORT_NONE(.fini)))
		. = ALIGN(4);
	} >FLASH AT>FLASH

	PROVIDE( _etext = . );
	PROVIDE( _eitcm = . );	

	.preinit_array  :
	{
	  PROVIDE_HIDDEN (__preinit_array_start = .);
	  KEEP (*(.preinit_array))
	  PROVIDE_HIDDEN (__preinit_array_end = .);
	} >FLASH AT>FLASH 
	
	.init_array     :
	{
	  PROVIDE_HIDDEN (__init_array_start = .);
	  KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
	  KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
	  PROVIDE_HIDDEN (__init_array_end = .);
	} >FLASH AT>FLASH 
	
	.fini_array     :
	{
	  PROVIDE_HIDDEN (__fini_array_start = .);
	  KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
	  KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
	  PROVIDE_HIDDEN (__fini_array_end = .);
	} >FLASH AT>FLASH 
	
	.ctors          :
	{
	  /* gcc uses crtbegin.o to find the start of
	     the constructors, so we make sure it is
	     first.  Because this is a wildcard, it
	     doesn't matter if the user does not
	     actually link against crtbegin.o; the
	     linker won't look for a file to match a
	     wildcard.  The wildcard also means that it
	     doesn't matter which directory crtbegin.o
	     is in.  */
	  KEEP (*crtbegin.o(.ctors))
	  KEEP (*crtbegin?.o(.ctors))
	  /* We don't want to include the .ctor section from
	     the crtend.o file until after the sorted ctors.
	     The .ctor section from the crtend file contains the
	     end of ctors marker and it must be last */
	  KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
	  KEEP (*(SORT(.ctors.*)))
	  KEEP (*(.ctors))
	} >FLASH AT>FLASH 
	
	.dtors          :
	{
	  KEEP (*crtbegin.o(.dtors))
	  KEEP (*crtbegin?.o(.dtors))
	  KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
	  KEEP (*(SORT(.dtors.*)))
	  KEEP (*(.dtors))
	} >FLASH AT>FLASH 

	.dalign :
	{
		. = ALIGN(4);
		PROVIDE(_data_vma = .);
	} >RAM AT>FLASH	

	.dlalign :
	{
		. = ALIGN(4); 
		PROVIDE(_data_lma = .);
	} >FLASH AT>FLASH

	.data :
	{
    	*(.gnu.linkonce.r.*)
    	*(.data .data.*)
    	*(.gnu.linkonce.d.*)
		. = ALIGN(8);
    	PROVIDE( __global_pointer$ = . + 0x800 );
    	*(.sdata .sdata.*)
		*(.sdata2.*)
    	*(.gnu.linkonce.s.*)
    	. = ALIGN(8);
    	*(.srodata.cst16)
    	*(.srodata.cst8)
    	*(.srodata.cst4)
    	*(.srodata.cst2)
    	*(.srodata .srodata.*)
    	. = ALIGN(4);
		PROVIDE( _edata = .);
	} >RAM AT>FLASH

	.bss :
	{
		. = ALIGN(4);
		PROVIDE( _sbss = .);
  	    *(.sbss*)
        *(.gnu.linkonce.sb.*)
		*(.bss*)
     	*(.gnu.linkonce.b.*)		
		*(COMMON*)
		. = ALIGN(4);
		PROVIDE( _ebss = .);
	} >RAM AT>FLASH

	PROVIDE( _end = _ebss);
	PROVIDE( end = . );

    .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
    {
        PROVIDE( _heap_end = . );   
        . = ALIGN(4);
        PROVIDE(_susrstack = . );
        . = . + __stack_size;
        PROVIDE( _eusrstack = .);
    } >RAM 

}
记录并分享
Built with Hugo
主题 StackJimmy 设计