本文主要介紹如何將一個依賴 Makefile 項目(MIDG)移植到 CMake 上。
首先介紹項目文件結構,文件主要由三個目錄組成
- 3rdParty
- include
- src
其中,3rdParty
中包含兩個外部函數庫,即 Metis
與 ParMetis
,生成兩個靜態鏈接庫 libmetis.a
與 libparmetis.a
。 src
包含項目所有源程序, include
則包含了全部頭文件。
因此,我們在根目錄下 cmake 配置文件內容如下
cmake_minimum_required(VERSION 3.1)
project(DGOM)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
set(CMAKE_C_COMPILER /usr/local/bin/mpicc)
set(CMAKE_CXX_COMPILER /usr/local/bin/mpicxx)
# 3rdParty library
# Build with original makefile
set(METIS_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/lib/libmetis.a)
set(PARMETIS_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/lib/libparmetis.a)
add_custom_target(build_metis ALL
COMMAND ${CMAKE_MAKE_PROGRAM}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/3rdParty/ParMetis-3.1/METISLib/
COMMENT "Original metis makefile target")
add_custom_target(build_parmetis ALL
COMMAND ${CMAKE_MAKE_PROGRAM}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/3rdParty/ParMetis-3.1/ParMETISLib/
COMMENT "Original parmetis makefile target")
add_library(metis STATIC IMPORTED)
add_library(parmetis STATIC IMPORTED)
set_property(TARGET metis APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
set_target_properties(metis PROPERTIES IMPORTED_LOCATION_NOCONFIG "${METIS_LIBRARY}")
set_property(TARGET parmetis APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
set_target_properties(parmetis PROPERTIES IMPORTED_LOCATION_NOCONFIG "${PARMETIS_LIBRARY}")
add_dependencies(metis build_metis)
add_dependencies(parmetis build_parmetis)
# source file
add_subdirectory(src)
set(CMAKE_C_COMPILER mpicc)
,set(CMAKE_CXX_COMPILER mpicxx)
負責選擇項目編譯器,本項目中選擇mpich2
Metis
Parmetis
第三方庫采用原始 makefile 編譯,將編譯好的靜態庫文件添加到項目中
1. 3rdParty
3rdParty
目錄如下
./
└── ParMetis-3.1
├── METISLib
├── Manual
└── ParMETISLib
METISLib
與 ParMETISLib
分別為兩個不同的網格划分庫。原始make命令分別進入兩個項目所在目錄使用make
命令即可。因此,在主目錄 CMakeLists.txt
中調用 make
命令編譯庫函數,主要步驟如下:
1.1. 增加自定義編譯方法
add_custom_target(build_metis ALL
COMMAND ${CMAKE_MAKE_PROGRAM}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/3rdParty/ParMetis-3.1/METISLib/
COMMENT "Original metis makefile target")
add_custom_target(build_parmetis ALL
COMMAND ${CMAKE_MAKE_PROGRAM}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/3rdParty/ParMetis-3.1/ParMETISLib/
COMMENT "Original parmetis makefile target")
add_custom_target
通過用戶給定的指令來增加一個新的編譯目標。ALL
代表該目標添加到默認編譯目標中,因此每次編譯都會執行。
1.2. 增加兩個編譯目標
這兩個目標為外部庫 IMPORTED
,而非項目自己編譯的
add_library(metis STATIC IMPORTED)
add_library(parmetis STATIC IMPORTED)
set_property(TARGET metis APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
set_target_properties(metis PROPERTIES IMPORTED_LOCATION_NOCONFIG "${METIS_LIBRARY}")
set_property(TARGET parmetis APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
set_target_properties(parmetis PROPERTIES IMPORTED_LOCATION_NOCONFIG "${PARMETIS_LIBRARY}")
1.3. 將編譯目標與編譯方法聯系
確保首先執行編譯過程
add_dependencies(metis build_metis)
add_dependencies(parmetis build_parmetis)
2. 項目源文件
源文件編譯時候需要頭文件路徑,並且與第三方庫進行鏈接
set(SRC_LIST
Mesh2d.c Utils.c LoadBalance2d.c FacePair2d.c
ParallelPairs.c BuildMaps2d.c StartUp2d.c
MaxwellsRun2d.c MaxwellsMPI2d.c MaxwellsDriver2d.c
MaxwellsRHS2d.c InitCPU2d.c)
add_executable(DGOM2 ${SRC_LIST})
include_directories("../include")
target_link_libraries(DGOM2 metis parmetis)
2.1. 增加可執行程序
add_executable(DGOM2 ${SRC_LIST})
2.2. 給出頭文件路徑
include_directories("../include")
2.3. 給定鏈接第三方函數庫
target_link_libraries(DGOM2 metis parmetis)