CMake

https://www.youtube.com/playlist?list=PLK6MXr8gasrGmIiSuVQXpfFuE1uPT615s

1. Running CMake

cd makefile_test
mkdir build
subl CMakeLists.txt

cmake_minimum_required(VERSION 3.15.2)
project(makefile_test_project VERSION 1.0.0)

1.1 method 1: cmake directory

cd build the directory to run cmake from
cmake .. .. means to build from the parent folder, and the following messages pop up:

-- The C compiler identification is AppleClang 10.0.1.10010046
-- The CXX compiler identification is AppleClang 10.0.1.10010046
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/ysgc/cpp_doc/makefile_test/build

1.2 Method 2: ccmake, a command line app

could check the cmakecache when gui is not available

1.3 Method 3: cmake-gui

cmake-gui
set the source code directory to the parent folder "some_path/makefile_test"
set the built binaries to "some_path/makefile_test/build"

2. a hello-world example

subl main.cpp

//main.cpp
#include <iostream>
int main(){
    std::cout << "hello world~" << std::endl;
    return 0;
}

subl CMakeLists.txt 在下面加入一行 add
_executable(output_file_name xxxx.cpp)

cmake_minimum_required(VERSION 3.15.2)
project(makefile_test_project VERSION 1.0.0) 

add_executable(test_main main.cpp)

cd build
cmake . 此處之前已經(jīng)cmake ..過了靡砌,所以可以直接在binary的文件夾下面cmake,和cmake+source_path效果一樣遏片。
make && ./test_main

3. Adding a library

the same file structure as the previous article:

// main.cpp
#include <iostream>
#include "funcs.h"
int main(){
    std::cout << std::endl;
    print_hello();
    std::cout << std::endl;
    std::cout << "The factorial of 5 is " << factorial(5) << std::endl;
    return 0;
}
//funcs.h
#ifndef FUNCS_H
#define FUNCS_H

void print_hello();
int factorial(int n);

#endif
// func1.cpp
#include "funcs.h"

int factorial(int n){
    if (n != 1){
        return n*factorial(n-1);
    }
    return 1;
}
// func2.cpp
#include <iostream>
#include "funcs.h"

void print_hello(){
    std::cout << "hello world!!!" << std::endl;
}

2.1 Method 1: put all the cpp file into "add_executable"

cmake_minimum_required(VERSION 3.15.2)
project(makefile_test_project VERSION 1.0.0) 

add_executable(test_main main.cpp func1.cpp func2.cpp)

2.2 Method 2:

cmake_minimum_required(VERSION 3.15.2)
project(makefile_test_project VERSION 1.0.0) 

add_library(
    func12_lib
    func1.cpp
    func2.cpp
#   funcs.h
    )

add_executable(test_main main.cpp)

target_link_libraries(test_main PRIVATE func12_lib)

NOTE: the default type of add_library is "static", instead, it could be "add_library(func12_lib SHARED func1.cpp func2.cpp)"

NOTE: the other key for add_library is MODULE

NOTE: the "PRIVATE" key in "target_link_libraries" will be covered later

NOTE: run ldd test_main ~> get the dynamic linker dependencies

3. CMake with vscode

install the two extensions first:


cmd+shift+p ~> cmake configure
select the compiler
click the build here
or here
set a break point
right click the executable file and run the debugger, and no further setting is needed

4. Subdirectories and Target Interface Properties

4.1 Add a subdirectory

添加一個目錄和一個空的CMakeLists
根目錄CMakeLists:添加一行綠框绰寞,其中l(wèi)ib_test是相對根目錄CMakeLists的位置

此時進行cmake build可以通過

4.2 Move head files into the subdirectory

cmake build通不過

-- Configuring done
CMake Error at CMakeLists.txt:6 (add_library):
Cannot find source file:

func1.cpp

Tried extensions .c .C .c++ .cc .cpp .cxx .cu .m .M .mm .h .hh >.h++ .hm
.hpp .hxx .in .txx

