CMakeLists.txt 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. #/|/ Copyright (c) Prusa Research 2018 - 2022 Lukáš Matěna @lukasmatena, Tomáš Mészáros @tamasmeszaros, Filip Sykala @Jony01, Vojtěch Bubník @bubnikv, Vojtěch Král @vojtechkral
  2. #/|/
  3. #/|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
  4. #/|/
  5. #
  6. # This CMake project downloads, configures and builds PrusaSlicer dependencies on Unix and Windows.
  7. #
  8. # When using this script, it's recommended to perform an out-of-source build using CMake.
  9. #
  10. # All the dependencies are installed in a `destdir` directory in the root of the build directory,
  11. # in a traditional Unix-style prefix structure. The destdir can be used directly by CMake
  12. # when building PrusaSlicer - to do this, set the CMAKE_PREFIX_PATH to ${destdir}/usr/local.
  13. # Warning: On UNIX/Linux, you also need to set -DSLIC3R_STATIC=1 when building PrusaSlicer.
  14. #
  15. # For better clarity of console output, it's recommended to _not_ use a parallelized build
  16. # for the top-level command, ie. use `make -j 1` or `ninja -j 1` to force single-threaded top-level
  17. # build. This doesn't degrade performance as individual dependencies are built in parallel fashion
  18. # if supported by the dependency.
  19. #
  20. # On Windows, architecture (64 vs 32 bits) is judged based on the compiler variant.
  21. # To build dependencies for either 64 or 32 bit OS, use the respective compiler command line.
  22. #
  23. # WARNING: On UNIX platforms wxWidgets hardcode the destdir path into its `wx-conffig` utility,
  24. # therefore, unfortunatelly, the installation cannot be copied/moved elsewhere without re-installing wxWidgets.
  25. #
  26. cmake_minimum_required(VERSION 3.12)
  27. project(PrusaSlicer_deps)
  28. # Redefine BUILD_SHARED_LIBS with default being OFF
  29. option(BUILD_SHARED_LIBS "Build shared libraries instead of static (experimental)" OFF)
  30. set(${PROJECT_NAME}_PACKAGE_EXCLUDES "" CACHE STRING "Exclude packages matching this regex pattern")
  31. # Support legacy parameter DESTDIR
  32. if (DESTDIR)
  33. set(${PROJECT_NAME}_DEP_INSTALL_PREFIX ${DESTDIR}/usr/local CACHE PATH "Destination directory" FORCE)
  34. endif ()
  35. # Support legacy parameter DEP_DOWNLOAD_DIR
  36. if (DEP_DOWNLOAD_DIR)
  37. set(${PROJECT_NAME}_DEP_DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR} CACHE PATH "Path for downloaded source packages." FORCE)
  38. endif ()
  39. # Slightly controversial
  40. set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules)
  41. if (MSVC)
  42. option(DEP_DEBUG "Build in debug version of packages automatically" ON)
  43. endif ()
  44. if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.24)
  45. cmake_policy(SET CMP0135 NEW)
  46. endif ()
  47. include(${PROJECT_SOURCE_DIR}/../cmake/modules/AddCMakeProject.cmake)
  48. macro(list_projects result curdir)
  49. file(GLOB children RELATIVE ${curdir} ${curdir}/*)
  50. set(dirlist "")
  51. foreach(child ${children})
  52. if(IS_DIRECTORY ${curdir}/${child})
  53. string(REGEX MATCH "^\\+([a-zA-Z0-9]+)" is_package_dir ${child})
  54. if(is_package_dir AND EXISTS ${curdir}/${child}/${CMAKE_MATCH_1}.cmake)
  55. list(APPEND dirlist ${CMAKE_MATCH_1})
  56. endif()
  57. endif()
  58. endforeach()
  59. set(${result} ${dirlist})
  60. endmacro()
  61. function(dep_message mode msg)
  62. if (NOT DEP_MESSAGES_WRITTEN)
  63. message(${mode} "${msg}")
  64. endif()
  65. endfunction ()
  66. # Always ON options:
  67. if (MSVC)
  68. if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
  69. dep_message(STATUS "Detected 64-bit compiler => building 64-bit deps bundle")
  70. set(DEPS_BITS 64)
  71. elseif ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
  72. dep_message(STATUS "Detected 32-bit compiler => building 32-bit deps bundle")
  73. set(DEPS_BITS 32)
  74. else ()
  75. dep_message(FATAL_ERROR "Unable to detect architecture!")
  76. endif ()
  77. else ()
  78. set(DEP_CMAKE_OPTS "-DCMAKE_POSITION_INDEPENDENT_CODE=ON")
  79. endif ()
  80. if (APPLE)
  81. if (CMAKE_OSX_DEPLOYMENT_TARGET)
  82. set(DEP_OSX_TARGET "${CMAKE_OSX_DEPLOYMENT_TARGET}")
  83. dep_message(STATUS "OS X Deployment Target: ${DEP_OSX_TARGET}")
  84. else ()
  85. # Attempt to infer the SDK version from the CMAKE_OSX_SYSROOT,
  86. # this is done because wxWidgets need the min version explicitly set
  87. string(REGEX MATCH "[0-9]+[.][0-9]+[.]sdk$" DEP_OSX_TARGET "${CMAKE_OSX_SYSROOT}")
  88. string(REGEX MATCH "^[0-9]+[.][0-9]+" DEP_OSX_TARGET "${DEP_OSX_TARGET}")
  89. if (NOT DEP_OSX_TARGET)
  90. message(FATAL_ERROR "Could not determine OS X SDK version. Please use -DCMAKE_OSX_DEPLOYMENT_TARGET=<version>")
  91. endif ()
  92. dep_message(STATUS "OS X Deployment Target (inferred from SDK): ${DEP_OSX_TARGET}")
  93. endif ()
  94. # This ensures dependencies don't use SDK features which are not available in the version specified by Deployment target
  95. # That can happen when one uses a recent SDK but specifies an older Deployment target
  96. set(DEP_WERRORS_SDK "-Werror=partial-availability -Werror=unguarded-availability -Werror=unguarded-availability-new")
  97. set(DEP_CMAKE_OPTS
  98. "-DCMAKE_POSITION_INDEPENDENT_CODE=ON"
  99. "-DCMAKE_OSX_SYSROOT=${CMAKE_OSX_SYSROOT}"
  100. "-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}"
  101. "-DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}"
  102. "-DCMAKE_CXX_FLAGS=${DEP_WERRORS_SDK}"
  103. "-DCMAKE_C_FLAGS=${DEP_WERRORS_SDK}"
  104. "-DCMAKE_FIND_FRAMEWORK=LAST"
  105. "-DCMAKE_FIND_APPBUNDLE=LAST"
  106. )
  107. endif ()
  108. list_projects(FOUND_PACKAGES ${CMAKE_CURRENT_LIST_DIR})
  109. dep_message(STATUS "Found external package definitions: ${FOUND_PACKAGES}")
  110. # Current list of all required dependencies for PS (top level)
  111. set(REQUIRED_PACKAGES
  112. Boost
  113. Catch2
  114. Cereal
  115. CURL
  116. EXPAT
  117. NLopt
  118. GLEW
  119. TBB
  120. Qhull
  121. wxWidgets
  122. OpenVDB
  123. CGAL
  124. OCCT
  125. ZLIB
  126. LibBGCode
  127. )
  128. set(${PROJECT_NAME}_PLATFORM_PACKAGES "" CACHE STRING "Select packages which are provided by the platform" )
  129. set(SYSTEM_PROVIDED_PACKAGES OpenGL)
  130. if (UNIX)
  131. # On UNIX systems (including Apple) ZLIB should be available
  132. list(APPEND SYSTEM_PROVIDED_PACKAGES ZLIB)
  133. endif ()
  134. list(APPEND SYSTEM_PROVIDED_PACKAGES ${${PROJECT_NAME}_PLATFORM_PACKAGES})
  135. list(REMOVE_DUPLICATES SYSTEM_PROVIDED_PACKAGES)
  136. include(CMakeDependentOption)
  137. option(${PROJECT_NAME}_SELECT_ALL "Choose all external projects to be built." ON)
  138. find_package(Git REQUIRED)
  139. # The default command line for patching. Only works for newer
  140. set(PATCH_CMD ${GIT_EXECUTABLE} apply --verbose --ignore-space-change --whitespace=fix)
  141. # all required package targets that have existing definitions will be gathered here
  142. set(DEPS_TO_BUILD "")
  143. set(_build_list "")
  144. set(_build_list_toplevel "")
  145. set(_checked_list "")
  146. # function to check if a package ought to be provided by the platform can really be found
  147. function (check_system_package pkg checked_list)
  148. if (NOT ${pkg} IN_LIST ${checked_list})
  149. find_package(${pkg})
  150. if (NOT ${pkg}_FOUND)
  151. dep_message(WARNING "No ${pkg} found in system altough marked as system provided. This might cause trouble building the dependencies on this platform")
  152. endif ()
  153. list(APPEND ${checked_list} ${pkg})
  154. set (${checked_list} ${${checked_list}} PARENT_SCOPE)
  155. endif ()
  156. endfunction()
  157. # Go through all the found package definition folders and filter them according to the provided cache options
  158. set(SUPPORTED_PACKAGES "")
  159. foreach (pkg ${FOUND_PACKAGES})
  160. cmake_dependent_option(${PROJECT_NAME}_SELECT_${pkg} "Select package ${pkg} to be built." OFF "NOT ${PROJECT_NAME}_SELECT_ALL" OFF)
  161. if (NOT ${PROJECT_NAME}_PACKAGE_EXCLUDES MATCHES ${pkg} AND (${PROJECT_NAME}_SELECT_ALL OR ${PROJECT_NAME}_SELECT_${pkg}))
  162. include(+${pkg}/${pkg}.cmake)
  163. list(APPEND SUPPORTED_PACKAGES ${pkg})
  164. if (${pkg} IN_LIST SYSTEM_PROVIDED_PACKAGES)
  165. check_system_package(${pkg} _checked_list)
  166. elseif (${pkg} IN_LIST REQUIRED_PACKAGES)
  167. list(APPEND DEPS_TO_BUILD ${pkg})
  168. endif ()
  169. endif ()
  170. endforeach()
  171. # Establish dependency graph
  172. foreach (pkg ${SUPPORTED_PACKAGES})
  173. if (${pkg} IN_LIST DEPS_TO_BUILD)
  174. list(APPEND _build_list dep_${pkg})
  175. list(APPEND _build_list_toplevel dep_${pkg})
  176. endif ()
  177. foreach(deppkg ${DEP_${pkg}_DEPENDS})
  178. if (${deppkg} IN_LIST SYSTEM_PROVIDED_PACKAGES)
  179. check_system_package(${deppkg} _checked_list)
  180. elseif(TARGET dep_${deppkg})
  181. dep_message(STATUS "Mapping dep_${deppkg} => dep_${pkg}")
  182. add_dependencies(dep_${pkg} dep_${deppkg})
  183. if (${pkg} IN_LIST REQUIRED_PACKAGES)
  184. list(APPEND _build_list dep_${deppkg})
  185. endif ()
  186. endif ()
  187. endforeach()
  188. endforeach()
  189. list(REMOVE_DUPLICATES _build_list)
  190. dep_message(STATUS "Building dep targets (${CMAKE_BUILD_TYPE}): ${_build_list}")
  191. add_custom_target(deps ALL DEPENDS ${_build_list_toplevel})
  192. # Support legacy option DEP_DEBUG on MSVC to build debug libraries in the same cmake run as for CMAKE_BUILD_TYPE:
  193. if (DEP_DEBUG AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
  194. # MSVC has this nice feature to not be able to link release mode libs to Debug mode
  195. # projects
  196. # Exclude the libraries which have no problem to link to Debug builds in
  197. # Release mode (mostly C libraries)
  198. set(DEP_DEBUG_EXCLUDES GMP MPFR OpenSSL NanoSVG TIFF JPEG ZLIB heatshrink)
  199. if (UNIX)
  200. # Making a separate debug build on Unix of wx is a nightmare
  201. list(APPEND DEP_DEBUG_EXCLUDES wxWidgets)
  202. endif ()
  203. # Create the list of targets needed in debug mode
  204. set(_build_list_dbg "")
  205. set(_build_list_filt ${_build_list})
  206. list(JOIN DEP_DEBUG_EXCLUDES "|" _excl_regexp)
  207. list(FILTER _build_list_filt EXCLUDE REGEX "${_excl_regexp}")
  208. foreach (t ${_build_list_filt})
  209. list(APPEND _build_list_dbg ${t}_debug)
  210. endforeach()
  211. # Create a subdirectory for the Debug build within the current binary dir:
  212. file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/_d)
  213. execute_process(
  214. COMMAND ${CMAKE_COMMAND} ${CMAKE_CURRENT_SOURCE_DIR} -G${CMAKE_GENERATOR}
  215. -DCMAKE_BUILD_TYPE=Debug
  216. -DDEP_WX_GTK3=${DEP_WX_GTK3}
  217. -D${PROJECT_NAME}_DEP_DOWNLOAD_DIR=${${PROJECT_NAME}_DEP_DOWNLOAD_DIR}
  218. -D${PROJECT_NAME}_DEP_INSTALL_PREFIX=${${PROJECT_NAME}_DEP_INSTALL_PREFIX}
  219. -D${PROJECT_NAME}_PACKAGE_EXCLUDES="${_excl_regexp}"
  220. -D${PROJECT_NAME}_SELECT_ALL=${${PROJECT_NAME}_SELECT_ALL}
  221. -D${PROJECT_NAME}_DEP_BUILD_VERBOSE=${${PROJECT_NAME}_DEP_BUILD_VERBOSE}
  222. -DCMAKE_DEBUG_POSTFIX=d
  223. #TODO: forward per-package selector variables
  224. -DDEP_MESSAGES_WRITTEN=ON
  225. WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/_d
  226. OUTPUT_QUIET
  227. )
  228. dep_message(STATUS "Building dep targets (Debug): ${_build_list_dbg}")
  229. # Each lib will have a dep_<package>_debug target to build only the debug counterpart
  230. # Not part of ALL (problem with parallelization)
  231. foreach(pkgtgt ${_build_list_filt})
  232. add_custom_target(${pkgtgt}_debug
  233. COMMAND ${CMAKE_COMMAND} --build . --target ${pkgtgt}
  234. WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/_d
  235. USES_TERMINAL
  236. )
  237. endforeach()
  238. # Can be used to build all the debug libs
  239. string(JOIN " " _build_list_filt_targets "${_build_list_filt}")
  240. add_custom_target(deps_debug ALL
  241. COMMAND ${CMAKE_COMMAND} --build . --target ${_build_list_filt_targets}
  242. WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/_d
  243. USES_TERMINAL
  244. )
  245. # The Release must be built before, as there are libs in this debug session which need
  246. # the release versions of the excluded libs
  247. add_dependencies(deps_debug deps)
  248. endif ()
  249. set(DEP_MESSAGES_WRITTEN ON CACHE BOOL "")
  250. install(CODE "message(STATUS \"Built packages succesfully.\")")