看了半天的手冊,這個基於CMake的通用模板總算是能工作了。
實現的功能是:將CMakeLists.txt放於源代碼目錄,在源代碼所在目錄的任意一個子目錄下(一般是build)執行“cmake .. && make”,將自動將所有文件中包含main函數的代碼作為目標批量生成。
目前這個版本有一些缺陷,一就是build目錄與源文件所在目錄的相對位置是固定的,因為我習慣在源文件目錄下的build目錄進行創建,所以這個腳本只能在 ${SOURCE_DIR}/build 目錄下生效。
另外一個缺陷就是我使用了bash命令,大致使用了egrep,cut和wc,可移植性不好。可能用純CMake命令也能實現目前的功能,不過我目前不想再去RTFM了。
第三個缺陷正如手冊中對aux_source_directory中提及的,在源目錄添加新文件並不會使CMake重新配置,因為CMakeLists.txt沒有被修改(事實上你一旦填寫好你的外部包含路徑、庫路徑和需要加入的庫,這個列表文件將不再需要任何修改),所以你必須在添加新文件后手動更新。當然這並不會很麻煩,我寧願手動更新一遍也不願意為一個新的目標而去修改列表文件。
這個文件模板如下:
cmake_minimum_required (VERSION 2.6) project (BuildAll) # some 3rd-party/customed include/link path include_directories (/home/jeremy/projects/include) link_directories(/home/jeremy/projects/include /home/jeremy/projects/lib) # some options / settings # ... # # add external libraries set (EXTRA_LIBS ${EXTRA_LIBS} ???} aux_source_directory (. SRC_LIST) # get source files holding main() function execute_process ( COMMAND echo ${SRC_LIST} COMMAND xargs egrep "main[ \t]*(.*)[ \t]*$" -l WORKING_DIRECTORY .. # NOTICE: Assumed build directory is ${SOURCE_DIR}/build, so # You may change the value of WORKING_DIRECTORY to suit your needs OUTPUT_VARIABLE TARGET_LIST ) string (REGEX REPLACE "\n$" "" TARGET_LIST ${TARGET_LIST}) # count number of targets execute_process ( COMMAND echo ${TARGET_LIST} COMMAND wc -l OUTPUT_VARIABLE TARGET_NUM ) # convert string from "./$1\n./$2\n..." to "$1 $2 ..." string (REGEX REPLACE "[.]/" "" TARGET_LIST ${TARGET_LIST}) string (REGEX REPLACE "\n" " " TARGET_LIST ${TARGET_LIST}) enable_testing () foreach ( i RANGE 1 ${TARGET_NUM}) execute_process ( COMMAND echo "${TARGET_LIST}" COMMAND cut -d " " -f ${i} OUTPUT_VARIABLE SRC ) string (REGEX REPLACE "\n" "" SRC ${SRC}) string (REGEX REPLACE "[.]cpp$" ".elf" ELF ${SRC}) add_executable (${ELF} ${SRC}) target_link_libraries (${ELF} ${EXTRA_LIBS}) add_test (${ELF}_Runs ${ELF}) endforeach (i) # do sth more, like add more tests...#
之所以會想寫一個這樣功能的CMakeLists.txt,原因很簡單,因為現在在學習階段經常要寫大量簡單小巧的練習代碼,為每個這樣規模的代碼建立一個項目或者建立一個目錄顯然都太過麻煩,現在有了這個文件,我就可以把所有源代碼放在一塊,統一生成、測試。所以我認為CMake和make之間是至少差了一個世代的,至少CMake對我來說要更加簡單和智能,實現同樣功能需要的代碼量和RTFM時間都要少得多。
生成的目標帶后綴名是個好主意,雖然很多linuxer認為Linux下二進制文件沒有后綴名顯得很酷很專業,但我這樣選擇的好處就是我可以很方便地執行像“rm *.elf ”或者“mv *.elf SOME/WHERE”之類的操作。