CMake与GN构建系统对比及GN使用指南

目录


一、引言

在软件开发中,构建系统是项目开发的核心工具之一。传统的构建工具如Make、Autotools等在大型项目中逐渐暴露出配置复杂、构建速度慢等问题。CMake作为跨平台的构建系统生成器,因其灵活性和广泛支持而广受欢迎。然而,Google开发的GN(Generate Ninja)构建系统,以其简洁的语法和高效的性能,在Chromium、OpenHarmony等大型项目中得到了广泛应用。

本文将详细对比CMake和GN两种构建系统,并深入讲解GN的使用方法,帮助开发者快速掌握GN构建系统。


二、CMake与GN构建系统对比

2.1 架构设计对比

特性 CMake GN
设计理念 跨平台构建系统生成器 专为Ninja设计的元构建系统
生成目标 Makefile、Ninja、Visual Studio等 仅生成Ninja构建文件
语法风格 类似于脚本语言,功能强大但较复杂 简洁的声明式语法,类似Python
执行方式 CMake → 生成构建文件 → 执行 GN → 生成.ninja → Ninja执行
性能 在大型项目中解析较慢 解析速度快,适合超大型项目

2.2 功能特性对比

CMake的优势
  1. 跨平台支持广泛:支持Windows、Linux、macOS等多种平台
  2. 生成器多样化:可生成Makefile、Ninja、Visual Studio、Xcode等多种构建文件
  3. 生态系统成熟:拥有丰富的模块和第三方库支持
  4. 社区活跃:文档完善,社区支持强大
  5. 灵活性强:支持复杂的构建逻辑和自定义命令
GN的优势
  1. 解析速度快:在包含数万模块的大型项目中,GN的解析速度远超CMake
  2. 语法简洁:声明式语法,代码量少,易于阅读和维护
  3. 类型安全:强类型系统,编译时检查语法错误
  4. 深度集成Ninja:充分利用Ninja的并行构建能力
  5. 适合超大型项目:专为Chromium等超大型项目设计

2.3 使用场景对比

使用场景 推荐工具 原因
中小型项目 CMake 生态成熟,文档丰富,易于上手
跨平台项目 CMake 支持多种平台和IDE
超大型项目(如Chromium) GN 解析速度快,性能优异
OpenHarmony开发 GN 官方构建系统,深度集成
需要快速原型开发 CMake 灵活性高,易于调整

2.4 语法对比示例

CMake示例
cmake 复制代码
cmake_minimum_required(VERSION 3.10)
project(MyProject)

set(CMAKE_CXX_STANDARD 11)

add_executable(hello_world main.cpp utils.cpp)

target_include_directories(hello_world PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)

target_link_libraries(hello_world PRIVATE mylib)

add_library(mylib STATIC lib.cpp lib_utils.cpp)

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    target_compile_definitions(hello_world PRIVATE DEBUG_MODE)
endif()
GN示例
gn 复制代码
executable("hello_world") {
  sources = [
    "main.cpp",
    "utils.cpp",
  ]
  include_dirs = [ "include" ]
  deps = [ ":mylib" ]
}

static_library("mylib") {
  sources = [
    "lib.cpp",
    "lib_utils.cpp",
  ]
}

if (is_debug) {
  defines = [ "DEBUG_MODE" ]
}

对比分析

  • GN的语法更加简洁,代码量减少约30%
  • GN使用列表而非分号分隔,更符合现代编程习惯
  • GN的类型系统更加严格,减少配置错误

三、GN构建系统的缺点与局限性

虽然GN构建系统在超大型项目中表现出色,但它也存在一些明显的缺点和局限性,开发者在选择使用时需要充分考虑这些因素。

3.1 主要缺点

3.1.1 生态系统相对较小
  • 社区规模有限:相比CMake庞大的社区,GN的社区相对较小
  • 第三方库支持不足:许多第三方库只提供CMake构建脚本,缺少GN支持
  • 文档资源有限:虽然官方文档完善,但社区贡献的教程和案例较少
  • 问题解决困难:遇到问题时,网上可参考的解决方案较少
3.1.2 平台支持有限
  • 仅支持Ninja:GN只能生成Ninja构建文件,不支持Makefile、Visual Studio等其他构建工具
  • IDE集成度低:缺乏对主流IDE(如Visual Studio、Xcode)的原生支持
  • Windows支持较弱:虽然支持Windows,但相比Linux和macOS,Windows上的体验和使用案例较少
  • 跨平台迁移困难:从其他构建系统迁移到GN需要重写所有构建脚本
3.1.3 学习曲线较陡
  • 概念理解困难:元构建系统的概念对初学者来说较为抽象
  • 语法独特:GN的语法与CMake、Make等传统构建系统差异较大
  • 调试复杂:构建脚本错误时,调试和定位问题相对困难
  • 缺乏可视化工具:缺少像CMake-GUI这样的可视化配置工具
3.1.4 功能限制
  • 生成器单一:只能生成Ninja文件,无法生成其他格式的构建文件
  • 灵活性受限:相比CMake,GN的自定义能力和扩展性较弱
  • 高级特性支持不足:某些复杂的构建场景(如复杂的条件编译、自定义生成器)实现困难
  • 包管理集成差:与主流包管理器(如vcpkg、conan)的集成不如CMake完善

3.2 适用性局限

