最後你崩潰了,你開始詛咒這個世界,專案結構就是專案結構啊,為什麼他們要逼你寫那麼多不一樣的東西?
於是在血與淚的吶喊中,Cmake誕生了,這是一個跨平台組織專案的工具,專門處理剪不斷理還亂的專案結構,她對於最擾人的C/C++專案特別有辦法,以下我將簡單示範用Cmake組織基本C專案的方法:
檔案結構
build /
src /
CMakeLists.txt
App_Path /
CMakeLists.txt
main.c
Old_Path /
old.h
Old.lib
New_Path /
CMakeLists.txt
Old_Path /
old.h
Old.lib
New_Path /
CMakeLists.txt
new.h
new.h
new.h
檔案內容說明
src/CMakeLists.txt:專案結構的起點,放置於原始碼的樹狀結構頂端
# 要求使用的Cmake的最低版本,怕麻煩可直接填你使用的Cmake版本,以後忽略說明
cmake_minimum_required( VERSION 2.6 )
# RUNTIME的意思是執行檔,表示把編譯出的執行檔輸出到${CMAKE_BINARY_DIR}/bin底下
# ${CMAKE_BINARY_DIR}之後說明
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
# ARCHIVE的意思是靜態函數庫,表示把編譯出的庫輸出到${CMAKE_BINARY_DIR}/lib底下
# Linux底下是 .a檔;Win32底下是 .lib檔
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
# 加入一個引入表頭檔的路徑,${CMAKE_SOURCE_DIR}表示原始碼的樹狀結構頂端及包含這個CMakeLists.txt的src
# 事實上只要包含CMakeLists.txt的檔案夾都可以被視為${CMAKE_SOURCE_DIR},所以需要在Cmake下指令時決定
include_directories( ${CMAKE_SOURCE_DIR} )
# 為原始碼的樹狀結構加入子檔案夾,注意Old_Path並不需要編譯,所以沒加進樹狀結構
add_subdirectory( New_Path )
add_subdirectory( App_Path )
到這裡先停下來說明我已經做了什麼:
1. 用cmake_minimum_required指定了Cmake的最低版本
2. 用set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ... 指定了執行檔的輸出位置
3. 用set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ... 指定了靜態庫的輸出位置
4. 用include_directories加入了表頭檔的參考路徑
5. 用add_subdirectory擴展了專案的結構
到目前為止我們已經有了專案結構的輪廓,現在來描述其內容:
Old_Path /
old.h:簡單的表頭檔內容不需說明
char* old_fun(void);
Old.lib:已經編譯好的靜態庫
Old_Path下的檔在在編譯時需要,但沒啥需要說明的
New_Path /
new.h:簡單的表頭檔內容不需說明
char* new_fun(void);
new.c:簡單的原始碼內容不需說明
#include "new.h"
static char str[16] = "new lib ! >w<";
char *
new_fun(void)
{
return str;
}
CMakeLists.txt:描述如何將new.h、new.c編譯成靜態庫
# 略過
cmake_minimum_required( VERSION 2.6 )
# project表示建立一個專案,一個完整的編譯動作如編譯執行檔或靜態庫都需要,名稱不拘
project( new_lib )
# add_library表示這個專案會產生一個庫,New是庫的名稱,STATIC表示要產生靜態庫,new.c表示產生庫時需要的檔案,若有很多個檔案只需以空白分隔一直往下寫
add_library( New STATIC new.c )
注意到New_Path資料夾本身也是一個完整的專案,若將Cmake的${CMAKE_SOURCE_DIR}設定於此,最後的結果將產生New.lib,之前在src下的CMakeLists.txt中並沒有project敘述但卻加入了子檔案夾,這表示src下的專案並不輸出檔案,而是遞迴往下組織子檔案夾下的專案,而因為set敘述,New_Path輸出的靜態庫也會被放到${CMAKE_BINARY_DIR}/bin中,有關CMAKE_BINARY_DIR與CMAKE_SOURCE_DIR,之後會在講解。
App_Path /
main.c:最後的程式,需要Old.lib與New.lib作靜態連結,由於已經使用include_directories將../src當成引入標頭檔的路徑,所以能找到相對路徑上的Old_Path與New_Path,不需說明
#include <stdio.h>
#include "Old_Path/old.h"
#include "New_Path/new.h"
int
main ()
{
puts(old_fun());
puts(new_fun());
}
CMakeLists.txt:描述如何產生執行檔的檔案
# 略過
cmake_minimum_required( VERSION 2.6 )
# 我們需要產生執行檔,略過
project( cmake_demo )
# ADD_LIBRARY表示Old庫會被引入,STATIC表示其為靜態庫,IMPORTED表示從專案結構外引入
ADD_LIBRARY( Old STATIC IMPORTED )
# SET_PROPERTY將設定Old的屬性,PROPERTY IMPORTED_LOCATION表示要設定引入路徑,${CMAKE_SOURCE_DIR}/Old_Path/Old.lib是其路徑加上完整名稱
SET_PROPERTY( TARGET Old PROPERTY IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/Old_Path/Old.lib )
# add_executable表示專案要產生名為App的執行檔,需要用到main.c檔,若有很多檔案一樣用空白分格繼續接
add_executable( App main.c )
# target_link_libraries表示執行檔App會使用Old與New作靜態連結,以空白分隔不是很明顯
# 注意到New並不需要ADD_LIBRARY,因為它存在於專案結構中,不需由外部引入
target_link_libraries( App Old New )
OK,來說明一下整個專案結構最後會做什麼吧:
1. Old.lib會從外部被引入,外部指的是不在原始碼的樹狀結構中,記得add_subdirectory並沒有加入她對吧
2. New.lib會被編譯出來,並被放入${CMAKE_BINARY_DIR}/lib中
3. App.exe會被編譯出來,並被放入${CMAKE_BINARY_DIR}/bin中
最後來產生專案吧
1.
首先將當前資料夾移到Demo/build/底下,是的,當前資料夾就是你的${CMAKE_BINARY_DIR},所以最後New.lib會被放到Demo/build/lib/底下,而App.exe會被放到Demo/build/bin/底下
2.
鍵入:
> cmake --help
可以看到你可以產生哪些種類的編譯器的專案
3.
鍵入:
> cmake -G "Visual Studio 10" ../src
-G "Visual Studio 10"表示要產生讓VS2010使用的專案檔,你應該用--help查看適合你有的編譯器並更改這段指令
../src指定了${CMAKE_SOURCE_DIR},所以Demo/src/就是你的原始碼的樹狀結構頂端,當然,如果你指定的是../src/New_Path/,那麼原始碼的樹狀結構頂端就是Demo/src/New_Path/,最後專案就只會產生New.lib,而且因為跳過了set敘述,所以New.lib會被輸出到編譯器預設的地方
4. 來編譯吧
最後Demo/build會出現完整的專案組態檔,以Linux來說你現在只要使用make就能在Demo/build/bin/底下得到App.exe,在Win32上就是使用VS囉,最後檔案結構應該會是:
Demo /
build /
bin/
Debug/App.exe
lib/
Debug/New.lib
...
src /
CMakeLists.txt
App_Path /
CMakeLists.txt
build /
bin/
Debug/App.exe
lib/
Debug/New.lib
...
src /
CMakeLists.txt
App_Path /
CMakeLists.txt
main.c
Old_Path /
old.h
Old.lib
New_Path /
CMakeLists.txt
Old_Path /
old.h
Old.lib
New_Path /
CMakeLists.txt
new.h
new.h
new.h
如果你很好奇有Debug怎麼沒有Realse,或是動態庫該怎麼使用,你在安裝Cmake後應該可以找到她的說明文件,Cmake已經被使用在多個大型專案中並得到成功,或許他能給你幫助、改善你的生活,如果你對本文的範例有興趣,載點在此。
沒有留言:
張貼留言