]> git.xonotic.org Git - xonotic/netradiant.git/commitdiff
bundle: bundle macos binaries (no .app file done yet)
authorThomas Debesse <dev@illwieckz.net>
Tue, 22 Dec 2020 17:37:36 +0000 (18:37 +0100)
committerThomas Debesse <dev@illwieckz.net>
Tue, 22 Dec 2020 22:53:06 +0000 (23:53 +0100)
CMakeLists.txt
bundle/CMakeLists.txt
library-bundler

index 3d78aa4798637c8569142ff466982ac1acd3885b..05ba8a3fcbd90e79f142d6709e5a62a603c5626b 100644 (file)
@@ -273,7 +273,7 @@ if (BUILD_BINARIES)
     include_directories("${PROJECT_SOURCE_DIR}/include")
     include_directories("${PROJECT_SOURCE_DIR}/libs")
 
-    if (WIN32 OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
+    if (WIN32 OR APPLE OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
         set(BUNDLING_SUPPORTED ON)
     endif()
 
index 1ab7609c6c9151249b4ce8f1b17b43c972c483b1..73750b7031e222b09e9ffbb96ea330794925df53 100644 (file)
@@ -1,6 +1,8 @@
 if (WIN32)
     set(BUNDLE_OS_NAME "windows")
-       set(BUNDLE_SHARE ON)
+    set(BUNDLE_SHARE ON)
+elseif (APPLE)
+    set(BUNDLE_OS_NAME "macos")
 elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
     set(BUNDLE_OS_NAME "linux")
 else ()
index 1a3389c9dc0aab23f4f80b5bcc0b7d74f8ae735b..9a48a626cdda0f9da6bf20a113499b18df2c2342 100755 (executable)
@@ -5,6 +5,28 @@ set -e
 export LANG='C.UTF-8'
 export LANGUAGE="${LANG}"
 
+_sed () {
+       case "${system_name}" in
+               'macos')
+                       gsed "${@}"
+                       ;;
+               *)
+                       sed "${@}"
+                       ;;
+       esac
+}
+
+_cpr () {
+       case "${system_name}" in
+               'macos')
+                       cp -R ${@}
+                       ;;
+               *)
+                       cp -R --preserve=timestamps ${@}
+                       ;;
+       esac
+}
+
 Common::noOp () {
        true
 }
@@ -30,15 +52,29 @@ Common::getPath () {
                        printf '%s\n' "${file_path}"
                fi
        fi \
-       | sed -e 's|/*$||'
+       | _sed -e 's|/*$||'
 }
 
 Common::grepLdd () {
-       egrep ' => '
+       case "${system_name}" in
+               'macos')
+                       egrep '^\t/'
+                       ;;
+               *)
+                       egrep ' => '
+                       ;;
+       esac
 }
 
 Common::stripLdd () {
-       sed -e 's/ (0x[0-9a-f]*)$//;s/^.* => //'
+       case "${system_name}" in
+               'macos')
+                       _sed -e 's/^\t\(.*\) (compatibility version .*/\1/'
+                       ;;
+               *)
+                       _sed -e 's/ (0x[0-9a-f]*)$//;s/^.* => //'
+                       ;;
+       esac
 }
 
 Multi::excludeLdd () {
@@ -75,6 +111,9 @@ Multi::excludeLdd () {
                'windows')
                        egrep -i '\.dll => [A-Z]:\\msys64\\'
                        ;;
+               'macos')
+                       egrep -v '^\t/System/|^\t/usr/lib/'
+                       ;;
        esac
 }
 
@@ -95,6 +134,8 @@ Multi::printLdd () {
                'windows')
                        ntldd --recursive "${exe_file}"
                        ;;
+               'macos')
+                       otool -L "${exe_file}"
        esac
 }
 
@@ -106,6 +147,9 @@ Multi::getGtkThemeName () {
                'windows')
                        echo 'MS-Windows'
                        ;;
+               *)
+                       echo 'Default'
+                       ;;
        esac
 }
 
