From 385fb523320da4617966e34fcd586beecfcc9014 Mon Sep 17 00:00:00 2001
From: ras0219 <533828+ras0219@users.noreply.github.com>
Date: Mon, 13 Jul 2020 13:43:39 -0700
Subject: [PATCH] [vcpkg] Track hashes of cmake script helpers in consuming
 portfiles (#12254)

* [vcpkg] Track hashes of cmake script helpers in consuming portfiles

* [vcpkg] Format

* [vcpkg_find_acquire_program] Use cpkg_from_sourceforge for FLEX and BISON

Co-authored-by: Robert Schumacher <roschuma@microsoft.com>
---
 docs/maintainers/portfile-functions.md        |   8 +-
 docs/maintainers/vcpkg_build_make.md          |  16 ++-
 docs/maintainers/vcpkg_common_definitions.md  |   1 +
 docs/maintainers/vcpkg_configure_make.md      |  22 +--
 .../maintainers/vcpkg_find_acquire_program.md |   2 +-
 docs/maintainers/vcpkg_fixup_pkgconfig.md     |  42 ++++++
 docs/maintainers/vcpkg_from_sourceforge.md    | 125 +++++++++---------
 .../cmake/vcpkg_find_acquire_program.cmake    | 108 +++++++--------
 scripts/cmake/vcpkg_from_sourceforge.cmake    |  14 +-
 toolsrc/include/vcpkg/vcpkgpaths.h            |   1 +
 toolsrc/src/vcpkg/build.cpp                   |  16 ++-
 toolsrc/src/vcpkg/vcpkgpaths.cpp              |  22 +++
 12 files changed, 229 insertions(+), 148 deletions(-)
 create mode 100644 docs/maintainers/vcpkg_fixup_pkgconfig.md

diff --git a/docs/maintainers/portfile-functions.md b/docs/maintainers/portfile-functions.md
index 591516466..aec901dc4 100644
--- a/docs/maintainers/portfile-functions.md
+++ b/docs/maintainers/portfile-functions.md
@@ -1,5 +1,5 @@
-<!-- Run regenerate.ps1 to extract documentation from scripts\cmake\*.cmake -->
-
+<!-- Run regenerate.ps1 to extract documentation from scripts\cmake\*.cmake -->
+
 # Portfile helper functions
 - [execute\_process](execute_process.md)
 - [vcpkg\_acquire\_msys](vcpkg_acquire_msys.md)
@@ -21,8 +21,8 @@
 - [vcpkg\_configure\_make](vcpkg_configure_make.md)
 - [vcpkg\_configure\_meson](vcpkg_configure_meson.md)
 - [vcpkg\_copy\_pdbs](vcpkg_copy_pdbs.md)
-- [vcpkg\_copy\_tool\_dependencies](vcpkg_copy_tool_dependencies.md)
 - [vcpkg\_copy\_tools](vcpkg_copy_tools.md)
+- [vcpkg\_copy\_tool\_dependencies](vcpkg_copy_tool_dependencies.md)
 - [vcpkg\_download\_distfile](vcpkg_download_distfile.md)
 - [vcpkg\_execute\_build\_process](vcpkg_execute_build_process.md)
 - [vcpkg\_execute\_required\_process](vcpkg_execute_required_process.md)
@@ -31,10 +31,12 @@
 - [vcpkg\_fail\_port\_install](vcpkg_fail_port_install.md)
 - [vcpkg\_find\_acquire\_program](vcpkg_find_acquire_program.md)
 - [vcpkg\_fixup\_cmake\_targets](vcpkg_fixup_cmake_targets.md)
+- [vcpkg\_fixup\_pkgconfig](vcpkg_fixup_pkgconfig.md)
 - [vcpkg\_from\_bitbucket](vcpkg_from_bitbucket.md)
 - [vcpkg\_from\_git](vcpkg_from_git.md)
 - [vcpkg\_from\_github](vcpkg_from_github.md)
 - [vcpkg\_from\_gitlab](vcpkg_from_gitlab.md)
+- [vcpkg\_from\_sourceforge](vcpkg_from_sourceforge.md)
 - [vcpkg\_install\_cmake](vcpkg_install_cmake.md)
 - [vcpkg\_install\_gn](vcpkg_install_gn.md)
 - [vcpkg\_install\_make](vcpkg_install_make.md)
diff --git a/docs/maintainers/vcpkg_build_make.md b/docs/maintainers/vcpkg_build_make.md
index 5161ba3ce..3332191d1 100644
--- a/docs/maintainers/vcpkg_build_make.md
+++ b/docs/maintainers/vcpkg_build_make.md
@@ -4,16 +4,26 @@ Build a linux makefile project.
 
 ## Usage:
 ```cmake
-vcpkg_build_make([TARGET <target>])
+vcpkg_build_make([BUILD_TARGET <target>]
+                 [ADD_BIN_TO_PATH]
+                 [ENABLE_INSTALL])
+                 [LOGFILE_ROOT <logfileroot>])
 ```
 
-### TARGET
-The target passed to the configure/make build command (`./configure/make/make install`). If not specified, no target will
+### BUILD_TARGET
+The target passed to the make build command (`./make <target>`). If not specified, the 'all' target will
 be passed.
 
 ### ADD_BIN_TO_PATH
 Adds the appropriate Release and Debug `bin\` directories to the path during the build such that executables can run against the in-tree DLLs.
 
+### ENABLE_INSTALL
+IF the port supports the install target use vcpkg_install_make() instead of vcpkg_build_make()
+
+### BUILD_TARGET
+The target passed to the make build command (`./make <target>`). If not specified, the 'all' target will
+be passed.
+
 ## Notes:
 This command should be preceeded by a call to [`vcpkg_configure_make()`](vcpkg_configure_make.md).
 You can use the alias [`vcpkg_install_make()`](vcpkg_configure_make.md) function if your CMake script supports the
diff --git a/docs/maintainers/vcpkg_common_definitions.md b/docs/maintainers/vcpkg_common_definitions.md
index 276e04190..21b05aa1d 100644
--- a/docs/maintainers/vcpkg_common_definitions.md
+++ b/docs/maintainers/vcpkg_common_definitions.md
@@ -16,6 +16,7 @@ VCPKG_TARGET_IMPORT_LIBRARY_PREFIX       import library prefix for target (same
 VCPKG_TARGET_IMPORT_LIBRARY_SUFFIX       import library suffix for target (same as CMAKE_IMPORT_LIBRARY_SUFFIX)
 VCPKG_FIND_LIBRARY_PREFIXES              target dependent prefixes used for find_library calls in portfiles
 VCPKG_FIND_LIBRARY_SUFFIXES              target dependent suffixes used for find_library calls in portfiles
+VCPKG_SYSTEM_LIBRARIES                   list of libraries are provide by the toolchain and are not managed by vcpkg
 ```
 
 CMAKE_STATIC_LIBRARY_(PREFIX|SUFFIX), CMAKE_SHARED_LIBRARY_(PREFIX|SUFFIX) and CMAKE_IMPORT_LIBRARY_(PREFIX|SUFFIX) are defined for the target
diff --git a/docs/maintainers/vcpkg_configure_make.md b/docs/maintainers/vcpkg_configure_make.md
index a18621794..43f7e45f1 100644
--- a/docs/maintainers/vcpkg_configure_make.md
+++ b/docs/maintainers/vcpkg_configure_make.md
@@ -7,9 +7,6 @@ Configure configure for Debug and Release builds of a project.
 vcpkg_configure_make(
     SOURCE_PATH <${SOURCE_PATH}>
     [AUTOCONFIG]
-    [DISABLE_AUTO_HOST]
-    [DISABLE_AUTO_DST]
-    [GENERATOR]
     [NO_DEBUG]
     [SKIP_CONFIGURE]
     [PROJECT_SUBPATH <${PROJ_SUBPATH}>]
@@ -28,10 +25,6 @@ By convention, this is usually set in the portfile as the variable `SOURCE_PATH`
 ### PROJECT_SUBPATH
 Specifies the directory containing the ``configure`/`configure.ac`.
 By convention, this is usually set in the portfile as the variable `SOURCE_PATH`.
-Should use `GENERATOR NMake` first.
-
-### NO_DEBUG
-This port doesn't support debug mode.
 
 ### SKIP_CONFIGURE
 Skip configure process
@@ -39,21 +32,8 @@ Skip configure process
 ### AUTOCONFIG
 Need to use autoconfig to generate configure file.
 
-### DISABLE_AUTO_HOST
-Don't set host automatically, the default value is `i686`.
-If use this option, you will need to set host manually.
-
-### DISABLE_AUTO_DST
-Don't set installation path automatically, the default value is `${CURRENT_PACKAGES_DIR}` and `${CURRENT_PACKAGES_DIR}/debug`
-If use this option, you will need to set dst path manually.
-
-### GENERATOR
-Specifies the precise generator to use.
-NMake: nmake(windows) make(unix)
-MAKE: make(windows) make(unix)
-
 ### PRERUN_SHELL
-Script that needs to be called before configuration
+Script that needs to be called before configuration (do not use for batch files which simply call autoconf or configure)
 
 ### OPTIONS
 Additional options passed to configure during the configuration.
diff --git a/docs/maintainers/vcpkg_find_acquire_program.md b/docs/maintainers/vcpkg_find_acquire_program.md
index 461d13822..a838bb974 100644
--- a/docs/maintainers/vcpkg_find_acquire_program.md
+++ b/docs/maintainers/vcpkg_find_acquire_program.md
@@ -44,4 +44,4 @@ Note that msys2 has a dedicated helper function: [`vcpkg_acquire_msys`](vcpkg_ac
 * [qt5](https://github.com/Microsoft/vcpkg/blob/master/ports/qt5/portfile.cmake)
 
 ## Source
-[scripts/cmake/vcpkg_find_acquire_program.cmake](https://github.com/Microsoft/vcpkg/blob/master/scripts/cmake/vcpkg_find_acquire_program.cmake)
+[scripts/cmake/vcpkg_find_acquire_program.cmake](https://github.com/Microsoft/vcpkg/blob/master/scripts/cmake/vcpkg_find_acquire_program.cmake)
diff --git a/docs/maintainers/vcpkg_fixup_pkgconfig.md b/docs/maintainers/vcpkg_fixup_pkgconfig.md
new file mode 100644
index 000000000..25c6aae5d
--- /dev/null
+++ b/docs/maintainers/vcpkg_fixup_pkgconfig.md
@@ -0,0 +1,42 @@
+# vcpkg_fixup_pkgconfig
+
+Fix common paths in *.pc files and make everything relativ to $(prefix)
+
+## Usage
+```cmake
+vcpkg_fixup_pkgconfig(
+    [RELEASE_FILES <PATHS>...]
+    [DEBUG_FILES <PATHS>...]
+    [SYSTEM_LIBRARIES <NAMES>...]
+)
+```
+
+## Parameters
+### RELEASE_FILES
+Specifies a list of files to apply the fixes for release paths.
+Defaults to every *.pc file in the folder ${CURRENT_PACKAGES_DIR} without ${CURRENT_PACKAGES_DIR}/debug/
+
+### DEBUG_FILES
+Specifies a list of files to apply the fixes for debug paths.
+Defaults to every *.pc file in the folder ${CURRENT_PACKAGES_DIR}/debug/
+
+### SYSTEM_PACKAGES
+If the *.pc file contains system packages outside vcpkg these need to be listed here.
+Since vcpkg checks the existence of all required packages within vcpkg.
+
+### SYSTEM_LIBRARIES
+If the *.pc file contains system libraries outside vcpkg these need to be listed here.
+VCPKG checks every -l flag for the existence of the required library within vcpkg.
+
+### IGNORE_FLAGS
+If the *.pc file contains flags in the lib field which are not libraries. These can be listed here
+
+## Notes
+Still work in progress. If there are more cases which can be handled here feel free to add them
+
+## Examples
+
+Just call vcpkg_fixup_pkgconfig() after any install step which installs *.pc files.
+
+## Source
+[scripts/cmake/vcpkg_fixup_pkgconfig.cmake](https://github.com/Microsoft/vcpkg/blob/master/scripts/cmake/vcpkg_fixup_pkgconfig.cmake)
diff --git a/docs/maintainers/vcpkg_from_sourceforge.md b/docs/maintainers/vcpkg_from_sourceforge.md
index faad06215..c5b5ae6e8 100644
--- a/docs/maintainers/vcpkg_from_sourceforge.md
+++ b/docs/maintainers/vcpkg_from_sourceforge.md
@@ -1,63 +1,68 @@
-# vcpkg_from_sourceforge
-
-Download and extract a project from sourceforge.
-
-## Usage:
-```cmake
+# vcpkg_from_sourceforge
+
+Download and extract a project from sourceforge.
+
+## Usage:
+```cmake
 vcpkg_from_sourceforge(
-    OUT_SOURCE_PATH SOURCE_PATH
-    REPO <cunit/CUnit>
+    OUT_SOURCE_PATH SOURCE_PATH
+    REPO <cunit/CUnit>
     [REF <2.1-3>]
-    SHA512 <547b417109332...>
-    FILENAME <CUnit-2.1-3.tar.bz2>
-    [DISABLE_SSL]
-    [NO_REMOVE_ONE_LEVEL]
-    [PATCHES <patch1.patch> <patch2.patch>...]
-)
-```
-
-## Parameters:
-### OUT_SOURCE_PATH
-Specifies the out-variable that will contain the extracted location.
-
-This should be set to `SOURCE_PATH` by convention.
-
-### REPO
-The organization or user and repository (optional) on sourceforge.
-
-### REF
-A stable version number that will not change contents.
-
-### FILENAME
-The local name for the file. Files are shared between ports, so the file may need to be renamed to make it clearly attributed to this port and avoid conflicts.
-
-For example, we can get the download link:
-https://sourceforge.net/settings/mirror_choices?projectname=mad&filename=libmad/0.15.1b/libmad-0.15.1b.tar.gz&selected=nchc
-So the REPO is `mad/libmad`, the REF is `0.15.1b`, and the FILENAME is `libmad-0.15.1b.tar.gz`
-
-For some special links:
-https://sourceforge.net/settings/mirror_choices?projectname=soxr&filename=soxr-0.1.3-Source.tar.xz&selected=nchc
-The REPO is `soxr`, REF is not exist, and the FILENAME is `soxr-0.1.3-Source.tar.xz`
-
-### SHA512
-The SHA512 hash that should match the archive.
-
-### PATCHES
-A list of patches to be applied to the extracted sources.
-
-Relative paths are based on the port directory.
-
-### DISABLE_SSL
-Disable ssl when downloading source.
-
-### NO_REMOVE_ONE_LEVEL
-Specifies that the default removal of the top level folder should not occur.
-
-## Examples:
-
-* [cunit](https://github.com/Microsoft/vcpkg/blob/master/ports/cunit/portfile.cmake)
-* [polyclipping](https://github.com/Microsoft/vcpkg/blob/master/ports/polyclipping/portfile.cmake)
-* [tinyfiledialogs](https://github.com/Microsoft/vcpkg/blob/master/ports/tinyfiledialogs/portfile.cmake)
-
-## Source
+    SHA512 <547b417109332...>
+    FILENAME <CUnit-2.1-3.tar.bz2>
+    [DISABLE_SSL]
+    [NO_REMOVE_ONE_LEVEL]
+    [PATCHES <patch1.patch> <patch2.patch>...]
+)
+```
+
+## Parameters:
+### OUT_SOURCE_PATH
+Specifies the out-variable that will contain the extracted location.
+
+This should be set to `SOURCE_PATH` by convention.
+
+### REPO
+The organization or user and repository (optional) on sourceforge.
+
+### REF
+A stable version number that will not change contents.
+
+### FILENAME
+The local name for the file. Files are shared between ports, so the file may need to be renamed to make it clearly attributed to this port and avoid conflicts.
+
+For example, we can get the download link:
+https://sourceforge.net/settings/mirror_choices?projectname=mad&filename=libmad/0.15.1b/libmad-0.15.1b.tar.gz&selected=nchc
+So the REPO is `mad/libmad`, the REF is `0.15.1b`, and the FILENAME is `libmad-0.15.1b.tar.gz`
+
+For some special links:
+https://sourceforge.net/settings/mirror_choices?projectname=soxr&filename=soxr-0.1.3-Source.tar.xz&selected=nchc
+The REPO is `soxr`, REF is not exist, and the FILENAME is `soxr-0.1.3-Source.tar.xz`
+
+### SHA512
+The SHA512 hash that should match the archive.
+
+### WORKING_DIRECTORY
+If specified, the archive will be extracted into the working directory instead of `${CURRENT_BUILDTREES_DIR}/src/`.
+
+Note that the archive will still be extracted into a subfolder underneath that directory (`${WORKING_DIRECTORY}/${REF}-${HASH}/`).
+
+### PATCHES
+A list of patches to be applied to the extracted sources.
+
+Relative paths are based on the port directory.
+
+### DISABLE_SSL
+Disable ssl when downloading source.
+
+### NO_REMOVE_ONE_LEVEL
+Specifies that the default removal of the top level folder should not occur.
+
+## Examples:
+
+* [cunit](https://github.com/Microsoft/vcpkg/blob/master/ports/cunit/portfile.cmake)
+* [polyclipping](https://github.com/Microsoft/vcpkg/blob/master/ports/polyclipping/portfile.cmake)
+* [tinyfiledialogs](https://github.com/Microsoft/vcpkg/blob/master/ports/tinyfiledialogs/portfile.cmake)
+
+## Source
 [scripts/cmake/vcpkg_from_sourceforge.cmake](https://github.com/Microsoft/vcpkg/blob/master/scripts/cmake/vcpkg_from_sourceforge.cmake)
diff --git a/scripts/cmake/vcpkg_find_acquire_program.cmake b/scripts/cmake/vcpkg_find_acquire_program.cmake
index 58a5380c2..a5aefdc29 100644
--- a/scripts/cmake/vcpkg_find_acquire_program.cmake
+++ b/scripts/cmake/vcpkg_find_acquire_program.cmake
@@ -244,33 +244,28 @@ function(vcpkg_find_acquire_program VAR)
     set(URL "https://github.com/mesonbuild/meson/archive/0.54.2.zip")
     set(ARCHIVE "meson-0.54.2.zip")
     set(HASH 8d19110bad3e6a223d1d169e833b746b884ece9cd23d2539ec02dccb5cd0c56542414b7afc0f7f2adcec9d957e4120d31f41734397aa0a7ee7f9c29ebdc9eb4c)
-  elseif(VAR MATCHES "FLEX")
+  elseif(VAR MATCHES "FLEX" OR VAR MATCHES "BISON")
     if(CMAKE_HOST_WIN32)
-      set(PROGNAME win_flex)
-      set(SUBDIR win_flex-2.5.16)
-      set(PATHS ${DOWNLOADS}/tools/win_flex/${SUBDIR})
-      set(URL "https://sourceforge.net/projects/winflexbison/files/winflexbison-2.5.16.zip/download")
-      set(ARCHIVE "win_flex_bison-2.5.16.zip")
-      set(HASH 0a14154bff5d998feb23903c46961528f8ccb4464375d5384db8c4a7d230c0c599da9b68e7a32f3217a0a0735742242eaf3769cb4f03e00931af8640250e9123)
+      set(SOURCEFORGE_ARGS
+        REPO winflexbison
+        FILENAME winflexbison-2.5.16.zip
+        SHA512 0a14154bff5d998feb23903c46961528f8ccb4464375d5384db8c4a7d230c0c599da9b68e7a32f3217a0a0735742242eaf3769cb4f03e00931af8640250e9123
+        NO_REMOVE_ONE_LEVEL
+        WORKING_DIRECTORY "${DOWNLOADS}/tools/winflexbison"
+      )
+      if(VAR MATCHES "FLEX")
+        set(PROGNAME win_flex)
+      else()
+        set(PROGNAME win_bison)
+      endif()
+      set(PATHS ${DOWNLOADS}/tools/winflexbison/0a14154bff-a8cf65db07)
       if(NOT EXISTS "${PATHS}/data/m4sugar/m4sugar.m4")
         file(REMOVE_RECURSE "${PATHS}")
       endif()
-    else()
+    elseif(VAR MATCHES "FLEX")
       set(PROGNAME flex)
       set(APT_PACKAGE_NAME flex)
       set(BREW_PACKAGE_NAME flex)
-    endif()
-  elseif(VAR MATCHES "BISON")
-    if(CMAKE_HOST_WIN32)
-      set(PROGNAME win_bison)
-      set(SUBDIR win_bison-2.5.16)
-      set(PATHS ${DOWNLOADS}/tools/win_bison/${SUBDIR})
-      set(URL "https://sourceforge.net/projects/winflexbison/files/winflexbison-2.5.16.zip/download")
-      set(ARCHIVE "win_flex_bison-2.5.16.zip")
-      set(HASH 0a14154bff5d998feb23903c46961528f8ccb4464375d5384db8c4a7d230c0c599da9b68e7a32f3217a0a0735742242eaf3769cb4f03e00931af8640250e9123)
-      if(NOT EXISTS "${PATHS}/data/m4sugar/m4sugar.m4")
-        file(REMOVE_RECURSE "${PATHS}")
-      endif()
     else()
       set(PROGNAME bison)
       set(APT_PACKAGE_NAME bison)
@@ -378,41 +373,48 @@ function(vcpkg_find_acquire_program VAR)
       message(FATAL_ERROR "Could not find ${PROGNAME}. Please install it via your package manager${EXAMPLE}")
     endif()
 
-    vcpkg_download_distfile(ARCHIVE_PATH
-        URLS ${URL}
-        SHA512 ${HASH}
-        FILENAME ${ARCHIVE}
-    )
-
-    set(PROG_PATH_SUBDIR "${DOWNLOADS}/tools/${PROGNAME}/${SUBDIR}")
-    file(MAKE_DIRECTORY ${PROG_PATH_SUBDIR})
-    if(DEFINED NOEXTRACT)
-      if(DEFINED _vfa_RENAME)
-        file(INSTALL ${ARCHIVE_PATH} DESTINATION ${PROG_PATH_SUBDIR} RENAME ${_vfa_RENAME} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
-      else()
-        file(COPY ${ARCHIVE_PATH} DESTINATION ${PROG_PATH_SUBDIR} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
-      endif()
+    if(DEFINED SOURCEFORGE_ARGS)
+      # Locally change editable to suppress re-extraction each time
+      set(_VCPKG_EDITABLE 1)
+      vcpkg_from_sourceforge(OUT_SOURCE_PATH SFPATH ${SOURCEFORGE_ARGS})
+      unset(_VCPKG_EDITABLE)
     else()
-      get_filename_component(ARCHIVE_EXTENSION ${ARCHIVE} LAST_EXT)
-      string(TOLOWER "${ARCHIVE_EXTENSION}" ARCHIVE_EXTENSION)
-      if(ARCHIVE_EXTENSION STREQUAL ".msi")
-        file(TO_NATIVE_PATH "${ARCHIVE_PATH}" ARCHIVE_NATIVE_PATH)
-        file(TO_NATIVE_PATH "${PROG_PATH_SUBDIR}" DESTINATION_NATIVE_PATH)
-        _execute_process(
-          COMMAND msiexec /a ${ARCHIVE_NATIVE_PATH} /qn TARGETDIR=${DESTINATION_NATIVE_PATH}
-          WORKING_DIRECTORY ${DOWNLOADS}
-        )
-      elseif("${ARCHIVE_PATH}" MATCHES ".7z.exe$")
-        vcpkg_find_acquire_program(7Z)
-        _execute_process(
-          COMMAND ${7Z} x "${ARCHIVE_PATH}" "-o${PROG_PATH_SUBDIR}" -y -bso0 -bsp0
-          WORKING_DIRECTORY ${PROG_PATH_SUBDIR}
-        )
+      vcpkg_download_distfile(ARCHIVE_PATH
+          URLS ${URL}
+          SHA512 ${HASH}
+          FILENAME ${ARCHIVE}
+      )
+
+      set(PROG_PATH_SUBDIR "${DOWNLOADS}/tools/${PROGNAME}/${SUBDIR}")
+      file(MAKE_DIRECTORY ${PROG_PATH_SUBDIR})
+      if(DEFINED NOEXTRACT)
+        if(DEFINED _vfa_RENAME)
+          file(INSTALL ${ARCHIVE_PATH} DESTINATION ${PROG_PATH_SUBDIR} RENAME ${_vfa_RENAME} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
+        else()
+          file(COPY ${ARCHIVE_PATH} DESTINATION ${PROG_PATH_SUBDIR} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
+        endif()
       else()
-        _execute_process(
-          COMMAND ${CMAKE_COMMAND} -E tar xzf ${ARCHIVE_PATH}
-          WORKING_DIRECTORY ${PROG_PATH_SUBDIR}
-        )
+        get_filename_component(ARCHIVE_EXTENSION ${ARCHIVE} LAST_EXT)
+        string(TOLOWER "${ARCHIVE_EXTENSION}" ARCHIVE_EXTENSION)
+        if(ARCHIVE_EXTENSION STREQUAL ".msi")
+          file(TO_NATIVE_PATH "${ARCHIVE_PATH}" ARCHIVE_NATIVE_PATH)
+          file(TO_NATIVE_PATH "${PROG_PATH_SUBDIR}" DESTINATION_NATIVE_PATH)
+          _execute_process(
+            COMMAND msiexec /a ${ARCHIVE_NATIVE_PATH} /qn TARGETDIR=${DESTINATION_NATIVE_PATH}
+            WORKING_DIRECTORY ${DOWNLOADS}
+          )
+        elseif("${ARCHIVE_PATH}" MATCHES ".7z.exe$")
+          vcpkg_find_acquire_program(7Z)
+          _execute_process(
+            COMMAND ${7Z} x "${ARCHIVE_PATH}" "-o${PROG_PATH_SUBDIR}" -y -bso0 -bsp0
+            WORKING_DIRECTORY ${PROG_PATH_SUBDIR}
+          )
+        else()
+          _execute_process(
+            COMMAND ${CMAKE_COMMAND} -E tar xzf ${ARCHIVE_PATH}
+            WORKING_DIRECTORY ${PROG_PATH_SUBDIR}
+          )
+        endif()
       endif()
     endif()
 
diff --git a/scripts/cmake/vcpkg_from_sourceforge.cmake b/scripts/cmake/vcpkg_from_sourceforge.cmake
index 258499242..34b2a12b0 100644
--- a/scripts/cmake/vcpkg_from_sourceforge.cmake
+++ b/scripts/cmake/vcpkg_from_sourceforge.cmake
@@ -42,6 +42,11 @@
 ## ### SHA512
 ## The SHA512 hash that should match the archive.
 ##
+## ### WORKING_DIRECTORY
+## If specified, the archive will be extracted into the working directory instead of `${CURRENT_BUILDTREES_DIR}/src/`.
+##
+## Note that the archive will still be extracted into a subfolder underneath that directory (`${WORKING_DIRECTORY}/${REF}-${HASH}/`).
+##
 ## ### PATCHES
 ## A list of patches to be applied to the extracted sources.
 ##
@@ -61,7 +66,7 @@
 
 function(vcpkg_from_sourceforge)
     set(booleanValueArgs DISABLE_SSL NO_REMOVE_ONE_LEVEL)
-    set(oneValueArgs OUT_SOURCE_PATH REPO REF SHA512 FILENAME)
+    set(oneValueArgs OUT_SOURCE_PATH REPO REF SHA512 FILENAME WORKING_DIRECTORY)
     set(multipleValuesArgs PATCHES)
     cmake_parse_arguments(_vdus "${booleanValueArgs}" "${oneValueArgs}" "${multipleValuesArgs}" ${ARGN})
 
@@ -77,6 +82,12 @@ function(vcpkg_from_sourceforge)
         message(FATAL_ERROR "The sourceforge repository must be specified.")
     endif()
 
+    if(DEFINED _vdus_WORKING_DIRECTORY)
+        set(WORKING_DIRECTORY WORKING_DIRECTORY "${_vdus_WORKING_DIRECTORY}")
+    else()
+        set(WORKING_DIRECTORY)
+    endif()
+
     if (_vdus_DISABLE_SSL)
         set(URL_PROTOCOL http:)
     else()
@@ -181,6 +192,7 @@ function(vcpkg_from_sourceforge)
         ARCHIVE "${ARCHIVE}"
         REF "${SANITIZED_REF}"
         ${NO_REMOVE_ONE_LEVEL}
+        ${WORKING_DIRECTORY}
         PATCHES ${_vdus_PATCHES}
     )
 
diff --git a/toolsrc/include/vcpkg/vcpkgpaths.h b/toolsrc/include/vcpkg/vcpkgpaths.h
index c9168f149..594407c4b 100644
--- a/toolsrc/include/vcpkg/vcpkgpaths.h
+++ b/toolsrc/include/vcpkg/vcpkgpaths.h
@@ -83,6 +83,7 @@ namespace vcpkg
         bool is_valid_triplet(Triplet t) const;
         const std::vector<std::string> get_available_triplets_names() const;
         const std::vector<TripletFile>& get_available_triplets() const;
+        const std::map<std::string, std::string>& get_cmake_script_hashes() const;
         const fs::path get_triplet_file_path(Triplet triplet) const;
 
         fs::path original_cwd;
diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp
index be8004875..a0e138339 100644
--- a/toolsrc/src/vcpkg/build.cpp
+++ b/toolsrc/src/vcpkg/build.cpp
@@ -836,12 +836,16 @@ namespace vcpkg::Build
         abi_tag_entries.emplace_back("powershell", paths.get_tool_version("powershell-core"));
 #endif
 
-        abi_tag_entries.emplace_back(
-            "vcpkg_fixup_cmake_targets",
-            vcpkg::Hash::get_file_hash(VCPKG_LINE_INFO,
-                                       fs,
-                                       paths.scripts / "cmake" / "vcpkg_fixup_cmake_targets.cmake",
-                                       Hash::Algorithm::Sha1));
+        auto& helpers = paths.get_cmake_script_hashes();
+        auto portfile_contents =
+            fs.read_contents(port_dir / fs::u8path("portfile.cmake")).value_or_exit(VCPKG_LINE_INFO);
+        for (auto&& helper : helpers)
+        {
+            if (Strings::case_insensitive_ascii_contains(portfile_contents, helper.first))
+            {
+                abi_tag_entries.emplace_back(helper.first, helper.second);
+            }
+        }
 
         abi_tag_entries.emplace_back("post_build_checks", "2");
         std::vector<std::string> sorted_feature_list = action.feature_list;
diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp
index 4a9fd7a82..4837c4b71 100644
--- a/toolsrc/src/vcpkg/vcpkgpaths.cpp
+++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp
@@ -2,6 +2,7 @@
 
 #include <vcpkg/base/expected.h>
 #include <vcpkg/base/files.h>
+#include <vcpkg/base/hash.h>
 #include <vcpkg/base/system.debug.h>
 #include <vcpkg/base/system.process.h>
 #include <vcpkg/base/util.h>
@@ -90,6 +91,7 @@ namespace vcpkg
 
             Lazy<std::vector<VcpkgPaths::TripletFile>> available_triplets;
             Lazy<std::vector<Toolset>> toolsets;
+            Lazy<std::map<std::string, std::string>> cmake_script_hashes;
 
             Files::Filesystem* fs_ptr;
 
@@ -286,6 +288,26 @@ If you wish to silence this error and use classic mode, you can:
         });
     }
 
+    const std::map<std::string, std::string>& VcpkgPaths::get_cmake_script_hashes() const
+    {
+        return m_pimpl->cmake_script_hashes.get_lazy([this]() -> std::map<std::string, std::string> {
+            auto& fs = this->get_filesystem();
+            std::map<std::string, std::string> helpers;
+            auto files = fs.get_files_non_recursive(this->scripts / fs::u8path("cmake"));
+            auto common_functions = fs::u8path("vcpkg_common_functions");
+            for (auto&& file : files)
+            {
+                auto stem = file.stem();
+                if (stem != common_functions)
+                {
+                    helpers.emplace(stem.u8string(),
+                                    Hash::get_file_hash(VCPKG_LINE_INFO, fs, file, Hash::Algorithm::Sha1));
+                }
+            }
+            return helpers;
+        });
+    }
+
     const fs::path VcpkgPaths::get_triplet_file_path(Triplet triplet) const
     {
         return m_pimpl->m_triplets_cache.get_lazy(
