Skip to content

Commit

Permalink
CMake: add new option "Mayo_PostBuildCopyRuntimeDLLs"
Browse files Browse the repository at this point in the history
Relates to GitHub #53
  • Loading branch information
HuguesDelorme committed Feb 28, 2024
1 parent 8ebab10 commit 6e0fc23
Show file tree
Hide file tree
Showing 2 changed files with 220 additions and 87 deletions.
165 changes: 78 additions & 87 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,24 @@ math(EXPR Mayo_TargetArchBitSize "8 * ${CMAKE_SIZEOF_VOID_P}")

option(Mayo_BuildTests "Build Mayo testing suite" OFF)
option(Mayo_BuildPluginAssimp "Build plugin to import/export mesh files supported by Assimp" OFF)
if(WIN32)
set(Mayo_PostBuildCopyRuntimeDLLs_DefaultValue OFF)
if(CMAKE_GENERATOR MATCHES "Visual Studio")
set(Mayo_PostBuildCopyRuntimeDLLs_DefaultValue ON)
endif()

message(STATUS "Mayo_PostBuildCopyRuntimeDLLs_DefaultValue=${Mayo_PostBuildCopyRuntimeDLLs_DefaultValue}")
option(
Mayo_PostBuildCopyRuntimeDLLs
"\
Add post build step to copy all runtime DLLs alongside Mayo executable.\n\
This simplifies running Mayo from eg Visual Studio IDE\
"
${Mayo_PostBuildCopyRuntimeDLLs_DefaultValue}
)

endif()

# TODO
# option(Mayo_BuildPluginGmio "Build plugin to import/export mesh files supported by gmio" OFF)

Expand All @@ -85,6 +103,10 @@ if(QT_FOUND)
find_package(Qt6 REQUIRED COMPONENTS OpenGLWidgets)
endif()

if(Mayo_PostBuildCopyRuntimeDLLs)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Svg)
endif()

message(STATUS "Qt version ${QT_VERSION}")
if(QT_VERSION VERSION_LESS 5.14)
message(FATAL_ERROR "Qt >= 5.14 is required but detected version is ${QT_VERSION}")
Expand Down Expand Up @@ -151,13 +173,21 @@ endif()
set(Mayo_LinkLibraries)
set(Mayo_LinkDirectories)

if(QT_VERSION_MAJOR EQUAL 5)
list(APPEND Mayo_LinkLibraries Qt5::Core Qt5::Gui Qt5::Widgets)
if(WIN32)
list(APPEND Mayo_LinkLibraries Qt5::WinExtras)
endif()
list(
APPEND Mayo_LinkLibraries
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets
)

if(Mayo_PostBuildCopyRuntimeDLLs)
list(APPEND Mayo_LinkLibraries Qt${QT_VERSION_MAJOR}::Svg)
endif()

if(WIN32 AND QT_VERSION_MAJOR EQUAL 5)
list(APPEND Mayo_LinkLibraries Qt5::WinExtras)
elseif(QT_VERSION_MAJOR EQUAL 6)
list(APPEND Mayo_LinkLibraries Qt6::Core Qt6::Gui Qt6::Widgets Qt6::OpenGLWidgets)
list(APPEND Mayo_LinkLibraries Qt6::OpenGLWidgets)
endif()

if(MSVC)
Expand Down Expand Up @@ -261,87 +291,11 @@ endif()
if(WIN32)
# Can't use find_package(OpenCASCADE) as OpenCASCADEConfig.cmake is broken for Windows platform
# See https://dev.opencascade.org/content/3rdparty-hard-coded-paths-when-building-against-opencascade

set(OpenCASCADE_DIR CACHE PATH "Path where is located OpenCASCADE env.bat file")

# OpenCASCADE_DIR may actually points to opencascade/cmake
if(NOT EXISTS ${OpenCASCADE_DIR}/env.bat)
cmake_path(GET OpenCASCADE_DIR PARENT_PATH OpenCASCADE_DIR_PARENT_PATH)
if(EXISTS ${OpenCASCADE_DIR_PARENT_PATH}/env.bat)
set(OpenCASCADE_DIR ${OpenCASCADE_DIR_PARENT_PATH})
endif()
endif()

