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 ()
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})
```
-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.
* `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.
--- /dev/null
+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}
+)
--- /dev/null
+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
--- /dev/null
+#! /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
endif ()
copy_dlls(${RADIANT_BASENAME})
-bundle_stuff(${RADIANT_BASENAME})