From: Thomas Debesse Date: Thu, 1 Aug 2019 19:20:23 +0000 (+0200) Subject: bundle: a bunch of improvements X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=2a499e0cea34582a9cb47d581c302edd49202fce;p=xonotic%2Fnetradiant.git bundle: a bunch of improvements --- diff --git a/CMakeLists.txt b/CMakeLists.txt index d3e0d8b0..bfc6fc70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}" "$" @@ -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}) diff --git a/library-bundler b/library-bundler index cf91dd35..0ef9567c 100755 --- a/library-bundler +++ b/library-bundler @@ -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 ' \n' } -Windows::printManifest () { +Windows::writeManifest () { local lib_dir="${1}" - cat <<-EOF + cat > "${manifest_file}" <<-EOF $(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