前言

使用教材: 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;
}

使用流程:

  1. 發現問題
$ cmake --build . # 呼叫 make 或 ninja
$ ./bin/exec
hello
3
Segmentation fault
  1. 利用 cmake 產生 debug 專用的編譯指令,讓額外的程式碼資訊一起編譯到執行檔中 (稍後可以試試不經過這一步會如何,需要先 $ rm CMakeCache.txt),此步驟在 ninja 或 make 都可以適用。
$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ..
$ cmake --build .
  1. 使用 gdb 開啟並執行編譯好的檔案
$ gdb -q -ex run --args ./bin/exec

顯示出錯位置,第 19 行 ptr 已經不可用

顯示出錯位置,第 19 行 ptr 已經不可用

OuO

參考資料

  • ⊛ Back to top
  • ⊛ Go to bottom