cmake 是什么让蕾?
cmake 是一個跨平臺的項目構(gòu)建工具,它使用與平臺無關(guān)的CMakeLists.txt 文件來指定各個項目的編譯過程或听。為什么要用cmake呢探孝?一是因為make 對windows平臺不友好,二是make管理大型項目特別麻煩誉裆。詳細討論可以參考知乎里面的討論[1]顿颅,總而言之,cmake 是寫大型項目必不可少的工具足丢,當然c++20 里面引入Modules后粱腻,會不會有其他的構(gòu)建工具不得而知。
編譯鏈接
用gcc 編譯源文件為可執(zhí)行程序
gcc -O2 -g -o p test.c
那么是gcc 是如何將源文件編譯成可執(zhí)行程序呢斩跌?書上[3]講解大概有四個步驟
- gcc運行C預(yù)處理器(cpp)將源文件翻譯成一個ascii碼文件test.i
- gcc在運行c編譯器(cc1)將test.i翻譯成匯編文件test.s (編譯原理主要內(nèi)容)
- gcc 在運行匯編器(as)將test.s翻譯成可重定位目標文件test.o
- gcc 最后運行鏈接器(ld) 將test.o 和一些必要的系統(tǒng)目標文件組合起來绍些,生成可執(zhí)行目標文件
如果需要觀察以上過程,可以執(zhí)行
gcc -O2 -g -o -v p test.c
如果需要觀察這些臨時文件耀鸦,可以執(zhí)行
gcc -save-temps test.c
目標文件的分類:
- 可重定位目標文件 :包含二進制代碼和數(shù)據(jù)柬批,其形式可以在編譯鏈接時候與其他可重定位文件合并,創(chuàng)建可執(zhí)行的目標文件袖订。
- 可執(zhí)行目標文件 :包含二進制代碼和數(shù)據(jù)萝快,其形式可以被直接拷貝到存儲器并執(zhí)行。
- 共享目標文件:一種特殊類型的可重定位目標文件著角,可以在加載或者運行時被動態(tài)的加載到存儲器并鏈接揪漩。
如何查看目標文件呢?可以通過readelf這個工具查看吏口,詳細解釋也可以查看[4]
readelf -a main.o
處理目標文件的工具:
ar: 創(chuàng)建靜態(tài)庫奄容,插入冰更、刪除、列出和提取成員
strings: 列出一個目標文件所有可打印的字符串信息
strip: 從目標文件中刪除符號表信息
nm: 列出目標文件的符號表中定義的符號
size:列出目標文件中結(jié)的名字和大小
readelf:顯示目標文件的完整結(jié)構(gòu)昂勒,包括ELF頭中編碼的所有信息蜀细。包含size和nm的功能
objdump: 可以反匯編.text結(jié)中的二進制指令
LDD: 列出可執(zhí)行文件運行時的共享庫
鏈接器的作用
符號解析和重定位
cmake 學(xué)習
構(gòu)建一個可執(zhí)行目標文件:
add_libary(archive archive.cpp zip.cpp lzma.cpp)
add_executable(zipapp zipapp.cpp)
target_link_libraries(zipapp archive)
archive 是一個靜態(tài)庫,它是由archive.cpp zip.cpp lzma.cpp 編譯得到的,zipapp 是一個可執(zhí)行的目標文件戈盈,它是由zipapp.cpp 編譯鏈接得到的奠衔,但是同時需要用到archive 這個靜態(tài)庫。
庫的類型
動態(tài)鏈接庫
add_library(archive SHARED archive.cpp zip.cpp lzma.cpp)
靜態(tài)庫
add_library(archive STATIC archive.cpp zip.cpp lzma.cpp)
MODULE
add_library(archive MODULE 7z.cpp)
不同之處在于他不用于
target_link_libraries()
塘娶,它在運行時作為插件加載归斤。
OBJECT
add_library(archive OBJECT archive.cpp zip.cpp lzma.cpp)
add_library(archiveExtras STATIC $<TARGET_OBJECTS:archive> extras.cpp)
add_executable(test_exe $<TARGET_OBJECTS:archive> test.cpp)
或者
add_library(archive OBJECT archive.cpp zip.cpp lzma.cpp)
add_library(archiveExtras STATIC extras.cpp)
target_link_libraries(archiveExtras PUBLIC archive)
add_executable(test_exe test.cpp)
target_link_libraries(test_exe archive)
編譯時的特性
因為c語言有不同版本,c++也有不同的版本刁岸,當你用c++11脏里,編譯器 卻用-std99肯定是出現(xiàn)錯誤,于是為了設(shè)置編譯器的版本類型虹曙,同時為了讓編譯器支持不同的語言特性迫横,我們可以使用target_compile_features()
這個命令
add_library(mylib requires_constexpr.cpp)
# cxx_constexpr is a usage-requirement
target_compile_features(mylib PUBLIC cxx_constexpr)
# main.cpp will be compiled with -std=gnu++11 on GNU for cxx_constexpr.
add_executable(myexe main.cpp)
target_link_libraries(myexe mylib)
target_compile_features(mylib PUBLIC cxx_std_11)
同時cmake 還有一些優(yōu)化編譯和條件編譯的命令可供選擇,詳細可以查看文檔.
Cmake 支持的編譯器
AppleClang: Apple Clang for Xcode versions 4.4 though 9.2.
Clang: Clang compiler versions 2.9 through 6.0.
GNU: GNU compiler versions 4.4 through 8.0.
MSVC: Microsoft Visual Studio versions 2010 through 2017.
SunPro: Oracle SolarisStudio versions 12.4 through 12.6.
Intel: Intel compiler versions 12.1 through 17.0.
Cmake 支持的語言
all compilers and versions listed above for C++.
GNU: GNU compiler versions 3.4 through 8.0.
[1] https://www.zhihu.com/question/27455963
[2] https://cmake.org/cmake/help/v3.12/#reference-manuals
[3] http://csapp.cs.cmu.edu/
[4] https://blog.csdn.net/xuehuafeiwu123/article/details/72963229