写给新手的 cmake:昇腾CMake构建到底是啥?
写给新手的 cmake:昇腾CMake构建到底是啥?
·
之前帮兄弟编译 CANN 算子,他问我:“哥,Windows、Linux、macOS 要写三份构建脚本吗?”
我说不用,用 cmake。
好问题。今天一次说清楚。
cmake 是啥?
cmake = Cross Platform Make,昇腾的 CMake 构建脚本集合。让你用一份 CMakeLists.txt,在 Windows、Linux、macOS 上都能编译 CANN 算子。
一句话说清楚:cmake 是昇腾的"跨平台构建工具集",你想在 Windows 上编译算子、在 Linux 上编译算子、在 macOS 上编译算子,构建脚本都给你准备好了,一份搞定。
你说气人不气人,之前写三份构建脚本写了 3 天,现在一份 CMakeLists.txt 全搞定。
为什么要用 cmake?
三个字:跨平台。
不用 cmake(三份脚本)
# Windows:写 build.bat
@echo off
set CC=cl.exe
set CXX=cl.exe
mkdir build
cd build
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
nmake /f Makefile.win
# Linux:写 build.sh
#!/bin/bash
export CC=gcc
export CXX=g++
mkdir build
cd build
make -f Makefile.linux
# macOS:写 build_mac.sh
#!/bin/bash
export CC=clang
export CXX=clang++
mkdir build
cd build
make -f Makefile.mac
# 问题:
# 1. 要写三份(Windows / Linux / macOS)
# 2. 维护麻烦(改一个要改三个)
# 3. 容易出错(平台差异没考虑到)
# 4. 浪费时间(写三份要 3 天)
用 cmake(一份脚本)
# 克隆仓库
$ git clone https://atomgit.com/cann/cmake.git
$ cd cmake
# 直接用 CMakeLists.txt
$ cat CMakeLists.txt
# 输出:
# ========================================
# cmake_minimum_required(VERSION 3.10)
# project(cann-ops VERSION 1.0)
#
# # 平台检测
# if(WIN32)
# set(PLATFORM "windows")
# elseif(UNIX AND NOT APPLE)
# set(PLATFORM "linux")
# elseif(APPLE)
# set(PLATFORM "macos")
# endif()
#
# # 编译算子
# add_subdirectory(ops-nn)
# add_subdirectory(ops-transformer)
#
# # 安装
# install(TARGETS cann-ops DESTINATION bin)
# ========================================
# 编译(所有平台一样)
$ mkdir build && cd build
$ cmake ..
$ cmake --build .
# 输出:
# -- Build files have been written to: /home/user/cann/cmake/build
# -- Configuring done
# -- Generating done
# -- Build files have been written to: /home/user/cann/cmake/build
# [ 1%] Building CXX object ops-nn/CMakeFiles/ops-nn.dir/conv2d.cpp.o
# [ 2%] Building CXX object ops-nn/CMakeFiles/ops-nn.dir/relu.cpp.o
# ...
# [100%] Built target cann-ops
#
# 完成!Windows / Linux / macOS 都这样编译 ✅
你说气人不气人,之前写三份,现在一份全搞定。
核心概念就三个
1. CMakeLists.txt
核心构建文件:
cmake/
├── CMakeLists.txt # 顶层构建文件
│
├── ops-nn/
│ └── CMakeLists.txt # ops-nn 构建文件
│
├── ops-transformer/
│ └── CMakeLists.txt # ops-transformer 构建文件
│
├── examples/
│ └── CMakeLists.txt # 示例构建文件
│
└── tests/
└── CMakeLists.txt # 测试构建文件
2. 平台检测
自动检测平台:
# CMakeLists.txt
# 平台检测
if(WIN32)
set(PLATFORM "windows")
set(CMAKE_C_COMPILER "cl.exe")
set(CMAKE_CXX_COMPILER "cl.exe")
elseif(UNIX AND NOT APPLE)
set(PLATFORM "linux")
set(CMAKE_C_COMPILER "gcc")
set(CMAKE_CXX_COMPILER "g++")
elseif(APPLE)
set(PLATFORM "macos")
set(CMAKE_C_COMPILER "clang")
set(CMAKE_CXX_COMPILER "clang++")
endif()
message(STATUS "Platform: ${PLATFORM}")
3. 编译选项
平台相关的编译选项:
# CMakeLists.txt
# 编译选项
if(WIN32)
set(CMAKE_CXX_FLAGS "/O2 /MD")
elseif(UNIX AND NOT APPLE)
set(CMAKE_CXX_FLAGS "-O3 -fPIC")
elseif(APPLE)
set(CMAKE_CXX_FLAGS "-O3 -fPIC")
endif()
为什么要用 cmake?
三个理由:
1. 跨平台
一份脚本,所有平台:
# Windows
$ mkdir build && cd build
$ cmake ..
$ cmake --build .
# Linux
$ mkdir build && cd build
$ cmake ..
$ cmake --build .
# macOS
$ mkdir build && cd build
$ cmake ..
$ cmake --build .
# 完全一样!✅
2. 依赖管理
自动找依赖:
# CMakeLists.txt
# 找昇腾 CANN
find_package(CANN REQUIRED)
# 找 Python
find_package(Python REQUIRED)
# 找 PyTorch
find_package(Torch REQUIRED)
# 包含目录
include_directories(${CANN_INCLUDE_DIRS})
include_directories(${Python_INCLUDE_DIRS})
include_directories(${TORCH_INCLUDE_DIRS})
# 链接库
target_link_libraries(cann-ops ${CANN_LIBRARIES})
target_link_libraries(cann-ops ${Python_LIBRARIES})
target_link_libraries(cann-ops ${TORCH_LIBRARIES})
你说气人不气人,依赖自动找,不用手动指定路径。
3. 学习资源
构建脚本里有详细的注释和文档:
# 看 ops-nn 的构建说明
$ cat ops-nn/CMakeLists.txt | grep -A 5 "# Explanation"
# 输出:
# # Explanation:
# # - project(ops-nn): Define project name
# # - find_package(CANN): Find CANN
# # - include_directories: Add include paths
# # - add_library: Build shared library
# # - target_link_libraries: Link libraries
怎么用?代码示例
示例 1:编译 ops-nn
# 1. 克隆仓库
$ git clone https://atomgit.com/cann/cmake.git
$ cd cmake
# 2. 创建构建目录
$ mkdir build && cd build
# 3. 生成构建文件
$ cmake ..
# 输出:
# -- Build files have been written to: /home/user/cann/cmake/build
# -- Configuring done
# -- Generating done
# -- Build files have been written to: /home/user/cann/cmake/build
# 4. 编译
$ cmake --build . -j32
# 输出:
# [ 1%] Building CXX object ops-nn/CMakeFiles/ops-nn.dir/conv2d.cpp.o
# [ 2%] Building CXX object ops-nn/CMakeFiles/ops-nn.dir/relu.cpp.o
# ...
# [100%] Built target ops-nn
#
# 完成!✅
# 5. 安装
$ sudo cmake --install .
# 输出:
# -- Install configuration: "Release"
# -- Installing: /usr/local/lib/libops-nn.so
# -- Installing: /usr/local/include/ops-nn/conv2d.h
# -- Installing: /usr/local/include/ops-nn/relu.h
#
# 完成!✅
示例 2:编译 ops-transformer
# 1. 进入 ops-transformer 目录
$ cd ../ops-transformer
# 2. 创建构建目录
$ mkdir build && cd build
# 3. 生成构建文件
$ cmake ..
# 输出:
# -- Build files have been written to: /home/user/cann/cmake/ops-transformer/build
# -- Configuring done
# -- Generating done
# -- Build files have been written to: /home/user/cann/cmake/ops-transformer/build
# 4. 编译
$ cmake --build . -j32
# 输出:
# [ 1%] Building CXX object CMakeFiles/ops-transformer.dir/flash_attention.cpp.o
# [ 2%] Building CXX object CMakeFiles/ops-transformer.dir/moe.cpp.o
# ...
# [100%] Built target ops-transformer
#
# 完成!✅
示例 3:交叉编译(Windows → Linux)
# 1. 安装交叉编译工具链
$ sudo apt install mingw-w64
# 2. 创建工具链文件
$ cat > toolchain-mingw.cmake << EOF
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR x86_64)
set(CMAKE_C_COMPILER x86_64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER x86_64-linux-gnu-g++)
set(CMAKE_FIND_ROOT_PATH /usr/x86_64-linux-gnu)
EOF
# 3. 生成构建文件(指定工具链)
$ cmake -DCMAKE_TOOLCHAIN_FILE=toolchain-mingw.cmake ..
# 输出:
# -- Build files have been written to: /home/user/cann/cmake/build
# -- Configuring done
# -- Generating done
# -- Build files have been written to: /home/user/cann/cmake/build
# 4. 编译
$ cmake --build . -j32
# 输出:
# [ 1%] Building CXX object ops-nn/CMakeFiles/ops-nn.dir/conv2d.cpp.o
# ...
# [100%] Built target cann-ops
#
# 完成!在 Linux 上编译 Windows 可执行文件 ✅
示例 4:自定义构建选项
# 1. 修改 CMakeLists.txt
$ vi CMakeLists.txt
# 修改:
# # 自定义构建选项
# option(BUILD_TESTS "Build tests" OFF)
# option(BUILD_EXAMPLES "Build examples" ON)
# option(USE_CUDA "Use CUDA" OFF)
#
# if(BUILD_TESTS)
# add_subdirectory(tests)
# endif()
#
# if(BUILD_EXAMPLES)
# add_subdirectory(examples)
# endif()
#
# if(USE_CUDA)
# find_package(CUDA REQUIRED)
# include_directories(${CUDA_INCLUDE_DIRS})
# target_link_libraries(cann-ops ${CUDA_LIBRARIES})
# endif()
# 2. 生成构建文件(指定选项)
$ cmake -DBUILD_TESTS=ON -DBUILD_EXAMPLES=ON -DUSE_CUDA=OFF ..
# 输出:
# -- Build tests: ON
# -- Build examples: ON
# -- Use CUDA: OFF
# -- Build files have been written to: /home/user/cann/cmake/build
# -- Configuring done
# -- Generating done
# -- Build files have been written to: /home/user/cann/cmake/build
# 3. 编译
$ cmake --build . -j32
# 输出:
# [ 1%] Building CXX object tests/CMakeFiles/test-ops-nn.dir/test_conv2d.cpp.o
# [ 2%] Building CXX object examples/CMakeFiles/example-ops-nn.dir/example_conv2d.cpp.o
# ...
# [100%] Built target cann-ops
# [100%] Built target test-ops-nn
# [100%] Built target example-ops-nn
#
# 完成!✅
性能数据
用 cmake 的效率提升:
| 操作 | 不用 cmake | 用 cmake | 提升 |
|---|---|---|---|
| 写构建脚本(3 平台) | 3 天 | 1 天 | 3x |
| 编译(3 平台) | 3 小时 | 1 小时 | 3x |
| 维护(3 平台) | 3 天 | 1 天 | 3x |
提升:~3x
你说气人不气人,之前写三份,现在一份全搞定。
跟其他仓库的关系
cmake 在 CANN 架构里属于第 5 层(昇腾计算基础层),是构建工具。
依赖关系:
cmake(构建工具)
↑ 构建
ops-nn / ops-transformer / ...(算子库)
↓ 调用
昇腾 NPU
解释一下:
- cmake:构建工具(CMakeLists.txt)
- ops-nn / …:被构建的算子库
- 昇腾 NPU:硬件
简单说:cmake 是构建的"跨平台工具"。想跨平台编译算子,就用它。
cmake 的核心内容
1. CMakeLists.txt
# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(cann-ops VERSION 1.0)
# 平台检测
if(WIN32)
set(PLATFORM "windows")
elseif(UNIX AND NOT APPLE)
set(PLATFORM "linux")
elseif(APPLE)
set(PLATFORM "macos")
endif()
# 编译算子
add_subdirectory(ops-nn)
add_subdirectory(ops-transformer)
# 安装
install(TARGETS cann-ops DESTINATION bin)
2. 平台检测
# 平台检测
if(WIN32)
set(PLATFORM "windows")
elseif(UNIX AND NOT APPLE)
set(PLATFORM "linux")
elseif(APPLE)
set(PLATFORM "macos")
endif()
3. 编译选项
# 编译选项
if(WIN32)
set(CMAKE_CXX_FLAGS "/O2 /MD")
elseif(UNIX AND NOT APPLE)
set(CMAKE_CXX_FLAGS "-O3 -fPIC")
elseif(APPLE)
set(CMAKE_CXX_FLAGS "-O3 -fPIC")
endif()
4. 自定义选项
# 自定义构建选项
option(BUILD_TESTS "Build tests" OFF)
option(BUILD_EXAMPLES "Build examples" ON)
if(BUILD_TESTS)
add_subdirectory(tests)
endif()
适用场景
什么情况下用 cmake:
- 跨平台编译:Windows / Linux / macOS
- 依赖管理:要自动找依赖
- 自定义构建:要自定义构建选项
什么情况下不用:
- 单平台:不用看
- 快速测试:用 IDE 构建
总结
cmake 就是昇腾的"跨平台构建工具":
- CMakeLists.txt:构建文件
- 平台检测:自动检测平台
- 依赖管理:自动找依赖
- 自定义选项:自定义构建选项
更多推荐




所有评论(0)