CMake Practice.pdflinux
. ├── CMakeLists.txt └── main.cpp
#include <iostream> int main() { std::cout <<"Hello World" << std::endl; return 0; }
PROJECT (PRACTISE1) SET(SRC_LIST main.cpp) MESSAGE(STATUS "This is BINARY dir "${PRACTISE1_BINARY_DIR}) MESSAGE(STATUS "This is BINARY dir "${PROJECT_BINARY_DIR}) MESSAGE(STATUS "This is SOURCE dir "${PRACTISE1_SOURCE_DIR}) MESSAGE(STATUS "This is SOURCE dir "${PROJECT_SOURCE_DIR}) ADD_EXECUTABLE(practise1 ${SRC_LIST})
$ cmake .
... -- This is BINARY dir xxx/practise1 -- This is BINARY dir xxx/practise1 -- This is SOURCE dir xxx/practise1 -- This is SOURCE dir xxx/practise1 ...
make clean
. ├── bin ├── build ├── CMakeLists.txt └── src ├── CMakeLists.txt └── main.cpp
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin ADD_EXECUTABLE(practise2 main.cpp)
PROJECT(PRACTISE2) MESSAGE(STATUS "PROJECT_BINARY_DIR= "${PROJECT_BINARY_DIR}) MESSAGE(STATUS "PROJECT_SOURCE_DIR= "${PROJECT_SOURCE_DIR}) ADD_SUBDIRECTORY(src)
$ cd build $ cmake .. $ make
-- PROJECT_BINARY_DIR= xxx/practise2/build -- PROJECT_SOURCE_DIR= xxx/practise2
practise2最後生成在bin目錄中ios
ADD_LIBRARY(庫名 SHARED 源文件列表)
把上面的ADD_EXECUTABLE修改成ADD_LIBRARY就能夠生成庫文件了, 第二個參數SHARED表示生成動態庫,STATIC表示生成靜態庫shell
SET(LIBRARY_OUTPUT_PATH <路徑>)
ADD_LIBRARY(hello_static STATIC hello.c) SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
本來會輸出 libhello_static.a
,加上後面這個後,庫文件名變爲libhello.a
windows
SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)
VERSION 指代動態庫版本,SOVERSION 指代 API 版本。函數
SET(LIBHELLO_SRC hello.cpp) SET(LIBRARY_OUTPUT_PATH lib) #目標文件生成目錄設置爲lib ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC}) ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC}) SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello") #對目標文件重命名 SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1) #不清理上個版本的生成文件 SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1) #不清理上個版本的生成文件
make以後會同時生成兩個文件ui
├── lib │ ├── libhello.a │ └── libhello.so
因爲windows調用dll通常是須要dll文件,帶有symbol的lib文件,以及函數聲明的頭文件,所以須要作額外的配置,CMAKE在動態庫編譯的以前會預約義一個宏 {庫名}_EXPORTS
,判斷這個宏來決定dll中的函數是否是導出函數,有了導出函數vs纔會額外的生成lib文件。debug
如下代碼兼容windows和linux dynamic.h日誌
#ifndef __DYNAMIC_H_ #define __DYNAMIC_H_ #ifdef _WIN32 #ifdef dynamic_EXPORTS #define __DLL_API __declspec(dllexport) #else #define __DLL_API __declspec(dllimport) #endif #endif //_WINDOWS #ifdef __linux__ #ifdef dynamic_EXPORTS #define __DLL_API __attribute__((visibility("default"))) #else #define __DLL_API #endif #endif //__linux__ __DLL_API void fun_dynamic(); #endif
dynamic_EXPORTS這個宏是cmake自動根據庫名生成的,正好能夠用來做爲是導出函數的判斷code
dynamic.cppci
#include "dynamic.h" #include <iostream> __DLL_API void fun_dynamic() { std::cout << "msg from dynamic" << std::endl; }
INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
這條指令能夠用來向工程添加多個特定的頭文件搜索路徑,路徑之間用空格分割,若是路徑 中包含了空格,可使用雙引號將它括起來,默認的行爲是追加到當前的頭文件搜索路徑的 後面,你能夠經過兩種方式來進行控制搜索路徑添加的方式: 1,CMAKE_INCLUDE_DIRECTORIES_BEFORE,經過 SET 這個 cmake 變量爲 on,能夠 將添加的頭文件搜索路徑放在已有路徑的前面。 2,經過 AFTER 或者 BEFORE 參數,也能夠控制是追加仍是置前。
添加非標準的共享庫搜索路徑
LINK_DIRECTORIES(directory1 directory2 ...)
爲 target 添加須要連接的庫,target能夠是可執行文件,也能夠是庫文件
TARGET_LINK_LIBRARIES(target library1 <debug | optimized> library2 ...)
├── bin ├── build ├── CMakeLists.txt ├── libs └── src ├── CMakeLists.txt ├── libdynamic │ ├── CMakeLists.txt │ ├── dynamic.cpp │ └── dynamic.h ├── libstatic │ ├── CMakeLists.txt │ ├── static.cpp │ └── static.h └── main ├── CMakeLists.txt └── main.cpp
本工程由一個可執行文件和一個靜態庫和一個動態庫構成,可執行文件調用了這兩個庫文件,可執行文件和動態庫最後生成在bin目錄下,靜態庫生成在libs目錄。
PROJECT(PRACTISE3) MESSAGE(STATUS "PROJECT_BINARY_DIR= "${PROJECT_BINARY_DIR}) MESSAGE(STATUS "PROJECT_SOURCE_DIR= "${PROJECT_SOURCE_DIR}) ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(libstatic) ADD_SUBDIRECTORY(libdynamic) ADD_SUBDIRECTORY(main)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) ADD_LIBRARY(dynamic SHARED dynamic.cpp)
設定生成目錄爲根目錄下面的bin
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/libs) ADD_LIBRARY(static STATIC static.cpp)
設定生成目錄爲根目錄下面的libs
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/libstatic ${PROJECT_SOURCE_DIR}/src/libdynamic) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) ADD_EXECUTABLE(practise3 main.cpp) TARGET_LINK_LIBRARIES(practise3 static) TARGET_LINK_LIBRARIES(practise3 dynamic)
設定了頭文件的查找目錄,並在最後指定了須要連接的動態庫和靜態庫,庫的名字應該與ADD_LIBRARY指令中使用的名字一致
Scanning dependencies of target static [ 33%] Building CXX object src/libstatic/CMakeFiles/static.dir/static.o Linking CXX static library ../../../libs/libstatic.a [ 33%] Built target static Scanning dependencies of target dynamic [ 66%] Building CXX object src/libdynamic/CMakeFiles/dynamic.dir/dynamic.o Linking CXX shared library ../../../bin/libdynamic.so [ 66%] Built target dynamic Scanning dependencies of target practise3 [100%] Building CXX object src/main/CMakeFiles/practise3.dir/main.o Linking CXX executable ../../../bin/practise3 [100%] Built target practise3
自動根據各個項目的包含關係決定構建的順序