版权声明:本文为博主原创文章,未经博主允许不得转载。
Cmakelists.txt是作为Cmake building system的输入文件,用于构建软件包。
一、CmakeList.txt的简单例子
cmake_minimum_required(VERSION2.8 FATAL_ERROR)
#set(project_namecloud_viewer_PointXYZ)
project(project_name)
find_package(PCL1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (project_name cloud_viewer_PointXYZ.cpp) #注意这里不能替换
target_link_libraries(project_name ${PCL_LIBRARIES})
二、解析
CmakeLists.txt的重要组成部分:
1、表明Cmake所需要的最低版本
cmake_minimum_required(VERSION2.8 FATAL_ERROR)
2、定义需要的特殊变量(optional)(关于set的用法我目前没有细看,有心的同学自己钻研)
SET(sampleName MyApp)
如上面的例子:set(project_name cloud_viewer_PointXYZ).
3、查找我们构建工程所需要的package
find_package(PCL 1.2 REQUIRED) #主要依赖的package
#REQUIRED表示如果没有找到,cmake会停止处理,并报告一个错误. 如果找到了package那么将会生成几个包含package信息的Cmake环境变量,这些变量将会在后面的cmakescript中用到。这些环境变量描述了package的外部头文件位置(include路径),依赖的库文件的位置(lib),以及源程序的位置。例如上面命令执行找到PCL后,将会创建环境变量PCL_INCLUDE_DIRS其中包含指定PCL库头文件.h的查找路径;创建环境变量PCL_LIBRARY_DIRS,其中包含指定PCL库的.lib文件的所在目录的路径.
如果所要构建的project还依赖于其它的package,例如python那么可以采用命令:
find_package(PCL 1.2 REQUIRED COMPONENTS python),
此时python将作为PCLpackage的组成成分,它所对应的头文件include路径和lib库文件路径都将被一起包含在PCL的对应环境变量PCL_INCLUDE_DIRS和PCL_LIBRARY_DIRS中,方便后面使用。
4、指定构建project所需要的资源
include_directories(${PCL_INCLUDE_DIRS})#包含头文件的位置
link_directories(${PCL_LIBRARY_DIRS})#添加链接器的lib库文件路径
add_definitions(${PCL_DEFINITIONS})
除此之外也可以手动添加特殊路径如:
include_directories("G:/Matlab/extern/include")
include_directories("C:/Program Files/MobileRobots/Aria/include")
link_directories("G:/Matlab/extern/lib/win32/microsoft")
link_directories("C:/Program Files/MobileRobots/Aria/lib")
5、从指定源文件构建可执行文件
add_executable (project_name cloud_viewer_PointXYZ.cpp)
该命令将从源文件cloud_viewer_PointXYZ.cpp构建可执行程序project_name.exe.
如果从多个源文件构建可执行程序则可以表示成:
add_executable (project_namemain.cpp test1.cpp test2.cpp)
add_executable (project_namemain.cpp part.h grab.h interface.h test.cpp test.h)
6、为project构建library
add_library(${project_name} ${${project_name}_src})#默认创建共享library
7、指定可执行文件需要连接的库
target_link_libraries (project_name ${PCL_LIBRARIES})#前一个参数为可执行文件的名字
target_link_libraries (project_name ${PCL_LIBRARIES} libeng.lib libmx.lib libmex.lib libmat.lib Aria.lib winmm.libwsock32.lib)
TARGET_LINK_LIBRARIES(
${project_name}
${MRPT_LIBS} # This is filled byFIND_PACKAGE(MRPT ...)
"" # Optional extra libs...
)
版权声明:本文为博主原创文章,未经博主允许不得转载。
CmakeLists.txt
######## A simple cmakelists.txt file for OpenCV() #############
cmake_minimum_required(VERSION 2.8)
PROJECT(ShowImage)
FIND_PACKAGE( OpenCV REQUIRED )
INCLUDE_DIRECTORIES( #包含目录
${ShowImage_SOURCE_DIR}
)
ADD_EXECUTABLE(ShowImage ShowImage.cpp)
TARGET_LINK_LIBRARIES (ShowImage ${OpenCV_LIBS} ) #这两行的次序也不能变!
# ########## end ####################################
上面示例文件中, 为了使添加的两行查找OpenCV库的指令正常工作,需要如下操作:
1). 添加系统变量: OpenCV_DIR = d:\OpenCV2.3\bulid\ (cmake使用此变量获得OpenCV的安装位置.)
2). 在OpenCV_DIR下存在配置文件 OpenCVConfig.cmake.
( 缺省安装中只有OpenCVConfig.cmake.in文件, 当使用cmake编译OpenCV后,
会根据上述的.cmake.in文件产生对应的 OpenCVConfig.cmake文件.)
3). 检查 OpenCVConfig.cmake 中的路径变量是否正确, 并做修改后保存.
与INCLUDE路径相关的变量: OpenCV_INCLUDE_DIRS
与LIB路径相关的变量: OpenCV_LIB_DIR
http://blog.csdn.net/dbzhang800/article/details/6314073
版权声明:本文为博主原创文章,未经博主允许不得转载。
目录(?)[+]
看来不学习一下cmake是不行了,一点一点来吧,找个最简单的C程序,慢慢复杂化,试试看:
例子一 |
单个源文件 main.c |
例子二 |
==>分解成多个 main.c hello.h hello.c |
例子三 |
==>先生成一个静态库,链接该库 |
例子四 |
==>将源文件放置到不同的目录 |
例子五 |
==>控制生成的程序和库所在的目录 |
例子六 |
==>使用动态库而不是静态库 |
一个经典的C程序,如何用cmake来进行构建程序呢?
//main.c #includeint main() { printf("Hello World!/n"); return 0; }
编写一个 CMakeList.txt 文件(可看做cmake的工程文件):
project(HELLO) set(SRC_LIST main.c) add_executable(hello ${SRC_LIST})
然后,建立一个任意目录(比如本目录下创建一个build子目录),在该build目录下调用cmake
cmake .. -G"NMake Makefiles" nmake
或者
cmake .. -G"MinGW Makefiles" make
即可生成可执行程序 hello(.exe)
目录结构
+ | +--- main.c +--- CMakeList.txt | /--+ build/ | +--- hello.exe
cmake 真的不太好用哈,使用cmake的过程,本身也就是一个编程的过程,只有多练才行。
我们先看看:前面提到的这些都是什么呢?
第一行 project 不是强制性的,但最好始终都加上。这一行会引入两个变量
同时,cmake自动定义了两个等价的变量
PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR
因为是out-of-source方式构建,所以我们要时刻区分这两个变量对应的目录
可以通过message来输出变量的值
message(${PROJECT_SOURCE_DIR})
set 命令用来设置变量
add_exectuable 告诉工程生成一个可执行文件。
add_library 则告诉生成一个库文件。
cmake 命令后跟一个路径(..),用来指出 CMakeList.txt 所在的位置。
由于系统中可能有多套构建环境,我们可以通过-G来制定生成哪种工程文件,通过 cmake -h 可得到详细信息。
要显示执行构建过程中详细的信息(比如为了得到更详细的出错信息),可以在CMakeList.txt内加入:
或者执行make时
或者
一个源文件的例子一似乎没什么意思,拆成3个文件再试试看:
#ifndef DBZHANG_HELLO_ #define DBZHANG_HELLO_ void hello(const char* name); #endif //DBZHANG_HELLO_
#include#include "hello.h" void hello(const char * name) { printf ("Hello %s!/n", name); }
#include "hello.h" int main() { hello("World"); return 0; }
project(HELLO) set(SRC_LIST main.c hello.c) add_executable(hello ${SRC_LIST})
执行cmake的过程同上,目录结构
+ | +--- main.c +--- hello.h +--- hello.c +--- CMakeList.txt | /--+ build/ | +--- hello.exe
例子很简单,没什么可说的。
接前面的例子,我们将 hello.c 生成一个库,然后再使用会怎么样?
改写一下前面的CMakeList.txt文件试试:
project(HELLO) set(LIB_SRC hello.c) set(APP_SRC main.c) add_library(libhello ${LIB_SRC}) add_executable(hello ${APP_SRC}) target_link_libraries(hello libhello)
和前面相比,我们添加了一个新的目标 libhello,并将其链接进hello程序
然后想前面一样,运行cmake,得到
+ | +--- main.c +--- hello.h +--- hello.c +--- CMakeList.txt | /--+ build/ | +--- hello.exe +--- libhello.lib
里面有一点不爽,对不?
添加一行
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
就可以了
在前面,我们成功地使用了库,可是源代码放在同一个路径下,还是不太正规,怎么办呢?分开放呗
我们期待是这样一种结构
+ | +--- CMakeList.txt +--+ src/ | | | +--- main.c | /--- CMakeList.txt | +--+ libhello/ | | | +--- hello.h | +--- hello.c | /--- CMakeList.txt | /--+ build/
哇,现在需要3个CMakeList.txt 文件了,每个源文件目录都需要一个,还好,每一个都不是太复杂
project(HELLO) add_subdirectory(src) add_subdirectory(libhello)
include_directories(${PROJECT_SOURCE_DIR}/libhello) set(APP_SRC main.c) add_executable(hello ${APP_SRC}) target_link_libraries(hello libhello)
set(LIB_SRC hello.c) add_library(libhello ${LIB_SRC}) set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
恩,和前面一样,建立一个build目录,在其内运行cmake,然后可以得到
回头看看,这次多了点什么,顶层的 CMakeList.txt 文件中使用 add_subdirectory 告诉cmake去子目录寻找新的CMakeList.txt 子文件
在 src 的 CMakeList.txt 文件中,新增加了include_directories,用来指明头文件所在的路径。
前面还是有一点不爽:如果想让可执行文件在 bin 目录,库文件在 lib 目录怎么办?
就像下面显示的一样:
+ build/ | +--+ bin/ | | | /--- hello.exe | /--+ lib/ | /--- hello.lib
project(HELLO) add_subdirectory(src bin) add_subdirectory(libhello lib)
不是build中的目录默认和源代码中结构一样么,我们可以指定其对应的目录在build中的名字。
这样一来:build/src 就成了 build/bin 了,可是除了 hello.exe,中间产物也进来了。还不是我们最想要的。
src/CMakeList.txt 文件
include_directories(${PROJECT_SOURCE_DIR}/libhello) #link_directories(${PROJECT_BINARY_DIR}/lib) set(APP_SRC main.c) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) add_executable(hello ${APP_SRC}) target_link_libraries(hello libhello)
libhello/CMakeList.txt 文件
set(LIB_SRC hello.c) add_library(libhello ${LIB_SRC}) set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
在例子三至五中,我们始终用的静态库,那么用动态库应该更酷一点吧。 试着写一下
如果不考虑windows下,这个例子应该是很简单的,只需要在上个例子的 libhello/CMakeList.txt 文件中的add_library命令中加入一个SHARED参数:
add_library(libhello SHARED ${LIB_SRC})
可是,我们既然用cmake了,还是兼顾不同的平台吧,于是,事情有点复杂:
#ifndef DBZHANG_HELLO_ #define DBZHANG_HELLO_ #if defined _WIN32 #if LIBHELLO_BUILD #define LIBHELLO_API __declspec(dllexport) #else #define LIBHELLO_API __declspec(dllimport) #endif #else #define LIBHELLO_API #endif LIBHELLO_API void hello(const char* name); #endif //DBZHANG_HELLO_
set(LIB_SRC hello.c) add_definitions("-DLIBHELLO_BUILD") add_library(libhello SHARED ${LIB_SRC}) set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
恩,剩下来的工作就和原来一样了。