当前位置: 首页 > news >正文

cmake入门学习

基础知识

带有头文件cmake编译

Makefile

解决问题

自动编译

自动变量

依赖第三方库

Cmake

项目结构准备

首先创建项目目录结构:

bash

helloworld/
├── CMakeLists.txt       # 主 CMake 文件
├── main.c               # 主程序
├── include/             # 头文件目录
│   └── hello.h
└── src/                 # 源代码目录└── hello.c

文件内容:

  1. include/hello.h
#ifndef HELLO_H
#define HELLO_Hvoid print_hello();#endif
  1. src/hello.c
#include <stdio.h>
#include "hello.h"void print_hello() {printf("Hello, World!\n");
}
  1. main.c
#include "hello.h"int main() {print_hello();return 0;
}

阶段 1: 直接编译 - CMakeLists.txt

cmake_minimum_required(VERSION 3.0)   # 最低CMake版本
project(HelloWorld)                  # 项目名称# 包含头文件目录
include_directories(include)# 添加可执行文件(直接编译所有源文件)
add_executable(hellomain.csrc/hello.c
)# 安装规则(可选)
install(TARGETS hello DESTINATION bin)

编译命令:​

mkdir build
cd build
cmake ..     # 生成构建系统
make          # 编译
./hello      # 运行

阶段 2: 静态库链接 - CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(HelloWorldStatic)include_directories(include)# 创建静态库
add_library(hello_lib STATICsrc/hello.c
)# 创建可执行文件
add_executable(hello main.c)# 链接静态库
target_link_libraries(hello hello_lib)# 安装规则(库+可执行文件)
install(TARGETS hello_lib ARCHIVE DESTINATION lib)
install(TARGETS hello DESTINATION bin)
install(FILES include/hello.h DESTINATION include)

编译命令:​

rm -rf build ; mkdir build ; cd build
cmake ..
make
./hello

查看静态库内容:​

ar t libhello_lib.a  # 查看库内文件
nm libhello_lib.a    # 查看符号表

阶段 3: 动态库链接 - CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(HelloWorldShared)include_directories(include)# 创建动态库
add_library(hello_lib SHAREDsrc/hello.c
)# 设置版本号
set_target_properties(hello_lib PROPERTIESVERSION 1.0.0SOVERSION 1
)# 创建可执行文件
add_executable(hello main.c)
target_link_libraries(hello hello_lib)# 安装规则
install(TARGETS hello_libLIBRARY DESTINATION libRUNTIME DESTINATION bin  # Windows平台需要
)
install(TARGETS hello DESTINATION bin)
install(FILES include/hello.h DESTINATION include)

编译命令:​

rm -rf build ; mkdir build ; cd build
cmake ..
make
./hello# 查看动态库依赖
ldd hello | grep hello

Cmake-ARM

一、使用CMake实现(交叉编译)

项目结构
helloworld/
├── CMakeLists.txt       # 主CMake文件
├── main.c               # 主程序
├── include/             # 头文件目录
│   └── hello.h
└── src/                 # 源代码目录└── hello.c
文件内容
  1. include/hello.h
#ifndef HELLO_H
#define HELLO_Hvoid print_hello();#endif
  1. src/hello.c
#include <stdio.h>
#include "hello.h"void print_hello() {printf("Hello, ARM World!\n");
}
  1. main.c
#include "hello.h"int main() {print_hello();return 0;
}
步骤1:直接编译(无库)

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(HelloWorldARM)# 设置交叉编译器
set(CMAKE_C_COMPILER arm-linux-gcc)# 添加可执行文件
add_executable(hellomain.csrc/hello.c
)# 包含头文件目录
target_include_directories(hello PRIVATE include)
步骤2:使用静态库

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(HelloWorldARM)set(CMAKE_C_COMPILER arm-linux-gcc)# 创建静态库
add_library(hello_lib STATICsrc/hello.c
)
target_include_directories(hello_lib PUBLIC include)# 添加可执行文件
add_executable(hello main.c)
target_link_libraries(hello hello_lib)
步骤3:使用动态库

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(HelloWorldARM)set(CMAKE_C_COMPILER arm-linux-gcc)# 创建动态库
add_library(hello_lib SHAREDsrc/hello.c
)
target_include_directories(hello_lib PUBLIC include)# 设置动态库版本
set_target_properties(hello_lib PROPERTIESVERSION 1.0.0SOVERSION 1
)# 添加可执行文件
add_executable(hello main.c)
target_link_libraries(hello hello_lib)

进阶​-多架构编译器

多架构编译支持:单一 CMakeLists 适配多种编译器

要实现单一 CMakeLists 文件支持多种编译器架构,同时保持项目结构和代码不变,需要使用 CMake 的工具链文件条件编译技术。以下是完整的解决方案:

