-
Notifications
You must be signed in to change notification settings - Fork 19
/
CMakeLists.txt
237 lines (209 loc) · 7.8 KB
/
CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# CMakeLists.txt for compiling MYSTRAN with gfortran in a GNU environment
# based on an older CMakeLists.txt by ceanwang@gmail.com
# made to work again by Bruno Borges Paschoalinoto (2020)
# set up basic project info
cmake_minimum_required(VERSION 3.18)
include(CheckFunctionExists)
enable_language(Fortran)
project(Mystran)
# basic compiler and output options
set(CMAKE_SOURCE_DIR "${PROJECT_SOURCE_DIR}/Source")
set(PROJECT_BINARY_DIR "${PROJECT_SOURCE_DIR}/Binaries")
set(CMAKE_FLAGS "-c -fbacktrace")
# set(CMAKE_BUILD_TYPE Debug)
# set some dirs
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
set(CMAKE_Fortran_MODULE_DIRECTORY "${PROJECT_BINARY_DIR}/mod")
include_directories("${CMAKE_SOURCE_DIR}/INCLUDE")
# uncomment this to debug
# set(CMAKE_VERBOSE_MAKEFILE true)
# suppress cmake warnings for superlu
if(NOT DEFINED CMAKE_SUPPRESS_DEVELOPER_WARNINGS)
set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS 1 CACHE INTERNAL "No dev warnings")
endif()
# recommend the appropriate make command
if(WIN32)
set(RECOMMENDED_MAKE "mingw32-make")
else()
set(RECOMMENDED_MAKE "make")
endif()
# submodules (i.e. SuperLU)
find_package(Git QUIET)
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
option(GIT_SUBMODULE "Check submodules during build" ON)
if(GIT_SUBMODULE)
message(STATUS "Updating submodules")
execute_process(
COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive --force
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE GIT_SUBMOD_RESULT
)
if(NOT GIT_SUBMOD_RESULT EQUAL "0")
message(
FATAL_ERROR
"git submodule update --init --recursive --force failed"
)
endif()
endif()
endif()
# check for SuperLU
set(SUPERLU_DIR "${PROJECT_SOURCE_DIR}/superlu")
include_directories("${SUPERLU_DIR}/SRC")
if(NOT EXISTS "${SUPERLU_DIR}/CMakeLists.txt")
message(
FATAL_ERROR
"The submodules were not downloaded. You have to do it manually!"
)
endif()
# f2c stuff
set(F2C_DIR "${PROJECT_SOURCE_DIR}/f2c")
set(F2C_INCLUDE_DIR "${F2C_DIR}/include")
set(F2C_FN "${F2C_DIR}/libf2c.zip")
set(F2C_URL "https://www.netlib.org/f2c/libf2c.zip")
# download f2c
if(NOT EXISTS ${F2C_DIR})
message(STATUS "Downloading libf2c source from ${F2C_URL}...")
make_directory("${F2C_DIR}")
file(DOWNLOAD ${F2C_URL} ${F2C_FN} TIMEOUT 60 STATUS DOWNLOAD_STATUS)
# Check if download was successful.
list(GET DOWNLOAD_STATUS 0 STATUS_CODE)
list(GET DOWNLOAD_STATUS 1 ERROR_MESSAGE)
if(${STATUS_CODE} EQUAL 0)
message(STATUS "Done downloading libf2c.")
else()
# Exit CMake if the download failed, printing the error message.
file(REMOVE_RECURSE ${F2C_DIR})
message(FATAL_ERROR "Error downloading libf2c: ${ERROR_MESSAGE}")
endif()
endif()
# extract libf2c source
file(ARCHIVE_EXTRACT INPUT ${F2C_FN} DESTINATION ${F2C_DIR})
# prepare libf2c header files
file(GLOB_RECURSE F2C_PREHEADERS "${F2C_DIR}/*.h0")
foreach(H0 ${F2C_PREHEADERS})
string(REGEX REPLACE "[.]h0$" ".h" H0_R ${H0})
file(RENAME "${H0}" "${H0_R}")
file(COPY "${H0_R}" DESTINATION "${F2C_INCLUDE_DIR}")
endforeach()
# get a load of this: f2c generates its own "arith.h" on the fly
# so we gotta compile arithchk and run it
set(F2C_ARITHCHK_SRC "${F2C_DIR}/arithchk.c")
set(F2C_ARITHCHK_BIN "${F2C_DIR}/arithchk")
if (WIN32)
set(F2C_ARITHCHK_BIN "${F2C_ARITHCHK_BIN}.exe")
endif()
set(F2C_ARITH_H "${F2C_INCLUDE_DIR}/arith.h")
set_source_files_properties(
${F2C_ARITHCHK_SRC} PROPERTIES COMPILE_FLAGS "-DNO_LONG_LONG -DNO_FPINIT"
)
add_executable(arithchk ${F2C_ARITHCHK_SRC})
target_link_libraries(arithchk m)
set_target_properties(
arithchk PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${F2C_DIR}
)
add_custom_command(
OUTPUT ${F2C_ARITH_H}
COMMAND ${F2C_ARITHCHK_BIN} > ${F2C_ARITH_H}
DEPENDS ${F2C_ARITHCHK_BIN}
)
# add libf2c to the compilation procedures
include_directories(${F2C_INCLUDE_DIR})
file(GLOB_RECURSE F2C_CFILES "${F2C_DIR}/*.c")
add_definitions(-DINTEGER_STAR_8)
add_library(f2c ${F2C_CFILES} ${F2C_ARITH_H})
# add some extra win32 flags for libf2c
if (WIN32)
add_definitions(-DUSE_CLOCK -DMSDOS)
endif()
# set some extra vars for MSYS builds to make the binary portable
if (WIN32)
set(CMAKE_EXE_LINKER_FLAGS "-static")
endif()
# build the SuperLU (and CBLAS if needed) static libs!
add_subdirectory(${SUPERLU_DIR})
# collect modules and interfaces into a module called MODULES
# the overuse of the word MODULE is brain-twisting, but bear with me
set(Modules_DIR "${CMAKE_SOURCE_DIR}/Modules")
file(GLOB_RECURSE Modules_ARPACK_FILES "${Modules_DIR}/ARPACK/*.f*")
file(GLOB_RECURSE Modules_LAPACK_FILES "${Modules_DIR}/LAPACK/*.f*")
file(GLOB_RECURSE Modules_BANDIT_FILES "${Modules_DIR}/BANDIT/*.f*")
file(GLOB_RECURSE Modules_FILES "${Modules_DIR}/*.f*")
file(GLOB_RECURSE Interfaces_FILES "${CMAKE_SOURCE_DIR}/Interfaces/*.f*")
file(GLOB_RECURSE USE_IFs_FILES "${CMAKE_SOURCE_DIR}/USE_IFs/*.f*")
# MODULES_ALL_FILES shall contain all the sources for the base modules lib
set(
MODULES_ALL_FILES ${USE_IFs_FILES} ${Interfaces_FILES} ${Modules_FILES}
${Modules_LAPACK_FILES} ${Modules_ARPACK_FILES}
)
add_library(MODULES OBJECT ${MODULES_ALL_FILES})
# collect modules
list(APPEND modules_names ARPACK BANDIT LK1 LK2 LK3 LK4 LK5 LK6 LK9 EMG)
foreach (modname IN LISTS modules_names)
file(GLOB_RECURSE TMP_MOD_FILES "${CMAKE_SOURCE_DIR}/${modname}/*.f*")
add_library(${modname} OBJECT ${TMP_MOD_FILES} ${TMP_MOD_FILES_PP})
target_link_libraries(${modname} MODULES)
endforeach()
# add the DGSSV C module from SuperLU and link it against SuperLU's BLAS
add_library(dgssv "${SUPERLU_DIR}/FORTRAN/c_fortran_dgssv.c")
target_link_libraries(dgssv blas)
# if (and only if) SuperLU is compiled with its internal CBLAS, some subrs will
# be missing, so we compile our own.
# first, we check for the missing subroutines
list(
APPEND blas_fns dgemm dgemv dlamch dlanst dscal dsteqr dsterf dswap dtrsm
dtrtri ilaenv lsame xerbla
)
foreach (fname IN LISTS blas_fns)
check_function_exists(${fname} BLAS_FN_EXISTS)
if (NOT BLAS_FN_EXISTS)
string(TOUPPER ${fname} fname_upper)
list(APPEND missing_blas_src "${CMAKE_SOURCE_DIR}/BLAS/${fname_upper}.f")
list(APPEND missing_blas_fns ${fname})
endif()
endforeach()
# if any subroutines have bene found, create an inner blas library
list(LENGTH missing_blas_fns MISSING_FNS_TOTAL)
if (MISSING_FNS_TOTAL GREATER 0)
if (MISSING_FNS_TOTAL GREATER 1)
message(
STATUS
"BLAS subrs (${missing_blas_fns}) are absent and will be built locally."
)
else()
message(
STATUS
"BLAS subr ${missing_blas_fns} is absent and will be built locally."
)
endif()
add_library(my_blas OBJECT ${missing_blas_src})
target_link_libraries(my_blas MODULES)
endif()
# prepare the main executable, linked against the specifics and the m
# it appears utils used to be a module, but that is no longer the case?
file(GLOB_RECURSE UTIL_FILES "${CMAKE_SOURCE_DIR}/UTIL/*.f*")
file(GLOB_RECURSE MAIN_FILES "${CMAKE_SOURCE_DIR}/MAIN/*.[fF]*")
add_executable(mystran ${MAIN_FILES} ${MODULES_ALL_FILES} ${UTIL_FILES})
target_link_libraries(mystran ${modules_names})
target_link_libraries(mystran dgssv superlu f2c blas)
if (MISSING_FNS_TOTAL GREATER 0)
target_link_libraries(mystran my_blas)
endif()
set_target_properties(
mystran PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}
)
if (CMAKE_COMPILER_IS_GNUCC)
target_compile_options(
mystran PRIVATE
-Wall -Wextra
-Wno-unused-variable -Wno-unused-label -Wno-unused-parameter -Wno-tabs
-Wno-compare-reals -Wno-character-truncation -Wno-unused-dummy-argument
-Wmaybe-uninitialized -Wrealloc-lhs -fcheck=all
)
endif()
# issue a couple messages about compilation
include(ProcessorCount)
ProcessorCount(NCPU)
message(STATUS "You can now compile MYSTRAN with ${RECOMMENDED_MAKE}.")
if (NOT NCPU EQUAL 0)
message(STATUS "Compile faster by passing -j${NCPU} to ${RECOMMENDED_MAKE}.")
endif()