Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[vcpkg] Add experimental $X_VCPKG_ASSET_SOURCES for source caching #13639

Merged
merged 11 commits into from
Jun 4, 2021
43 changes: 43 additions & 0 deletions docs/users/assetcaching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Asset Caching

**The latest version of this documentation is available on [GitHub](https://github.com/Microsoft/vcpkg/tree/master/docs/users/assetcaching.md).**

**Experimental feature: this may change or be removed at any time**

Vcpkg can utilize mirrors to cache downloaded assets, ensuring continued operation even if the original source changes
or disappears.

In-tool help is available via `vcpkg help assetcaching`.

## Configuration

Asset caching can be configured by setting the environment variable `X_VCPKG_ASSET_SOURCES` to a semicolon-delimited
list of source strings. Characters can be escaped using backtick (\`).

### Valid source strings

The `<rw>` optional parameter for certain strings controls how they will be accessed. It can be specified as `read`,
`write`, or `readwrite` and defaults to `read`.

#### `clear`

Syntax: `clear`

Removes all previous sources

#### `x-azurl`

Syntax: `x-azurl,<url>[,<sas>[,<rw>]]`

Adds an Azure Blob Storage source, optionally using Shared Access Signature validation. URL should include the container
path and be terminated with a trailing `/`. SAS, if defined, should be prefixed with a `?`. Non-Azure servers will also
work if they respond to GET and PUT requests of the form: `<url><sha512><sas>`.

See also the [binary caching documentation for Azure Blob Storage](binarycaching.md#azure-blob-storage-experimental) for
more information on how to set up an `x-azurl` source.

#### `x-block-origin`

Syntax: `x-block-origin`

Disables use of the original URLs in case the mirror does not have the file available.
6 changes: 6 additions & 0 deletions docs/users/config-environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,9 @@ This environment variable changes the metadata of produced NuGet packages. See [
#### VCPKG_USE_NUGET_CACHE

This environment variable allows using NuGet's cache for every nuget-based binary source. See [Binary Caching](binarycaching.md#NuGets-cache) for more details.

#### X_VCPKG_ASSET_SOURCES

> Note: This is an experimental feature and may change or be removed at any time

This environment variable allows using a private mirror for all SHA512-tagged assets. See [Asset Caching](assetcaching.md) for more details.
3 changes: 3 additions & 0 deletions scripts/azure-pipelines/linux/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ jobs:
value: /mnt/vcpkg-ci
- name: VCPKG_DOWNLOADS
value: /mnt/vcpkg-ci/downloads
- group: azblob-test-sas-group
- name: X_VCPKG_ASSET_SOURCES
value: "x-azurl,$(azblob-root-url),$(azblob-test-sas),readwrite"

steps:
- bash: df -h
Expand Down
2 changes: 2 additions & 0 deletions scripts/azure-pipelines/osx/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ jobs:
- group: osx-2021-04-16
- name: BINARY_SOURCE_STUB
value: "x-azblob,$(azblob-root-url),$(azblob-test-sas)"
- name: X_VCPKG_ASSET_SOURCES
value: "x-azurl,$(azblob-root-url),$(azblob-test-sas),readwrite"

steps:
- bash: df -h
Expand Down
3 changes: 3 additions & 0 deletions scripts/azure-pipelines/windows/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ jobs:
value: D:\
- name: VCPKG_DOWNLOADS
value: D:\downloads
- group: azblob-test-sas-group
- name: X_VCPKG_ASSET_SOURCES
value: "x-azurl,$(azblob-root-url),$(azblob-test-sas),readwrite"

steps:
- task: PowerShell@2
Expand Down
8 changes: 8 additions & 0 deletions scripts/ci.baseline.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,16 @@ charls:x64-windows=skip
charls:x64-windows-static=skip
charls:x64-windows-static-md=skip
charls:x86-windows=skip
# chartdir does not offer stable download URLs
chartdir:arm64-windows=fail
chartdir:arm-uwp=fail
chartdir:x64-uwp=fail
chartdir:x64-windows-static=fail
chartdir:x86-windows=fail
chartdir:x64-windows=fail
chartdir:x64-windows-static-md=fail
chartdir:x64-linux=fail
chartdir:x64-osx=fail
chmlib:arm-uwp=fail
chmlib:x64-uwp=fail
# Chromium Base requires a recent version of Clang to be installed.
Expand Down Expand Up @@ -1636,6 +1642,8 @@ v8:arm64-windows=fail
v8:arm-uwp=fail
v8:x64-osx=fail
v8:x64-uwp=fail
# The domain hosting vamp-sdk uses a newer root cert than is available in our linux CI
vamp-sdk:x64-linux=fail
vectorclass:arm64-windows=fail
vectorclass:arm-uwp=fail
vlpp:x64-osx=fail
Expand Down
79 changes: 49 additions & 30 deletions scripts/cmake/vcpkg_download_distfile.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,12 @@ function(vcpkg_download_distfile VAR)
if(NOT DEFINED vcpkg_download_distfile_FILENAME)
message(FATAL_ERROR "vcpkg_download_distfile requires a FILENAME argument.")
endif()
if(NOT _VCPKG_INTERNAL_NO_HASH_CHECK)
if(vcpkg_download_distfile_SILENT_EXIT)
message(WARNING "SILENT_EXIT has been deprecated as an argument to vcpkg_download_distfile -- remove the argument to resolve this warning")
endif()
if(_VCPKG_INTERNAL_NO_HASH_CHECK)
set(vcpkg_download_distfile_SKIP_SHA512 1)
else()
if(NOT vcpkg_download_distfile_SKIP_SHA512 AND NOT DEFINED vcpkg_download_distfile_SHA512)
message(FATAL_ERROR "vcpkg_download_distfile requires a SHA512 argument. If you do not know the SHA512, add it as 'SHA512 0' and re-run this command.")
endif()
Expand Down Expand Up @@ -113,7 +118,7 @@ function(vcpkg_download_distfile VAR)

if(EXISTS "${downloaded_file_path}")
if(NOT vcpkg_download_distfile_QUIET)
message(STATUS "Using cached ${downloaded_file_path}")
message(STATUS "Using ${downloaded_file_path}")
endif()
test_hash("${downloaded_file_path}" "cached file" "Please delete the file and retry if this file should be downloaded again.")
else()
Expand All @@ -127,7 +132,7 @@ function(vcpkg_download_distfile VAR)
vcpkg_find_acquire_program("ARIA2")
message(STATUS "Downloading ${vcpkg_download_distfile_FILENAME}...")
if(vcpkg_download_distfile_HEADERS)
foreach(header ${vcpkg_download_distfile_HEADERS})
foreach(header IN LISTS vcpkg_download_distfile_HEADERS)
list(APPEND request_headers "--header=${header}")
endforeach()
endif()
Expand Down Expand Up @@ -159,29 +164,60 @@ function(vcpkg_download_distfile VAR)
)
set(download_success 1)
endif()
else()
elseif(vcpkg_download_distfile_SKIP_SHA512)
set(download_success 0)
set(request_headers)
if(vcpkg_download_distfile_HEADERS)
foreach(header IN LISTS vcpkg_download_distfile_HEADERS)
list(APPEND request_headers HTTPHEADER ${header})
endforeach()
endif()
foreach(url IN LISTS vcpkg_download_distfile_URLS)
message(STATUS "Downloading ${url} -> ${vcpkg_download_distfile_FILENAME}...")
if(vcpkg_download_distfile_HEADERS)
foreach(header ${vcpkg_download_distfile_HEADERS})
list(APPEND request_headers HTTPHEADER ${header})
endforeach()
endif()
file(DOWNLOAD "${url}" "${download_file_path_part}" STATUS download_status ${request_headers})
list(GET download_status 0 status_code)
if (NOT "${status_code}" STREQUAL "0")
message(STATUS "Downloading ${url}... Failed. Status: ${download_status}")
set(download_success 0)
else()
test_hash("${download_file_path_part}" "downloaded file" "The file may have been corrupted in transit. This can be caused by proxies. If you use a proxy, please set the HTTPS_PROXY and HTTP_PROXY environment variables to \"https://user:password@your-proxy-ip-address:port/\".\n")
get_filename_component(downloaded_file_dir "${downloaded_file_path}" DIRECTORY)
file(MAKE_DIRECTORY "${downloaded_file_dir}")
file(RENAME ${download_file_path_part} ${downloaded_file_path})
set(download_success 1)
break()
endif()
endforeach(url)
else()
set(urls)
foreach(url IN LISTS vcpkg_download_distfile_URLS)
list(APPEND urls "--url=${url}")
endforeach()
if(NOT vcpkg_download_distfile_QUIET)
message(STATUS "Downloading ${vcpkg_download_distfile_URLS} -> ${vcpkg_download_distfile_FILENAME}...")
endif()
set(request_headers)
if(vcpkg_download_distfile_HEADERS)
foreach(header IN LISTS vcpkg_download_distfile_HEADERS)
list(APPEND request_headers "--header=${header}")
endforeach()
endif()
vcpkg_execute_in_download_mode(
COMMAND "$ENV{VCPKG_COMMAND}" x-download "${downloaded_file_path}" "${vcpkg_download_distfile_SHA512}" ${urls} ${request_headers} --debug
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ras0219-msft This change introduced the use of the x-download vcpkg tool command which was not availabe in version 2021-01-13-d67989bce1043b98092ac45996a8230a059a2d7e of the tool. This already created a lot of issues, e.g. #18676. IMO this change needs to be complemented by use of

vcpkg_minimum_required(VERSION 2021-05-05)

either here where the new command is used, or globally in ports.cmake where the minimum is 2021-01-13 at the moment.

(I don't want to send a PR blindly because it will rebuild the world.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while you are very kind in principle, experience has already demonstrated many times that already merged PRs are rarely seen by vcpkg team.
i’d open a new issue at minimum, or send a PR anyway at best.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cenit Not really, I think we should force the user to update vcpkg and download vcpkg binary using bootstrap.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were probably more than 10 issues related to x-download, and none was taken as a reason to demand a change.

I would send a PR if it could be discussed before having another world rebuild blocking the CI pipeline. The script audits are heavy enough.

So as a start, I prefer to have another comment close to the offending change, adressing author, assignees and reviewers which normally remain subscribed. An issue or PR can follow.

OUTPUT_VARIABLE output
ERROR_VARIABLE output
RESULT_VARIABLE failure
WORKING_DIRECTORY "${DOWNLOADS}"
)
if(failure)
message("${output}")
set(download_success 0)
else()
set(download_success 1)
endif()
endif()

if (NOT vcpkg_download_distfile_SILENT_EXIT)
if (NOT download_success)
message(FATAL_ERROR
if(NOT download_success)
message(FATAL_ERROR
" \n"
" Failed to download file.\n"
" If you use a proxy, please check your proxy setting. Possible causes are:\n"
Expand All @@ -205,23 +241,6 @@ function(vcpkg_download_distfile VAR)
" and (https://github.com/microsoft/vcpkg-tool/pull/77)\n"
" \n"
" Otherwise, please submit an issue at https://github.com/Microsoft/vcpkg/issues\n")
else()
test_hash("${download_file_path_part}" "downloaded file" "The file may have been corrupted in transit. This can be caused by proxies. If you use a proxy, please set the HTTPS_PROXY and HTTP_PROXY environment variables to \"https://user:password@your-proxy-ip-address:port/\".\n")
get_filename_component(downloaded_file_dir "${downloaded_file_path}" DIRECTORY)
file(MAKE_DIRECTORY "${downloaded_file_dir}")
file(RENAME ${download_file_path_part} ${downloaded_file_path})
endif()
else()
if (NOT download_success)
message(WARNING
" \n"
" Failed to download file.\n")
else()
test_hash("${download_file_path_part}" "downloaded file" "The file may have been corrupted in transit. This can be caused by proxies. If you use a proxy, please set the HTTPS_PROXY and HTTP_PROXY environment variables to \"https://user:password@your-proxy-ip-address:port/\".\n")
get_filename_component(downloaded_file_dir "${downloaded_file_path}" DIRECTORY)
file(MAKE_DIRECTORY "${downloaded_file_dir}")
file(RENAME ${download_file_path_part} ${downloaded_file_path})
endif()
endif()
endif()
set(${VAR} ${downloaded_file_path} PARENT_SCOPE)
Expand Down
85 changes: 10 additions & 75 deletions scripts/cmake/vcpkg_from_sourceforge.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -67,34 +67,6 @@ Specifies that the default removal of the top level folder should not occur.
#]===]

function(vcpkg_from_sourceforge)
macro(check_file_content)
if (EXISTS ${ARCHIVE})
file(SIZE ${ARCHIVE} DOWNLOAD_FILE_SIZE)
if (DOWNLOAD_FILE_SIZE LESS_EQUAL 1024)
file(READ ${ARCHIVE} _FILE_CONTENT_)
string(FIND "${_FILE_CONTENT_}" "the Sourceforge site is currently in Disaster Recovery mode." OUT_CONTENT)
message("OUT_CONTENT: ${OUT_CONTENT}")
if (OUT_CONTENT EQUAL -1)
set(download_success 1)
else()
file(REMOVE ${ARCHIVE})
endif()
endif()
endif()
endmacro()

macro(check_file_sha512)
file(SHA512 ${ARCHIVE} FILE_HASH)
if(NOT FILE_HASH STREQUAL _vdus_SHA512)
message(FATAL_ERROR
"\nFile does not have expected hash:\n"
" File path: [ ${ARCHIVE} ]\n"
" Expected hash: [ ${_vdus_SHA512} ]\n"
" Actual hash: [ ${FILE_HASH} ]\n"
"${CUSTOM_ERROR_ADVICE}\n")
endif()
endmacro()

set(booleanValueArgs DISABLE_SSL NO_REMOVE_ONE_LEVEL)
set(oneValueArgs OUT_SOURCE_PATH REPO REF SHA512 FILENAME WORKING_DIRECTORY)
set(multipleValuesArgs PATCHES)
Expand Down Expand Up @@ -154,7 +126,8 @@ function(vcpkg_from_sourceforge)

string(SUBSTRING "${_vdus_SHA512}" 0 10 SANITIZED_REF)

list(APPEND SOURCEFORGE_MIRRORS
set(Z_VCPKG_SOURCEFORGE_MIRRORS ${SOURCEFORGE_MIRRORS})
list(APPEND Z_VCPKG_SOURCEFORGE_MIRRORS
cfhcable # United States
pilotfiber # New York, NY
gigenet # Chicago, IL
Expand All @@ -176,56 +149,18 @@ function(vcpkg_from_sourceforge)
ufpr # Curitiba, Brazil
tenet # Wynberg, South Africa
)

# Try to use auto-select first
set(DOWNLOAD_URL ${URL}/download)
message(STATUS "Trying auto-select mirror...")

set(URLS "${URL}/download")
foreach(SOURCEFORGE_MIRROR IN LISTS Z_VCPKG_SOURCEFORGE_MIRRORS)
list(APPEND URLS "${URL}/download?use_mirror=${SOURCEFORGE_MIRROR}")
endforeach()

vcpkg_download_distfile(ARCHIVE
URLS "${DOWNLOAD_URL}"
SKIP_SHA512
URLS ${URLS}
SHA512 "${_vdus_SHA512}"
FILENAME "${_vdus_FILENAME}"
SILENT_EXIT
)
check_file_content()
if (download_success)
check_file_sha512()
else()
message(STATUS "The default mirror is in Disaster Recovery mode, trying other mirrors...")
endif()

if (NOT download_success EQUAL 1)
foreach(SOURCEFORGE_MIRROR ${SOURCEFORGE_MIRRORS})
set(DOWNLOAD_URL ${URL}/download?use_mirror=${SOURCEFORGE_MIRROR})
message(STATUS "Trying mirror ${SOURCEFORGE_MIRROR}...")
vcpkg_download_distfile(ARCHIVE
URLS "${DOWNLOAD_URL}"
SKIP_SHA512
FILENAME "${_vdus_FILENAME}"
SILENT_EXIT
)

if (EXISTS ${ARCHIVE})
set(download_success 1)
check_file_content()
if (download_success)
check_file_sha512()
else()
message(STATUS "Mirror ${SOURCEFORGE_MIRROR} is in Disaster Recovery mode, trying other mirrors...")
endif()
break()
endif()
endforeach()
endif()

if (NOT download_success)
message(FATAL_ERROR [[
Couldn't download source from any of the sourceforge mirrors, please check your network.
If you use a proxy, please set the HTTPS_PROXY and HTTP_PROXY environment
variables to "http[s]://user:password@your-proxy-ip-address:port/".
Otherwise, please submit an issue at https://github.com/Microsoft/vcpkg/issues
]])
endif()

vcpkg_extract_source_archive_ex(
OUT_SOURCE_PATH SOURCE_PATH
ARCHIVE "${ARCHIVE}"
Expand Down