diff options
Diffstat (limited to 'packaging/macos')
-rw-r--r-- | packaging/macos/020-vars.sh | 207 | ||||
-rw-r--r-- | packaging/macos/030-funcs.sh | 406 | ||||
-rwxr-xr-x | packaging/macos/110-sysprep.sh | 40 | ||||
-rwxr-xr-x | packaging/macos/130-jhbuild-bootstrap.sh | 69 | ||||
-rwxr-xr-x | packaging/macos/140-jhbuild-gtk3.sh | 19 | ||||
-rwxr-xr-x | packaging/macos/150-jhbuild-inkdeps.sh | 37 | ||||
-rwxr-xr-x | packaging/macos/160-jhbuild-other.sh | 61 | ||||
-rwxr-xr-x | packaging/macos/210-inkscape-build.sh | 59 | ||||
-rwxr-xr-x | packaging/macos/220-inkscape-package.sh | 175 | ||||
-rwxr-xr-x | packaging/macos/230-inkscape-distrib.sh | 51 | ||||
-rw-r--r-- | packaging/macos/README.md | 106 | ||||
-rwxr-xr-x | packaging/macos/build_inkscape.sh | 21 | ||||
-rwxr-xr-x | packaging/macos/build_toolset.sh | 44 | ||||
-rw-r--r-- | packaging/macos/fonts.conf | 77 | ||||
-rw-r--r-- | packaging/macos/inkscape.bundle | 165 | ||||
-rw-r--r-- | packaging/macos/inkscape.plist | 565 | ||||
-rw-r--r-- | packaging/macos/inkscape_dmg.py | 246 | ||||
-rwxr-xr-x | packaging/macos/install_toolset.sh | 66 | ||||
-rwxr-xr-x | packaging/macos/uninstall_toolset.sh | 36 |
19 files changed, 2450 insertions, 0 deletions
diff --git a/packaging/macos/020-vars.sh b/packaging/macos/020-vars.sh new file mode 100644 index 0000000..98f7a1b --- /dev/null +++ b/packaging/macos/020-vars.sh @@ -0,0 +1,207 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the build pipeline for Inkscape on macOS. +# +# ### 020-vars.sh ### +# This file contains all the global variables (as in: configuration for the +# build pipeline) and gets sourced by all the other scripts. +# If you want to override settings, the suggested way is that you create a +# `0nn-custom.sh` file and put them there. All files named '0nn-*.sh' get +# sourced in numerical order. + +[ -z $VARS_INCLUDED ] && VARS_INCLUDED=true || return # include guard + +### name and directory ######################################################### + +SELF_NAME=$(basename $0) + +### nesting level when trapping errors ######################################### + +ERRTRACE_COUNT=0 + +### multithreading ############################################################# + +CORES=$(sysctl -n hw.ncpu) # use all available cores +export MAKEFLAGS="-j $CORES" + +### target OS version ########################################################## + +# The current build setup is +# - Xcode 12 +# - OS X El Capitan 10.11 SDK (part of Xcode 7.3.1) +# - macOS Catalina 10.15.6 + +SDK_VERSION=10.11 +[ -z $SDKROOT_DIR ] && SDKROOT_DIR=/opt/sdks +export SDKROOT=$SDKROOT_DIR/MacOSX${SDK_VERSION}.sdk + +### build system/toolset version ############################################### + +TOOLSET_VERSION=0.37.6 + +### ramdisk #################################################################### + +# Using the toolset dmg, a small writable overlay is required. +OVERLAY_RAMDISK_SIZE=3 # unit is GiB + +### toolset root directory ##################################################### + +# This is the main directory where all the action takes place below. It is +# one level above WRK_DIR (which in previous releases has been called the +# main directory) so we can manage and switch between multiple different WRK_DIR +# versions as required. + +# Allow this to be overridable or use the default. +[ -z $TOOLSET_ROOT_DIR ] && TOOLSET_ROOT_DIR=/Users/Shared/work || true + +if [ $(mkdir -p $TOOLSET_ROOT_DIR 2>/dev/null; echo $?) -eq 0 ] && + [ -w $TOOLSET_ROOT_DIR ] ; then + : # nothing to do, everything ok +else + echo "❌ directory not usable (TOOLSET_ROOT_DIR): $TOOLSET_ROOT_DIR" + exit 1 +fi + +### toolset directories ######################################################## + +# This is where .dmg files with pre-compiled toolsets are downloaded to. +TOOLSET_REPO_DIR=$TOOLSET_ROOT_DIR/repo +# Persistent location for ccache. +export CCACHE_DIR=$TOOLSET_ROOT_DIR/ccache + +### work directory and subdirectories ########################################## + +# Allow this to be overrideable or use version number as default. +[ -z $WRK_DIR ] && WRK_DIR=$TOOLSET_ROOT_DIR/$TOOLSET_VERSION || true + +OPT_DIR=$WRK_DIR/opt +BIN_DIR=$OPT_DIR/bin +INC_DIR=$OPT_DIR/include +LIB_DIR=$OPT_DIR/lib +SRC_DIR=$OPT_DIR/src +TMP_DIR=$OPT_DIR/tmp + +### use TMP_DIR for everything temporary ####################################### + +export TMP=$TMP_DIR +export TEMP=$TMP_DIR +export TMPDIR=$TMP_DIR +export XDG_CACHE_HOME=$TMP_DIR # instead ~/.cache +export XDG_CONFIG_HOME=$TMP_DIR # instead ~/.config +export PIP_CACHE_DIR=$TMP_DIR # instead ~/Library/Caches/pip +export PIPENV_CACHE_DIR=$TMP_DIR # instead ~/Library/Caches/pipenv + +# TODO: ~/Library/Caches/pip-tools ? + +### JHBuild subdirectories and configuration ################################### + +export DEVROOT=$WRK_DIR/gtk-osx +export DEVPREFIX=$DEVROOT/local +export DEV_SRC_ROOT=$DEVROOT/source + +export JHBUILDRC=$DEVROOT/jhbuildrc # requires modified gtk-osx-setup.sh +export JHBUILDRC_CUSTOM=$JHBUILDRC-custom + +### Inkscape Git repository directory ########################################## + +# Location is different when running as GitLab CI job. + +if [ -z $CI_JOB_ID ]; then + INK_DIR=$SRC_DIR/inkscape +else + INK_DIR=$SELF_DIR/../.. # SELF_DIR needs to be set by the sourcing script + INK_DIR=$(cd $INK_DIR; pwd -P) # make path canoncial +fi + +### artifact path ############################################################## + +# This is the location where the final product - like application bundle or +# diskimage (no intermediate programs/libraries/...) - is created in. + +ARTIFACT_DIR=$WRK_DIR/artifacts + +### application bundle paths ################################################### + +APP_DIR=$ARTIFACT_DIR/Inkscape.app +APP_CON_DIR=$APP_DIR/Contents +APP_RES_DIR=$APP_CON_DIR/Resources +APP_FRA_DIR=$APP_CON_DIR/Frameworks +APP_BIN_DIR=$APP_RES_DIR/bin +APP_ETC_DIR=$APP_RES_DIR/etc +APP_EXE_DIR=$APP_CON_DIR/MacOS +APP_LIB_DIR=$APP_RES_DIR/lib + +APP_PLIST=$APP_CON_DIR/Info.plist + +### bundled Python version ##################################################### + +PY3_MAJOR=3 +PY3_MINOR=8 +PY3_PATCH=5 +PY3_BUILD=2 # custom framework build number + +### download URLs for dependencies ############################################# + +# https://github.com/dehesselle/gtk-osx +# Forked from https://gitlab.gnome.org/GNOME/gtk-osx +URL_GTK_OSX=https://raw.githubusercontent.com/dehesselle/gtk-osx/inkscape-1.0.x-10 +URL_GTK_OSX_SETUP=$URL_GTK_OSX/gtk-osx-setup.sh +URL_GTK_OSX_MODULESET=$URL_GTK_OSX/modulesets-stable/gtk-osx.modules + +### download URLs for auxiliary software ####################################### + +# These are versioned URLs of software that is not a direct dependency but +# required for building, packaging or similar. + +# create application bundle +# https://github.com/dehesselle/gtk-mac-bundler +# Forked from https://gitlab.gnome.org/GNOME/gtk-mac-bundler +URL_GTK_MAC_BUNDLER=https://github.com/dehesselle/gtk-mac-bundler/archive/f96a9daf2236814af7ace7a2fa91bbfb4f077779.tar.gz +# Inkscapge Git repo (for standalone/non-CI builds) +URL_INKSCAPE=https://gitlab.com/inkscape/inkscape +# disk image icon +URL_INKSCAPE_DMG_ICNS=https://github.com/dehesselle/mibap/raw/master/inkscape_dmg.icns +# convert PNG image to iconset in ICNS format +# https://github.com/bitboss-ca/png2icns +URL_PNG2ICNS=https://github.com/bitboss-ca/png2icns/archive/v0.1.tar.gz +# This is a relocatable Python.framework to be bundled with the app. +# https://github.com/dehesselle/py3framework +URL_PYTHON=https://github.com/dehesselle/py3framework/releases/download/py$PY3_MAJOR$PY3_MINOR$PY3_PATCH.$PY3_BUILD/py$PY3_MAJOR$PY3_MINOR${PY3_PATCH}_framework_$PY3_BUILD.tar.xz +# A pre-compiled version of the whole toolset. +# https://github.com/dehesselle/mibap +URL_TOOLSET=https://github.com/dehesselle/mibap/releases/download/v$TOOLSET_VERSION/mibap_v$TOOLSET_VERSION.dmg + +### Python: packages for Inkscape ############################################## + +# The following Python packages are bundled with Inkscape. + +# https://cairocffi.readthedocs.io/en/stable/ +# https://github.com/Kozea/cairocffi +PYTHON_CAIROCFFI=cairocffi==1.1.0 +# https://lxml.de +# https://github.com/lxml/lxml +# https://github.com/dehesselle/py3framework +PYTHON_LXML=$(dirname $URL_PYTHON)/lxml-4.5.2-cp$PY3_MAJOR$PY3_MINOR-cp$PY3_MAJOR$PY3_MINOR-macosx_10_9_x86_64.whl +# https://github.com/numpy/numpy +PYTHON_NUMPY=numpy==1.19.1 +# https://pygobject.readthedocs.io/en/latest/ +PYTHON_PYGOBJECT=PyGObject==3.36.1 +# https://github.com/scour-project/scour +PYTHON_SCOUR=scour==0.37 +# https://pyserial.readthedocs.io/en/latest/ +# https://github.com/pyserial/pyserial +PYTHON_PYSERIAL=pyserial==3.4 + +### Python: auxiliary packages ################################################# + +# convert SVG to PNG +# https://cairosvg.org +PYTHON_CAIROSVG=cairosvg==2.4.2 +# create DMG +# https://dmgbuild.readthedocs.io/en/latest/ +# https://github.com/al45tair/dmgbuild +PYTHON_DMGBUILD="biplist==1.0.3 dmgbuild==1.4.2" + +### path ####################################################################### + +export PATH=$DEVPREFIX/bin:$BIN_DIR:/usr/bin:/bin:/usr/sbin:/sbin diff --git a/packaging/macos/030-funcs.sh b/packaging/macos/030-funcs.sh new file mode 100644 index 0000000..3b08141 --- /dev/null +++ b/packaging/macos/030-funcs.sh @@ -0,0 +1,406 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the build pipeline for Inkscape on macOS. +# +# ### 030-funcs.sh ### +# This file contains all the functions used by the other scripts. It helps +# modularizing functionality and keeping the scripts that do the real work +# as readable as possible. +# This file does not include the "vars" files it requires itself (on purpose, +# for flexibility reasons), the script that wants to use these functions +# needs to do that. The suggested way is to always source all the "0nn-*.sh" +# files in order. + +[ -z $FUNCS_INCLUDED ] && FUNCS_INCLUDED=true || return # include guard + +### get repository version string ############################################## + +function get_repo_version +{ + local repo=$1 + # do it the same way as in CMakeScripts/inkscape-version.cmake + echo $(git -C $repo rev-parse --short HEAD) +} + +### get Inkscape version from CMakeLists.txt ################################### + +function get_inkscape_version +{ + local file=$INK_DIR/CMakeLists.txt + local ver_major=$(grep INKSCAPE_VERSION_MAJOR $file | head -n 1 | awk '{ print $2+0 }') + local ver_minor=$(grep INKSCAPE_VERSION_MINOR $file | head -n 1 | awk '{ print $2+0 }') + local ver_patch=$(grep INKSCAPE_VERSION_PATCH $file | head -n 1 | awk '{ print $2+0 }') + local ver_suffix=$(grep INKSCAPE_VERSION_SUFFIX $file | head -n 1 | awk '{ print $2 }') + + ver_suffix=${ver_suffix%\"*} # remove "double quote and everything after" from end + ver_suffix=${ver_suffix#\"} # remove "double quote" from beginning + + echo $ver_major.$ver_minor.$ver_patch$ver_suffix +} + +### get compression flag by filename extension ################################# + +function get_comp_flag +{ + local file=$1 + + local extension=${file##*.} + + case $extension in + bz2) echo "j" ;; + gz) echo "z" ;; + tgz) echo "z" ;; + xz) echo "J" ;; + *) echo "ERROR unknown extension $extension" + esac +} + +### download and extract source tarball ######################################## + +function install_source +{ + local url=$1 + local target_dir=$2 # optional: target directory, defaults to $SRC_DIR + local options=$3 # optional: additional options for 'tar' + + [ ! -d $TMP_DIR ] && mkdir -p $TMP_DIR + local log=$(mktemp $TMP_DIR/$FUNCNAME.XXXX) + [ -z $target_dir ] && target_dir=$SRC_DIR + [ ! -d $SRC_DIR ] && mkdir -p $SRC_DIR + + cd $target_dir + + # This downloads a file and pipes it directly into tar (file is not saved + # to disk) to extract it. Output from stderr is saved temporarily to + # determine the directory the files have been extracted to. + curl -L $(preferCachedUrl $url) | tar xv$(get_comp_flag $url) $options 2>$log + cd $(head -1 $log | awk '{ print $2 }') + [ $? -eq 0 ] && rm $log || echo "$FUNCNAME: check $log" +} + +### download a file and save to disk ########################################### + +function save_file +{ + local url=$1 + local target_dir=$2 # optional argument, defaults to $SRC_DIR + + [ -z $target_dir ] && target_dir=$SRC_DIR + + local file=$target_dir/$(basename $url) + if [ -f $file ]; then + echo "$FUNCNAME: file $file exists" + else + curl -o $file -L $url + fi +} + +### make, make install in jhbuild environment ################################## + +function make_makeinstall +{ + jhbuild run make + jhbuild run make install +} + +### configure, make, make install in jhbuild environment ####################### + +function configure_make_makeinstall +{ + local flags="$*" + + jhbuild run ./configure --prefix=$OPT_DIR $flags + make_makeinstall +} + +### cmake, make, make install in jhbuild environment ########################### + +function cmake_make_makeinstall +{ + local flags="$*" + + mkdir builddir + cd builddir + jhbuild run cmake -DCMAKE_INSTALL_PREFIX=$OPT_DIR $flags .. + make_makeinstall +} + +### create and mount ramdisk ################################################### + +# There is a more common approach to do this using +# diskutil eraseVolume HFS+ VolName $(hdiutil attach -nomount ram://<size>) +# but that always attaches the ramdisk below '/Volumes'. +# To have full control, we need to do it as follows. + +function create_ramdisk +{ + local dir=$1 # mountpoint + local size=$2 # unit is GiB + + if [ $(mount | grep $dir | wc -l) -eq 0 ]; then + local device=$(hdiutil attach -nomount ram://$(expr $size \* 1024 \* 2048)) + newfs_hfs -v "RAMDISK" $device + mount -o noatime,nobrowse -t hfs $device $dir + fi +} + +### insert line into a textfile ################################################ + +# usage: +# insert_before <filename> <insert before this pattern> <line to insert> + +function insert_before +{ + local file=$1 + local pattern=$2 + local line=$3 + + local file_tmp=$(mktemp) + awk "/${pattern}/{print \"$line\"}1" $file > $file_tmp + cat $file_tmp > $file # we don't 'mv' to preserve permissions + rm $file_tmp +} + +### escape replacement string for sed ########################################## + +# Escape slashes, backslashes and ampersands in strings to be used s as +# replacement strings when using 'sed'. Newlines are not taken into +# consideartion here. +# reference: https://stackoverflow.com/a/2705678 + +function escape_sed +{ + local string="$*" + + echo "$string" | sed -e 's/[\/&]/\\&/g' +} + +### replace line that matches pattern ########################################## + +function replace_line +{ + local file=$1 + local pattern=$2 + local replacement=$3 + + sed -i '' "s/.*${pattern}.*/$(escape_sed $replacement)/" $file +} + +### relocate a library dependency ############################################## + +function relocate_dependency +{ + local target=$1 # fully qualified path and library name to new location + local library=$2 # library to be modified (change 'source' to 'target'I + + local source_lib=${target##*/} # get library filename from target location + local source=$(otool -L $library | grep $source_lib | awk '{ print $1 }') + + install_name_tool -change $source $target $library +} + +### relocate all neighbouring libraries in a directory ######################### + +function relocate_neighbouring_libs +{ + local dir=$1 + + for lib in $dir/*.dylib; do + for linked_lib in $(otool -L $lib | tail -n +3 | awk '{ print $1 }'); do + if [ -f $APP_LIB_DIR/$(basename $linked_lib) ]; then + relocate_dependency @loader_path/$(basename $linked_lib) $lib + fi + done + done +} + +### 'readlink -f' replacement ################################################## + +# This is what the oneliner setting SELF_DIR (see top of file) is based on. + +function readlinkf +{ + # 'readlink -f' replacement: https://stackoverflow.com/a/1116890 + # 'do while' replacement: https://stackoverflow.com/a/16491478 + + local file=$1 + + # iterate down a (possible) chain of symlinks + while + [ ! -z $(readlink $file) ] && file=$(readlink $file) + cd $(dirname $file) + file=$(basename $file) + [ -L "$file" ] + do + : + done + + # Compute the canonicalized name by finding the physical path + # for the directory we're in and appending the target file. + echo $(pwd -P)/$file +} + +### create disk image ########################################################## + +function create_dmg +{ + local app=$1 + local dmg=$2 + local cfg=$3 + + # set application + sed -i '' "s/PLACEHOLDERAPPLICATION/$(escape_sed $app)/" $cfg + + # set disk image icon (if it exists) + local icon=$SRC_DIR/$(basename -s .py $cfg).icns + if [ -f $icon ]; then + sed -i '' "s/PLACEHOLDERICON/$(escape_sed $icon)/" $cfg + fi + + # set background image (if it exists) + local background=$SRC_DIR/$(basename -s .py $cfg).png + if [ -f $background ]; then + sed -i '' "s/PLACEHOLDERBACKGROUND/$(escape_sed $background)/" $cfg + fi + + # create disk image + dmgbuild -s $cfg "$(basename -s .app $app)" $dmg +} + +### run script via Terminal.app ################################################ + +# This is for commands that otherwise don't behave when running in CI. +# It requires a running desktop session (i.e. logged in user) and special +# permissions on newer macOS versions. +# Adapted from: https://stackoverflow.com/a/27970527 +# https://gist.github.com/masci/ff51d9cf40a87a80094c + +function run_in_terminal +{ + local command=$1 + + #local window_id=$(uuidgen) # this would be really unique but... + local window_id=$(date +%s) # ...seconds would help more with debugging + + osascript <<EOF +tell application "Terminal" + set _tab to do script "echo -n -e \"\\\033]0;$window_id\\\007\"; $command; exit" + delay 1 + repeat while _tab is busy + delay 1 + end repeat + close (every window whose name contains "$window_id") +end tell +EOF +} + +### replacements for plain echo: ok, error, info, warning ###################### + +function echo_ok +{ + echo -e "✅ $*" +} + +function echo_err +{ + echo -e "❌ $*" +} + +function echo_warn +{ + echo -e "⚠️ $*" +} + +function echo_info +{ + echo -e "ℹ️ $*" +} + +function echo_act # action +{ + echo -e "➡️ $*" +} + +### create a ramdisk and return the device ##################################### + +function create_ram_device +{ + local size_gib=$1 # unit is GiB + local name=$2 # volume name + + [ -z $name ] && name=$(uuidgen | md5 | head -c 8) # generate random name + + local size_sectors=$(expr $size_gib \* 1024 \* 2048) + local device=$(hdiutil attach -nomount ram://$size_sectors) + newfs_hfs -v "$name" $device >/dev/null + + echo $device +} + +### attach a disk image and return the device ################################## + +function create_dmg_device +{ + local dmg=$1 + local options=$2 # optional arguments for hdiutil + + local device=$(hdiutil attach -nomount $dmg $options | grep "^/dev/disk" | \ + grep "Apple_HFS" | awk '{ print $1 }') + + echo $device +} + +### replace URL ################################################################ + +function preferCachedUrl +{ + local url=$1 + + # This is a placeholder function you can use to replace URLs with locally + # mirrored ones. + + echo $url +} + +### install Python package with Python.framework ############################### + +function pip_install +{ + local package=$1 + + local PATH_ORIGINAL=$PATH + export PATH=$APP_FRA_DIR/Python.framework/Versions/Current/bin:$PATH + + pip$PY3_MAJOR install \ + --prefix=$APP_RES_DIR \ + --ignore-installed \ + $package + + export PATH=$PATH_ORIGINAL +} + +### this function is called on "trap ERR" ###################################### + +# macOS' old bash 3.x has a bug that causes the line number of the error +# to point to the function entry instead of the command inside the function. + +function catch_error +{ + local file=$1 + local line=$2 + local func=$3 + local command=$4 + local rc=$5 + + [ -z $func ] && func="main" || true + + ((ERRTRACE_COUNT++)) + + case $ERRTRACE_COUNT in + 1) echo -e "\033[97m\033[101m\033[1m[$file:$line] $func failed with rc=$rc\033[39m\033[49m\033[0m" + echo -e "\033[93m$command\033[39m" + ;; + *) echo -e "[$file:$line] <- $func" + ;; + esac +} diff --git a/packaging/macos/110-sysprep.sh b/packaging/macos/110-sysprep.sh new file mode 100755 index 0000000..56bc5eb --- /dev/null +++ b/packaging/macos/110-sysprep.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the build pipeline for Inkscape on macOS. +# +# ### 110-sysprep.sh ### +# System preparation tasks. + +### load settings and functions ################################################ + +SELF_DIR=$(F=$0; while [ ! -z $(readlink $F) ] && F=$(readlink $F); cd $(dirname $F); F=$(basename $F); [ -L $F ]; do :; done; echo $(pwd -P)) +for script in $SELF_DIR/0??-*.sh; do source $script; done + +### initial information ######################################################## + +echo_info "TOOLSET_ROOT_DIR = $TOOLSET_ROOT_DIR" +echo_info "WRK_DIR = $WRK_DIR" + +### check for presence of SDK ################################################## + +if [ ! -d $SDKROOT ]; then + echo_err "SDK not found: $SDKROOT" + exit 1 +fi + +### create work directory ###################################################### + +[ ! -d $WRK_DIR ] && mkdir -p $WRK_DIR || true + +### create temporary directory ################################################# + +[ ! -d $TMP_DIR ] && mkdir -p $TMP_DIR || true + +### create binary directory ################################################# + +[ ! -d $BIN_DIR ] && mkdir -p $BIN_DIR || true + +### create toolset repository directory ######################################## + +[ ! -d $TOOLSET_REPO_DIR ] && mkdir -p $TOOLSET_REPO_DIR || true diff --git a/packaging/macos/130-jhbuild-bootstrap.sh b/packaging/macos/130-jhbuild-bootstrap.sh new file mode 100755 index 0000000..d6611bc --- /dev/null +++ b/packaging/macos/130-jhbuild-bootstrap.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the build pipeline for Inkscape on macOS. +# +# ### 130-jhbuild-bootstrap.sh ### +# Bootstrap the JHBuild environment. + +### load global settings and functions ######################################### + +SELF_DIR=$(F=$0; while [ ! -z $(readlink $F) ] && F=$(readlink $F); cd $(dirname $F); F=$(basename $F); [ -L $F ]; do :; done; echo $(pwd -P)) +for script in $SELF_DIR/0??-*.sh; do source $script; done + +### local settings ############################################################# + +export PYTHONUSERBASE=$DEVPREFIX +export PIP_CONFIG_DIR=$DEVROOT/pip + +### install and configure jhbuild ############################################## + +bash <(curl -s $URL_GTK_OSX_SETUP) # run jhbuild setup script + +# JHBuild: paths +echo "checkoutroot = '$SRC_DIR/checkout'" >> $JHBUILDRC_CUSTOM +echo "prefix = '$OPT_DIR'" >> $JHBUILDRC_CUSTOM +echo "tarballdir = '$SRC_DIR/download'" >> $JHBUILDRC_CUSTOM + +# JHBuild: console output +echo "quiet_mode = True" >> $JHBUILDRC_CUSTOM +echo "progress_bar = True" >> $JHBUILDRC_CUSTOM + +# JHBuild: moduleset +echo "moduleset = '$URL_GTK_OSX_MODULESET'" >> $JHBUILDRC_CUSTOM + +# JHBuild: macOS SDK +sed -i "" "s/^setup_sdk/#setup_sdk/" $JHBUILDRC_CUSTOM +echo "setup_sdk(target=\"$SDK_VERSION\")" >> $JHBUILDRC_CUSTOM +echo "os.environ[\"SDKROOT\"]=\"$SDKROOT\"" >> $JHBUILDRC_CUSTOM + +# JHBuild: TODO: I have forgotten why this is here +echo "if \"openssl\" in skip:" >> $JHBUILDRC_CUSTOM +echo " skip.remove(\"openssl\")" >> $JHBUILDRC_CUSTOM + +# Remove harmful settings in regards to the target platform: +# - MACOSX_DEPLOYMENT_TARGET +# - -mmacosx-version-min +# +# otool -l <library> | grep -A 3 -B 1 LC_VERSION_MIN_MACOSX +# +# cmd LC_VERSION_MIN_MACOSX +# cmdsize 16 +# version 10.11 +# sdk n/a < - - - notarized app won't load this library +echo "os.environ.pop(\"MACOSX_DEPLOYMENT_TARGET\")" \ + >> $JHBUILDRC_CUSTOM +echo "os.environ[\"CFLAGS\"] = \"-O2 -I$SDKROOT/usr/include -isysroot $SDKROOT\"" \ + >> $JHBUILDRC_CUSTOM +echo "os.environ[\"CPPFLAGS\"] = \"-I$INC_DIR -I$SDKROOT/usr/include -isysroot $SDKROOT\"" \ + >> $JHBUILDRC_CUSTOM +echo "os.environ[\"CXXFLAGS\"] = \"-O2 -I$SDKROOT/usr/include -isysroot $SDKROOT\"" \ + >> $JHBUILDRC_CUSTOM +echo "os.environ[\"LDFLAGS\"] = \"-L$LIB_DIR -L$SDKROOT/usr/lib -isysroot $SDKROOT -Wl,-headerpad_max_install_names\"" \ + >> $JHBUILDRC_CUSTOM +echo "os.environ[\"OBJCFLAGS\"] = \"-O2 -I$SDKROOT/usr/include -isysroot $SDKROOT\"" \ + >> $JHBUILDRC_CUSTOM + +### bootstrap JHBuild ########################################################## + +jhbuild bootstrap-gtk-osx diff --git a/packaging/macos/140-jhbuild-gtk3.sh b/packaging/macos/140-jhbuild-gtk3.sh new file mode 100755 index 0000000..73709f0 --- /dev/null +++ b/packaging/macos/140-jhbuild-gtk3.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the build pipeline for Inkscape on macOS. +# +# ### 140-jhbuild-gtk3.sh ### +# Install GTK3 libraries. + +### load settings and functions ################################################ + +SELF_DIR=$(F=$0; while [ ! -z $(readlink $F) ] && F=$(readlink $F); cd $(dirname $F); F=$(basename $F); [ -L $F ]; do :; done; echo $(pwd -P)) +for script in $SELF_DIR/0??-*.sh; do source $script; done + +### install GTK3 libraries ##################################################### + +jhbuild build \ + meta-gtk-osx-bootstrap \ + meta-gtk-osx-gtk3 \ + meta-gtk-osx-gtkmm3 diff --git a/packaging/macos/150-jhbuild-inkdeps.sh b/packaging/macos/150-jhbuild-inkdeps.sh new file mode 100755 index 0000000..1de75d2 --- /dev/null +++ b/packaging/macos/150-jhbuild-inkdeps.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the build pipeline for Inkscape on macOS. +# +# ### 150-jhbuild-inkdeps.sh ### +# Install additional dependencies into our jhbuild environment required for +# building Inkscape. + +### load settings and functions ################################################ + +SELF_DIR=$(F=$0; while [ ! -z $(readlink $F) ] && F=$(readlink $F); cd $(dirname $F); F=$(basename $F); [ -L $F ]; do :; done; echo $(pwd -P)) +for script in $SELF_DIR/0??-*.sh; do source $script; done + +### install Inkscape dependencies ############################################## + +# Part of gtk-osx module sets. + +jhbuild build \ + libsoup + +# Part of inkscape module set. + +jhbuild build \ + boehm_gc \ + double_conversion \ + gdl \ + ghostscript \ + google_test \ + gsl \ + gtkspell3 \ + imagemagick \ + libcdr \ + openjpeg \ + openmp \ + poppler \ + potrace diff --git a/packaging/macos/160-jhbuild-other.sh b/packaging/macos/160-jhbuild-other.sh new file mode 100755 index 0000000..cb54da7 --- /dev/null +++ b/packaging/macos/160-jhbuild-other.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the build pipeline for Inkscape on macOS. +# +# ### 160-jhbuild-other.sh ### +# Install additional components that are not direct dependencies, like tools +# required for packaging. + +### load settings and functions ################################################ + +SELF_DIR=$(F=$0; while [ ! -z $(readlink $F) ] && F=$(readlink $F); cd $(dirname $F); F=$(basename $F); [ -L $F ]; do :; done; echo $(pwd -P)) +for script in $SELF_DIR/0??-*.sh; do source $script; done + +set -e -o errtrace +trap 'catch_error "$SELF_NAME" "$LINENO" "$FUNCNAME" "${BASH_COMMAND}" "${?}"' ERR + +### install disk image creator ################################################# + +jhbuild run pip3 install $PYTHON_DMGBUILD + +### download icon for disk image ############################################### + +# dmgbuild offers to generate a badged version of the disk image icon, but +# it doesn't work and I have not investigated yet. We use a pre-made image +# for now. + +save_file $URL_INKSCAPE_DMG_ICNS + +### install gtk-mac-bundler #################################################### + +( + export GMB_BINDIR=$BIN_DIR + + install_source $URL_GTK_MAC_BUNDLER + jhbuild run make install +) + +### install svg to png convertor ############################################### + +jhbuild run pip3 install $PYTHON_CAIROSVG +jhbuild run pip3 install $PYTHON_CAIROCFFI + +### install png to icns converter ############################################## + +install_source $URL_PNG2ICNS +ln -s $(pwd)/png2icns.sh $BIN_DIR + +### downlaod a pre-built Python.framework ###################################### + +# This will be bundled with the application. + +save_file $URL_PYTHON + +### install compiler cache ##################################################### + +jhbuild build ccache + +################################################################################ + +# vim: expandtab:shiftwidth=2:tabstop=2:softtabstop=2 : diff --git a/packaging/macos/210-inkscape-build.sh b/packaging/macos/210-inkscape-build.sh new file mode 100755 index 0000000..5f6f61e --- /dev/null +++ b/packaging/macos/210-inkscape-build.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the build pipeline for Inkscape on macOS. +# +# ### 210-inkscape-build.sh ### +# Build Inscape. + +### load settings and functions ################################################ + +SELF_DIR=$(F=$0; while [ ! -z $(readlink $F) ] && F=$(readlink $F); cd $(dirname $F); F=$(basename $F); [ -L $F ]; do :; done; echo $(pwd -P)) +for script in $SELF_DIR/0??-*.sh; do source $script; done + +set -e -o errtrace +trap 'catch_error "$SELF_NAME" "$LINENO" "$FUNCNAME" "${BASH_COMMAND}" "${?}"' ERR + +### build Inkscape ############################################################# + +if [ -z $CI_JOB_ID ]; then # running standalone + git clone --recurse-submodules --depth 10 $URL_INKSCAPE $INK_DIR +fi + +[ -d $INK_DIR.build ] && rm -rf $INK_DIR.build || true # cleanup previous run + +mkdir -p $INK_DIR.build +cd $INK_DIR.build + +# about the '-DOpenMP_*' arguments: +# All the settings for OpenMP are to trigger the detection during 'cmake'. +# Experimenting with a "Hello World"-style example shows that linking with +# '-lomp' would suffice, no '-fopenmp' required. +# TODO further investigation into required flags + +cmake \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DCMAKE_PREFIX_PATH=$OPT_DIR \ + -DCMAKE_INSTALL_PREFIX=$OPT_DIR \ + -DOpenMP_CXX_FLAGS="-Xclang -fopenmp" \ + -DOpenMP_C_FLAGS="-Xclang -fopenmp" \ + -DOpenMP_CXX_LIB_NAMES="omp" \ + -DOpenMP_C_LIB_NAMES="omp" \ + -DOpenMP_omp_LIBRARY=$LIB_DIR/libomp.dylib \ + $INK_DIR + +make +make install +make tests + +### patch Poppler library locations ############################################ + +relocate_dependency $LIB_DIR/libpoppler.94.dylib $BIN_DIR/inkscape +relocate_dependency $LIB_DIR/libpoppler-glib.8.dylib $BIN_DIR/inkscape +relocate_dependency $LIB_DIR/libpoppler.94.dylib $LIB_DIR/inkscape/libinkscape_base.dylib +relocate_dependency $LIB_DIR/libpoppler-glib.8.dylib $LIB_DIR/inkscape/libinkscape_base.dylib + +### patch OpenMP library locations ############################################# + +relocate_dependency $LIB_DIR/libomp.dylib $BIN_DIR/inkscape +relocate_dependency $LIB_DIR/libomp.dylib $LIB_DIR/inkscape/libinkscape_base.dylib diff --git a/packaging/macos/220-inkscape-package.sh b/packaging/macos/220-inkscape-package.sh new file mode 100755 index 0000000..903bcf9 --- /dev/null +++ b/packaging/macos/220-inkscape-package.sh @@ -0,0 +1,175 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the build pipeline for Inkscape on macOS. +# +# ### 220-inkscape-package.sh ### +# Create Inkscape application bundle. + +### load settings and functions ################################################ + +SELF_DIR=$(F=$0; while [ ! -z $(readlink $F) ] && F=$(readlink $F); cd $(dirname $F); F=$(basename $F); [ -L $F ]; do :; done; echo $(pwd -P)) +for script in $SELF_DIR/0??-*.sh; do source $script; done + +set -e -o errtrace +trap 'catch_error "$SELF_NAME" "$LINENO" "$FUNCNAME" "${BASH_COMMAND}" "${?}"' ERR + +### create application bundle ################################################## + +mkdir -p $ARTIFACT_DIR + +( # use subshell to fence temporary variables + + BUILD_DIR=$SRC_DIR/gtk-mac-bundler.build + mkdir -p $BUILD_DIR + + cp $SELF_DIR/inkscape.bundle $BUILD_DIR + cp $SELF_DIR/inkscape.plist $BUILD_DIR + + export ARTIFACT_DIR # referenced in inkscape.bundle + cd $BUILD_DIR + jhbuild run gtk-mac-bundler inkscape.bundle +) + +# Rename to get from lowercase to capitalized "i". This works only on +# case-insensitive filesystems (default on macOS). + +mv $APP_DIR $APP_DIR.tmp +mv $APP_DIR.tmp $APP_DIR + +# Patch library link paths. + +relocate_dependency @executable_path/../Resources/lib/inkscape/libinkscape_base.dylib $APP_EXE_DIR/inkscape + +relocate_dependency @loader_path/../libpoppler.94.dylib $APP_LIB_DIR/inkscape/libinkscape_base.dylib +relocate_dependency @loader_path/../libpoppler-glib.8.dylib $APP_LIB_DIR/inkscape/libinkscape_base.dylib + +relocate_neighbouring_libs $APP_LIB_DIR + +# update Inkscape version information +/usr/libexec/PlistBuddy -c "Set CFBundleShortVersionString '$(get_inkscape_version) ($(get_repo_version $INK_DIR))'" $APP_PLIST +/usr/libexec/PlistBuddy -c "Set CFBundleVersion '$(get_inkscape_version) ($(get_repo_version $INK_DIR))'" $APP_PLIST + +# update minimum system version according to deployment target +/usr/libexec/PlistBuddy -c "Set LSMinimumSystemVersion '$SDK_VERSION'" $APP_PLIST + +### generate application icon ################################################## + +# svg to png + +( + export DYLD_FALLBACK_LIBRARY_PATH=$LIB_DIR + jhbuild run cairosvg -f png -s 8 -o $SRC_DIR/inkscape.png $INK_DIR/share/branding/inkscape.svg +) + +# png to icns + +cd $SRC_DIR # png2icns.sh outputs to current directory +png2icns.sh inkscape.png +mv inkscape.icns $APP_RES_DIR + +### bundle Python.framework #################################################### + +# This section deals with bundling Python.framework into the application. + +mkdir $APP_FRA_DIR +install_source file://$SRC_DIR/$(basename $URL_PYTHON) $APP_FRA_DIR --exclude="Versions/$PY3_MAJOR.$PY3_MINOR/lib/python$PY3_MAJOR.$PY3_MINOR/test/"'*' + +# link it to $APP_BIN_DIR so it'll be in $PATH for the app +ln -sf ../../Frameworks/Python.framework/Versions/Current/bin/python$PY3_MAJOR $APP_BIN_DIR + +# create '.pth' file inside Framework to include our site-packages directory +echo "./../../../../../../../Resources/lib/python$PY3_MAJOR.$PY3_MINOR/site-packages" > $APP_FRA_DIR/Python.framework/Versions/Current/lib/python$PY3_MAJOR.$PY3_MINOR/site-packages/inkscape.pth + +### install Python package: lxml ############################################### + +pip_install $PYTHON_LXML + +# patch 'etree' +relocate_dependency @loader_path/../../../libxml2.2.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/lxml/etree.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libz.1.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/lxml/etree.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libxslt.1.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/lxml/etree.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libexslt.0.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/lxml/etree.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +# patch 'objectify' +relocate_dependency @loader_path/../../../libxml2.2.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/lxml/objectify.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libz.1.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/lxml/objectify.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libxslt.1.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/lxml/objectify.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libexslt.0.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/lxml/objectify.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so + +### install Python package: NumPy ############################################## + +pip_install $PYTHON_NUMPY + +### install Python package: PyGObject ########################################## + +pip_install $PYTHON_PYGOBJECT + +# patch '_gi' +relocate_dependency @loader_path/../../../libglib-2.0.0.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/gi/_gi.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libintl.8.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/gi/_gi.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libgio-2.0.0.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/gi/_gi.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libgobject-2.0.0.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/gi/_gi.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libgirepository-1.0.1.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/gi/_gi.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libffi.7.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/gi/_gi.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so + +# patch '_gi_cairo' +relocate_dependency @loader_path/../../../libglib-2.0.0.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/gi/_gi_cairo.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libintl.8.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/gi/_gi_cairo.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libgio-2.0.0.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/gi/_gi_cairo.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libgobject-2.0.0.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/gi/_gi_cairo.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libgirepository-1.0.1.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/gi/_gi_cairo.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libffi.7.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/gi/_gi_cairo.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libcairo.2.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/gi/_gi_cairo.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so +relocate_dependency @loader_path/../../../libcairo-gobject.2.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/gi/_gi_cairo.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so + +### install Python package: Pycairo ############################################ + +# This package got pulled in by PyGObject. + +# patch '_cairo' +relocate_dependency @loader_path/../../../libcairo.2.dylib $APP_LIB_DIR/python$PY3_MAJOR.$PY3_MINOR/site-packages/cairo/_cairo.cpython-$PY3_MAJOR${PY3_MINOR}-darwin.so + +### install Python package: pySerial ########################################### + +pip_install $PYTHON_PYSERIAL + +### install Python package: Scour ############################################## + +pip_install $PYTHON_SCOUR + +### precompile all Python packages ############################################# + +$APP_FRA_DIR/Python.framework/Versions/Current/bin/python$PY3_MAJOR -m compileall -f $APP_DIR || true + +### fontconfig ################################################################# + +# Mimic the behavior of having all files under 'share' and linking the +# active ones to 'etc'. +cd $APP_ETC_DIR/fonts/conf.d + +for file in ./*.conf; do + ln -sf ../../../share/fontconfig/conf.avail/$(basename $file) +done + +# Our customized version loses all the non-macOS paths and sets a cache +# directory below '$HOME/Library/Application Support/Inkscape'. +cp $SELF_DIR/fonts.conf $APP_ETC_DIR/fonts + +### Ghostscript ################################################################ + +relocate_dependency @executable_path/../lib/libfontconfig.1.dylib $APP_BIN_DIR/gs +relocate_dependency @executable_path/../lib/libfreetype.6.dylib $APP_BIN_DIR/gs + +### create GObject introspection repository #################################### + +mkdir $APP_LIB_DIR/girepository-1.0 + +# remove fully qualified paths from libraries in *.gir files +for gir in $OPT_DIR/share/gir-1.0/*.gir; do + sed "s/$(escape_sed $LIB_DIR/)//g" $gir > $SRC_DIR/$(basename $gir) +done + +# compile *.gir into *.typelib files +for gir in $SRC_DIR/*.gir; do + jhbuild run g-ir-compiler -o $APP_LIB_DIR/girepository-1.0/$(basename -s .gir $gir).typelib $gir +done diff --git a/packaging/macos/230-inkscape-distrib.sh b/packaging/macos/230-inkscape-distrib.sh new file mode 100755 index 0000000..f722444 --- /dev/null +++ b/packaging/macos/230-inkscape-distrib.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the build pipeline for Inkscape on macOS. +# +# ### 230-inkscape-distrib.sh ### +# Get application ready for distribution. + +### load settings and functions ################################################ + +SELF_DIR=$(F=$0; while [ ! -z $(readlink $F) ] && F=$(readlink $F); cd $(dirname $F); F=$(basename $F); [ -L $F ]; do :; done; echo $(pwd -P)) +for script in $SELF_DIR/0??-*.sh; do source $script; done + +set -o errtrace +trap 'catch_error "$SELF_NAME" "$LINENO" "$FUNCNAME" "${BASH_COMMAND}" "${?}"' ERR + +### create disk image for distribution ######################################### + +# Create background for development snapshots. This is not meant for +# official releases, those will be re-packaged manually (they also need +# to be signed and notarized). + +convert -size 560x400 xc:transparent \ + -font Andale-Mono -pointsize 64 -fill black \ + -draw "text 20,60 'Inkscape'" \ + -draw "text 20,120 '$(get_inkscape_version)'" \ + -draw "text 20,180 'development'" \ + -draw "text 20,240 'snapshot'" \ + -draw "text 20,300 '$(get_repo_version $INK_DIR)'" \ + $SRC_DIR/inkscape_dmg.png + +# create the disk image + +# Due to an undiagnosed instability that only occurs during CI runs (not when +# run interactively from the terminal), the following code will be put into +# a separate script and be executed via Terminal.app. +# See: https://github.com/al45tair/dmgbuild/pull/11 + +cp $SELF_DIR/inkscape_dmg.py $SRC_DIR + +create_dmg $ARTIFACT_DIR/Inkscape.app $TMP_DIR/Inkscape.dmg $SRC_DIR/inkscape_dmg.py + +rm -rf $APP_DIR +mv $TMP_DIR/Inkscape.dmg $ARTIFACT_DIR + +# CI: move disk image to a location accessible for the runner + +if [ ! -z $CI_JOB_ID ]; then + [ -d $INK_DIR/artifacts ] && rm -rf $INK_DIR/artifacts + mv $ARTIFACT_DIR $INK_DIR/artifacts +fi diff --git a/packaging/macos/README.md b/packaging/macos/README.md new file mode 100644 index 0000000..fa119c8 --- /dev/null +++ b/packaging/macos/README.md @@ -0,0 +1,106 @@ +# macOS build pipeline + +This folder contains the scripts that make up the build pipeline for Inkscape on macOS. + +## Usage + +### Requirements + +ℹ️ _The following is bound to change as development progresses and I won't deny that there's usually more than one way to do something, but I can only support what I use myself. So feel free to experiment and deviate, but know that __it is dangerous to go alone! Take this 🗡️.___ + +- A __clean environment__ is key. + - Make sure there are no remnants from other build environments (e.g. MacPorts, Fink, Homebrew) on your system. + - Rule of thumb: clear out `/usr/local`. + - Use a dedicated user account to avoid any interference with the environment (e.g. no custom settings in `.profile`, `.bashrc`, etc.). + +- There are __version recommendations__. + - macOS Catalina 10.15.6 + - Xcode 11.6 + - OS X El Capitan 10.11 SDK from Xcode 7.3.1 (expected in `/opt/sdks/MacOSX10.11.sdk`) + +- A somewhat decent __internet connection__ for all the downloads. + +### Building the toolset + +ℹ️ _If you only want to build Inkscape and not the complete toolset, skip ahead to the next section!_ + +1. Clone this repository and `cd` into `packaging/macos`. + + ```bash + git clone --depth 1 https://gitlab.com/inkscape/inkscape + cd inkscape/packaging/macos + ``` + +2. Specify a folder where all the action is going to take place. (Please avoid spaces in paths!) + + ```bash + echo "TOOLSET_ROOT_DIR=$HOME/my_build_dir" > 015-customdir.sh + ``` + +3. Build the toolset. + + ```bash + ./build_toolset.sh + ``` + +4. ☕ (Time to get a beverage - this will take a while!) + +### Installing a pre-compiled toolset + +ℹ️ _If you built the toolset yourself, skip ahead to the next section!_ + +ℹ️ _Using `/Users/Shared/work` as `TOOLSET_ROOT_DIR` is mandatory! (This is the default.)_ + +1. Clone this repository and `cd` into it. + + ```bash + git clone --depth 1 https://gitlab.com/inkscape/inkscape + cd inkscape/packaging/macos + ``` + +2. Install the toolset. + + ```bash + ./install_toolset.sh + ``` + + This will + + - download a disk image (about 1.6 GiB) to `/Users/Shared/work/repo` + - mount the disk image to `/Users/Shared/work/$TOOLSET_VERSION` + - union-mount a ramdisk (2 GiB) to `/Users/Shared/work/$TOOLSET_VERSION` + + The mounted volumes won't show up in the Finder but you can see them using `diskutil`. Use `uninstall_toolset.sh` to eject them (this won't delete `repo` though). + +### Building Inkscape + +1. Build Inkscape. + + ```bash + ./build_inkscape.sh + ``` + + Ultimately this will produce `/Users/Shared/work/$TOOLSET_VERSION/artifacts/Inkscape.dmg`. + +## GitLab CI + +Make sure the runner fulfills the same requirements as listed in the usage section above. + +Configure a job in your `.gitlab-ci.yml` as follows: + +```yaml +buildmacos: + before_script: + - packaging/macos/install_toolset.sh + script: + - packaging/macos/build_inkscape.sh + after_script: + - packaging/macos/uninstall_toolset.sh + artifacts: + paths: + - artifacts/ +``` + +## Status + +This is based on [mibap](https://github.com/dehesselle/mibap) and still a work in progress. diff --git a/packaging/macos/build_inkscape.sh b/packaging/macos/build_inkscape.sh new file mode 100755 index 0000000..dc3139a --- /dev/null +++ b/packaging/macos/build_inkscape.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the build pipeline for Inkscape on macOS. +# +# ### build_inkscape.sh ### +# Compile and package Inkscape. + +### load settings and functions ################################################ + +SELF_DIR=$(F=$0; while [ ! -z $(readlink $F) ] && F=$(readlink $F); \ + cd $(dirname $F); F=$(basename $F); [ -L $F ]; do :; done; echo $(pwd -P)) +for script in $SELF_DIR/0??-*.sh; do source $script; done + +set -e + +### run scripts to compile and build Inkscape ################################## + +for script in $SELF_DIR/2??-*.sh; do + $script +done diff --git a/packaging/macos/build_toolset.sh b/packaging/macos/build_toolset.sh new file mode 100755 index 0000000..5bdb5ae --- /dev/null +++ b/packaging/macos/build_toolset.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the build pipeline for Inkscape on macOS. +# +# ### build_toolset.sh ### +# Create JHBuild toolset with all dependencies for Inkscape. + +### load settings and functions ################################################ + +SELF_DIR=$(F=$0; while [ ! -z $(readlink $F) ] && F=$(readlink $F); \ + cd $(dirname $F); F=$(basename $F); [ -L $F ]; do :; done; echo $(pwd -P)) +for script in $SELF_DIR/0??-*.sh; do source $script; done + +set -e + +### build toolset ############################################################## + +function build +{ + echo_info building toolset in $WRK_DIR + for script in $SELF_DIR/1??-*.sh; do + $script + done +} + +### remove some files ########################################################## + +# Our way of union-mounting a writable overlay ontop of a readonly filesystem +# introduces the additional challenge that paths cannot be written to if the +# parent path has not been written to (either a bug or a limitation, IDK). +# For most of the build system we work around that by re-creating the +# complete folder structure inside the writable overlay. In some cases +# we remove the paths causing problems. + +function remove_files +{ + rm -rf $TMP_DIR/wheels +} + +### main ####################################################################### + +build +remove_files diff --git a/packaging/macos/fonts.conf b/packaging/macos/fonts.conf new file mode 100644 index 0000000..364bd3b --- /dev/null +++ b/packaging/macos/fonts.conf @@ -0,0 +1,77 @@ +<?xml version="1.0"?> +<!DOCTYPE fontconfig SYSTEM "fonts.dtd"> +<!-- /etc/fonts/fonts.conf file to configure system font access --> +<fontconfig> + <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0"> + <its:translateRule translate="no" selector="/fontconfig/*[not(self::description)]"/> + </its:rules> + + <description>Default configuration file</description> + +<!-- + Usually you'll find the "DO NOT EDIT THIS FILE" warning here. + I removed it since I clearly edited this file. I removed the + non-macOS paths and configured the cachedir. + + Rene de Hesselle +--> + +<!-- Font directory list --> + + <dir>/System/Library/Fonts</dir> <dir>/Library/Fonts</dir> <dir>~/Library/Fonts</dir> +<!-- + Accept deprecated 'mono' alias, replacing it with 'monospace' +--> + <match target="pattern"> + <test qual="any" name="family"> + <string>mono</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>monospace</string> + </edit> + </match> + +<!-- + Accept alternate 'sans serif' spelling, replacing it with 'sans-serif' +--> + <match target="pattern"> + <test qual="any" name="family"> + <string>sans serif</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>sans-serif</string> + </edit> + </match> + +<!-- + Accept deprecated 'sans' alias, replacing it with 'sans-serif' +--> + <match target="pattern"> + <test qual="any" name="family"> + <string>sans</string> + </test> + <edit name="family" mode="assign" binding="same"> + <string>sans-serif</string> + </edit> + </match> + +<!-- + Load local system customization file +--> + <include ignore_missing="yes">conf.d</include> + +<!-- Font cache directory list --> + + <cachedir>~/Library/Application Support/Inkscape/cache/fontconfig</cachedir> + + <config> +<!-- + Rescan configuration every 30 seconds when FcFontSetList is called + --> + <rescan> + <int>30</int> + </rescan> + </config> + +</fontconfig> + diff --git a/packaging/macos/inkscape.bundle b/packaging/macos/inkscape.bundle new file mode 100644 index 0000000..5cc3752 --- /dev/null +++ b/packaging/macos/inkscape.bundle @@ -0,0 +1,165 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<app-bundle> + + <meta> + <!-- Where to pick up the GTK+ installation, icon themes, + etc. Note that "${env:JHBUILD_PREFIX}" is evaluated to the + value of the environment variable JHBUILD_PREFIX. You can + define additional prefixes and refer to them in paths + throughout this file on the form "${prefix:name}". This is + useful for installing certain libraries or even the + application itself separately. Note that JHBUILD_PREFIX is + defined by jhbuild, so it you are not using jhbuild you can + either define your own or just hardcode the path here. + --> + <prefix name="default">${env:JHBUILD_PREFIX}</prefix> + + <!-- The project directory is the default location of the created + app. If you leave out the path, the current directory is + used. Note the usage of an environment variable here again. + --> + <destination overwrite="yes">${env:ARTIFACT_DIR}</destination> + + <image> + <!-- Not implemented yet (DMG image). --> + </image> + + <!-- Comment this out to keep the install names in binaries --> + <run-install-name-tool/> + + <!-- Optionally specify a launcher script to use. If the + application sets up everything needed itself, like + environment variable, linker paths, etc, a launcher script is + not needed. If the source path is left out, the default + script will be used. + <launcher-script>${project}/gtk3-launcher.sh</launcher-script > + --> + + <!-- Not implemented: Optional runtime, could be python or mono + for example. + --> + <!-- runtime copy="yes">/usr/bin/python</runtime --> + <!-- Indicate the active gtk version to use. This is needed only + for gtk+-3.0 projects. --> + <gtk>gtk+-3.0</gtk> + </meta> + + <!-- The special macro "${project}" refers to the directory where + this bundle file is located. The application name and bundle + identifier are taken from the plist file. + --> + <plist>${project}/inkscape.plist</plist> + + <main-binary>${prefix}/bin/inkscape</main-binary> + + <!-- Copy in the input methods. Dunno if they actually work with + OSX. Note the ${gtkdir} macro, which expands to the correct + library subdirectory for the specified gtk version. --> + <binary> + ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/immodules/*.so + </binary> + +<!-- And the print backends --> + <binary> + ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/printbackends/*.so + </binary> + +<!-- Starting with 2.24, gdk-pixbuf installs into its own directory. --> + <binary> + ${prefix}/lib/gdk-pixbuf-2.0/${pkg:gdk-pixbuf-2.0:gdk_pixbuf_binary_version}/loaders/*.so + </binary> + +<!-- No longer needed for pango >= 1.38 + <binary> + ${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/ + </binary> +--> + <binary> + ${prefix}/lib/inkscape/libinkscape_base.dylib + </binary> + <binary> + ${prefix}/lib/libexslt.0.dylib + </binary> + <binary> + ${prefix}/lib/libssl.1.1.dylib + </binary> + <binary> + ${prefix}/lib/gio/modules/*.so + </binary> + <!-- GObject Introspection repository manager --> + <binary> + ${prefix}/lib/libgirepository-1.0.1.dylib + </binary> + <!-- Ghostscript --> + <binary> + ${prefix}/bin/gs + </binary> + <!-- Translation filenames, one for each program or library that you + want to copy in to the bundle. The "dest" attribute is + optional, as usual. Bundler will find all translations of that + library/program under the indicated directory and copy them.--> + <translations name="gdk-pixbuf"> + ${prefix}/share/locale + </translations> + <translations name="gdl-3"> + ${prefix}/share/locale + </translations> + <translations name="gtk30"> + ${prefix}/share/locale + </translations> + <translations name="gtk30-properties"> + ${prefix}/share/locale + </translations> + <translations name="inkscape"> + ${prefix}/share/locale + </translations> + + <!-- Data to copy in, usually Glade/UI files, images, sounds files + etc. The destination inside the bundle can be specified if the + files should end up at a different location, by using the + "dest" property. The destination must then start with the macro + "${bundle}", which refers to the bundle root directory. + --> + <!-- data> + ${prefix}/share/gtk3-demo + </data --> + + <data> + ${prefix}/etc/fonts + </data> + <data> + ${prefix}/share/fontconfig + </data> + <data> + ${prefix}/share/glib-2.0 + </data> + <data> + ${prefix}/share/icons + </data> + <data> + ${prefix}/share/ImageMagick-6 + </data> + <data> + ${prefix}/share/inkscape + </data> + <data> + ${prefix}/share/ghostscript + </data> + <data> + ${prefix}/bin/ps2pdf* + </data> + <!-- Copy in the themes data. You may want to trim this to save space + in your bundle. --> + <data> + ${prefix}/share/themes + </data> + + <!-- Copy icons. Note that the .icns file is an Apple format which + contains up to 4 sizes of icon. You can use + /Developer/Applications/Utilities/Icon Composer.app to import + artwork and create the file. > + <data dest="${bundle}/Contents/Resources"> + ${project}/Giggle.icns + </data --> + + </app-bundle> diff --git a/packaging/macos/inkscape.plist b/packaging/macos/inkscape.plist new file mode 100644 index 0000000..1931285 --- /dev/null +++ b/packaging/macos/inkscape.plist @@ -0,0 +1,565 @@ +<?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>English</string> + <key>CFBundleDocumentTypes</key> + <array> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>svg</string> + <string>SVG</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>image-svg+xml.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>image/svg+xml</string> + </array> + <key>CFBundleTypeName</key> + <string>Scalable Vector Graphics Image</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>SVG </string> + </array> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>LSHandlerRank</key> + <string>Owner</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>svgz</string> + <string>SVGZ</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>image-svg+xml-compressed.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>image/svg+xml-compressed</string> + </array> + <key>CFBundleTypeName</key> + <string>Compressed Scalable Vector Graphics Image</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>SVGZ</string> + </array> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>LSHandlerRank</key> + <string>Owner</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>eps</string> + <string>epsi</string> + <string>EPS</string> + <string>EPSI</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>image-x-eps.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/postscript</string> + <string>image/x-eps</string> + </array> + <key>CFBundleTypeName</key> + <string>PostScript Document</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>EPS </string> + <string>EPSI</string> + </array> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + <key>LSItemContentTypes</key> + <array> + <string>com.adobe.encapsulated-postscript</string> + </array> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>ps</string> + <string>PS</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>image-x-ps.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/postscript</string> + <string>image/x-ps</string> + </array> + <key>CFBundleTypeName</key> + <string>PostScript Document</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>PS </string> + </array> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + <key>LSItemContentTypes</key> + <array> + <string>com.adobe.postscript</string> + </array> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>ai</string> + <string>AI</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>application-illustrator.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/illustrator</string> + <string>application/pdf</string> + </array> + <key>CFBundleTypeName</key> + <string>Adobe Illustrator Document</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>AI </string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + <key>LSItemContentTypes</key> + <array> + <string>com.adobe.illustrator.ai-image</string> + </array> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>aisvg</string> + <string>AISVG</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>application-illustrator-svg.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/illustrator-svg</string> + </array> + <key>CFBundleTypeName</key> + <string>Adobe Illustrator SVG Document</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>AISVG</string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>wmf</string> + <string>WMF</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>image-vnd.windows-metafile.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>image/vnd.windows-metafile</string> + </array> + <key>CFBundleTypeName</key> + <string>Windows MetaFile</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>WMF </string> + </array> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>pdf</string> + <string>PDF</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>application-pdf.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/pdf</string> + </array> + <key>CFBundleTypeName</key> + <string>NSPDFPboardType</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>PDF </string> + </array> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + <key>LSItemContentTypes</key> + <array> + <string>com.adobe.pdf</string> + </array> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>ggr</string> + <string>GGR</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>application-gimp-gradient.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/x-gimp-gradient</string> + </array> + <key>CFBundleTypeName</key> + <string>Gimp Gradient</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + <key>LSItemContentTypes</key> + <array> + <string>org.gimp.ggr</string> + </array> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>ccx</string> + <string>CCX</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>application-vnd.corel-draw-compressed.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/vnd.corel-draw-compressed</string> + </array> + <key>CFBundleTypeName</key> + <string>Corel Draw Compressed Document</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>CCX </string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>cdt</string> + <string>CDT</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>application-vnd.corel-draw-template.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/vnd.corel-draw-template</string> + </array> + <key>CFBundleTypeName</key> + <string>Corel Draw Template</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>CDT </string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>cdr</string> + <string>CDR</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>application-vnd.corel-draw.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/vnd.corel-draw</string> + </array> + <key>CFBundleTypeName</key> + <string>Corel Draw Compressed Document</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>CDR </string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>xaml</string> + <string>XAML</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>application-vnd.ms.xaml.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/vnd.ms.xaml</string> + </array> + <key>CFBundleTypeName</key> + <string>Extensible Application Markup Language (XAML)</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>XAML</string> + </array> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>dxf</string> + <string>DXF</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>image-vnd.dxf.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>image/vnd.dxf</string> + </array> + <key>CFBundleTypeName</key> + <string>AutoCAD Document</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>DXF </string> + </array> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>sk1</string> + <string>SK1</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>image-vnd.sk1.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>image/vnd.sk1</string> + </array> + <key>CFBundleTypeName</key> + <string>Sketch Document</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>SK1 </string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>wpg</string> + <string>WPG</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>application-vnd.wordperfect-graphic.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/vnd.wordperfect-graphic</string> + <string>image/x-wpg</string> + </array> + <key>CFBundleTypeName</key> + <string>WordPerfect Graphics</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>WPG </string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>emf</string> + <string>EMF</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>Inkscape-Generic.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>image/emf</string> + </array> + <key>CFBundleTypeName</key> + <string>Windows Enhanced Metafile document</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>EMF </string> + </array> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>vsd</string> + <string>VSD</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>Inkscape-Generic.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/vnd.visio</string> + </array> + <key>CFBundleTypeName</key> + <string>Microsoft Visio Diagram</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>vdx</string> + <string>VDX</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>Inkscape-Generic.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/vnd.visio</string> + </array> + <key>CFBundleTypeName</key> + <string>Microsoft Visio XML Diagram</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>vsdm</string> + <string>VSDM</string> + <string>vsdx</string> + <string>VSDX</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>Inkscape-Generic.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/vnd.visio</string> + </array> + <key>CFBundleTypeName</key> + <string>Microsoft Visio 2013 drawing</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>plt</string> + <string>PLT</string> + <string>hpgl</string> + <string>hpgl</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>Inkscape-Generic.icons</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/vnd.hp-HPGL</string> + <string>image/hpgl</string> + <string>image/plt</string> + <string>image/x-plt</string> + </array> + <key>CFBundleTypeName</key> + <string>HP Graphics Language file</string> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>LSHandlerRank</key> + <string>Alternate</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>png</string> + <string>PNG</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>Inkscape-Generic.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>image/png</string> + </array> + <key>CFBundleTypeName</key> + <string>Portable Network Graphics Image</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>PNGf</string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSHandlerRank</key> + <string>None</string> + </dict> + </array> + <key>CFBundleExecutable</key> + <string>inkscape</string> + <key>CFBundleName</key> + <string>Inkscape</string> + <key>CFBundleIconFile</key> + <string>inkscape.icns</string> + <key>CFBundleIdentifier</key> + <string>org.inkscape.Inkscape</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>CFBundleShortVersionString</string> + <key>CFBundleSignature</key> + <string>Inks</string> + <key>CFBundleVersion</key> + <string>CFBundleVersion</string> + <key>NSHumanReadableCopyright</key> + <string>Copyright © 2020 Inkscape Developers, GNU General Public License.</string> + <key>LSApplicationCategoryType</key> + <string>public.app-category.graphics-design</string> + <key>LSMinimumSystemVersion</key> + <string>LSMinimumSystemVersion</string> + <key>NSDesktopFolderUsageDescription</key> + <string>Inkscape needs your permission to access the Desktop folder.</string> + <key>NSDocumentsFolderUsageDescription</key> + <string>Inkscape needs your permission to access the Documents folder.</string> + <key>NSDownloadsFolderUsageDescription</key> + <string>Inkscape needs your permission to access the Downloads folder.</string> + <key>NSRemoveableVolumesUsageDescription</key> + <string>Inkscape needs your permission to access removable volumes.</string> + <key>NSHighResolutionCapable</key> + <true/> + <key>NSRequiresAquaSystemAppearance</key> + <false/> + </dict> +</plist> diff --git a/packaging/macos/inkscape_dmg.py b/packaging/macos/inkscape_dmg.py new file mode 100644 index 0000000..266e27b --- /dev/null +++ b/packaging/macos/inkscape_dmg.py @@ -0,0 +1,246 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import biplist +import os.path + +# +# Example settings file for dmgbuild +# + +# Use like this: dmgbuild -s settings.py "Test Volume" test.dmg + +# You can actually use this file for your own application (not just TextEdit) +# by doing e.g. +# +# dmgbuild -s settings.py -D app=/path/to/My.app "My Application" MyApp.dmg + +# .. Useful stuff .............................................................. + +application = defines.get('app', 'PLACEHOLDERAPPLICATION') +appname = os.path.basename(application) + +def icon_from_app(app_path): + plist_path = os.path.join(app_path, 'Contents', 'Info.plist') + plist = biplist.readPlist(plist_path) + icon_name = plist['CFBundleIconFile'] + icon_root,icon_ext = os.path.splitext(icon_name) + if not icon_ext: + icon_ext = '.icns' + icon_name = icon_root + icon_ext + return os.path.join(app_path, 'Contents', 'Resources', icon_name) + +# .. Basics .................................................................... + +# Uncomment to override the output filename +# filename = 'test.dmg' + +# Uncomment to override the output volume name +# volume_name = 'Test' + +# Volume format (see hdiutil create -help) +format = defines.get('format', 'UDBZ') + +# Volume size +size = defines.get('size', None) + +# Files to include +files = [ application ] + +# Symlinks to create +#symlinks = { 'Applications': '/Applications' } + +# Volume icon +# +# You can either define icon, in which case that icon file will be copied to the +# image, *or* you can define badge_icon, in which case the icon file you specify +# will be used to badge the system's Removable Disk icon +# +icon = 'PLACEHOLDERICON' +#badge_icon = icon_from_app(application) + +# Where to put the icons +icon_locations = { + appname: (390, 240), +# 'Applications': (500, 120) + } + +# .. Window configuration ...................................................... + +# Background +# +# This is a STRING containing any of the following: +# +# #3344ff - web-style RGB color +# #34f - web-style RGB color, short form (#34f == #3344ff) +# rgb(1,0,0) - RGB color, each value is between 0 and 1 +# hsl(120,1,.5) - HSL (hue saturation lightness) color +# hwb(300,0,0) - HWB (hue whiteness blackness) color +# cmyk(0,1,0,0) - CMYK color +# goldenrod - X11/SVG named color +# builtin-arrow - A simple built-in background with a blue arrow +# /foo/bar/baz.png - The path to an image file +# +# The hue component in hsl() and hwb() may include a unit; it defaults to +# degrees ('deg'), but also supports radians ('rad') and gradians ('grad' +# or 'gon'). +# +# Other color components may be expressed either in the range 0 to 1, or +# as percentages (e.g. 60% is equivalent to 0.6). +background = 'PLACEHOLDERBACKGROUND' + +show_status_bar = False +show_tab_view = False +show_toolbar = False +show_pathbar = False +show_sidebar = False +sidebar_width = 180 + +# Window position in ((x, y), (w, h)) format +window_rect = ((100, 100), (500, 380)) + +# Select the default view; must be one of +# +# 'icon-view' +# 'list-view' +# 'column-view' +# 'coverflow' +# +default_view = 'icon-view' + +# General view configuration +show_icon_preview = False + +# Set these to True to force inclusion of icon/list view settings (otherwise +# we only include settings for the default view) +include_icon_view_settings = 'auto' +include_list_view_settings = 'auto' + +# .. Icon view configuration ................................................... + +arrange_by = None +grid_offset = (0, 0) +grid_spacing = 100 +scroll_position = (0, 0) +label_pos = 'bottom' # or 'right' +text_size = 12 +icon_size = 64 + +# .. List view configuration ................................................... + +# Column names are as follows: +# +# name +# date-modified +# date-created +# date-added +# date-last-opened +# size +# kind +# label +# version +# comments +# +list_icon_size = 16 +list_text_size = 12 +list_scroll_position = (0, 0) +list_sort_by = 'name' +list_use_relative_dates = True +list_calculate_all_sizes = False, +list_columns = ('name', 'date-modified', 'size', 'kind', 'date-added') +list_column_widths = { + 'name': 300, + 'date-modified': 181, + 'date-created': 181, + 'date-added': 181, + 'date-last-opened': 181, + 'size': 97, + 'kind': 115, + 'label': 100, + 'version': 75, + 'comments': 300, + } +list_column_sort_directions = { + 'name': 'ascending', + 'date-modified': 'descending', + 'date-created': 'descending', + 'date-added': 'descending', + 'date-last-opened': 'descending', + 'size': 'descending', + 'kind': 'ascending', + 'label': 'ascending', + 'version': 'ascending', + 'comments': 'ascending', + } + +# .. License configuration ..................................................... + +# Text in the license configuration is stored in the resources, which means +# it gets stored in a legacy Mac encoding according to the language. dmgbuild +# will *try* to convert Unicode strings to the appropriate encoding, *but* +# you should be aware that Python doesn't support all of the necessary encodings; +# in many cases you will need to encode the text yourself and use byte strings +# instead here. + +# Recognized language names are: +# +# af_ZA, ar, be_BY, bg_BG, bn, bo, br, ca_ES, cs_CZ, cy, da_DK, de_AT, de_CH, +# de_DE, dz_BT, el_CY, el_GR, en_AU, en_CA, en_GB, en_IE, en_SG, en_US, eo, +# es_419, es_ES, et_EE, fa_IR, fi_FI, fo_FO, fr_001, fr_BE, fr_CA, fr_CH, +# fr_FR, ga-Latg_IE, ga_IE, gd, grc, gu_IN, gv, he_IL, hi_IN, hr_HR, hu_HU, +# hy_AM, is_IS, it_CH, it_IT, iu_CA, ja_JP, ka_GE, kl, ko_KR, lt_LT, lv_LV, +# mk_MK, mr_IN, mt_MT, nb_NO, ne_NP, nl_BE, nl_NL, nn_NO, pa, pl_PL, pt_BR, +# pt_PT, ro_RO, ru_RU, se, sk_SK, sl_SI, sr_RS, sv_SE, th_TH, to_TO, tr_TR, +# uk_UA, ur_IN, ur_PK, uz_UZ, vi_VN, zh_CN, zh_TW + +# license = { +# 'default-language': 'en_US', +# 'licenses': { +# # For each language, the text of the license. This can be plain text, +# # RTF (in which case it must start "{\rtf1"), or a path to a file +# # containing the license text. If you're using RTF, +# # watch out for Python escaping (or read it from a file). +# 'English': b'''{\\rtf1\\ansi\\ansicpg1252\\cocoartf1504\\cocoasubrtf820 +# {\\fonttbl\\f0\\fnil\\fcharset0 Helvetica-Bold;\\f1\\fnil\\fcharset0 Helvetica;} +# {\\colortbl;\\red255\\green255\\blue255;\\red0\\green0\\blue0;} +# {\\*\\expandedcolortbl;;\\cssrgb\\c0\\c0\\c0;} +# \\paperw11905\\paperh16837\\margl1133\\margr1133\\margb1133\\margt1133 +# \\deftab720 +# \\pard\\pardeftab720\\sa160\\partightenfactor0 + +# \\f0\\b\\fs60 \\cf2 \\expnd0\\expndtw0\\kerning0 +# \\up0 \\nosupersub \\ulnone \\outl0\\strokewidth0 \\strokec2 Test License\\ +# \\pard\\pardeftab720\\sa160\\partightenfactor0 + +# \\fs36 \\cf2 \\strokec2 What is this?\\ +# \\pard\\pardeftab720\\sa160\\partightenfactor0 + +# \\f1\\b0\\fs22 \\cf2 \\strokec2 This is the English license. It says what you are allowed to do with this software.\\ +# \\ +# }''', +# }, +# 'buttons': { +# # For each language, text for the buttons on the licensing window. +# # +# # Default buttons and text are built-in for the following languages: +# # +# # English (en_US), German (de_DE), Spanish (es_ES), French (fr_FR), +# # Italian (it_IT), Japanese (ja_JP), Dutch (nl_NL), Swedish (sv_SE), +# # Brazilian Portuguese (pt_BR), Simplified Chinese (zh_CN), +# # Traditional Chinese (zh_TW), Danish (da_DK), Finnish (fi_FI), +# # Korean (ko_KR), Norwegian (nb_NO) +# # +# # You don't need to specify them for those languages; if you fail to +# # specify them for some other language, English will be used instead. + +# 'en_US': ( +# b'English', +# b'Agree', +# b'Disagree', +# b'Print', +# b'Save', +# b'If you agree with the terms of this license, press "Agree" to ' +# b'install the software. If you do not agree, press "Disagree".' +# ), +# }, +# } diff --git a/packaging/macos/install_toolset.sh b/packaging/macos/install_toolset.sh new file mode 100755 index 0000000..5b4259a --- /dev/null +++ b/packaging/macos/install_toolset.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the build pipeline for Inkscape on macOS. +# +# ### install_toolset.sh ### +# Install a pre-compiled version of the JHBuild toolset and required +# dependencies for Inkscape. + +### load settings and functions ################################################ + +SELF_DIR=$(F=$0; while [ ! -z $(readlink $F) ] && F=$(readlink $F); \ + cd $(dirname $F); F=$(basename $F); [ -L $F ]; do :; done; echo $(pwd -P)) +for script in $SELF_DIR/0??-*.sh; do source $script; done + +set -e + +### install toolset ############################################################ + +function install +{ + local toolset_dmg=$TOOLSET_REPO_DIR/$(basename $URL_TOOLSET) + + if [ -f $toolset_dmg ]; then + echo_info "no download required" + else + # File not present on disk, we need to download. + echo_act "download required" + save_file $URL_TOOLSET $TOOLSET_REPO_DIR + echo_ok "download successful" + fi + + # mount build system read-only + local device=$(create_dmg_device $toolset_dmg) + [ ! -d $WRK_DIR ] && mkdir -p $WRK_DIR + mount -o nobrowse,noowners,ro -t hfs $device $WRK_DIR + echo_ok "toolset mounted as $device" + + # Sadly, there are some limitations involved with union-mounting: + # - Files are not visible to 'ls'. + # - You cannot write in a location without having written to its + # parent location. That's why we need to pre-create all directories + # below. + # + # Shadow-mounting a dmg is not a feasible alternative due to its + # bad write-performance. + + # prepare a script for mass-creating directories + find $OPT_DIR -type d ! -path "$TMP_DIR/*" ! -path "$SRC_DIR/*" \ + -exec echo "mkdir {}" > $TOOLSET_ROOT_DIR/create_dirs.sh \; + chmod 755 $TOOLSET_ROOT_DIR/create_dirs.sh + + # create writable (ramdisk-) overlay + device=$(create_ram_device $OVERLAY_RAMDISK_SIZE build) + mount -o nobrowse,rw,union -t hfs $device $WRK_DIR + echo_ok "writable ramdisk overlay mounted as $device" + + # create all directories inside overlay + $TOOLSET_ROOT_DIR/create_dirs.sh + rm $TOOLSET_ROOT_DIR/create_dirs.sh +} + +### main ####################################################################### + +$SELF_DIR/110-sysprep.sh +install diff --git a/packaging/macos/uninstall_toolset.sh b/packaging/macos/uninstall_toolset.sh new file mode 100755 index 0000000..ba92577 --- /dev/null +++ b/packaging/macos/uninstall_toolset.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This file is part of the build pipeline for Inkscape on macOS. +# +# ### uninstall_toolset.sh ### +# Uninstall a previously installed toolset. In this case, "uninstall" means +# "unmount", the downloaded .dmg won't be deleted. + +### load settings and functions ################################################ + +SELF_DIR=$(F=$0; while [ ! -z $(readlink $F) ] && F=$(readlink $F); \ + cd $(dirname $F); F=$(basename $F); [ -L $F ]; do :; done; echo $(pwd -P)) +for script in $SELF_DIR/0??-*.sh; do source $script; done + +set -e + +### uninstall toolset ########################################################## + +function uninstall +{ + while : ; do # unmount everything (in reverse order) + local disk=$(mount | grep $WRK_DIR | tail -n1 | awk '{ print $1 }') + + if [ ${#disk} -eq 0 ]; then + break # nothing to do here + else + diskutil eject $disk > /dev/null # unmount + echo_ok "ejected $disk" + fi + done +} + +### main ####################################################################### + +uninstall |