本文的对应代码可在此处下载
http://download.youkuaiyun.com/detail/gh_home/9633641
cmake 命令与visual studio的对应
cmake | visual studio |
---|---|
PROJECT(name) | 解决方案名称 name |
ADD_EXECUTABLE(name ${SRC_LIST}) | 工程名称 生成exe名称 name |
设置cmake的编译器
- 首先使用 cmake -help获取cmake支持的编译器
- 运行 cmake -G “Visual Studio 12 2013 Win64” 设定好
外部构建
如果cpp文件和CmakeLists.txt文件在同一文件夹下,在此文件夹下运行
cmake .
这样所有cmake产生的编译文件都在此文件夹下,和我们的源文件混在一起,为了避免这种情况,我们需要在CmakeList文件夹下新建一个build文件夹,进入此文件夹,运行
cmake ..
这样,所有编译产生的文件都会在build文件夹下了
正规的源代码目录
- 所有的源代码文件放入src文件夹
- 生成的目标文件exe 放入bin文件夹
- 对于工程项目的接口及说明文件放入doc文件夹
- 对于项目所调用的外部lib文件放入lib文件夹
- 对于项目的功能性描述放入README.md
- 对于项目的exe的示例调用写一个.bat或者.sh文件放出来
- 写明CopyRight文件
- 对于项目的构建,文件结构,调用关系放在CmakeLists.txt中,以方便之后调用
- 附加: 其实还可以建立一个文件夹为build用于存放编译工程产生的中间文件,但是这个文件夹在发布的时候是要删除的
关于生成的visual studio项目结构
- 首先要配置管理器,要求这三个项目都生成
- 在我们的executable工程即OPENCV_CMAKE_EXE工程上右键,选择设为启动项目,这样ctr+F5就可以运行我们生成的exe了
- 以上三个项目的作用:我们可以通过点击解决方案OPENCV_CMAKE,查看项目依赖项,会发现:
- 所有的项目都会依赖于ZERO_CHECK这个项目
- ALL_BUILD会依赖所有的项目,这是为了我们在每一个execuable后都会生成一个项目,有时候我们更改了某几个项目,但是又不方便每次都记住是哪些项目发生了更改,这样我们就可以直接通过生成ALL_BUILD来更新所有的更改项目以及与更改有关的(附加依赖)的项目
将源码文件放在src文件夹编译怎么做?
首先,所有要编译的文件夹下都需要有一个CMakeLists.txt,因此我们这里会写两个CMakeLists.txt,一个用于CMake的工程,这个相当于所有cmake编译的入口,这个CMakeLists的标志就在于其会出现
PROJECT(NAME)
之后,主CMakeLists会调用各个子文件夹的CMakeLists,这些CMakeLists是怎么关联起来的呢?我认为是通过以主CMakeLists的相对路径通过ADD_SUBDIRECTORY命令来关联
ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
其中source_dir 为存放你要加入的CMakeLists的所在文件夹,binary_dir是可选的,这里指定source_dir 中的CMakeLists 编译输出(包含编译中间结果)路径为binary_dir。如果不进行 binary_dir目录的指定,那么编译结果(包括中间结果)都将存放在build/source_dir 目录(这个目录跟原有的 source_dir 目录对应),指定 binary_dir目录后,相当于在编译时将 source_dir 重命名为 binary_dir,所有的中间结果和目标二进制都将存放在 binary_dir目录。
以上是主CMakeLists中该写的内容,那么在source_dir 中用于编译源代码的CMakeLists该怎么写呢?事实上我们需要将source_dir 中的源代码编译成一个lib以便主CMakeLists的PROJECT调用。使用以下命令编译lib
SET(LIBHELLO_SRC hello.c)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
这样,我们就会在source_dir 中得到一个名为libhello.so的文件,如果我们想指定这个文件的生成位置,可以使用以下命令
SET(LIBRARY_OUTPUT_PATH <路径>)来指定一个新的位置
如果我们想要使用静态库,调用
ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})
将源文件编译为静态库是不够的,因为生成的文件可能与动态库文件重名,所以要不更改生成静态库的名字为hello_static,或者使用下述命令
ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
SET_TARGET_PROPERTIES,其基本语法是:
SET_TARGET_PROPERTIES(target1 target2 ...
PROPERTIES prop1 value1
prop2 value2 ...)
这个函数就是设置一些固有的property,其中还包括改变生成.so的版本号
我们如何调用src下编译好的lib来生成exe
1. 链接头文件
src文件夹下的.cpp文件和.h文件之间互相关联也是通过相对路径的,如果.cpp和.h都在src文件夹下,在.cpp中使用
#include"hello.h"
在cmake中是可以编译通过的,意味着在搜寻hello.h时,.cpp所在文件夹是默认的搜索路径
但是如果.h文件在另外一个文件夹,我们就需要增加寻找头文件的路径了,通过以下命令
INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
其中[AFTER|BEFORE]缺省,意味着后面添加的路径追加在已有路径之前还是之后。
使用示例
INCLUDE_DIRECTORIES(/usr/include/hello)
当然,如果头文件距离我们的源文件相对路径不远,我们也可以通过以下方式,上面那种方式很适合绝对路径,就是调用一个类似于OPENCV的库的时候
#include "include/hello.h"
2. 链接库文件
之前我们编译生成了libhello.so,现在我们要把这个库链入exe文件,我们使用TARGET_LINK_LIBRARIES
TARGET_LINK_LIBRARIES(target library1
<debug | optimized> library2
...)
链接动态库
TARGET_LINK_LIBRARIES(main libhello.so)
链接静态库
TARGET_LINK_LIBRARIES(main libhello.a)
这里的目标文件main为一个可执行文件
下面是一个使用cmake编译带有opencv库的示例
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
PROJECT(OPENCV_CMAKE)
SET(SRC_LIST main.cpp)
set (OpenCV_DIR D:/OpenCV/opencv2410/opencv/build) #这一句设置了OPENCV的目录地址
FIND_PACKAGE(OpenCV REQUIRED)
INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
ADD_EXECUTABLE(OPENCV_CMAKE_EXE ${SRC_LIST})
TARGET_LINK_LIBRARIES(OPENCV_CMAKE_EXE ${OpenCV_LIBS})
main.cpp
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
cv::Mat image = imread("test.jpg");
imshow("GH_HOME", image);
cv::waitKey();
}
编译结果如下
-- OpenCV ARCH: x64
-- OpenCV RUNTIME: vc12
-- OpenCV STATIC: OFF
-- Found OpenCV 2.4.10 in D:/OpenCV/opencv2410/opencv/build/x64/vc12/lib
-- You might need to add D:\OpenCV\opencv2410\opencv\build\x64\vc12\bin to your PATH to be able to run your applications.
-- Configuring done
-- Generating done
-- Build files have been written to: D:/MyDesign/code/CMake/OpenCVTemp/BUILD
这样的话直接运行生成的exe会出现确实OpenCV相关的DLL文件,所以设置上可以补充两点:
1. 在系统的环境变量Path中添加OpenCV的DLL所在目录
2. 在项目的属性-调试-环境 中添加OpenCV的DLL所在目录