# Generate file "Mayo_OpenCascadeEnv.cmake"
if(EXISTS "${OpenCASCADE_DIR}/env.bat")
execute_process(
COMMAND cmd /c ${PROJECT_SOURCE_DIR}/scripts/gen-cmake-opencascade-vars.bat "${OpenCASCADE_DIR}"
OUTPUT_FILE ${CMAKE_BINARY_DIR}/Mayo_OpenCascadeEnv.cmake
)
include(${CMAKE_BINARY_DIR}/Mayo_OpenCascadeEnv.cmake)
endif()

# Set OpenCASCADE variables
if(OpenCASCADE_FOUND)
# Set variables for OpenCASCADE version
file(READ ${OpenCASCADE_INCLUDE_DIR}/Standard_Version.hxx OpenCascade_FileVersionHxx)
string(REGEX MATCH "define[ \t]+OCC_VERSION_MAJOR[ \t]+([0-9]+)" OpenCASCADE_MAJOR_VERSION "${OpenCascade_FileVersionHxx}")
set(OpenCASCADE_MAJOR_VERSION ${CMAKE_MATCH_1})
string(REGEX MATCH "define[ \t]+OCC_VERSION_MINOR[ \t]+([0-9]+)" OpenCASCADE_MINOR_VERSION "${OpenCascade_FileVersionHxx}")
set(OpenCASCADE_MINOR_VERSION ${CMAKE_MATCH_1})
string(REGEX MATCH "define[ \t]+OCC_VERSION_MAINTENANCE[ \t]+([0-9]+)" OpenCASCADE_MAINTENANCE_VERSION "${OpenCascade_FileVersionHxx}")
set(OpenCASCADE_MAINTENANCE_VERSION ${CMAKE_MATCH_1})
set(OpenCASCADE_VERSION "${OpenCASCADE_MAJOR_VERSION}.${OpenCASCADE_MINOR_VERSION}.${OpenCASCADE_MAINTENANCE_VERSION}")

include(${PROJECT_SOURCE_DIR}/cmake/OpenCascadeWin.cmake)
if (OpenCASCADE_FOUND)
# Add OpenCASCADE include directory
list(APPEND Mayo_IncludeDirectories ${OpenCASCADE_INCLUDE_DIR})

# Add OpenCASCADE "HAVE_RAPIDJSON" compile flags
if(OpenCASCADE_HAVE_RAPIDJSON STREQUAL "true")
list(APPEND Mayo_CompileDefinitions HAVE_RAPIDJSON)
elseif(OpenCASCADE_VERSION VERSION_GREATER_EQUAL 7.8.0)
file(GLOB OpenCASCADE_CompileDefsCMakeFiles ${OpenCASCADE_DIR}/cmake/OpenCASCADECompileDefinitions*.cmake)
foreach(CMakeFile ${OpenCASCADE_CompileDefsCMakeFiles})
file(READ "${CMakeFile}" CMakeFileContents)
if(CMakeFileContents MATCHES ":HAVE_RAPIDJSON>")
list(APPEND Mayo_CompileDefinitions HAVE_RAPIDJSON)
break()
endif()
endforeach()
endif()

# Set OpenCASCADE_3RDPARTY_BINARY_DIRS variable that will contain the OpenCASCADE
# 3rd-party binary directories(ie containing DLL files)
set(OpenCASCADE_3RDPARTY_BINARY_DIRS)
if(OpenCASCADE_VERSION VERSION_GREATER_EQUAL 7.8.0)
list(
APPEND OpenCASCADE_3RDPARTY_BINARY_DIRS
${TCL_DIR}
${TK_DIR}
${FREETYPE_DIR}
${FREEIMAGE_DIR}
${FFMPEG_DIR}
${TBB_DIR}
${OPENVR_DIR}
${JEMALLOC_DIR}
)
else()
if(Mayo_TargetArchBitSize STREQUAL "32")
list(APPEND OpenCASCADE_3RDPARTY_BINARY_DIRS ${CSF_OPT_BIN32})
else()
list(APPEND OpenCASCADE_3RDPARTY_BINARY_DIRS ${CSF_OPT_BIN64})
endif()