3.2.1 不适合的场景
  1. 中小型项目:GN的优势在大型项目中才能体现,中小型项目使用GN显得"杀鸡用牛刀"
  2. 需要多IDE支持的项目:如果项目需要在多种IDE中打开和调试,GN不是最佳选择
  3. 快速原型开发:需要频繁调整构建配置的场景,CMake的灵活性更胜一筹
  4. 依赖大量第三方库的项目:如果项目依赖的库只提供CMake支持,使用GN会增加集成成本
3.2.2 团队协作挑战
  • 团队学习成本:团队成员需要学习GN语法和概念
  • 招聘难度:熟悉GN的开发者相对较少,招聘可能面临困难
  • 知识传承困难:社区资源少,新成员上手需要更多时间
  • 工具链依赖:团队需要统一使用GN+Ninja工具链,灵活性降低

3.3 与CMake的对比总结

方面 GN CMake
生态系统 较小,主要在Chromium生态 成熟,广泛支持
平台支持 仅支持Ninja 支持多种生成器
IDE集成 较弱 优秀
学习曲线 较陡 较平缓
灵活性 中等
文档资源 官方文档完善,社区资源少 官方和社区文档都很丰富
第三方库支持 有限 广泛
适用项目规模 超大型项目 各种规模

3.4 选择建议

选择GN的情况:
  • 项目规模巨大(如Chromium、OpenHarmony级别)
  • 构建速度是关键指标
  • 团队已经熟悉GN
  • 项目主要在Linux/macOS平台开发
  • 不需要IDE集成
选择CMake的情况:
  • 中小型项目
  • 需要跨平台支持
  • 需要IDE集成
  • 依赖大量第三方库
  • 团队成员不熟悉GN
  • 需要快速原型开发

四、GN构建系统环境要求

使用GN构建系统需要准备特定的开发环境,包括操作系统、依赖工具和配置要求。本节将详细介绍GN构建系统的环境要求。

4.1 操作系统要求

4.1.1 支持的操作系统

GN支持以下操作系统:

操作系统 支持版本 说明
Linux 主流发行版 Ubuntu 18.04+, Debian 10+, CentOS 7+, Arch Linux等
macOS 10.14+ 推荐使用最新版本
Windows Windows 10/11 需要安装适当的工具链
4.1.2 推荐的操作系统配置

Linux系统

bash 复制代码
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y build-essential git python3 python3-pip

# CentOS/RHEL
sudo yum groupinstall "Development Tools"
sudo yum install git python3 python3-pip

# Arch Linux
sudo pacman -S base-devel git python python-pip

macOS系统

bash 复制代码
# 安装Xcode命令行工具
xcode-select --install

# 安装Homebrew(如果尚未安装)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# 安装必要的工具
brew install git python3

Windows系统

powershell 复制代码
# 安装Visual Studio Build Tools
# 下载地址:https://visualstudio.microsoft.com/downloads/
# 选择"使用C++的桌面开发"工作负载

# 安装Git
# 下载地址:https://git-scm.com/download/win

# 安装Python
# 下载地址:https://www.python.org/downloads/
# 安装时勾选"Add Python to PATH"

4.2 必需依赖工具

4.2.1 Python环境

GN需要Python环境来执行某些脚本和工具。

版本要求

  • Python 3.6 或更高版本

安装验证

bash 复制代码
# 检查Python版本
python3 --version

# 或
python --version

推荐配置

bash 复制代码
# 安装pip(如果尚未安装)
python3 -m ensurepip --upgrade

# 升级pip
python3 -m pip install --upgrade pip
4.2.2 Ninja构建工具

GN生成的构建文件需要Ninja来执行。

安装方法

方法一:通过包管理器安装

bash 复制代码
# Ubuntu/Debian
sudo apt-get install ninja-build

# CentOS/RHEL
sudo yum install ninja-build

# macOS
brew install ninja

# Windows (使用Chocolatey)
choco install ninja

# Windows (使用Scoop)
scoop install ninja

方法二:从源码编译

bash 复制代码
# 克隆Ninja源码
git clone https://github.com/ninja-build/ninja.git
cd ninja

# 编译
python3 configure.py --bootstrap

# 复制到PATH
sudo cp ninja /usr/local/bin/

# 验证安装
ninja --version

方法三:下载预编译二进制文件

bash 复制代码
# Linux
wget https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-linux.zip
unzip ninja-linux.zip
sudo mv ninja /usr/local/bin/

# macOS
wget https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-mac.zip
unzip ninja-mac.zip
sudo mv ninja /usr/local/bin/

# Windows
# 下载:https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-win.zip
# 解压后将ninja.exe添加到PATH
4.2.3 编译器工具链

根据目标平台,需要安装相应的编译器。

Linux/macOS

bash 复制代码
# GCC (GNU Compiler Collection)
sudo apt-get install gcc g++  # Ubuntu/Debian
sudo yum install gcc gcc-c++   # CentOS/RHEL

# Clang
sudo apt-get install clang clang++  # Ubuntu/Debian
sudo yum install clang clang++     # CentOS/RHEL

# macOS通常自带Clang

Windows

powershell 复制代码
# Visual Studio编译器
# 通过Visual Studio Installer安装
# 或使用Build Tools for Visual Studio

# MinGW-w64(可选)
# 下载地址:https://www.mingw-w64.org/

