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}>"
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})
#! /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}"
-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}")
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