1
include (CheckCXXSourceRuns)
3
# ================================================================================
4
# == Macros, mostly for special targets ==========================================
6
MACRO (fc_copy_sources target_name outpath)
7
if(BUILD_VERBOSE_GENERATION)
8
set(fc_details " (fc_copy_sources called from ${CMAKE_CURRENT_SOURCE_DIR})")
13
get_filename_component(infile ${it} ABSOLUTE)
14
get_filename_component(outfile "${outpath}/${it}" ABSOLUTE)
15
add_file_dependencies("${infile}" "${outfile}")
17
COMMAND "${CMAKE_COMMAND}" -E copy "${infile}" "${outfile}"
19
COMMENT "Copying ${infile} to ${outfile}${fc_details}"
20
MAIN_DEPENDENCY "${infile}"
27
ENDMACRO(fc_copy_sources)
29
MACRO (fc_copy_file_if_different inputfile outputfile)
30
if (EXISTS ${inputfile})
31
if (EXISTS ${outputfile})
33
COMMAND ${CMAKE_COMMAND} -E compare_files ${inputfile}
35
RESULT_VARIABLE DIFFERENT_FILES
41
execute_process(COMMAND "${CMAKE_COMMAND}" -E copy "${inputfile}"
45
execute_process(COMMAND "${CMAKE_COMMAND}" -E copy "${inputfile}"
49
ENDMACRO(fc_copy_file_if_different)
51
MACRO (fc_target_copy_resource target_name inpath outpath)
52
# Macro to copy a list of files into a nested directory structure
54
# target_name - name of the target the files will be added to
55
# inpath - name of the source directory
56
# outpath - name of the destination directory
57
# ARGN - a list of relative file names that will be copied
59
# If a relative file name is foo/bar.txt then the foo directory
60
# part will be kept so that the destination file name will be
61
# ${outpath}/foo/bar.txt
63
if(BUILD_VERBOSE_GENERATION)
64
set(fc_details " (fc_target_copy_resource called from ${CMAKE_CURRENT_SOURCE_DIR})")
69
get_filename_component(infile "${inpath}/${it}" ABSOLUTE)
70
get_filename_component(outfile "${outpath}/${it}" ABSOLUTE)
71
add_file_dependencies("${infile}" "${outfile}")
73
COMMAND "${CMAKE_COMMAND}" -E copy "${infile}" "${outfile}"
75
COMMENT "Copying ${infile} to ${outfile}${fc_details}"
76
MAIN_DEPENDENCY "${infile}"
83
ENDMACRO(fc_target_copy_resource)
85
MACRO (fc_target_copy_resource_flat target_name inpath outpath)
86
# Macro to copy a list of files into a flat directory structure
88
# target_name - name of the target the files will be added to
89
# inpath - name of the source directory
90
# outpath - name of the destination directory
91
# ARGN - a list of relative file names that will be copied
93
# If a relative file name is foo/bar.txt then the foo directory
94
# part will be removed so that the destination file name will be
97
if(BUILD_VERBOSE_GENERATION)
98
set(fc_details " (fc_target_copy_resource_flat called from ${CMAKE_CURRENT_SOURCE_DIR})")
103
get_filename_component(infile "${inpath}/${it}" ABSOLUTE)
104
get_filename_component(outfile "${it}" NAME)
105
get_filename_component(outfile "${outpath}/${outfile}" ABSOLUTE)
106
add_file_dependencies("${infile}" "${outfile}")
108
COMMAND "${CMAKE_COMMAND}" -E copy "${infile}" "${outfile}"
110
COMMENT "Copying ${infile} to ${outfile}${fc_details}"
111
MAIN_DEPENDENCY "${infile}"
115
TARGET ${target_name}
118
ENDMACRO(fc_target_copy_resource_flat)
120
# It would be a bit cleaner to generate these files in ${CMAKE_CURRENT_BINARY_DIR}
122
macro(generate_from_xml BASE_NAME)
123
set(TOOL_PATH "${CMAKE_SOURCE_DIR}/src/Tools/generate.py")
124
file(TO_NATIVE_PATH "${TOOL_PATH}" TOOL_NATIVE_PATH)
125
file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${BASE_NAME}.xml" SOURCE_NATIVE_PATH)
127
set(SOURCE_CPP_PATH "${CMAKE_CURRENT_BINARY_DIR}/${BASE_NAME}.cpp" )
129
# BASE_NAME may include also a path name
130
GET_FILENAME_COMPONENT(OUTPUT_PATH "${SOURCE_CPP_PATH}" PATH)
131
file(TO_NATIVE_PATH "${OUTPUT_PATH}" OUTPUT_NATIVE_PATH)
132
if(NOT EXISTS "${SOURCE_CPP_PATH}")
133
# assures the source files are generated at least once
134
message(STATUS "${SOURCE_CPP_PATH}")
135
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "${TOOL_NATIVE_PATH}" --outputPath "${OUTPUT_NATIVE_PATH}" "${SOURCE_NATIVE_PATH}"
136
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
140
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${BASE_NAME}.h" "${CMAKE_CURRENT_BINARY_DIR}/${BASE_NAME}.cpp"
141
COMMAND ${PYTHON_EXECUTABLE} "${TOOL_NATIVE_PATH}" --outputPath "${OUTPUT_NATIVE_PATH}" ${BASE_NAME}.xml
142
MAIN_DEPENDENCY "${BASE_NAME}.xml"
144
"${CMAKE_SOURCE_DIR}/src/Tools/generateTemplates/templateClassPyExport.py"
146
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
147
COMMENT "Building ${BASE_NAME}.h/.cpp out of ${BASE_NAME}.xml"
149
endmacro(generate_from_xml)
151
macro(generate_from_py BASE_NAME OUTPUT_FILE)
152
set(TOOL_PATH "${CMAKE_SOURCE_DIR}/src/Tools/PythonToCPP.py")
153
file(TO_NATIVE_PATH "${TOOL_PATH}" TOOL_NATIVE_PATH)
154
file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${BASE_NAME}.py" SOURCE_NATIVE_PATH)
156
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_FILE}"
157
COMMAND "${PYTHON_EXECUTABLE}" "${TOOL_NATIVE_PATH}" "${SOURCE_NATIVE_PATH}" "${OUTPUT_FILE}"
158
MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/${BASE_NAME}.py"
159
DEPENDS "${TOOL_PATH}"
160
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
161
COMMENT "Building files out of ${BASE_NAME}.py")
162
endmacro(generate_from_py)
164
macro(generate_from_any INPUT_FILE OUTPUT_FILE VARIABLE)
165
set(TOOL_PATH "${CMAKE_SOURCE_DIR}/src/Tools/PythonToCPP.py")
166
file(TO_NATIVE_PATH "${TOOL_PATH}" TOOL_NATIVE_PATH)
167
file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_FILE}" SOURCE_NATIVE_PATH)
169
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_FILE}"
170
COMMAND "${PYTHON_EXECUTABLE}" "${TOOL_NATIVE_PATH}" "${SOURCE_NATIVE_PATH}" "${OUTPUT_FILE}" "${VARIABLE}"
171
MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_FILE}"
172
DEPENDS "${TOOL_PATH}"
173
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
174
COMMENT "Building files out of ${INPUT_FILE}")
175
endmacro(generate_from_any)
179
MACRO(ADD_MSVC_PRECOMPILED_HEADER TargetName PrecompiledHeader PrecompiledSource SourcesVar)
181
GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE)
183
SET(PrecompiledBinary "$(IntDir)\\$(TargetName).pch")
185
SET(PrecompiledBinary ${CMAKE_CURRENT_BINARY_DIR}/${TargetName}.pch)
187
SET(Sources ${${SourcesVar}})
189
SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource}
190
PROPERTIES COMPILE_FLAGS "/Yc\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\""
191
OBJECT_OUTPUTS "${PrecompiledBinary}")
192
SET_SOURCE_FILES_PROPERTIES(${Sources}
193
PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledHeader}\" /FI\"${PrecompiledBinary}\" /Fp\"${PrecompiledBinary}\""
194
OBJECT_DEPENDS "${PrecompiledBinary}")
195
# Add precompiled header to SourcesVar
196
LIST(APPEND ${SourcesVar} ${PrecompiledSource})
198
ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER)
200
MACRO(GET_MSVC_PRECOMPILED_SOURCE PrecompiledSource SourcesVar)
203
GET_FILENAME_COMPONENT(file_ext ${it} EXT)
204
GET_FILENAME_COMPONENT(file_name ${it} NAME)
205
STRING(COMPARE EQUAL ${it} ${PrecompiledSource} pch)
207
# get c++ source files
208
STRING(REGEX MATCH "^(.cpp|.cc|.cxx)$" cpp_file ${file_ext})
209
# ignore any generated source files from Qt
210
STRING(REGEX MATCH "^(moc_|qrc_|ui_)" gen_file ${file_name})
211
IF(cpp_file AND NOT gen_file)
212
LIST(APPEND ${SourcesVar} ${it})
213
ENDIF(cpp_file AND NOT gen_file)
217
ENDMACRO(GET_MSVC_PRECOMPILED_SOURCE)
219
# Macro to replace all the binary output locations. Takes 2 optional parameters.
220
# ${ARGVN} is zero based so the 3rd element is ${ARGV2}. When the 3rd element is missing,
221
# Runtime and Lib directories default to /bin and /lib. When present, the 3rd element
222
# specifies both Runtime and Lib directories. 4th specifies linux install path.
223
MACRO(SET_BIN_DIR ProjectName OutputName)
224
set_target_properties(${ProjectName} PROPERTIES OUTPUT_NAME ${OutputName})
225
if(${ARGC} GREATER 2)
226
# VS_IDE (and perhaps others) make Release and Debug subfolders. This removes them.
227
set_target_properties(${ProjectName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}${ARGV2})
228
set_target_properties(${ProjectName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}${ARGV2})
229
set_target_properties(${ProjectName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}${ARGV2})
230
set_target_properties(${ProjectName} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}${ARGV2})
231
set_target_properties(${ProjectName} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}${ARGV2})
232
set_target_properties(${ProjectName} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}${ARGV2})
233
else(${ARGC} GREATER 2)
234
set_target_properties(${ProjectName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
235
set_target_properties(${ProjectName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin)
236
set_target_properties(${ProjectName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin)
237
set_target_properties(${ProjectName} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
238
set_target_properties(${ProjectName} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/lib)
239
set_target_properties(${ProjectName} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/lib)
240
endif(${ARGC} GREATER 2)
243
set_target_properties(${ProjectName} PROPERTIES DEBUG_OUTPUT_NAME ${OutputName}_d)
245
# FreeCADBase, SMDS, Driver and MEFISTO2 libs don't depend on parts from CMAKE_INSTALL_LIBDIR
246
if(NOT ${ProjectName} MATCHES "^(FreeCADBase|SMDS|Driver|MEFISTO2)$")
247
if(${ARGC} STREQUAL 4)
248
set_property(TARGET ${ProjectName} APPEND PROPERTY INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${ARGV3})
249
elseif(NOT IS_ABSOLUTE ${CMAKE_INSTALL_LIBDIR})
250
set_property(TARGET ${ProjectName} APPEND PROPERTY INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
252
set_property(TARGET ${ProjectName} APPEND PROPERTY INSTALL_RPATH ${CMAKE_INSTALL_LIBDIR})
258
# Set python prefix & suffix together
259
MACRO(SET_PYTHON_PREFIX_SUFFIX ProjectName)
261
set_target_properties(${ProjectName} PROPERTIES PREFIX "")
265
set_target_properties(${ProjectName} PROPERTIES SUFFIX ".pyd")
266
# 0000661: cmake build on Mac OS: dealing with dylib versus so
268
set_target_properties(${ProjectName} PROPERTIES SUFFIX ".so")
270
ENDMACRO(SET_PYTHON_PREFIX_SUFFIX)
272
# Locate the include directory for a pip-installed package -- uses pip show to find the base pip
273
# install directory, and then appends the package name and "/include" to the end
274
macro(find_pip_package PACKAGE)
276
COMMAND ${PYTHON_EXECUTABLE} -m pip show ${PACKAGE}
277
RESULT_VARIABLE FAILURE
278
OUTPUT_VARIABLE PRINT_OUTPUT
281
# Extract Name: and Location: lines and use them to construct the include directory
282
string(REPLACE "\n" ";" PIP_OUTPUT_LINES ${PRINT_OUTPUT})
283
foreach(LINE IN LISTS PIP_OUTPUT_LINES)
284
STRING(FIND "${LINE}" "Name: " NAME_STRING_LOCATION)
285
STRING(FIND "${LINE}" "Location: " LOCATION_STRING_LOCATION)
286
if(${NAME_STRING_LOCATION} EQUAL 0)
287
STRING(SUBSTRING "${LINE}" 6 -1 PIP_PACKAGE_NAME)
288
STRING(STRIP "${PIP_PACKAGE_NAME}" PIP_PACKAGE_NAME)
289
STRING(REPLACE "-" "_" PIP_PACKAGE_NAME "${PIP_PACKAGE_NAME}")
290
elseif(${LOCATION_STRING_LOCATION} EQUAL 0)
291
STRING(SUBSTRING "${LINE}" 9 -1 PIP_PACKAGE_LOCATION)
292
STRING(STRIP "${PIP_PACKAGE_LOCATION}" PIP_PACKAGE_LOCATION)
295
file(TO_CMAKE_PATH "${PIP_PACKAGE_LOCATION}" PIP_PACKAGE_LOCATION)
296
if(EXISTS "${PIP_PACKAGE_LOCATION}/${PIP_PACKAGE_NAME}/include")
297
set(INCLUDE_DIR "${PIP_PACKAGE_LOCATION}/${PIP_PACKAGE_NAME}/include")
299
# There are many different library naming schemes, but basically we are looking for things that look like
300
# PACKAGE*.lib/so or PACKAGE_d*.lib/so
302
file(GLOB OPT_LIBRARIES "${PIP_PACKAGE_LOCATION}/${PIP_PACKAGE_NAME}/${PIP_PACKAGE_NAME}.*.lib")
303
file(GLOB DEBUG_LIBRARIES "${PIP_PACKAGE_LOCATION}/${PIP_PACKAGE_NAME}/${PIP_PACKAGE_NAME}_d.*.lib")
305
string(TOLOWER ${PIP_PACKAGE_NAME} PIP_LIB_NAME)
306
file(GLOB OPT_LIBRARIES "${PIP_PACKAGE_LOCATION}/${PIP_PACKAGE_NAME}/*${PIP_LIB_NAME}*.so.*")
308
if (OPT_LIBRARIES AND DEBUG_LIBRARIES)
309
set(${PACKAGE}_LIBRARIES optimized ${OPT_LIBRARIES} debug ${DEBUG_LIBRARIES} CACHE PATH "")
310
elseif(OPT_LIBRARIES)
311
set(${PACKAGE}_LIBRARIES ${OPT_LIBRARIES} CACHE PATH "")
312
elseif(DEBUG_LIBRARIES)
313
set(${PACKAGE}_LIBRARIES ${DEBUG_LIBRARIES} CACHE PATH "")
315
set(${PACKAGE}_INCLUDE_DIRS ${INCLUDE_DIR} CACHE PATH "")
316
set(${PACKAGE}_FOUND ON CACHE BOOL OFF)
317
message(STATUS "Found pip-installed ${PACKAGE} in ${PIP_PACKAGE_LOCATION}/${PIP_PACKAGE_NAME}")
321
function(target_compile_warn_error ProjectName)
322
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX)
323
target_compile_options(${ProjectName} PRIVATE -Werror)