cmake学习


本工程需要,查阅海量资料,大同小异。此文参考甚多,略显杂乱,亦有本人心得。
是为记录,他日细阅...

 cmake学习
~cmake跨平台,工具只需cmake和make
~如果工程比较小,直接用makefile就可以了
~c/c++/java之外的文件就不需要用了
~qt编程有qmake
~如果是比较完整的IDE,也不需要

示例:
1. 首先建立一个文件夹cmake,在mkdir t1,在t1下建立main.c和CMakeLists.txt
2. main.c就是一个简单的helloworld程序。CMakeLists.txt内容:
project(hello)
set(SRC_LIST main.c)
message(STATUS "this is binary dir" ${hello_BINARY_DIR}")
message(STATUS "this is source dir" ${hello_SOURCE_DIR}")
add_executable(hello SRC_LIST)
3. 执行cmake .会生成makefile, 再执行make就行了。如果要看到make的构建过程,make VERBOSE=1或者VERBOSE=1

语法:
1. project(name [CXX] [C] [Java])
可以指定工程支持的语言,默认支持所有语言,此时隐式定义了两个路径:name_BINARY_DIR和name_SOURCE_DIR
同时预定义了PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR两者(编译发生的当前目录)意思一样

2.set(var value)
定义变量,如果有多个,可以set(SRC_LIST main.c ti.c t2.c)

3.message([...] "str")
输出用户定义的信息,str中如果有空格就必须用"",也可以输出变量名。[...]中有三个选项可选:
SEND_ERROR,产生错误,生成过程被跳过
SARUS, 输出前缀为-的信息
FATAL_ERROR,立即终止所有cmake过程

4. add_executable()

5. 变量定义${}后引用,如果在if语句中,就不需要这个结构了

6. 指令大小写无关,参数和变量大小写有关

7.特别解释:作为工程名的hello和生成的可执行文件hello是没有任何关系的

8.可以忽略source列表中的源文件后缀,如:
add_executable(hello main t1)
add_executalbe(hello main.c; t1.c)都可以
如果不得,在cmake的时候会提示错误

9. 清理工程
make clean

10. in-source build和out-of-source build

11. add_subdirectory(source_dir [binary_dir] [execlude_from_all])
向当前工程中添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置, 后一个是排除的目录。

改进:
1. 添加如下文件夹:src(存放源代码), doc(hello.txt), COPYRIGHT, README, runhello.sh(调用脚本), bin(构建后的目标文件). 另外安装文件hello和runhello.sh安装到/usr/bin, doc目录及内容及安装到/usr/shar/doc/cmake/t2(自己建立的文件夹)

2. 在src中建立CMakeLists.txt: add_executable(hello main.c), 根目录中的CMakeLists.txt中内容:project(hello)
                                  add_subdirectory(src bin) #指定在哪,就生成在哪,否则在本目录下
然后建立build目录,进入,cmake .. ; make
如果不进行bin目录指定,那么生成的就在build/src目录中

3. 换个地方保存二进制文件
可以通过EXECUTABLE_OUTPUT_PATH和LIBRARY_OUTPUT_PATH变量来指定最终的目标二进制的位置,如:
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)




A.源代码在哪里?
B.头文件在哪里?
C.怎么生成静态或者动态库?
D.程序链接的静态库在哪里?
E.如果工程的代码存放在很多地方,那又该怎么找到它们呢?
 
1. 对于一个工程,应该有的文件夹:src, bin, include, lib, build, CMakeLists.txt. cd到build下,执行cmake .. 将生成CMakeCache.txt Makefile cmake_install.cmake hello(目标文件). 此处的makefile可以直接make生成hello

2. CMakeLists.txt
#注释行
projetc(hello)
set(TEST "test hello")
set(SRC_LST hello.c) 或者FILE(GLOB SOURCE *.c)这个是告诉源文件夹在哪
message(${TEST})
add_executable(hello ${SRC_LST})
这是这个hello的cmakelists.txt
~其中,变量可以用小写,没有问题
~message(test,hello)也可,如果有空格,用""
~变量引用${},有空格的话用""
~add_executable(), 生成可执行程序
~如果引用内部库,就添加target_link_libraries(hello SDL) target_link_libraries(hello GLU)对应的命令是-lSDL -lGLU
~FILE(GLOB_RECURSE SRC_LIST "*.cpp") 将当前目录所有文件.cpp包括子目录赋值给.
~

3. 可以加个if...else...endif
例:if(WIN32)
      message(*********)
     else(WIN32)
     message(#########)
     endif(WIN32)
三者后面都要有条件

4.
set()
subdirs() 
add_library()
添加静态链接文件到目标中
会查找当前目录文件和subdirs指定的文件夹

add_executable()  添加一个可执行程序到目标文件中
aux_source_directory()
progect()

5.
include_directories(dir1 dir2...) 相当于-ldir1 -ldir2
link_directories()
link_libraries()
target_link_libraries()

6.
project(main)工程名称
cmake_min_requiered(version 2.6)

aux_source_directory(<dir> <variable>) 将dir下所有的文件名赋值给var
常用:aux_source_directory(. dir_srcs)

7. add_subdirectory(src)指明本项目包含一个子目录src
   target_link_libraries(main test)指明main需要链接一个test链接库

8. 常用变量
cmake_source_dir
project_source_dir 
<projectname>_source_dir
三者皆指工程顶层目录

cmake_binary_dir
project_binary_dir
<projectname>_binary_dir
如果是in-source编译,指的是工程顶层目录,如果是out-of-source指的是工程程编译发生的目录

 CMAKE_CURRENT_SOURCE_DIR
指的是当前处理的CMakeLists.txt所在的路径。
CMAKE_CURRRENT_BINARY_DIR
如果是in-source编译,它跟CMAKE_CURRENT_SOURCE_DIR一致,如果是out-ofsource 编译,他指的是target编译目录。
CMAKE_CURRENT_LIST_FILE
输出调用这个变量的CMakeLists.txt的完整路径

9.
UNIX 与 WIN32
UNIX,在所有的类UNIX平台为TRUE,包括OS X和cygwin
WIN32,在所有的win32平台为TRUE,包括cygwin

10. 工程示例:

test                                     //工程根目录
├── cmake                     //CMake目录:代码和CMake编译目录分离
│   ├── bin
│   │   └── main               //生成后的可执行文件放在这里
│   ├── CMakeLists.txt
│   ├── lib
│   │   └── libhello.a                          //生成后的静态库放在这里
│   └── src
│       ├── CMakeLists.txt
│       ├── hello
│       │   └── CMakeLists.txt
│       └── main
│           └── CMakeLists.txt
├── hello                                      //hello静态库的源代码
│   └── hello.cpp
├── include                                   //头文件
│   └── hello.h
└── main                                     //可执行文件的源代码目录
    └── main.cpp

首先,需要给CMake的一个总入口,这个CMake设置一些全局的变量(cmake/CMakeLists.txt):
PROJECT(hello_3)
SET(PROJECT_ROOT_PATH "${CMAKE_SOURCE_DIR}/../")                 #工程的根目录,即test
SET(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin/")    #可执行生成后存放的目录(CMAKE_SOURCE_DIR是cmake目录)
SET(LIBRARY_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/lib/")             #静态库生成后存放的目录

INCLUDE_DIRECTORIES("${PROJECT_ROOT_PATH}/include/")            #告诉CMake头文件在哪里?

LINK_DIRECTORIES("${CMAKE_SOURCE_DIR}/lib/")                             #告诉CMake静态库在哪里?

ADD_SUBDIRECTORY(src)                                                                     #多目录,把src目录加进来,src里面才是真正编译main和hello的
(b).src目录下的CMakeList.txt,这个CMake只是简单地把main目录和hello目录链接起来:
ADD_SUBDIRECTORY(main)
ADD_SUBDIRECTORY(hello)
(c).hello静态库:
FILE(GLOB SOURCE_1 "${PROJECT_ROOT_PATH}/hello/*.cpp")      #告诉CMake源文件在哪里?
ADD_LIBRARY(hello STATIC ${SOURCE_1})                                       #告诉CMake生成的是一个静态库
 
(d).main可执行文件:
FILE(GLOB SOURCE_1 "${PROJECT_ROOT_PATH}/main/*.cpp")     #告诉CMake源文件在哪里?

ADD_EXECUTABLE(main ${SOURCE_1})                                          #告诉CMake生成一个main可执行文件
TARGET_LINK_LIBRARIES(main hello)                                              #告诉CMake静态库在哪里?



每天早上叫醒你的不是闹钟,而是心中的梦~
原文地址:https://www.cnblogs.com/vintion/p/4117073.html