VxWorks 的编译体系与标准的 Linux/Windows C 编译(如 gcc)有很大不同,它不是一个简单的命令行工具,而是一个集成在开发环境(IDE)中的、基于 Tornado 或 Workbench 的、针对特定目标板(BSP)的交叉编译系统。

核心概念是交叉编译:在你的宿主机(通常是 x86 架构的 Linux 或 Windows PC)上,使用 VxWorks 提供的工具链,编译出能在目标机(如 ARM, PowerPC, MIPS 等架构的嵌入式板卡)上运行的代码。
下面我将从几个方面为你详细拆解这个过程:
核心概念与工具
在开始编译之前,你必须理解以下几个关键角色:
| 角色 | 描述 | 常见工具/文件 |
|---|---|---|
| 宿主机 | 你进行开发和编译的计算机,如运行 Windows 或 Linux 的 PC。 | - |
| 目标机 | 运行 VxWorks 操作系统的嵌入式硬件设备。 | - |
| 交叉编译器 | 在宿主机上运行,但能生成目标机可执行代码的编译器。 | diab, gcc (VxWorks 提供的特定版本) |
| BSP (Board Support Package) | 板级支持包,包含了驱动程序、启动代码、以及编译目标机代码所需的所有配置文件(如 config.h, Makefile)。BSP 是连接你的代码和硬件的桥梁。 |
bsp_name |
| VxWorks 映像 | 最终下载到目标机上运行的 VxWorks 内核,它可以是单内核,也可以是包含用户模块的完整系统。 | vxWorks, vxWorks.st |
| 下载工具 | 将编译好的代码或映像下载到目标机的工具。 | windsh, target server |
编译流程概述
VxWorks 的编译流程通常遵循以下步骤:

