= Compiling on macOS

The official OpenCPN packages are currently built as universal binaries and run natively on both Intel and Apple Silicon machines.

== The fast track

This process will allow building single architecture binaries which are NOT compatible with the official OpenCPN packages and plugin built for them, but does not do modifications to the environment that might cause you problems while building other software. Such a setup is perfectly good for OpenCPN development.

- Install Xcode and the Command Line Tools for Xcode from the Apple Developer website (https://developer.apple.com/download/all/)
- Install Homebrew (https://brew.sh)
- Clone the OpenCPN source code (`git clone https://github.com/OpenCPN/OpenCPN.git`)
- Switch to the source tree (`cd OpenCPN`)
- Run the build script (`ci/generic-build-macos.sh`)
  - The script installs additional tools and dependencies required to build OpenCPN and needs internet connection
  - It is not necessary to run the script for subsequent builds, as all the dependencies are already installed, use the normal `cmake` workflow for them.
- The build products can be found in the `build` subdirectory

This process is continuously tested by the OpenCPN automatic builds, so it is known to work.
The `generic-build-macos.sh` is extensively commented, it's strongly recommended to use it as reference while
creating a build environment manually.

Note that the official OpenCPN builds for macOS are created using a slightly different process implemented in `universal-build-macos.sh` to be repeatable, compatible with older macOS systems and to be able to produce universal binaries running natively on both Apple Silicon and Intel hardware. This process requires special set of dependencies that may conflict with other libraries on your system and you do not need it unless you intend to distribute your build product or use it with plugins from other developers available through the plugin manager.

== Development environment, detailed instructions

There are required development tools that can be installed via Homebrew
(https://brew.sh) (or similarly from MacPorts, but it is unsupported and
untested).

Install Xcode and the Command Line Tools for Xcode from the Apple Developer website (https://developer.apple.com/download/all/)

Install Homebrew:

 $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Install cmake and gettext via Homebrew:

 $ brew install cmake
 $ brew install gettext

And either restart Terminal.app or reload your environment using

 . ~/.bash_profile


=== Required external libraries

If you are building OpenCPN with extended archive support (default,
required to download and unpack up to date GSHHG basemaps and pilot
charts using the chart downloader plugin), libarchive library is needed,
install it using:

 $ brew install zstd xz libarchive

[Read following note - install only if necessary] - To produce binaries
fully compatible with older macOS versions on newer macOS, libarchive
must instead of from Homebrew, be built as follows:

 $ export MACOSX_DEPLOYMENT_TARGET=10.13
 $ wget https://libarchive.org/downloads/libarchive-3.3.3.tar.gz
 $ tar zxf libarchive-3.3.3.tar.gz
 $ cd libarchive-3.3.3
 $ ./configure --without-lzo2 --without-nettle --without-xml2 --without-openssl --with-expat make
 $ make install
 $ cd ..

==== wxWidgets

OpenCPN is built upon wxWidgets, a package providing a cross-platform UI SDK.
For local development the wxWidgets from Homebrew (or built locally) can be used:

 $ brew install wxwidgets

But to get results fully compatible with the official OpenCPN
builds, which retain compatibility with older macOS versions, wxWidgets must be version 3.2.5 built manually.
For very old Intel machines you may download the prebuilt binaries archive from https://dl.cloudsmith.io/public/nohal/opencpn-dependencies/raw/files/macos_deps_intel_legacy.tar.xz
For modern Macs, OpenCPN is built as a universal binary against set of prebuilt dependencies available from https://dl.cloudsmith.io/public/nohal/opencpn-dependencies/raw/files/macos_deps_universal-opencpn.tar.xz

To build wxWidgets manually, you may use the following process:

 $ git clone --recurse-submodules --depth 1 --branch v3.2.5 https://github.com/wxWidgets/wxWidgets.git
 $ cd wxWidgets
 $ mkdir build-release && cd build-release
 $ ../configure --with-cxx=11 --with-macosx-version-min=10.13 --enable-unicode --with-osx-cocoa --enable-aui --disable-debug --with-opengl --without-subdirs
 $ make -j2
 $ sudo make install

==== Packages tool

To create .pkg files for plugins, download the “Packages” tool from
http://s.sudre.free.fr/Software/Packages/about.html[s.sudre.free.fr]
Install Packages.dmg by double-clicking the file and following the
instructions - no need to open Packages.app as the installer configures
the necessary command line tools for Packages.

 $ brew install --cask packages

=== Building OpenCPN

Officially OpenCPN is built from the command line, but it's also
possible to use Apple's Xcode IDE for development. Regardless of which
method we choose, the first steps are the same: Get the OpenCPN source:

 $ git clone https://github.com/OpenCPN/OpenCPN.git


Create the build directory, where our local builds will take place, so
that we don't work directly in the source tree:

 $ mkdir OpenCPN/build && cd OpenCPN/build

*Build Method 1* - From the command line Prepare our build environment:

 $ export MACOSX_DEPLOYMENT_TARGET=10.13
 $ cmake ..

Build OpenCPN:

 $ make

To build a debug version use:

 $ export MACOSX_DEPLOYMENT_TARGET=10.13
 $ cmake -DCMAKE_BUILD_TYPE=Debug ..
 $ make

Install OpenCPN:

 $ make install

*Build Method 2* - Using Xcode Create the Xcode project:

 $ export MACOSX_DEPLOYMENT_TARGET=10.13
 $ cmake -G Xcode ..

Open the `OpenCPN.xcodeproj` file in Xcode, and use the “Build”, “Run”,
“Debug”, etc features as normal. To use the “Run” action you need to
build the “OpenCPN” target rather than the default “ALL_BUILD” target.

=== Code Signing

When building OpenCPN on Apple Silicon Macs, additional configuration
may be needed to handle code signing and architecture.
After building, sign the application with an ad-hoc signature:

 $ codesign --force --deep --sign - /path/bin/OpenCPN.app

Note: These settings create a build that can run locally but
isn't suitable for distribution through the App Store.

=== Creating the installer package

WARNING - Do The Following:

The default install location is (/usr/local/bin). Everything from
/usr/local/bin gets packaged into your DMG which is not desirable. To
avoid this, change the install location with 'cmake' as follows:

 $ cmake -DCMAKE_INSTALL_PREFIX=/tmp ..

Some developers have reported that the install step copies a redundant
set of the wxWidgets dynamic library into the install directory, causing
OpenCPN to fail. This is intended, but gets annoying for local bundles
not intended to be distributed. A kludgey fix:

 $ sudo rm /usr/local/bin/OpenCPN.app/Contents/MacOS/libwx*dylib

Build the installable PKG:

 $ make create-pkg

Build the installable DMG:

 $ make create-dmg

Depending on your local system, during both steps above you may observe
insufficient permissions on some files. Either fix the permissions or
use sudo to run make install/create-dmg

Do not distribute binaries not built against the official dependencies, they will not be ABI compatible with
the build products of other developers and will cause interoperability problems and confusion to the users.
