1# ***** BEGIN GPL LICENSE BLOCK *****
2#
3# This program is free software; you can redistribute it and/or
4# modify it under the terms of the GNU General Public License
5# as published by the Free Software Foundation; either version 2
6# of the License, or (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software Foundation,
15# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16#
17# The Original Code is Copyright (C) 2016, Blender Foundation
18# All rights reserved.
19# ***** END GPL LICENSE BLOCK *****
20
21# Xcode and system configuration for Apple.
22
23if(NOT CMAKE_OSX_ARCHITECTURES)
24  execute_process(COMMAND uname -m OUTPUT_VARIABLE ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE)
25  message(STATUS "Detected native architecture ${ARCHITECTURE}.")
26  set(CMAKE_OSX_ARCHITECTURES ${ARCHITECTURE} CACHE STRING
27    "Choose the architecture you want to build Blender for: arm64 or x86_64"
28    FORCE)
29endif()
30
31if(NOT DEFINED OSX_SYSTEM)
32  execute_process(
33      COMMAND xcodebuild -version -sdk macosx SDKVersion
34      OUTPUT_VARIABLE OSX_SYSTEM
35      OUTPUT_STRIP_TRAILING_WHITESPACE)
36endif()
37
38# workaround for incorrect cmake xcode lookup for developer previews - XCODE_VERSION does not
39# take xcode-select path into account but would always look  into /Applications/Xcode.app
40# while dev versions are named Xcode<version>-DP<preview_number>
41execute_process(
42    COMMAND xcode-select --print-path
43    OUTPUT_VARIABLE XCODE_CHECK OUTPUT_STRIP_TRAILING_WHITESPACE)
44string(REPLACE "/Contents/Developer" "" XCODE_BUNDLE ${XCODE_CHECK}) # truncate to bundlepath in any case
45
46if(NOT ${CMAKE_GENERATOR} MATCHES "Xcode")
47  # Unix makefile generator does not fill XCODE_VERSION var, so we get it with a command.
48  # Note that `xcodebuild -version` gives output in two lines: first line will include
49  # Xcode version, second one will include build number. We are only interested in the
50  # former one. Here is an example of the output:
51  #   Xcode 11.4
52  #   Build version 11E146
53  # The expected XCODE_VERSION in this case is 11.4.
54
55  execute_process(COMMAND xcodebuild -version OUTPUT_VARIABLE XCODE_VERS_BUILD_NR)
56
57  # Convert output to a single line by replacling newlines with spaces.
58  # This is needed because regex replace can not operate through the newline character
59  # and applies substitutions for each individual lines.
60  string(REPLACE "\n" " " XCODE_VERS_BUILD_NR_SINGLE_LINE "${XCODE_VERS_BUILD_NR}")
61
62  string(REGEX REPLACE "(.*)Xcode ([0-9\\.]+).*" "\\2" XCODE_VERSION "${XCODE_VERS_BUILD_NR_SINGLE_LINE}")
63
64  unset(XCODE_VERS_BUILD_NR)
65  unset(XCODE_VERS_BUILD_NR_SINGLE_LINE)
66endif()
67
68message(STATUS "Detected OS X ${OSX_SYSTEM} and Xcode ${XCODE_VERSION} at ${XCODE_BUNDLE}")
69
70# Require a relatively recent Xcode version.
71if(${XCODE_VERSION} VERSION_LESS 10.0)
72  message(FATAL_ERROR "Only Xcode version 10.0 and newer is supported")
73endif()
74
75# note: xcode-select path could be ambiguous,
76# cause /Applications/Xcode.app/Contents/Developer or /Applications/Xcode.app would be allowed
77# so i use a selfcomposed bundlepath here
78set(OSX_SYSROOT_PREFIX ${XCODE_BUNDLE}/Contents/Developer/Platforms/MacOSX.platform)
79message(STATUS "OSX_SYSROOT_PREFIX: " ${OSX_SYSROOT_PREFIX})
80
81# Collect list of OSX system versions which will be used to detect path to corresponding SDK.
82# Start with macOS SDK version reported by xcodebuild and include possible extra ones.
83#
84# The reason for need of extra ones is because it's possible that xcodebuild will report
85# SDK version in the full manner (aka major.minor.patch), but the actual path will only
86# include major.minor.
87#
88# This happens, for example, on macOS Catalina 10.15.4 and Xcode 11.4: xcodebuild on this
89# system outputs "10.15.4", but the actual SDK path is MacOSX10.15.sdk.
90#
91# This should be safe from picking wrong SDK version because (a) xcodebuild reports full semantic
92# SDK version, so such SDK does exist on the system. And if it doesn't exist with full version
93# in the path, what SDK is in the major.minor folder then.
94set(OSX_SDK_TEST_VERSIONS ${OSX_SYSTEM})
95if(OSX_SYSTEM MATCHES "([0-9]+)\\.([0-9]+)\\.([0-9]+)")
96  string(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\1.\\2" OSX_SYSTEM_NO_PATCH "${OSX_SYSTEM}")
97  list(APPEND OSX_SDK_TEST_VERSIONS ${OSX_SYSTEM_NO_PATCH})
98  unset(OSX_SYSTEM_NO_PATCH)
99endif()
100
101# Loop through all possible versions and pick the first one which resolves to a valid SDK path.
102set(OSX_SDK_PATH)
103set(OSX_SDK_FOUND FALSE)
104set(OSX_SDK_PREFIX ${OSX_SYSROOT_PREFIX}/Developer/SDKs)
105set(OSX_SDKROOT)
106foreach(OSX_SDK_VERSION ${OSX_SDK_TEST_VERSIONS})
107  set(CURRENT_OSX_SDK_PATH "${OSX_SDK_PREFIX}/MacOSX${OSX_SDK_VERSION}.sdk")
108  if(EXISTS ${CURRENT_OSX_SDK_PATH})
109    set(OSX_SDK_PATH "${CURRENT_OSX_SDK_PATH}")
110    set(OSX_SDKROOT macosx${OSX_SDK_VERSION})
111    set(OSX_SDK_FOUND TRUE)
112    break()
113  endif()
114endforeach()
115unset(OSX_SDK_PREFIX)
116unset(OSX_SDK_TEST_VERSIONS)
117
118if(NOT OSX_SDK_FOUND)
119  message(FATAL_ERROR "Unable to find SDK for macOS version ${OSX_SYSTEM}")
120endif()
121
122message(STATUS "Detected OSX_SYSROOT: ${OSX_SDK_PATH}")
123
124set(CMAKE_OSX_SYSROOT ${OSX_SDK_PATH} CACHE PATH "" FORCE)
125unset(OSX_SDK_PATH)
126unset(OSX_SDK_FOUND)
127
128if(${CMAKE_GENERATOR} MATCHES "Xcode")
129  # to silence sdk not found warning, just overrides CMAKE_OSX_SYSROOT
130  set(CMAKE_XCODE_ATTRIBUTE_SDKROOT ${OSX_SDKROOT})
131endif()
132unset(OSX_SDKROOT)
133
134
135# 10.13 is our min. target, if you use higher sdk, weak linking happens
136if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
137  set(OSX_MIN_DEPLOYMENT_TARGET 11.00)
138else()
139  set(OSX_MIN_DEPLOYMENT_TARGET 10.13)
140endif()
141
142if(CMAKE_OSX_DEPLOYMENT_TARGET)
143  if(${CMAKE_OSX_DEPLOYMENT_TARGET} VERSION_LESS ${OSX_MIN_DEPLOYMENT_TARGET})
144    message(STATUS "Setting deployment target to ${OSX_MIN_DEPLOYMENT_TARGET}, lower versions are not supported")
145    set(CMAKE_OSX_DEPLOYMENT_TARGET "${OSX_MIN_DEPLOYMENT_TARGET}" CACHE STRING "" FORCE)
146  endif()
147else()
148  set(CMAKE_OSX_DEPLOYMENT_TARGET "${OSX_MIN_DEPLOYMENT_TARGET}" CACHE STRING "" FORCE)
149endif()
150
151if(NOT ${CMAKE_GENERATOR} MATCHES "Xcode")
152  # Force CMAKE_OSX_DEPLOYMENT_TARGET for makefiles, will not work else (CMake bug?)
153  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
154  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
155  add_definitions("-DMACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
156endif()
157