C++中使用CMake編譯管理項目

CMake是一個跨平臺的Makefile生成工具茫藏,可以根據(jù)特定的規(guī)則生成相應(yīng)的Makefile文件,并對C/C++源代碼進行編譯和管理包个。
有一篇博客介紹CMake的使用刷允,比較通俗易懂冤留,鏈接地址是:Cmake 詳解
CMake的官方下載地址為:https://cmake.org/download/
官方文檔地址為:CMake 3.16 Documentation
官方的CMake指南地址為:CMake Tutorial

一碧囊、CMake中添加對C++11的支持

1、在對應(yīng)的CMakeLists.txt文件中加入以下語句:

add_definitions(-std=c++11)

或者

 if(CMAKE_COMPILER_IS_GNUCXX)
      set(CMAKE_CXX_FLAGS "-std=c++11 -g ${CMAKE_CXX_FLAGS}")
 endif(CMAKE_COMPILER_IS_GNUCXX)

2纤怒、延伸 如何寫cmake使其包含c++11特性 (-std=c++11如何寫進cmakeList.txt)

使用的g++版本和cmake版本分別是g++ 4.8.2和cmake 2.8
之前寫cmkae編譯帶有c++11特性的代碼有這么一句:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

但是總會出現(xiàn)cc1plus: error: unrecognized command line option "-std=c++11" 報錯糯而。
所以set(QMAKE_CXXFLAGS "-std=c++11") 類似的寫法肯定不行。
后來發(fā)現(xiàn)是std=c++11 這種寫法老版本不支持泊窘。
ok
直接測試新寫法 CMakeLists.txt文件如下所示:

#CMakeLists.txt
project(test)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST}${PROJECT_NAME}.cpp)

include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
       set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
       set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
    message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()

測試c++11代碼如下:

//test.cc
#include <iostream>
#include<vector>
using namespace std; 
int main()
{
    const std::vector<int>v(1);
    auto a = v[0];//a為int類型
        cout <<"a : "<< a <<endl;
    decltype(v[0]) b = 0;//b為const int&類型熄驼,即std::vector<int>::operator[](size_type)const的返回類型
    auto c = 0;//c為int類型
    auto d = c;//d為int類型
    decltype(c) e;//e為int類型像寒,c實體的類型
    decltype((c)) f = e;//f為int&類型,因為(c)是左值
    decltype(0) g;//g為int類型瓜贾,因為0是右值
    
    return 0;
}

examples_CMake項目

github上面有一個韓國人jacking75寫的簡單的cmake使用示例诺祸,
examples_CMake項目地址是:https://github.com/jacking75/examples_CMake

CMake例子

范例介紹

示例代碼在CMake_example目錄中。

01 helloworld 一個簡單文件中的-C ++代碼
  • main.cpp
#include <iostream>

int main()
{
  auto name = "jacking";
  std::cout << "hello world: " << name << std::endl;
  return 0;
}
  • CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
add_definitions(-std=c++11)
add_executable(Main main.cpp)
02 helloworld-設(shè)置編譯器選項祭芦。 -Wall筷笨,C ++ 14
  • main.cpp
#include <iostream>

int main()
{
  auto name = "jacking";
  std::cout << "hello world: " << name << std::endl;
  return 0;
}
  • CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
add_definitions("-Wall -std=c++14")
add_executable(Main main.cpp)
03 helloworld-如果您有除主代碼文件以外的其他代碼文件
  • main.cpp
#include "test.h"

int main()
{
    TEST test;
    test.Print();
    return 0;
}
  • test.h
class TEST
{
public:
    void Print();
};
  • test.cpp
#include "test.h"

#include <iostream>

void TEST::Print()
{
    std::cout << "Test::Print" << std::endl;
}
  • CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
add_executable(Main
  main.cpp
  test.cpp
)
04 helloworld-如果mai.cpp以外的文件位于其他目錄中

源代碼04_helloworld目錄結(jié)構(gòu)如下:

[root@ltcos01 04_helloworld]$ tree -L 2
.
├── CMakeLists.txt
├── main.cpp
├── test01
│   ├── test01.cpp
│   └── test01.h
└── test02
    ├── test02.cpp
    └── test02.h

2 directories, 6 files
  • main.cpp
#include "test01/test01.h"
#include "test02/test02.h"

int main()
{
  TEST01 test01;
  test01.Print();

  TEST02 test02;
  test02.Print();
  return 0;
}

test01目錄下 有test01.h和test01.cpp這兩個文件

  • test01/test01.h
class TEST01
{
public:
  void Print();
};
  • test01/test01.cpp
#include "test01.h"
#include <iostream>

void TEST01::Print()
{
    std::cout << "Test01::Print" << std::endl;
}

test02目錄下有test02.h和test02.cpp這兩個文件

  • test02/test02.h
class TEST02
{
public:
    void Print();
};
  • test02/test02.cpp
#include "test02.h"
#include <iostream>

void TEST02::Print()
{
    std::cout << "Test02::Print" << std::endl;
}
  • CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
add_executable(Main
  main.cpp
  test01/test01.cpp
  test02/test02.cpp
)
05 helloworld-reference 創(chuàng)建靜態(tài)文件后

05_helloworld源代碼目錄樹結(jié)構(gòu)如下所示:

[root@ltcos01 05_helloworld]$ tree -L 2
.
├── CMakeLists.txt
├── main.cpp
├── test01
│   ├── CMakeLists.txt
│   ├── test01.cpp
│   └── test01.h
└── test02
    ├── CMakeLists.txt
    ├── test02.cpp
    └── test02.h

2 directories, 8 files
  • main.cpp
