1.安装Cmake
在ubuntu的终端下使用如下命令:
sudo apt-get install cmake
2.创建好自己的项目
例如项目组成如下:
|-bin
|-build
|-include
|- -程序头文件
|-src
|- -程序源文件
|-CMakeLists.txt
其中,bin文件夹存放项目最终输出的elf可执行文件,build文件夹存放生成的对象文件,include文件夹存放项目中程序的.h头文件,src文件夹存放项目中程序的.c源文件,CMakeLists.txt为下一步需要编写的cmake脚本文件
3.编写CMakeLists.txt文件
在项目中创建并编写CMakeLists.txt,命令如下:
touch CMakeLists.txt
编写信息如下:
cmake_minimum_required (VERSION 3.5)
project (demo)
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
aux_source_directory (src SRC_LIST)
include_directories (include)
add_executable (main ${SRC_LIST})
其中:
第一行意思是表示我们cmake的最低版本要求是2.8,我电脑安装的是3.5.1;
第二行是表示本工程信息,也就是工程名叫demo
第三行把存放elf文件的位置设置为工程根目录下的bin目录
note:
EXECUTABLE_OUTPUT_PATH为CMake自带的预定义变量,表示目标二进制可执行文件的存放位置
PROJECT_SOURCE_DIR一样,在cmake中表示工程的根目录
cmake中变量使用${}方式取值。
第四行使用aux_source_directory命令把指定目录下的源文件列表存放到变量SRC_LIST里
note:
aux_source_directory()会把指定目录下的所有源文件都加进来,可能会加入一些我们不需要的文件,此时我们可以使用set命令去新建变量来存放需要的源文件,如下:
set( SRC_LIST
./main.c
./func1.c
./func2.c)
第五行使用include_directories命令向工程添加多个指定头文件的搜索路径
第六行比较关键,表示最终要生成的elf文件的名字叫main,使用的源文件是main.c
4.运行cmake生成Makefile文件
使用外部编译方式编译项目,项目终端输入命令:
cd build //进入目录build
cmake .. //运行cmake命令
第二行命令使cmake检测编译环境,并在bulid文件夹生成相应的Makefile文件和运行中产生的中间文件。“…”代表父目录,因为CMakeLists.txt文件存在于父目录。
5.使用make命令编译程序
输入命令:
make
运行命令make进行编译。编译后,生成的所有中间文件在build目录下。由于我们修改可执行文件的存放位置为项目的bin文件夹,因此make命令最终生成的elf文件在bin文件中。
如果要清除生成的elf文件,使用命令:
make clean
6.运行elf文件
使用命令:
./文件名
7.cmake中动态库和静态库的编译控制
在项目中当我们写好自己的程序且无需修改时,别人需要调用我们写好的程序,我们只需要把写好的程序编译出静态库或动态库。因为静态库只在链接的时候才进行,可以减少他人编译程序时的时间。
动态库文件扩展名常为 “.so”; 静态库文件扩展名常为 “.a”,我们通常希望静态库和动态库文件名保持一致,只是扩展名不同。
eg:文件树如下
CMakeLists.txt信息如下:
cmake_minimum_required (VERSION 3.5)
project (demo)
set(SRC_LIST ${PROJECT_SOURCE_DIR}/src/testFunc.c)
add_library(testFunc_shared SHARED ${SRC_LIST})
add_library(testFunc_static STATIC ${SRC_LIST})
set_target_properties(testFunc_shared PROPERTIES OUTPUT_NAME "testFunc")
set_target_properties(testFunc_static PROPERTIES OUTPUT_NAME "testFunc")
include_directories(${PROJECT_SOURCE_DIR}/include)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
cmake中动态库和静态库的编译控制命令如下:
add_library (func_shared SHARED ${SRC_LIST}) //生成动态库
add_library (func_static STATIC ${SRC_LIST}) //生成静态库
add_library函数用以生成动态库或静态库(第1个参数指定库的名字;第2个参数决定是动态库还是静态库,如果没有就默认为静态;第3个参数指定生成库的源文件)
注:
上面提到静态库和动态库文件名通常保持一致,但add_library函数中库的名字不能够和其他文件重名的。因此需要添加“_shared”或“_static”,然后使用set_target_properties函数设置库输出的名称。命令如下:
set_target_properties (testFunc_shared PROPERTIES OUTPUT_NAME "func")
set_target_properties (testFunc_static PROPERTIES OUTPUT_NAME "func")
这样,我们就可以同时得到 func.so和func.a 两个库了。
然后指定cmake编译后库的存放路径,命令如下:
set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
LIBRARY_OUTPUT_PATH为库文件的默认输出路径,这里设置为工程目录下的lib目录。
8.cmake中库的链接
eg:文件树如下
CMakeLists.txt信息如下:
cmake_minimum_required (VERSION 3.5)
project (demo)
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
set (SRC_LIST ${PROJECT_SOURCE_DIR}/src/main.c)
include_directories (${PROJECT_SOURCE_DIR}/testFunc/inc)
add_executable (main ${SRC_LIST})
target_link_libraries (main ${PROJECT_SOURCE_DIR}/testFunc/lib/libtestFunc.so)
target_link_libraries()函数把目标文件与库文件进行链接,这里采用了绝对路径方式。