CMake Error at CMakeLists.txt:6 (add_library):
No SOURCES given to target: func12_lib

CMake Generate step failed. Build files cannot be regenerated correctly.

4.3 Edit the CMakeLists inside the subdirectory

move these lines from root folder CMakeLists into the one in subdirectory. Then change the directory a little.

Now, the building of cmake coud pass while the one of make could not.

cmake ..
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/ysgc/cpp_doc/makefile_test/build

make
Scanning dependencies of target func12_lib
[ 20%] Building CXX object lib_test/CMakeFiles/func12_lib.dir/src/lib_test/func1.cpp.o
[ 40%] Building CXX object lib_test/CMakeFiles/func12_lib.dir/src/lib_test/func2.cpp.o
[ 60%] Linking CXX static library libfunc12_lib.a
[ 60%] Built target func12_lib
Scanning dependencies of target test_main
[ 80%] Building CXX object CMakeFiles/test_main.dir/main.cpp.o
/Users/ysgc/cpp_doc/makefile_test/main.cpp:2:10: fatal error: 'funcs.h' file not found
#include "funcs.h"
^~~~~~~~~
1 error generated.
make[2]: *** [CMakeFiles/test_main.dir/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/test_main.dir/all] Error 2
make: *** [all] Error 2

4.4 Link the library to main.cpp

change the folder structure: remove the /lib_test/src/lib_test; all head files are under the /lib_test/src/ now.
func12_lib is just a nick name of the head files' directory; "first and second" means the subdirectory should be added before the main.cpp
line 7 tells the cmake system to know the real absolute path of the nickname
final step! include the head file, but since the head file is directly under the "func12_lib", the nickname, there's no extra path to be written before "funcs.h"

Now, it's clear why a more proper structure should be:

so that there's a nickname for the library before the head file, and different head files can be written after its library name.

4.5 Move main into a subdirectory

File structure
# root folder CMakeLists.txt
cmake_minimum_required(VERSION 3.15.2)
project(makefile_test_project VERSION 1.0.0) 

add_subdirectory(lib_test)
add_subdirectory(exec_test)
# /exec_test/CMakeLists.txt
add_executable(test_main main.cpp)

target_link_libraries(test_main PRIVATE func12_lib)

NOTE: now, the executable file is under /build/exec_test/ rather than /build/, file's name is still "main_test"

5. Add a macro variable

# /lib_test/CMakeLists.txt
add_library(
    func12_lib
    func12_lib/func1.cpp
    func12_lib/func2.cpp
    )
    
