diff --git a/pkgs/os-specific/cygwin/cygwin-dll-link-hook/cygwin-dll-link.sh b/pkgs/os-specific/cygwin/cygwin-dll-link-hook/cygwin-dll-link.sh index f5d1ae8e0a9c..006dc0408cd0 100644 --- a/pkgs/os-specific/cygwin/cygwin-dll-link-hook/cygwin-dll-link.sh +++ b/pkgs/os-specific/cygwin/cygwin-dll-link-hook/cygwin-dll-link.sh @@ -28,20 +28,24 @@ declare -Ag _linkDeps_visited _linkDeps() { local target="$1" dir="$2" + + # canonicalise these for the dictionary + target=$(realpath -s "$target") + dir=$(realpath -s "$dir") + if [[ -v _linkDeps_visited[$target] ]]; then echo "_linkDeps: $target was already linked." 1>&2 return fi - if [[ ! -f "$target" || ! -x "$target" ]]; then + if [[ ! -f $target || ! -x $target ]]; then echo "_linkDeps: $target is not an executable file, skipping." 1>&2 return fi - local realTarget output inOutput - realTarget="$(readlink -f "$target")" + local output inOutput for output in $outputs ; do - if [[ $realTarget == "${!output}"* ]]; then - echo "_linkDeps: $target ($realTarget) is in $output (${!output})." 1>&2 + if [[ $target == "${!output}"* && ! -L $target ]]; then + echo "_linkDeps: $target is in $output (${!output})." 1>&2 inOutput=1 break fi @@ -51,25 +55,32 @@ _linkDeps() { local dll while read -r dll; do echo ' dll:' "$dll" - if [[ -v _linkDeps_visited[$dir/$dll] ]]; then + local dllPath=$dir/$dll + if [[ -v _linkDeps_visited[$dllPath] ]]; then echo "_linkDeps: $dll was already linked into $dir." 1>&2 continue fi - if [[ -L "$dir/$dll" || -e "$dir/$dll" ]]; then - echo ' already exists' - _linkDeps "$dir/$dll" "$dir" + if [[ -L $dllPath ]]; then + echo ' already linked' + dllPath=$(realpath -s "$(readlink "$dllPath")") + _linkDeps "$dllPath" "$dir" + elif [[ -e $dllPath ]]; then + echo ' already exits' + _linkDeps "$dllPath" "$dir" else - local dllPath if [[ $dll = cygwin1.dll ]]; then dllPath=/bin/cygwin1.dll else - local searchPath - searchPath=$(dirname "$target"):$_linkDeps_outputPath:$_linkDeps_inputPath:$HOST_PATH - # Locate the DLL - it should be an *executable* file on $HOST_PATH. - # This intentionally doesn't use $dir because we want to prefer dependencies - # that are already linked next to the target. - if ! dllPath="$(PATH="$searchPath" type -P "$dll")"; then - if [[ -z "$inOutput" || -n "${allowedImpureDLLsMap[$dll]}" ]]; then + # This intentionally doesn't use $dir because we want to prefer + # dependencies that are already linked next to the target. + local searchPath realTarget + searchPath=$_linkDeps_outputPath:$_linkDeps_inputPath:$HOST_PATH + if [[ -L $target ]]; then + searchPath=$searchPath:$(dirname "$(readlink "$target")") + fi + searchPath=$(dirname "$target"):$searchPath + if ! dllPath=$(PATH="$searchPath" type -P "$dll"); then + if [[ -z $inOutput || -n ${allowedImpureDLLsMap[$dll]} ]]; then continue fi echo unable to find "$dll" in "$searchPath" >&2 @@ -82,6 +93,7 @@ _linkDeps() { fi _linkDeps_visited[$dir/$dll]=1 done < <(_dllDeps "$target") + wait $! } # linkDLLsDir can be used to override the destination path for links. This is @@ -94,7 +106,7 @@ linkDLLs() { # shellcheck disable=SC2154 ( set -e - shopt -s globstar nullglob + shopt -s globstar nullglob dotglob local -a allowedImpureDLLsArray concatTo allowedImpureDLLsArray allowedImpureDLLs