mitsuba/data/cmake/MitsubaUtil.cmake

526 lines
18 KiB
CMake

# Macros to build the mitsuba targets. They are to be used by the CMake scripts
# only, otherwise they don't make any sense at all.
include (CMakeParseArguments)
include (CMakeDependentOption)
include (PCHTargets)
# Function to check that the assumed configurations exist
function (mts_check_configurations)
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(WARNING "The build type is not set. Set the value of CMAKE_BUILD_TYPE.")
return ()
endif ()
if (CMAKE_BUILD_TYPE)
set (configs ${ARGN})
list (FIND configs ${CMAKE_BUILD_TYPE} idx)
if (idx LESS 0)
message (AUTHOR_WARNING "Unexpected configuration '${CMAKE_BUILD_TYPE}' Check the value of CMAKE_BUILD_TYPE.")
endif ()
return ()
endif ()
set (configs "")
foreach (cfg ${CMAKE_CONFIGURATION_TYPES})
set (configs ${configs} ${cfg})
endforeach ()
set (myconfigs "")
foreach (cfg ${ARGN})
set (myconfigs ${myconfigs} ${cfg})
list (FIND configs ${cfg} idx)
if (idx LESS 0)
message (AUTHOR_WARNING "The assumed configuration '${cfg}' is not available.")
endif ()
endforeach ()
foreach (cfg ${configs})
list (FIND myconfigs ${cfg} idx)
if (idx LESS 0)
message (AUTHOR_WARNING "Unexpected configuration '${cfg}' found.")
endif ()
endforeach ()
endfunction()
# Check the standard configurations
mts_check_configurations (Debug Release MinSizeRel RelWithDebInfo)
# Option to enable interprocedural optimizations
option(MTS_LTCG "Enable interprocedural optimizations on Release targets" ON)
mark_as_advanced (MTS_LTCG)
# Macro to enable interprocedural optimizations on a target
macro (mts_target_ltcg target)
if (MTS_LTCG)
set_target_properties (${target} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE 1
)
endif()
endmacro()
# Macro to enable parallel compilation on MSVC
macro (mts_msvc_mp target)
if (MSVC_IDE AND MSVC_VERSION GREATER 1400)
set_property (TARGET ${target} APPEND
PROPERTY COMPILE_FLAGS " /MP")
endif ()
endmacro()
# Option for precompiled headers
if (PCH_MSVC OR PCH_GCC)
set (MTS_PCH_DEFAULT ON)
else ()
set (MTS_PCH_DEFAULT OFF)
endif ()
CMAKE_DEPENDENT_OPTION (MTS_USE_PCH "Use precompiled headers (PCH)."
${MTS_PCH_DEFAULT} "PCH_SUPPORTED" OFF)
CMAKE_DEPENDENT_OPTION (MTS_USE_PCH_ALL_PLUGINS
"Use PCH for all plugins irrespective of their number of source files."
OFF "MTS_USE_PCH" OFF)
# Default project-wide header to be precompiled
set (MTS_DEFAULT_PCH "${PROJECT_SOURCE_DIR}/data/pch/mitsuba_precompiled.hpp")
# Function to configure the output path according to the configurations
# The output path configure expression, contained in "path_cfgstr" should
# have the placeholder @CFGNAME@ for proper substitution
function (SET_OUTPATH_CFG target_name property_suffix path_cfgstr)
if (CMAKE_CONFIGURATION_TYPES)
foreach (CFGNAME ${CMAKE_CONFIGURATION_TYPES})
string (TOUPPER ${CFGNAME} cfg_upper)
string (CONFIGURE "${path_cfgstr}" outpath @ONLY)
set_target_properties (${target_name} PROPERTIES
${property_suffix}_${cfg_upper} "${outpath}")
endforeach ()
else ()
set (CFGNAME ".")
string (CONFIGURE "${path_cfgstr}" outpath @ONLY)
set_target_properties (${target_name} PROPERTIES
${property_suffix} "${outpath}")
endif ()
endfunction ()
# Function to set up the default windows resource file:
# target_filename - where to write the configured file
# name - base name WITHOUT extension, eg "mitsuba"
# extension - file extension including the . ".exe"
# description - File description to be presented to users
# ICON <iconfile> - icon to be shown for executables
function(mts_win_resource target_filename name ext description)
CMAKE_PARSE_ARGUMENTS(_res "" "ICON" "" ${ARGN})
if (NOT WIN32)
message(AUTHOR_WARNING "This is not a Windows build!")
elseif(NOT MTS_VERSION)
message(AUTHOR_WARNING "The mitsuba version variable is not set")
endif()
set(RC_FILE "${PROJECT_SOURCE_DIR}/data/windows/mitsuba_res.rc.in")
#TODO Set up the VS_FF_PRERELEASE and VS_FF_PRIVATEBUILD flags adequately
string(TOLOWER "${ext}" ext_lower)
if(ext_lower STREQUAL ".dll")
set(RC_FILETYPE "VFT_DLL")
elseif(ext_lower STREQUAL ".exe")
set(RC_FILETYPE "VFT_APP")
elseif(ext_lower STREQUAL ".lib")
set(RC_FILETYPE "VFT_STATIC_LIB")
else()
message(AUTHOR_WARNING "Unknown windows file type: ${ext_lower}")
set(RC_FILETYPE "VFT_UNKNOWN")
endif()
if(_res_ICON)
get_filename_component(_res_dir "${target_filename}" PATH)
file(RELATIVE_PATH RC_ICON "${_res_dir}" "${_res_ICON}")
else()
set(RC_ICON "")
endif()
set(RC_DESCRIPTION "${description}")
if (MTS_HAS_VALID_REV)
set(RC_VERSION "${MTS_VERSION}-${MTS_VERSION_BUILD}hg${MTS_REV_ID}")
else()
set(RC_VERSION "${MTS_VERSION}")
endif()
set(RC_VERSION_COMMA "${MTS_VERSION_MAJOR},${MTS_VERSION_MINOR},${MTS_VERSION_PATCH},0")
set(RC_FILENAME "${name}${ext}")
set(RC_NAME "${name}")
# MTS_DATE has the format YYYY.MM.DD
string(SUBSTRING "${MTS_DATE}" 0 4 RC_YEAR)
configure_file("${RC_FILE}" "${target_filename}" ESCAPE_QUOTES @ONLY)
endfunction()
# Constant with the bundle name for Mitsuba
set(MTS_BUNDLE_NAME "Mitsuba.app")
set(MTS_BUNDLE_RESOURCES "${MTS_BUNDLE_NAME}/Contents/Resources")
# Flag to use either simple or traditional Unix paths (e.g. share/mitsuba/...)
CMAKE_DEPENDENT_OPTION(MTS_SIMPLE_PATHS
"Use a simple, Windows-like dir structure instead of the typical Unix one."
ON "NOT WIN32; NOT APPLE" OFF)
# Constant with the destination for the Python bindings
if (WIN32 OR MTS_SIMPLE_PATHS)
set(MTS_PYTHON_DEST "python")
elseif (APPLE)
set(MTS_PYTHON_DEST "${MTS_BUNDLE_NAME}/python")
else()
set(MTS_PYTHON_DEST "share/mitsuba/python")
endif()
# Constant with the destination for the core libraries
if (WIN32 OR MTS_SIMPLE_PATHS)
set(MTS_LIB_DEST ".")
elseif (APPLE)
set(MTS_LIB_DEST "${MTS_BUNDLE_NAME}/Contents/Frameworks")
else ()
set(MTS_LIB_DEST "lib")
endif ()
# Macro to add a build target for a mitsuba core library.
#
# Usage:
#
# add_mts_corelib (name source1 [source2 ...]
# [LINK_LIBRARIES external_lib1 ...] )
#
# The plugin name is taken from the first argument. Additional libraries
# (for example, libpng) may be specified after the optionl LINK_LIBRARIES
# keyword.
#
# Each time this macro adds a target, it adds a new element to the
# variable "MTS_CORELIBS", which will contain all the generated core libs
#
macro (add_mts_corelib _corelib_name)
CMAKE_PARSE_ARGUMENTS(_corelib "" "" "LINK_LIBRARIES" ${ARGN})
set (_corelib_srcs ${_corelib_UNPARSED_ARGUMENTS})
set(MTS_CORELIBS ${MTS_CORELIBS} ${_corelib_name} PARENT_SCOPE)
if (WIN32)
set(_corelib_res "${CMAKE_CURRENT_BINARY_DIR}/${_corelib_name}_res.rc")
set(_corelib_description "Mitsuba core library: ${_corelib_name}")
mts_win_resource("${_corelib_res}"
"lib${_corelib_name}" ".dll" "${_corelib_description}")
list(APPEND _corelib_srcs "${_corelib_res}")
endif()
if (MTS_USE_PCH)
pch_add_library (${_corelib_name} SHARED
PCH_HEADER "${MTS_DEFAULT_PCH}" ${_corelib_srcs})
else ()
add_library (${_corelib_name} SHARED ${_corelib_srcs})
endif ()
target_link_libraries (${_corelib_name} ${_corelib_LINK_LIBRARIES})
if (WIN32)
set_target_properties (${_corelib_name} PROPERTIES
PREFIX "lib"
VERSION "${MTS_VERSION}")
endif()
if (WIN32)
set (_corelib_property_suffix "RUNTIME_OUTPUT_DIRECTORY")
else ()
set (_corelib_property_suffix "LIBRARY_OUTPUT_DIRECTORY")
endif ()
SET_OUTPATH_CFG (${_corelib_name} ${_corelib_property_suffix}
"${PROJECT_BINARY_DIR}/binaries/@CFGNAME@/${MTS_LIB_DEST}"
)
mts_target_ltcg (${_corelib_name})
mts_msvc_mp (${_corelib_name})
install(TARGETS ${_corelib_name}
RUNTIME DESTINATION "${MTS_LIB_DEST}" COMPONENT Runtime
LIBRARY DESTINATION "${MTS_LIB_DEST}" COMPONENT Runtime
ARCHIVE DESTINATION "sdk/lib" COMPONENT Developer
)
endmacro()
# Constant with the destination for the plugins
if (WIN32 OR MTS_SIMPLE_PATHS)
set(MTS_PLUGIN_DEST "plugins")
elseif (APPLE)
set(MTS_PLUGIN_DEST "${MTS_BUNDLE_NAME}/plugins")
else()
set(MTS_PLUGIN_DEST "share/mitsuba/plugins")
endif()
# Macro to add a build target for a mitsuba plugin (based on the OIIO one).
#
# Usage:
#
# add_mts_plugin (name source1 [source2 ...]
# [LINK_LIBRARIES external_lib1 ...]
# [MTS_HW] [MTS_BIDIR]
# [NO_MTS_PCH]
# [TYPE plugin_type] )
#
# The plugin name is taken from the first argument and the
# source is automatically linked against mitsuba libraries. Additional
# libraries (for example, libpng) may be specified after the optional
# LINK_LIBRARIES keyword. NO_MTS_PCH makes the target not to use the
# default mitsuba precompiled header (on supported platforms).
#
# By default the plugins are linked against mitsuba-core and mitsuba-render.
# When MTS_HW is set, the plugin will be linked against with mitsuba-hw. When
# MTS_BIDIR is specified, the plugin will also be linked against mitsuba-bidir.
#
# The plugin type (i.e. camera, bsdf, luminaire) may be specified
# after the TYPE keyword. Currently doing this modifies the IDE project name
# in order to have a nicer organization.
#
macro (add_mts_plugin _plugin_name)
CMAKE_PARSE_ARGUMENTS(_plugin "MTS_HW;MTS_BIDIR;NO_MTS_PCH"
"TYPE" "LINK_LIBRARIES" ${ARGN})
set (_plugin_srcs ${_plugin_UNPARSED_ARGUMENTS})
if (WIN32)
set(_plugin_res "${CMAKE_CURRENT_BINARY_DIR}/${_plugin_name}_res.rc")
if (_plugin_TYPE)
set(_plugin_description "Mitsuba ${_plugin_TYPE} plugin: ${_plugin_name}")
else()
set(_plugin_description "Mitsuba plugin: ${_plugin_name}")
endif()
mts_win_resource("${_plugin_res}"
"${_plugin_name}" ".dll" "${_plugin_description}")
list(APPEND _plugin_srcs "${_plugin_res}")
endif()
# Use the PCH only with the plugins with 2 or more source files
set(_plugin_cxx_count "0")
foreach(_src ${_plugin_srcs})
if(_src MATCHES ".+\\.[cC][^.]*$")
math(EXPR _plugin_cxx_count "${_plugin_cxx_count} + 1")
endif()
endforeach()
if (NOT _plugin_NO_MTS_PCH AND MTS_USE_PCH AND
(MTS_USE_PCH_ALL_PLUGINS OR _plugin_cxx_count GREATER 1))
pch_add_library (${_plugin_name} MODULE
PCH_HEADER "${MTS_DEFAULT_PCH}" ${_plugin_srcs})
else ()
add_library (${_plugin_name} MODULE ${_plugin_srcs})
endif ()
set(_plugin_core_libraries "mitsuba-core" "mitsuba-render")
if (_plugin_MTS_HW)
list(APPEND _plugin_core_libraries "mitsuba-hw")
endif()
if (_plugin_MTS_BIDIR)
list(APPEND _plugin_core_libraries "mitsuba-bidir")
endif()
target_link_libraries (${_plugin_name}
${_plugin_core_libraries} ${_plugin_LINK_LIBRARIES})
set_target_properties (${_plugin_name} PROPERTIES PREFIX "")
if (APPLE)
set_target_properties (${_plugin_name} PROPERTIES SUFFIX ".dylib")
endif ()
if (WIN32)
set_target_properties (${_plugin_name} PROPERTIES VERSION "${MTS_VERSION}")
endif()
set (_plugin_FOLDER "plugins")
if (_plugin_TYPE)
if (CMAKE_GENERATOR MATCHES "Visual Studio")
set (_plugin_FOLDER "plugins/${_plugin_TYPE}")
else()
set_target_properties (${_plugin_name} PROPERTIES
PROJECT_LABEL "${_plugin_TYPE}-${_plugin_name}")
endif()
endif()
set_target_properties (${_plugin_name} PROPERTIES
FOLDER ${_plugin_FOLDER})
unset (_plugin_FOLDER)
SET_OUTPATH_CFG (${_plugin_name} LIBRARY_OUTPUT_DIRECTORY
"${PROJECT_BINARY_DIR}/binaries/@CFGNAME@/${MTS_PLUGIN_DEST}"
)
mts_target_ltcg (${_plugin_name})
mts_msvc_mp (${_plugin_name})
install(TARGETS ${_plugin_name}
RUNTIME DESTINATION ${MTS_PLUGIN_DEST} COMPONENT Runtime
LIBRARY DESTINATION ${MTS_PLUGIN_DEST} COMPONENT Runtime)
endmacro ()
# Constant with the executables destination
if (WIN32 OR MTS_SIMPLE_PATHS)
set (MTS_EXE_DEST ".")
elseif (APPLE)
set (MTS_EXE_DEST "${MTS_BUNDLE_NAME}/Contents/MacOS")
else()
set (MTS_EXE_DEST "bin")
endif()
# Macro to add a build target for a mitsuba application.
#
# Usage:
#
# add_mts_exe (name [WIN32] source1 [source2 ...]
# [LINK_LIBRARIES external_lib1 ...]
# [RES_ICON filename]
# [RES_DESCRIPTION "Description string"]
# [NO_INSTALL]
# [MTS_HW] [MTS_BIDIR]
# [NO_MTS_PCH | PCH pch_header] )
#
# The executable name is taken from the first argument. The target gets
# automatically linked against mitusba's core libraries, as defined
# in the "MTS_CORELIBS" variable Additional libraries
# (for example, libpng) may be specified after the optionl LINK_LIBRARIES
# keyword.
#
# By default the executables are linked against mitsuba-core and mitsuba-render.
# When MTS_HW is set, the executable will be linked against with mitsuba-hw.
# When MTS_BIDIR is specified, the executable will also be linked against
# mitsuba-bidir.
#
# The optional keyword WIN32, if presents, gets passed to add_executable(...)
# to produce a Windows executable using winmain, thus it won't have a
# console. The NO_INSTALL keyword causes the target not to be installed.
# NO_MTS_PCH makes the target not to use the default mitsuba precompiled header
# (on supported platforms). PCH specifies a custom precompiler header to use
# which is more suitable for the application.
#
# The optional RES_ICON parameter specified an icon to be bundled into the
# executable. This only works on Windows builds. The optional RES_DESCRIPTION
# parameters sets a specific executable description to be used in the Windows
# builds; other platforms simply ignore this value as with RES_ICON.
#
macro (add_mts_exe _exe_name)
CMAKE_PARSE_ARGUMENTS(_exe "WIN32;NO_INSTALL;MTS_HW;MTS_BIDIR;NO_MTS_PCH"
"PCH;RES_ICON;RES_DESCRIPTION" "LINK_LIBRARIES" ${ARGN})
set (_exe_srcs ${_exe_UNPARSED_ARGUMENTS})
if (_exe_WIN32)
set(_exe_TYPE WIN32)
endif()
if (WIN32)
set(_exe_res "${CMAKE_CURRENT_BINARY_DIR}/${_exe_name}_res.rc")
set(_exe_res_args "${_exe_res}" "${_exe_name}" ".exe")
if (_exe_RES_DESCRIPTION)
set(_exe_description "${_exe_RES_DESCRIPTION}")
else()
set(_exe_description "Mitsuba application: ${_exe_name}")
endif()
list(APPEND _exe_res_args "${_exe_description}")
if (_exe_RES_ICON)
list(APPEND _exe_res_args "ICON" "${_exe_RES_ICON}")
endif()
mts_win_resource(${_exe_res_args})
list(APPEND _exe_srcs "${_exe_res}")
endif()
if (MTS_USE_PCH AND (NOT _exe_NO_MTS_PCH OR _exe_PCH))
set (_exe_pch_header "${MTS_DEFAULT_PCH}")
if (_exe_PCH)
set (_exe_pch_header "${_exe_PCH}")
if (_exe_NO_MTS_PCH)
message (AUTHOR_WARNING
"'NO_MTS_PCH' ignored due to 'PCH ${_exe_PCH}'.")
endif ()
endif ()
pch_add_executable (${_exe_name} ${_exe_TYPE}
PCH_HEADER "${_exe_pch_header}" ${_exe_srcs})
else ()
add_executable (${_exe_name} ${_exe_TYPE} ${_exe_srcs})
endif ()
set(_exe_core_libraries "mitsuba-core" "mitsuba-render")
if (_exe_MTS_HW)
list(APPEND _exe_core_libraries "mitsuba-hw")
endif()
if (_exe_MTS_BIDIR)
list(APPEND _exe_core_libraries "mitsuba-bidir")
endif()
target_link_libraries (${_exe_name} ${_exe_core_libraries} ${_exe_LINK_LIBRARIES})
if (WIN32)
set_target_properties (${_exe_name} PROPERTIES VERSION "${MTS_VERSION}")
endif()
set_target_properties (${_exe_name} PROPERTIES FOLDER "apps")
SET_OUTPATH_CFG (${_exe_name} RUNTIME_OUTPUT_DIRECTORY
"${PROJECT_BINARY_DIR}/binaries/@CFGNAME@/${MTS_EXE_DEST}"
)
mts_target_ltcg (${_exe_name})
mts_msvc_mp (${_exe_name})
if (NOT _exe_NO_INSTALL)
install(TARGETS ${_exe_name}
RUNTIME DESTINATION ${MTS_EXE_DEST} COMPONENT Runtime)
endif()
endmacro()
# Constant with the headers destination
if (WIN32 OR MTS_SIMPLE_PATHS)
set (MTS_HEADER_DEST "sdk/include")
elseif (APPLE)
set (MTS_HEADER_DEST "${MTS_BUNDLE_NAME}/Headers")
else()
set (MTS_HEADER_DEST "include")
endif()
# Macro to install header files. The FOLDER option specifies a subdirectory
# on which the given headers will be installed. Usage:
# mts_install_headers(header1 header2 ... [FOLDER subdir])
macro (mts_install_headers)
CMAKE_PARSE_ARGUMENTS(_hdrs "" "FOLDER" "" ${ARGN})
set (_hdrs_files ${_hdrs_UNPARSED_ARGUMENTS})
if (NOT _hdrs_FOLDER)
set (_hdrs_FOLDER ".")
endif ()
install (FILES ${_hdrs_files}
PERMISSIONS "OWNER_READ" "GROUP_READ" "WORLD_READ"
DESTINATION "${MTS_HEADER_DEST}/${_hdrs_FOLDER}"
COMPONENT Developer)
endmacro ()
# Function to get a list of paths contained in variables which match the regex
# "LIBRAR(Y|IES)$". This is intended to be used with the FIXUP_BUNDLE macro.
# Example usage:
# mts_library_paths (paths)
# message (${paths})
function (mts_library_paths outvar_name)
set (library_paths "")
get_cmake_property (variables VARIABLES)
foreach (var ${variables})
if (var MATCHES "LIBRAR(Y|IES)$")
foreach (path ${${var}})
get_filename_component (libpath "${path}" PATH)
if (libpath AND EXISTS "${libpath}")
get_filename_component (libpath "${libpath}" REALPATH)
set (library_paths ${library_paths} ${libpath})
endif ()
endforeach ()
endif ()
endforeach ()
list (REMOVE_DUPLICATES library_paths)
# Try to add the "bin" directories that might exist as well
set (bin_paths "")
if (WIN32)
foreach (libpath ${library_paths})
if (EXISTS "${libpath}/../bin")
get_filename_component (binpath "${libpath}/../bin" REALPATH)
set (bin_paths ${bin_paths} ${binpath})
endif ()
if (EXISTS "${libpath}/bin")
get_filename_component (binpath "${libpath}/bin" REALPATH)
set (bin_paths ${bin_paths} ${binpath})
endif ()
endforeach ()
endif ()
list (REMOVE_DUPLICATES bin_paths)
set (${outvar_name} ${bin_paths} ${library_paths} PARENT_SCOPE)
endfunction ()