4.3 可选依赖工具

4.3.1 Git版本控制

虽然不是GN构建的必需工具,但强烈推荐安装Git用于版本控制。

bash 复制代码
# Ubuntu/Debian
sudo apt-get install git

# CentOS/RHEL
sudo yum install git

# macOS
brew install git

# Windows
# 下载安装:https://git-scm.com/download/win
4.3.2 depot_tools(推荐)

Google开发的工具集,包含GN、Ninja等工具。

bash 复制代码
# 克隆depot_tools
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

# 添加到PATH(Linux/macOS)
export PATH="$PATH:/path/to/depot_tools"

# 添加到PATH(Windows PowerShell)
$env:PATH += ";C:\path\to\depot_tools"

# 永久添加到PATH
# Linux/macOS: 添加到 ~/.bashrc 或 ~/.zshrc
# Windows: 添加到系统环境变量
4.3.3 其他开发工具
bash 复制代码
# 调试工具
sudo apt-get install gdb  # Linux
brew install lldb        # macOS

# 代码格式化工具
sudo apt-get install clang-format  # Linux
brew install clang-format           # macOS

# 静态分析工具
sudo apt-get install cppcheck  # Linux
brew install cppcheck          # macOS

4.4 环境变量配置

4.4.1 PATH配置

确保GN、Ninja等工具在PATH中。

bash 复制代码
# Linux/macOS - 临时添加
export PATH="/path/to/gn:$PATH"
export PATH="/path/to/ninja:$PATH"

# Linux/macOS - 永久添加(添加到 ~/.bashrc 或 ~/.zshrc)
echo 'export PATH="/path/to/gn:$PATH"' >> ~/.bashrc
echo 'export PATH="/path/to/ninja:$PATH"' >> ~/.bashrc
source ~/.bashrc

# Windows - 通过系统设置
# 控制面板 → 系统 → 高级系统设置 → 环境变量
# 编辑Path变量,添加工具路径
4.4.2 其他环境变量
bash 复制代码
# GN脚本解释器(可选)
export GN_PYTHON=/usr/bin/python3

# Ninja并行数(可选)
export NINJA_STATUS="[%f/%t] "  # 显示构建进度

4.5 验证环境配置

4.5.1 检查工具版本
bash 复制代码
# 检查GN版本
gn --version

# 检查Ninja版本
ninja --version

# 检查Python版本
python3 --version

# 检查编译器版本
gcc --version
clang --version
4.5.2 测试构建环境

创建一个简单的测试项目:

bash 复制代码
# 创建测试目录
mkdir gn_test
cd gn_test

# 创建.gn文件
echo 'buildconfig = "//build/BUILDCONFIG.gn"' > .gn

# 创建BUILD.gn文件
cat > BUILD.gn << 'EOF'
executable("hello") {
  sources = [ "hello.cpp" ]
}
EOF

# 创建源文件
cat > hello.cpp << 'EOF'
#include <iostream>

int main() {
    std::cout << "Hello, GN!" << std::endl;
    return 0;
}
EOF

# 创建构建配置目录
mkdir -p build
cat > build/BUILDCONFIG.gn << 'EOF'
# 简单的构建配置
set_default_toolchain("//build:toolchain")

toolchain("toolchain") {
  tool("cc") {
    command = "gcc -c \$in -o \$out"
    description = "CC \$out"
  }
  
  tool("cxx") {
    command = "g++ -c \$in -o \$out"
    description = "CXX \$out"
  }
  
  tool("link") {
    command = "g++ \$in -o \$out"
    description = "LINK \$out"
  }
}
EOF

# 生成构建文件
gn gen out

# 编译项目
ninja -C out

# 运行程序
./out/hello

4.6 OpenHarmony特殊环境要求

如果要在OpenHarmony环境中使用GN,还需要满足以下额外要求:

4.6.1 OpenHarmony源码环境
bash 复制代码
# 下载OpenHarmony源码
repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify
repo sync -c

# 安装OpenHarmony构建依赖
# 参考官方文档:https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/quick-start/README.md
4.6.2 hb命令工具
bash 复制代码
# 安装hb命令
pip3 install --user ohos-build

# 添加到PATH
export PATH="$HOME/.local/bin:$PATH"

# 验证安装
hb -h
4.6.3 交叉编译工具链
bash 复制代码
# OpenHarmony提供预编译的工具链
# 位于:prebuilts/clang/ohos/linux-x86_64/

# 添加到PATH
export PATH="/path/to/openharmony/prebuilts/clang/ohos/linux-x86_64/bin:$PATH"

4.7 常见环境问题

4.7.1 GN命令找不到
bash 复制代码
# 问题:bash: gn: command not found

# 解决方案:
# 1. 检查PATH配置
echo $PATH

# 2. 重新加载配置
source ~/.bashrc  # Linux/macOS

# 3. 使用绝对路径
/path/to/gn --version
4.7.2 Python版本不兼容
bash 复制代码
# 问题:GN需要Python 3.6+

# 解决方案:
# 1. 检查Python版本
python3 --version

# 2. 安装较新版本的Python
sudo apt-get install python3.8  # Ubuntu/Debian

# 3. 使用虚拟环境
python3 -m venv venv
source venv/bin/activate
4.7.3 Ninja版本过低
bash 复制代码
# 问题:Ninja版本过低,某些功能不可用

