dllbundler.sh 1.96 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
#!/bin/bash -e
#
# Scans an executable for runtime dependencies and copies them to the
# executable's directory. This script relies on the mingw-objdump tool to
# parse dependencies. It processes all input recursively.
#
# Copied by permission from:
# https://github.com/jdolan/quake2world/blob/master/mingw-cross/dllbundler.sh
#
# Licensed under the GPLv2

while getopts "h:" opt; do
	case "${opt}" in
		h)
			host="${OPTARG}"
			;;
		\?)
			echo "Invalid option: -${OPTARG}" >&2
			exit 1
			;;
	esac
done

test "${host}" || {
	echo "Required option -h host is missing" >&2
	exit 1
}

objdump=$(which ${host}-objdump)
test -x "${objdump}" || {
	echo "No ${host}-objdump in PATH" >&2
	exit 2
}

shift $((OPTIND-1))

exes="${@}"
for exe in ${exes}; do
	test -e "${exe}" || {
		echo "${exe} is not an executable" >&2
		exit 3
	}

	dir=$(dirname "${exe}")
	test -w "${dir}" || {
		echo "${dir} is not writable" >&2
		exit 3
	}

	# Clean up ${dir} bedore copying .dll files
	pushd ${dir}
	rm -f $(find . -type f | egrep -v "cygwin|*.exe")
	popd
done

tmp=$(mktemp -d /tmp/dllbundler-XXXXXX)
test -w "${tmp}" || {
	echo "${tmp} is not writable" >&2
	exit 4
}

search_path="${MINGW_PREFIX}/usr/${host}"
test -d "${search_path}" || {
	echo "${search_path} does not exist" >&2
	exit 5
}


#
# Resolve dependencies recursively, copying them from the search path to dir.
#
function bundle_recursively(){
	local deps=$($objdump -p "${1}" | sed -rn 's/DLL Name: (.*\.dll)/\1/p' | sort -u)
	for dep in ${deps}; do
		test -f "${dir}/${dep}" && continue
		test -f "${tmp}/${dep}" && continue

		local dll=$(find "${search_path}" -name "${dep}")
		test -z "${dll}" && {
			echo "WARNING: Couldn't find ${dep} in ${search_path}" >&2
			touch "${tmp}/${dep}"
			continue
		}

		bundle_recursively "${dll}"

		echo "Installing ${dll}.."
		install "${dll}" "${dir}"
	done
}

for exe in ${exes}; do
    dir=$(dirname "${exe}")
    echo "Bundling .dll files for ${exe} in ${dir}.."
	bundle_recursively "${exe}"
done

rm -rf "${tmp}"