target_include_directories(func12_lib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")

target_compile_definitions(func12_lib PUBLIC FUNC12_LIB_VERSION=3)

Keyword: PUBLIC in the last line:
could be replaced by "PRIVATE" or "INTERFACE"
"PRIVATE" means the macro variable could only be used by func12_lib's file.
"INTERFACE" means the macro variable could only be used by files other than files in func12_lib

6. Scripting in CMakeLists.txt

  • set(MY_VARIABLE "I am a variable") ~> 意思是MY_VARIABLE等于"I am a varialbe" ~> 所有變量都是string;此處不加""就會變成"Iamavariable"
  • message(STATUS "The variable value is: ${MY_VARIABLE}")~>意思是執(zhí)行到這一行的時候print(some_string)

Control flow and Auto-dereferencing

set(my_bool TRUE)

if(NOT my_bool) # if(NOT "${my_bool}")
    message(STATUS "Condition was met")
else()
    message(STATUS "Condition failed")
endif()

set(s1 "string1")
set(s2 "string1")
set(s3 "string3")

if(s1 STREQUAL s3)
    message(STATUS "s1 = s3")
endif()


set(var 3)

if (var EQUAL "2")
    message(STATUS "${var} not equal to 2")
endif()


if((s1 STREQUAL s3) AND (var EQUAL "2"))
    message(STATUS "Condition was met in if")
elseif(my_bool)
    message(STATUS "Condition was met in elseif")
endif()

while(var LESS 50)
    message(STATUS "Value is ${var}")
    math(EXPR var "${var} + 1")
endwhile()

foreach(item IN ITEMS foo bar baz qux)
    message(STATUS "Item is: ${item}")
endforeach()

foreach(idx RANGE 0 99) # eq to foreach(idx RANGE 100)
    message(STATUS "Index is ${idx}")
endforeach()

7. Functions, Scopes, Arguments, and List Expansion

  • Array
set(my_list 4 5 6)
set_property(
    GLOBAL # DIRECTORY ${PROJECT_SOURCE_DIR}
    PROPERTY FOO
    1
    2
    3
    ${my_list}
)
get_cmake_property(foo_value FOO)
message(STATUS "Value of FOO is ${foo_value}")
  • function
function(function_test first_arg)
    message(STATUS "You called the function with argument: ${first_arg}")
endfunction()

function_test(101)

function(function_test arg1 arg2)
    foreach(arg IN LISTS ARGN)
        message(STATUS "You called the function with argN: ${arg}")
    endforeach()
    foreach(arg IN LISTS ARGV)
        message(STATUS "You called the function with argV: ${arg}")
    endforeach()
endfunction()

function_test(101 102 103 104 105)

~>

-- You called the function with argument: 101
-- You called the function with argN: 103
-- You called the function with argN: 104
-- You called the function with argN: 105
-- You called the function with argV: 101
-- You called the function with argV: 102
-- You called the function with argV: 103
-- You called the function with argV: 104
-- You called the function with argV: 105

  • dereference
function(increment var)
    message(STATUS "Value is: ${var}")
endfunction()

set(value 14)
increment(value)

~> Value is: value

function(increment var)
    message(STATUS "Value is: ${${var}}")
endfunction()

set(value 14)
increment(value)

~> Value is: 14

8. Test

https://www.youtube.com/watch?v=mBjRjZcRTA0&list=PLK6MXr8gasrGmIiSuVQXpfFuE1uPT615s&index=12

9.

https://www.youtube.com/watch?v=vyHp2YNUmSQ&list=PLK6MXr8gasrGmIiSuVQXpfFuE1uPT615s&index=13

10. Add external library

https://mirkokiefer.com/cmake-by-example-f95eb47d45b1

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末泉手,一起剝皮案震驚了整個濱河市黔寇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌斩萌,老刑警劉巖缝裤,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異颊郎,居然都是意外死亡憋飞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門姆吭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來榛做,“玉大人,你說我怎么就攤上這事内狸〖烀校” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵昆淡,是天一觀的道長锰瘸。 經(jīng)常有香客問我,道長昂灵,這世上最難降的妖魔是什么避凝? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮眨补,結(jié)果婚禮上管削,老公的妹妹穿的比我還像新娘。我一直安慰自己撑螺,他們只是感情好佩谣,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著实蓬,像睡著了一般茸俭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上安皱,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天调鬓,我揣著相機與錄音,去河邊找鬼酌伊。 笑死腾窝,一個胖子當著我的面吹牛缀踪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播虹脯,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼驴娃,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了循集?” 一聲冷哼從身側(cè)響起唇敞,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎咒彤,沒想到半個月后疆柔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡镶柱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年旷档,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歇拆。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡鞋屈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出故觅,到底是詐尸還是另有隱情谐区,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布逻卖,位于F島的核電站,受9級特大地震影響昭抒,放射性物質(zhì)發(fā)生泄漏评也。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一灭返、第九天 我趴在偏房一處隱蔽的房頂上張望盗迟。 院中可真熱鬧,春花似錦熙含、人聲如沸罚缕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽邮弹。三九已至,卻和暖如春蚓聘,著一層夾襖步出監(jiān)牢的瞬間腌乡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工夜牡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留与纽,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像急迂,于是被迫代替她去往敵國和親影所。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348