学习linux之 cmake(1)
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。
CMake是一个比make更高级的编译配置工具,它可以根据不同平台、不同的编译器,生成相应的Makefile或者vcproj项目。 通过编写CMakeLists.txt,可以控制生成的Makefile,从而控制编译过程。
Cmake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然后再依一般的建构方式使用。CMake自动生成的Makefile不仅可以通过make命令构建项目生成目标文件,还支持安装(make install)、测试安装的程序是否能正确执行(make test,或者ctest)、生成当前平台的安装包(make package)、生成源码包(make package_source)、产生Dashboard显示数据并上传等高级功能,只要在CMakeLists.txt中简单配置,就可以完成很多复杂的功能,包括写测试用例。
如果有嵌套目录,子目录下可以有自己的CMakeLists.txt。
总之,CMake是一个非常强大的编译自动配置工具,支持各种平台,KDE也是用它编译的,感兴趣的可以试用一下。
一个高级程序从编写到被执行会经历哪些过程呢?
这个很简单,了解编译原理的同学都知道,高级程序最终是要被转化成机器理解的机器代码的,这样才能被机器理解执行。
这个过程可以粗略的分为 源代码(编译)-->目标代码(链接)--->可执行程序
在IDE环境下开发软件,我们只需编写好源文件、头文件、告诉IDE我们依赖的第三方头文件路径、库文件全路径,然后剩下的就交给IDE来完成这个所谓的转化过程。
这个转化过程其实可以用语言描述实现,独立于IDE环境之外。比如可以直接在linux终端用指令编译代码,然后再链接。当工程很简单的时候这样做无妨,然而,当工程变的庞大后,几十个乃至上百个cpp。特别是调试时,修改一个地方,还得把代码链接一遍,靠指令一个个去编译源代码就不现实了。而cmakelist就省事多了。
一个简单的cmakelist的编写
作为入门cmakelist,我写了一个简单的测试代码。
为了标准化,我采用out-of-source的方式来构建程序,使程序看起来清晰有条理。
工程目录
~learn_cmake2/
+src/
| |--cpp1.cpp
| |--cpp2.cpp
| |---main.cpp
+include/
| |---cpp1.h
| |---cpp2.h
+build/
+CMakeList
cpp1.h
#include<iostream> using namespace std; void print1();
cpp2.h
#include<iostream> using namespace std; void print2();
cpp1.cpp #include"cpp1.h" void print1() { cout<<"this is cpp1"<<endl; }
cpp2.cpp #include"cpp2.h" void print2() { cout<<"this is cpp2"<<endl; }
main.cpp #include<iostream> #include"opencv2/highgui/highgui.hpp" #include"cpp1.h" #include"cpp2.h" using namespace std; using namespace cv; int main() { Mat a=imread("cones.png",0); print1(); print2(); imshow("cones",a); cvWaitKey(0); }
至此,我们需要的几个简单的头文件和源文件已经编写好。
那么怎么描述本工程(learn_cmake)的编译过程呢?
---CMakeLists.txt #注意,字母大小写不能写错 project(learn_cmake2) #工程名 find_package(OpenCV 2.4.8 REQUIRED) # find_package可以被用来在系统中自动查找配置构建工程所需的程序库 # 其中REQUIRED表示如果没有找到,cmake会停止处理,并报告一个错误 #找到opencv 2.4.8后,变量OpenCV_INCLUDE_DIRS中将包括指定OpenCV库头文件的查找路径. #变量OpenCV_LIBRARY_DIRS中将包含指定Opencv库的.a或.so文件的所在目录的路径 include_directories( #头文件目录 ${PROJECT_SOURCE_DIR}/include #PROJECT_SOURCE_DIR 是系统变量 ${PROJECT_SOURCE_DIR}是cmakelist所在工程的路径 ${OpenCV_INCLUDE_DIRS} ) #一个工程有三种东西需要链接 #<1> 工程内除了maincpp以外的cpp生成的库 #<2>第三方的现有的库 #<3>maincpp生成可执行程序 set(src_list src/cpp1.cpp src/cpp2.cpp ) #设置变量 工程内除了maincpp以外的cpp 默认去工程目录下去寻找cpp add_library(cpp ${src_list}) #把工程内除了main函数以外的cpp生成一个库 target_link_libraries(cpp ${OpenCV_LIBS}) #链接第三方的库 add_executable(main src/main.cpp) #把main函数生成可执行程序 target_link_libraries(main cpp) #main函数链接这些库 MESSAGE(success)
通过这样一个文本就可以把编译链接过程描述清楚了。
那么,下面我们开始编译程序。
step1 进入工程目录下的build文件夹下 然后
cmake .. 注:cmake ..的意思是去上层目录寻找cmakelist
step2 cmake 过后,你会看到build目录下生成makefile文件,那么现在你可以 执行这句话
make
step3 make过后就会生成一个名字为main可执行程序,输入
./main
便可以执行代码。