CMakeLists.txt 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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. # List libraries to be excluded from build
  31. set(${PROJECT_NAME}_PACKAGE_EXCLUDES "" CACHE STRING "Exclude packages matching this regex pattern")
  32. # Support legacy parameter DESTDIR
  33. if (DESTDIR)
  34. set(${PROJECT_NAME}_DEP_INSTALL_PREFIX ${DESTDIR}/usr/local CACHE PATH "Destination directory" FORCE)
  35. endif ()
  36. # Support legacy parameter DEP_DOWNLOAD_DIR
  37. if (DEP_DOWNLOAD_DIR)
  38. set(${PROJECT_NAME}_DEP_DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR} CACHE PATH "Path for downloaded source packages." FORCE)
  39. endif ()
  40. # Slightly controversial
  41. set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules)
  42. if (MSVC)
  43. option(DEP_DEBUG "Build in debug version of packages automatically" ON)
  44. endif ()
  45. if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.24)
  46. cmake_policy(SET CMP0135 NEW)
  47. endif ()
  48. include(${PROJECT_SOURCE_DIR}/../cmake/modules/AddCMakeProject.cmake)
  49. macro(list_projects result curdir)
  50. file(GLOB children RELATIVE ${curdir} ${curdir}/*)
  51. set(dirlist "")
  52. foreach(child ${children})
  53. if(IS_DIRECTORY ${curdir}/${child})
  54. string(REGEX MATCH "^\\+([a-zA-Z0-9]+)" is_package_dir ${child})
  55. if(is_package_dir AND EXISTS ${curdir}/${child}/${CMAKE_MATCH_1}.cmake)
  56. list(APPEND dirlist ${CMAKE_MATCH_1})
  57. endif()
  58. endif()
  59. endforeach()
  60. set(${result} ${dirlist})
  61. endmacro()
  62. function(dep_message mode msg)
  63. if (NOT DEP_MESSAGES_WRITTEN)
  64. message(${mode} "${msg}")
  65. endif()
  66. endfunction ()
  67. # Always ON options:
  68. if (MSVC)
  69. if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
  70. dep_message(STATUS "Detected 64-bit compiler => building 64-bit deps bundle")
  71. set(DEPS_BITS 64)
  72. elseif ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
  73. dep_message(STATUS "Detected 32-bit compiler => building 32-bit deps bundle")
  74. set(DEPS_BITS 32)
  75. else ()
  76. dep_message(FATAL_ERROR "Unable to detect architecture!")
  77. endif ()
  78. else ()
  79. set(DEP_CMAKE_OPTS "-DCMAKE_POSITION_INDEPENDENT_CODE=ON")
  80. endif ()
  81. if (APPLE)
  82. if (CMAKE_OSX_DEPLOYMENT_TARGET)
  83. set(DEP_OSX_TARGET "${CMAKE_OSX_DEPLOYMENT_TARGET}")
  84. dep_message(STATUS "OS X Deployment Target: ${DEP_OSX_TARGET}")
  85. else ()
  86. # Attempt to infer the SDK version from the CMAKE_OSX_SYSROOT,
  87. # this is done because wxWidgets need the min version explicitly set
  88. string(REGEX MATCH "[0-9]+[.][0-9]+[.]sdk$" DEP_OSX_TARGET "${CMAKE_OSX_SYSROOT}")
  89. string(REGEX MATCH "^[0-9]+[.][0-9]+" DEP_OSX_TARGET "${DEP_OSX_TARGET}")
  90. if (NOT DEP_OSX_TARGET)
  91. message(FATAL_ERROR "Could not determine OS X SDK version. Please use -DCMAKE_OSX_DEPLOYMENT_TARGET=<version>")
  92. endif ()
  93. dep_message(STATUS "OS X Deployment Target (inferred from SDK): ${DEP_OSX_TARGET}")
  94. endif ()
  95. # This ensures dependencies don't use SDK features which are not available in the version specified by Deployment target
  96. # That can happen when one uses a recent SDK but specifies an older Deployment target
  97. set(DEP_WERRORS_SDK "-Werror=partial-availability -Werror=unguarded-availability -Werror=unguarded-availability-new")
  98. set(DEP_CMAKE_OPTS
  99. "-DCMAKE_POSITION_INDEPENDENT_CODE=ON"
  100. "-DCMAKE_OSX_SYSROOT=${CMAKE_OSX_SYSROOT}"
  101. "-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}"
  102. "-DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}"
  103. "-DCMAKE_CXX_FLAGS=${DEP_WERRORS_SDK}"
  104. "-DCMAKE_C_FLAGS=${DEP_WERRORS_SDK}"
  105. "-DCMAKE_FIND_FRAMEWORK=LAST"
  106. "-DCMAKE_FIND_APPBUNDLE=LAST"
  107. )
  108. endif ()
  109. list_projects(FOUND_PACKAGES ${CMAKE_CURRENT_LIST_DIR})
  110. dep_message(STATUS "Found external package definitions: ${FOUND_PACKAGES}")
  111. # Current list of all required dependencies for PS (top level)
  112. set(REQUIRED_PACKAGES
  113. Boost
  114. Catch2
  115. Cereal
  116. CURL
  117. EXPAT
  118. NLopt
  119. GLEW
  120. TBB
  121. Qhull
  122. wxWidgets
  123. OpenVDB
  124. CGAL
  125. OCCT
  126. ZLIB
  127. LibBGCode
  128. )
  129. set(${PROJECT_NAME}_PLATFORM_PACKAGES "" CACHE STRING "Select packages which are provided by the platform" )
  130. set(SYSTEM_PROVIDED_PACKAGES OpenGL)
  131. if (UNIX)
  132. # On UNIX systems (including Apple) ZLIB should be available
  133. list(APPEND SYSTEM_PROVIDED_PACKAGES ZLIB)
  134. if (APPLE)
  135. # Deal with CURL on Apple (See issue #5984 on GH):
  136. # Mac SDK should include CURL from at least version 10.12
  137. list(APPEND SYSTEM_PROVIDED_PACKAGES CURL)
  138. endif ()
  139. endif ()
  140. list(APPEND SYSTEM_PROVIDED_PACKAGES ${${PROJECT_NAME}_PLATFORM_PACKAGES})
  141. list(REMOVE_DUPLICATES SYSTEM_PROVIDED_PACKAGES)
  142. include(CMakeDependentOption)
  143. option(${PROJECT_NAME}_SELECT_ALL "Choose all external projects to be built." ON)
  144. find_package(Git REQUIRED)
  145. # The default command line for patching. Only works for newer
  146. set(PATCH_CMD ${GIT_EXECUTABLE} apply --verbose --ignore-space-change --whitespace=fix)
  147. # all required package targets that have existing definitions will be gathered here
  148. set(DEPS_TO_BUILD "")
  149. set(_build_list "")
  150. set(_build_list_toplevel "")
  151. set(_checked_list "")
  152. # function to check if a package ought to be provided by the platform can really be found
  153. function (check_system_package pkg checked_list)
  154. if (NOT ${pkg} IN_LIST ${checked_list})
  155. find_package(${pkg})
  156. if (NOT ${pkg}_FOUND)
  157. dep_message(WARNING "No ${pkg} found in system altough marked as system provided. This might cause trouble building the dependencies on this platform")
  158. endif ()
  159. list(APPEND ${checked_list} ${pkg})
  160. set (${checked_list} ${${checked_list}} PARENT_SCOPE)
  161. endif ()
  162. endfunction()
  163. # Go through all the found package definition folders and filter them according to the provided cache options
  164. set(SUPPORTED_PACKAGES "")
  165. foreach (pkg ${FOUND_PACKAGES})
  166. cmake_dependent_option(${PROJECT_NAME}_SELECT_${pkg} "Select package ${pkg} to be built." OFF "NOT ${PROJECT_NAME}_SELECT_ALL" OFF)
  167. if (NOT ${PROJECT_NAME}_PACKAGE_EXCLUDES MATCHES ${pkg} AND (${PROJECT_NAME}_SELECT_ALL OR ${PROJECT_NAME}_SELECT_${pkg}))
  168. include(+${pkg}/${pkg}.cmake)
  169. list(APPEND SUPPORTED_PACKAGES ${pkg})
  170. if (${pkg} IN_LIST SYSTEM_PROVIDED_PACKAGES)
  171. check_system_package(${pkg} _checked_list)
  172. elseif (${pkg} IN_LIST REQUIRED_PACKAGES)
  173. list(APPEND DEPS_TO_BUILD ${pkg})
  174. endif ()
  175. endif ()
  176. endforeach()
  177. # Establish dependency graph
  178. foreach (pkg ${SUPPORTED_PACKAGES})
  179. if (${pkg} IN_LIST DEPS_TO_BUILD)
  180. list(APPEND _build_list dep_${pkg})
  181. list(APPEND _build_list_toplevel dep_${pkg})
  182. endif ()
  183. foreach(deppkg ${DEP_${pkg}_DEPENDS})
  184. if (${deppkg} IN_LIST SYSTEM_PROVIDED_PACKAGES)
  185. check_system_package(${deppkg} _checked_list)
  186. elseif(TARGET dep_${deppkg})
  187. dep_message(STATUS "Mapping dep_${deppkg} => dep_${pkg}")
  188. add_dependencies(dep_${pkg} dep_${deppkg})
  189. if (${pkg} IN_LIST REQUIRED_PACKAGES)
  190. list(APPEND _build_list dep_${deppkg})
  191. endif ()
  192. endif ()
  193. endforeach()
  194. endforeach()
  195. list(REMOVE_DUPLICATES _build_list)
  196. dep_message(STATUS "Building dep targets (${CMAKE_BUILD_TYPE}): ${_build_list}")
  197. add_custom_target(deps ALL DEPENDS ${_build_list_toplevel})
  198. # Support legacy option DEP_DEBUG on MSVC to build debug libraries in the same cmake run as for CMAKE_BUILD_TYPE:
  199. if (DEP_DEBUG AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
  200. # MSVC has this nice feature to not be able to link release mode libs to Debug mode
  201. # projects
  202. # Exclude the libraries which have no problem to link to Debug builds in
  203. # Release mode (mostly C libraries)
  204. set(DEP_DEBUG_EXCLUDES GMP MPFR OpenSSL NanoSVG TIFF JPEG ZLIB heatshrink)
  205. if (UNIX)
  206. # Making a separate debug build on Unix of wx is a nightmare
  207. list(APPEND DEP_DEBUG_EXCLUDES wxWidgets)
  208. endif ()
  209. # Create the list of targets needed in debug mode
  210. set(_build_list_dbg "")
  211. set(_build_list_filt ${_build_list})
  212. list(JOIN DEP_DEBUG_EXCLUDES "|" _excl_regexp)
  213. list(FILTER _build_list_filt EXCLUDE REGEX "${_excl_regexp}")
  214. foreach (t ${_build_list_filt})
  215. list(APPEND _build_list_dbg ${t}_debug)
  216. endforeach()
  217. # Create a subdirectory for the Debug build within the current binary dir:
  218. file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/_d)
  219. execute_process(
  220. COMMAND ${CMAKE_COMMAND} ${CMAKE_CURRENT_SOURCE_DIR} -G${CMAKE_GENERATOR}
  221. -DCMAKE_BUILD_TYPE=Debug
  222. -DDEP_WX_GTK3=${DEP_WX_GTK3}
  223. -D${PROJECT_NAME}_DEP_DOWNLOAD_DIR=${${PROJECT_NAME}_DEP_DOWNLOAD_DIR}
  224. -D${PROJECT_NAME}_DEP_INSTALL_PREFIX=${${PROJECT_NAME}_DEP_INSTALL_PREFIX}
  225. -D${PROJECT_NAME}_PACKAGE_EXCLUDES="${_excl_regexp}"
  226. -D${PROJECT_NAME}_SELECT_ALL=${${PROJECT_NAME}_SELECT_ALL}
  227. -D${PROJECT_NAME}_DEP_BUILD_VERBOSE=${${PROJECT_NAME}_DEP_BUILD_VERBOSE}
  228. -DCMAKE_DEBUG_POSTFIX=d
  229. #TODO: forward per-package selector variables
  230. -DDEP_MESSAGES_WRITTEN=ON
  231. WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/_d
  232. OUTPUT_QUIET
  233. )
  234. dep_message(STATUS "Building dep targets (Debug): ${_build_list_dbg}")
  235. # Each lib will have a dep_<package>_debug target to build only the debug counterpart
  236. # Not part of ALL (problem with parallelization)
  237. foreach(pkgtgt ${_build_list_filt})
  238. add_custom_target(${pkgtgt}_debug
  239. COMMAND ${CMAKE_COMMAND} --build . --target ${pkgtgt}
  240. WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/_d
  241. USES_TERMINAL
  242. )
  243. endforeach()
  244. # Can be used to build all the debug libs
  245. string(JOIN " " _build_list_filt_targets "${_build_list_filt}")
  246. add_custom_target(deps_debug ALL
  247. COMMAND ${CMAKE_COMMAND} --build . --target ${_build_list_filt_targets}
  248. WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/_d
  249. USES_TERMINAL
  250. )
  251. # The Release must be built before, as there are libs in this debug session which need
  252. # the release versions of the excluded libs
  253. add_dependencies(deps_debug deps)
  254. endif ()
  255. set(DEP_MESSAGES_WRITTEN ON CACHE BOOL "")
  256. install(CODE "message(STATUS \"Built packages succesfully.\")")