# 解决方案:
# 1. 检查当前版本
ninja --version

# 2. 升级Ninja
sudo apt-get install --only-upgrade ninja-build  # Ubuntu/Debian
brew upgrade ninja                              # macOS

# 3. 从源码编译最新版本
git clone https://github.com/ninja-build/ninja.git
cd ninja
python3 configure.py --bootstrap
sudo cp ninja /usr/local/bin/

4.8 环境优化建议

4.8.1 性能优化
bash 复制代码
# 增加Ninja并行构建数
ninja -C out -j$(nproc)  # Linux
ninja -C out -j$(sysctl -n hw.ncpu)  # macOS

# 使用ccache加速编译
sudo apt-get install ccache  # Linux
brew install ccache             # macOS

# 配置GN使用ccache
export CC="ccache gcc"
export CXX="ccache g++"
4.8.2 磁盘空间优化
bash 复制代码
# 定期清理构建产物
rm -rf out/

# 使用符号链接减少重复
ln -s /path/to/common_lib ./common_lib

# 配置GN使用增量构建
gn gen out --args="use_incremental_build=true"

五、GN构建系统详解

5.1 GN简介

GN(Generate Ninja)是由Google开发的元构建系统,主要用于生成Ninja构建文件。它的设计目标是解决传统构建工具在大型项目中存在的配置复杂、构建速度慢等问题。

核心特点

  • 不直接执行编译,而是生成Ninja构建文件
  • 简洁的脚本语法,易于学习和使用
  • 快速的解析速度,适合超大型项目
  • 强类型系统,减少配置错误
  • 深度集成Ninja,充分利用并行构建能力

5.2 GN与Ninja的关系

GN和Ninja的关系可以类比为CMake和Make的关系:

复制代码
GN → 生成 .ninja 文件 → Ninja 执行编译
CMake → 生成 Makefile → Make 执行编译

工作流程

  1. GN读取BUILD.gn等配置文件
  2. GN解析构建目标和依赖关系
  3. GN生成build.ninja文件
  4. Ninja读取build.ninja文件
  5. Ninja执行实际的编译、链接等操作

5.3 GN的文件结构

一个典型的GN项目包含以下文件:

复制代码
project_root/
├── .gn                    # GN配置文件
├── BUILD.gn              # 根构建文件
├── build/
│   ├── BUILDCONFIG.gn    # 构建配置
│   └── toolchain/
│       └── BUILD.gn      # 工具链配置
├── args.gn               # 构建参数(在构建目录中)
└── out/                  # 构建输出目录
    └── build/
        ├── build.ninja   # 生成的Ninja文件
        └── args.gn       # 构建参数

5.4 GN的安装

方法一:通过depot_tools安装
bash 复制代码
# 克隆depot_tools
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

# 添加到PATH
export PATH=$PATH:/path/to/depot_tools

# 验证安装
which gn
方法二:从源码编译
bash 复制代码
# 克隆GN源码
git clone https://gn.googlesource.com/gn
cd gn

# 编译
python build/gen.py
ninja -C out

# 添加到PATH
export PATH=$PATH:/path/to/gn/out
方法三:使用预编译二进制文件
bash 复制代码
# 下载预编译二进制文件
# Linux: https://chrome-infra-packages.appspot.com/dl/gn/gn/linux-amd64/+/latest
# macOS: https://chrome-infra-packages.appspot.com/dl/gn/gn/mac-amd64/+/latest
# Windows: https://chrome-infra-packages.appspot.com/dl/gn/gn/windows-amd64/+/latest

# 添加到PATH
chmod +x gn
export PATH=$PATH:/path/to/gn
方法四:通过包管理器安装
bash 复制代码
# macOS (Homebrew)
brew install gn

# Linux (Debian/Ubuntu)
sudo apt-get install gn

# Linux (Arch)
sudo pacman -S gn

六、GN基础语法

6.1 基本概念

4.1.1 目标(Target)

GN中的目标是指一个构建单元,可以是可执行文件、库文件或其他构建产物。

4.1.2 标签(Label)

标签用于标识目标,格式为://path/to/dir:target_name

  • // 表示项目根目录
  • path/to/dir 表示目标所在目录
  • target_name 表示目标名称

示例:

gn 复制代码
//:hello              # 根目录下的hello目标
//utils:helpers       # utils目录下的helpers目标
//third_party:openssl # third_party目录下的openssl目标

4.2 变量与数据类型

4.2.1 变量定义
gn 复制代码
# 字符串
name = "hello"

# 列表
sources = [
  "main.cpp",
  "utils.cpp",
]

# 布尔值
enable_debug = true

# 作用域变量
config("my_config") {
  defines = [ "DEBUG" ]
}
4.2.2 内置变量
gn 复制代码
# 目标名称
target_name = "my_target"

# 构建目录
root_build_dir = "//out/Default"

# 目标生成目录
target_gen_dir = "$root_build_dir/gen"

# 当前CPU架构
current_cpu = "x64"

# 目标CPU架构
target_cpu = "arm64"

# 当前操作系统
current_os = "linux"

# 目标操作系统
target_os = "android"

6.3 构建目标类型

