diff options
Diffstat (limited to 'docs/markdown/Creating-OSX-packages.md')
-rw-r--r-- | docs/markdown/Creating-OSX-packages.md | 102 |
1 files changed, 81 insertions, 21 deletions
diff --git a/docs/markdown/Creating-OSX-packages.md b/docs/markdown/Creating-OSX-packages.md index 4a4612e..14b2af8 100644 --- a/docs/markdown/Creating-OSX-packages.md +++ b/docs/markdown/Creating-OSX-packages.md @@ -4,15 +4,27 @@ short-description: Tools to create OS X packages # Creating OSX packages -Meson does not have native support for building OSX packages but it does provide all the tools you need to create one yourself. The reason for this is that it is a very hard task to write a system that provides for all the different ways to do that but it is very easy to write simple scripts for each application. +Meson does not have native support for building OSX packages but it +does provide all the tools you need to create one yourself. The reason +for this is that it is a very hard task to write a system that +provides for all the different ways to do that but it is very easy to +write simple scripts for each application. -Sample code for this can be found in [the Meson manual test suite](https://github.com/jpakkane/meson/tree/master/manual%20tests/4%20standalone%20binaries). +Sample code for this can be found in [the Meson manual test +suite](https://github.com/jpakkane/meson/tree/master/manual%20tests/4%20standalone%20binaries). ## Creating an app bundle -OSX app bundles are actually extremely simple. They are just a directory of files in a certain format. All the details you need to know are on [this page](https://stackoverflow.com/questions/1596945/building-osx-app-bundle) and it is highly recommended that you read it first. +OSX app bundles are actually extremely simple. They are just a +directory of files in a certain format. All the details you need to +know are on [this +page](https://stackoverflow.com/questions/1596945/building-osx-app-bundle) +and it is highly recommended that you read it first. -Let's assume that we are creating our app bundle into `/tmp/myapp.app`. Suppose we have one executable, so we need to install that into `Contents/MacOS`. If we define the executable like this: +Let's assume that we are creating our app bundle into +`/tmp/myapp.app`. Suppose we have one executable, so we need to +install that into `Contents/MacOS`. If we define the executable like +this: ```meson executable('myapp', 'foo1.c', ..., install : true) @@ -27,18 +39,29 @@ $ meson --prefix=/tmp/myapp.app \ <other flags you might need> ``` -Now when we do `ninja install` the bundle is properly staged. If you have any resource files or data, you need to install them into `Contents/Resources` either by custom install commands or specifying more install paths to the Meson command. +Now when we do `ninja install` the bundle is properly staged. If you +have any resource files or data, you need to install them into +`Contents/Resources` either by custom install commands or specifying +more install paths to the Meson command. -Next we need to install an `Info.plist` file and an icon. For those we need the following two Meson definitions. +Next we need to install an `Info.plist` file and an icon. For those we +need the following two Meson definitions. ```meson install_data('myapp.icns', install_dir : 'Contents/Resources') install_data('Info.plist', install_dir : 'Contents') ``` -The format of `Info.plist` can be found in the link or the sample project linked above. Be careful, the sample code on the linked page is malformed, it is missing a less than character (<) before `!DOCTYPE`. The simplest way to get an icon in the `icns` format is to save your image as a tiff an then use the `tiff2icns` helper application that comes with XCode. +The format of `Info.plist` can be found in the link or the sample +project linked above. Be careful, the sample code on the linked page +is malformed, it is missing a less than character (<) before +`!DOCTYPE`. The simplest way to get an icon in the `icns` format is to +save your image as a tiff an then use the `tiff2icns` helper +application that comes with XCode. -Some applications assume that the working directory of the app process is the same where the binary executable is. If this is the case for you, then you need to create a wrapper script that looks like this: +Some applications assume that the working directory of the app process +is the same where the binary executable is. If this is the case for +you, then you need to create a wrapper script that looks like this: ```bash #!/bin/bash @@ -53,17 +76,25 @@ install it with this: install_data('myapp.sh', install_dir : 'Contents/MacOS') ``` -and make sure that you specify `myapp.sh` as the executable to run in your `Info.plist`. +and make sure that you specify `myapp.sh` as the executable to run in +your `Info.plist`. -If you are not using any external libraries, this is all you need to do. You now have a full app bundle in `/tmp/myapp.app` that you can use. Most applications use third party frameworks and libraries, though, so you need to add them to the bundle so it will work on other peoples' machines. +If you are not using any external libraries, this is all you need to +do. You now have a full app bundle in `/tmp/myapp.app` that you can +use. Most applications use third party frameworks and libraries, +though, so you need to add them to the bundle so it will work on other +peoples' machines. -As an example we are going to use the [SDL2](https://libsdl.org/) framework. In order to bundle it in our app, we first specify an installer script to run. +As an example we are going to use the [SDL2](https://libsdl.org/) +framework. In order to bundle it in our app, we first specify an +installer script to run. ```meson meson.add_install_script('install_script.sh') ``` -The install script does two things. First it copies the whole framework into our bundle. +The install script does two things. First it copies the whole +framework into our bundle. ```console $ mkdir -p ${MESON_INSTALL_PREFIX}/Contents/Frameworks @@ -71,7 +102,10 @@ $ cp -R /Library/Frameworks/SDL2.framework \ ${MESON_INSTALL_PREFIX}/Contents/Frameworks ``` -Then it needs to alter the library search path of our executable(s). This tells OSX that the libraries your app needs are inside your bundle. In the case of SDL2, the invocation goes like this: +Then it needs to alter the library search path of our +executable(s). This tells OSX that the libraries your app needs are +inside your bundle. In the case of SDL2, the invocation goes like +this: ```console $ install_name_tool -change @rpath/SDL2.framework/Versions/A/SDL2 \ @@ -79,22 +113,48 @@ $ install_name_tool -change @rpath/SDL2.framework/Versions/A/SDL2 \ ${MESON_INSTALL_PREFIX}/Contents/MacOS/myapp ``` -This is the part of OSX app bundling that you must always do manually. OSX dependencies come in many shapes and forms and unfortunately there is no reliable automatic way to determine how each dependency should be handled. Frameworks go to the `Frameworks` directory while plain `.dylib` files usually go to `Contents/Resources/lib` (but you can put them wherever you like). To get this done you have to check what your program links against with `otool -L /path/to/binary` and manually add the copy and fix steps to your install script. Do not copy system libraries inside your bundle, though. +This is the part of OSX app bundling that you must always do +manually. OSX dependencies come in many shapes and forms and +unfortunately there is no reliable automatic way to determine how each +dependency should be handled. Frameworks go to the `Frameworks` +directory while plain `.dylib` files usually go to +`Contents/Resources/lib` (but you can put them wherever you like). To +get this done you have to check what your program links against with +`otool -L /path/to/binary` and manually add the copy and fix steps to +your install script. Do not copy system libraries inside your bundle, +though. -After this you have a fully working, self-contained OSX app bundle ready for distribution. +After this you have a fully working, self-contained OSX app bundle +ready for distribution. ## Creating a .dmg installer -A .dmg installer is similarly quite simple, at its core it is basically a fancy compressed archive. A good description can be found on [this page](https://el-tramo.be/guides/fancy-dmg/). Please read it and create a template image file according to its instructions. +A .dmg installer is similarly quite simple, at its core it is +basically a fancy compressed archive. A good description can be found +on [this page](https://el-tramo.be/guides/fancy-dmg/). Please read it +and create a template image file according to its instructions. -The actual process of creating the installer is very simple: you mount the template image, copy your app bundle in it, unmount it and convert the image into a compressed archive. The actual commands to do this are not particularly interesting, feel free to steal them from either the linked page above or from the sample script in Meson's test suite. +The actual process of creating the installer is very simple: you mount +the template image, copy your app bundle in it, unmount it and convert +the image into a compressed archive. The actual commands to do this +are not particularly interesting, feel free to steal them from either +the linked page above or from the sample script in Meson's test suite. ## Putting it all together -There are many ways to put the .dmg installer together and different people will do it in different ways. The linked sample code does it by having two different scripts. This separates the different pieces generating the installer into logical pieces. +There are many ways to put the .dmg installer together and different +people will do it in different ways. The linked sample code does it by +having two different scripts. This separates the different pieces +generating the installer into logical pieces. -`install_script.sh` only deals with embedding dependencies and fixing the library paths. +`install_script.sh` only deals with embedding dependencies and fixing +the library paths. -`build_osx_installer.sh` sets up the build with the proper paths, compiles, installs and generates the .dmg package. +`build_osx_installer.sh` sets up the build with the proper paths, +compiles, installs and generates the .dmg package. -The main reasoning here is that in order to build a complete OSX installer package from source, all you need to do is to cd into the source tree and run `./build_osx_installer.sh`. To build packages on other platforms you would write scripts such as `build_windows_installer.bat` and so on. +The main reasoning here is that in order to build a complete OSX +installer package from source, all you need to do is to cd into the +source tree and run `./build_osx_installer.sh`. To build packages on +other platforms you would write scripts such as +`build_windows_installer.bat` and so on. |