# Remove Qt binary path probably added in CSF_OPT_BIN(32/64) variable
set(OpenCASCADE_QT_BINDIR)
foreach(BINDIR ${OpenCASCADE_3RDPARTY_BINARY_DIRS})
if(BINDIR MATCHES "qt5")
set(OpenCASCADE_QT_BINDIR ${BINDIR})
endif()
endforeach()
list(REMOVE_ITEM OpenCASCADE_3RDPARTY_BINARY_DIRS ${OpenCASCADE_QT_BINDIR})
endif()

# Add OpenCASCADE library directories
# Note: QtCreator option "Run->Add build library search to PATH" will add to PATH env variable
# the contents of Mayo_LinkDirectories variable. For convenience, let's add also the
Expand All @@ -352,9 +306,7 @@ if(WIN32)
${OpenCASCADE_LIBRARY_DIR}
${OpenCASCADE_3RDPARTY_BINARY_DIRS}
)
else()
message(WARNING "OpenCASCADE not found from this location OpenCASCADE_DIR='${OpenCASCADE_DIR}' ")
endif()
endif()
else()
find_package(OpenCASCADE REQUIRED)
if(OpenCASCADE_FOUND)
Expand Down Expand Up @@ -401,6 +353,7 @@ if(OpenCASCADE_FOUND)
)

if(OpenCASCADE_VERSION VERSION_GREATER_EQUAL 7.8.0)
list(APPEND Mayo_LinkLibraries TKDE)
list(APPEND Mayo_LinkLibraries TKDEIGES)
list(APPEND Mayo_LinkLibraries TKDESTEP)
list(APPEND Mayo_LinkLibraries TKDESTL)
Expand Down Expand Up @@ -553,3 +506,41 @@ set_target_properties(
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)

if(Mayo_PostBuildCopyRuntimeDLLs)
# Copy required Qt plugins
set(QtPluginsDir "${QT_DIR}/../../../plugins")
file(GLOB QtPluginIconEnginesDLLs "${QtPluginsDir}/iconengines/qsvgicon*.dll")
file(GLOB QtPluginImageFormatsDLLs "${QtPluginsDir}/imageformats/qsvg*.dll")
file(GLOB QtPluginPlatformsDLLs "${QtPluginsDir}/platforms/qwindows*.dll")
set(QtPluginsDLLs ${QtPluginIconEnginesDLLs} ${QtPluginImageFormatsDLLs} ${QtPluginPlatformsDLLs})
foreach(QtPluginDLL ${QtPluginsDLLs})
cmake_path(GET QtPluginDLL PARENT_PATH QtPluginDLL_Path)
cmake_path(GET QtPluginDLL_Path FILENAME QtPluginDLL_PathName)
add_custom_command(
TARGET mayo POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:mayo>/plugins/${QtPluginDLL_PathName}"
)
add_custom_command(
TARGET mayo POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${QtPluginDLL}" "$<TARGET_FILE_DIR:mayo>/plugins/${QtPluginDLL_PathName}"
)
endforeach()

# Copy OpenCascade 3rd-party DLLs
foreach(Occ3rdDLL ${OpenCASCADE_3RDPARTY_DLLS})
add_custom_command(
TARGET mayo POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${Occ3rdDLL}" $<TARGET_FILE_DIR:mayo>
)
endforeach()

# Copy runtime DLLs specified with library IMPORTED_LOCATION property
add_custom_command(
TARGET mayo POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_RUNTIME_DLLS:mayo> $<TARGET_FILE_DIR:mayo>
COMMAND_EXPAND_LISTS
)
endif()
142 changes: 142 additions & 0 deletions cmake/OpenCascadeWin.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
set(OpenCASCADE_DIR CACHE PATH "Path where is located OpenCASCADE env.bat file")