4.3.1 可执行文件(executable)
gn 复制代码
executable("my_app") {
  sources = [
    "main.cpp",
    "app.cpp",
  ]
  deps = [
    ":my_lib",
  ]
}
4.3.2 静态库(static_library)
gn 复制代码
static_library("my_lib") {
  sources = [
    "lib.cpp",
    "lib_utils.cpp",
  ]
  include_dirs = [
    "include",
  ]
}
4.3.3 动态库(shared_library)
gn 复制代码
shared_library("my_shared_lib") {
  sources = [
    "shared.cpp",
  ]
  defines = [
    "MY_SHARED_LIB_IMPLEMENTATION",
  ]
}
4.3.4 源文件集合(source_set)
gn 复制代码
source_set("common_sources") {
  sources = [
    "common.cpp",
    "utils.cpp",
  ]
  # 不会生成中间文件,直接编译到依赖它的目标中
}
4.3.5 组目标(group)
gn 复制代码
group("all_targets") {
  deps = [
    ":executable",
    ":library",
    ":test",
  ]
  # 虚目标,用于组织其他目标
}
4.3.6 动作目标(action)
gn 复制代码
action("generate_code") {
  script = "generate.py"
  sources = [
    "input.txt",
  ]
  outputs = [
    "$target_gen_dir/generated.cpp",
  ]
  args = [
    "--input",
    rebase_path("input.txt", root_build_dir),
    "--output",
    rebase_path(target_gen_dir, root_build_dir),
  ]
}

4.4 配置(Config)

配置用于封装编译选项、宏定义、头文件路径等。

gn 复制代码
config("my_config") {
  defines = [
    "ENABLE_FEATURE",
    "VERSION=1.0",
  ]
  include_dirs = [
    "include",
    "//third_party/include",
  ]
  cflags = [
    "-Wall",
    "-Wextra",
  ]
}

# 使用配置
executable("my_app") {
  sources = [ "main.cpp" ]
  configs += [ ":my_config" ]
}

# 公共配置(传递给依赖者)
static_library("my_lib") {
  sources = [ "lib.cpp" ]
  public_configs = [ ":my_config" ]
}

4.5 依赖关系

gn 复制代码
# 定义库
static_library("base") {
  sources = [ "base.cpp" ]
}

static_library("utils") {
  sources = [ "utils.cpp" ]
  deps = [ ":base" ]
}

# 可执行文件依赖utils,间接依赖base
executable("app") {
  sources = [ "main.cpp" ]
  deps = [ ":utils" ]
}

6.6 条件编译

gn 复制代码
# 根据构建类型
if (is_debug) {
  defines = [ "DEBUG" ]
} else {
  defines = [ "NDEBUG" ]
}

# 根据目标CPU
if (target_cpu == "arm64") {
  cflags = [ "-march=armv8-a" ]
} else if (target_cpu == "x86_64") {
  cflags = [ "-march=x86-64" ]
}

# 根据操作系统
if (is_android) {
  libs = [ "log" ]
} else if (is_linux) {
  libs = [ "dl", "pthread" ]
}

# 自定义条件
declare_args() {
  enable_feature = false
}

if (enable_feature) {
  sources += [ "feature.cpp" ]
}

4.7 模板(Template)

模板用于定义可复用的构建规则。

gn 复制代码
# 定义模板
template("my_template") {
  executable(target_name) {
    sources = [
      "common.cpp",
      invoker.sources,
    ]
    configs = [
      ":common_config",
    ]
  }
}

# 使用模板
my_template("app1") {
  sources = [ "app1.cpp" ]
}

my_template("app2") {
  sources = [ "app2.cpp" ]
}

6.8 函数调用

gn 复制代码
# rebase_path:转换路径为相对于构建目录的路径
rebase_path("include", root_build_dir)

# exec_script:执行脚本
result = exec_script("get_version.py", [], "list lines")

# print:打印调试信息
print("Building for $target_os")

# get_label_info:获取标签信息
target_dir = get_label_info(":my_target", "dir")
target_name = get_label_info(":my_target", "name")

五、GN实战示例

5.1 创建简单项目

项目结构
复制代码
simple_project/
├── .gn
├── BUILD.gn
├── build/
│   ├── BUILDCONFIG.gn
│   └── toolchain/
│       └── BUILD.gn
├── src/
│   ├── main.cpp
│   ├── hello.cpp
│   └── hello.h
└── out/
    └── default/
.gn文件
gn 复制代码
buildconfig = "//build/BUILDCONFIG.gn"
BUILD.gn文件
gn 复制代码
executable("hello_world") {
  sources = [
    "src/main.cpp",
    "src/hello.cpp",
  ]
  include_dirs = [
    "src",
  ]
}
main.cpp
cpp 复制代码
#include <iostream>
#include "hello.h"

int main() {
    say_hello();
    return 0;
}
hello.cpp
cpp 复制代码
#include <iostream>
#include "hello.h"

void say_hello() {
    std::cout << "Hello, World!" << std::endl;
}
hello.h
cpp 复制代码
#ifndef HELLO_H
#define HELLO_H

void say_hello();

#endif

7.2 构建项目

bash 复制代码
# 生成构建文件
gn gen out/default

# 查看构建参数
gn args out/default --list

# 设置构建参数
gn args out/default
# 在编辑器中添加:
# is_debug = true
# target_cpu = "x64"

# 编译项目
ninja -C out/default

# 运行程序
./out/default/hello_world

