2012-06-04 27 views
86

我想知道是否有用於Makefile S(make)和CMakeLists.txtcmake)任何示例代碼都做同樣的事情(唯一的區別在於,一個是寫在make,另一個在cmake)。Cmake vs製作示例代碼?

我試圖尋找「cmake的VS製作」,但我從來沒有發現任何代碼的比較。理解差異會非常有幫助,即使只是一個簡單的例子。

+15

+1這是一個很好的問題;當我開始使用'cmake'時,我也想這樣做。但我懷疑你會發現它,因爲這些功能不能很好地映射到另一個。如果你試圖讓'cmake'像'make'一樣行事,那麼你會認真對待自己。最好從頭開始。 'make'中的微不足道的事情涉及'cmake',反之亦然。 –

+0

@ ErnestFriedman-Hill你有更多的細節嗎?所以'make'和'cmake'是如此獨特,以至於它們應該被看作是互補而非競爭工具呢? –

+1

@Shurane - cmake本身並不構建任何東西;它會創建Makefiles(以及其他類似的構建腳本),然後運行它。因此,無論何時編寫cmake文件,都必須考慮命令是應該在生成時間期間還是在編譯期間應用。有些動作 - 複製一個通配符組文件在構建時,例如 - 是相當複雜的,相比「'CP * .X $(OUTDIR)'」你在一個Makefile寫。也許,我最討厭的是,所產生的Makefile文件設計完全不可移植的,不靈活(續) –

回答

5

抓鬥使用的CMake作爲其構建系統的一些軟件(有許多開源項目,從作爲一個例子選擇)。獲取源代碼並使用CMake進行配置。閱讀結果makefile並享受。

有一點要記住,這些工具沒有映射一個對一個。最明顯的區別是CMake會掃描不同文件(例如C頭文件和源文件)之間的依賴關係,而make會將其留給makefile作者。

92

以下Makefile將從源 prog1.c, prog2.c, prog3.c and main.c構建一個名爲prog的可執行文件。 prog是針對libmystatlib.alibmydynlib.so這兩者都是從同樣內置來源鏈接。此外,prog使用 在stuff/liblibstuff.a及其stuff/include頭。該 Makefile文件默認情況下建立一個公佈目標,而且還提供了一個調試目標:

#Makefile  
CC = gcc 
CPP = g++ 
RANLIB = ar rcs 
RELEASE = -c -O3 
DEBUG = -c -g -D_DEBUG 
INCDIR = -I./stuff/include 
LIBDIR = -L./stuff/lib -L. 
LIBS = -lstuff -lmystatlib -lmydynlib 
CFLAGS = $(RELEASE) 

PROGOBJS = prog1.o prog2.o prog3.o 

prog: main.o $(PROGOBJS) mystatlib mydynlib 
    $(CC) main.o $(PROGOBJS) $(LIBDIR) $(LIBS) -o prog 
debug: CFLAGS=$(DEBUG) 
debug: prog 

mystatlib: mystatlib.o 
    $(RANLIB) libmystatlib.a mystatlib.o 
mydynlib: mydynlib.o 
    $(CPP) -shared mydynlib.o -o libmydynlib.so 

%.o: %.c 
    $(CC) $(CFLAGS) $(INCDIR) $< -o [email protected] 
%.o: %.cpp 
    $(CPP) $(CFLAGS) $(INCDIR) -fPIC $< -o [email protected] 

這裏是一個CMakeLists.txt,做(幾乎)完全一樣,有一些意見強調 相似之處的Makefile:

#CMakeLists.txt  
cmake_minimum_required(VERSION 2.8)     # stuff not directly 
project(example)          # related to building 

include_directories(${CMAKE_SOURCE_DIR}/stuff/include) # -I flags for compiler 
link_directories(${CMAKE_SOURCE_DIR}/stuff/lib)  # -L flags for linker 

set(PROGSRC prog1.c prog2.c prog3.c)     # define variable 

add_executable(prog main.c ${PROGSRC})     # define executable target prog, specify sources 
target_link_libraries(prog mystatlib mydynlib stuff) # -l flags for linking prog target 

add_library(mystatlib STATIC mystatlib.c)    # define static library target mystatlib, specify sources 

add_library(mydynlib SHARED mydynlib.cpp)    # define shared library target mydynlib, specify sources 
#extra flags for linking mydynlib 
set_target_properties(mydynlib PROPERTIES POSITION_INDEPENDENT_CODE TRUE) 
#alternatively: 
#set_target_properties(mydynlib PROPERTIES COMPILE_FLAGS "-fPIC") 

在這個簡單的例子,最重要的區別是:

  • CMake的REC確認使用哪種編譯器來源。而且,它爲每種類型的目標調用正確的命令序列。因此, 沒有像$(CC)...,$(RANLIB)等命令的明確說明。

  • 所有通常的編譯器/鏈接器標誌處理包含頭文件,庫等。 被獨立於平臺/構建系統的命令取代。

  • 調試標誌由任一設定可變CMAKE_BUILD_TYPE包括以「調試」, 或通過調用程序時將它傳遞給CMake的:cmake -DCMAKE_BUILD_TYPE:STRING=Debug

  • 的CMake還提供「-fPIC」標誌的平臺無關納入(通過 的POSITION_INDEPENDENT_CODE屬性)和其他許多人。儘管如此,更復雜的設置可以通過CMake以及Makefile(通過使用COMPILE_FLAGS 以及類似的屬性)手動實現。當第三方庫(如OpenGL)以便攜方式包含在內時,CMake當然會開始發光。

  • 構建過程有一個步驟,如果你使用一個Makefile,即在命令行中鍵入 make。對於CMake的,有兩個步驟:首先,你需要設置你的編譯環境(通過輸入你的build目錄cmake <source_dir>或通過運行一些GUI客戶端)。這會根據您選擇的構建系統(例如,在Unix或VC++或Windows上的MinGW + Msys上創建)創建一個Makefile或類似的東西。構建系統可以作爲參數傳遞給CMake;但是,CMake會根據您的系統配置進行合理的默認選擇。其次,您在選定的構建系統中執行實際構建。

來源和構建說明可在https://github.com/rhoelzel/make_cmake

+2

是不是Makefile過於複雜?通過使用'CPPFLAGS'而不是'INCDIR',人們可以使用內置的規則,並且編譯器的顯式調用將會是多餘的。同樣,對於ar的處理,內置的規則也可以覆蓋它。另外,爲什麼明確設置「CPP」和「CC」?它們已經被'make'設置爲很好的值,它們是預定義的變量。 'make'還可以識別哪種編譯器用於哪種源,內置規則很多。 –

+2

哦,對於'RELEASE',缺少'-DNDEBUG' ... –

+1

這些變量中的很多應該用':='而不是'='來分配。 –