# OpenCASCADE_DIR may actually points to opencascade/cmake
if(NOT EXISTS ${OpenCASCADE_DIR}/env.bat)
cmake_path(GET OpenCASCADE_DIR PARENT_PATH OpenCASCADE_DIR_PARENT_PATH)
if(EXISTS ${OpenCASCADE_DIR_PARENT_PATH}/env.bat)
set(OpenCASCADE_DIR ${OpenCASCADE_DIR_PARENT_PATH})
endif()
endif()

# Generate file "OpenCascadeWin_env.cmake"
if(EXISTS "${OpenCASCADE_DIR}/env.bat")
execute_process(
COMMAND cmd /c ${PROJECT_SOURCE_DIR}/scripts/gen-cmake-opencascade-vars.bat "${OpenCASCADE_DIR}"
OUTPUT_FILE ${CMAKE_BINARY_DIR}/OpenCascadeWin_env.cmake
)
include(${CMAKE_BINARY_DIR}/OpenCascadeWin_env.cmake)
endif()

# Set OpenCASCADE variables
if(OpenCASCADE_FOUND)
# Set variables for OpenCASCADE version
file(READ ${OpenCASCADE_INCLUDE_DIR}/Standard_Version.hxx OpenCascade_FileVersionHxx)
string(REGEX MATCH "define[ \t]+OCC_VERSION_MAJOR[ \t]+([0-9]+)" OpenCASCADE_MAJOR_VERSION "${OpenCascade_FileVersionHxx}")
set(OpenCASCADE_MAJOR_VERSION ${CMAKE_MATCH_1})
string(REGEX MATCH "define[ \t]+OCC_VERSION_MINOR[ \t]+([0-9]+)" OpenCASCADE_MINOR_VERSION "${OpenCascade_FileVersionHxx}")
set(OpenCASCADE_MINOR_VERSION ${CMAKE_MATCH_1})
string(REGEX MATCH "define[ \t]+OCC_VERSION_MAINTENANCE[ \t]+([0-9]+)" OpenCASCADE_MAINTENANCE_VERSION "${OpenCascade_FileVersionHxx}")
set(OpenCASCADE_MAINTENANCE_VERSION ${CMAKE_MATCH_1})
set(OpenCASCADE_VERSION "${OpenCASCADE_MAJOR_VERSION}.${OpenCASCADE_MINOR_VERSION}.${OpenCASCADE_MAINTENANCE_VERSION}")

# Add OpenCASCADE "HAVE_RAPIDJSON" compile flags
if(OpenCASCADE_HAVE_RAPIDJSON STREQUAL "true")
list(APPEND Mayo_CompileDefinitions HAVE_RAPIDJSON)
elseif(OpenCASCADE_VERSION VERSION_GREATER_EQUAL 7.8.0)
file(GLOB OpenCASCADE_CompileDefsCMakeFiles ${OpenCASCADE_DIR}/cmake/OpenCASCADECompileDefinitions*.cmake)
foreach(CMakeFile ${OpenCASCADE_CompileDefsCMakeFiles})
file(READ "${CMakeFile}" CMakeFileContents)
if(CMakeFileContents MATCHES ":HAVE_RAPIDJSON>")
list(APPEND Mayo_CompileDefinitions HAVE_RAPIDJSON)
break()
endif()
endforeach()
endif()

# Set OpenCASCADE_3RDPARTY_BINARY_DIRS variable that will contain the OpenCASCADE
# 3rd-party binary directories(ie containing DLL files)
set(OpenCASCADE_3RDPARTY_BINARY_DIRS)
if(OpenCASCADE_VERSION VERSION_GREATER_EQUAL 7.8.0)
list(
APPEND OpenCASCADE_3RDPARTY_BINARY_DIRS
${TCL_DIR}
${TK_DIR}
${FREETYPE_DIR}
${FREEIMAGE_DIR}
${FFMPEG_DIR}
${TBB_DIR}
${OPENVR_DIR}
${JEMALLOC_DIR}
)
else()
if(Mayo_TargetArchBitSize STREQUAL "32")
list(APPEND OpenCASCADE_3RDPARTY_BINARY_DIRS ${CSF_OPT_BIN32})
else()
list(APPEND OpenCASCADE_3RDPARTY_BINARY_DIRS ${CSF_OPT_BIN64})
endif()

