-
Notifications
You must be signed in to change notification settings - Fork 113
/
MacroHelper.cmake
194 lines (179 loc) · 8.02 KB
/
MacroHelper.cmake
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
# =============================================================================
# Helper functions used in the project
# =============================================================================
include(CheckIncludeFileCXX)
include(CheckIncludeFiles)
include(CheckFunctionExists)
include(CheckSymbolExists)
include(CheckCXXSymbolExists)
include(CMakeParseArguments)
set(CMAKE_REQUIRED_QUIET TRUE)
# =============================================================================
# Check if directory related to DIR exists by compiling code
# =============================================================================
macro(nrn_check_dir_exists HEADER VARIABLE)
# code template to check existence of DIR
string(
CONCAT CONFTEST_DIR_TPL
"#include <sys/types.h>\n"
"#include <@dir_header@>\n"
"int main () {\n"
" if ((DIR *) 0)\n"
" return 0\;\n"
" return 0\;\n"
"}\n")
# first get header file
check_include_files(${HEADER} HAVE_HEADER)
if(${HAVE_HEADER})
# if header is found, create a code from template
string(REPLACE "@dir_header@" ${HEADER} CONFTEST_DIR "${CONFTEST_DIR_TPL}")
file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/conftest.cpp" ${CONFTEST_DIR})
# try to compile
try_compile(${VARIABLE} "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/conftest.cpp")
file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/conftest.cpp")
endif()
endmacro()
# =============================================================================
# Check if given type exists by compiling code
# =============================================================================
macro(nrn_check_type_exists HEADER TYPE DEFAULT_TYPE VARIABLE)
# code template to check existence of specific type
string(
CONCAT CONFTEST_TYPE_TPL
"#include <@header@>\n"
"int main () {\n"
" if (sizeof (@type@))\n"
" return 0\;\n"
" return 0\;\n"
"}\n")
string(REPLACE "@header@" ${HEADER} CONFTEST_TYPE "${CONFTEST_TYPE_TPL}")
string(REPLACE "@type@" ${TYPE} CONFTEST_TYPE "${CONFTEST_TYPE}")
file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/conftest.cpp ${CONFTEST_TYPE})
try_compile(MY_RESULT_VAR ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/conftest.cpp)
if(NOT ${MY_RESULT_VAR})
set(${VARIABLE} ${DEFAULT_TYPE})
endif()
file(REMOVE "conftest.cpp")
endmacro()
# =============================================================================
# Perform check_include_files and add it to NRN_HEADERS_INCLUDE_LIST if exist Passing an optional
# CXX will call check_include_files_cxx instead.
# =============================================================================
macro(nrn_check_include_files filename variable)
set(options CXX)
cmake_parse_arguments(nrn_check_include_files "${options}" "" "" ${ARGN})
if(${nrn_check_include_files_CXX})
check_include_file_cxx(${filename} ${variable})
else()
check_include_files(${filename} ${variable})
endif()
if(${variable})
list(APPEND NRN_HEADERS_INCLUDE_LIST ${filename})
endif()
endmacro()
# =============================================================================
# Perform check_symbol_exists using NRN_HEADERS_INCLUDE_LIST if empty header_list
# =============================================================================
macro(nrn_check_symbol_exists name header_list variable)
if("${header_list}" STREQUAL "")
check_symbol_exists("${name}" "${NRN_HEADERS_INCLUDE_LIST}" ${variable})
else()
check_symbol_exists("${name}" "${header_list}" ${variable})
endif()
endmacro()
# =============================================================================
# Perform check_cxx_symbol_exists using NRN_HEADERS_INCLUDE_LIST if empty header_list
# =============================================================================
# note that sometimes, though it should have succeeded, cc fails but c++ succeeds
macro(nrn_check_cxx_symbol_exists name header_list variable)
if("${header_list}" STREQUAL "")
check_cxx_symbol_exists("${name}" "${NRN_HEADERS_INCLUDE_LIST}" ${variable})
else()
check_cxx_symbol_exists("${name}" "${header_list}" ${variable})
endif()
endmacro()
# =============================================================================
# Append arguments to given list in the form of prefix/argument
# =============================================================================
macro(nrn_create_file_list list_name prefix)
foreach(name ${ARGN})
list(APPEND ${list_name} ${prefix}/${name})
endforeach(name)
endmacro()
# =============================================================================
# Set string with double quotes
# =============================================================================
macro(nrn_set_string variable value)
set(${variable} \"${value}\")
endmacro()
# =============================================================================
# Set var to to dos path format
# =============================================================================
macro(dospath path var)
# file(TO_NATIVE_PATH does not convert / to \ for us in msys2.
string(REPLACE "/" "\\" var1 "${path}")
set(${var} ${var1})
endmacro()
# =============================================================================
# Utility macro to print all matching CMake variables
# =============================================================================
# example usage : nrn_print_matching_variables("[Mm][Pp][Ii]")
macro(nrn_print_matching_variables prefix_regex)
get_cmake_property(variable_names VARIABLES)
list(SORT variable_names)
foreach(variable ${variable_names})
if(variable MATCHES "^${prefix_regex}")
message(NOTICE " ${variable} ${${variable}}")
endif()
endforeach()
endmacro()
# =============================================================================
# Run nocmodl to convert NMODL to C++
# =============================================================================
macro(nocmodl_mod_to_cpp modfile_basename source_dir target_dir)
set(NOCMODL_SED_EXPR "s/_reg()/_reg_()/")
if(NOT MSVC)
set(NOCMODL_SED_EXPR "'${NOCMODL_SED_EXPR}'")
endif()
add_custom_command(
OUTPUT "${target_dir}/${modfile_basename}.cpp"
COMMAND
${CMAKE_COMMAND} -E env "MODLUNIT=${PROJECT_BINARY_DIR}/share/nrn/lib/nrnunits.lib"
${NRN_NOCMODL_SANITIZER_ENVIRONMENT} $<TARGET_FILE:nocmodl> -o "${target_dir}"
"${source_dir}/${modfile_basename}.mod"
COMMAND sed -i -e ${NOCMODL_SED_EXPR} "${target_dir}/${modfile_basename}.cpp"
DEPENDS nocmodl "${source_dir}/${modfile_basename}.mod"
"${PROJECT_BINARY_DIR}/share/nrn/lib/nrnunits.lib"
WORKING_DIRECTORY ${target_dir})
endmacro()
# =============================================================================
# Create symbolic links
# =============================================================================
macro(nrn_install_dir_symlink source_dir symlink_dir)
# make sure to have directory path exist upto parent dir
get_filename_component(parent_symlink_dir ${symlink_dir} DIRECTORY)
install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${parent_symlink_dir})")
# create symbolic link
install(
CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${source_dir} ${symlink_dir})")
endmacro(nrn_install_dir_symlink)
# ========================================================================
# There is an edge case to 'find_package(MPI REQUIRED)' in that we can still build a universal2
# macos package on an arm64 architecture even if the mpi library has no slice for x86_64.
# ========================================================================
macro(nrn_mpi_find_package)
if("arm64" IN_LIST CMAKE_OSX_ARCHITECTURES
AND "x86_64" IN_LIST CMAKE_OSX_ARCHITECTURES
AND NRN_ENABLE_MPI_DYNAMIC)
set(_temp ${CMAKE_OSX_ARCHITECTURES})
unset(CMAKE_OSX_ARCHITECTURES CACHE)
find_package(MPI REQUIRED)
set(CMAKE_OSX_ARCHITECTURES
${_temp}
CACHE INTERNAL "" FORCE)
set(NRN_UNIVERSAL2_BUILD ON)
else()
find_package(MPI REQUIRED)
endif()
endmacro()