diff --git a/azure-pipelines/e2e_ports/integrate-install/NoProps.vcxproj b/azure-pipelines/e2e_ports/integrate-install/NoProps.vcxproj index 5b75d09615..6f85444235 100644 --- a/azure-pipelines/e2e_ports/integrate-install/NoProps.vcxproj +++ b/azure-pipelines/e2e_ports/integrate-install/NoProps.vcxproj @@ -141,5 +141,5 @@ - + \ No newline at end of file diff --git a/azure-pipelines/e2e_ports/integrate-install/Project1.vcxproj b/azure-pipelines/e2e_ports/integrate-install/Project1.vcxproj index a8896fe29d..342099061f 100644 --- a/azure-pipelines/e2e_ports/integrate-install/Project1.vcxproj +++ b/azure-pipelines/e2e_ports/integrate-install/Project1.vcxproj @@ -52,7 +52,7 @@ Unicode - + @@ -142,5 +142,5 @@ - + \ No newline at end of file diff --git a/azure-pipelines/e2e_ports/integrate-install/VcpkgTriplet.vcxproj b/azure-pipelines/e2e_ports/integrate-install/VcpkgTriplet.vcxproj index 883fc8ec1a..2197c98dd8 100644 --- a/azure-pipelines/e2e_ports/integrate-install/VcpkgTriplet.vcxproj +++ b/azure-pipelines/e2e_ports/integrate-install/VcpkgTriplet.vcxproj @@ -52,7 +52,7 @@ Unicode - + @@ -147,5 +147,5 @@ - + \ No newline at end of file diff --git a/azure-pipelines/e2e_ports/integrate-install/VcpkgTriplet2.vcxproj b/azure-pipelines/e2e_ports/integrate-install/VcpkgTriplet2.vcxproj index d3352e195b..0224be227f 100644 --- a/azure-pipelines/e2e_ports/integrate-install/VcpkgTriplet2.vcxproj +++ b/azure-pipelines/e2e_ports/integrate-install/VcpkgTriplet2.vcxproj @@ -53,7 +53,7 @@ Unicode - + @@ -145,5 +145,5 @@ - + \ No newline at end of file diff --git a/azure-pipelines/e2e_ports/integrate-install/VcpkgUseStatic.vcxproj b/azure-pipelines/e2e_ports/integrate-install/VcpkgUseStatic.vcxproj index 28c4fc7158..7558f1650e 100644 --- a/azure-pipelines/e2e_ports/integrate-install/VcpkgUseStatic.vcxproj +++ b/azure-pipelines/e2e_ports/integrate-install/VcpkgUseStatic.vcxproj @@ -52,7 +52,7 @@ Unicode - + @@ -147,5 +147,5 @@ - + \ No newline at end of file diff --git a/azure-pipelines/e2e_ports/integrate-install/VcpkgUseStatic2.vcxproj b/azure-pipelines/e2e_ports/integrate-install/VcpkgUseStatic2.vcxproj index 98beaee4b1..a70a307351 100644 --- a/azure-pipelines/e2e_ports/integrate-install/VcpkgUseStatic2.vcxproj +++ b/azure-pipelines/e2e_ports/integrate-install/VcpkgUseStatic2.vcxproj @@ -53,7 +53,7 @@ Unicode - + @@ -145,5 +145,5 @@ - + \ No newline at end of file diff --git a/azure-pipelines/e2e_ports/integrate-install/VcpkgUseStaticManifestHost.vcxproj b/azure-pipelines/e2e_ports/integrate-install/VcpkgUseStaticManifestHost.vcxproj new file mode 100644 index 0000000000..a80f878ec5 --- /dev/null +++ b/azure-pipelines/e2e_ports/integrate-install/VcpkgUseStaticManifestHost.vcxproj @@ -0,0 +1,154 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {5AFB7AF5-D8FC-4A86-B0D2-3BBD039ED03A} + VcpkgUseStaticManifestHost + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + true + x64-windows-static + true + $(TestingVcpkgInstalledDir) + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Console + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + + + Console + true + true + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + \ No newline at end of file diff --git a/azure-pipelines/e2e_ports/integrate-install/vcpkg.json b/azure-pipelines/e2e_ports/integrate-install/vcpkg.json new file mode 100644 index 0000000000..54275ccd51 --- /dev/null +++ b/azure-pipelines/e2e_ports/integrate-install/vcpkg.json @@ -0,0 +1,11 @@ +{ + "name": "integrate-install-test", + "version-string": "0", + "dependencies": [ + { + "name": "zlib", + "host": true + }, + "zlib" + ] +} \ No newline at end of file diff --git a/azure-pipelines/e2e_ports/overlays/tool-control/CONTROL b/azure-pipelines/e2e_ports/overlays/tool-control/CONTROL new file mode 100644 index 0000000000..58052ece7b --- /dev/null +++ b/azure-pipelines/e2e_ports/overlays/tool-control/CONTROL @@ -0,0 +1,4 @@ +Source: tool-control +Version: 1 +Description: test tool port +Build-Depends: tool-liba diff --git a/azure-pipelines/e2e_ports/overlays/tool-control/portfile.cmake b/azure-pipelines/e2e_ports/overlays/tool-control/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e_ports/overlays/tool-control/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e_ports/overlays/tool-liba/portfile.cmake b/azure-pipelines/e2e_ports/overlays/tool-liba/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e_ports/overlays/tool-liba/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e_ports/overlays/tool-liba/vcpkg.json b/azure-pipelines/e2e_ports/overlays/tool-liba/vcpkg.json new file mode 100644 index 0000000000..038eec9302 --- /dev/null +++ b/azure-pipelines/e2e_ports/overlays/tool-liba/vcpkg.json @@ -0,0 +1,4 @@ +{ + "name": "tool-liba", + "version-string": "1" +} diff --git a/azure-pipelines/e2e_ports/overlays/tool-libb/portfile.cmake b/azure-pipelines/e2e_ports/overlays/tool-libb/portfile.cmake new file mode 100644 index 0000000000..54e886c6c2 --- /dev/null +++ b/azure-pipelines/e2e_ports/overlays/tool-libb/portfile.cmake @@ -0,0 +1,21 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) + +if(NOT DEFINED _HOST_TRIPLET) + message(FATAL_ERROR "tool-libb requires _HOST_TRIPLET to be defined") +endif() + +get_filename_component(base_install_dir "${CURRENT_INSTALLED_DIR}" DIRECTORY) + +# This is needed to cut the requirement for an atomic change across both Microsoft/vcpkg and Microsoft/vcpkg-tool +if(DEFINED CURRENT_HOST_INSTALLED_DIR AND NOT CURRENT_HOST_INSTALLED_DIR STREQUAL "${base_install_dir}/${_HOST_TRIPLET}") + message(FATAL_ERROR "tool-libb requires CURRENT_HOST_INSTALLED_DIR to be defined to \"${base_install_dir}/${_HOST_TRIPLET}\"") +endif() + +set(CURRENT_HOST_INSTALLED_DIR "${base_install_dir}/${_HOST_TRIPLET}") + +if(NOT EXISTS "${CURRENT_HOST_INSTALLED_DIR}/share/tool-manifest") + message(FATAL_ERROR "tool-libb requires tool-manifest on the host (${CURRENT_HOST_INSTALLED_DIR}/share/tool-manifest)") +endif() +if(NOT EXISTS "${CURRENT_HOST_INSTALLED_DIR}/share/tool-control") + message(FATAL_ERROR "tool-libb requires tool-control on the host (${CURRENT_HOST_INSTALLED_DIR}/share/tool-control)") +endif() diff --git a/azure-pipelines/e2e_ports/overlays/tool-libb/vcpkg.json b/azure-pipelines/e2e_ports/overlays/tool-libb/vcpkg.json new file mode 100644 index 0000000000..6212bf8e2e --- /dev/null +++ b/azure-pipelines/e2e_ports/overlays/tool-libb/vcpkg.json @@ -0,0 +1,14 @@ +{ + "name": "tool-libb", + "version-string": "1", + "dependencies": [ + { + "name": "tool-manifest", + "host": true + }, + { + "name": "tool-control", + "host": true + } + ] +} \ No newline at end of file diff --git a/azure-pipelines/e2e_ports/overlays/tool-manifest/portfile.cmake b/azure-pipelines/e2e_ports/overlays/tool-manifest/portfile.cmake new file mode 100644 index 0000000000..065116c276 --- /dev/null +++ b/azure-pipelines/e2e_ports/overlays/tool-manifest/portfile.cmake @@ -0,0 +1 @@ +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) diff --git a/azure-pipelines/e2e_ports/overlays/tool-manifest/vcpkg.json b/azure-pipelines/e2e_ports/overlays/tool-manifest/vcpkg.json new file mode 100644 index 0000000000..74f81ede0a --- /dev/null +++ b/azure-pipelines/e2e_ports/overlays/tool-manifest/vcpkg.json @@ -0,0 +1,7 @@ +{ + "name": "tool-manifest", + "version-string": "1.0.0", + "dependencies": [ + "tool-liba" + ] +} diff --git a/azure-pipelines/e2e_ports/triplets/x64-linux-e2e.cmake b/azure-pipelines/e2e_ports/triplets/x64-linux-e2e.cmake new file mode 100644 index 0000000000..5196184638 --- /dev/null +++ b/azure-pipelines/e2e_ports/triplets/x64-linux-e2e.cmake @@ -0,0 +1,5 @@ +set(VCPKG_TARGET_ARCHITECTURE x64) +set(VCPKG_CRT_LINKAGE dynamic) +set(VCPKG_LIBRARY_LINKAGE static) + +set(VCPKG_CMAKE_SYSTEM_NAME Linux) diff --git a/azure-pipelines/e2e_ports/triplets/x64-osx-e2e.cmake b/azure-pipelines/e2e_ports/triplets/x64-osx-e2e.cmake new file mode 100644 index 0000000000..8cd8c90b4a --- /dev/null +++ b/azure-pipelines/e2e_ports/triplets/x64-osx-e2e.cmake @@ -0,0 +1,6 @@ +set(VCPKG_TARGET_ARCHITECTURE x64) +set(VCPKG_CRT_LINKAGE dynamic) +set(VCPKG_LIBRARY_LINKAGE static) + +set(VCPKG_CMAKE_SYSTEM_NAME Darwin) +set(VCPKG_OSX_ARCHITECTURES x86_64) diff --git a/azure-pipelines/e2e_ports/triplets/x64-windows-e2e.cmake b/azure-pipelines/e2e_ports/triplets/x64-windows-e2e.cmake new file mode 100644 index 0000000000..d0be7297f0 --- /dev/null +++ b/azure-pipelines/e2e_ports/triplets/x64-windows-e2e.cmake @@ -0,0 +1,4 @@ +set(VCPKG_TARGET_ARCHITECTURE x64) +set(VCPKG_CRT_LINKAGE dynamic) +set(VCPKG_LIBRARY_LINKAGE dynamic) + diff --git a/azure-pipelines/end-to-end-tests-dir/integrate-install.ps1 b/azure-pipelines/end-to-end-tests-dir/integrate-install.ps1 index 38362ba8cb..f02a5ec6d5 100644 --- a/azure-pipelines/end-to-end-tests-dir/integrate-install.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/integrate-install.ps1 @@ -1,28 +1,43 @@ if (-not $IsLinux -and -not $IsMacOS) { . $PSScriptRoot/../end-to-end-tests-prelude.ps1 + $iiroot = "$PSScriptRoot/../e2e_ports/integrate-install" + + $env:VCPKG_BINARY_SOURCES="clear;default,read" + $env:VCPKG_KEEP_ENV_VARS="VCPKG_KEEP_ENV_VARS;VCPKG_BINARY_SOURCES;VCPKG_FORCE_SYSTEM_BINARIES;VCPKG_DOWNLOADS;VCPKG_DEFAULT_BINARY_CACHE" # Test msbuild props and targets - $Script:CurrentTest = "zlib:x86-windows-static msbuild scripts\testing\integrate-install\..." + $Script:CurrentTest = "zlib:x86-windows msbuild $iiroot\..." Write-Host $Script:CurrentTest - ./vcpkg $commonArgs install zlib:x86-windows-static --x-binarysource=clear + ./vcpkg $commonArgs install zlib:x86-windows Throw-IfFailed - foreach ($project in @("VcpkgTriplet", "VcpkgTriplet2", "VcpkgUseStatic", "VcpkgUseStatic2")) { - $Script:CurrentTest = "msbuild scripts\testing\integrate-install\$project.vcxproj" - ./vcpkg $commonArgs env "msbuild scripts\testing\integrate-install\$project.vcxproj /p:VcpkgRoot=$TestingRoot /p:IntDir=$TestingRoot\int\ /p:OutDir=$TestingRoot\out\ " + foreach ($project in @("Project1", "NoProps")) { + $Script:CurrentTest = "msbuild $iiroot\$project.vcxproj" + Write-Host $Script:CurrentTest + ./vcpkg $commonArgs env "msbuild $iiroot\$project.vcxproj /p:VCPKG_ROOT=$VcpkgRoot /p:VcpkgRoot=$TestingRoot /p:IntDir=$TestingRoot\int\ /p:OutDir=$TestingRoot\out\ " Throw-IfFailed Remove-Item -Recurse -Force $TestingRoot\int Remove-Item -Recurse -Force $TestingRoot\out } - $Script:CurrentTest = "zlib:x86-windows msbuild scripts\testing\integrate-install\..." + + $Script:CurrentTest = "zlib:x86-windows-static msbuild $iiroot\..." Write-Host $Script:CurrentTest - ./vcpkg $commonArgs install zlib:x86-windows --x-binarysource=clear + ./vcpkg $commonArgs install zlib:x86-windows-static Throw-IfFailed - foreach ($project in @("Project1", "NoProps")) { - $Script:CurrentTest = "msbuild scripts\testing\integrate-install\$project.vcxproj" - Write-Host $Script:CurrentTest - ./vcpkg $commonArgs env "msbuild scripts\testing\integrate-install\$project.vcxproj /p:VcpkgRoot=$TestingRoot /p:IntDir=$TestingRoot\int\ /p:OutDir=$TestingRoot\out\ " + foreach ($project in @("VcpkgTriplet", "VcpkgTriplet2", "VcpkgUseStatic", "VcpkgUseStatic2")) { + $Script:CurrentTest = "msbuild $iiroot\$project.vcxproj" + ./vcpkg $commonArgs env "msbuild $iiroot\$project.vcxproj /p:VCPKG_ROOT=$VcpkgRoot /p:VcpkgRoot=$TestingRoot /p:IntDir=$TestingRoot\int\ /p:OutDir=$TestingRoot\out\ " Throw-IfFailed Remove-Item -Recurse -Force $TestingRoot\int Remove-Item -Recurse -Force $TestingRoot\out } + + # This test is currently disabled because it requires adding the ability to override the vcpkg executable into the msbuild props/targets. + # Require-FileNotExists $installRoot/x64-windows-static/include/zlib.h + # Require-FileNotExists $installRoot/x64-windows/include/zlib.h + # Require-FileExists $installRoot/x86-windows/include/zlib.h + # $Script:CurrentTest = "msbuild $iiroot\VcpkgUseStaticManifestHost.vcxproj" + # ./vcpkg $commonArgs env "msbuild $iiroot\VcpkgUseStaticManifestHost.vcxproj /p:VCPKG_ROOT=$VcpkgRoot `"/p:_VcpkgExecutable=$VcpkgExe`" /p:VcpkgRoot=$TestingRoot /p:IntDir=$TestingRoot\int\ /p:OutDir=$TestingRoot\out\ /p:TestingVcpkgInstalledDir=$installRoot" + # Throw-IfFailed + # Require-FileExists $installRoot/x64-windows-static/include/zlib.h + # Require-FileNotExists $installRoot/x86-windows/include/zlib.h } diff --git a/azure-pipelines/end-to-end-tests-dir/tool-ports.ps1 b/azure-pipelines/end-to-end-tests-dir/tool-ports.ps1 new file mode 100644 index 0000000000..4436ae6dd3 --- /dev/null +++ b/azure-pipelines/end-to-end-tests-dir/tool-ports.ps1 @@ -0,0 +1,84 @@ +. $PSScriptRoot/../end-to-end-tests-prelude.ps1 + +$commonArgs += @("--x-binarysource=clear") + +$hostTriplet = "$Triplet" +$env:VCPKG_DEFAULT_HOST_TRIPLET = "$hostTriplet" +if (!$IsLinux -and !$IsMacOS) +{ + $targetTriplet = "x64-windows-e2e" +} +elseif ($IsMacOS) +{ + $targetTriplet = "x64-osx-e2e" +} +else +{ + $targetTriplet = "x64-linux-e2e" +} + +$env:VCPKG_FEATURE_FLAGS="-compilertracking" + +# Test native installation +Run-Vcpkg ($commonArgs + @("install", "tool-libb")) +Throw-IfFailed +@("tool-control", "tool-manifest", "tool-liba", "tool-libb") | % { + Require-FileNotExists $installRoot/$targetTriplet/share/$_ + Require-FileExists $installRoot/$hostTriplet/share/$_ +} + +Refresh-TestRoot + +# Test cross installation +Run-Vcpkg ($commonArgs + @("install", "tool-libb:$targetTriplet")) +Throw-IfFailed +@("tool-control", "tool-manifest", "tool-liba") | % { + Require-FileNotExists $installRoot/$targetTriplet/share/$_ + Require-FileExists $installRoot/$hostTriplet/share/$_ +} +@("tool-libb") | % { + Require-FileExists $installRoot/$targetTriplet/share/$_ + Require-FileNotExists $installRoot/$hostTriplet/share/$_ +} + +# Test removal of packages in cross installation +Run-Vcpkg ($commonArgs + @("remove", "tool-manifest", "--recurse")) +Throw-IfFailed +@("tool-control", "tool-liba") | % { + Require-FileNotExists $installRoot/$targetTriplet/share/$_ + Require-FileExists $installRoot/$hostTriplet/share/$_ +} +@("tool-libb", "tool-manifest") | % { + Require-FileNotExists $installRoot/$targetTriplet/share/$_ + Require-FileNotExists $installRoot/$hostTriplet/share/$_ +} + +Refresh-TestRoot + +# Test VCPKG_DEFAULT_HOST_TRIPLET +$env:VCPKG_DEFAULT_HOST_TRIPLET = $targetTriplet +Run-Vcpkg ($commonArgs + @("install", "tool-libb:$hostTriplet")) +Throw-IfFailed +@("tool-control", "tool-manifest", "tool-liba") | % { + Require-FileExists $installRoot/$targetTriplet/share/$_ + Require-FileNotExists $installRoot/$hostTriplet/share/$_ +} +@("tool-libb") | % { + Require-FileNotExists $installRoot/$targetTriplet/share/$_ + Require-FileExists $installRoot/$hostTriplet/share/$_ +} + +Refresh-TestRoot + +Remove-Item env:VCPKG_DEFAULT_HOST_TRIPLET +# Test --host-triplet +Run-Vcpkg ($commonArgs + @("install", "tool-libb:$hostTriplet", "--host-triplet=$targetTriplet")) +Throw-IfFailed +@("tool-control", "tool-manifest", "tool-liba") | % { + Require-FileExists $installRoot/$targetTriplet/share/$_ + Require-FileNotExists $installRoot/$hostTriplet/share/$_ +} +@("tool-libb") | % { + Require-FileNotExists $installRoot/$targetTriplet/share/$_ + Require-FileExists $installRoot/$hostTriplet/share/$_ +} diff --git a/azure-pipelines/end-to-end-tests-prelude.ps1 b/azure-pipelines/end-to-end-tests-prelude.ps1 index 497f4fc941..7d51787fd3 100644 --- a/azure-pipelines/end-to-end-tests-prelude.ps1 +++ b/azure-pipelines/end-to-end-tests-prelude.ps1 @@ -12,19 +12,11 @@ $commonArgs = @( "--x-buildtrees-root=$buildtreesRoot", "--x-install-root=$installRoot", "--x-packages-root=$packagesRoot", - "--overlay-ports=$PSScriptRoot/e2e_ports/overlays" + "--overlay-ports=$PSScriptRoot/e2e_ports/overlays", + "--overlay-triplets=$PSScriptRoot/e2e_ports/triplets" ) $Script:CurrentTest = 'unassigned' -if ($IsWindows) -{ - $VcpkgExe = Get-Item './vcpkg.exe' -} -else -{ - $VcpkgExe = Get-Item './vcpkg' -} - function Refresh-TestRoot { Remove-Item -Recurse -Force $TestingRoot -ErrorAction SilentlyContinue mkdir $TestingRoot | Out-Null @@ -72,7 +64,7 @@ function Run-Vcpkg { [Parameter(ValueFromRemainingArguments)] [string[]]$TestArgs ) - $Script:CurrentTest = "vcpkg $($testArgs -join ' ')" + $Script:CurrentTest = "$VcpkgExe $($testArgs -join ' ')" Write-Host $Script:CurrentTest & $VcpkgExe @testArgs } diff --git a/azure-pipelines/end-to-end-tests.ps1 b/azure-pipelines/end-to-end-tests.ps1 index d25bc67ff1..f8fa756674 100644 --- a/azure-pipelines/end-to-end-tests.ps1 +++ b/azure-pipelines/end-to-end-tests.ps1 @@ -29,7 +29,9 @@ Param( [string]$VcpkgRoot, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] - [string]$Filter + [string]$Filter, + [Parameter(Mandatory = $false)] + [string]$VcpkgExe ) $ErrorActionPreference = "Stop" @@ -40,7 +42,18 @@ if (-Not (Test-Path $WorkingRoot)) { $WorkingRoot = (Get-Item $WorkingRoot).FullName $VcpkgRoot = (Get-Item $VcpkgRoot).FullName -$env:VCPKG_ROOT = $VcpkgRoot + +if ([string]::IsNullOrEmpty($VcpkgExe)) +{ + if ($IsWindows) + { + $VcpkgExe = Get-Item './vcpkg.exe' + } + else + { + $VcpkgExe = Get-Item './vcpkg' + } +} $AllTests = Get-ChildItem $PSScriptRoot/end-to-end-tests-dir/*.ps1 if ($Filter -ne $Null) { @@ -49,9 +62,58 @@ if ($Filter -ne $Null) { $n = 1 $m = $AllTests.Count -$AllTests | % { - Write-Host "[end-to-end-tests.ps1] [$n/$m] Running suite $_" - & $_ +$envvars_clear = @( + "VCPKG_DEFAULT_HOST_TRIPLET", + "VCPKG_DEFAULT_TRIPLET", + "VCPKG_BINARY_SOURCES", + "VCPKG_OVERLAY_PORTS", + "VCPKG_OVERLAY_TRIPLETS", + "VCPKG_KEEP_ENV_VARS", + "VCPKG_ROOT", + "VCPKG_FEATURE_FLAGS", + "VCPKG_DISABLE_METRICS" +) +$envvars = $envvars_clear + @("VCPKG_DOWNLOADS") + +foreach ($Test in $AllTests) +{ + Write-Host "[end-to-end-tests.ps1] [$n/$m] Running suite $Test" + + $envbackup = @{} + foreach ($var in $envvars) + { + $envbackup[$var] = [System.Environment]::GetEnvironmentVariable($var) + } + + try + { + foreach ($var in $envvars_clear) + { + if (Test-Path "Env:\$var") + { + Remove-Item "Env:\$var" + } + } + $env:VCPKG_ROOT = $VcpkgRoot + & $Test + } + finally + { + foreach ($var in $envvars) + { + if ($envbackup[$var] -eq $null) + { + if (Test-Path "Env:\$var") + { + Remove-Item "Env:\$var" + } + } + else + { + Set-Item "Env:\$var" "$envbackup[$var]" + } + } + } $n += 1 } diff --git a/include/vcpkg/binaryparagraph.h b/include/vcpkg/binaryparagraph.h index a807797f88..7bc4682a8a 100644 --- a/include/vcpkg/binaryparagraph.h +++ b/include/vcpkg/binaryparagraph.h @@ -39,9 +39,9 @@ namespace vcpkg std::vector maintainers; std::string feature; std::vector default_features; - std::vector dependencies; + std::vector dependencies; std::string abi; - Type type = {Type::UNKNOWN}; + Type type = {Type::PORT}; }; bool operator==(const BinaryParagraph&, const BinaryParagraph&); diff --git a/include/vcpkg/build.h b/include/vcpkg/build.h index ed27244359..afe89ce311 100644 --- a/include/vcpkg/build.h +++ b/include/vcpkg/build.h @@ -59,6 +59,7 @@ namespace vcpkg::Build { int perform_ex(const VcpkgCmdArguments& args, const FullPackageSpec& full_spec, + Triplet host_triplet, const SourceControlFileLocation& scfl, const PortFileProvider::PathsPortFileProvider& provider, IBinaryProvider& binaryprovider, @@ -66,14 +67,21 @@ namespace vcpkg::Build const VcpkgPaths& paths); void perform_and_exit_ex(const VcpkgCmdArguments& args, const FullPackageSpec& full_spec, + Triplet host_triplet, const SourceControlFileLocation& scfl, const PortFileProvider::PathsPortFileProvider& provider, IBinaryProvider& binaryprovider, const IBuildLogsRecorder& build_logs_recorder, const VcpkgPaths& paths); - int perform(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); + int perform(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet); } enum class UseHeadVersion @@ -384,6 +392,7 @@ namespace vcpkg::Build { virtual void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const override; + Triplet default_triplet, + Triplet host_triplet) const override; }; } diff --git a/include/vcpkg/commands.buildexternal.h b/include/vcpkg/commands.buildexternal.h index b4e1aa669b..4187fa3876 100644 --- a/include/vcpkg/commands.buildexternal.h +++ b/include/vcpkg/commands.buildexternal.h @@ -4,12 +4,16 @@ namespace vcpkg::Commands::BuildExternal { - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet); struct BuildExternalCommand : TripletCommand { virtual void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const override; + Triplet default_triplet, + Triplet host_triplet) const override; }; } diff --git a/include/vcpkg/commands.ci.h b/include/vcpkg/commands.ci.h index 4657741c92..8061e14354 100644 --- a/include/vcpkg/commands.ci.h +++ b/include/vcpkg/commands.ci.h @@ -5,12 +5,16 @@ namespace vcpkg::Commands::CI { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet); struct CICommand : TripletCommand { virtual void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const override; + Triplet default_triplet, + Triplet host_triplet) const override; }; } diff --git a/include/vcpkg/commands.dependinfo.h b/include/vcpkg/commands.dependinfo.h index 81301b6d9c..ef5d8a1080 100644 --- a/include/vcpkg/commands.dependinfo.h +++ b/include/vcpkg/commands.dependinfo.h @@ -5,12 +5,16 @@ namespace vcpkg::Commands::DependInfo { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet); struct DependInfoCommand : TripletCommand { virtual void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const override; + Triplet default_triplet, + Triplet host_triplet) const override; }; } diff --git a/include/vcpkg/commands.env.h b/include/vcpkg/commands.env.h index 5ba58d081d..d7087e7e7f 100644 --- a/include/vcpkg/commands.env.h +++ b/include/vcpkg/commands.env.h @@ -5,12 +5,16 @@ namespace vcpkg::Commands::Env { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet); struct EnvCommand : TripletCommand { virtual void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const override; + Triplet default_triplet, + Triplet host_triplet) const override; }; } diff --git a/include/vcpkg/commands.interface.h b/include/vcpkg/commands.interface.h index c8bc14ca96..e9f6da0479 100644 --- a/include/vcpkg/commands.interface.h +++ b/include/vcpkg/commands.interface.h @@ -31,7 +31,8 @@ namespace vcpkg::Commands { virtual void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const = 0; + Triplet default_triplet, + Triplet host_triplet) const = 0; virtual ~TripletCommand() = default; }; } diff --git a/include/vcpkg/commands.setinstalled.h b/include/vcpkg/commands.setinstalled.h index c5723669bd..efeb864c0a 100644 --- a/include/vcpkg/commands.setinstalled.h +++ b/include/vcpkg/commands.setinstalled.h @@ -15,12 +15,16 @@ namespace vcpkg::Commands::SetInstalled Dependencies::ActionPlan action_plan, DryRun dry_run, const Optional& pkgsconfig_path); - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet); struct SetInstalledCommand : TripletCommand { virtual void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const override; + Triplet default_triplet, + Triplet host_triplet) const override; }; } diff --git a/include/vcpkg/commands.upgrade.h b/include/vcpkg/commands.upgrade.h index 340a70c97c..8f724a0808 100644 --- a/include/vcpkg/commands.upgrade.h +++ b/include/vcpkg/commands.upgrade.h @@ -5,12 +5,16 @@ namespace vcpkg::Commands::Upgrade { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet); struct UpgradeCommand : TripletCommand { virtual void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const override; + Triplet default_triplet, + Triplet host_triplet) const override; }; } diff --git a/include/vcpkg/dependencies.h b/include/vcpkg/dependencies.h index 1b1a7748b6..8a30b3fd1b 100644 --- a/include/vcpkg/dependencies.h +++ b/include/vcpkg/dependencies.h @@ -56,6 +56,7 @@ namespace vcpkg::Dependencies InstallPlanAction(const PackageSpec& spec, const SourceControlFileLocation& scfl, const RequestType& request_type, + Triplet host_triplet, std::map>&& dependencies); std::string displayname() const; @@ -76,6 +77,7 @@ namespace vcpkg::Dependencies std::map> feature_dependencies; std::vector package_dependencies; std::vector feature_list; + Triplet host_triplet; Optional abi_info; }; @@ -142,7 +144,11 @@ namespace vcpkg::Dependencies struct CreateInstallPlanOptions { + CreateInstallPlanOptions(Graphs::Randomizer* r, Triplet t) : randomizer(r), host_triplet(t) { } + CreateInstallPlanOptions(Triplet t) : host_triplet(t) { } + Graphs::Randomizer* randomizer = nullptr; + Triplet host_triplet; }; std::vector create_remove_plan(const std::vector& specs, @@ -159,30 +165,31 @@ namespace vcpkg::Dependencies const CMakeVars::CMakeVarProvider& var_provider, const std::vector& specs, const StatusParagraphs& status_db, - const CreateInstallPlanOptions& options = {}); + const CreateInstallPlanOptions& options = {Triplet{}}); ActionPlan create_upgrade_plan(const PortFileProvider::PortFileProvider& provider, const CMakeVars::CMakeVarProvider& var_provider, const std::vector& specs, const StatusParagraphs& status_db, - const CreateInstallPlanOptions& options = {}); + const CreateInstallPlanOptions& options = {Triplet{}}); // `features` should have "default" instead of missing "core". This is only exposed for testing purposes. std::vector resolve_deps_as_top_level(const SourceControlFile& scf, Triplet triplet, + Triplet host_triplet, std::vector features, CMakeVars::CMakeVarProvider& var_provider); - /// Contains the ports of the current environment. - /// Feature specifications to resolve dependencies for. - /// Status of installed packages in the current environment. ExpectedS create_versioned_install_plan(const PortFileProvider::IVersionedPortfileProvider& vprovider, const PortFileProvider::IBaselineProvider& bprovider, const PortFileProvider::IOverlayProvider& oprovider, const CMakeVars::CMakeVarProvider& var_provider, const std::vector& deps, const std::vector& overrides, - const PackageSpec& toplevel); + const PackageSpec& toplevel, + Triplet host_triplet); - void print_plan(const ActionPlan& action_plan, const bool is_recursive = true, const fs::path& vcpkg_root_dir = {}); + void print_plan(const ActionPlan& action_plan, + const bool is_recursive = true, + const fs::path& builtin_ports_dir = {}); } diff --git a/include/vcpkg/export.h b/include/vcpkg/export.h index 0dd5b1aacd..f440fee0c0 100644 --- a/include/vcpkg/export.h +++ b/include/vcpkg/export.h @@ -14,6 +14,7 @@ namespace vcpkg::Export { virtual void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const override; + Triplet default_triplet, + Triplet host_triplet) const override; }; } diff --git a/include/vcpkg/install.h b/include/vcpkg/install.h index 8187735c5f..103a0b30a9 100644 --- a/include/vcpkg/install.h +++ b/include/vcpkg/install.h @@ -105,12 +105,16 @@ namespace vcpkg::Install extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet); struct InstallCommand : Commands::TripletCommand { virtual void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const override; + Triplet default_triplet, + Triplet host_triplet) const override; }; } diff --git a/include/vcpkg/packagespec.h b/include/vcpkg/packagespec.h index 43be57e68c..44b1fbab36 100644 --- a/include/vcpkg/packagespec.h +++ b/include/vcpkg/packagespec.h @@ -149,10 +149,20 @@ namespace vcpkg struct Dependency { + // Remove when support for MSVC v140 is dropped. + Dependency(std::string n = {}, + std::vector f = {}, + PlatformExpression::Expr expr = {}, + DependencyConstraint dc = {}, + bool h = false) + : name(std::move(n)), features(std::move(f)), platform(std::move(expr)), constraint(std::move(dc)), host(h) + { + } std::string name; std::vector features; PlatformExpression::Expr platform; DependencyConstraint constraint; + bool host = false; Json::Object extra_info; diff --git a/include/vcpkg/remove.h b/include/vcpkg/remove.h index faba3e3686..74e56aaba5 100644 --- a/include/vcpkg/remove.h +++ b/include/vcpkg/remove.h @@ -29,6 +29,7 @@ namespace vcpkg::Remove { virtual void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const override; + Triplet default_triplet, + Triplet host_triplet) const override; }; } diff --git a/include/vcpkg/sourceparagraph.h b/include/vcpkg/sourceparagraph.h index 52ce539808..a88252f83f 100644 --- a/include/vcpkg/sourceparagraph.h +++ b/include/vcpkg/sourceparagraph.h @@ -19,6 +19,7 @@ namespace vcpkg { std::vector filter_dependencies(const std::vector& deps, Triplet t, + Triplet host, const std::unordered_map& cmake_vars); struct Type @@ -71,7 +72,7 @@ namespace vcpkg std::string license; // SPDX license expression Optional builtin_baseline; - Type type; + Type type = {Type::PORT}; PlatformExpression::Expr supports_expression; Json::Object extra_info; diff --git a/include/vcpkg/triplet.h b/include/vcpkg/triplet.h index 40f6d6f236..21da0d5dad 100644 --- a/include/vcpkg/triplet.h +++ b/include/vcpkg/triplet.h @@ -38,6 +38,7 @@ namespace vcpkg inline bool operator!=(Triplet left, Triplet right) { return !(left == right); } Triplet default_triplet(const VcpkgCmdArguments& args); + Triplet default_host_triplet(const VcpkgCmdArguments& args); } namespace std diff --git a/include/vcpkg/vcpkgcmdarguments.h b/include/vcpkg/vcpkgcmdarguments.h index 14208e926b..5c8cba1a6f 100644 --- a/include/vcpkg/vcpkgcmdarguments.h +++ b/include/vcpkg/vcpkgcmdarguments.h @@ -143,6 +143,9 @@ namespace vcpkg constexpr static StringLiteral TRIPLET_ENV = "VCPKG_DEFAULT_TRIPLET"; constexpr static StringLiteral TRIPLET_ARG = "triplet"; std::unique_ptr triplet; + constexpr static StringLiteral HOST_TRIPLET_ENV = "VCPKG_DEFAULT_HOST_TRIPLET"; + constexpr static StringLiteral HOST_TRIPLET_ARG = "host-triplet"; + std::unique_ptr host_triplet; constexpr static StringLiteral OVERLAY_PORTS_ENV = "VCPKG_OVERLAY_PORTS"; constexpr static StringLiteral OVERLAY_PORTS_ARG = "overlay-ports"; std::vector overlay_ports; diff --git a/src/vcpkg-test/binarycaching.cpp b/src/vcpkg-test/binarycaching.cpp index 8a1a28d237..d4352d07e9 100644 --- a/src/vcpkg-test/binarycaching.cpp +++ b/src/vcpkg-test/binarycaching.cpp @@ -87,6 +87,7 @@ Build-Depends: bzip Dependencies::InstallPlanAction ipa(PackageSpec{"zlib2", Test::X64_WINDOWS}, scfl, Dependencies::RequestType::USER_REQUESTED, + Test::ARM_UWP, {{"a", {}}, {"b", {}}}); ipa.abi_info = Build::AbiInfo{}; diff --git a/src/vcpkg-test/dependencies.cpp b/src/vcpkg-test/dependencies.cpp index 696a3ee142..1861d7cecb 100644 --- a/src/vcpkg-test/dependencies.cpp +++ b/src/vcpkg-test/dependencies.cpp @@ -215,7 +215,23 @@ static ExpectedS create_versioned_install_plan( const PackageSpec& toplevel) { return Dependencies::create_versioned_install_plan( - provider, bprovider, s_empty_mock_overlay, var_provider, deps, overrides, toplevel); + provider, bprovider, s_empty_mock_overlay, var_provider, deps, overrides, toplevel, Test::ARM_UWP); +} + +namespace vcpkg::Dependencies +{ + static ExpectedS create_versioned_install_plan( + const PortFileProvider::IVersionedPortfileProvider& provider, + const PortFileProvider::IBaselineProvider& bprovider, + const PortFileProvider::IOverlayProvider& oprovider, + const CMakeVars::CMakeVarProvider& var_provider, + const std::vector& deps, + const std::vector& overrides, + const PackageSpec& toplevel) + { + return vcpkg::Dependencies::create_versioned_install_plan( + provider, bprovider, oprovider, var_provider, deps, overrides, toplevel, Test::ARM_UWP); + } } TEST_CASE ("basic version install single", "[versionplan]") @@ -1646,6 +1662,89 @@ TEST_CASE ("version install self features", "[versionplan]") check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}, {"x", "y"}); } +static auto create_versioned_install_plan(MockVersionedPortfileProvider& vp, + MockBaselineProvider& bp, + std::vector deps) +{ + MockCMakeVarProvider var_provider; + + return create_versioned_install_plan(vp, bp, var_provider, deps, {}, toplevel_spec()); +} + +TEST_CASE ("version install host tool", "[versionplan]") +{ + MockBaselineProvider bp; + bp.v["a"] = {"1", 0}; + bp.v["b"] = {"1", 0}; + bp.v["c"] = {"1", 0}; + bp.v["d"] = {"1", 0}; + + MockVersionedPortfileProvider vp; + vp.emplace("a", {"1", 0}); + auto& b_scf = vp.emplace("b", {"1", 0}).source_control_file; + b_scf->core_paragraph->dependencies.push_back(Dependency{"a", {}, {}, {}, true}); + auto& c_scf = vp.emplace("c", {"1", 0}).source_control_file; + c_scf->core_paragraph->dependencies.push_back(Dependency{"a"}); + auto& d_scf = vp.emplace("d", {"1", 0}).source_control_file; + d_scf->core_paragraph->dependencies.push_back(Dependency{"d", {}, {}, {}, true}); + + SECTION ("normal toplevel") + { + Dependency dep_c{"c"}; + + auto install_plan = unwrap(create_versioned_install_plan(vp, bp, {dep_c})); + + REQUIRE(install_plan.size() == 2); + check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}); + REQUIRE(install_plan.install_actions[0].spec.triplet() == Test::X86_WINDOWS); + check_name_and_version(install_plan.install_actions[1], "c", {"1", 0}); + REQUIRE(install_plan.install_actions[1].spec.triplet() == Test::X86_WINDOWS); + } + SECTION ("toplevel") + { + Dependency dep_a{"a"}; + dep_a.host = true; + + auto install_plan = unwrap(create_versioned_install_plan(vp, bp, {dep_a})); + + REQUIRE(install_plan.size() == 1); + check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}); + REQUIRE(install_plan.install_actions[0].spec.triplet() == Test::ARM_UWP); + } + SECTION ("transitive 1") + { + auto install_plan = unwrap(create_versioned_install_plan(vp, bp, {{"b"}})); + + REQUIRE(install_plan.size() == 2); + check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}); + REQUIRE(install_plan.install_actions[0].spec.triplet() == Test::ARM_UWP); + check_name_and_version(install_plan.install_actions[1], "b", {"1", 0}); + REQUIRE(install_plan.install_actions[1].spec.triplet() == Test::X86_WINDOWS); + } + SECTION ("transitive 2") + { + Dependency dep_c{"c"}; + dep_c.host = true; + + auto install_plan = unwrap(create_versioned_install_plan(vp, bp, {dep_c})); + + REQUIRE(install_plan.size() == 2); + check_name_and_version(install_plan.install_actions[0], "a", {"1", 0}); + REQUIRE(install_plan.install_actions[0].spec.triplet() == Test::ARM_UWP); + check_name_and_version(install_plan.install_actions[1], "c", {"1", 0}); + REQUIRE(install_plan.install_actions[1].spec.triplet() == Test::ARM_UWP); + } + SECTION ("self-reference") + { + auto install_plan = unwrap(create_versioned_install_plan(vp, bp, {{"d"}})); + + REQUIRE(install_plan.size() == 2); + check_name_and_version(install_plan.install_actions[0], "d", {"1", 0}); + REQUIRE(install_plan.install_actions[0].spec.triplet() == Test::ARM_UWP); + check_name_and_version(install_plan.install_actions[1], "d", {"1", 0}); + REQUIRE(install_plan.install_actions[1].spec.triplet() == Test::X86_WINDOWS); + } +} TEST_CASE ("version overlay ports", "[versionplan]") { MockBaselineProvider bp; diff --git a/src/vcpkg-test/manifests.cpp b/src/vcpkg-test/manifests.cpp index bbbe0c96c5..8eee3f4959 100644 --- a/src/vcpkg-test/manifests.cpp +++ b/src/vcpkg-test/manifests.cpp @@ -609,6 +609,37 @@ TEST_CASE ("SourceParagraph manifest construct qualified dependencies", "[manife REQUIRE(pgh.core_paragraph->dependencies[1].platform.evaluate({{"VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore"}})); } +TEST_CASE ("SourceParagraph manifest construct host dependencies", "[manifests]") +{ + std::string raw = R"json({ + "name": "zlib", + "version-string": "1.2.8", + "dependencies": [ + { + "name": "liba", + "host": true + }, + "libb" + ] +} +)json"; + auto m_pgh = test_parse_manifest(raw); + REQUIRE(m_pgh.has_value()); + auto& pgh = **m_pgh.get(); + + REQUIRE(pgh.core_paragraph->name == "zlib"); + REQUIRE(pgh.core_paragraph->version == "1.2.8"); + REQUIRE(pgh.core_paragraph->maintainers.empty()); + REQUIRE(pgh.core_paragraph->description.empty()); + REQUIRE(pgh.core_paragraph->dependencies.size() == 2); + REQUIRE(pgh.core_paragraph->dependencies[0].name == "liba"); + REQUIRE(pgh.core_paragraph->dependencies[0].host); + REQUIRE(pgh.core_paragraph->dependencies[1].name == "libb"); + REQUIRE(!pgh.core_paragraph->dependencies[1].host); + + REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == raw); +} + TEST_CASE ("SourceParagraph manifest default features", "[manifests]") { auto m_pgh = test_parse_manifest(R"json({ diff --git a/src/vcpkg-test/paragraph.cpp b/src/vcpkg-test/paragraph.cpp index cb3f8e6207..b44aaf50ab 100644 --- a/src/vcpkg-test/paragraph.cpp +++ b/src/vcpkg-test/paragraph.cpp @@ -242,7 +242,7 @@ TEST_CASE ("BinaryParagraph construct maximum", "[paragraph]") REQUIRE(pgh.description.size() == 1); REQUIRE(pgh.description[0] == "d"); REQUIRE(pgh.dependencies.size() == 1); - REQUIRE(pgh.dependencies[0] == "bd"); + REQUIRE(pgh.dependencies[0].name() == "bd"); } TEST_CASE ("BinaryParagraph three dependencies", "[paragraph]") @@ -256,9 +256,28 @@ TEST_CASE ("BinaryParagraph three dependencies", "[paragraph]") }); REQUIRE(pgh.dependencies.size() == 3); - REQUIRE(pgh.dependencies[0] == "a"); - REQUIRE(pgh.dependencies[1] == "b"); - REQUIRE(pgh.dependencies[2] == "c"); + REQUIRE(pgh.dependencies[0].name() == "a"); + REQUIRE(pgh.dependencies[1].name() == "b"); + REQUIRE(pgh.dependencies[2].name() == "c"); +} + +TEST_CASE ("BinaryParagraph dependencies with triplets", "[paragraph]") +{ + auto pgh = test_make_binary_paragraph({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", "a:x64-windows, b, c:arm-uwp"}, + }); + + REQUIRE(pgh.dependencies.size() == 3); + REQUIRE(pgh.dependencies[0].name() == "a"); + REQUIRE(pgh.dependencies[0].triplet() == vcpkg::Test::X64_WINDOWS); + REQUIRE(pgh.dependencies[1].name() == "b"); + REQUIRE(pgh.dependencies[1].triplet() == vcpkg::Test::X86_WINDOWS); + REQUIRE(pgh.dependencies[2].name() == "c"); + REQUIRE(pgh.dependencies[2].triplet() == vcpkg::Test::ARM_UWP); } TEST_CASE ("BinaryParagraph abi", "[paragraph]") @@ -484,18 +503,36 @@ TEST_CASE ("BinaryParagraph serialize max", "[paragraph]") TEST_CASE ("BinaryParagraph serialize multiple deps", "[paragraph]") { - auto pgh = test_make_binary_paragraph({ - {"Package", "zlib"}, - {"Version", "1.2.8"}, - {"Architecture", "x86-windows"}, - {"Multi-Arch", "same"}, - {"Depends", "a, b, c"}, - }); - std::string ss = Strings::serialize(pgh); - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss, "").value_or_exit(VCPKG_LINE_INFO); - - REQUIRE(pghs.size() == 1); - REQUIRE(pghs[0]["Depends"].first == "a, b, c"); + SECTION ("target only") + { + auto pgh = test_make_binary_paragraph({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", "a, b, c"}, + }); + std::string ss = Strings::serialize(pgh); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss, "").value_or_exit(VCPKG_LINE_INFO); + + REQUIRE(pghs.size() == 1); + REQUIRE(pghs[0]["Depends"].first == "a, b, c"); + } + SECTION ("host deps") + { + auto pgh = test_make_binary_paragraph({ + {"Package", "zlib"}, + {"Version", "1.2.8"}, + {"Architecture", "x86-windows"}, + {"Multi-Arch", "same"}, + {"Depends", "a:x64-windows, b, c:arm-uwp"}, + }); + std::string ss = Strings::serialize(pgh); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss, "").value_or_exit(VCPKG_LINE_INFO); + + REQUIRE(pghs.size() == 1); + REQUIRE(pghs[0]["Depends"].first == "a:x64-windows, b, c:arm-uwp"); + } } TEST_CASE ("BinaryParagraph serialize abi", "[paragraph]") diff --git a/src/vcpkg-test/plan.cpp b/src/vcpkg-test/plan.cpp index 363a2d9b46..74cdce868f 100644 --- a/src/vcpkg-test/plan.cpp +++ b/src/vcpkg-test/plan.cpp @@ -1066,6 +1066,159 @@ TEST_CASE ("features depend core remove scheme 2", "[plan]") REQUIRE(remove_plan.at(0).spec.name() == "curl"); } +TEST_CASE ("self-referencing scheme", "[plan]") +{ + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "a"); + auto spec_b = spec_map.emplace("b", "b, b (x64)"); + + PortFileProvider::MapPortFileProvider map_port(spec_map.map); + MockCMakeVarProvider var_provider; + + SECTION ("basic") + { + auto install_plan = Dependencies::create_feature_install_plan( + map_port, var_provider, {FullPackageSpec{spec_a, {}}}, {}, {{}, Test::X64_WINDOWS}); + + REQUIRE(install_plan.size() == 1); + REQUIRE(install_plan.install_actions.at(0).spec == spec_a); + } + SECTION ("qualified") + { + auto install_plan = Dependencies::create_feature_install_plan( + map_port, var_provider, {FullPackageSpec{spec_b, {}}}, {}, {{}, Test::X64_WINDOWS}); + + REQUIRE(install_plan.size() == 1); + REQUIRE(install_plan.install_actions.at(0).spec == spec_b); + } +} + +TEST_CASE ("basic tool port scheme", "[plan]") +{ + std::vector> status_paragraphs; + + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "b"); + auto spec_b = spec_map.emplace("b", "c"); + auto spec_c = spec_map.emplace("c"); + + spec_map.map.at("a").source_control_file->core_paragraph->dependencies[0].host = true; + + PortFileProvider::MapPortFileProvider map_port(spec_map.map); + MockCMakeVarProvider var_provider; + + auto install_plan = Dependencies::create_feature_install_plan(map_port, + var_provider, + {FullPackageSpec{spec_a, {}}}, + StatusParagraphs(std::move(status_paragraphs)), + {{}, Test::X64_WINDOWS}); + + REQUIRE(install_plan.size() == 3); + REQUIRE(install_plan.install_actions.at(0).spec.name() == "c"); + REQUIRE(install_plan.install_actions.at(0).spec.triplet() == Test::X64_WINDOWS); + REQUIRE(install_plan.install_actions.at(1).spec.name() == "b"); + REQUIRE(install_plan.install_actions.at(1).spec.triplet() == Test::X64_WINDOWS); + REQUIRE(install_plan.install_actions.at(2).spec.name() == "a"); +} + +TEST_CASE ("basic existing tool port scheme", "[plan]") +{ + std::vector> pghs; + pghs.push_back(make_status_pgh("b", "", "", "x64-windows")); + StatusParagraphs status_db(std::move(pghs)); + MockCMakeVarProvider var_provider; + + SECTION ("a+b") + { + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "b"); + auto spec_b = spec_map.emplace("b"); + + spec_map.map.at("a").source_control_file->core_paragraph->dependencies[0].host = true; + + PortFileProvider::MapPortFileProvider map_port(spec_map.map); + + auto install_plan = Dependencies::create_feature_install_plan( + map_port, var_provider, {FullPackageSpec{spec_a, {}}}, status_db, {{}, Test::X64_WINDOWS}); + + REQUIRE(install_plan.size() == 1); + REQUIRE(install_plan.install_actions.at(0).spec == spec_a); + } + + SECTION ("a recurse") + { + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "a"); + + spec_map.map.at("a").source_control_file->core_paragraph->dependencies[0].host = true; + + PortFileProvider::MapPortFileProvider map_port(spec_map.map); + + auto install_plan = Dependencies::create_feature_install_plan( + map_port, var_provider, {FullPackageSpec{spec_a, {}}}, status_db, {{}, Test::X64_WINDOWS}); + + REQUIRE(install_plan.size() == 2); + REQUIRE(install_plan.install_actions.at(0).spec.name() == "a"); + REQUIRE(install_plan.install_actions.at(0).spec.triplet() == Test::X64_WINDOWS); + REQUIRE(install_plan.install_actions.at(1).spec == spec_a); + + install_plan = Dependencies::create_feature_install_plan( + map_port, var_provider, {FullPackageSpec{spec_a, {}}}, status_db, {{}, Test::X86_WINDOWS}); + + REQUIRE(install_plan.size() == 1); + REQUIRE(install_plan.install_actions.at(0).spec == spec_a); + } + + SECTION ("a+b (arm)") + { + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "b"); + auto spec_b = spec_map.emplace("b"); + + spec_map.map.at("a").source_control_file->core_paragraph->dependencies[0].host = true; + + PortFileProvider::MapPortFileProvider map_port(spec_map.map); + + auto install_plan = Dependencies::create_feature_install_plan( + map_port, var_provider, {FullPackageSpec{spec_a, {}}}, status_db, {{}, Test::ARM_UWP}); + + REQUIRE(install_plan.size() == 2); + REQUIRE(install_plan.install_actions.at(0).spec.name() == "b"); + REQUIRE(install_plan.install_actions.at(0).spec.triplet() == Test::ARM_UWP); + REQUIRE(install_plan.install_actions.at(1).spec == spec_a); + } + + SECTION ("a+b+c") + { + PackageSpecMap spec_map; + auto spec_a = spec_map.emplace("a", "b"); + auto spec_b = spec_map.emplace("b", "c"); + auto spec_c = spec_map.emplace("c"); + + spec_map.map.at("a").source_control_file->core_paragraph->dependencies[0].host = true; + + PortFileProvider::MapPortFileProvider map_port(spec_map.map); + + auto install_plan = Dependencies::create_feature_install_plan( + map_port, var_provider, {FullPackageSpec{spec_a, {}}}, status_db, {{}, Test::X64_WINDOWS}); + + REQUIRE(install_plan.size() == 1); + REQUIRE(install_plan.install_actions.at(0).spec == spec_a); + } +} + +TEST_CASE ("remove tool port scheme", "[plan]") +{ + std::vector> pghs; + pghs.push_back(make_status_pgh("a")); + StatusParagraphs status_db(std::move(pghs)); + + auto remove_plan = Dependencies::create_remove_plan({{"a", Test::X86_WINDOWS}}, status_db); + + REQUIRE(remove_plan.size() == 1); + REQUIRE(remove_plan.at(0).spec.name() == "a"); +} + TEST_CASE ("basic upgrade scheme", "[plan]") { std::vector> pghs; diff --git a/src/vcpkg-test/versionplan.cpp b/src/vcpkg-test/versionplan.cpp index 2f82d21b43..0d004ab632 100644 --- a/src/vcpkg-test/versionplan.cpp +++ b/src/vcpkg-test/versionplan.cpp @@ -34,12 +34,12 @@ TEST_CASE ("filter depends", "[dependencies]") auto deps_ = parse_dependencies_list("liba (!uwp), libb, libc (uwp)"); REQUIRE(deps_); auto& deps = *deps_.get(); - auto v = filter_dependencies(deps, Test::X64_WINDOWS, x64_win_cmake_vars); + auto v = filter_dependencies(deps, Test::X64_WINDOWS, Test::X86_WINDOWS, x64_win_cmake_vars); REQUIRE(v.size() == 2); REQUIRE(v.at(0).package_spec.name() == "liba"); REQUIRE(v.at(1).package_spec.name() == "libb"); - auto v2 = filter_dependencies(deps, Test::ARM_UWP, arm_uwp_cmake_vars); + auto v2 = filter_dependencies(deps, Test::ARM_UWP, Test::X86_WINDOWS, arm_uwp_cmake_vars); REQUIRE(v.size() == 2); REQUIRE(v2.at(0).package_spec.name() == "libb"); REQUIRE(v2.at(1).package_spec.name() == "libc"); @@ -95,6 +95,8 @@ TEST_CASE ("resolve_deps_as_top_level", "[dependencies]") FullPackageSpec spec_b{spec_map.emplace("b", "", {{"b1", ""}}), {}}; FullPackageSpec spec_c{spec_map.emplace("c", "b", {{"c1", "b[b1]"}, {"c2", "c[c1], a"}}, {"c1"}), {"core"}}; FullPackageSpec spec_d{spec_map.emplace("d", "c[core]"), {}}; + FullPackageSpec spec_e{spec_map.emplace("e", "c[core]"), {}}; + spec_map.map.at("e").source_control_file->core_paragraph->dependencies[0].host = true; PortFileProvider::MapPortFileProvider map_port{spec_map.map}; MockCMakeVarProvider var_provider; @@ -102,20 +104,20 @@ TEST_CASE ("resolve_deps_as_top_level", "[dependencies]") var_provider.dep_info_vars[{"a", t_linux}].emplace("VCPKG_CMAKE_SYSTEM_NAME", "Linux"); { auto deps = vcpkg::Dependencies::resolve_deps_as_top_level( - *spec_map.map.at("a").source_control_file, Test::X86_WINDOWS, {}, var_provider); + *spec_map.map.at("a").source_control_file, Test::X86_WINDOWS, Test::ARM_UWP, {}, var_provider); REQUIRE(deps.size() == 1); REQUIRE(deps.at(0) == spec_b); } { auto deps = vcpkg::Dependencies::resolve_deps_as_top_level( - *spec_map.map.at("a").source_control_file, t_linux, {}, var_provider); + *spec_map.map.at("a").source_control_file, t_linux, Test::ARM_UWP, {}, var_provider); REQUIRE(deps.size() == 1); REQUIRE(deps.at(0) == FullPackageSpec({"b", t_linux}, {"b1"})); } { // without defaults auto deps = vcpkg::Dependencies::resolve_deps_as_top_level( - *spec_map.map.at("c").source_control_file, Test::X86_WINDOWS, {}, var_provider); + *spec_map.map.at("c").source_control_file, Test::X86_WINDOWS, Test::ARM_UWP, {}, var_provider); REQUIRE(deps.size() == 1); REQUIRE(deps.at(0) == spec_b); } @@ -123,21 +125,21 @@ TEST_CASE ("resolve_deps_as_top_level", "[dependencies]") { // with defaults of c (c1) auto deps = vcpkg::Dependencies::resolve_deps_as_top_level( - *spec_map.map.at("c").source_control_file, Test::X86_WINDOWS, {"default"}, var_provider); + *spec_map.map.at("c").source_control_file, Test::X86_WINDOWS, Test::ARM_UWP, {"default"}, var_provider); REQUIRE(deps.size() == 1); REQUIRE(deps.at(0) == spec_b_with_b1); } { // with c1 auto deps = vcpkg::Dependencies::resolve_deps_as_top_level( - *spec_map.map.at("c").source_control_file, Test::X86_WINDOWS, {"c1"}, var_provider); + *spec_map.map.at("c").source_control_file, Test::X86_WINDOWS, Test::ARM_UWP, {"c1"}, var_provider); REQUIRE(deps.size() == 1); REQUIRE(deps.at(0) == spec_b_with_b1); } { // with c2 implying c1 auto deps = vcpkg::Dependencies::resolve_deps_as_top_level( - *spec_map.map.at("c").source_control_file, Test::X86_WINDOWS, {"c2"}, var_provider); + *spec_map.map.at("c").source_control_file, Test::X86_WINDOWS, Test::ARM_UWP, {"c2"}, var_provider); REQUIRE(deps.size() == 2); REQUIRE(deps.at(0) == spec_a); REQUIRE(deps.at(1) == spec_b_with_b1); @@ -145,8 +147,17 @@ TEST_CASE ("resolve_deps_as_top_level", "[dependencies]") { // d -> c[core] auto deps = vcpkg::Dependencies::resolve_deps_as_top_level( - *spec_map.map.at("d").source_control_file, Test::X86_WINDOWS, {}, var_provider); + *spec_map.map.at("d").source_control_file, Test::X86_WINDOWS, Test::ARM_UWP, {}, var_provider); REQUIRE(deps.size() == 1); REQUIRE(deps.at(0) == spec_c); } + SECTION ("host dep") + { + // e -> c[core]:$host + auto deps = vcpkg::Dependencies::resolve_deps_as_top_level( + *spec_map.map.at("e").source_control_file, Test::X86_WINDOWS, Test::ARM_UWP, {}, var_provider); + REQUIRE(deps.size() == 1); + REQUIRE(deps.at(0).package_spec.name() == "c"); + REQUIRE(deps.at(0).package_spec.triplet() == Test::ARM_UWP); + } } diff --git a/src/vcpkg.cpp b/src/vcpkg.cpp index f25a0c3b60..3e4dd000b0 100644 --- a/src/vcpkg.cpp +++ b/src/vcpkg.cpp @@ -87,10 +87,12 @@ static void inner(vcpkg::Files::Filesystem& fs, const VcpkgCmdArguments& args) Triplet default_triplet = vcpkg::default_triplet(args); Input::check_triplet(default_triplet, paths); + Triplet host_triplet = vcpkg::default_host_triplet(args); + Input::check_triplet(host_triplet, paths); if (const auto command_function = find_command(Commands::get_available_triplet_commands())) { - return command_function->function->perform_and_exit(args, paths, default_triplet); + return command_function->function->perform_and_exit(args, paths, default_triplet, host_triplet); } return invalid_command(args.command); diff --git a/src/vcpkg/binaryparagraph.cpp b/src/vcpkg/binaryparagraph.cpp index d30fd47516..b22d9faca8 100644 --- a/src/vcpkg/binaryparagraph.cpp +++ b/src/vcpkg/binaryparagraph.cpp @@ -71,11 +71,16 @@ namespace vcpkg std::string multi_arch; parser.required_field(Fields::MULTI_ARCH, multi_arch); + Triplet my_triplet = this->spec.triplet(); this->dependencies = Util::fmap( parse_qualified_specifier_list(parser.optional_field(Fields::DEPENDS)).value_or_exit(VCPKG_LINE_INFO), - [](const ParsedQualifiedSpecifier& dep) { + [my_triplet](const ParsedQualifiedSpecifier& dep) { // for compatibility with previous vcpkg versions, we discard all irrelevant information - return dep.name; + return PackageSpec{ + dep.name, + dep.triplet.map([](auto&& s) { return Triplet::from_canonical_name(std::string(s)); }) + .value_or(my_triplet), + }; }); if (!this->is_feature()) { @@ -113,7 +118,7 @@ namespace vcpkg , abi(abi_tag) , type(spgh.type) { - this->dependencies = Util::fmap(deps, [](const FeatureSpec& spec) { return spec.spec().name(); }); + this->dependencies = Util::fmap(deps, [](const FeatureSpec& spec) { return spec.spec(); }); canonicalize(); } @@ -132,7 +137,7 @@ namespace vcpkg , abi() , type(spgh.type) { - this->dependencies = Util::fmap(deps, [](const FeatureSpec& spec) { return spec.spec().name(); }); + this->dependencies = Util::fmap(deps, [](const FeatureSpec& spec) { return spec.spec(); }); canonicalize(); } @@ -223,6 +228,20 @@ namespace vcpkg serialize_array(name, array, out_str, "\n "); } + static std::string serialize_deps_list(View deps, Triplet target) + { + return Strings::join(", ", deps, [target](const PackageSpec& pspec) { + if (pspec.triplet() == target) + { + return pspec.name(); + } + else + { + return pspec.to_string(); + } + }); + } + void serialize(const BinaryParagraph& pgh, std::string& out_str) { const size_t initial_end = out_str.size(); @@ -242,7 +261,7 @@ namespace vcpkg if (!pgh.dependencies.empty()) { - serialize_array(Fields::DEPENDS, pgh.dependencies, out_str); + serialize_string(Fields::DEPENDS, serialize_deps_list(pgh.dependencies, pgh.spec.triplet()), out_str); } serialize_string(Fields::ARCHITECTURE, pgh.spec.triplet().to_string(), out_str); diff --git a/src/vcpkg/build.cpp b/src/vcpkg/build.cpp index b38062f0c9..0b5ae8420d 100644 --- a/src/vcpkg/build.cpp +++ b/src/vcpkg/build.cpp @@ -59,14 +59,16 @@ namespace vcpkg::Build void Command::perform_and_exit_ex(const VcpkgCmdArguments& args, const FullPackageSpec& full_spec, + Triplet host_triplet, const SourceControlFileLocation& scfl, const PathsPortFileProvider& provider, IBinaryProvider& binaryprovider, const IBuildLogsRecorder& build_logs_recorder, const VcpkgPaths& paths) { - Checks::exit_with_code(VCPKG_LINE_INFO, - perform_ex(args, full_spec, scfl, provider, binaryprovider, build_logs_recorder, paths)); + Checks::exit_with_code( + VCPKG_LINE_INFO, + perform_ex(args, full_spec, host_triplet, scfl, provider, binaryprovider, build_logs_recorder, paths)); } const CommandStructure COMMAND_STRUCTURE = { @@ -77,13 +79,17 @@ namespace vcpkg::Build nullptr, }; - void Command::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) + void Command::perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet) { - Checks::exit_with_code(VCPKG_LINE_INFO, perform(args, paths, default_triplet)); + Checks::exit_with_code(VCPKG_LINE_INFO, perform(args, paths, default_triplet, host_triplet)); } int Command::perform_ex(const VcpkgCmdArguments& args, const FullPackageSpec& full_spec, + Triplet host_triplet, const SourceControlFileLocation& scfl, const PathsPortFileProvider& provider, IBinaryProvider& binaryprovider, @@ -97,7 +103,7 @@ namespace vcpkg::Build StatusParagraphs status_db = database_load_check(paths); auto action_plan = Dependencies::create_feature_install_plan( - provider, var_provider, std::vector{full_spec}, status_db); + provider, var_provider, std::vector{full_spec}, status_db, {host_triplet}); var_provider.load_tag_vars(action_plan, provider); @@ -165,7 +171,10 @@ namespace vcpkg::Build return 0; } - int Command::perform(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) + int Command::perform(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet) { // Build only takes a single package and all dependencies must already be installed const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); @@ -187,6 +196,7 @@ namespace vcpkg::Build return perform_ex(args, spec, + host_triplet, *scfl, provider, args.binary_caching_enabled() ? *binaryprovider : null_binary_provider(), @@ -196,9 +206,10 @@ namespace vcpkg::Build void BuildCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const + Triplet default_triplet, + Triplet host_triplet) const { - Build::Command::perform_and_exit(args, paths, default_triplet); + Build::Command::perform_and_exit(args, paths, default_triplet, host_triplet); } } @@ -573,6 +584,8 @@ namespace vcpkg::Build {"CURRENT_PORT_DIR", paths.scripts / "detect_compiler"}, {"CURRENT_BUILDTREES_DIR", buildpath}, {"CURRENT_PACKAGES_DIR", paths.packages / ("detect_compiler_" + triplet.canonical_name())}, + // The detect_compiler "port" doesn't depend on the host triplet, so always natively compile + {"_HOST_TRIPLET", triplet.canonical_name()}, }; get_generic_cmake_build_args(paths, triplet, abi_info.toolset.value_or_exit(VCPKG_LINE_INFO), cmake_args); @@ -645,8 +658,7 @@ namespace vcpkg::Build static std::vector get_cmake_build_args(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - const Dependencies::InstallPlanAction& action, - Triplet triplet) + const Dependencies::InstallPlanAction& action) { #if !defined(_WIN32) // TODO: remove when vcpkg.exe is in charge for acquiring tools. Change introduced in vcpkg v0.0.107. @@ -665,6 +677,7 @@ namespace vcpkg::Build std::vector variables{ {"ALL_FEATURES", all_features}, {"CURRENT_PORT_DIR", scfl.source_location}, + {"_HOST_TRIPLET", action.host_triplet.canonical_name()}, {"FEATURES", Strings::join(";", action.feature_list)}, {"PORT", scf.core_paragraph->name}, {"VCPKG_USE_HEAD_VERSION", Util::Enum::to_bool(action.build_options.use_head_version) ? "1" : "0"}, @@ -685,7 +698,7 @@ namespace vcpkg::Build get_generic_cmake_build_args( paths, - triplet, + action.spec.triplet(), action.abi_info.value_or_exit(VCPKG_LINE_INFO).toolset.value_or_exit(VCPKG_LINE_INFO), variables); @@ -803,8 +816,7 @@ namespace vcpkg::Build const auto timer = Chrono::ElapsedTimer::create_started(); - auto command = - vcpkg::make_cmake_cmd(paths, paths.ports_cmake, get_cmake_build_args(args, paths, action, triplet)); + auto command = vcpkg::make_cmake_cmd(paths, paths.ports_cmake, get_cmake_build_args(args, paths, action)); const auto& env = paths.get_action_env(action.abi_info.value_or_exit(VCPKG_LINE_INFO)); diff --git a/src/vcpkg/buildenvironment.cpp b/src/vcpkg/buildenvironment.cpp index bc116f4f3c..c86aa93d21 100644 --- a/src/vcpkg/buildenvironment.cpp +++ b/src/vcpkg/buildenvironment.cpp @@ -1,5 +1,6 @@ #include #include +#include #include namespace vcpkg diff --git a/src/vcpkg/commands.buildexternal.cpp b/src/vcpkg/commands.buildexternal.cpp index 65b1ec8230..dbaf41e426 100644 --- a/src/vcpkg/commands.buildexternal.cpp +++ b/src/vcpkg/commands.buildexternal.cpp @@ -17,7 +17,10 @@ namespace vcpkg::Commands::BuildExternal nullptr, }; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet) { const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); @@ -38,6 +41,7 @@ namespace vcpkg::Commands::BuildExternal Build::Command::perform_and_exit_ex(args, spec, + host_triplet, maybe_scfl.value_or_exit(VCPKG_LINE_INFO), provider, args.binary_caching_enabled() ? *binaryprovider : null_binary_provider(), @@ -47,8 +51,9 @@ namespace vcpkg::Commands::BuildExternal void BuildExternalCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const + Triplet default_triplet, + Triplet host_triplet) const { - BuildExternal::perform_and_exit(args, paths, default_triplet); + BuildExternal::perform_and_exit(args, paths, default_triplet, host_triplet); } } diff --git a/src/vcpkg/commands.ci.cpp b/src/vcpkg/commands.ci.cpp index 26ae058add..0424ff7a27 100644 --- a/src/vcpkg/commands.ci.cpp +++ b/src/vcpkg/commands.ci.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -65,7 +66,8 @@ namespace { for (const fs::path& p : children) { - filesystem.copy_file(p, target_path / p.filename(), fs::copy_options::none, VCPKG_LINE_INFO); + filesystem.copy_file( + p, target_path / p.filename(), fs::copy_options::overwrite_existing, VCPKG_LINE_INFO); } } } @@ -292,7 +294,8 @@ namespace vcpkg::Commands::CI const PortFileProvider::PortFileProvider& provider, const CMakeVars::CMakeVarProvider& var_provider, const std::vector& specs, - IBinaryProvider& binaryprovider) + IBinaryProvider& binaryprovider, + const Dependencies::CreateInstallPlanOptions& serialize_options) { auto ret = std::make_unique(); @@ -312,7 +315,8 @@ namespace vcpkg::Commands::CI } var_provider.load_dep_info_vars(packages_with_qualified_deps); - auto action_plan = Dependencies::create_feature_install_plan(provider, var_provider, specs, {}, {}); + auto action_plan = + Dependencies::create_feature_install_plan(provider, var_provider, specs, {}, serialize_options); std::vector install_specs; for (auto&& install_action : action_plan.install_actions) @@ -419,7 +423,10 @@ namespace vcpkg::Commands::CI return ret; } - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet) { std::unique_ptr binaryproviderStorage; if (args.binary_caching_enabled()) @@ -496,7 +503,7 @@ namespace vcpkg::Commands::CI return FullPackageSpec{spec, std::move(default_features)}; }); - Dependencies::CreateInstallPlanOptions serialize_options; + Dependencies::CreateInstallPlanOptions serialize_options(host_triplet); struct RandomizerInstance : Graphs::Randomizer { @@ -515,8 +522,13 @@ namespace vcpkg::Commands::CI serialize_options.randomizer = &randomizer_instance; } - auto split_specs = find_unknown_ports_for_ci( - paths, exclusions_set, provider, var_provider, all_default_full_specs, binaryprovider); + auto split_specs = find_unknown_ports_for_ci(paths, + exclusions_set, + provider, + var_provider, + all_default_full_specs, + binaryprovider, + serialize_options); auto& action_plan = split_specs->plan; @@ -599,8 +611,9 @@ namespace vcpkg::Commands::CI void CICommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const + Triplet default_triplet, + Triplet host_triplet) const { - CI::perform_and_exit(args, paths, default_triplet); + CI::perform_and_exit(args, paths, default_triplet, host_triplet); } } diff --git a/src/vcpkg/commands.dependinfo.cpp b/src/vcpkg/commands.dependinfo.cpp index bfd719df08..bade947902 100644 --- a/src/vcpkg/commands.dependinfo.cpp +++ b/src/vcpkg/commands.dependinfo.cpp @@ -237,7 +237,10 @@ namespace vcpkg::Commands::DependInfo nullptr, }; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet) { const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); const int max_depth = get_max_depth(options); @@ -261,7 +264,8 @@ namespace vcpkg::Commands::DependInfo // By passing an empty status_db, we should get a plan containing all dependencies. // All actions in the plan should be install actions, as there's no installed packages to remove. StatusParagraphs status_db; - auto action_plan = Dependencies::create_feature_install_plan(provider, var_provider, specs, status_db); + auto action_plan = + Dependencies::create_feature_install_plan(provider, var_provider, specs, status_db, {host_triplet}); Checks::check_exit( VCPKG_LINE_INFO, action_plan.remove_actions.empty(), "Only install actions should exist in the plan"); std::vector install_actions = @@ -332,8 +336,9 @@ namespace vcpkg::Commands::DependInfo void DependInfoCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const + Triplet default_triplet, + Triplet host_triplet) const { - DependInfo::perform_and_exit(args, paths, default_triplet); + DependInfo::perform_and_exit(args, paths, default_triplet, host_triplet); } } diff --git a/src/vcpkg/commands.env.cpp b/src/vcpkg/commands.env.cpp index f129f02626..cc92bcea13 100644 --- a/src/vcpkg/commands.env.cpp +++ b/src/vcpkg/commands.env.cpp @@ -33,7 +33,10 @@ namespace vcpkg::Commands::Env }; // This command should probably optionally take a port - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet triplet) + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet triplet, + Triplet /*host_triplet*/) { const auto& fs = paths.get_filesystem(); @@ -115,8 +118,9 @@ namespace vcpkg::Commands::Env void EnvCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const + Triplet default_triplet, + Triplet host_triplet) const { - Env::perform_and_exit(args, paths, default_triplet); + Env::perform_and_exit(args, paths, default_triplet, host_triplet); } } diff --git a/src/vcpkg/commands.setinstalled.cpp b/src/vcpkg/commands.setinstalled.cpp index 28eee6992a..5b24d52a06 100644 --- a/src/vcpkg/commands.setinstalled.cpp +++ b/src/vcpkg/commands.setinstalled.cpp @@ -117,7 +117,10 @@ namespace vcpkg::Commands::SetInstalled Checks::exit_success(VCPKG_LINE_INFO); } - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet) { // input sanitization const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); @@ -150,7 +153,7 @@ namespace vcpkg::Commands::SetInstalled // We have a set of user-requested specs. // We need to know all the specs which are required to fulfill dependencies for those specs. // Therefore, we see what we would install into an empty installed tree, so we can use the existing code. - auto action_plan = Dependencies::create_feature_install_plan(provider, *cmake_vars, specs, {}); + auto action_plan = Dependencies::create_feature_install_plan(provider, *cmake_vars, specs, {}, {host_triplet}); for (auto&& action : action_plan.install_actions) { @@ -169,8 +172,9 @@ namespace vcpkg::Commands::SetInstalled void SetInstalledCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const + Triplet default_triplet, + Triplet host_triplet) const { - SetInstalled::perform_and_exit(args, paths, default_triplet); + SetInstalled::perform_and_exit(args, paths, default_triplet, host_triplet); } } diff --git a/src/vcpkg/commands.upgrade.cpp b/src/vcpkg/commands.upgrade.cpp index 2d25be4550..535f1f5057 100644 --- a/src/vcpkg/commands.upgrade.cpp +++ b/src/vcpkg/commands.upgrade.cpp @@ -36,7 +36,10 @@ namespace vcpkg::Commands::Upgrade nullptr, }; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet) { const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); @@ -78,7 +81,8 @@ namespace vcpkg::Commands::Upgrade provider, var_provider, Util::fmap(outdated_packages, [](const Update::OutdatedPackage& package) { return package.spec; }), - status_db); + status_db, + {host_triplet}); } else { @@ -158,7 +162,8 @@ namespace vcpkg::Commands::Upgrade if (to_upgrade.empty()) Checks::exit_success(VCPKG_LINE_INFO); - action_plan = Dependencies::create_upgrade_plan(provider, var_provider, to_upgrade, status_db); + action_plan = + Dependencies::create_upgrade_plan(provider, var_provider, to_upgrade, status_db, {host_triplet}); } Checks::check_exit(VCPKG_LINE_INFO, !action_plan.empty()); @@ -203,8 +208,9 @@ namespace vcpkg::Commands::Upgrade void UpgradeCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const + Triplet default_triplet, + Triplet host_triplet) const { - Upgrade::perform_and_exit(args, paths, default_triplet); + Upgrade::perform_and_exit(args, paths, default_triplet, host_triplet); } } diff --git a/src/vcpkg/dependencies.cpp b/src/vcpkg/dependencies.cpp index f52b4b7095..3d33816ca5 100644 --- a/src/vcpkg/dependencies.cpp +++ b/src/vcpkg/dependencies.cpp @@ -16,6 +16,8 @@ using namespace vcpkg; namespace vcpkg::Dependencies { + struct ClusterGraph; + namespace { struct ClusterInstalled @@ -82,7 +84,8 @@ namespace vcpkg::Dependencies // Precondition: must have called "mark_for_reinstall()" or "create_install_info()" on this cluster void add_feature(const std::string& feature, const CMakeVars::CMakeVarProvider& var_provider, - std::vector& out_new_dependencies) + std::vector& out_new_dependencies, + Triplet host_triplet) { ClusterInstallInfo& info = m_install_info.value_or_exit(VCPKG_LINE_INFO); if (feature == "default") @@ -110,7 +113,7 @@ namespace vcpkg::Dependencies if (auto vars = maybe_vars.get()) { // Qualified dependency resolution is available - auto fullspec_list = filter_dependencies(*qualified_deps, m_spec.triplet(), *vars); + auto fullspec_list = filter_dependencies(*qualified_deps, m_spec.triplet(), host_triplet, *vars); for (auto&& fspec : fullspec_list) { @@ -127,8 +130,9 @@ namespace vcpkg::Dependencies { if (dep.platform.is_empty()) { + auto t = dep.host ? host_triplet : m_spec.triplet(); Util::Vectors::append(&dep_list, - FullPackageSpec({dep.name, m_spec.triplet()}, dep.features) + FullPackageSpec({dep.name, t}, dep.features) .to_feature_specs({"default"}, {"default"})); } else @@ -137,11 +141,17 @@ namespace vcpkg::Dependencies } } Util::sort_unique_erase(dep_list); - if (!requires_qualified_resolution) + if (requires_qualified_resolution) + { + auto my_spec = this->m_spec; + Util::erase_remove_if(dep_list, [my_spec](FeatureSpec& f) { return f.spec() == my_spec; }); + } + else { info.build_edges.emplace(feature, dep_list); } } + Util::Vectors::append(&out_new_dependencies, dep_list); } @@ -223,14 +233,15 @@ namespace vcpkg::Dependencies { PackageGraph(const PortFileProvider::PortFileProvider& provider, const CMakeVars::CMakeVarProvider& var_provider, - const StatusParagraphs& status_db); + const StatusParagraphs& status_db, + Triplet host_triplet); ~PackageGraph(); void install(Span specs); void upgrade(Span specs); void mark_user_requested(const PackageSpec& spec); - ActionPlan serialize(const CreateInstallPlanOptions& options = {}) const; + ActionPlan serialize(Graphs::Randomizer* randomizer) const; void mark_for_reinstall(const PackageSpec& spec, std::vector& out_reinstall_requirements); const CMakeVars::CMakeVarProvider& m_var_provider; @@ -243,9 +254,10 @@ namespace vcpkg::Dependencies /// /// Directional graph representing a collection of packages with their features connected by their dependencies. /// - struct ClusterGraph : Util::MoveOnlyBase + struct ClusterGraph : Util::ResourceBase { - explicit ClusterGraph(const PortFileProvider::PortFileProvider& port_provider) : m_port_provider(port_provider) + explicit ClusterGraph(const PortFileProvider::PortFileProvider& port_provider, Triplet host_triplet) + : m_port_provider(port_provider), m_host_triplet(host_triplet) { } @@ -261,45 +273,48 @@ namespace vcpkg::Dependencies { const SourceControlFileLocation* scfl = m_port_provider.get_control_file(spec.name()).get(); - Checks::check_maybe_upgrade( - VCPKG_LINE_INFO, scfl, "Error: Cannot find definition for package `%s`.", spec.name()); + Checks::check_exit(VCPKG_LINE_INFO, + scfl, + "Error: Cannot find definition for package `%s` while getting `%s`.", + spec.name(), + spec); - return m_graph - .emplace(std::piecewise_construct, std::forward_as_tuple(spec), std::forward_as_tuple(spec, *scfl)) - .first->second; + it = m_graph + .emplace( + std::piecewise_construct, std::forward_as_tuple(spec), std::forward_as_tuple(spec, *scfl)) + .first; } return it->second; } - Cluster& get(const InstalledPackageView& ipv) + Cluster& insert(const InstalledPackageView& ipv) { - auto it = m_graph.find(ipv.spec()); - - if (it == m_graph.end()) - { - ExpectedS maybe_scfl = - m_port_provider.get_control_file(ipv.spec().name()); + ExpectedS maybe_scfl = + m_port_provider.get_control_file(ipv.spec().name()); - return m_graph - .emplace(std::piecewise_construct, - std::forward_as_tuple(ipv.spec()), - std::forward_as_tuple(ipv, std::move(maybe_scfl))) - .first->second; - } - - if (!it->second.m_installed) + if (maybe_scfl.has_value()) { - it->second.m_installed = {ipv}; + Checks::check_exit(VCPKG_LINE_INFO, + maybe_scfl.get()->source_control_file->core_paragraph->type.type == + ipv.core->package.type.type, + "Error: the port type of '%s' differs between the installed and available " + "portfile.\nPlease manually remove '%s' and re-run this command.", + ipv.spec().name(), + ipv.spec()); } - return it->second; + return m_graph + .emplace(std::piecewise_construct, + std::forward_as_tuple(ipv.spec()), + std::forward_as_tuple(ipv, std::move(maybe_scfl))) + .first->second; } const Cluster& find_or_exit(const PackageSpec& spec, LineInfo linfo) const { auto it = m_graph.find(spec); - Checks::check_maybe_upgrade(linfo, it != m_graph.end(), "Failed to locate spec in graph"); + Checks::check_exit(linfo, it != m_graph.end(), "Failed to locate spec in graph: %s", spec); return it->second; } @@ -309,6 +324,9 @@ namespace vcpkg::Dependencies private: std::map m_graph; const PortFileProvider::PortFileProvider& m_port_provider; + + public: + const Triplet m_host_triplet; }; static std::string to_output_string(RequestType request_type, @@ -370,6 +388,7 @@ namespace vcpkg::Dependencies InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const SourceControlFileLocation& scfl, const RequestType& request_type, + Triplet host_triplet, std::map>&& dependencies) : spec(spec) , source_control_file_location(scfl) @@ -377,6 +396,7 @@ namespace vcpkg::Dependencies , request_type(request_type) , build_options{} , feature_dependencies(std::move(dependencies)) + , host_triplet(host_triplet) { for (const auto& kv : feature_dependencies) { @@ -626,11 +646,12 @@ namespace vcpkg::Dependencies // `features` should have "default" instead of missing "core" std::vector resolve_deps_as_top_level(const SourceControlFile& scf, Triplet triplet, + Triplet host_triplet, std::vector features, CMakeVars::CMakeVarProvider& var_provider) { PackageSpec spec{scf.core_paragraph->name, triplet}; - std::map> specs_to_features; + std::map> specs_to_features; Optional ctx_storage = var_provider.get_dep_info_vars(spec); auto ctx = [&]() -> const PlatformExpression::Context& { @@ -650,7 +671,10 @@ namespace vcpkg::Dependencies if (dep.name == spec.name()) Util::Vectors::append(&features, dep.features); else - Util::Vectors::append(&specs_to_features[dep.name], dep.features); + { + auto t = dep.host ? host_triplet : triplet; + Util::Vectors::append(&specs_to_features[{dep.name, t}], dep.features); + } } } }; @@ -682,8 +706,8 @@ namespace vcpkg::Dependencies if (it != scf.feature_paragraphs.end()) handle_deps(it->get()->dependencies); } } - return Util::fmap(specs_to_features, [triplet](std::pair>& p) { - return FullPackageSpec({p.first, triplet}, Util::sort_unique_erase(std::move(p.second))); + return Util::fmap(specs_to_features, [](std::pair>& p) { + return FullPackageSpec(p.first, Util::sort_unique_erase(std::move(p.second))); }); } @@ -693,7 +717,7 @@ namespace vcpkg::Dependencies const StatusParagraphs& status_db, const CreateInstallPlanOptions& options) { - PackageGraph pgraph(port_provider, var_provider, status_db); + PackageGraph pgraph(port_provider, var_provider, status_db, options.host_triplet); std::vector feature_specs; for (const FullPackageSpec& spec : specs) @@ -725,7 +749,7 @@ namespace vcpkg::Dependencies } pgraph.install(feature_specs); - auto res = pgraph.serialize(options); + auto res = pgraph.serialize(options.randomizer); return res; } @@ -775,6 +799,7 @@ namespace vcpkg::Dependencies // Get the cluster for the PackageSpec of the FeatureSpec we are adding to the install graph Cluster& clust = m_graph->get(spec.spec()); + spec = FeatureSpec{clust.m_spec, spec.feature()}; // If this spec hasn't already had its qualified dependencies resolved if (!m_var_provider.get_dep_info_vars(spec.spec()).has_value()) @@ -812,14 +837,14 @@ namespace vcpkg::Dependencies if (clust.m_install_info.has_value()) { - clust.add_feature(spec.feature(), m_var_provider, next_dependencies); + clust.add_feature(spec.feature(), m_var_provider, next_dependencies, m_graph->m_host_triplet); } else { if (!clust.m_installed.has_value()) { clust.create_install_info(next_dependencies); - clust.add_feature(spec.feature(), m_var_provider, next_dependencies); + clust.add_feature(spec.feature(), m_var_provider, next_dependencies, m_graph->m_host_triplet); } else { @@ -840,7 +865,8 @@ namespace vcpkg::Dependencies // which hasn't already been installed to this cluster. In this case, we need to reinstall // the port if the feature isn't already present. mark_for_reinstall(spec.spec(), next_dependencies); - clust.add_feature(spec.feature(), m_var_provider, next_dependencies); + clust.add_feature( + spec.feature(), m_var_provider, next_dependencies, m_graph->m_host_triplet); } } } @@ -885,14 +911,14 @@ namespace vcpkg::Dependencies const StatusParagraphs& status_db, const CreateInstallPlanOptions& options) { - PackageGraph pgraph(port_provider, var_provider, status_db); + PackageGraph pgraph(port_provider, var_provider, status_db, options.host_triplet); pgraph.upgrade(specs); - return pgraph.serialize(options); + return pgraph.serialize(options.randomizer); } - ActionPlan PackageGraph::serialize(const CreateInstallPlanOptions& options) const + ActionPlan PackageGraph::serialize(Graphs::Randomizer* randomizer) const { struct BaseEdgeProvider : Graphs::AdjacencyProvider { @@ -952,8 +978,8 @@ namespace vcpkg::Dependencies installed_vertices.push_back(kv.first); } } - auto remove_toposort = Graphs::topological_sort(removed_vertices, removeedgeprovider, options.randomizer); - auto insert_toposort = Graphs::topological_sort(installed_vertices, installedgeprovider, options.randomizer); + auto remove_toposort = Graphs::topological_sort(removed_vertices, removeedgeprovider, randomizer); + auto insert_toposort = Graphs::topological_sort(installed_vertices, installedgeprovider, randomizer); ActionPlan plan; @@ -995,6 +1021,7 @@ namespace vcpkg::Dependencies plan.install_actions.emplace_back(p_cluster->m_spec, p_cluster->get_scfl_or_exit(), p_cluster->request_type, + m_graph->m_host_triplet, std::move(computed_edges)); } else if (p_cluster->request_type == RequestType::USER_REQUESTED && p_cluster->m_installed.has_value()) @@ -1008,15 +1035,17 @@ namespace vcpkg::Dependencies } static std::unique_ptr create_feature_install_graph( - const PortFileProvider::PortFileProvider& port_provider, const StatusParagraphs& status_db) + const PortFileProvider::PortFileProvider& port_provider, + const StatusParagraphs& status_db, + Triplet host_triplet) { - std::unique_ptr graph = std::make_unique(port_provider); + std::unique_ptr graph = std::make_unique(port_provider, host_triplet); auto installed_ports = get_installed_ports(status_db); for (auto&& ipv : installed_ports) { - graph->get(ipv); + graph->insert(ipv); } // Populate the graph with "remove edges", which are the reverse of the Build-Depends edges. @@ -1041,8 +1070,9 @@ namespace vcpkg::Dependencies PackageGraph::PackageGraph(const PortFileProvider::PortFileProvider& port_provider, const CMakeVars::CMakeVarProvider& var_provider, - const StatusParagraphs& status_db) - : m_var_provider(var_provider), m_graph(create_feature_install_graph(port_provider, status_db)) + const StatusParagraphs& status_db, + Triplet host_triplet) + : m_var_provider(var_provider), m_graph(create_feature_install_graph(port_provider, status_db, host_triplet)) { } @@ -1178,11 +1208,13 @@ namespace vcpkg::Dependencies VersionedPackageGraph(const IVersionedPortfileProvider& ver_provider, const IBaselineProvider& base_provider, const PortFileProvider::IOverlayProvider& oprovider, - const CMakeVars::CMakeVarProvider& var_provider) + const CMakeVars::CMakeVarProvider& var_provider, + Triplet host_triplet) : m_ver_provider(ver_provider) , m_base_provider(base_provider) , m_o_provider(oprovider) , m_var_provider(var_provider) + , m_host_triplet(host_triplet) { } @@ -1197,6 +1229,7 @@ namespace vcpkg::Dependencies const IBaselineProvider& m_base_provider; const PortFileProvider::IOverlayProvider& m_o_provider; const CMakeVars::CMakeVarProvider& m_var_provider; + const Triplet m_host_triplet; struct DepSpec { @@ -1417,7 +1450,7 @@ namespace vcpkg::Dependencies for (auto&& dep : *deps.get()) { - PackageSpec dep_spec(dep.name, ref.first.triplet()); + PackageSpec dep_spec(dep.name, dep.host ? m_host_triplet : ref.first.triplet()); if (!dep.platform.is_empty()) { @@ -1435,7 +1468,6 @@ namespace vcpkg::Dependencies } auto& dep_node = emplace_package(dep_spec); - // Todo: cycle detection add_constraint(dep_node, dep, ref.first.name()); p.first->second.emplace_back(dep_spec, "core"); @@ -1624,9 +1656,11 @@ namespace vcpkg::Dependencies void VersionedPackageGraph::add_roots(View deps, const PackageSpec& toplevel) { - auto specs = Util::fmap(deps, [&toplevel](const Dependency& d) { - return PackageSpec{d.name, toplevel.triplet()}; - }); + auto dep_to_spec = [&toplevel, this](const Dependency& d) { + return PackageSpec{d.name, d.host ? m_host_triplet : toplevel.triplet()}; + }; + auto specs = Util::fmap(deps, dep_to_spec); + specs.push_back(toplevel); Util::sort_unique_erase(specs); m_var_provider.load_dep_info_vars(specs); @@ -1635,7 +1669,6 @@ namespace vcpkg::Dependencies for (auto&& dep : deps) { - PackageSpec spec(dep.name, toplevel.triplet()); if (!dep.platform.evaluate(vars)) continue; active_deps.push_back(&dep); @@ -1644,7 +1677,7 @@ namespace vcpkg::Dependencies // Note: x[core], x[y] will still eventually depend on defaults due to the second x[y] if (Util::find(dep.features, "core") != dep.features.end()) { - auto& node = emplace_package(spec); + auto& node = emplace_package(dep_to_spec(dep)); node.second.default_features = false; } } @@ -1652,7 +1685,7 @@ namespace vcpkg::Dependencies for (auto pdep : active_deps) { const auto& dep = *pdep; - PackageSpec spec(dep.name, toplevel.triplet()); + auto spec = dep_to_spec(dep); auto& node = emplace_package(spec); @@ -1795,7 +1828,8 @@ namespace vcpkg::Dependencies // -> Add stack frame auto maybe_vars = m_var_provider.get_dep_info_vars(spec); - InstallPlanAction ipa(spec, *p_vnode->scfl, RequestType::USER_REQUESTED, std::move(p_vnode->deps)); + InstallPlanAction ipa( + spec, *p_vnode->scfl, RequestType::USER_REQUESTED, m_host_triplet, std::move(p_vnode->deps)); std::vector deps; for (auto&& f : ipa.feature_list) { @@ -1804,7 +1838,8 @@ namespace vcpkg::Dependencies { for (auto&& dep : *maybe_deps) { - if (dep.name == spec.name()) continue; + PackageSpec dep_spec(dep.name, dep.host ? m_host_triplet : spec.triplet()); + if (dep_spec == spec) continue; if (!dep.platform.is_empty() && !dep.platform.evaluate(maybe_vars.value_or_exit(VCPKG_LINE_INFO))) @@ -1815,7 +1850,7 @@ namespace vcpkg::Dependencies if (auto cons = maybe_cons.get()) { - deps.emplace_back(DepSpec{{dep.name, spec.triplet()}, std::move(*cons)}); + deps.emplace_back(DepSpec{std::move(dep_spec), std::move(*cons)}); } else { @@ -1890,9 +1925,10 @@ namespace vcpkg::Dependencies const CMakeVars::CMakeVarProvider& var_provider, const std::vector& deps, const std::vector& overrides, - const PackageSpec& toplevel) + const PackageSpec& toplevel, + Triplet host_triplet) { - VersionedPackageGraph vpg(provider, bprovider, oprovider, var_provider); + VersionedPackageGraph vpg(provider, bprovider, oprovider, var_provider, host_triplet); for (auto&& o : overrides) vpg.add_override(o.name, {o.version, o.port_version}); vpg.add_roots(deps, toplevel); diff --git a/src/vcpkg/export.chocolatey.cpp b/src/vcpkg/export.chocolatey.cpp index 875982ed67..ba535526d5 100644 --- a/src/vcpkg/export.chocolatey.cpp +++ b/src/vcpkg/export.chocolatey.cpp @@ -14,20 +14,19 @@ namespace vcpkg::Export::Chocolatey using Install::InstallDir; static std::string create_nuspec_dependencies(const BinaryParagraph& binary_paragraph, - const std::map& packages_version) + const std::map& packages_version) { static constexpr auto CONTENT_TEMPLATE = R"()"; std::string nuspec_dependencies; - for (const std::string& depend : binary_paragraph.dependencies) + for (const auto& depend : binary_paragraph.dependencies) { auto found = packages_version.find(depend); if (found == packages_version.end()) { Checks::exit_with_message(VCPKG_LINE_INFO, "Cannot find desired dependency version."); } - - std::string nuspec_dependency = Strings::replace_all(CONTENT_TEMPLATE, "@PACKAGE_ID@", depend); + std::string nuspec_dependency = Strings::replace_all(CONTENT_TEMPLATE, "@PACKAGE_ID@", depend.name()); Strings::inplace_replace_all(nuspec_dependency, "@PACKAGE_VERSION@", found->second); nuspec_dependencies += nuspec_dependency; } @@ -36,7 +35,7 @@ namespace vcpkg::Export::Chocolatey static std::string create_nuspec_file_contents(const std::string& exported_root_dir, const BinaryParagraph& binary_paragraph, - const std::map& packages_version, + const std::map& packages_version, const Options& chocolatey_options) { static constexpr auto CONTENT_TEMPLATE = R"( @@ -58,7 +57,7 @@ namespace vcpkg::Export::Chocolatey )"; - auto package_version = packages_version.find(binary_paragraph.spec.name()); + auto package_version = packages_version.find(binary_paragraph.spec); if (package_version == packages_version.end()) { Checks::exit_with_message(VCPKG_LINE_INFO, "Cannot find desired package version."); @@ -168,7 +167,7 @@ if (Test-Path $installedDir) fs.create_directory(exported_dir_path, ec); // execute the plan - std::map packages_version; + std::map packages_version; for (const ExportPlanAction& action : export_plan) { if (action.plan_type != ExportPlanType::ALREADY_BUILT) @@ -183,7 +182,7 @@ if (Test-Path $installedDir) Strings::inplace_replace_all(norm_version, '-', '.'); Strings::inplace_replace_all(norm_version, '_', '.'); norm_version += chocolatey_options.maybe_version_suffix.value_or(""); - packages_version.insert(std::make_pair(binary_paragraph.spec.name(), norm_version)); + packages_version.emplace(binary_paragraph.spec, norm_version); } for (const ExportPlanAction& action : export_plan) diff --git a/src/vcpkg/export.cpp b/src/vcpkg/export.cpp index 1f202a9d54..fd882cb47e 100644 --- a/src/vcpkg/export.cpp +++ b/src/vcpkg/export.cpp @@ -700,7 +700,8 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console void ExportCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const + Triplet default_triplet, + Triplet /*host_triplet*/) const { Export::perform_and_exit(args, paths, default_triplet); } diff --git a/src/vcpkg/export.ifw.cpp b/src/vcpkg/export.ifw.cpp index 74b06f5244..3093569794 100644 --- a/src/vcpkg/export.ifw.cpp +++ b/src/vcpkg/export.ifw.cpp @@ -94,7 +94,7 @@ namespace vcpkg::Export::IFW fs::generic_u8string(package_xml_file_path)); auto deps = Strings::join( - ",", binary_paragraph.dependencies, [](const std::string& dep) { return "packages." + dep + ":"; }); + ",", binary_paragraph.dependencies, [](const auto& dep) { return "packages." + dep.name() + ":"; }); if (!deps.empty()) deps = "\n " + deps + ""; diff --git a/src/vcpkg/install.cpp b/src/vcpkg/install.cpp index 5c62af4ede..2213e992f0 100644 --- a/src/vcpkg/install.cpp +++ b/src/vcpkg/install.cpp @@ -758,7 +758,10 @@ namespace vcpkg::Install /// Run "install" command. /// /// - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet host_triplet) { // input sanitization const ParsedArguments options = @@ -903,7 +906,8 @@ namespace vcpkg::Install var_provider, dependencies, manifest_scf.core_paragraph->overrides, - {manifest_scf.core_paragraph->name, default_triplet}) + {manifest_scf.core_paragraph->name, default_triplet}, + host_triplet) .value_or_exit(VCPKG_LINE_INFO); for (InstallPlanAction& action : install_plan.install_actions) @@ -938,7 +942,8 @@ namespace vcpkg::Install StatusParagraphs status_db = database_load_check(paths); // Note: action_plan will hold raw pointers to SourceControlFileLocations from this map - auto action_plan = Dependencies::create_feature_install_plan(provider, var_provider, specs, status_db); + auto action_plan = + Dependencies::create_feature_install_plan(provider, var_provider, specs, status_db, {host_triplet}); for (auto&& action : action_plan.install_actions) { @@ -1065,9 +1070,10 @@ namespace vcpkg::Install void InstallCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, - Triplet default_triplet) const + Triplet default_triplet, + Triplet host_triplet) const { - Install::perform_and_exit(args, paths, default_triplet); + Install::perform_and_exit(args, paths, default_triplet, host_triplet); } SpecSummary::SpecSummary(const PackageSpec& spec, const Dependencies::InstallPlanAction* action) diff --git a/src/vcpkg/remove.cpp b/src/vcpkg/remove.cpp index e29ae16c8f..b82f6cabd0 100644 --- a/src/vcpkg/remove.cpp +++ b/src/vcpkg/remove.cpp @@ -214,9 +214,7 @@ namespace vcpkg::Remove &valid_arguments, }; - void RemoveCommand::perform_and_exit(const VcpkgCmdArguments& args, - const VcpkgPaths& paths, - Triplet default_triplet) const + static void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet) { if (paths.manifest_mode_enabled()) { @@ -334,4 +332,12 @@ namespace vcpkg::Remove Checks::exit_success(VCPKG_LINE_INFO); } + + void RemoveCommand::perform_and_exit(const VcpkgCmdArguments& args, + const VcpkgPaths& paths, + Triplet default_triplet, + Triplet /*host_triplet*/) const + { + Remove::perform_and_exit(args, paths, default_triplet); + } } diff --git a/src/vcpkg/sourceparagraph.cpp b/src/vcpkg/sourceparagraph.cpp index 52f72da943..b63f524182 100644 --- a/src/vcpkg/sourceparagraph.cpp +++ b/src/vcpkg/sourceparagraph.cpp @@ -427,6 +427,7 @@ namespace vcpkg virtual StringView type_name() const override { return "a dependency"; } constexpr static StringLiteral NAME = "name"; + constexpr static StringLiteral HOST = "host"; constexpr static StringLiteral FEATURES = "features"; constexpr static StringLiteral DEFAULT_FEATURES = "default-features"; constexpr static StringLiteral PLATFORM = "platform"; @@ -436,6 +437,7 @@ namespace vcpkg { static const StringView t[] = { NAME, + HOST, FEATURES, DEFAULT_FEATURES, PLATFORM, @@ -481,6 +483,7 @@ namespace vcpkg { dep.features.push_back("core"); } + r.optional_object_field(obj, HOST, dep.host, Json::BooleanDeserializer::instance); r.optional_object_field(obj, PLATFORM, dep.platform, PlatformExprDeserializer::instance); @@ -917,7 +920,6 @@ namespace vcpkg control_file->core_paragraph = std::make_unique(); auto& spgh = control_file->core_paragraph; - spgh->type = Type{Type::PORT}; for (const auto& el : obj) { @@ -1188,7 +1190,8 @@ namespace vcpkg } std::vector filter_dependencies(const std::vector& deps, - Triplet t, + Triplet target, + Triplet host, const std::unordered_map& cmake_vars) { std::vector ret; @@ -1196,6 +1199,7 @@ namespace vcpkg { if (dep.platform.evaluate(cmake_vars)) { + Triplet t = dep.host ? host : target; ret.emplace_back(FullPackageSpec({dep.name, t}, dep.features)); } } @@ -1205,7 +1209,7 @@ namespace vcpkg static bool is_dependency_trivial(const Dependency& dep) { return dep.features.empty() && dep.platform.is_empty() && dep.extra_info.is_empty() && - dep.constraint.type == Versions::Constraint::Type::None; + dep.constraint.type == Versions::Constraint::Type::None && !dep.host; } static Json::Object serialize_manifest_impl(const SourceControlFile& scf, bool debug) @@ -1265,6 +1269,7 @@ namespace vcpkg } dep_obj.insert(DependencyDeserializer::NAME, Json::Value::string(dep.name)); + if (dep.host) dep_obj.insert(DependencyDeserializer::HOST, Json::Value::boolean(true)); auto features_copy = dep.features; auto core_it = std::find(features_copy.begin(), features_copy.end(), "core"); @@ -1375,11 +1380,6 @@ namespace vcpkg } } - if (debug) - { - obj.insert("TYPE", Json::Value::string(Type::to_string(scf.core_paragraph->type))); - } - return obj; } diff --git a/src/vcpkg/statusparagraph.cpp b/src/vcpkg/statusparagraph.cpp index ff3700d4b6..cc2d693337 100644 --- a/src/vcpkg/statusparagraph.cpp +++ b/src/vcpkg/statusparagraph.cpp @@ -88,7 +88,7 @@ namespace vcpkg std::map> InstalledPackageView::feature_dependencies() const { - auto extract_deps = [&](const std::string& name) { return FeatureSpec{{name, spec().triplet()}, "core"}; }; + auto extract_deps = [&](const PackageSpec& spec) { return FeatureSpec{spec, "core"}; }; std::map> deps; @@ -104,7 +104,7 @@ namespace vcpkg { // accumulate all features in installed dependencies // Todo: make this unneeded by collapsing all package dependencies into the core package - std::vector deps; + std::vector deps; for (auto&& feature : features) for (auto&& dep : feature->package.dependencies) deps.push_back(dep); @@ -113,9 +113,10 @@ namespace vcpkg for (auto&& dep : core->package.dependencies) deps.push_back(dep); - Util::erase_remove_if(deps, [&](const std::string& pspec) { return pspec == spec().name(); }); + auto this_spec = this->spec(); + Util::erase_remove_if(deps, [this_spec](const PackageSpec& pspec) { return pspec == this_spec; }); Util::sort_unique_erase(deps); - return PackageSpec::to_package_specs(deps, spec().triplet()); + return deps; } } diff --git a/src/vcpkg/triplet.cpp b/src/vcpkg/triplet.cpp index 9943ec9a8e..24a1f813af 100644 --- a/src/vcpkg/triplet.cpp +++ b/src/vcpkg/triplet.cpp @@ -73,38 +73,61 @@ namespace vcpkg return nullopt; } - Triplet default_triplet(const VcpkgCmdArguments& args) + static Triplet system_triplet() { - if (args.triplet != nullptr) +#if defined(_WIN32) + auto host_proc = System::get_host_processor(); + switch (host_proc) { - return Triplet::from_canonical_name(std::string(*args.triplet)); + case System::CPUArchitecture::X86: return Triplet::from_canonical_name("x86-windows"); + case System::CPUArchitecture::X64: return Triplet::from_canonical_name("x64-windows"); + case System::CPUArchitecture::ARM: return Triplet::from_canonical_name("arm-windows"); + case System::CPUArchitecture::ARM64: return Triplet::from_canonical_name("arm64-windows"); + default: return Triplet::from_canonical_name("x86-windows"); } - else - { -#if defined(_WIN32) - return Triplet::from_canonical_name("x86-windows"); #elif defined(__APPLE__) - return Triplet::from_canonical_name("x64-osx"); + return Triplet::from_canonical_name("x64-osx"); #elif defined(__FreeBSD__) - return Triplet::from_canonical_name("x64-freebsd"); + return Triplet::from_canonical_name("x64-freebsd"); #elif defined(__OpenBSD__) - return Triplet::from_canonical_name("x64-openbsd"); + return Triplet::from_canonical_name("x64-openbsd"); #elif defined(__GLIBC__) #if defined(__aarch64__) - return Triplet::from_canonical_name("arm64-linux"); + return Triplet::from_canonical_name("arm64-linux"); #elif defined(__arm__) - return Triplet::from_canonical_name("arm-linux"); + return Triplet::from_canonical_name("arm-linux"); #elif defined(__s390x__) - return Triplet::from_canonical_name("s390x-linux"); + return Triplet::from_canonical_name("s390x-linux"); #elif (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) && \ defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) - return Triplet::from_canonical_name("ppc64le-linux"); + return Triplet::from_canonical_name("ppc64le-linux"); #else - return Triplet::from_canonical_name("x64-linux"); + return Triplet::from_canonical_name("x64-linux"); #endif #else - return Triplet::from_canonical_name("x64-linux-musl"); + return Triplet::from_canonical_name("x64-linux-musl"); #endif + } + + Triplet default_triplet(const VcpkgCmdArguments& args) + { + if (args.triplet != nullptr) + { + return Triplet::from_canonical_name(std::string(*args.triplet)); + } +#if defined(_WIN32) + return Triplet::from_canonical_name("x86-windows"); +#else + return system_triplet(); +#endif + } + + Triplet default_host_triplet(const VcpkgCmdArguments& args) + { + if (args.host_triplet != nullptr) + { + return Triplet::from_canonical_name(std::string(*args.host_triplet)); } + return system_triplet(); } } diff --git a/src/vcpkg/vcpkgcmdarguments.cpp b/src/vcpkg/vcpkgcmdarguments.cpp index 6ac05e5380..b704f1ab4f 100644 --- a/src/vcpkg/vcpkgcmdarguments.cpp +++ b/src/vcpkg/vcpkgcmdarguments.cpp @@ -270,6 +270,7 @@ namespace vcpkg cojoined_values[] = { {VCPKG_ROOT_DIR_ARG, &VcpkgCmdArguments::vcpkg_root_dir}, {TRIPLET_ARG, &VcpkgCmdArguments::triplet}, + {HOST_TRIPLET_ARG, &VcpkgCmdArguments::host_triplet}, {MANIFEST_ROOT_DIR_ARG, &VcpkgCmdArguments::manifest_root_dir}, {BUILDTREES_ROOT_DIR_ARG, &VcpkgCmdArguments::buildtrees_root_dir}, {DOWNLOADS_ROOT_DIR_ARG, &VcpkgCmdArguments::downloads_root_dir}, @@ -613,6 +614,9 @@ namespace vcpkg table.format(opt(TRIPLET_ARG, "=", ""), "Specify the target architecture triplet. See 'vcpkg help triplet'"); table.format("", "(default: " + format_environment_variable("VCPKG_DEFAULT_TRIPLET") + ')'); + table.format(opt(HOST_TRIPLET_ARG, "=", ""), + "Specify the host architecture triplet. See 'vcpkg help triplet'"); + table.format("", "(default: " + format_environment_variable("VCPKG_DEFAULT_HOST_TRIPLET") + ')'); table.format(opt(OVERLAY_PORTS_ARG, "=", ""), "Specify directories to be used when searching for ports"); table.format("", "(also: " + format_environment_variable("VCPKG_OVERLAY_PORTS") + ')'); table.format(opt(OVERLAY_TRIPLETS_ARG, "=", ""), "Specify directories containing triplets files"); @@ -658,6 +662,7 @@ namespace vcpkg } from_env(TRIPLET_ENV, triplet); + from_env(HOST_TRIPLET_ENV, host_triplet); from_env(VCPKG_ROOT_DIR_ENV, vcpkg_root_dir); from_env(DOWNLOADS_ROOT_DIR_ENV, downloads_root_dir); from_env(DEFAULT_VISUAL_STUDIO_PATH_ENV, default_visual_studio_path); @@ -925,6 +930,8 @@ namespace vcpkg constexpr StringLiteral VcpkgCmdArguments::TRIPLET_ENV; constexpr StringLiteral VcpkgCmdArguments::TRIPLET_ARG; + constexpr StringLiteral VcpkgCmdArguments::HOST_TRIPLET_ENV; + constexpr StringLiteral VcpkgCmdArguments::HOST_TRIPLET_ARG; constexpr StringLiteral VcpkgCmdArguments::OVERLAY_PORTS_ENV; constexpr StringLiteral VcpkgCmdArguments::OVERLAY_PORTS_ARG; constexpr StringLiteral VcpkgCmdArguments::OVERLAY_TRIPLETS_ENV;