使用cmake编译ucos Iii
最近下载了 Linux Simulation 版 uCOS-III 的源代码,但这只是纯代码,需要自己编译。以前单位编译操作系统都是自己编写 Makefile ,如果目录、文件比较多则编写 Makefile 比较麻烦,所以我就考虑使用 cmake 自动生成 Makefile ,刚巧前不久在编译应用的时候就使用了 cmake ,现在刚好可以深入使用 cmake 了。
从官网下载源代码需要注册、登陆,我已经把可以编译的系统源代码上传到了 github 上了,可以直接在 ubuntu 16.04 x64 系统上编译,配合 gcc 5.4 和 cmake 3.5.1 使用(其它版本应该也没问题,不过没做实验)。
下载的 Linux Simulation uCOS-III 的代码是可以直接作为 eclipse 工程使用(工程文件位于 ` `),使用 eclipse 导入工程然后就可以编译、运行,它直接使用 makefile 编译。接下来我们就要使用 cmake 编译 uCOS 了。
cmake 有自己的语法来生成 makefile 。要用到的包括设置编译器和参数、头文件路径、源码路径、库文件等。
-
第一步,分析代码的结构,准备如何编写 cmake 脚本。
下载好的 uCOS 的代码结构如下:
➜ Micrium tree . ├── Examples │ └── POSIX │ └── GNU │ └── OS3 │ ├── app.c │ ├── app_cfg.h │ ├── cpu_cfg.h │ ├── eclipse-GCC │ ├── lib_cfg.h │ ├── os_app_hooks.c │ ├── os_app_hooks.h │ ├── os_cfg_app.h │ └── os_cfg.h ├── Micrium POSIX Readme.pdf └── Software ├── uC-CPU │ ├── cpu_cache.h │ ├── cpu_core.c │ ├── cpu_core.h │ ├── cpu_def.h │ └── Posix │ └── GNU │ ├── cpu_c.c │ └── cpu.h ├── uC-LIB │ ├── lib_ascii.c │ ├── lib_ascii.h │ ├── lib_def.h │ ├── lib_math.c │ ├── lib_math.h │ ├── lib_mem.c │ ├── lib_mem.h │ ├── lib_str.c │ └── lib_str.h └── uCOS-III ├── Ports │ └── POSIX │ └── GNU │ ├── os_cpu_c.c │ └── os_cpu.h └── Source ├── os_cfg_app.c ├── os_core.c ├── os_dbg.c ├── os_flag.c ├── os.h ├── os_int.c ├── os_mem.c ├── os_mon.c ├── os_msg.c ├── os_mutex.c ├── os_pend_multi.c ├── os_prio.c ├── os_q.c ├── os_sem.c ├── os_stat.c ├── os_task.c ├── os_tick.c ├── os_time.c ├── os_tmr.c ├── os_type.h └── os_var.c
系统代码明显可以分为两部分
Examples
和Software
,后者是单纯的系统代码、libc 库,以及处理器框架代码,也就是说这部分代码和实际的硬件是无关的,arm 版 、 ppc 版等各个版本的这部分代码都是一样的,而前者则包含了测试程序和硬件相关代码。所以我就以Examples
为主代码(main()
入口)开始编译。 -
第二步,为各个源码目录编写 cmake 脚本,脚本名均为
CMakeLists.txt
。编写好的 cmake 脚本列表如下:
├── CMakeLists.txt ├── Examples │ └── POSIX │ └── GNU │ └── OS3 └── Software ├── uC-CPU │ ├── CMakeLists.txt │ └── Posix │ └── GNU │ └── CMakeLists.txt ├── uC-LIB │ └── CMakeLists.txt └── uCOS-III ├── CMakeLists.txt1 ├── Ports │ └── POSIX │ └── GNU │ └── CMakeLists.txt └── Source └── CMakeLists.txt
因为
Examples
是我们的主代码,所以这个目录下没有CMakeLists.txt
, 主目录下的CMakeLists.txt
负责编译Example
的代码。各个子目录的CMakeLists.txt
内容类似,以uCOS-III/Source
为例:AUX_SOURCE_DIRECTORY(. LIBOS3_SRC) INCLUDE_DIRECTORIES(/workspace/repos/github/rtos/ucos/Micrium/Software/uC-CPU) INCLUDE_DIRECTORIES(/workspace/repos/github/rtos/ucos/Micrium/Software/uC-LIB) INCLUDE_DIRECTORIES(/workspace/repos/github/rtos/ucos/Micrium/Software/uCOS-III/Ports/POSIX/GNU) INCLUDE_DIRECTORIES(/workspace/repos/github/rtos/ucos/Micrium/Examples/POSIX/GNU/OS3) INCLUDE_DIRECTORIES(../../uC-CPU) INCLUDE_DIRECTORIES(../../uC-CPU/Posix/GNU) add_library(libos1 ${LIBOS3_SRC})
这部分脚本有三个意思:
AUX_SOURCE_DIRECTORY
将目录下的代码列表赋给LIBOS3_SRC
;INCLUDE_DIRECTORIES
指定了头文件引用路径 ;add_library
将源代码添加到名为libos1
的静态库。
其它目录下的
CMakeLists.txt
内容也就这些了。根目录下的
CMakeLists.txt
就比较复杂,首先定义了工程名和使用的 cmake 版本要求:PROJECT (USOS3) CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
然后设置编译选项,并且指定使用
Debug
版的选项:SET(CMAKE_C_FLAGS_DEBUG "$ENV{CFLAGS} -static -O0 -g3 -Wall -fmessage-length=0 ") #set debug mode c flags SET(CMAKE_C_FLAGS_RELEASE "$ENV{CFLAGS} -O3 -Wall ") #set release mode c flags SET(CMAKE_BUILD_TYPE "Debug") #set Debug or Release
接着定义头文件、子目录路径(注意,子目录路径不要包含
Examples
)和Examples
的源码:INCLUDE_DIRECTORIES(/workspace/repos/github/rtos/ucos/Micrium/Examples/POSIX/GNU/OS3) ... ADD_SUBDIRECTORY(Software/uC-CPU/Posix/GNU) ... AUX_SOURCE_DIRECTORY(./Examples/POSIX/GNU/OS3 LIBSIM_SRC)
最后编译
Examples
并将由各个子目录编译的的库文件链接进来,生成可执行文件:ADD_EXECUTABLE(${TARGET_EXE_Z} ${LIBSIM_SRC}) #生成可执行文件 TARGET_LINK_LIBRARIES(${TARGET_EXE_Z} libos1) #链接库文件 TARGET_LINK_LIBRARIES(${TARGET_EXE_Z} pthread) ...
注意一点,在 Linux 上运行 ucos 要用到 pthread 库,所以一定要将 pthread 添加到链接库中。
-
第三步,编译 uCOS。 直接在代码目录使用 cmake 编译的话会生成很多临时文件,不好清理,cmake 官方也没提供有效的办法清理这些临时文件,所以需要使用源码外编译(out of source builds)。在根目录创建一个
build
目录,然后在该目录下执行cmake ..
即可完成编译,之后只要删除了该目录就可以清理全部临时文件了,而我的则编写了一个简单脚本build.sh
来执行编译:rm -rf ./build/* cd build cmake .. make VERBOSE=0
最后,执行脚本
sh build.sh
就可以完成编译了,会在build
目录下生成ucos
可执行文件(注:我使用的这个版本并不运行在开发板上,而是在 Linux 上运行的的一个仿真器,对操作系统来说就是一个特殊点的 ELF 可执行文件。)。运行 ucos 要注意,因为需要将 RTPRIO 设置为 unlimited ,所以需要在 root 用户下运行ulimit -r unlimited
解除限制,然后再执行 ucos./build/ucos
。