前言
使用教材: aben20807/learn_cmake
$ git clone https://github.com/aben20807/learn_cmake.git
$ cd learn_cmake
基本編譯及執行
$ mkdir build
$ cd build
$ cmake ..
$ make
$ ./bin/exec
hello
3
$ls
bin/ CMakeFiles/ extern/ lib/ src/ cmake_install.cmake CMakeCache.txt Makefile
改用 ninja 來取代 make [可跳過]
Ninja,跟 make 相同地位,但號稱是更快速的建置系統,主要可以善用平行化編譯,且沒有 make 那樣的歷史包袱導致過於複雜,ninja 生來就是用來被產生,沒錯,cmake 也可以產生 ninja 使用的編譯腳本。目前相當多大型專案 (Google Chrome, parts of Android, LLVM) 都仰賴 ninja。
因為用不同工具編譯的指令不同 make 用 make
, ninja 用 ninja
,所以 cmake 有一個指令 ($ cmake --build .
) 是可以依照當初產生的來自動呼叫對應的指令,後面章節會用到。
$ sudo apt install ninja-build
刪除使用 make 的版本並指定使用 ninja
$ cd ..
$ rm -r build
$ mkdir build
$ cd build
$ cmake -G Ninja ..
$ ninja
$ ./bin/exec
hello
3
$ ls
bin/ CMakeFiles/ extern/ lib/ src/ build.ninja cmake_install.cmake CMakeCache.txt rules.ninja
使用 gdb
建議可以先參考舊文 107.06.18 好看的 gdb, gdb-dashboard 來提升 gdb 的顏值 (x
使用 gdb 主要原因就是因為程式只有印出 Segmentation fault 然後就沒有其他了,不會通靈的話基本上無法解決。不過本篇使用的是最簡單的例子,一般會更複雜,不過使用 gdb 還是比通靈實在多了。
為了演示,我將 ../src/main.cpp
改為下面內容,當前目錄都在 learn_cmake/build/
中:
#include <say_hello_util/hello.hpp>
#include <sum_header/sum.hpp>
#include <stdlib.h>
struct Foo {
int x;
};
int main() {
hh::hello();
std::cout << ss::sum(1, 2) << "\n";
Foo* ptr = (Foo*)malloc(sizeof(Foo));
ptr->x = 42;
std::cout << ptr->x;
free(ptr);
ptr = NULL;
std::cout << ptr->x;
}
使用流程:
- 發現問題
$ cmake --build . # 呼叫 make 或 ninja
$ ./bin/exec
hello
3
Segmentation fault
- 利用 cmake 產生 debug 專用的編譯指令,讓額外的程式碼資訊一起編譯到執行檔中 (稍後可以試試不經過這一步會如何,需要先
$ rm CMakeCache.txt
),此步驟在 ninja 或 make 都可以適用。
$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ..
$ cmake --build .
- 使用 gdb 開啟並執行編譯好的檔案
$ gdb -q -ex run --args ./bin/exec