前言
相較於 Makefile 的難維護, 有很多工具 "取而代之", 或者幫忙產生 Makefile.
其中 CMake 是個人認為目前較優的. 原因很多, 光 KDE 這麼龐大的計畫,
都可以透過它去完成編譯, 起碼也有相當的優勢.
OSS 的東西最怕的就是: 沒人維護, 沒人用! 沒人氣就沒人可以問, 可以協助了!
在 CMake 的 wiki 有提到幾支工具可以將現有的編譯系統轉成 CMake.
其中常用的 autotools 所列的幾支, 多半是給 KDE 用的, 其他案子不見得適用,
如果懂點 Ruby 的話, 倒是可以自己改看看.
關於 AutoTools, 可以參考 AutoBook
如果要轉成 CMake 系統, 就是要去 "翻譯" Makefile.am 和 configure.acMakefile.am
基本上和 Makefile 很接近, 因此很好轉譯. 例如:
SUBDIRS = . D1 D2 D3 |
就會變成
ADD_SUBDIRECTORY(D1) ADD_SUBDIRECTORY(D2) ADD_SUBDIRECTORY(D3) |
一些常用的 AutoMake 的 primary 例如 _DATA, _HEADERS, _LIBRARIES, _PROGRAMS, _SOURCES, etc.
就要用 ADD_LIBRARY(), ADD_EXECUTABL(), TARGET_LINK_LIBRARIES(), INSTALL() 等去描述.
像一些特別的 target 則須要手動自己加 ADD_CUSTOM_TARGET(), ADD_CUSTOM_COMMAND()
configure.ac
config.h.in
請留意 SIZEOF_LONG 的寫法. @SIZEOF_LONG@ 會被實際的值取代, 如果有的話.
TODO
configure.ac
這部分是比較麻煩的, 尤其是一些系統偵測的動作, CMake 也許不支援或者要用其他方式
config.h.in
產生的 config.h 是最常用來判定該產生怎樣的 code.
首先,
可以將 config.h.in 改名, 例如: config.h.cmake 或要沿用這個名字也無妨.
其次,
原先在 config.h.in 裡的定義要修改, 例如:
#undef HAVE_SOMETHING |
要改成
#cmakedefine HAVE_SOMETHING |
例如:
/* Define to 1 if you have the <stdlib.h> header file. */ #cmakedefine HAVE_STDLIB_H /* Whether we have alarm() */ #cmakedefine HAVE_ALARM /* The size of `long', as computed by sizeof. */ #define SIZEOF_LONG (@SIZEOF_LONG@) /* Name of package */ #cmakedefine PACKAGE |
就會變成
#define HAVE_STDLIB_H #define HAVE_ALARM #define SIZEOF_LONG (4) #define PACKAGE |
請留意 SIZEOF_LONG 的寫法. @SIZEOF_LONG@ 會被實際的值取代, 如果有的話.
另外, 是使用 define 而非 cmakedefine
CMakeLists.txt 裡的寫法是
CMakeLists.txt 裡的寫法是
INCLUDE (CheckIncludeFiles) CHECK_INCLUDE_FILES(stdlib.h HAVE_STDLIB_H) INCLUDE (CheckFunctionExists) CHECK_FUNCTION_EXISTS(alarm HAVE_ALARM) INCLUDE (CheckTypeSize) CHECK_TYPE_SIZE(long SIZEOF_LONG) SET(PACKAGE 1) # Generate build-path/config.h from config.h.in at source directory. CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) |
請留意 SET(PACKAGE 1) 的寫法. 因為我沒把 PACKAGE 的判讀方式轉換, 偷懶直接使用 SET()
在 config.h.in 裡, #cmakedefine PACKAGE 也可以改成 #define PACKAGE @PACKAGE@
而最後一行則是告訴 CMake 如何把 config.h.in 轉成 config.h
TODO
有些偵測系統的部分, 可能要實際編譯程式去跑. 這就有點麻煩.
可以參考 CMakePath/share/cmake-x.y/Modules 下的
FindThreads.cmake & CheckForPthreads.c
裡面 TRY_RUN() 的範例.
如果案子不大, 簡單的判斷會輕鬆多了.
像 OPTION(), CMAKE_BUILD_TYPE(), 及一些內建的 variable
判斷來決定 CMAKE_C_FLAGS.
沒有留言:
張貼留言