CMakeLists.txt 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  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. set(${PROJECT_NAME}_PLATFORM_PACKAGES "" CACHE STRING "Select packages which are provided by the platform" )
  112. set(SYSTEM_PROVIDED_PACKAGES OpenGL)
  113. if (UNIX)
  114. # On UNIX systems (including Apple) ZLIB should be available
  115. list(APPEND SYSTEM_PROVIDED_PACKAGES ZLIB)
  116. if (APPLE)
  117. # Deal with CURL on Apple (See issue #5984 on GH):
  118. # Mac SDK should include CURL from at least version 10.12
  119. list(APPEND SYSTEM_PROVIDED_PACKAGES CURL)
  120. endif ()
  121. endif ()
  122. list(APPEND SYSTEM_PROVIDED_PACKAGES ${${PROJECT_NAME}_PLATFORM_PACKAGES})
  123. list(REMOVE_DUPLICATES SYSTEM_PROVIDED_PACKAGES)
  124. include(CMakeDependentOption)
  125. option(${PROJECT_NAME}_SELECT_ALL "Choose all external projects to be built." ON)
  126. find_package(Git REQUIRED)
  127. # The default command line for patching. Only works for newer
  128. set(PATCH_CMD ${GIT_EXECUTABLE} apply --verbose --ignore-space-change --whitespace=fix)
  129. # all required package targets that have existing definitions will be gathered here
  130. set(DEPS_TO_BUILD "")
  131. set(_build_list "")
  132. set(_build_list_toplevel "")
  133. set(_checked_list "")
  134. # function to check if a package ought to be provided by the platform can really be found
  135. function (check_system_package pkg checked_list)
  136. if (NOT ${pkg} IN_LIST ${checked_list})
  137. find_package(${pkg})
  138. if (NOT ${pkg}_FOUND)
  139. dep_message(WARNING "No ${pkg} found in system altough marked as system provided. This might cause trouble building the dependencies on this platform")
  140. endif ()
  141. list(APPEND ${checked_list} ${pkg})
  142. set (${checked_list} ${${checked_list}} PARENT_SCOPE)
  143. endif ()
  144. endfunction()
  145. # Go through all the found package definition folders and filter them according to the provided cache options
  146. set(SUPPORTED_PACKAGES "")
  147. foreach (pkg ${FOUND_PACKAGES})
  148. cmake_dependent_option(${PROJECT_NAME}_SELECT_${pkg} "Select package ${pkg} to be built." OFF "NOT ${PROJECT_NAME}_SELECT_ALL" OFF)
  149. if (NOT ${PROJECT_NAME}_PACKAGE_EXCLUDES MATCHES ${pkg} AND (${PROJECT_NAME}_SELECT_ALL OR ${PROJECT_NAME}_SELECT_${pkg}))
  150. include(+${pkg}/${pkg}.cmake)
  151. list(APPEND SUPPORTED_PACKAGES ${pkg})
  152. if (${pkg} IN_LIST SYSTEM_PROVIDED_PACKAGES)
  153. check_system_package(${pkg} _checked_list)
  154. elseif (TARGET dep_${pkg})
  155. get_target_property(_is_excluded_from_all dep_${pkg} EXCLUDE_FROM_ALL)
  156. if (NOT _is_excluded_from_all)
  157. list(APPEND DEPS_TO_BUILD ${pkg})
  158. endif ()
  159. endif ()
  160. endif ()
  161. endforeach()
  162. # This ugly append ensures that WebView2 was appended no matter what EXCLUDE_FROM_ALL is.
  163. # (Webview2 is not added by add_cmake_project)
  164. if (MSVC)
  165. list(APPEND DEPS_TO_BUILD WebView2)
  166. endif()
  167. # Establish dependency graph
  168. foreach (pkg ${SUPPORTED_PACKAGES})
  169. if (${pkg} IN_LIST DEPS_TO_BUILD)
  170. list(APPEND _build_list dep_${pkg})
  171. list(APPEND _build_list_toplevel dep_${pkg})
  172. endif ()
  173. foreach(deppkg ${DEP_${pkg}_DEPENDS})
  174. if (${deppkg} IN_LIST SYSTEM_PROVIDED_PACKAGES)
  175. check_system_package(${deppkg} _checked_list)
  176. elseif(TARGET dep_${deppkg})
  177. dep_message(STATUS "Mapping dep_${deppkg} => dep_${pkg}")
  178. add_dependencies(dep_${pkg} dep_${deppkg})
  179. list(APPEND _build_list dep_${deppkg})
  180. endif ()
  181. endforeach()
  182. endforeach()
  183. list(REMOVE_DUPLICATES _build_list)
  184. dep_message(STATUS "Building dep targets (${CMAKE_BUILD_TYPE}): ${_build_list}")
  185. add_custom_target(deps ALL DEPENDS ${_build_list_toplevel})
  186. # Support legacy option DEP_DEBUG on MSVC to build debug libraries in the same cmake run as for CMAKE_BUILD_TYPE:
  187. if (DEP_DEBUG AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
  188. # MSVC has this nice feature to not be able to link release mode libs to Debug mode
  189. # projects
  190. # Exclude the libraries which have no problem to link to Debug builds in
  191. # Release mode (mostly C libraries)
  192. set(DEP_DEBUG_EXCLUDES GMP MPFR OpenSSL NanoSVG TIFF JPEG ZLIB heatshrink)
  193. if (UNIX)
  194. # Making a separate debug build on Unix of wx is a nightmare
  195. list(APPEND DEP_DEBUG_EXCLUDES wxWidgets)
  196. endif ()
  197. # Create the list of targets needed in debug mode
  198. set(_build_list_dbg "")
  199. set(_build_list_filt ${_build_list})
  200. list(JOIN DEP_DEBUG_EXCLUDES "|" _excl_regexp)
  201. list(FILTER _build_list_filt EXCLUDE REGEX "${_excl_regexp}")
  202. foreach (t ${_build_list_filt})
  203. list(APPEND _build_list_dbg ${t}_debug)
  204. endforeach()
  205. # Create a subdirectory for the Debug build within the current binary dir:
  206. file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/_d)
  207. execute_process(
  208. COMMAND ${CMAKE_COMMAND} ${CMAKE_CURRENT_SOURCE_DIR} -G${CMAKE_GENERATOR}
  209. -DCMAKE_BUILD_TYPE=Debug
  210. -DDEP_WX_GTK3=${DEP_WX_GTK3}
  211. -D${PROJECT_NAME}_DEP_DOWNLOAD_DIR=${${PROJECT_NAME}_DEP_DOWNLOAD_DIR}
  212. -D${PROJECT_NAME}_DEP_INSTALL_PREFIX=${${PROJECT_NAME}_DEP_INSTALL_PREFIX}
  213. -D${PROJECT_NAME}_PACKAGE_EXCLUDES="${_excl_regexp}"
  214. -D${PROJECT_NAME}_SELECT_ALL=${${PROJECT_NAME}_SELECT_ALL}
  215. -D${PROJECT_NAME}_DEP_BUILD_VERBOSE=${${PROJECT_NAME}_DEP_BUILD_VERBOSE}
  216. -DCMAKE_DEBUG_POSTFIX=d
  217. #TODO: forward per-package selector variables
  218. -DDEP_MESSAGES_WRITTEN=ON
  219. WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/_d
  220. OUTPUT_QUIET
  221. )
  222. dep_message(STATUS "Building dep targets (Debug): ${_build_list_dbg}")
  223. # Each lib will have a dep_<package>_debug target to build only the debug counterpart
  224. # Not part of ALL (problem with parallelization)
  225. foreach(pkgtgt ${_build_list_filt})
  226. add_custom_target(${pkgtgt}_debug
  227. COMMAND ${CMAKE_COMMAND} --build . --target ${pkgtgt}
  228. WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/_d
  229. USES_TERMINAL
  230. )
  231. endforeach()
  232. # Can be used to build all the debug libs
  233. string(JOIN " " _build_list_filt_targets "${_build_list_filt}")
  234. add_custom_target(deps_debug ALL
  235. COMMAND ${CMAKE_COMMAND} --build . --target ${_build_list_filt_targets}
  236. WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/_d
  237. USES_TERMINAL
  238. )
  239. # The Release must be built before, as there are libs in this debug session which need
  240. # the release versions of the excluded libs
  241. add_dependencies(deps_debug deps)
  242. endif ()
  243. set(DEP_MESSAGES_WRITTEN ON CACHE BOOL "")
  244. install(CODE "message(STATUS \"Built packages succesfully.\")")