|
|
/* |
|
|
This file is part of Magnum. |
|
|
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
|
|
2020, 2021, 2022, 2023, 2024 |
|
|
Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
|
|
copy of this software and associated documentation files (the "Software"), |
|
|
to deal in the Software without restriction, including without limitation |
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
|
and/or sell copies of the Software, and to permit persons to whom the |
|
|
Software is furnished to do so, subject to the following conditions: |
|
|
|
|
|
The above copyright notice and this permission notice shall be included |
|
|
in all copies or substantial portions of the Software. |
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
|
DEALINGS IN THE SOFTWARE. |
|
|
*/ |
|
|
|
|
|
namespace Magnum { |
|
|
|
|
|
/** @page platforms-macos macOS |
|
|
@brief Tips and tricks for macOS |
|
|
|
|
|
@tableofcontents |
|
|
@m_footernavigation |
|
|
|
|
|
@m_keyword{Apple macOS,,} |
|
|
|
|
|
@todoc code coverage |
|
|
|
|
|
See also @ref platforms-ios. |
|
|
|
|
|
@section platforms-macos-bundle Bundle creation |
|
|
|
|
|
While graphical applications *can* run "as is", directly from the compiled |
|
|
executable, it's not possible to set various crucial properties of the app |
|
|
such as @ref platforms-macos-hidpi "HiDPI" support --- for that you need to |
|
|
create a bundle, specifying its options through a `*.plist` file. If you use |
|
|
CMake, it provides [a builtin file](https://cmake.org/cmake/help/latest/prop_tgt/MACOSX_BUNDLE_INFO_PLIST.html) |
|
|
with a few options and you can use it like this: |
|
|
|
|
|
@code{.cmake} |
|
|
add_executable(my-application main.cpp) |
|
|
# ... |
|
|
if(CORRADE_TARGET_APPLE) |
|
|
set_target_properties(my-application PROPERTIES |
|
|
MACOSX_BUNDLE ON |
|
|
MACOSX_BUNDLE_BUNDLE_NAME "My Application" |
|
|
MACOSX_BUNDLE_BUNDLE_IDENTIFIER "cz.mosra.magnum.my-application") |
|
|
endif() |
|
|
@endcode |
|
|
|
|
|
The builtin file doesn't include all possible properties, however it's possible |
|
|
to supply your own. A minimal file can look like this: |
|
|
|
|
|
@code{.xml-jinja} |
|
|
<?xml version="1.0" encoding="UTF-8"?> |
|
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|
|
<plist version="1.0"> |
|
|
<dict> |
|
|
<key>CFBundleDevelopmentRegion</key> |
|
|
<string>en-US</string> |
|
|
<key>CFBundleExecutable</key> |
|
|
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string> |
|
|
<key>CFBundleIdentifier</key> |
|
|
<string>{{ package }}</string> |
|
|
<key>CFBundleInfoDictionaryVersion</key> |
|
|
<string>6.0</string> |
|
|
<key>CFBundleName</key> |
|
|
<string>{{ app_name }}</string> |
|
|
<key>CFBundlePackageType</key> |
|
|
<string>APPL</string> |
|
|
</dict> |
|
|
</plist> |
|
|
@endcode |
|
|
|
|
|
Replace @cb{.jinja} {{ package }} @ce with Java-like package name for your app |
|
|
(in this case it could be e.g. @cpp "cz.mosra.magnum.my_application" @ce, for |
|
|
example), @cb{.jinja} {{ app_name }} @ce with human-readable app name that's |
|
|
displayed in the system (so e.g. @cpp "My Application" @ce). If you name it |
|
|
`MacOSXBundleInfo.plist.in`, it can be supplied to the bundle like below. The |
|
|
@cb{.cmake} ${MACOSX_BUNDLE_EXECUTABLE_NAME} @ce will get automatically |
|
|
replaced with the target executable name. |
|
|
|
|
|
@code{.cmake} |
|
|
if(CORRADE_TARGET_APPLE) |
|
|
set_target_properties(my-application PROPERTIES |
|
|
MACOSX_BUNDLE ON |
|
|
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/MacOSXBundleInfo.plist.in) |
|
|
endif() |
|
|
@endcode |
|
|
|
|
|
See [the official Apple Property List file documentation](https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html) |
|
|
for information about all options. |
|
|
|
|
|
If you don't use CMake, these options can be set directly through Xcode UI, for |
|
|
example. |
|
|
|
|
|
@subsection platforms-macos-bundle-dylibs Bundling dylibs |
|
|
|
|
|
If your application relies on dylibs (such as `libGLESv2.dylib` / |
|
|
`libEGL.dylib` for @ref platforms-gl-es-angle "ANGLE"), there's a few extra |
|
|
steps compared to static libraries to get them working. First, these have to be |
|
|
put into the `Frameworks/` directory inside the bundle --- for example like |
|
|
below if you have them referenced with a CMake project. Additionally, the |
|
|
files may need to get signed when copied: |
|
|
|
|
|
@code{.cmake} |
|
|
set_source_files_properties(libGLESv2.dylib libEGL.dylib PROPERTIES |
|
|
MACOSX_PACKAGE_LOCATION Frameworks |
|
|
XCODE_FILE_ATTRIBUTES CodeSignOnCopy) |
|
|
@endcode |
|
|
|
|
|
Then, the `*.dylib` files need to have their install name changed to contan a |
|
|
RPATH entry, so the executable linking to them will know it has to look for |
|
|
them in the RPATH. For 3rd party `*.dylib` files it can be done with the |
|
|
following command, dynamic libraries built directly by CMake |
|
|
[should have this already set](https://cmake.org/cmake/help/latest/prop_tgt/MACOSX_RPATH.html). |
|
|
|
|
|
@code{.sh} |
|
|
install_name_tool -id "@rpath/libGLESv2.dylib" libGLESv2.dylib |
|
|
install_name_tool -id "@rpath/libEGL.dylib" libEGL.dylib |
|
|
@endcode |
|
|
|
|
|
Finally, the application executable needs to have the RPATH pointed to the |
|
|
framework location: |
|
|
|
|
|
@code{.sh} |
|
|
set_target_properties(my-application PROPERTIES |
|
|
INSTALL_RPATH "@executable_path/../Frameworks") |
|
|
@endcode |
|
|
|
|
|
@section platforms-macos-hidpi HiDPI (Retina) support |
|
|
|
|
|
macOS and iOS is the only platform where HiDPI support of an app can't be |
|
|
advertised programmatically. According to various sources, this capability is |
|
|
enabled by default on macOS 10.15+ and iOS 13+, for older versions you need to |
|
|
supply a custom `*.plist` file with `NSHighResolutionCapable` enabled: |
|
|
|
|
|
@code{.xml} |
|
|
<?xml version="1.0" encoding="UTF-8"?> |
|
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|
|
<plist version="1.0"> |
|
|
<dict> |
|
|
... |
|
|
<key>NSHighResolutionCapable</key> |
|
|
<true/> |
|
|
</dict> |
|
|
</plist> |
|
|
@endcode |
|
|
|
|
|
If you are using CMake, you can use the @ref platforms-macos-bundle "method described above" |
|
|
to create a bundle with given file. Also note that this property is already |
|
|
included in CMake's builtin `Info.plist` on [version 3.9 and newer](https://gitlab.kitware.com/cmake/cmake/merge_requests/682). |
|
|
|
|
|
@section platforms-macos-clang-version-mapping Clang version mapping |
|
|
|
|
|
Apple Clang has a different versioning scheme from upstream Clang, making it |
|
|
hard to know which Clang version corresponds to which Apple Clang version. |
|
|
Wikipedia has a [handy version mapping table](https://en.wikipedia.org/wiki/Xcode#Toolchain_versions). |
|
|
|
|
|
CMake exposes Apple Clang as `AppleClang`, so a complete check for e.g. |
|
|
upstream version 5 needs to look like this: |
|
|
|
|
|
@code{.cmake} |
|
|
if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT |
|
|
CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0") OR |
|
|
(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT |
|
|
CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.3")) |
|
|
# Code requiring Clang 5 and newer |
|
|
endif() |
|
|
@endcode |
|
|
|
|
|
@note CMake supports `VERSION_GREATER_EQUAL` in the @cb{.cmake} if() @ce |
|
|
statement only [since version 3.7](https://cmake.org/cmake/help/latest/release/3.7.html#commands), |
|
|
use a negated `VERSION_LESS` like above in older versions. |
|
|
|
|
|
@see @ref platforms-windows-msvc-version-mapping |
|
|
|
|
|
@section platforms-macos-opengl-best-practices Best practices |
|
|
|
|
|
Official Apple documentation: |
|
|
|
|
|
- [Best Practices for Working with Vertex Data](https://developer.apple.com/library/mac/#documentation/graphicsimaging/Conceptual/OpenGL-MacProgGuide/opengl_vertexdata/opengl_vertexdata.html) |
|
|
- [Best Practices for Working with Texture Data](https://developer.apple.com/library/mac/#documentation/graphicsimaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/opengl_texturedata.html) |
|
|
|
|
|
@section platforms-macos-travis Setting up macOS build on Travis CI |
|
|
|
|
|
A lot of Travis features is shared between Linux and macOS, see |
|
|
@ref platforms-linux-travis for more information. |
|
|
|
|
|
In general, a macOS build is done by adding the following to your `.travis.yml` |
|
|
matrix build. See [the official documentation](https://docs.travis-ci.com/user/reference/osx/) |
|
|
for more information. |
|
|
|
|
|
@code{.yml} |
|
|
matrix: |
|
|
include: |
|
|
- language: cpp |
|
|
os: osx |
|
|
compiler: clang |
|
|
@endcode |
|
|
|
|
|
Most of the build setup can be shared with Linux, as both systems have roughly |
|
|
the same set of packages. For installing dependencies there's no builtin way, |
|
|
but you can use Homebrew. Be aware that calling for example |
|
|
@cb{.sh} brew install ninja @ce by default causes Homebrew to update itself |
|
|
first. That currently (March 2018) takes almost two minutes. It's possible to |
|
|
skip the update by setting an environment variable as shown below, however this |
|
|
might fail in case you need a very recent version of a package. |
|
|
|
|
|
@code{.sh} |
|
|
HOMEBREW_NO_AUTO_UPDATE=1 brew install ninja |
|
|
@endcode |
|
|
|
|
|
@section platforms-macos-troubleshooting Troubleshooting |
|
|
|
|
|
@subsection platforms-macos-troubleshooting-build-mysteriously-fails Build mysteriously fails due to some <cmath> errors |
|
|
|
|
|
Happening usually after a system or Xcode upgrade, builds can start failing |
|
|
with errors like below. The exact reasons are unclear, can vary and happen only |
|
|
in certain cases (for example a manual build works but Homebrew package install |
|
|
doesn't). |
|
|
|
|
|
@m_class{m-console-wrap} |
|
|
|
|
|
@code{.ansi} |
|
|
In file included from ../src/MagnumPlugins/PngImageConverter/PngImageConverter.cpp:42: |
|
|
In file included from /usr/local/include/Magnum/ImageView.h:35: |
|
|
In file included from /usr/local/include/Magnum/PixelStorage.h:36: |
|
|
In file included from /usr/local/include/Magnum/Math/Vector3.h:32: |
|
|
In file included from /usr/local/include/Magnum/Math/Vector2.h:32: |
|
|
In file included from /usr/local/include/Magnum/Math/Vector.h:37: |
|
|
In file included from /usr/local/include/Corrade/Utility/StlMath.h:75: |
|
|
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cmath:317:9: error: no member named 'signbit' in the global namespace |
|
|
using ::signbit; |
|
|
~~^ |
|
|
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cmath:318:9: error: no member named 'fpclassify' in the global namespace |
|
|
using ::fpclassify; |
|
|
~~^ |
|
|
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/cmath:319:9: error: no member named 'isfinite' in the global namespace; did you mean 'finite'? |
|
|
using ::isfinite; |
|
|
~~^ |
|
|
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk/usr/include/math.h:752:12: note: 'finite' declared here |
|
|
extern int finite(double) |
|
|
^ |
|
|
@endcode |
|
|
|
|
|
In the above case it's because @ref Trade::PngImageConverter "PngImageConverter" |
|
|
(or @ref Trade::PngImporter "PngImporter") uses libPNG, which depends on zlib. |
|
|
Zlib, along with curl and few others are the only libraries shipped directly |
|
|
with macOS, and that's the core of the problem. Here zlib got errorneously |
|
|
found in a different SDK than the remaining dependencies, causing two mutually |
|
|
incompatible include directories from a 11.0 and 10.15 SDK used together, as |
|
|
can be seen in the clang invocation (which gets displayed by `ninja` on failure |
|
|
or can be retreived from Homebrew logs): |
|
|
|
|
|
@m_class{m-console-wrap} |
|
|
|
|
|
@code{.ansi} |
|
|
clang++ … -I/Library/Developer/CommandLineTools/SDKs/[1;34mMacOSX11.0.sdk[0m/usr/include[0m … -o CMakeFiles/PngImageConverter.dir/PngImageConverter.cpp.o -c ../src/MagnumPlugins/PngImageConverter/PngImageConverter.cpp -isysroot/Library/Developer/CommandLineTools/SDKs/[1;34mMacOSX10.15.sdk[0m --sysroot=/Library/Developer/CommandLineTools/SDKs/[1;34mMacOSX10.15.sdk[0m -isystem/usr/local/include |
|
|
@endcode |
|
|
|
|
|
A magic incantation that should remove the curse, often suggested by Homebrew |
|
|
itself, is the following: |
|
|
|
|
|
@code{.sh} |
|
|
sudo rm -rf /Library/Developer/CommandLineTools |
|
|
sudo xcode-select --install |
|
|
@endcode |
|
|
|
|
|
@section platforms-macos-vulkan Vulkan on macOS |
|
|
|
|
|
Vulkan on macOS is implemented on top of Metal, and there are two possible |
|
|
ways: |
|
|
|
|
|
- Using [MoltenVK](https://github.com/KhronosGroup/MoltenVK) directly. The |
|
|
library can supplement a Vulkan loader as well, which means you don't need |
|
|
two libraries, however this way you lose the possibility to have multiple |
|
|
devices (for example a SwiftShader software rendering). MoltenVK is |
|
|
directly available in Homebrew as `molten-vk`. |
|
|
- Using [Vulkan Loader](https://github.com/KhronosGroup/Vulkan-Loader) |
|
|
together with MoltenVK and possibly other device implementations. That way |
|
|
you'll get the benefits of a standard loader and device selection. The |
|
|
loader isn't available in Homebrew so you need to either install the whole |
|
|
several-hunred-megabyte SDK or [build it from source](https://github.com/KhronosGroup/Vulkan-Loader/blob/master/BUILD.md#building-on-macos). |
|
|
|
|
|
Magnum's own [FindVulkan.cmake](https://github.com/mosra/magnum/blob/master/modules/FindVulkan.cmake) |
|
|
will look for the Vulkan Loader first and if not found, falls back to searching |
|
|
for MoltenVK. |
|
|
|
|
|
@section platforms-macos-gl OpenGL on macOS |
|
|
|
|
|
With Apple decision to focus on Metal, macOS OpenGL support is stuck on version |
|
|
4.1 (i.e., two versions before compute shaders are available). Moreover, OpenGL |
|
|
is deprecated since macOS 10.14. If you don't want to rely on the deprecated |
|
|
OpenGL driver, you have an option to use |
|
|
@ref platforms-macos-vulkan "Vulkan as shown above", go with ANGLE to translate |
|
|
OpenGL to Metal (details below), or go with Mesa Zink to translate OpenGL to |
|
|
Vulkan. |
|
|
|
|
|
With the deprecated macOS drivers, these are the known issues: |
|
|
|
|
|
- @ref GL::AbstractShaderProgram::validate() expects that the shader has a |
|
|
properly configured framebuffer bound along with proper @ref GL::Renderer |
|
|
setup. That is often hard to achieve, so the function cannot be portably |
|
|
used for shader validity testing. |
|
|
- `GL_TIMESTAMP` used by @ref GL::TimeQuery::timestamp() is not implemented |
|
|
on macOS and gives zero results. |
|
|
|
|
|
@subsection platforms-macos-gl-angle Using ANGLE to translate OpenGL to Metal |
|
|
|
|
|
@todoc cmake options to switch to GLES/EGL, mention getting the binaries from browser installs |
|
|
@todoc steps for building angle from scratch? |
|
|
@todoc reference this from the iOS guide |
|
|
|
|
|
See also @ref platforms-gl-es-angle for further information. |
|
|
|
|
|
*/ |
|
|
|
|
|
}
|
|
|
|