# Remove Qt binary path probably added in CSF_OPT_BIN(32/64) variable
set(OpenCASCADE_QT_BINDIR)
foreach(BINDIR ${OpenCASCADE_3RDPARTY_BINARY_DIRS})
if(BINDIR MATCHES "qt5")
set(OpenCASCADE_QT_BINDIR ${BINDIR})
endif()
endforeach()
list(REMOVE_ITEM OpenCASCADE_3RDPARTY_BINARY_DIRS ${OpenCASCADE_QT_BINDIR})
endif()

# Create imported target for each toolkit
set(
OpenCASCADE_TOOLKITS
# FoundationClasses
TKernel TKMath
# ModelingData
TKG2d TKG3d TKGeomBase TKBRep
# ModelingAlgorithms
TKBO TKBool TKGeomAlgo TKHLR TKMesh TKPrim TKShHealing TKTopAlgo
# Visualization
TKMeshVS TKOpenGl TKService TKV3d
# ApplicationFramework
TKBin TKBinL TKBinXCAF TKCAF TKCDF TKLCAF TKVCAF TKXml TKXmlL
# DataExchange
TKXCAF TKXmlXCAF TKXSBase
)

if(OpenCASCADE_VERSION VERSION_GREATER_EQUAL 7.8.0)
list(APPEND OpenCASCADE_TOOLKITS TKDE TKDEIGES TKDESTEP TKDESTL TKDEVRML)
else()
list(APPEND OpenCASCADE_TOOLKITS TKIGES TKXDEIGES)
list(APPEND OpenCASCADE_TOOLKITS TKSTEP TKSTEP209 TKSTEPAttr TKSTEPBase TKXDESTEP)
list(APPEND OpenCASCADE_TOOLKITS TKSTL)
list(APPEND OpenCASCADE_TOOLKITS TKVRML)
if(OpenCASCADE_VERSION VERSION_GREATER_EQUAL 7.7.0)
list(APPEND OpenCASCADE_TOOLKITS TKXDE)
endif()
endif()

if(OpenCASCADE_VERSION VERSION_GREATER_EQUAL 7.4.0)
list(APPEND OpenCASCADE_TOOLKITS TKRWMesh)
if(OpenCASCADE_VERSION VERSION_GREATER_EQUAL 7.8.0)
list(APPEND OpenCASCADE_TOOLKITS TKDEOBJ TKDEGLTF)
endif()
endif()

foreach(OccTK ${OpenCASCADE_TOOLKITS})
add_library(${OccTK} SHARED IMPORTED)
set_target_properties(
${OccTK} PROPERTIES
IMPORTED_IMPLIB "${OpenCASCADE_LIBRARY_DIR}/${OccTK}.lib"
IMPORTED_LOCATION "${OpenCASCADE_BINARY_DIR}/${OccTK}.dll"
)
endforeach()

# Add OpenCASCADE library directories
# Note: QtCreator option "Run->Add build library search to PATH" will add to PATH env variable
# the contents of Mayo_LinkDirectories variable. For convenience, let's add also the
# directories containing DLLs
list(
APPEND Mayo_LinkDirectories
${OpenCASCADE_BINARY_DIR}
${OpenCASCADE_LIBRARY_DIR}
${OpenCASCADE_3RDPARTY_BINARY_DIRS}
)

# List all 3rd-party DLLs required by OpenCASCADE
set(OpenCASCADE_3RDPARTY_DLLS)
foreach(OccBINDIR ${OpenCASCADE_3RDPARTY_BINARY_DIRS})
file(GLOB OccBINDIR_DLLS ${OccBINDIR}/*.dll)
list(APPEND OpenCASCADE_3RDPARTY_DLLS ${OccBINDIR_DLLS})
endforeach()
else()
message(WARNING "OpenCASCADE not found from this location OpenCASCADE_DIR='${OpenCASCADE_DIR}' ")
endif()

0 comments on commit 6e0fc23

Please sign in to comment.