]> git.xonotic.org Git - xonotic/netradiant.git/commitdiff
bundle: a bunch of improvements
authorThomas Debesse <dev@illwieckz.net>
Thu, 1 Aug 2019 19:20:23 +0000 (21:20 +0200)
committerThomas Debesse <dev@illwieckz.net>
Sun, 4 Aug 2019 21:32:49 +0000 (23:32 +0200)
CMakeLists.txt
library-bundler

index d3e0d8b065455f6f98ed9608fde98f3decc3a665..bfc6fc70ad020e09f9704ebb0ae8637eb5d47fb5 100644 (file)
@@ -211,22 +211,28 @@ if (BUILD_BINARIES)
     include_directories("${PROJECT_SOURCE_DIR}/include")
     include_directories("${PROJECT_SOURCE_DIR}/libs")
 
-    if (WIN32 AND NOT CMAKE_CROSSCOMPILING)
-        set(BUNDLE_LIBRARIES_DEFAULT ON)
-    else ()
-        set(BUNDLE_LIBRARIES_DEFAULT OFF)
-    endif ()
+    if (WIN32 OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
+        set(BUNDLING_SUPPORTED ON)
+    endif()
+
+    if (BUNDLING_SUPPORTED)
+        if(WIN32 AND NOT CMAKE_CROSSCOMPILING)
+            set(BUNDLE_LIBRARIES_DEFAULT ON)
+        else ()
+            set(BUNDLE_LIBRARIES_DEFAULT OFF)
+        endif ()
 
-    option(BUNDLE_LIBRARIES "Bundle libraries" ${BUNDLE_LIBRARIES_DEFAULT})
+        option(BUNDLE_LIBRARIES "Bundle libraries" ${BUNDLE_LIBRARIES_DEFAULT})
+    endif ()
 
-    if (BUNDLE_LIBRARIES)
+    if (BUNDLE_LIBRARIES AND BUNDLING_SUPPORTED)
         add_subdirectory(bundle)
 
         set(FHS_INSTALL OFF CACHE PATH "Disabled because of BUNDLE_LIBRARIES" FORCE)
     endif ()
 
     macro (copy_dlls target)
-        if (BUNDLE_LIBRARIES)
+        if (BUNDLE_LIBRARIES AND BUNDLING_SUPPORTED)
             add_custom_command(TARGET ${target} POST_BUILD
                 COMMAND "${PROJECT_SOURCE_DIR}/library-bundler"
                 "register" "${PROJECT_BINARY_DIR}" "$<TARGET_FILE:${target}>"
@@ -277,10 +283,12 @@ if (BUILD_BINARIES)
     macro (radiant_tool name)
         add_dependencies(binaries ${name})
 
-        if (BUNDLE_LIBRARIES AND WIN32)
-            add_executable(${name} ${ARGN} ${PROJECT_SOURCE_DIR}/include/lib.rc)
-        else ()
-            add_executable(${name} ${ARGN})
+        if (BUNDLE_LIBRARIES AND BUNDLING_SUPPORTED)
+            if (WIN32)
+                add_executable(${name} ${ARGN} ${PROJECT_SOURCE_DIR}/include/lib.rc)
+            else ()
+                add_executable(${name} ${ARGN})
+            endif()
         endif ()
 
         copy_dlls(${name})
index cf91dd35dd7a39fe2bcbccc4acf1462f0cafbc9d..0ef9567c3c4a91896c6b35e3ddeaad7e2a4e846a 100755 (executable)
@@ -1,5 +1,172 @@
 #! /usr/bin/env bash
 
+Common::noOp () {
+       printf ''
+}
+
+Common::getPath () {
+       local file_path="${1}"
+
+       if command -v cygpath >/dev/null
+       then
+               if [ "${file_path}" = '-' ]
+               then
+                       tr '\n' '\0' \
+                       | xargs -0 -n1 -P1 -I{} \
+                               cygpath --unix '{}'
+               else
+                       cygpath --unix "${file_path}"
+               fi
+       else
+               if [ "${file_path}" = '-' ]
+               then
+                       cat
+               else
+                       printf '%s\n' "${file_path}"
+               fi
+       fi
+}
+
+Common::grepLdd () {
+       egrep ' => '
+}
+
+Common::stripLdd () {
+       sed -e 's/ (0x[0-9a-f]*)$//;s/^.* => //'
+}
+
+Multi::excludeLdd () {
+       case "${system_name}" in
+               'windows')
+                       egrep -i '\.dll => [A-Z]:\\msys64\\' \
+                       ;;
+       esac
+}
+
+Multi::filterLib () {
+       Common::grepLdd \
+       | Multi::excludeLdd \
+       | Common::stripLdd \
+       | Common::getPath -
+}
+
+Multi::printLdd () {
+       local exe_file="${1}"
+
+       case "${system_name}" in
+               'windows')
+                       ntldd --recursive "${exe_file}"
+                       ;;
+       esac
+}
+
+Multi::getGtkThemeName () {
+       case "${system_name}" in
+               'windows')
+                       echo 'MS-Windows'
+                       ;;
+       esac
+}
+
+Multi::getGtkLibName () {
+       case "${system_name}" in
+               'windows')
+                       echo 'libgtk-win32-2.0-0.dll'
+                       ;;
+       esac
+}
+
+Multi::getRootPrefix () {
+       local lib_file="${1}"
+
+       case "${system_name}" in
+               'windows')
+                       basename "${lib_file}" \
+                       | xargs -n1 -P 1 which \
+                       | cut -f2 -d'/'
+                       ;;
+       esac
+}
+
+Multi::getLibPrefix () {
+       local lib_file="${1}"
+
+       case "${system_name}" in
+               'windows')
+                       echo 'lib'
+                       ;;
+       esac
+}
+
+Multi::bundleGtkDepsFromFile () {
+       local lib_file="${1}"
+
+       lib_basename="$(basename "${lib_file}")"
+
+       gtk_lib_name="$(Multi::getGtkLibName)"
+       if [ "${lib_basename}" = "${gtk_lib_name}" ]
+       then
+               root_prefix="$(Multi::getRootPrefix "${lib_file}")"
+               lib_prefix="$(Multi::getLibPrefix "${lib_file}")"
+               gtk_theme_name="$(Multi::getGtkThemeName)"
+
+               for component_dir in \
+                       'share/themes/'"${gtk_theme_name}"'/gtk-2.0' \
+                       'share/icons/hicolor' \
+                       "${lib_prefix}"'/gdk-pixbuf-2.0' \
+                       "${lib_prefix}"'/gtk-2.0'
+               do
+                       if ! [ -d "${bundle_dir}/${component_dir}" ]
+                       then
+                               mkdir --parents "${bundle_dir}/$(dirname "${component_dir}")"
+
+                               cp -r --preserve=timestamps \
+                                       "/${root_prefix}/${component_dir}" \
+                                       "${bundle_dir}/${component_dir}"
+                       fi
+               done
+       fi
+}
+
+Multi::bundleLibFromFile () {
+       local exe_file="${1}"
+
+       Multi::printLdd "${exe_file}" \
+       | Multi::filterLib \
+       | while read lib_file
+       do
+               lib_basename="$(basename "${lib_file}")"
+
+               if [ -f "${bundle_dir}/${lib_basename}" ]
+               then
+                       continue
+               fi
+
+               cp --preserve=timestamps \
+                       "${lib_file}" \
+                       "${lib_dir}/${lib_basename}"
+
+               Multi::bundleGtkDepsFromFile "${lib_file}"
+       done
+}
+
+Multi::cleanUp () {
+       find "${bundle_dir}/lib" \
+               -type f \
+               -name '*.a' \
+               -exec rm {} \;
+
+       find "${bundle_dir}/lib" \
+               -type f \
+               -name '*.h' \
+               -exec rm {} \;
+
+       find "${bundle_dir}/lib" \
+               -type d \
+               -depth \
+               -exec rmdir --ignore-fail-on-non-empty {} \;
+}
+
 Windows::listLibForManifest () {
        local lib_dir="${1}"
 
@@ -8,14 +175,15 @@ Windows::listLibForManifest () {
                -type f \
                -name '*.dll' \
                -exec basename {} \; \
-       | xargs -I {} \
+       | tr '\n' '\0' \
+       | xargs -0 -n1 -P1 -I{} \
                printf '  <file name="{}"/>\n'
 }
 
-Windows::printManifest () {
+Windows::writeManifest () {
        local lib_dir="${1}"
 
-       cat <<-EOF
+       cat > "${manifest_file}" <<-EOF
        <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
          <assemblyIdentity type="win32" name="lib" version="1.0.0.0"/>
        $(Windows::listLibForManifest "${lib_dir}")
@@ -23,86 +191,51 @@ Windows::printManifest () {
        EOF
 }
 
-Windows::bundleLibFromFile () {
-       local exe_file="${1}"
-
-       exe_file="$(cygpath --unix "${exe_file}")"
-
-       ntldd --recursive "${exe_file}" \
-       | egrep -i '\.dll => [A-Z]:\\msys64\\' \
-       | sed -e 's/ (0x[0-9a-f]*)$//;s/^.* => //' \
-       | cygpath --unix --file - \
-       | while read dll_file
-       do
-               dll_basename="$(basename "${dll_file}")"
-
-               if [ -f "${bundle_dir}/${dll_basename}" ]
-               then
-                       continue
-               fi
-
-               cp --preserve=timestamps "${dll_file}" "${lib_dir}/${dll_basename}"
-
-               if [ "${dll_basename}" = 'libgtk-win32-2.0-0.dll' ]
-               then
-                       mingw="$(which 'libgtk-win32-2.0-0.dll' | cut -f2 -d'/')"
-
-                       for component_dir in \
-                               'share/themes/MS-Windows' \
-                               'share/icons/hicolor' \
-                               'lib/gdk-pixbuf-2.0' \
-                               'lib/gtk-2.0'
-                       do
-                               if ! [ -d "${bundle_dir}/${component_dir}" ]
-                               then
-                                       mkdir --parents "${bundle_dir}/$(dirname "${component_dir}")"
-                                       cp -r --preserve=timestamps "/${mingw}/${component_dir}" \
-                                               "${bundle_dir}/${component_dir}"
-                               fi
-                       done
-
-                       find "${bundle_dir}/lib" -type f -name '*.a' -exec rm {} \;
-                       find "${bundle_dir}/lib" -type f -name '*.h' -exec rm {} \;
-                       find "${bundle_dir}/lib" -type d -exec rmdir --ignore-fail-on-non-empty {} \;
-               fi
-       done
-}
-
 system_name="${1}"; shift
 bundle_dir="${1}"; shift
 exe_file="${1}"; shift
 
+bundle_dir="$(Common::getPath "${bundle_dir}")"
 registry_dir="${bundle_dir}/registry"
+lib_dir="${bundle_dir}/lib"
+
+rpath_string='@executable_path:lib'
+
+lib_action='Common::noOp'
 
 case "${system_name}" in
        'register')
                mkdir --parents "${registry_dir}"
-               printf '%s\n' "${exe_file}" > "${registry_dir}/$(uuidgen)"
+               Common::getPath "${exe_file}" > "${registry_dir}/$(uuidgen)"
+               exit
                ;;
        'windows')
-               bundle_dir="$(cygpath --unix "${bundle_dir}")"
-
-               lib_dir="${bundle_dir}/lib"
-               mkdir --parents "${lib_dir}"
-
-               if [ -d "${registry_dir}" ]
-               then
-                       for registry_entry in "${registry_dir}"/*
-                       do
-                               exe_file="$(cat "${registry_entry}")"
-
-                               Windows::bundleLibFromFile "${exe_file}"
-
-                               rm "${registry_entry}"
-                               rmdir --ignore-fail-on-non-empty "${registry_dir}"
-                       done
-
-                       manifest_file="${lib_dir}/lib.manifest"
-                       Windows::printManifest "${lib_dir}" > "${manifest_file}"
-               fi
+               lib_action='Windows::writeManifest'
                ;;
        *)
                printf 'ERROR: unsupported system: %s\n' "${system_name}" >&2
                exit 1
                ;;
 esac
+
+mkdir --parents "${lib_dir}"
+
+if [ -d "${registry_dir}" ]
+then
+       for registry_entry in "${registry_dir}"/*
+       do
+               exe_file="$(cat "${registry_entry}")"
+
+               Multi::bundleLibFromFile "${exe_file}"
+
+               "${exe_action}" "${exe_file}"
+
+               rm "${registry_entry}"
+       done
+
+       rmdir "${registry_dir}"
+fi
+
+"${lib_action}" "${lib_dir}"
+
+Multi::cleanUp