forked from libprima/prima
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CMakeLists.txt
167 lines (146 loc) · 6.32 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
cmake_minimum_required (VERSION 3.13)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type")
project (prima Fortran)
option (BUILD_SHARED_LIBS "shared/static" ON)
include (GNUInstallDirs)
# the compiler enables an executable stack because of nested functions and this is fine
if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU" AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
include (CheckLinkerFlag)
check_linker_flag (Fortran "-Wl,--no-warn-execstack" HAVE_WARN_EXECSTACK)
endif ()
# Set additional Fortran compiler flags
# 1. We require the compilers to allocate arrays on the heap instead of the stack, which is
# slower (does not matter for DFO applications) but can avoid memory errors on large problems.
# 2. We require the compilers to compile the solvers so that they can be called recursively.
# See https://fortran-lang.discourse.group/t/frecursive-assume-recursion-and-recursion-thread-safety
option (PRIMA_HEAP_ARRAYS "allocate arrays on heap" ON)
if (PRIMA_HEAP_ARRAYS)
if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fno-stack-arrays -frecursive")
elseif (CMAKE_Fortran_COMPILER_ID MATCHES "Intel")
if (WIN32)
set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} /heap-arrays /assume:recursion")
else ()
set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -heap-arrays -assume recursion")
endif ()
elseif (CMAKE_Fortran_COMPILER_ID MATCHES "NVHPC")
set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -Mnostack_arrays -Mrecursive")
elseif (CMAKE_Fortran_COMPILER_ID MATCHES "NAG")
set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -recursive") # What about stack/heap?
endif ()
endif ()
# Set additional linker flags
# Zaikun 20240217: Fix https://github.com/libprima/prima/issues/158, which is due to the new linker
# implemented in Xcode 15 on macOS. It happens only if the Fortran compiler is ifort.
# An alternative is `add_link_options("-ld_classic")`, which forces Xcode to use the old linker.
# Will CMake adapt itself to the new linker later? Will a newer version of CMake make the fix unnecessary?
# See
# https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#Linking
# https://stackoverflow.com/questions/77525544/apple-linker-warning-ld-warning-undefined-error-is-deprecated
# https://medium.com/@hackingwithcode/cmake-and-xcode-15-solving-the-undefined-error-puzzle-3c847e6d1008
if((APPLE) AND (CMAKE_Fortran_COMPILER_ID MATCHES "Intel"))
add_link_options("-Wl,-undefined,dynamic_lookup")
endif()
# For running tests with gdb. $_exitcode != 0 means the program ran without exiting
# normally, and in this case we want to show a stack trace
file(WRITE ${CMAKE_BINARY_DIR}/cmdfile.gdb "init-if-undefined $_exitcode = 0
run
set language c
if $_exitcode != 0
where
end
quit $_exitcode
")
option(PRIMA_ENABLE_EXAMPLES "build examples by default" OFF)
add_custom_target (examples)
enable_testing ()
option(PRIMA_ENABLE_TESTING "build tests" OFF)
add_custom_target (tests)
add_dependencies(tests examples)
add_subdirectory(fortran)
option (PRIMA_ENABLE_C "C binding" ON)
if (PRIMA_ENABLE_C)
enable_language(C)
add_subdirectory(c)
set(primac_target "primac")
endif ()
# Get the version number
find_package(Git)
set(IS_REPO FALSE)
if(GIT_EXECUTABLE)
# --always means git describe will output the commit hash if no tags are found
# This is usually the case for forked repos since they do not clone tags by default.
execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --always --dirty
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE PRIMA_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE GIT_RESULT ERROR_QUIET)
if (GIT_RESULT EQUAL 0)
set(IS_REPO TRUE)
endif()
endif()
if(NOT GIT_EXECUTABLE OR NOT IS_REPO)
# If git is not available, or this isn't a repo, that may indicate we are building
# on macports which downloads the bundle from github (which uses git archive) and
# so the version number should be in .git-archival.txt.
# Alternatively it might mean that we're building the Python bindings, in which case
# the version is output in _version.txt. I know, it's complicated. I don't make the rules.
if(EXISTS _version.txt)
file(STRINGS _version.txt PRIMA_VERSION)
else()
file(STRINGS .git-archival.txt PRIMA_VERSION)
if(PRIMA_VERSION MATCHES "describe")
message(WARNING "No git detected and .git-archival.txt does not contain a version number")
set(PRIMA_VERSION "unknown")
endif()
endif()
endif()
# Remove the leading v from PRIMA_VERSION, if it contains one.
string(REGEX REPLACE "^v" "" PRIMA_VERSION ${PRIMA_VERSION})
message(STATUS "Setting PRIMA version to ${PRIMA_VERSION}")
option (PRIMA_ENABLE_PYTHON "Python binding" OFF)
if (PRIMA_ENABLE_PYTHON)
if(NOT PRIMA_ENABLE_C)
message(FATAL_ERROR "Building Python bindings requires C bindings. Please turn on PRIMA_ENABLE_C")
endif()
if(BUILD_SHARED_LIBS)
# This will include libprimaf, libprimafc, and libprimac into the compiled Python binding, removing the need
# to properly set the rpath or find those libraries at runtime.
# Even if we did make it successfully build with shared libraries, delocate/auditwheel will copy them into the
# bindings anyway
message(FATAL_ERROR "Building Python bindings requires static libraries. Please disable BUILD_SHARED_LIBS")
endif()
if(NOT CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
message(WARNING "Compiling Python bindings with compilers other than GNU has not been tested and no support is planned at this time")
endif()
enable_language(CXX)
add_subdirectory(python)
endif ()
install(
TARGETS primaf ${primac_target}
EXPORT prima-targets
INCLUDES DESTINATION include
)
install(
EXPORT prima-targets
FILE prima-targets.cmake
NAMESPACE prima::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/prima
)
include(CMakePackageConfigHelpers)
configure_package_config_file(
${PROJECT_SOURCE_DIR}/prima-config.cmake.in
${CMAKE_BINARY_DIR}/prima-config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/prima
)
write_basic_package_version_file(
${CMAKE_BINARY_DIR}/prima-config-version.cmake
VERSION ${PRIMA_VERSION}
COMPATIBILITY AnyNewerVersion
)
install(
FILES
${CMAKE_BINARY_DIR}/prima-config.cmake
${CMAKE_BINARY_DIR}/prima-config-version.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/prima
)