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\n",a);
b = cal_sqrt(a);
printf("sqrt result:%f\n",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.參考資料
[1]. CMake 使用方法 & CMakeList.txt
參考: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 )

