]> de.git.xonotic.org Git - xonotic/netradiant.git/commitdiff
Merge branch 'bundle' into 'master'
authorThomas Debesse <gitlab@illwieckz.net>
Mon, 24 Jun 2019 19:02:41 +0000 (19:02 +0000)
committerThomas Debesse <gitlab@illwieckz.net>
Mon, 24 Jun 2019 19:02:41 +0000 (19:02 +0000)
improve lib and other stuff bundling on windows

See merge request xonotic/netradiant!136

CMakeLists.txt
README.md
bundle/CMakeLists.txt [new file with mode: 0644]
include/lib.rc [new file with mode: 0644]
library-bundler [new file with mode: 0644]
radiant/CMakeLists.txt

index 4cbf3658077dcdd0dfe5b90ce91306cc31932470..1a414aa15ca54d811fe04400a1c221d3914f1622 100644 (file)
@@ -213,36 +213,18 @@ if (BUILD_BINARIES)
 
     option(BUNDLE_LIBRARIES "Bundle libraries" ${BUNDLE_LIBRARIES_DEFAULT})
 
+    if (BUNDLE_LIBRARIES)
+        add_subdirectory(bundle)
+    endif ()
+
     macro (copy_dlls target)
-        if (BUNDLE_LIBRARIES AND WIN32)
+        if (BUNDLE_LIBRARIES)
             add_custom_command(TARGET ${target} POST_BUILD
-                COMMAND bash
-                ARGS -c "ldd '$<TARGET_FILE:${target}>' | egrep -i '\\.dll ' | grep -iv '/c/Windows' | awk '{ print $1 }' | while read dll; do dllbasename=\"$(which \"$dll\")\"; [ -f \"${PROJECT_BINARY_DIR}/$dllbasename\" ] || cp --preserve=timestamps \"$dllbasename\" '${PROJECT_BINARY_DIR}'; done"
+                COMMAND "${PROJECT_SOURCE_DIR}/library-bundler"
+                "register" "${PROJECT_BINARY_DIR}" "$<TARGET_FILE:${target}>"
                 VERBATIM
-        )
-        endif ()
-    endmacro ()
-
-    macro (bundle_stuff target)
-        if (BUNDLE_LIBRARIES AND WIN32)
-            add_custom_command(TARGET ${target} POST_BUILD
-                COMMAND bash
-                ARGS -c "mkdir -p '${PROJECT_BINARY_DIR}/share/themes'; mkdir -p '${PROJECT_BINARY_DIR}/lib'; mingw=\"$(echo '${CMAKE_C_COMPILER}' | sed -e 's|/bin/.*||')\"; [ -d '${PROJECT_BINARY_DIR}/share/themes/MS-Windows' ] || cp -r --preserve=timestamps \"$mingw/share/themes/MS-Windows\" '${PROJECT_BINARY_DIR}/share/themes/'; [ -d '${PROJECT_BINARY_DIR}/lib/gdk-pixbuf-2.0' ] || cp -r --preserve=timestamps \"$mingw/lib/gdk-pixbuf-2.0\" '${PROJECT_BINARY_DIR}/lib/'; [ -d '${PROJECT_BINARY_DIR}/lib/gtk-2.0' ] || cp -r --preserve=timestamps \"$mingw/lib/gtk-2.0\" '${PROJECT_BINARY_DIR}/lib/'"
-                VERBATIM
-        )
-
-        file(GLOB DLL_FILES ${PROJECT_BINARY_DIR}/*.dll)
-
-        install(FILES
-            ${DLL_FILES}
-            DESTINATION ${CMAKE_INSTALL_PREFIX}
-        )
-
-        install(DIRECTORY
-            ${PROJECT_BINARY_DIR}/lib
-            ${PROJECT_BINARY_DIR}/share
-            DESTINATION ${CMAKE_INSTALL_PREFIX}
-        )
+            )
+            add_dependencies(bundle ${target})
         endif ()
     endmacro ()
 endif ()
@@ -285,7 +267,11 @@ if (BUILD_BINARIES)
     endif ()
 
     macro (radiant_tool name)
-        add_executable(${name} ${ARGN})
+        if (BUNDLE_LIBRARIES AND WIN32)
+            add_executable(${name} ${ARGN} ${PROJECT_SOURCE_DIR}/include/lib.rc)
+        else ()
+            add_executable(${name} ${ARGN})
+        endif ()
 
         copy_dlls(${name})
 
index 8ffb05e5ab91a191b72f87705baf1d546e831cbe..8aa17a4288141efa61ba1e9cbe4fa609dd169a54 100644 (file)
--- a/README.md
+++ b/README.md
@@ -52,7 +52,7 @@ Install the dependencies this way:
 
 
 ```
-pacman -S --needed base-devel mingw-w64-$(uname -m)-{toolchain,cmake,make,gtk2,gtkglext,libwebp,minizip-git} git
+pacman -S --needed base-devel mingw-w64-$(uname -m)-{ntldd-git,toolchain,cmake,make,gtk2,gtkglext,libwebp,minizip-git} git
 ```
 
 Explicitely use `mingw-w64-x86_64-` or `mingw-w64-i686-` prefix if you need to target a non-default architecture.
@@ -161,12 +161,6 @@ target:
 * `install`  
   Install files
 
-Note that because of both the way NetRadiant works and the way bundled library loading works CMake has to do some globbing to detect some of the produced/copied files it has to install. So you have to run cmake again before installing:
-
-```
-cmake -H. -Bbuild && cmake --build build -- install
-```
-
 ## Note about Crunch
 
 The crnlib used to decode `.crn` files is the one from [Dæmon](http://github.com/DaemonEngine/Daemon) which is the one by [Unity](https://github.com/Unity-Technologies/crunch/tree/unity) made cross-platform and slightly improved. Since Unity brokes compatibility with [BinomialLLC's legacy tree](https://github.com/BinomialLLC/crunch) it's required to use either the `crunch` tool from Dæmon or the one from Unity to compress textures that have to be read by radiant or q3map2.
diff --git a/bundle/CMakeLists.txt b/bundle/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1cb5a22
--- /dev/null
@@ -0,0 +1,18 @@
+if (WIN32)
+    set(BUNDLE_OS_NAME "windows")
+else ()
+    set(BUNDLE_OS_NAME "unsupported")
+endif ()
+
+add_custom_target(bundle ALL
+    COMMAND "${PROJECT_SOURCE_DIR}/library-bundler"
+    "${BUNDLE_OS_NAME}" "${PROJECT_BINARY_DIR}"
+    VERBATIM
+    COMMENT "Bundling libraries"
+)
+
+install(DIRECTORY
+    ${PROJECT_BINARY_DIR}/lib
+    ${PROJECT_BINARY_DIR}/share
+    DESTINATION ${CMAKE_INSTALL_PREFIX}
+)
diff --git a/include/lib.rc b/include/lib.rc
new file mode 100644 (file)
index 0000000..3ad3a12
--- /dev/null
@@ -0,0 +1,11 @@
+1 24 /* RT_MANIFEST */
+BEGIN
+    "<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>"
+    "<assembly xmlns=""urn:schemas-microsoft-com:asm.v1"" manifestVersion=""1.0"">"
+      "<dependency>"
+        "<dependentAssembly>"
+          "<assemblyIdentity type=""win32"" name=""lib"" version=""1.0.0.0""/>"
+        "</dependentAssembly>"
+      "</dependency>"
+    "</assembly>"
+END
diff --git a/library-bundler b/library-bundler
new file mode 100644 (file)
index 0000000..c2855be
--- /dev/null
@@ -0,0 +1,108 @@
+#! /usr/bin/env bash
+
+Windows::listLibForManifest () {
+       local lib_dir="${1}"
+
+       find "${lib_dir}" \
+               -maxdepth 1 \
+               -type f \
+               -name '*.dll' \
+               -exec basename {} \; \
+       | xargs -I {} \
+               printf '  <file name="{}"/>\n'
+}
+
+Windows::printManifest () {
+       local lib_dir="${1}"
+
+       cat <<-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}")
+       </assembly>
+       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
+
+registry_dir="${bundle_dir}/registry"
+
+case "${system_name}" in
+       'register')
+               mkdir --parents "${registry_dir}"
+               printf '%s\n' "${exe_file}" > "${registry_dir}/$(uuidgen)"
+               ;;
+       '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
+               ;;
+       *)
+               printf 'ERROR: unsupported system: %s\n' "${system_name}" >&2
+               exit 1
+               ;;
+esac
index 424c42d6675e97bab647222f69af668cc74bd129..6fcb36809d27fa167e98fa8a4661672d42f47e66 100644 (file)
@@ -131,4 +131,3 @@ if (X11_LIBRARIES)
 endif ()
 
 copy_dlls(${RADIANT_BASENAME})
-bundle_stuff(${RADIANT_BASENAME})