@@ -117,6 +161,9 @@ Multi::getGtkLibName () {
                'windows')
                        echo 'libgtk-win32-2.0-0.dll'
                        ;;
+               'macos')
+                       echo 'libgtk-quartz-2.0.0.dylib'
+                       ;;
        esac
 }
 
@@ -133,6 +180,8 @@ Multi::getRootPrefix () {
                        | xargs -n1 -P1 which \
                        | cut -f2 -d'/'
                        ;;
+               'macos')
+                       echo 'usr/local'
        esac
 }
 
@@ -147,6 +196,9 @@ Multi::getLibPrefix () {
                'windows')
                        echo 'lib'
                        ;;
+               'macos')
+                       echo 'lib'
+                       ;;
        esac
 }
 
@@ -154,12 +206,24 @@ Multi::getGtkDeps () {
        local lib_prefix="${1}"
        local gtk_theme_name="${2}"
 
-       cat <<-EOF
-       share/themes/${gtk_theme_name}/gtk-2.0
-       share/icons/hicolor
-       ${lib_prefix}/gdk-pixbuf-2.0
-       ${lib_prefix}/gtk-2.0
-       EOF
+       case "${system_name}" in
+               'linux'|'windows')
+                       cat <<-EOF
+                       share/themes/${gtk_theme_name}/gtk-2.0
+                       share/icons/hicolor
+                       ${lib_prefix}/gdk-pixbuf-2.0
+                       ${lib_prefix}/gtk-2.0
+                       EOF
+                       ;;
+               'macos')
+                       cat <<-EOF
+                       share/icons/hicolor
+                       share/locale
+                       ${lib_prefix}/gdk-pixbuf-2.0
+                       ${lib_prefix}/gtk-2.0
+                       EOF
+                       ;;
+       esac
 
        case "${system_name}" in
                'linux')
@@ -173,8 +237,29 @@ Multi::getGtkDeps () {
        esac
 }
 
