-
-
Notifications
You must be signed in to change notification settings - Fork 14.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #252459 from brano543/win-dll-link
- Loading branch information
Showing
2 changed files
with
93 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,89 @@ | ||
|
||
fixupOutputHooks+=(_linkDLLs) | ||
|
||
# For every *.{exe,dll} in $output/bin/ we try to find all (potential) | ||
# transitive dependencies and symlink those DLLs into $output/bin | ||
# so they are found on invocation. | ||
addEnvHooks "$targetOffset" linkDLLGetFolders | ||
|
||
linkDLLGetFolders() { | ||
addToSearchPath "LINK_DLL_FOLDERS" "$1/lib" | ||
addToSearchPath "LINK_DLL_FOLDERS" "$1/bin" | ||
} | ||
|
||
_linkDLLs() { | ||
linkDLLsInfolder "$prefix/bin" | ||
} | ||
|
||
# Try to links every known dependency of exe/dll in the folder of the 1str input | ||
# into said folder, so they are found on invocation. | ||
# (DLLs are first searched in the directory of the running exe file.) | ||
# The links are relative, so relocating whole /nix/store won't break them. | ||
_linkDLLs() { | ||
( | ||
if [ ! -d "$prefix/bin" ]; then exit; fi | ||
cd "$prefix/bin" | ||
|
||
# Compose path list where DLLs should be located: | ||
# prefix $PATH by currently-built outputs | ||
local DLLPATH="" | ||
local outName | ||
for outName in $(getAllOutputNames); do | ||
addToSearchPath DLLPATH "${!outName}/bin" | ||
done | ||
DLLPATH="$DLLPATH:$PATH" | ||
|
||
echo DLLPATH="'$DLLPATH'" | ||
|
||
linkCount=0 | ||
# Iterate over any DLL that we depend on. | ||
local dll | ||
for dll in $($OBJDUMP -p *.{exe,dll} | sed -n 's/.*DLL Name: \(.*\)/\1/p' | sort -u); do | ||
if [ -e "./$dll" ]; then continue; fi | ||
# Locate the DLL - it should be an *executable* file on $DLLPATH. | ||
local dllPath="$(PATH="$DLLPATH" type -P "$dll")" | ||
if [ -z "$dllPath" ]; then continue; fi | ||
# That DLL might have its own (transitive) dependencies, | ||
# so add also all DLLs from its directory to be sure. | ||
local dllPath2 | ||
for dllPath2 in "$dllPath" "$(dirname $(readlink "$dllPath" || echo "$dllPath"))"/*.dll; do | ||
if [ -e ./"$(basename "$dllPath2")" ]; then continue; fi | ||
CYGWIN+=\ winsymlinks:nativestrict ln -sr "$dllPath2" . | ||
linkCount=$(($linkCount+1)) | ||
linkDLLsInfolder() { | ||
( | ||
local folder | ||
folder="$1" | ||
if [ ! -d "$folder" ]; then | ||
echo "Not linking DLLs in the non-existent folder $folder" | ||
return | ||
fi | ||
cd "$folder" || exit | ||
|
||
# Use associative arrays as set | ||
local filesToChecks | ||
local filesDone | ||
declare -A filesToChecks # files that still needs to have their dependancies checked | ||
declare -A filesDone # files that had their dependancies checked and who is copied to the bin folder if found | ||
|
||
markFileAsDone() { | ||
if [ ! "${filesDone[$1]+a}" ]; then filesDone[$1]=a; fi | ||
if [ "${filesToChecks[$1]+a}" ]; then unset 'filesToChecks[$1]'; fi | ||
} | ||
|
||
addFileToLink() { | ||
if [ "${filesDone[$1]+a}" ]; then return; fi | ||
if [ ! "${filesToChecks[$1]+a}" ]; then filesToChecks[$1]=a; fi | ||
} | ||
|
||
# Compose path list where DLLs should be located: | ||
# prefix $PATH by currently-built outputs | ||
local DLLPATH="" | ||
local outName | ||
for outName in $(getAllOutputNames); do | ||
addToSearchPath DLLPATH "${!outName}/bin" | ||
done | ||
done | ||
echo "Created $linkCount DLL link(s) in $prefix/bin" | ||
) | ||
} | ||
DLLPATH="$DLLPATH:$LINK_DLL_FOLDERS" | ||
|
||
echo DLLPATH="'$DLLPATH'" | ||
|
||
for peFile in *.{exe,dll}; do | ||
if [ -e "./$peFile" ]; then | ||
addFileToLink "$peFile" | ||
fi | ||
done | ||
|
||
local searchPaths | ||
readarray -td: searchPaths < <(printf -- "%s" "$DLLPATH") | ||
|
||
local linkCount=0 | ||
while [ ${#filesToChecks[*]} -gt 0 ]; do | ||
local listOfDlls=("${!filesToChecks[@]}") | ||
local file=${listOfDlls[0]} | ||
markFileAsDone "$file" | ||
if [ ! -e "./$file" ]; then | ||
local pathsFound | ||
readarray -d '' pathsFound < <(find "${searchPaths[@]}" -name "$file" -type f -print0) | ||
if [ ${#pathsFound[@]} -eq 0 ]; then continue; fi | ||
local dllPath | ||
dllPath="${pathsFound[0]}" | ||
CYGWIN+=" winsymlinks:nativestrict" ln -sr "$dllPath" . | ||
echo "linking $dllPath" | ||
file="$dllPath" | ||
linkCount=$((linkCount + 1)) | ||
fi | ||
# local dep_file | ||
# Look at the file’s dependancies | ||
for dep_file in $($OBJDUMP -p "$file" | sed -n 's/.*DLL Name: \(.*\)/\1/p' | sort -u); do | ||
addFileToLink "$dep_file" | ||
done | ||
done | ||
|
||
echo "Created $linkCount DLL link(s) in $folder" | ||
) | ||
} |