7.3 复杂项目示例

项目结构
复制代码
complex_project/
├── .gn
├── BUILD.gn
├── build/
│   ├── BUILDCONFIG.gn
│   └── toolchain/
│       └── BUILD.gn
├── src/
│   ├── main.cpp
│   ├── core/
│   │   ├── BUILD.gn
│   │   ├── core.cpp
│   │   └── core.h
│   ├── utils/
│   │   ├── BUILD.gn
│   │   ├── utils.cpp
│   │   └── utils.h
│   └── network/
│       ├── BUILD.gn
│       ├── network.cpp
│       └── network.h
└── out/
根BUILD.gn
gn 复制代码
group("all") {
  deps = [
    "//src:my_app",
    "//src:tests",
  ]
}
src/BUILD.gn
gn 复制代码
executable("my_app") {
  sources = [ "main.cpp" ]
  deps = [
    ":core",
    ":utils",
    ":network",
  ]
}

group("tests") {
  testonly = true
  deps = [
    "//src/core:tests",
    "//src/utils:tests",
  ]
}
src/core/BUILD.gn
gn 复制代码
static_library("core") {
  sources = [
    "core.cpp",
    "core.h",
  ]
  public_configs = [ ":core_config" ]
}

config("core_config") {
  include_dirs = [ "." ]
  defines = [ "CORE_VERSION=1.0" ]
}

test("core_tests") {
  sources = [ "core_test.cpp" ]
  deps = [ ":core" ]
}
src/utils/BUILD.gn
gn 复制代码
source_set("utils") {
  sources = [
    "utils.cpp",
    "utils.h",
  ]
  deps = [
    "//src/core:core",
  ]
}

test("utils_tests") {
  sources = [ "utils_test.cpp" ]
  deps = [ ":utils" ]
}
src/network/BUILD.gn
gn 复制代码
shared_library("network") {
  sources = [
    "network.cpp",
    "network.h",
  ]
  deps = [
    "//src/core:core",
    "//src/utils:utils",
  ]
  defines = [ "NETWORK_EXPORT" ]
}

7.4 跨平台配置

gn 复制代码
# BUILD.gn
executable("my_app") {
  sources = [ "main.cpp" ]
  
  deps = [
    ":platform_specific",
  ]
  
  if (is_android) {
    deps += [ "//third_party/android_support:android_support" ]
  } else if (is_linux) {
    deps += [ "//third_party/linux_support:linux_support" ]
  }
}

# 平台特定代码
if (is_android) {
  source_set("platform_specific") {
    sources = [ "platform_android.cpp" ]
  }
} else if (is_linux) {
  source_set("platform_specific") {
    sources = [ "platform_linux.cpp" ]
  }
} else if (is_win) {
  source_set("platform_specific") {
    sources = [ "platform_windows.cpp" ]
  }
}

7.5 使用第三方库

gn 复制代码
# 引用第三方库
executable("my_app") {
  sources = [ "main.cpp" ]
  
  deps = [
    "//third_party/openssl:openssl",
    "//third_party/curl:curl",
  ]
  
  # 配置第三方库
  configs += [
    "//third_party/openssl:openssl_config",
  ]
}

八、GN在OpenHarmony中的应用

8.1 OpenHarmony构建系统概述

OpenHarmony使用GN+Ninja作为其主要的构建工具链,类似于CMake+Make的关系。OpenHarmony的构建系统包含以下主要组件:

  1. GN:用于生成Ninja构建文件
  2. Ninja:负责执行实际的编译和链接
  3. hb命令:OpenHarmony提供的构建命令行工具
  4. Python脚本:用于辅助构建过程

8.2 OpenHarmony项目结构

复制代码
OpenHarmony/
├── build/
│   ├── lite/
│   │   ├── .gn              # GN配置文件
│   │   ├── BUILDCONFIG.gn    # 构建配置
│   │   └── toolchain/        # 工具链配置
│   └── ohos/
│       ├── .gn
│       └── BUILDCONFIG.gn
├── kernel/
│   ├── linux/
│   └── liteos_a/
├── foundation/
│   ├── communication/
│   ├── graphic/
│   └── multimedia/
├── vendor/
│   └── huawei/
│       └── hisilicon/
└── out/
    └── [产品名]/

6.3 OpenHarmony中的GN配置

.gn文件
gn 复制代码
# OpenHarmony的.gn文件示例
buildconfig = "//build/lite/BUILDCONFIG.gn"
secondary_source = ["//vendor/huawei/hisilicon/"]
BUILDCONFIG.gn
gn 复制代码
# 构建配置
default_toolchain = "//build/lite/toolchain:linux_clang_arm64"

# 默认配置
set_defaults("executable") {
  configs = default_executable_configs
}

set_defaults("shared_library") {
  configs = default_shared_library_configs
}

set_defaults("static_library") {
  configs = default_static_library_configs
}

8.4 OpenHarmony组件开发

创建组件
gn 复制代码
# foundation/my_component/BUILD.gn
import("//build/lite/config/component/lite_component.gni")

lite_component("my_component") {
  component_type = "shared_library"
  
  sources = [
    "src/my_component.cpp",
    "src/my_component_impl.cpp",
  ]
  
  include_dirs = [
    "include",
    "include/inner",
  ]
  
  deps = [
    "//utils/log:log",
    "//utils/memory:memory",
  ]
  
  public_configs = [ ":my_component_public_config" ]
}