+Multi::rewriteLoadersCache () {
+       local bundle_component_path="${1}"
+       local cache_file
+
+       find "${bundle_component_path}" \
+               -type f \
+               \( \
+               -name 'loaders.cache' \
+               -o -name 'immodules.cache' \
+               \) \
+       | while read cache_file
+       do
+               _sed \
+                       -e 's|^"/[^"]*/lib/|"lib/|;s| "/[^"]*/share/| "share/|;/^# ModulesPath = /d;/^# Created by /d;/^#$/d' \
+                       -i "${cache_file}"
+       done
+}
+
 Multi::bundleGtkDepsFromFile () {
        local lib_file="${1}"
+       local component_dir
+       local real_component_dir
+       local bundle_component_dir
 
        lib_basename="$(basename "${lib_file}")"
 
@@ -187,14 +272,22 @@ Multi::bundleGtkDepsFromFile () {
 
                for component_dir in $(Multi::getGtkDeps "${lib_prefix}" "${gtk_theme_name}")
                do
-                       bundle_component_dir="$(echo "${component_dir}" | sed -e 's|^'"${lib_prefix}"'|lib|')"
+                       bundle_component_dir="$(echo "${component_dir}" | _sed -e 's|^'"${lib_prefix}"'|lib|')"
                        if ! [ -e "${bundle_dir}/${bundle_component_dir}" ]
                        then
-                               mkdir --parents "${bundle_dir}/$(dirname "${bundle_component_dir}")"
+                               real_component_dir="$(realpath "/${root_prefix}/${component_dir}")"
+
+                               mkdir -p "${bundle_dir}/$(dirname "${bundle_component_dir}")"
+
+                               _cpr -H -L \
+                                       "${real_component_dir}" \
+                                       "${bundle_dir}/${bundle_component_dir}"
 
-                               cp -H -r --preserve=timestamps \
-                                       "/${root_prefix}/${component_dir}" \
+                               touch -r \
+                                       "/${real_component_dir}" \
                                        "${bundle_dir}/${bundle_component_dir}"
+
+                               Multi::rewriteLoadersCache "${bundle_dir}/${bundle_component_dir}"
                        fi
                done
        fi
@@ -221,11 +314,21 @@ Multi::bundleLibFromFile () {
                        continue
                fi
 
-               cp --preserve=timestamps \
+               cp -H \
+                       "${lib_file}" \
+                       "${lib_dir}/${lib_basename}"
+
+               touch -r \
                        "${lib_file}" \
                        "${lib_dir}/${lib_basename}"
 
                Multi::bundleGtkDepsFromFile "${lib_file}"
+
+               case "${system_name}" in
+                       'macos')
+                               Multi::bundleLibFromFile "${lib_file}"
+                               ;;
+               esac
        done
 }
 
@@ -233,17 +336,18 @@ Multi::cleanUp () {
        find "${bundle_dir}/lib" \
                -type f \
                -name '*.a' \
-               -exec rm {} \;
+               -exec rm -f {} \;
 
        find "${bundle_dir}/lib" \
                -type f \
                -name '*.h' \
-               -exec rm {} \;
+               -exec rm -f {} \;
 
        find "${bundle_dir}/lib" \
                -depth \
                -type d \
-               -exec rmdir --ignore-fail-on-non-empty {} \;
+               -exec rmdir {} \; \
+       || true
 }
 
 Linux::getRpath () {
@@ -253,7 +357,7 @@ Linux::getRpath () {
        local path_start="$(printf '%s' "${bundle_dir}" | wc -c)"
        path_start="$((${path_start} + 1))"
 
-       local exe_subdir="$(echo "${exe_dir}" | cut -c "${path_start}-" | sed -e 's|//*|/|;s|^/||')"
+       local exe_subdir="$(echo "${exe_dir}" | cut -c "${path_start}-" | _sed -e 's|//*|/|;s|^/||')"
 
        local rpath_origin='$ORIGIN'
 
@@ -298,6 +402,38 @@ Linux::patchLib () {
        done
 }
 
+Darwin::patchExe () {
+       local exe_file="${1}"
+
+       Multi::printLdd "${exe_file}" \
+       | Multi::filterLib \
+       | while read lib_file
+       do
+               new_path="$(echo "${lib_file}" | _sed -e 's|^/.*/lib/|@executable_path/lib/|')"
+               id_name="$(echo "${lib_file}" | _sed -e 's|.*/||g')"
+               chmod u+w,go-w "${exe_file}"
+               install_name_tool -change "${lib_file}" "${new_path}" "${exe_file}"
+               install_name_tool -id "${id_name}" "${exe_file}"
+       done
+}
+
+Darwin::patchLib () {
+       local lib_dir="${1}"
+       local exe_file
+
+       find "${lib_dir}" \
+               -type f \
+               \( \
+               -name '*.dylib' \
+               -o -name '*.so' \
+               \) \
+       | while read exe_file
+       do
+               Darwin::patchExe "${exe_file}"
+               chmod ugo-x "${exe_file}"
+       done
+}
+
 Windows::listLibForManifest () {
        local lib_dir="${1}"
 
@@ -341,7 +477,7 @@ lib_action='Common::noOp'
 
 case "${system_name}" in
        'register')
-               mkdir --parents "${registry_dir}"
+               mkdir -p "${registry_dir}"
                Common::getPath "${exe_file}" > "${registry_dir}/$(uuidgen)"
                exit
                ;;
@@ -352,13 +488,17 @@ case "${system_name}" in
        'windows')
                lib_action='Windows::writeManifest'
                ;;
+       'macos')
+               exe_action='Darwin::patchExe'
+               lib_action='Darwin::patchLib'
+               ;;
        *)
                printf 'ERROR: unsupported system: %s\n' "${system_name}" >&2
                exit 1
                ;;
 esac
 
-mkdir --parents "${lib_dir}"
+mkdir -p "${lib_dir}"
 
 if [ -d "${registry_dir}" ]
 then