1.CMake编译原理
CMake是一种跨平台编译工具,比make更为高级,使用起来要方便得多。CMake主要是编写CMakeLists.txt文件,然后用cmake命令将CMakeLists.txt文件转化为make所需要的makefile文件,最后用make命令编译源码生成可执行程序或共享库(so(shared object))。因此CMake的编译基本就两个步骤:
1. cmake 2. make
cmake 指向CMakeLists.txt所在的目录,例如cmake .. 表示CMakeLists.txt在当前目录的上一级目录。cmake后会生成很多编译的中间文件以及makefile文件,所以一般建议新建一个新的目录,专门用来编译,例如
mkdir build cd build cmake .. make
make根据生成makefile文件,编译程序。
2.使用Cmake编译程序
我们编写一个关于开平方的C/C++程序项目,即b= sqrt(a),以此理解整个CMake编译的过程。
a.准备程序文件
文件目录结构如下:
. ├── build ├── CMakeLists.txt ├── include │ └── b.h └── src ├── b.c └── main.c
头文件b.h,如下所示:
#ifndef B_FILE_HEADER_INC #define B_FIEL_HEADER_INC #include<math.h> double cal_sqrt(double value); #endif
头文件b.c,如下所示:
#include "../include/b.h" double cal_sqrt(double value) { return sqrt(value); }
main.c主函数,如下所示:
#include "../include/b.h" #include <stdio.h> int main(int argc, char** argv) { double a = 49.0; double b = 0.0; printf("input a:%f ",a); b = cal_sqrt(a); printf("sqrt result:%f ",b); return 0; }
b.编写CMakeLists.txt
接下来编写CMakeLists.txt文件,该文件放在和src,include的同级目录,实际方哪里都可以,只要里面编写的路径能够正确指向就好了。CMakeLists.txt文件,如下所示:
1 #1.cmake verson,指定cmake版本 2 cmake_minimum_required(VERSION 3.2) 3 4 #2.project name,指定项目的名称,一般和项目的文件夹名称对应 5 PROJECT(test_sqrt) 6 7 #3.head file path,头文件目录 8 INCLUDE_DIRECTORIES( 9 include 10 ) 11 12 #4.source directory,源文件目录 13 AUX_SOURCE_DIRECTORY(src DIR_SRCS) 14 15 #5.set environment variable,设置环境变量,编译用到的源文件全部都要放到这里,否则编译能够通过,但是执行的时候会出现各种问题,比如"symbol lookup error xxxxx , undefined symbol" 16 SET(TEST_MATH 17 ${DIR_SRCS} 18 ) 19 20 #6.add executable file,添加要编译的可执行文件 21 ADD_EXECUTABLE(${PROJECT_NAME} ${TEST_MATH}) 22 23 #7.add link library,添加可执行文件所需要的库,比如我们用到了libm.so(命名规则:lib+name+.so),就添加该库的名称 24 TARGET_LINK_LIBRARIES(${PROJECT_NAME} m)
CMakeLists.txt主要包含以上的7个步骤,具体的意义,请阅读相应的注释。
c.编译和运行程序
准备好了以上的所有材料,接下来,就可以编译了,由于编译中出现许多中间的文件,因此最好新建一个独立的目录build,在该目录下进行编译,编译步骤如下所示:
mkdir build cd build cmake .. make
操作后,在build下生成的目录结构如下:
├── build │ ├── CMakeCache.txt │ ├── CMakeFiles │ │ ├── 3.2.2 │ │ │ ├── CMakeCCompiler.cmake │ │ │ ├── CMakeCXXCompiler.cmake │ │ │ ├── CMakeDetermineCompilerABI_C.bin │ │ │ ├── CMakeDetermineCompilerABI_CXX.bin │ │ │ ├── CMakeSystem.cmake │ │ │ ├── CompilerIdC │ │ │ │ ├── a.out │ │ │ │ └── CMakeCCompilerId.c │ │ │ └── CompilerIdCXX │ │ │ ├── a.out │ │ │ └── CMakeCXXCompilerId.cpp │ │ ├── cmake.check_cache │ │ ├── CMakeDirectoryInformation.cmake │ │ ├── CMakeOutput.log │ │ ├── CMakeTmp │ │ ├── feature_tests.bin │ │ ├── feature_tests.c │ │ ├── feature_tests.cxx │ │ ├── Makefile2 │ │ ├── Makefile.cmake │ │ ├── progress.marks │ │ ├── TargetDirectories.txt │ │ └── test_sqrt.dir │ │ ├── build.make │ │ ├── C.includecache │ │ ├── cmake_clean.cmake │ │ ├── DependInfo.cmake │ │ ├── depend.internal │ │ ├── depend.make │ │ ├── flags.make │ │ ├── link.txt │ │ ├── progress.make │ │ └── src │ │ ├── b.c.o │ │ └── main.c.o │ ├── cmake_install.cmake │ ├── Makefile │ └── test_sqrt ├── CMakeLists.txt ├── include │ └── b.h └── src ├── b.c └── main.c
注意在build的目录下生成了一个可执行的文件test_sqrt,运行获取结果如下:
命令: ./test_sqrt 结果: input a:49.000000 sqrt result:7.000000
d.源码
3.参考资料
参考:http://blog.csdn.net/cust_hf/article/category/345853
CMakeListserv.txt的写法
(1):要求CMake根据指定的源文件生成可执行文件
Demo1:
add_executable(hello main.cpp)
这将从main.cpp源码文件创建一个叫“hello”(Windows下叫“hello.exe”)的可执行文件。你可以根据自己的需要将C和C++文件混合。在同一个CMakeLists.txt可以有多个可执行文件和库。同一个源码文件可以用于不同的目的,源码可以从其他目标中为每个目的独立的编译。
Demo2:
add_executable(demo main.cpp main.h main.rc)
这奖使用main.cpp源文件,main.h文件,main.rc文件构造可执行文件。至于如何使用这些文件,CMake比我们都清楚。
(2):调试CMakeLists.txt的办法
这个是调试CMakeLists.txt的一个手段啦。不得不学习哦。
演示1如下:
MESSAGE("俺们正在生成项目文件")
会显示一个警告框。
演示2如下:
MESSAGE(STATUS "俺们正在创建项目文件")
遇到这条指令,会把文字显示在状态栏里面(一闪而过,不容易发现)。
演示3如下:
MESSAGE(FATAL_ERROR "严重错误,俺们搞不定啦")
这条指令会提示出错,并退出。
(3):使用标准模块
cmake提供了很多标准模块,扩展名都是txt.我们可以直接包含进来。就像使用C语言的#include指令一般。比如:
INCLUDE(FindBoost)
一句话,就告诉了CMake“我们的程序需要Boost”。
(4):使用变量 .
SET( MY_SOURCES main.cpp widget.cpp)
MESSAGE(STATUS "my sources: ${MY_SOURCES}")使用SET()命令来为变量设置值。如果你列出了一个以上的字符串,变量将是串列表。列表是一列由分号隔开的字符串。如果只设置个一项,那么这项只有一个值。可以通过${VAR}获得变量的值。可以使用FOREACH()来迭代一份列表:
FOREACH(next_ITEM ${MY_SOURCES})
MESSAGE(STATUS "next item: ${next_ITEM}")
ENDFOREACH(next_ITEM ${MY_SOURCES})
CMake中的命令是大小写无关的。变量名和参数名是大小写相关的。
(5):测试平台相关信息 .
办法一(这个代码没有检验过哦)
IF (UNIX)
MESSAGE("这个是UNIX操作系统")
ENDIF (UNIX)
IF (MSVC)
MESSAGE("这个需要做VC的项目文件")
ENDIF (MSVC)
办法二(这个测试过)
IF (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
SET(option WIN32)
SET(win32_LIBRARIES comctl32.lib shlwapi.lib shell32.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib)
#SET(defs -DUNICODE -D_UNICODE)
ENDIF (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
(6):要求CMake根据指定的源文件生成库文件 .
ADD_LIBRARY: Add a library to the project using the specified source files.
• ADD_LIBRARY(libname [SHARED | STATIC | MODULE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN)Adds a library target. SHARED, STATIC or MODULE keywords are used to set the library type. If the keyword MODULE appears, the library type is set to MH_BUNDLE on systems which use dyld. On systems without dyld, MODULE is treated like SHARED. If no keywords appear as the second argument, the type defaults to the current value of BUILD_SHARED_LIBS. If this variable is not set, the type defaults to STATIC.
If EXCLUDE_FROM_ALL is given the target will not be built by default. It will be built only if the user explicitly builds the target or another target that requires the target depends on it.
(7):添加查找头文件的路径 .
INCLUDE_DIRECTORIES: Add include directories to the build.
INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)Add the given directories to those searched by the compiler for include files. By default the directories are appended onto the current list of directories. This default behavior can be changed by setting CMAKE_INCLUDE_DIRECTORIES_BEFORE to ON. By using BEFORE or AFTER you can select between appending and prepending, independent from the default. If the SYSTEM option is given the compiler will be told that the directories are meant as system include directories on some platforms.
(8):添加库文件的搜索路径 .
分类: CMake相关 2007-11-04 00:50 421人阅读 评论(0) 收藏 举报
LINK_DIRECTORIES: Specify directories in which to search for libraries.
LINK_DIRECTORIES(directory1 directory2 ...)
(9):显式指定链接时需要的库文件 .
分类: CMake相关 2007-11-04 00:54 491人阅读 评论(0) 收藏 举报
为每个目标分别指定需要链接的库文件(指定部分目标专用的库文件)
TARGET_LINK_LIBRARIES: Link a target to given libraries.
TARGET_LINK_LIBRARIES(target library1 <debug | optimized> library2 ...)Specify a list of libraries to be linked into the specified target. The debug and optimized strings may be used to indicate that the next library listed is to be used only for that specific type of build
为所有目标统一指定需要的库文件(指定所有目标都用的库文件)
LINK_LIBRARIES: Link libraries to all targets added later.
LINK_LIBRARIES(library1 <debug | optimized> library2 ...)This is an old CMake command for linking libraries. Use TARGET_LINK_LIBRARIES unless you have a good reason for every target to link to the same set of libraries.
Specify a list of libraries to be linked into any following targets (typically added with the ADD_EXECUTABLE or ADD_LIBRARY calls). This command is passed down to all subdirectories. The debug and optimized strings may be used to indicate that the next library listed is to be used only for that specific type of build.
(10):显式实施宏定义 .
分类: CMake相关 2007-11-04 00:58 496人阅读 评论(0) 收藏 举报
用法演示一(文本宏):
ADD_DEFINITIONS(-DDEBUG)
用法演示二(常量宏)
ADD_DEFINITIONS(-DVERSION=1)
ADD_DEFINITIONS: Adds -D define flags to the command line of C and C++ compilers.
ADD_DEFINITIONS(-DFOO -DBAR ...)Adds flags to command line of C and C++ compilers. This command can be used to add any flag to a compile line, but the -D flag is accepted most C/C++ compilers. Other flags may not be as portable.
转自:http://blog.csdn.net/gxuan/article/details/7701035
范例:
1 cmake_minimum_required(VERSION 3.4.1) 2 3 ### libgameplay 4 #头文件路径 5 include_directories( 6 src_gameplay/src 7 src_gameplay/external-deps/include 8 ) 9 10 link_directories( 11 src_gameplay/external-deps/lib 12 ) 13 14 file(GLOB gameplay_src "src_gameplay/src/*.cpp") #声明字符串变量,此处字符串为源文件路径 15 file(GLOB gameplay_lua "src_gameplay/src/lua/*.cpp") 16 file(GLOB homura_src "src_gameplay/homura/*.cpp") 17 18 add_library( # Sets the name of the library. 19 gameplay 20 # Sets the library as a shared library. 21 SHARED 22 # Provides a relative path to your source file(s). 23 # Associated headers in the same location as their source 24 # file are automatically included. 25 ${gameplay_src} 26 ${gameplay_lua} 27 ${homura_src} ) 28 29 set_target_properties( gameplay PROPERTIES IMPORTED_LOCATION libs/${ANDROID_ABI}/libgameplay.so ) 30 set(CMAKE_CXX_FLAGS "-Os -std=c++11 -frtti -Wno-switch-enum -Wno-switch -Wno-error=non-virtual-dtor -D__ANDROID__") 31 32 target_link_libraries( # Specifies the target library. 33 gameplay 34 # Denpendences 35 gameplay-deps 36 log 37 android 38 EGL 39 GLESv2 40 OpenSLES ) 41 42 ########################################################################################## 43 44 ### libgameplay_jni 45 file(GLOB gameplay_jni "jni/game_jni/*.cpp") 46 add_library( # Sets the name of the library. 47 gameplay_jni 48 # Sets the library as a shared library. 49 SHARED 50 # Provides a relative path to your source file(s). 51 # Associated headers in the same location as their source 52 # file are automatically included. 53 ${gameplay_jni} ) 54 55 set_target_properties( gameplay_jni PROPERTIES IMPORTED_LOCATION libs/${ANDROID_ABI}/libgameplay_jni.so ) 56 set(CMAKE_CXX_FLAGS "-Os -std=c++11 -frtti -Wno-switch-enum -Wno-switch -Wno-error=non-virtual-dtor -D__ANDROID__") 57 58 target_link_libraries( # Specifies the target library. 59 gameplay_jni 60 # Denpendences 61 gameplay 62 log 63 android )