config("my_component_public_config") {
  include_dirs = [ "include" ]
  defines = [ "MY_COMPONENT_VERSION=1.0" ]
}
添加到子系统
gn 复制代码
# foundation/my_subsystem/BUILD.gn
import("//build/lite/config/subsystem/lite_subsystem.gni")

lite_subsystem("my_subsystem") {
  subsystem_components = [
    ":my_component",
  ]
}

lite_component("my_component") {
  component_type = "shared_library"
  # ... 组件配置
}

6.5 使用hb命令构建

bash 复制代码
# 设置环境变量
hb set

# 选择产品
# 1. 选择开发板
# 2. 选择产品

# 编译
hb build -f

# 编译特定组件
hb build -f my_component

# 清理构建
hb clean

# 查看帮助
hb -h

6.6 OpenHarmony构建参数

gn 复制代码
# 常用构建参数
declare_args() {
  # 构建类型
  ohos_build_type = "debug"  # 或 "release"
  
  # 编译器
  ohos_build_compiler = "clang"  # 或 "gcc"
  
  # 目标架构
  ohos_build_target_cpu = "arm64"  # 或 "arm", "x86_64"
  
  # 启用特性
  enable_ohos_test = false
  enable_ohos_ndk = true
}

九、GN高级特性

9.1 自定义工具链

gn 复制代码
# toolchain/BUILD.gn
toolchain("my_toolchain") {
  tool("cc") {
    command = "gcc -c $in -o $out"
    description = "CC $out"
    depsformat = "gcc"
  }
  
  tool("cxx") {
    command = "g++ -c $in -o $out"
    description = "CXX $out"
    depsformat = "gcc"
  }
  
  tool("alink") {
    command = "ar rcs $out $in"
    description = "AR $out"
  }
  
  tool("solink") {
    command = "g++ -shared $in -o $out"
    description = "SOLINK $out"
  }
  
  tool("link") {
    command = "g++ $in -o $out"
    description = "LINK $out"
  }
}

7.2 元数据(Metadata)

gn 复制代码
executable("my_app") {
  sources = [ "main.cpp" ]
  
  metadata = {
    app_name = "My Application"
    app_version = "1.0.0"
    app_category = "utility"
  }
}

# 读取元数据
# gn desc out/default //:my_app metadata

7.3 可见性控制

gn 复制代码
# 限制目标可见性
static_library("internal_lib") {
  sources = [ "internal.cpp" ]
  visibility = [
    "//src:*",           # 仅src目录可见
    "//tests:*",         # tests目录可见
  ]
}

# 公共库
static_library("public_lib") {
  sources = [ "public.cpp" ]
  visibility = [ "*" ]  # 所有目录可见
}

9.4 测试支持

gn 复制代码
# 定义测试目标
test("my_test") {
  sources = [
    "test_main.cpp",
    "test_utils.cpp",
  ]
  deps = [
    ":my_lib",
    "//third_party/gtest:gtest",
  ]
  
  testonly = true
}

# 运行测试
# ninja -C out/default my_test
# ./out/default/my_test

7.5 生成文件

gn 复制代码
# 使用action生成文件
action("generate_config") {
  script = "generate_config.py"
  sources = [
    "config_template.json",
  ]
  outputs = [
    "$target_gen_dir/config.h",
  ]
  args = [
    "--template",
    rebase_path("config_template.json", root_build_dir),
    "--output",
    rebase_path("$target_gen_dir/config.h", root_build_dir),
  ]
}

# 使用生成的文件
executable("my_app") {
  sources = [
    "main.cpp",
  ]
  deps = [
    ":generate_config",
  ]
  include_dirs = [
    target_gen_dir,
  ]
}

7.6 多工具链支持

gn 复制代码
# 定义多个工具链
toolchain("host_toolchain") {
  tool("cc") {
    command = "gcc -c $in -o $out"
  }
  # ... 其他工具
}

toolchain("cross_toolchain") {
  tool("cc") {
    command = "arm-linux-gnueabihf-gcc -c $in -o $out"
  }
  # ... 其他工具
}

# 为不同目标使用不同工具链
executable("host_app") {
  sources = [ "main.cpp" ]
  toolchain = "//toolchain:host_toolchain"
}

executable("target_app") {
  sources = [ "main.cpp" ]
  toolchain = "//toolchain:cross_toolchain"
}

八、常见问题与解决方案

8.1 常见错误

错误1:找不到BUILD.gn文件
复制代码
Error: Unable to find "//BUILD.gn"

解决方案

  • 确保项目根目录有.gn文件
  • 检查.gn文件中的buildconfig路径是否正确
  • 使用gn help dotfile查看配置
错误2:类型不匹配
复制代码
Error: Assigning list to scope

解决方案

  • 检查变量类型是否正确
  • 使用+=而不是=添加到列表
  • 确保变量在使用前已定义
错误3:依赖循环
复制代码
Error: Dependency cycle detected

解决方案

  • 使用gn desc <build_dir> <target> deps --tree查看依赖树
  • 重构代码,消除循环依赖
  • 考虑使用接口或抽象层

10.2 调试技巧

查看目标信息
bash 复制代码
# 查看目标详细信息
gn desc out/default //:my_target

