Makefile和Cmake的聯絡與區別
CMake是一種跨平臺編譯工具,比make更為高階,使用起來要方便得多。CMake主要是編寫CMakeLists.txt檔案,然後用cmake命令將CMakeLists.txt檔案轉化為make所需要的makefile檔案,最後用make命令編譯原始碼生成可執行程式或共享庫(so(shared object)).它的作用和qt的qmake是相似的。
C/C++程式設計師肯定離不開Makefile和Cmake,因為如果對這兩個工具不熟悉,那麼你就不是一個合格的C/C++程式設計師。本文對Makefile和Cmake,及它們的使用進行了詳細的介紹,本文的目錄如下:
一、Makefile詳解
1.1 Makefile語法
1.2 Makefile示例
二、Cmake詳解
2.1 Cmake語法
2.2 Cmake示例
一、Makefile詳解
Makefile描述了整個工程的編譯、連線等規則,makefile定義了一些列規則來指定,哪些檔案需要編譯以及如何編譯、需要建立哪些庫檔案以及如何建立這些庫檔案、如何產生我們想要的可執行檔案。使用Makefile,整個工程都可以完全自動化編譯。而且Makefile 可以有效的減少編譯和連線的程式,只編譯和連線那些修改的檔案。
1.1 Makefile語法
1.1.1
Makefile包含了五個重要的東西:顯示規則、隱晦規則、變數定義、檔案指示和註釋。
1. 顯示規則:顯示規則說明了,如何生成一個或多個目標。這是由Makefile指出要生成的檔案和檔案依賴的檔案。
2. 隱晦規則:基於Makefile的自動推導功能
3. 變數的定義:一般是字串
4. 檔案指示:一般是在Makefile中引用另外一個makefile檔案;根據某些規則指定Makefile中有效的部分;多行
5. 註釋:#指示註釋
Makefile有三個非常重要的變數:[email protected]、$^、$#,它們的含義如下:
[email protected] ---目標檔案
$^ ---所有依賴檔案
$< ---第一個依賴檔案
.PHONY ---偽目標檔案
Makefile的執行過程如下:
1. 在當前目錄下尋找Makefile或makefile。
2. 找到第一個檔案中的第一個目標檔案,和目標檔案依賴的.o檔案。
3. 如果.o檔案不存在,或是後面.o檔案比target檔案更新,那麼它就會執行後面的語句來生成這個檔案。
4. 最後makefile會根據.o檔案依賴的.h和.c檔案生成.o檔案。
1.1.2
注意:
1. clean不要放在target前面。
2. -rm edit $(objects) 忽略某些檔案的問題。
3. Makefile中的命令,必須以[Tab]鍵分割。檔案之間最好使用空格分割。
4. -I 或 --include-dir 引數,那麼make就會在這些目錄下去尋找。
5. -L 相當於load lib dir, -lfb303 相當於libfb303.so
1.1.3 g++編譯命令:
1. -g 相當於debug
2. -Wall 相當於忽略warnning
3. -O1~3 相當於優化級別
4. -lpthread多執行緒
5. -j8 多執行緒編譯
6. -D相當於巨集定義,-D_YUQIANG,那麼#ifdef _YUQIANG就是True的。
1.2 Makefile示例
[cpp] view plain copy
- CC = gcc
- RM = rm
- CFLAGS += -D _YUQIANG
- TARGETS := myapp
- all:$(TARGETS)
- $(TARGETS):main.c
- $(CC) $(CFLAGS) $^ -o [email protected]
- clean:
- -$(RM) -f *.o
- -$(RM) -f $(TARGETS)
二、CMake詳解
CMake是一個誇平臺的安裝(編譯)工具,可以簡單的語句描述所有平臺的安裝(編譯過程)。它能輸出各種各樣的makefile或者project檔案,能測試編譯器所支援的c++特性,類似UNIX下的automake。
2.1 Cmake語法
1. project name
PROJECT( project name )
2. 標頭檔案路徑
INCLUDE_DIRECTORIES( include )
3. 設定環境變數的值
SET( TEST_DIR ${DIR_SRCS})
4. 設定外部庫
SET(LIBRARIES libm.so)
5. 設定可執行檔案路徑
ADD_EXECUTABLE( ../bin/bin ${TEST_DIR})
6. 設定連結庫
TARGET_LINK_LIBRARIES(../bin/bin ${LIBRARIES})
7. 設定程式碼子目錄
ADD_SUBDIRECTORY
2.2 CMake示例
[cpp] view plain copy
- #project name
- PROJECT(test_math)
- #head file path
- INCLUDE_DIRECTORIES(
- include
- )
- #source directory
- AUX_SOURCE_DIRECTORY(src DIR_SRCS)
- #set environment variable
- SET(TEST_MATH
- ${DIR_SRCS}
- )
- #set extern libraries
- SET(LIBRARIES
- libm.so
- )
- #add executable file
- ADD_EXECUTABLE(../bin/bin ${TEST_MATH})
- #add link library
- TARGET_LINK_LIBRARIES(../bin/bin ${LIBRARIES}
1.CMake編譯原理
CMake是一種跨平臺編譯工具,比make更為高階,使用起來要方便得多。CMake主要是編寫CMakeLists.txt檔案,然後用cmake命令將CMakeLists.txt檔案轉化為make所需要的makefile檔案,最後用make命令編譯原始碼生成可執行程式或共享庫(so(shared object))。因此CMake的編譯基本就兩個步驟:
1. cmake 指向CMakeLists.txt所在的目錄,例如cmake .. 表示CMakeLists.txt在當前目錄的上一級目錄。cmake後會生成很多編譯的中間檔案以及makefile檔案,所以一般建議新建一個新的目錄,專門用來編譯, mkdir build cd build cmake .. make 2. make 根據生成makefile檔案,編譯程式。
2.使用Cmake編譯程式
我們編寫一個關於開平方的C/C++程式專案,即b= sqrt(a),以此理解整個CMake編譯的過程。
a.準備程式檔案
檔案目錄結構如下:
. ├── build ├── CMakeLists.txt ├── include │ └── b.h └── src ├── b.c └── main.c
b.編寫CMakeLists.txt
接下來編寫CMakeLists.txt檔案,該檔案放在和src,include的同級目錄,實際方哪裡都可以,只要裡面編寫的路徑能夠正確指向就好了。CMakeLists.txt檔案,如下所示:
1 #1 .cmake verson,指定cmake版本 2 cmake_minimum_required(VERSION 3.2 ) 3 4 #2 .project name,指定專案的名稱,一般和專案的資料夾名稱對應 5 PROJECT(test_sqrt) 6 7 #3 .head file path,標頭檔案目錄 8 INCLUDE_DIRECTORIES( 9 include 10 ) 11 12 #4 .source directory,原始檔目錄 13 AUX_SOURCE_DIRECTORY(src DIR_SRCS) 14 15 #5 .set environment variable,設定環境變數,編譯用到的原始檔全部都要放到這裡,否則編譯能夠通過,但是執行的時候會出現各種問題,比如" symbol lookup error xxxxx , undefined symbol " 16 SET(TEST_MATH 17 ${DIR_SRCS} 18 ) 19 20 #6 .add executable file ,新增要編譯的可執行檔案 21 ADD_EXECUTABLE(${PROJECT_NAME} ${TEST_MATH}) 22 23 #7 .add link library,新增可執行檔案所需要的庫,比如我們用到了libm.so(命名規則:lib+name+.so),就新增該庫的名稱 24 TARGET_LINK_LIBRARIES(${PROJECT_NAME} m)
CMakeLists.txt主要包含以上的7個步驟,具體的意義,請閱讀相應的註釋。
c.編譯和執行程式
準備好了以上的所有材料,接下來,就可以編譯了,由於編譯中出現許多中間的檔案,因此最好新建一個獨立的目錄build,在該目錄下進行編譯,編譯步驟如下所示:
mkdir build cd build cmake .. make
操作後,在build下生成的目錄結構如下:
├── build │ ├── CMakeCache.txt │ ├── CMakeFiles │ │ ├── 3.2 .2 │ │ │ ├── CMakeCCompiler.cmake │ │ │ ├── CMakeCXXCompiler.cmake │ │ │ ├── CMakeDetermineCompilerABI_C.bin │ │ │ ├── CMakeDetermineCompilerABI_CXX.bin │ │ │ ├── CMakeSystem.cmake │ │ │ ├── CompilerIdC │ │ │ │ ├── a.out │ │ │ │ └── CMakeCCompilerId.c │ │ │ └── CompilerIdCXX │ │ │ ├── a.out │ │ │ └── CMakeCXXCompilerId. cpp │ │ ├── cmake.check_cache │ │ ├── CMakeDirectoryInformation.cmake │ │ ├── CMakeOutput.log │ │ ├── CMakeTmp │ │ ├── feature_tests.bin │ │ ├── feature_tests.c │ │ ├── feature_tests.cxx │ │ ├── Makefile2 │ │ ├── Makefile.cmake │ │ ├── progress.marks │ │ ├── TargetDirectories.txt │ │ └── test_sqrt. dir │ │ ├── build. make │ │ ├── C.includecache │ │ ├── cmake_clean.cmake │ │ ├── DependInfo.cmake │ │ ├── depend.internal │ │ ├── depend. make │ │ ├── flags. make │ │ ├── link.txt │ │ ├── progress. make │ │ └── src │ │ ├── b.c.o │ │ └── main.c.o │ ├── cmake_install.cmake │ ├── Makefile │ └── test_sqrt ├── CMakeLists.txt ├── include │ └── b.h └── src ├── b.c └── main.c
注意在build的目錄下生成了一個可執行的檔案test_sqrt,執行獲取結果如下:
命令: ./test_sqrt 結果: input a: 49.000000 sqrt result: 7.000000
參考文獻:
1. Linux Makefile教程: http://blog.csdn.net/liang13664759/article/details/1771246
2. CMake 學習二: http://blog.sina.com.cn/s/blog_53b7ddf00101mjp5.html
3. CMake基本用法: http://blog.sina.com.cn/s/blog_68409a2801019bm7.html
1.gcc是GNU Compiler Collection(就是GNU編譯器套件),也可以簡單認為是編譯器,它可以編譯很多種程式語言(括C、C++、Objective-C、Fortran、Java等等)。
2.當你的程式只有一個原始檔時,直接就可以用gcc命令編譯它。
3.但是當你的程式包含很多個原始檔時,用gcc命令逐個去編譯時,你就很容易混亂而且工作量大
4.所以出現了make工具
make工具可以看成是一個智慧的批處理工具,它本身並沒有編譯和連結的功能,而是用類似於批處理的方式—通過呼叫makefile檔案中使用者指定的命令來進行編譯和連結的。
5.makefile是什麼?簡單的說就像一首歌的樂譜,make工具就像指揮家,指揮家根據樂譜指揮整個樂團怎麼樣演奏,make工具就根據makefile中的命令進行編譯和連結的。
6.makefile命令中就包含了呼叫gcc(也可以是別的編譯器)去編譯某個原始檔的命令。
7.makefile在一些簡單的工程完全可以人工手下,但是當工程非常大的時候,手寫makefile也是非常麻煩的,如果換了個平臺makefile又要重新修改。
8.這時候就出現了Cmake這個工具,cmake就可以更加簡單的生成makefile檔案給上面那個make用。當然cmake還有其他功能,就是可以跨平臺生成對應平臺能用的makefile,你不用再自己去修改了。
9.可是cmake根據什麼生成makefile呢?它又要根據一個叫CMakeLists.txt檔案(學名:組態檔)去生成makefile。
10.到最後CMakeLists.txt檔案誰寫啊?親,是你自己手寫的。
11.當然如果你用IDE,類似VS這些一般它都能幫你弄好了,你只需要按一下那個三角形
12.cmake是make maker,生成各種可以直接控制編譯過程的控制器的配置檔案,比如makefile、各種IDE的配置檔案。
13.make是一個簡單的通過檔案時間戳控制自動過程、處理依賴關係的軟體,這個自動過程可以是編譯一個專案。