summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Nagaev <bnagaev@gmail.com>2016-02-21 00:10:38 (GMT)
committerBoris Nagaev <bnagaev@gmail.com>2016-02-21 00:10:38 (GMT)
commit62467d9d4dbb69aa632ae684b4a5a3f4c3b4a1ff (patch)
treedbf88affcb91eb67679145d43cef3cd3be84cad8
parentff84342c27a5e8badbbdfb58403e22635b78726e (diff)
parent2e86ace952aa11e5a4e4e69304f370ad533cedec (diff)
downloadmxe-62467d9d4dbb69aa632ae684b4a5a3f4c3b4a1ff.zip
mxe-62467d9d4dbb69aa632ae684b4a5a3f4c3b4a1ff.tar.gz
mxe-62467d9d4dbb69aa632ae684b4a5a3f4c3b4a1ff.tar.bz2
Merge pull request #1215 from dl5rcw/master
introducing copydlldeps.sh and copydlldeps.txt
-rw-r--r--tools/copydlldeps.md71
-rwxr-xr-xtools/copydlldeps.sh382
2 files changed, 453 insertions, 0 deletions
diff --git a/tools/copydlldeps.md b/tools/copydlldeps.md
new file mode 100644
index 0000000..4d2eb22
--- /dev/null
+++ b/tools/copydlldeps.md
@@ -0,0 +1,71 @@
+README of copydlldeps.sh
+========================
+This document belongs to copydlldeps.sh and is a part of the MXE project.
+
+It can be invoked on the command line like:
+
+```
+/share/mxe/tools/copydlldeps.sh --infile /home/mxeuser/test/i686-w64-mingw32.shared/Application.exe \
+ --destdir /home/mxeuser/testdlls/ \
+ --recursivesrcdir /home/mxeuser/mxe/usr/i686-w64-mingw32.shared/ \
+ --srcdir /home/mxeuser/test/ \
+ --copy \
+ --enforce /home/mxeuser/mxe/usr/i686-w64-mingw32.shared/qt5/plugins/platforms/ \
+ --objdump /home/mxeuser/mxe/usr/bin/i686-w64-mingw32.shared-objdump
+```
+
+It got embedded in a build script like:
+
+```
+MXEPATH=/path/to/mxe
+compiler=i686-w64-mingw32.shared
+orgDir=/path/to/my/nsis/dll # nsis is then copying all dlls in there to the place where the exe is located
+
+if [ ! $( echo $compiler | grep -q "shared" ) ]; then
+ echo "\$compiler=$compiler and contains the word 'shared'" | tee -a $CURLOG
+
+ echo "+-----------------------------------------------+ " | tee -a $CURLOG
+ echo "| Starting new MXE copydlldeps.sh by LHE DL5RCW | " | tee -a $CURLOG
+ echo "+-----------------------------------------------+ " | tee -a $CURLOG
+ echo "currently working in $( pwd ) " | tee -a $CURLOG
+ executable=$( find . -name "*.exe" | tail -n 1 )
+ sharedLibsDir="${orgDir}/nsis/sharedLibs"
+ echo "populating dir $sharedLibsDir with dll dependencies of $executable" | tee -a $CURLOG
+ OBJDUMP=objdump
+ if [ -e "$MXEPATH/usr/bin/$compiler-objdump" ]; then
+ OBJDUMP="$MXEPATH/usr/bin/$compiler-objdump"
+ fi
+ $MXEPATH/tools/copydlldeps.sh --infile $executable \
+ --destdir "$sharedLibsDir" \
+ --recursivesrcdir "$MXEPATH/usr/$compiler/" \
+ --enforce "$MXEPATH/usr/$compiler/qt5/plugins/platforms/" \
+ --copy \
+ --objdump "$OBJDUMP" \
+ | tee -a $CURLOG
+fi
+```
+
+Additional hints
+================
+
+objdump
+-------
+I checked if there is a mxe objdump. If not, I took the native one on my server.
+I actually do not know the difference but decided to include it in the script
+in case it is important to someone.
+
+enforce
+-------
+My application is using Qt5 and objdump did not return the needed qwindows.dll -
+so I enforce the platform folder. You may add multiple --enforce directories using
+`--enforce /path/folder1 --enforce /path/folder2 --enforce /path/folder3`.
+
+They are NOT recursively copied, only flat. See:
+
+```bash
+ string=$( find $enforcedDirectory -maxdepth 1 -iregex '.*\(dll\|exe\)' | tr '\n' ' ' )
+```
+
+If you would remove the `-maxdepth 1`, it would become recoursive.
+
+February, 2, 2016. Lars Holger Engelhard aka [DL5RCW](https://github.com/dl5rcw).
diff --git a/tools/copydlldeps.sh b/tools/copydlldeps.sh
new file mode 100755
index 0000000..23b31ca
--- /dev/null
+++ b/tools/copydlldeps.sh
@@ -0,0 +1,382 @@
+#!/bin/bash
+#
+
+# print version and license
+# is hereby part of the code and also displayed to the user
+version() {
+ cat <<EOF >&2
+
+Welcome to $( basename $0)!
+Authors: Lars Holger Engelhard - DL5RCW (2016)
+ Tiancheng "Timothy" Gu (2014)
+
+Version: 1.0
+
+# This file is part of the MXE Project, sponsored by the named authors
+# it supports the shared build approach by providing an easy way to
+# check for library dependencies in a recursive manner
+
+# Copyright (c) 2014 Tiancheng "Timothy" Gu
+# (c) 2016 Lars Holger Engelhard - DL5RCW
+
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject
+# to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+EOF
+}
+
+# default application objdump
+# you can specify your own objdump with --objdump or -o
+OBJDUMP=objdump
+
+# create a temp directory
+tmp=`mktemp -d`
+
+# print an help menu
+help() {
+ cat <<EOF >&2
+
+
+Usage: $0 -c -d DEST -s SRC [-f FILE|-F DIR]
+ or: $0 -p [-f FILE|-F DIR]
+ or: $0 -c -p -d DEST -s SRC [-f FILE|-F DIR]
+ or: $0 -p -d DEST -R SRC [-f FILE|-F DIR]
+ or: $0 -p -d DEST -S "SRC_1 SRC_2 ... SRC_n" [-f FILE|-F DIR]
+ or: $0 -c -d DEST -R SRC_1 -e SRC_2 [-f FILE|-F DIR]
+
+
+Copy executable FILE(s) and their DLL dependencies for SRC directory to a
+DEST directory, and/or print the recursive dependencies.
+
+Operating modes:
+ -c, --copy print and copy dependencies
+ -p, --print print dependencies (no copy action)
+
+Operating options:
+ -d, --destdir Destination directory
+ -f, --infile The input executable file or DLL.
+ -F, --infiles, --indir The input directory of executable files and/or DLLs.
+ -s, --srcdir [ multiCall ] The directory with DLLs that can be copied.
+ -S, --srcdirs [ multiCall ] List of directories with DLLs that can be copied. Put "" around them, e.g. "/dir1 /root/dir2 /root/dir3"
+ -R, --recursivesrcdir [ multiCall ] Target directory for recursive search of folders containing *dll files
+
+Optional binary settings:
+ -o, --objdump Specify the path or name of your objdump application
+ -e, --enforce Enforce executable files and/or DLLs of a specific directory
+ It will be entirely copied - flat, non recursive. assumes *.dll and *.exe in the top level directory
+ e.g. <path_to_mxe>/mxe/usr/<compiler>/qt5/plugins/platforms/ - for qwindows.dll becomes
+ DESTDIR/platforms/ containing qwindows.dll
+Other options:
+ -h,-H, --help Display this message and exit
+ -v,-V, --version Display version of this application
+ -l,-L, --logLevel Display more output - default is 1
+
+multiCall => you can specify this option multiple times!
+
+Authors: Lars Holger Engelhard - DL5RCW
+ Tiancheng "Timothy" Gu
+EOF
+}
+
+# terminate the application
+# print an error message
+# and clean the tmp directory
+die() {
+ echo $1 >&2
+ rm -rf "$tmp"
+ help
+ exit 1
+}
+
+# find all directories containing dll files
+# you can pass a list (array) of directories
+# and findAllSrcDirectories will hunt for dlls in each one recursively
+# it will return a sorted list and duplicates are removed
+findAllSrcDirectories(){
+ar_recursiveDirList=${!1}
+string=""
+for curPath in "${ar_recursiveDirList[@]}"; do
+ for element in $(find $curPath -name "*.dll"); do
+ #ar_list+="$(dirname $element) "
+ string+="$(dirname $element) "
+ done
+done
+string=$(echo "$string" | tr -s ' ' | tr ' ' '\n' | nl | sort -u -k2 | sort -n | cut -f2-)
+echo $string #returns the string
+}
+
+while [ $# -gt 0 ]; do
+ key="$1"
+ shift
+
+ case $key in
+ -f|--infile)
+ infile="$1"
+ shift
+ ;;
+ -F|--indir|--infiles)
+ indir="$1"
+ shift
+ ;;
+ -s|--srcdir)
+ srcdir+=" $1"
+ shift
+ ;;
+ -d|--destdir)
+ destdir="$1"
+ shift
+ ;;
+ -S|--srcdirs)
+ srcdirs+=" $1"
+ shift
+ ;;
+ -R|--recursivesrcdir)
+ recursivesrcdir+=" $1"
+ shift
+ ;;
+ -o|--objdump)
+ OBJDUMP="$1"
+ shift
+ ;;
+ -e|--enforce)
+ enforce+=" $1"
+ shift
+ ;;
+ -l|-L|--logLevel)
+ logLevel="$1"
+ shift
+ ;;
+ -p|--print)
+ opmode="print"
+ ;;
+ -c|--copy)
+ opmode="copy"
+ ;;
+ -h|-H|--help)
+ help
+ exit 0
+ ;;
+ -v|-V|--version)
+ version
+ exit 0
+ ;;
+ *)
+ echo "unknown option $key ignored" >&2
+ ;;
+ esac
+done
+if ! [ "$logLevel" ]; then
+ logLevel=0
+fi
+
+if ! [ "$opmode" ]; then
+ opmode="copy" # used as default in productive
+ #opmode="print" # used as default in development
+fi
+
+if [ "$indir" ] && [ "$infile" ]; then
+ die '--indir and --infile are mutually exclusive.'
+elif ! [ "$indir" ] && ! [ "$infile" ]; then
+ die 'Neither --indir nor --infile is specified.'
+fi
+
+if ! [ "$destdir" ]; then
+ die '--destdir is not specified.'
+fi
+if ! ([ "$srcdir" ] || [ "$srcdirs" ] || [ "$recursivesrcdir" ]); then
+ die 'either --srcdir or --srcdirs or --recursivesrcdir must be specified.'
+fi
+
+if [ "$indir" ]; then
+ filelist=`find $indir -iregex '.*\(dll\|exe\)' | tr '\n' ' '`
+else
+ filelist="$infile"
+fi
+
+if [ -n "$(ls -A $destdir 2>/dev/null)" ]; then
+ echo 'Warning: --destdir already exists and contains files.' >&2
+else
+ mkdir -p "$destdir"
+ echo "info: created --destdir $destdir"
+fi
+
+if [ "$logLevel" -gt 1 ]; then
+ echo "filelist=$filelist"
+ echo "opmode=$opmode"
+fi
+
+ar_srcDirList=()
+str_srcDirList=""
+if [ "$srcdir" ]; then
+ str_srcDirList+=" $srcdir"
+fi
+if [ "$srcdirs" ]; then
+ str_srcDirList+=" $srcdirs"
+fi
+if [ "$recursivesrcdir" ]; then
+ result="$( findAllSrcDirectories recursivesrcdir )"
+ str_srcDirList+=" $result"
+fi
+if [ "$logLevel" -gt 1 ]; then
+ echo "infiles: filelist=$filelist"
+ echo " opmode: $opmode"
+fi
+
+if [ "$logLevel" -gt 1 ]; then
+ echo "list for sources: str_srcDirList=${str_srcDirList}"
+ echo "using OBJDUMP=$OBJDUMP in Version $( $OBJDUMP -V)"
+fi
+
+if [ "$logLevel" -gt 1 ]; then
+ ## during development, I like to interrupt here to check the above output and skip the rest
+ echo "starting in 5 seconds" && sleep 5
+fi
+
+# function to append dependencies (recursively)
+append_deps() {
+ if [ "$logLevel" -gt 1 ]; then
+ echo "\$1=$1 + \$2=$2 "
+ sleep 2
+ fi
+ local bn="`basename $1`"
+ if [ -e "$tmp/$bn" ]; then
+ return 0
+ fi
+ if [ $# -eq 2 ]; then
+ path="$1"
+ else
+ path=""
+ for curPath in $( echo "${str_srcDirList}" | tr -s ' ' | tr ' ' '\n' ); do
+ counter=0
+ result=$(find $curPath -name "$bn" | tail -n 1)
+ if [ ! -z $result ];then
+ path=$result
+ counter=$(expr $counter + 1)
+ fi
+ if [ "$logLevel" -gt 1 ]; then
+ if [ $counter == 0 ]; then
+ echo "could not find \$path for dll $bn, \$counter=$counter: searched $curPath"
+ else
+ echo "found path for dll $bn = $path, \$counter=$counter: searched $curPath"
+ fi
+ fi
+ done
+ if [ "$logLevel" -gt 1 ]; then
+ echo "path for dll $bn now is $path"
+ sleep 2
+ fi
+ fi
+ echo "Processing $1" >&2
+ if ! [ -e "$path" ]; then
+ if [ "$logLevel" -gt 1 ]; then
+ echo "path=$path| and we touch $tmp/$bn -> non existent in our src directories!"
+ sleep 4
+ fi
+ touch "$tmp/$bn"
+ return 0
+ fi
+ $OBJDUMP -p "$path" | grep 'DLL Name:' | cut -f3 -d' ' > "$tmp/$bn"
+ echo "executing: $OBJDUMP -p "$path" | grep 'DLL Name:' | cut -f3 -d' ' > "$tmp/$bn""
+ for dll in `cat "$tmp/$bn" | tr '\n' ' '`; do
+ append_deps "$dll"
+ done
+ alldeps=$(printf "$alldeps\n%s" "$(cat $tmp/$bn)" | sort | uniq)
+}
+
+process_enforced_deps(){
+ enforcedDirectory=$1
+ if [ ! -d $enforcedDirectory ]; then
+ echo "warning! \$enforcedDirectory=$enforcedDirectory is not valid"
+ if [ "$logLevel" -gt 1 ]; then
+ sleep 10
+ fi
+ fi
+ # first we append the path to enforced dir to our list of source directories
+ # if we would do this file recursively, we should loop to find those and append them all to the list
+ str_srcDirList+=" $enforcedDirectory"
+ # now we search for the dll and exe files to be included
+ string=$( find $enforcedDirectory -maxdepth 1 -iregex '.*\(dll\|exe\)' | tr '\n' ' ' )
+ if [ "$logLevel" -gt 1 ]; then
+ echo "enforcedDirectory=$enforcedDirectory"
+ echo "we found dlls and exes:$string"
+ sleep 4
+ fi
+ # we hard copy it to DEST
+ cp -dpRxv "${enforcedDirectory}" "$destdir"
+}
+
+# beginning of the main function
+# we start with the enforced dlls and exe
+if [ ! -z $enforce ]; then
+ for curFile in $enforce; do
+ echo "startig for file $curFile"
+ append_deps "$curFile" rel
+ process_enforced_deps "$curFile"
+ done
+fi
+
+# then we start with our indir or infile list
+for file in $filelist; do
+ echo "starting for file $file"
+ #sleep 4
+ append_deps "$file" rel
+done
+
+echo "I will now search for \$alldeps"
+for debugOut in $( echo $alldeps | tr -s ' ' | tr '\n' ' '); do
+ echo "debugOut: $debugOut"
+done
+if [ "$logLevel" -eq 1 ]; then
+ echo "waiting 10 seconds until I proceed - so you can read my debugOut"
+ sleep 10
+
+ tmpStr=${str_srcDirList}
+ echo "\$alldeps has ${#alldeps[@]} elements"
+ echo "and \$str_srcDirList has ${#str_srcDirList} elements"
+ echo "waiting another 10 seconds"
+ #sleep 10
+fi
+
+for dll in `echo $alldeps | tr '\n' ' '`; do
+ counter=0
+ for curFolder in $( echo "${str_srcDirList}" | tr -s ' ' | tr ' ' '\n'); do
+ if [ "$logLevel" -gt 1 ]; then
+ echo "search for dll $dll in curFolder $curFolder"
+ sleep 1
+ fi
+ if [ -e "${curFolder}/${dll}" ]; then
+ counter=$(expr $counter + 1)
+ if [ $opmode == "copy" ]; then
+ cp -dpRxv "${curFolder}/${dll}" "$destdir"
+ elif [ $opmode == "print" ]; then
+ echo "found $dll in: ${curFolder}/${dll}"
+ else
+ echo "unknown opmode=$opmode"
+ fi
+ fi
+ done
+ if [ $counter == 0 ]; then
+ echo "Warning: \"$dll\" not found. \$counter=$counter." >&2
+ else
+ echo "Found dll $dll in the list. \$counter=$counter" >&2
+ fi
+done
+
+rm -rf "$tmp"