#include "test01/test01.h"
#include "test02/test02.h"

int main()
{
    TEST01 test01;
    test01.Print();

    TEST02 test02;
    test02.Print();
    return 0;
}
  • CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
add_subdirectory(test01)                
add_subdirectory(test02)                
add_executable(Main main.cpp)
target_link_libraries(Main Test01 Test02)

test01目錄下有test01.h和test01.cpp以及相應(yīng)的CMakeLists.txt文件

  • test01/test01.h
class TEST01
{
public:
    void Print();
};
  • test01/test01.cpp
#include "test01.h"

#include <iostream>

void TEST01::Print()
{
    std::cout << "Test01::Print" << std::endl;
}
  • test01/CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
add_library(Test01 STATIC
  test01.cpp
)

上面的test01目錄下的CMakeLists.txt的add_library(Test01 STATIC test01.cpp)指令會生成相應(yīng)的靜態(tài)庫文件libTest01.a

test02目錄下和test01目錄結(jié)構(gòu)一樣,也有test02.h和test02.cpp以及相應(yīng)的CMakeLists.txt文件

  • test01/test02.h
class TEST02
{
public:
    void Print();
};
  • test02/test02.cpp
#include "test02.h"

#include <iostream>

void TEST02::Print()
{
    std::cout << "Test02::Print" << std::endl;
}
  • test02/CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
add_library(Test02 STATIC
  test02.cpp
)

同樣的龟劲,在上面的test02目錄下執(zhí)行cmake命令會生成相應(yīng)的靜態(tài)庫文件libTest02.a胃夏。具體操作過程如下:新建一個build目錄,然后進入到build目錄下執(zhí)行cmake ..運行上一級目錄即test02下的CMakeLists.txt文件昌跌,操作如下:

[root@ltcos01 test02]$ ls
build  CMakeLists.txt  test02.cpp  test02.h
[root@ltcos01 test02]$ cd build/
[root@ltcos01 build]$ ls
[root@ltcos01 build]$ cmake ..
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /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: /usr/bin/c++
-- Check for working CXX compiler: /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: /data/public/home/cchufeng/GithubProjects/examples_CMake/CMake_example/05_helloworld/test02/build
[root@ltcos01 build]$ make
Scanning dependencies of target Test02
[ 50%] Building CXX object CMakeFiles/Test02.dir/test02.cpp.o
[100%] Linking CXX static library libTest02.a
[100%] Built target Test02
[root@ltcos01 build]$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  libTest02.a  Makefile
[root@ltcos01 build]$ 
06 helloworld-指定編譯器
  • main.cpp
#include <iostream>

int main()
{
    auto name = "jacking";
  std::cout << "hello world: " << name << std::endl;
  return 0;
}
  • CMakeLists.txt
PROJECT(hello)

set(CMAKE_CXX_COMPILER g++)
add_definitions("-Wall -std=c++14")

ADD_EXECUTABLE(main main.cpp)
07 helloworld-使用外部庫(此處為Boost庫)
  • main.cpp
#include <boost/thread.hpp>
#include <iostream>

int main()
{
    std::cout << "Boost.Thread !!!" << std::endl;
    boost::thread Thread1( [] ()
    {
        for( int i = 0; i < 5; ++i )
        {
            std::cout << "Thread Num : " << i << std::endl;
        }
    } );

    Thread1.join();
    return 0;
}
  • CMakeLists.txt
PROJECT(hello)

set(CMAKE_CXX_COMPILER g++)
set(CMAKE_CXX_FLAGS "-m64")
add_definitions("-Wall -std=c++14")

INCLUDE_DIRECTORIES(/$ENV{HOME}/Dev/C++/ThirdParty/boost_1_60_0)
LINK_DIRECTORIES(/$ENV{HOME}/Dev/C++/ThirdParty/boost_1_60_0/stage/gcc/lib)

ADD_EXECUTABLE(hello-boost hello-boost.cpp)

TARGET_LINK_LIBRARIES(hello-boost pthread boost_thread boost_system boost_chrono)

參考資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仰禀,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蚕愤,更是在濱河造成了極大的恐慌答恶,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萍诱,死亡現(xiàn)場離奇詭異亥宿,居然都是意外死亡,警方通過查閱死者的電腦和手機砂沛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門烫扼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人碍庵,你說我怎么就攤上這事映企。” “怎么了静浴?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵堰氓,是天一觀的道長。 經(jīng)常有香客問我苹享,道長双絮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任得问,我火速辦了婚禮囤攀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宫纬。我一直安慰自己焚挠,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布漓骚。 她就那樣靜靜地躺著蝌衔,像睡著了一般榛泛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上噩斟,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天曹锨,我揣著相機與錄音,去河邊找鬼剃允。 笑死艘希,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的硅急。 我是一名探鬼主播覆享,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼营袜!你這毒婦竟也來了撒顿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤荚板,失蹤者是張志新(化名)和其女友劉穎凤壁,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跪另,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡拧抖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了免绿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唧席。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖嘲驾,靈堂內(nèi)的尸體忽然破棺而出淌哟,到底是詐尸還是另有隱情,我是刑警寧澤辽故,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布徒仓,位于F島的核電站,受9級特大地震影響誊垢,放射性物質(zhì)發(fā)生泄漏掉弛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一喂走、第九天 我趴在偏房一處隱蔽的房頂上張望殃饿。 院中可真熱鬧,春花似錦缴啡、人聲如沸壁晒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秒咐。三九已至,卻和暖如春碘裕,著一層夾襖步出監(jiān)牢的瞬間携取,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工帮孔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留雷滋,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓文兢,卻偏偏與公主長得像晤斩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子姆坚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355