# 查看依赖树
gn desc out/default //:my_target deps --tree

# 查看配置
gn desc out/default //:my_target configs --tree

# 查看源文件
gn desc out/default //:my_target sources
打印调试信息
gn 复制代码
executable("my_app") {
  sources = [ "main.cpp" ]
  
  # 打印变量值
  print("Building $target_name with configs: $configs")
  
  # 条件打印
  if (is_debug) {
    print("Debug build enabled")
  }
}
使用详细模式
bash 复制代码
# 生成构建文件时显示详细信息
gn gen -v out/default

# 查看GN解析过程
gn gen --check=out/default

8.3 性能优化

减少依赖
gn 复制代码
# 避免不必要的依赖
executable("my_app") {
  sources = [ "main.cpp" ]
  
  # 仅依赖真正需要的库
  deps = [
    ":essential_lib",
  ]
  
  # 使用public_configs传递配置,而不是依赖
  public_configs = [ ":common_config" ]
}
使用source_set
gn 复制代码
# 对于小型的源文件集合,使用source_set
source_set("common") {
  sources = [
    "utils.cpp",
    "helpers.cpp",
  ]
  # 不会生成中间文件,减少构建时间
}
并行构建
bash 复制代码
# Ninja默认使用所有CPU核心
ninja -C out/default

# 限制并行数
ninja -C out/default -j 4

8.4 迁移指南

从CMake迁移到GN

步骤1:理解项目结构

cmake 复制代码
# CMakeLists.txt
add_executable(my_app main.cpp utils.cpp)
target_include_directories(my_app PRIVATE include)
target_link_libraries(my_app PRIVATE mylib)
gn 复制代码
# BUILD.gn
executable("my_app") {
  sources = [
    "main.cpp",
    "utils.cpp",
  ]
  include_dirs = [ "include" ]
  deps = [ ":mylib" ]
}

步骤2:转换配置

cmake 复制代码
# CMake
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    add_definitions(-DDEBUG)
endif()
gn 复制代码
# GN
if (is_debug) {
  defines = [ "DEBUG" ]
}

步骤3:转换库定义

cmake 复制代码
# CMake
add_library(mylib STATIC lib.cpp)
gn 复制代码
# GN
static_library("mylib") {
  sources = [ "lib.cpp" ]
}

十一、总结

11.1 CMake vs GN 总结

方面 CMake GN
学习曲线 中等,需要掌握复杂语法 较低,语法简洁
构建速度 中等,大型项目较慢 快,适合超大型项目
跨平台支持 优秀,支持多种平台和IDE 良好,主要支持类Unix系统
生态系统 成熟,丰富的第三方支持 较新,主要在Chromium生态
适用场景 中小型项目、跨平台项目 超大型项目、OpenHarmony开发

9.2 GN最佳实践

  1. 保持简洁:使用简洁的语法,避免过度复杂的配置
  2. 模块化设计:将项目分解为小的、可重用的模块
  3. 使用配置:将编译选项封装到config中,提高复用性
  4. 控制可见性:合理使用visibility限制目标访问
  5. 编写测试:使用test目标编写单元测试
  6. 文档化:为复杂的构建逻辑添加注释

11.3 学习资源

11.4 结语

GN构建系统以其简洁的语法、高效的性能和强大的功能,成为OpenHarmony等大型项目的首选构建工具。虽然CMake在跨平台支持和生态系统方面更具优势,但在超大型项目的构建效率上,GN无疑更具竞争力。

对于开发者来说,掌握GN构建系统不仅能提高开发效率,还能更好地参与OpenHarmony等开源项目的开发。希望本文能够帮助读者快速上手GN构建系统,并在实际项目中灵活运用。

参考连接

鸿蒙源码构建工具Gn 与 Ninja 的介绍及使用入门

深入理解鸿蒙内核源码:GN构建工具的实践与应用

OpenHarmony轻量系统开发【4】编写第一个程序

鸿蒙南向开发------GN快速入门指南

https://cloud.tencent.com/developer/user/11158284

相关推荐
SuperHeroWu711 小时前
如何判断应用在鸿蒙卓易通或者出境易环境下?
华为·harmonyos
大雷神12 小时前
HarmonyOS APP<玩转React>开源教程十五:首页完整实现
react.js·开源·harmonyos
云和数据.ChenGuang13 小时前
鸿蒙智联,极智共生:HarmonyOS与MiniMax智能体的融合新纪元
华为·harmonyos·鸿蒙
不爱吃糖的程序媛13 小时前
已有 Flutter 应用适配鸿蒙平台指导文档
flutter·华为·harmonyos
大雷神14 小时前
HarmonyOS APP<玩转React>开源教程十六:课程列表页面
harmonyos
弓.长.14 小时前
ReactNative for OpenHarmony项目鸿蒙化三方库:react-native-video — 视频播放组件
react native·音视频·harmonyos
坚果派·白晓明14 小时前
在 Ubuntu 中搭建鸿蒙 PC 三方库交叉编译构建开发环境
ubuntu·华为·harmonyos
弓.长.15 小时前
ReactNative for OpenHarmony项目鸿蒙化三方库:react-native-webview — 网页渲染组件
react native·react.js·harmonyos
特立独行的猫a15 小时前
海思WS63平台CMake构建系统使用指南
cmake·海思·ws63·fbb_ws63