- 环境准备:安装并配置好 VxWorks 开发环境(如 Wind River Workbench)。
- 创建或选择项目:在 Workbench 中创建一个新的 C 项目,或者选择一个现有的 BSP 示例项目。
- 编写 C 代码:创建
.c源文件。 - 编写或修改 Makefile:告诉构建系统如何编译你的代码。
- 执行构建:在 Workbench 中点击 "Build" 按钮,或者在命令行中使用
make。 - 下载与调试:将编译生成的模块或映像下载到目标机,并使用
windsh或调试器进行测试。
两种主要的编译方式
在 VxWorks 中,你有两种主要的方式来编译和运行你的 C 代码:
编译为可下载内核模块
这是最常用、最灵活的方式,尤其适合开发和调试独立的驱动、算法或应用程序。
- 特点:
- 编译出的文件是
.out格式的目标文件。 - 这个文件不是独立的可执行文件,它需要 VxWorks 内核在运行时通过
ld(Loadable Module) 命令动态加载。 - 修改代码后,无需重新编译整个庞大的 VxWorks 内核,只需重新编译你的模块并重新加载即可,大大缩短了开发-测试循环。
- 编译出的文件是
- 适用场景:设备驱动、独立的业务逻辑库、应用程序。
编译并集成到 VxWorks 内核中
这种方式用于修改内核本身或编写必须在内核启动时就初始化的关键代码。
- 特点:
- 你的 C 代码会直接被编译进 VxWorks 内核映像(如
vxWorks)。 - 修改代码后,必须重新编译整个 VxWorks 内核,这个过程非常耗时。
- 代码在内核启动时自动运行,无需手动加载。
- 你的 C 代码会直接被编译进 VxWorks 内核映像(如
- 适用场景:修改内核调度算法、添加核心系统调用、编写必须在系统最早期初始化的硬件驱动。
详细步骤:编译一个可下载模块 (以 Workbench 为例)
这是最常见的实践,我们将以此为例。

步骤 1: 创建 Workbench 项目
- 打开 Wind River Workbench。
- 选择
File -> New -> Project...。 - 在向导中,选择
C/C++ -> Project from Template。 - 选择
VxWorks Kernel Module或Vxworks User Application模板,对于简单的 C 程序,后者更合适。 - 输入项目名称(
my_app),并选择一个已存在的 BSP作为目标配置,BSP 的选择至关重要,因为它决定了编译的目标架构和库。 - 点击 "Finish"。
Workbench 会自动为你生成一个包含 Makefile 和示例源文件(如 main.c)的项目结构。
步骤 2: 编写你的 C 代码
在项目中创建一个新的 C 文件,hello.c。
// hello.c
#include <stdio.h>
#include <vxWorks.h>
void hello_task(int arg)
{
while (1) {
printf("Hello from VxWorks! Task ID: %d\n", taskIdSelf());
taskDelay(sysClkRateGet() * 2); // Delay for 2 seconds
}
}
步骤 3: 理解并修改 Makefile
Workbench 生成的 Makefile 已经为你处理了大部分复杂性,你只需要关注一些关键变量。
打开项目根目录下的 Makefile,你会看到类似这样的内容:
# ... (其他自动生成的变量) # 定义你的 C 源文件 SRCS = hello.c main.c # 定义你的模块名称 MODULE_NAME = my_app # ... (更多自动生成的规则)
SRCS:列出所有需要编译的 C 源文件,将你的hello.c添加到这里。MODULE_NAME:定义最终生成的.out文件的名字。my_app.out。
如果你没有使用 Workbench,而是手动编译,你需要编写一个类似的 Makefile,VxWorks 的 BSP 目录下有很多示例 Makefile 可以参考。
步骤 4: 构建项目
- 在 Workbench 的 Project Explorer 中右键点击你的项目。
- 选择
Build Project。
Workbench 会调用底层的 make 工具,并根据 Makefile 的规则进行编译、链接,编译成功后,你会在项目的 build/<bsp_name>/ 目录下找到生成的 my_app.out 文件。
步骤 5: 下载并运行
-
连接目标机:确保你的目标板已经通过网线或串口连接到宿主机,Workbench 能够通过 Target Server 连接到它。
-
打开
windsh:在 Workbench 的 "Target" 视图中,右键点击你的目标连接,选择 "Shell",这将打开一个windsh控制台。 -
加载模块:在
windsh中使用ld命令加载你的模块。-> ld < /path/to/your/project/build/<bsp_name>/my_app.out
如果加载成功,你会看到类似
0xxxxxxxx的返回值,这是模块加载到内存的地址。 -
运行代码:如果你的代码中创建了任务(如上面的
hello_task),你需要启动它,模块的初始化函数(如果定义了INIT_MODULE宏)会在加载时自动执行,如果没有,你需要手动调用。假设你的
main.c中有如下代码来创建任务:// main.c #include <vxWorks.h> #include <taskLib.h> void hello_task(int arg); void my_app_init() { taskSpawn("tHello", 100, 0, 2000, (FUNCPTR)hello_task, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); }并且你在 Makefile 中定义了初始化函数:
# ... USERINIT_C = my_app_init.c # 或者直接在这里定义 # ...
加载模块后,任务就会自动创建并运行,你会在
windsh的控制台(如果目标机的 stdout 重定向到了 shell)或串口终端上看到 "Hello from VxWorks!" 的打印信息。
命令行编译方式 (高级)
虽然 Workbench 是主流,但了解命令行编译对于理解底层原理和自动化脚本编写很有帮助。
-
设置环境变量: 在编译前,你必须先设置 VxWorks 的开发环境,通常在 VxWorks 安装目录的
wrenv.sh(Linux) 或wrenv.bat(Windows) 脚本中完成。# Linux source /opt/windriver/wrenv.sh -p vxworks-7
-
进入项目目录:
cd /path/to/your/project -
执行 make: 直接调用
make,它会自动查找当前目录下的Makefile并执行。make
命令行编译的 Makefile 规则与 Workbench 内部使用的规则基本一致,但需要你手动处理更多的路径和依赖关系。
总结与常见问题
| 问题 | 可能原因与解决方案 |
|---|---|
编译错误:undefined reference to 'xxx' |
函数未定义:检查函数拼写和声明。 2. 链接顺序问题:确保包含函数定义的源文件在 SRCS 列表中。 3. 库文件未链接:如果使用了外部库,需要在 Makefile 的 LDLIBS 变量中添加。 |
编译错误:cannot find <vxWorks.h> |
包含路径错误:在 Makefile 的 CFLAGS 中检查 -I 路径是否正确指向了 VxWorks 的头文件目录。 2. BSP 选择错误:确保你选择了正确的 BSP,因为 BSP 的 config.h 和头文件路径至关重要。 |
下载模块失败:Bad magic number |
架构不匹配:你为 ARM 编译的模块试图在 PowerPC 目标机上运行,检查 BSP 架构设置。 2. 工具链版本错误:宿主机上的编译器版本与目标机所需的版本不兼容。 |
windsh 中 ld 命令找不到文件 |
文件路径错误,确保 ld 命令中的路径是目标机文件系统上的路径,或者你可以先将 .out 文件拷贝到目标机的 TFTP 目录(如 /tftpboot),然后使用 ld < my_app.out。 |
VxWorks 的 C 语言编译是一个围绕 BSP 和 交叉工具链 构建的系统,对于初学者,强烈建议从 Wind River Workbench 开始,它能极大地简化项目配置、编译和调试的复杂性,理解了模块化编译和内核编译的区别,以及 Makefile 的作用,你就掌握了 VxWorks 开发的核心。
