CMake 編寫
Example 1: 簡易的hello world專案 [Top]
簡易的hello world範例, 編譯一個執行檔, 以下為project底下的檔案列表
.
├── CMakeLists.txt
├── build
└── hello_world.c
CMakeLists.txt裡面填寫所要編譯相關規則.
build是一個空目錄, 進去此目錄後, 下達cmake相關指令後, 把編譯的檔案放置此處
以下為CMakeLists.txt內容
1 2 3 4 5 | # recommend to add these two lines cmake_minimum_required(VERSION 2.8.9) project(hello_world) add_executable(hello_world hello_world.c) |
行2是規定所需要的最低cmake版本.
行3是專案名稱.
行5則是編譯一個名稱為hello_world執行檔,其source檔案為hello_world.c
#編譯 $ mkdir build ; cd build; cmake ..; make #執行程式 $ ./hello_world hello world!
Example 2: 多層階層的專案(hierarchical CMakeLists.txt) [Top]
階層的CMakeLists.txt範例
. ├── CMakeLists.txt ├── src1 │ ├── CMakeLists.txt │ └── foo.cpp └── src2 ├── CMakeLists.txt └── bar.cpp
此專案底下有兩個小程式src1與src2,藉由最上層的CMakeLists.txt去執行兩個程式裡的CMakeLists.txt. 藉此個別編譯出對應的程式
以下為3個CMakeLists.txt個別的內容.
1 2 3 4 5 6 7 | # top CMakeKLists.txt cmake_minimum_required(VERSION 3.8.1) project (hierarchical-cmakelists) message("===> start to build.... " ${PROJECT_NAME}) add_subdirectory(src1) add_subdirectory(src2) |
主要行7~8使用add_subdirectory把這兩個目錄加入到程序. cmake便會依序進入目錄裡去尋找CMakeLists.txt來編譯
1 2 3 4 | # CMakeKLists.txt in src1 cmake_minimum_required(VERSION 3.8.1) project (foo) add_executable(foo foo.cpp) |
1 2 3 4 | # CMakeKLists.txt in src2 cmake_minimum_required(VERSION 3.8.1) project (bar) add_executable(bar bar.cpp) |
src1與src2的內容跟hello world專案裡的CMakeLists.txt並無太大差異
#編譯 $ mkdir build/; cd build/; cmake ..; make #執行 $ ./src1/foo; ./src2/bar Foo! Bar !
Example 3: 建立靜態與動態程式庫(static and dynamic libraries) [Top]
建立static library與share library, 並撰寫使用此函式庫的測試程式
. ├── CMakeLists.txt ├── lib │ ├── foo.cpp │ └── foo.h └── main.cpp
專案底下有一個lib資料夾,用來產生static library與share library. 而main.cpp則是使用此lib的測試程式
底下為CMakeLists.txt內容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | cmake_minimum_required(VERSION 3.8.1) project (static-lib-and-dynamic-lib) set(CMAKE_BUILD_TYPE Release) # include headers include_directories(lib) # source files set(SOURCES "lib/foo.cpp") # share library add_library(foo-d SHARED ${SOURCES}) # static library add_library(foo-s STATIC ${SOURCES}) # unit test for libraries # way 1: add to each #add_compile_options(-D_TEST_) #add_executable(foo-test lib/foo.cpp) # way 2: only available with this project add_executable(foo-test lib/foo.cpp) target_compile_options( foo-test PRIVATE -D_TEST_) # excutable with share library add_executable(main-d main.cpp) target_link_libraries(main-d foo-d) # excutable with static library add_executable(main-s main.cpp) target_link_libraries(main-s foo-s) |
行1~3為CMakeLists.txt的基本設置.
行6主要是設置header files所在的目錄. 由於我這邊是放在lib目錄. 所以include_directories(lib)
行8是設定編譯此library所需的source file有哪些
行11與行13使用add_library編譯出library. 其根據${SOURCE}變數的檔案去產生對應的library類型.
行16~18與行19~24作用相同. 主要編譯出lib的unit test程式. 因為main()函數被我用#ifdef _TEST_的方式包起來, 所以編譯的時候需夾帶 -D_TEST_.
行25~30個別編譯使用這些lib的測試程式.
#編譯 $ mkdir build; cd build; cmake ..; make #執行測試 echo "===> unit test"; ./foo-test; echo "===> use lib test"; ./main-d ; ./main-s ===> unit test TEST: Call foo()... foo: This is foo! ===> use lib test Main: Call foo()... foo: This is foo! Main: Call foo()... foo: This is foo!
Example 4: 使用外部函式庫 [Top]
查找系統上所需的package(library).這邊使用(1)cmake內建的find_package. (2) pkg-config的方式去查找. (3)使用搜尋檔案的方式
. ├── CMakeLists.txt ├── build └── externallib.cpp
目錄底下的externally.cpp會使用libcurl作為測試
以下為CMakeLists.txt內容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | # recommend to add these two lines cmake_minimum_required(VERSION 3.8.1) project(external_libs) message("CMAKE_ROOT => " ${CMAKE_ROOT}) message("CMAKE_MODULE_PATH => " ${CMAKE_MODULE_PATH}) add_executable(externallib externallib.cpp) # way - use find package to get information of package if(0) find_package(CURL REQUIRED) if(CURL_FOUND) include_directories(${CURL_INCLUDE_DIR}) target_link_libraries(externallib ${CURL_LIBRARY}) message("curl found => " ${CURL_FOUND}) message("curl header => " ${CURL_INCLUDE_DIR}) message("curl Library => " ${CURL_LIBRARY}) message("curl Libraries => " ${CURL_LIBRARIES}) else() # or else(CURL_FOUND) message(FATAL_ERROR "curl not found!") endif() # or endif(CURL_FOUND) endif() # way - use find libray to get library link if(1) IF (APPLE) #find_path(CURL_TEST_INCLUDE_DIR NAMES curl/curl.h) # Additional search locations can be specified after the PATHS argument. find_path(CURL_TEST_INCLUDE_DIR NAMES curl.h PATHS /usr/include/curl) find_library(CURL_TEST_LIB curl) message("header -> ${CURL_TEST_INCLUDE_DIR}") message("lib -> ${CURL_TEST_LIB}") target_link_libraries(externallib ${CURL_TEST_LIB}) ENDIF (APPLE) endif() # way - use pkg-config if(0) message("PKG_CONFIG_FOUND => " ${PKG_CONFIG_FOUND}) message("PKG_CONFIG_EXECUTABLE => " ${PKG_CONFIG_EXECUTABLE}) message("PKG_CONFIG_VERSION_STRING => " ${PKG_CONFIG_VERSION_STRING}) find_package(PKGCONFIG) message("PKG_CONFIG_FOUND => " ${PKG_CONFIG_FOUND}) message("PKG_CONFIG_EXECUTABLE => " ${PKG_CONFIG_EXECUTABLE}) message("PKG_CONFIG_VERSION_STRING => " ${PKG_CONFIG_VERSION_STRING}) # use find_package(PKGCONFIG) before use pkg-config module pkg_check_modules(LIBPCRE libpcre) message("LIBPCRE found => " ${LIBPCRE_FOUND}) message("LIBPCRE Libraries => " ${LIBPCRE_LIBRARIES}) message("LIBPCRE Library dirs => " ${LIBPCRE_LIBRARY_DIR}) message("LIBPCRE LDFLAGS => " ${LIBPCRE_LDFLAGS}) message("LIBPCRE LIBPCRE_LDFLAGS_OTHER => " ${LIBPCRE_LDFLAGS_OTHER}) message("LIBPCRE LIBPCRE_INCLUDE_DIRS => " ${LIBPCRE_INCLUDE_DIRS}) message("LIBPCRE LIBPCRE_CFLAGS => " ${LIBPCRE_CFLAGS}) message("LIBPCRE LIBPCRE_CFLAGS_OTHER => " ${LIBPCRE_CFLAGS_OTHER}) pkg_check_modules (RUBY ruby-2.3) pkg_search_module(RUBY ruby-2.3 ruby) message("ruby => " ${RUBY_FOUND}) endif() |
行1~3為基本的project設置
行5~6輸出make module的資訊
行7則是編譯出目標的執行檔
行10~22則是使用find_package的方式去尋找libcurl.
行13~18則是把找到的package資訊,加入到編譯選項並顯示出來. include_directories加入header files路徑. target_link_libraries加入所需連接(link)的library.
行25~35則是指定明確路徑(目錄)的方式去尋找libcurl.
行29使用find_path去尋找curl.h是否存在於/usr/include/curl. 並把找到檔案的目錄存在CURL_TEST_INCLUDE_DIR
行30使用find_library去尋找curl函式庫.並把資訊存放於CURL_TEST_LIB.
行38~60則是使用pkg-config的module. 這邊因為libcurl不存在於pkg-config裡面. 所以使用 libpcre來做範例
行42先尋找是否有pkg-config模組. 此行在使用pkg-config之前必須先使用.
行47使用pkg_check_modules來尋找libpcre.
#編譯 $ mkdir build; cd build; cmake ..; make #執行結果. 此範例是curl的範例程式 $ ./externallib <!doctype html> <html> <head> <title>Example Domain</title> <meta charset="utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <style type="text/css"> body { background-color: #f0f0f2; margin: 0; padding: 0; font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; } div { width: 600px; margin: 5em auto; padding: 50px; background-color: #fff; border-radius: 1em; } a:link, a:visited { color: #38488f; text-decoration: none; } @media (max-width: 700px) { body { background-color: #fff; } div { width: auto; margin: 0 auto; border-radius: 0; padding: 1em; } } </style> </head> <body> <div> <h1>Example Domain</h1> <p>This domain is established to be used for illustrative examples in documents. You may use this domain in examples without prior coordination or asking for permission.</p> <p><a href="http://www.iana.org/domains/example">More information...</a></p> </div> </body> </html> We received Content-Type: text/html
留言
張貼留言