---
tags: [CANN]
doc_type: knowledge-note
abstract: "区分源码职责，完成终端或 Notebook 中的配置、编译和运行。"
返回目录: "[[计算机系/昇腾与CANN/大模型与算子专题学习导航|大模型与算子专题学习导航]]"
专题目录: "[[计算机系/昇腾与CANN/CMake与Ascend C编译入门|CMake与Ascend C编译入门]]"
上一篇: "[[计算机系/昇腾与CANN/01 CMake最小配置与编译选项|01 CMake最小配置与编译选项]]"
前置操作: "[[计算机系/昇腾与CANN/01 CMake最小配置与编译选项|01 CMake最小配置与编译选项]]"
下一篇: "[[计算机系/昇腾与CANN/03 多级CMake工程与构建检查|03 多级CMake工程与构建检查]]"
---

# 02 Ascend C源码组织与编译运行

区分源码职责，完成终端或 Notebook 中的配置、编译和运行。

## 6. `.h`、`.cpp`、`.asc` 的分工

| 文件 | 常见用途 | 构建时的处理方式 |
| --- | --- | --- |
| `.h`、`.hpp` | 函数声明、类型声明，以及适合放在头文件中的定义 | 通常由源文件 `#include`，不单独编译为目标文件 |
| `.cpp` | C++ 实现 | 作为 CXX 源文件编译 |
| `.c` | C 实现 | 启用 C 语言后按 C 源文件编译 |
| `.asc` | Ascend C 源码 | 使用 ASC 构建支持处理 |

头文件也可以包含模板、内联函数等定义，因此不能简单理解为“.h 只能写声明”。`.h` 也不是 C 专属，C++ 同样可以使用。

把头文件加入 `add_executable` 的源文件列表可以方便 IDE 展示，但**不等于设置了头文件搜索路径，也不等于会单独编译它**。头文件搜索路径由 `target_include_directories` 等配置管理。

项目较小时，`.asc` 可以同时包含 Host 入口和 Device 核函数，就像 [算子基础中的 Hello World](Ascend%20C算子基础整理.md#5.%20Hello%20World：理解核函数如何启动)。拆分到多个源文件时，需要同时考虑函数声明、ASC 调用语法、Host/Device 编译边界与链接依赖。不要默认普通 C++ 编译器能够直接理解 `<<<>>>`。

## 7. 配置、构建与运行

假设工程结构是：

```text
kernel_samples/
├── CMakeLists.txt
└── add_custom.asc
```

在已配置好 ASC 开发环境的终端中，从工程目录执行：

```bash
cmake -S . -B build
cmake --build build --target demo
```

| 命令部分 | 含义 |
| --- | --- |
| `-S .` | 源码目录是当前目录 |
| `-B build` | 使用 `build` 作为构建目录 |
| `--build build` | 调用该目录对应的构建工具 |
| `--target demo` | 构建 `demo` 及其必要依赖 |

第一条命令进行配置与生成，包括找包、启用语言、检查工具链和建立构建规则。第二条命令执行实际构建。**构建成功也不会自动运行程序。**

对于上述 Linux 单配置目录布局，运行命令通常是：

```bash
./build/demo
```

如果设置了输出目录或使用多配置生成器，应按实际输出路径运行。NPU 程序还需要对应的设备与运行环境。

### 7.1 在 Notebook 中编译和运行

假设 Notebook 当前工作目录下存在 `Sources/02.04`，其中包含 `CMakeLists.txt` 和源码。使用 Linux Shell 时，可以分三个单元格执行。

创建构建目录：

```python
!cd Sources/02.04 && mkdir -p build
```

配置并编译：

```python
!cd Sources/02.04/build && cmake .. && make
```

运行程序：

```python
!cd Sources/02.04/build && ./demo
```

这里的 `!` 是 IPython/Notebook 调用 Shell 命令的语法，不属于 CMake，也不是普通 Python 语法。每次 `!` 调用通常在独立的 Shell 中执行，因此前一个单元格里的 `cd` 不会改变下一个单元格的工作目录，需要再次进入目标目录。

| 命令或符号 | 含义 |
| --- | --- |
| `cd Sources/02.04` | 进入工程源码目录 |
| `mkdir -p build` | 创建构建目录；已存在时不因这一原因报错 |
| `&&` | 前一条命令成功后，才执行后一条 |
| `cmake ..` | 在当前构建目录配置工程，使用上一级目录中的 `CMakeLists.txt` |
| `make` | 执行生成的 Makefile，完成编译与链接 |
| `./demo` | 运行当前目录下的可执行程序 |

`make` 要放在 `cmake ..` 之后。运行命令前的 `!` 属于另一个 Notebook 单元格，不能与前面的命令粘成 `make!cd`。

这套写法假定 CMake 使用 Makefile 生成器。如果生成的是 Ninja 等其他规则，使用对应工具，或者统一使用 `cmake --build`。

### 7.2 推荐的 Notebook 写法

用 `-S` 和 `-B` 指定目录，可以减少反复切换目录；用 `cmake --build` 可以避免依赖特定构建工具的命令名称。

```python
!cmake -S Sources/02.04 -B Sources/02.04/build
```

```python
!cmake --build Sources/02.04/build --target demo
```

```python
!cd Sources/02.04/build && ./demo
```

保留运行前的 `cd`，是因为程序如果通过相对路径读取输入文件，会以运行时工作目录为基准。直接从 Notebook 所在目录执行 `Sources/02.04/build/demo`，其工作目录并不会自动切换到 `build`。

### 7.3 普通终端中的等价写法

在 Linux 终端中去掉 Notebook 的 `!`：

```bash
cd Sources/02.04 && mkdir -p build && cd build
cmake .. && make
./demo
```

这些命令在同一个终端会话中执行，`cd` 的效果会保留。只有前面的配置和编译成功后，才继续运行程序。

Linux Shell 中的反斜杠 `\` 可以用来续行，必须紧接换行，后面不能再添加解释文字。上面的命令采用单行写法，避免将续行符与正文混在一起。

### 7.4 编译与实际运行的边界

配置成功表示构建规则已经生成；编译成功表示可执行文件已经产生；执行 `./demo` 才会进入程序入口，并按程序逻辑准备数据、启动核函数和取得结果。

运行成功还需观察程序的返回状态和结果校验。对于 Add，关注输出是否满足逐元素相加，而不只是看是否生成了 `demo` 文件。