修改后的 CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(HelloWorldMultiArch)# 1. 包含头文件目录
include_directories(include)# 2. 设置默认架构(可通过命令行覆盖)
if(NOT DEFINED TARGET_ARCH)set(TARGET_ARCH "x86_64")  # 默认架构
endif()# 3. 根据架构选择工具链文件
if(TARGET_ARCH STREQUAL "arm")set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/toolchains/arm-linux-gcc.cmake)
elseif(TARGET_ARCH STREQUAL "aarch64")set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/toolchains/aarch64-linux-gcc.cmake)
elseif(TARGET_ARCH STREQUAL "riscv")set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/toolchains/riscv-linux-gcc.cmake)
elseif(TARGET_ARCH STREQUAL "x86_64")# 使用本地编译器,无需工具链文件
endif()# 4. 应用工具链文件(如果指定)
if(CMAKE_TOOLCHAIN_FILE)message(STATUS "Using toolchain: ${CMAKE_TOOLCHAIN_FILE}")include(${CMAKE_TOOLCHAIN_FILE})
endif()# 5. 创建动态库
add_library(hello_lib SHAREDsrc/hello.c
)# 6. 设置版本号
set_target_properties(hello_lib PROPERTIESVERSION 1.0.0SOVERSION 1
)# 7. 创建可执行文件
add_executable(hello main.c)
target_link_libraries(hello hello_lib)# 8. 安装规则(通用)
include(GNUInstallDirs)  # 包含标准安装路径定义install(TARGETS hello_libLIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}  # Windows平台需要
)install(TARGETS hello DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES include/hello.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

工具链文件目录结构

创建 toolchains/ 目录存放各种架构的工具链文件:

project/
├── CMakeLists.txt
├── toolchains/
│   ├── arm-linux-gcc.cmake
│   ├── aarch64-linux-gcc.cmake
│   └── riscv-linux-gcc.cmake
├── main.c
├── include/
│   └── hello.h
└── src/└── hello.c

工具链文件示例

1. ARM 架构工具链 (toolchains/arm-linux-gcc.cmake)

# ARM 工具链设置
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)# 编译器路径
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)# Sysroot 路径(可选)
set(CMAKE_SYSROOT /opt/arm-sysroot)# 查找规则
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)# CPU 特性优化
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mfpu=neon")

2. AArch64 架构工具链 (toolchains/aarch64-linux-gcc.cmake)

# AArch64 工具链设置
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)# 编译器路径
set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)# CPU 特性优化
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcpu=cortex-a72")

3. RISC-V 架构工具链 (toolchains/riscv-linux-gcc.cmake)

# RISC-V 工具链设置
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR riscv)# 编译器路径
set(CMAKE_C_COMPILER riscv64-unknown-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER riscv64-unknown-linux-gnu-g++)# CPU 特性优化
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=rv64gc -mabi=lp64d")

使用说明

1. 编译不同架构

# ARM 架构
mkdir build-arm && cd build-arm
cmake .. -DTARGET_ARCH=arm
make# AArch64 架构
mkdir build-aarch64 && cd build-aarch64
cmake .. -DTARGET_ARCH=aarch64
make# RISC-V 架构
mkdir build-riscv && cd build-riscv
cmake .. -DTARGET_ARCH=riscv
make# x86_64 架构(默认)
mkdir build-x86 && cd build-x86
cmake ..  # 或显式指定 -DTARGET_ARCH=x86_64
make

2. 验证输出文件架构

# 检查生成的可执行文件架构
file hello# ARM 输出示例: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV)
# AArch64 输出示例: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV)
# RISC-V 输出示例: ELF 64-bit LSB executable, UCB RISC-V, version 1 (SYSV)
# x86_64 输出示例: ELF 64-bit LSB executable, x86-64, version 1 (SYSV)

3. 安装到不同架构的系统

# ARM 系统安装
cd build-arm
make install DESTDIR=/mnt/arm-rootfs# RISC-V 系统安装
cd build-riscv
make install DESTDIR=/mnt/riscv-rootfs

高级技巧:自动检测架构

如果需要在 CMake 中自动检测当前架构,可以添加以下代码:

# 自动检测主机架构
execute_process(COMMAND uname -m OUTPUT_VARIABLE HOST_ARCH)
string(STRIP ${HOST_ARCH} HOST_ARCH)# 设置默认架构为当前主机架构
if(NOT DEFINED TARGET_ARCH)set(TARGET_ARCH ${HOST_ARCH})
endif()# 显示当前架构信息
message(STATUS "Building for target architecture: ${TARGET_ARCH}")
message(STATUS "Host architecture: ${HOST_ARCH}")
http://www.dtcms.com/a/301585.html

相关文章:

  • HCIE学习之路:路由引入
  • 嵌入式硬件篇---ESP32拓展板
  • C语言中 %zu 的用法
  • Javascript中的instanceof
  • VMware Workstation Pro虚拟机的下载和安装图文保姆级教程(附下载链接)
  • 点云的协方差矩阵的三个特征值代表什么?
  • 5.7 多处理器的基本概念 (答案见原书 P278)
  • 6、企业信息化
  • 大模型应用主要组成
  • 一、openEuler 安装git 详细操作步骤
  • 俄罗斯方块游戏开发(面向对象编程)
  • CPA青少年编程能力等级测评试卷及答案 Python编程(三级)
  • Go的defer和recover
  • Windows 11 安装 jdk 8
  • Cgroup 控制组学习(三)在容器中使用 CGroups
  • goland编写go语言导入自定义包出现: package xxx is not in GOROOT (/xxx/xxx) 的解决方案
  • 微服务架构面试题
  • PiscCode使用OpenCV实现漂浮方块特效
  • 编程语言Java——核心技术篇(五)IO流:数据洪流中的航道设计
  • 仓库管理系统-2-后端之基于继承基类的方式实现增删改查
  • 【RL第三篇】REINFORCE Leave-One-Out(RLOO)算法(基于留一法的REINFORCE策略梯度算法)
  • RK3568基于mpp实现硬解码(一):mpp库的编译使用
  • [每周一更]-(第151期):Go语言中的Map、Slice、Array和Hash原理详解
  • 博士招生 | 香港大学 招收人工智能和网络安全方向 博士生
  • 7.27 状态机dp|质数线性筛|序列化树
  • Linux网络-------2.应⽤层⾃定义协议与序列化
  • SpringBoot实现Serverless:手撸一个本地函数计算引擎
  • mcu trace工具调研
  • elasticsearch 倒排索引原理详解
  • SpringBoot3整合Redis