Commit cbb96285 authored by David McFarland's avatar David McFarland
Browse files

cygwin-dll-link: allow linkDLLs to be used on individual dirs/files

parent f5353dd5
Loading
Loading
Loading
Loading
+75 −29
Original line number Diff line number Diff line
@@ -24,39 +24,74 @@ _dllDeps() {
    | sort -u
}

declare -Ag _linkDeps_visited

_linkDeps() {
  local target="$1" dir="$2" check="$3"
  [[ ! -x "$target" ]] && echo "_linkDeps: $target is not executable, skipping." 1>&2 && return
  local target="$1" dir="$2"
  if [[ -v _linkDeps_visited[$target] ]]; then
    echo "_linkDeps: $target was already linked." 1>&2
    return
  fi
  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")"
  for output in $outputs ; do
    if [[ $realTarget == "${!output}"* ]]; then
      echo "_linkDeps: $target ($realTarget) is in $output (${!output})." 1>&2
      inOutput=1
      break
    fi
  done

  echo 'target:' "$target"
  local dll
  _dllDeps "$target" | while read -r dll; do
  while read -r dll; do
    echo '  dll:' "$dll"
    if [[ -L "$dir/$dll" || -e "$dir/$dll" ]]; then continue; fi
    if [[ $dll = cygwin1.dll ]]; then
      CYGWIN+=\ winsymlinks:nativestrict ln -sr /bin/cygwin1.dll "$dir"
    if [[ -v _linkDeps_visited[$dir/$dll] ]]; then
      echo "_linkDeps: $dll was already linked into $dir." 1>&2
      continue
    fi
    # Locate the DLL - it should be an *executable* file on $HOST_PATH.
    local dllPath searchPath
    if [[ -L "$dir/$dll" || -e "$dir/$dll" ]]; then
      echo '    already exists'
      _linkDeps "$dir/$dll" "$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 "$check" || -n "${allowedImpureDLLsMap[$dll]}" ]]; then
          if [[ -z "$inOutput" || -n "${allowedImpureDLLsMap[$dll]}" ]]; then
            continue
          fi
          echo unable to find "$dll" in "$searchPath" >&2
          exit 1
        fi
      fi
      echo '    linking to:' "$dllPath"
      CYGWIN+=\ winsymlinks:nativestrict ln -sr "$dllPath" "$dir"
    # That DLL might have its own (transitive) dependencies,
    # so add also all DLLs from its directory to be sure.
    _linkDeps "$dllPath" "$dir" ""
  done
      _linkDeps "$dllPath" "$dir"
    fi
    _linkDeps_visited[$dir/$dll]=1
  done < <(_dllDeps "$target")
}

# linkDLLsDir can be used to override the destination path for links.  This is
# useful if you're trying to link dependencies of libraries into the directory
# containing an executable.
#
# Arguments can be a file or directory path. Directories are searched
# recursively.
linkDLLs() {
  # shellcheck disable=SC2154
  if [ ! -d "$prefix" ]; then return; fi
  (
    set -e
    shopt -s globstar nullglob
@@ -70,15 +105,26 @@ linkDLLs() {
      allowedImpureDLLsMap[$dll]=1
    done

    cd "$prefix"

    local target file
    for target in "$@"; do
      # Iterate over any DLL that we depend on.
    local target
    for target in {bin,lib,libexec}/**/*.{exe,dll}; do
      [[ ! -f "$target" || ! -x "$target" ]] ||
        _linkDeps "$target" "$(dirname "$target")" "1"
      if [[ -f "$target" ]]; then
        _linkDeps "$target" "${linkDLLsDir-$(dirname "$target")}"
      elif [[ -d "$target" ]]; then
        for file in "${target%/}"/**/*.{exe,dll}; do
          _linkDeps "$file" "${linkDLLsDir-$(dirname "$file")}"
        done
      else
        echo "linkDLLs: $target is not a file or directory, skipping." 1>&2
      fi
    done
  )
}

fixupOutputHooks+=(linkDLLs)
_linkDLLs() {
  # shellcheck disable=SC2154
  if [[ ! -d $prefix || ${dontLinkDLLs-} ]]; then return; fi
  linkDLLs "$prefix"/{bin,lib,libexec}/
}

fixupOutputHooks+=(_linkDLLs)