diff --git a/src/Build.UnitTests/Evaluation/SdkResultEvaluation_Tests.cs b/src/Build.UnitTests/Evaluation/SdkResultEvaluation_Tests.cs index 9632dce86b3..a459c5339ef 100644 --- a/src/Build.UnitTests/Evaluation/SdkResultEvaluation_Tests.cs +++ b/src/Build.UnitTests/Evaluation/SdkResultEvaluation_Tests.cs @@ -549,6 +549,121 @@ public void SdkResolverCanSetEnvVarsThatInfluenceBuild() instance.GetItems("ExecThingsAsEnvironment").ShouldHaveSingleItem().EvaluatedInclude.ShouldBe("TestEnvVarValue"); } + [Fact] + public void SdkResolverEnvironmentVariablesOverrideAmbientEnvironmentVariables() + { + string originalValue = Environment.GetEnvironmentVariable("SDK_TEST_VAR"); + try + { + // Set an ambient environment variable + Environment.SetEnvironmentVariable("SDK_TEST_VAR", "AmbientValue"); + + var projectOptions = SdkUtilities.CreateProjectOptionsWithResolver(new SdkUtilities.ConfigurableMockSdkResolver((_, _, factory) => + factory.IndicateSuccess(Path.Combine(_testFolder, "Sdk"), "1.0.0", null, null, null, environmentVariablesToAdd: new Dictionary + { + { "SDK_TEST_VAR", "SdkValue" } + }))); + + string projectContent = """ + + + $(SDK_TEST_VAR) + + + + $(SDK_TEST_VAR) + + + + """; + + string projectPath = Path.Combine(_testFolder, "project.proj"); + File.WriteAllText(projectPath, projectContent); + + string sdkPropsContents = ""; + string sdkPropsPath = Path.Combine(_testFolder, "Sdk", "Sdk.props"); + Directory.CreateDirectory(Path.Combine(_testFolder, "Sdk")); + File.WriteAllText(sdkPropsPath, sdkPropsContents); + + string sdkTargetsContents = @""; + string sdkTargetsPath = Path.Combine(_testFolder, "Sdk", "Sdk.targets"); + File.WriteAllText(sdkTargetsPath, sdkTargetsContents); + + var project = CreateProject(projectPath, projectOptions); + var instance = project.CreateProjectInstance(); + + _logger.AssertNoErrors(); + _logger.AssertNoWarnings(); + + // The SDK value should override the ambient environment variable + instance.GetPropertyValue("CapturedValue").ShouldBe("SdkValue"); + + instance.Build(["TestTarget"], [_logger], out var targetOutputs); + + instance.GetPropertyValue("ExecValue").ShouldBe("SdkValue"); + } + finally + { + Environment.SetEnvironmentVariable("SDK_TEST_VAR", originalValue); + } + } + + [Fact] + public void FirstSdkEnvironmentVariableWinsOverSubsequentSdks() + { + var projectOptions = SdkUtilities.CreateProjectOptionsWithResolver(new SdkUtilities.ConfigurableMockSdkResolver((sdkReference, _, factory) => + { + // First SDK sets the variable + if (sdkReference.Name == "FirstSdk") + { + return factory.IndicateSuccess(Path.Combine(_testFolder, "Sdk1"), "1.0.0", null, null, null, environmentVariablesToAdd: new Dictionary + { + { "SHARED_VAR", "FirstValue" } + }); + } + // Second SDK tries to set it, but should be ignored + else if (sdkReference.Name == "SecondSdk") + { + return factory.IndicateSuccess(Path.Combine(_testFolder, "Sdk2"), "1.0.0", null, null, null, environmentVariablesToAdd: new Dictionary + { + { "SHARED_VAR", "SecondValue" } + }); + } + return null; + })); + + string projectContent = """ + + + + + $(SHARED_VAR) + + + """; + + string projectPath = Path.Combine(_testFolder, "project.proj"); + File.WriteAllText(projectPath, projectContent); + + string sdk1PropsContents = ""; + string sdk1PropsPath = Path.Combine(_testFolder, "Sdk1", "Sdk.props"); + Directory.CreateDirectory(Path.Combine(_testFolder, "Sdk1")); + File.WriteAllText(sdk1PropsPath, sdk1PropsContents); + + string sdk2PropsContents = ""; + string sdk2PropsPath = Path.Combine(_testFolder, "Sdk2", "Sdk.props"); + Directory.CreateDirectory(Path.Combine(_testFolder, "Sdk2")); + File.WriteAllText(sdk2PropsPath, sdk2PropsContents); + + var project = CreateProject(projectPath, projectOptions); + + _logger.AssertNoErrors(); + _logger.AssertNoWarnings(); + + // The first SDK's value should win + project.GetPropertyValue("CapturedValue").ShouldBe("FirstValue"); + } + public void Dispose() { _env.Dispose(); diff --git a/src/Build/BackEnd/Components/SdkResolution/SdkResult.cs b/src/Build/BackEnd/Components/SdkResolution/SdkResult.cs index fab702e7df1..3643fad5edc 100644 --- a/src/Build/BackEnd/Components/SdkResolution/SdkResult.cs +++ b/src/Build/BackEnd/Components/SdkResolution/SdkResult.cs @@ -92,6 +92,7 @@ public void Translate(ITranslator translator) keyTranslator: (ITranslator t, ref string s) => t.Translate(ref s), valueTranslator: SdkResultTranslationHelpers.Translate, dictionaryCreator: count => new Dictionary(count, StringComparer.OrdinalIgnoreCase)); + translator.TranslateDictionary(ref _environmentVariablesToAdd, count => new Dictionary(count, StringComparer.OrdinalIgnoreCase)); translator.Translate(ref _sdkReference); } @@ -112,6 +113,7 @@ public override bool Equals(object obj) _additionalPaths?.Count == result._additionalPaths?.Count && _propertiesToAdd?.Count == result._propertiesToAdd?.Count && _itemsToAdd?.Count == result._propertiesToAdd?.Count && + _environmentVariablesToAdd?.Count == result._environmentVariablesToAdd?.Count && EqualityComparer.Default.Equals(_sdkReference, result._sdkReference)) { if (_additionalPaths != null) @@ -147,6 +149,17 @@ public override bool Equals(object obj) } } + if (_environmentVariablesToAdd != null) + { + foreach (var envVarToAdd in _environmentVariablesToAdd) + { + if (result._environmentVariablesToAdd[envVarToAdd.Key] != envVarToAdd.Value) + { + return false; + } + } + } + return true; } @@ -185,6 +198,14 @@ public override int GetHashCode() hashCode = (hashCode * -1521134295) + itemToAdd.Value.GetHashCode(); } } + if (_environmentVariablesToAdd != null) + { + foreach (var envVarToAdd in _environmentVariablesToAdd) + { + hashCode = (hashCode * -1521134295) + envVarToAdd.Key.GetHashCode(); + hashCode = (hashCode * -1521134295) + envVarToAdd.Value.GetHashCode(); + } + } return hashCode; } diff --git a/src/Build/Definition/Project.cs b/src/Build/Definition/Project.cs index 4638632614c..91cff85c433 100644 --- a/src/Build/Definition/Project.cs +++ b/src/Build/Definition/Project.cs @@ -4466,9 +4466,11 @@ public IItemDefinition GetItemDefinition(string itemType) /// Environment variable value. public void AddSdkResolvedEnvironmentVariable(string name, string value) { - // If the property has already been set as an environment variable or by another SDK, we do not overwrite it. - if (EnvironmentVariablePropertiesDictionary?.Contains(name) == true - || SdkResolvedEnvironmentVariablePropertiesDictionary?.Contains(name) == true) + ErrorUtilities.VerifyThrowArgumentLength(name); + ErrorUtilities.VerifyThrowArgumentNull(value); + + // If another SDK already set it, we do not overwrite it. + if (SdkResolvedEnvironmentVariablePropertiesDictionary?.Contains(name) == true) { return; } @@ -4478,6 +4480,7 @@ public void AddSdkResolvedEnvironmentVariable(string name, string value) SdkResolvedEnvironmentVariablePropertiesDictionary ??= new(); SdkResolvedEnvironmentVariablePropertiesDictionary.Set(property); + // SDK-resolved environment variables override ambient environment variables. SetProperty(name, value, isGlobalProperty: false, mayBeReserved: false, loggingContext: null); } diff --git a/src/Build/Instance/ProjectInstance.cs b/src/Build/Instance/ProjectInstance.cs index fe0cdee00e6..0c4abcef214 100644 --- a/src/Build/Instance/ProjectInstance.cs +++ b/src/Build/Instance/ProjectInstance.cs @@ -1387,14 +1387,11 @@ PropertyDictionary IEvaluatorData)this) .SetProperty(name, value, isGlobalProperty: false, mayBeReserved: false, loggingContext: _loggingContext, isEnvironmentVariable: true, isCommandLineProperty: false); diff --git a/src/Build/Resources/Strings.resx b/src/Build/Resources/Strings.resx index 83dd0ac7d07..0f97c00c554 100644 --- a/src/Build/Resources/Strings.resx +++ b/src/Build/Resources/Strings.resx @@ -1392,6 +1392,9 @@ Errors: {3} An SDK attempted set the environment variable "{0}" to "{1}". + + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + MSB4189: <{1}> is not a valid child of the <{0}> element. {StrBegin="MSB4189: "} diff --git a/src/Build/Resources/xlf/Strings.cs.xlf b/src/Build/Resources/xlf/Strings.cs.xlf index 38887c86af2..493cf30a687 100644 --- a/src/Build/Resources/xlf/Strings.cs.xlf +++ b/src/Build/Resources/xlf/Strings.cs.xlf @@ -901,6 +901,11 @@ Chyby: {3} Sada SDK se pokusila nastavit proměnnou prostředí {0} na {1}, která ale už byla nastavena jinou sadou SDK. + + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + + An SDK attempted set the environment variable "{0}" to "{1}". Sada SDK se pokusila nastavit proměnnou prostředí {0} na {1}. diff --git a/src/Build/Resources/xlf/Strings.de.xlf b/src/Build/Resources/xlf/Strings.de.xlf index 8d391df1fee..ae365ee88aa 100644 --- a/src/Build/Resources/xlf/Strings.de.xlf +++ b/src/Build/Resources/xlf/Strings.de.xlf @@ -901,6 +901,11 @@ Fehler: {3} Ein SDK hat versucht, die Umgebungsvariable „{0}“ auf „{1}“ festzulegen, sie wurde aber bereits von einem anderen SDK festgelegt. + + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + + An SDK attempted set the environment variable "{0}" to "{1}". Ein SDK hat versucht, die Umgebungsvariable „{0}“ auf „{1}“ festzulegen. diff --git a/src/Build/Resources/xlf/Strings.es.xlf b/src/Build/Resources/xlf/Strings.es.xlf index fb48065a368..61b108f6ded 100644 --- a/src/Build/Resources/xlf/Strings.es.xlf +++ b/src/Build/Resources/xlf/Strings.es.xlf @@ -901,6 +901,11 @@ Errores: {3} Un SDK intentó establecer la variable de entorno "{0}" en "{1}", pero ya la estableció otro SDK. + + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + + An SDK attempted set the environment variable "{0}" to "{1}". Un SDK intentó establecer la variable de entorno "{0}" en "{1}". diff --git a/src/Build/Resources/xlf/Strings.fr.xlf b/src/Build/Resources/xlf/Strings.fr.xlf index 35383a1e6af..1e9c55294bb 100644 --- a/src/Build/Resources/xlf/Strings.fr.xlf +++ b/src/Build/Resources/xlf/Strings.fr.xlf @@ -901,6 +901,11 @@ Erreurs : {3} Un Kit de développement logiciel (SDK) a tenté de définir la variable d’environnement « {0} » à « {1} », mais elle était déjà définie par un autre SDK. + + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + + An SDK attempted set the environment variable "{0}" to "{1}". Un Kit de développement logiciel (SDK) a tenté de définir la variable d’environnement « {0} » à « {1} ». diff --git a/src/Build/Resources/xlf/Strings.it.xlf b/src/Build/Resources/xlf/Strings.it.xlf index 1bc1a5b494f..344f67806ba 100644 --- a/src/Build/Resources/xlf/Strings.it.xlf +++ b/src/Build/Resources/xlf/Strings.it.xlf @@ -901,6 +901,11 @@ Errori: {3} Un SDK ha tentato di impostare la variabile di ambiente "{0}" su "{1}" ma era già stata impostata da un altro SDK. + + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + + An SDK attempted set the environment variable "{0}" to "{1}". Un SDK ha tentato di impostare la variabile di ambiente "{0}" su "{1}". diff --git a/src/Build/Resources/xlf/Strings.ja.xlf b/src/Build/Resources/xlf/Strings.ja.xlf index 0a3aecf356a..557be230878 100644 --- a/src/Build/Resources/xlf/Strings.ja.xlf +++ b/src/Build/Resources/xlf/Strings.ja.xlf @@ -901,6 +901,11 @@ Errors: {3} SDK は環境変数 "{0}" を "{1}" に設定しようとしましたが、それは既に別の SDK によって設定されていました。 + + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + + An SDK attempted set the environment variable "{0}" to "{1}". SDK が環境変数 "{0}" を "{1}" に設定しようとしました。 diff --git a/src/Build/Resources/xlf/Strings.ko.xlf b/src/Build/Resources/xlf/Strings.ko.xlf index c4de33c7e66..da239dd1f7f 100644 --- a/src/Build/Resources/xlf/Strings.ko.xlf +++ b/src/Build/Resources/xlf/Strings.ko.xlf @@ -901,6 +901,11 @@ Errors: {3} SDK가 환경 변수 "{0}"을(를) "{1}"(으)로 설정하려고 했지만 이미 다른 SDK에 의해 설정되었습니다. + + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + + An SDK attempted set the environment variable "{0}" to "{1}". SDK가 환경 변수 "{0}"을(를) "{1}"(으)로 설정하려고 했습니다. diff --git a/src/Build/Resources/xlf/Strings.pl.xlf b/src/Build/Resources/xlf/Strings.pl.xlf index f7833c69dbf..c879521412b 100644 --- a/src/Build/Resources/xlf/Strings.pl.xlf +++ b/src/Build/Resources/xlf/Strings.pl.xlf @@ -901,6 +901,11 @@ Błędy: {3} Zestaw SDK próbował ustawić zmienną środowiskową „{0}” na „{1}”, ale została już ustawiona przez inny zestaw SDK. + + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + + An SDK attempted set the environment variable "{0}" to "{1}". Zestaw SDK próbował ustawić zmienną środowiskową „{0}” na „{1}”. diff --git a/src/Build/Resources/xlf/Strings.pt-BR.xlf b/src/Build/Resources/xlf/Strings.pt-BR.xlf index f2518068b1a..1c95e5609dc 100644 --- a/src/Build/Resources/xlf/Strings.pt-BR.xlf +++ b/src/Build/Resources/xlf/Strings.pt-BR.xlf @@ -901,6 +901,11 @@ Erros: {3} Um SDK tentou definir a variável de ambiente "{0}" como "{1}", mas ela já foi definida por outro SDK. + + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + + An SDK attempted set the environment variable "{0}" to "{1}". Um SDK tentou definir a variável de ambiente "{0}" como "{1}". diff --git a/src/Build/Resources/xlf/Strings.ru.xlf b/src/Build/Resources/xlf/Strings.ru.xlf index caf1ee1d68d..12b2e0bba36 100644 --- a/src/Build/Resources/xlf/Strings.ru.xlf +++ b/src/Build/Resources/xlf/Strings.ru.xlf @@ -901,6 +901,11 @@ Errors: {3} Пакет SDK попытался настроить для переменной среды "{0}" значение "{1}", но она уже была настроена другим пакетом SDK. + + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + + An SDK attempted set the environment variable "{0}" to "{1}". Пакет SDK попытался настроить для переменной среды "{0}" значение "{1}". diff --git a/src/Build/Resources/xlf/Strings.tr.xlf b/src/Build/Resources/xlf/Strings.tr.xlf index fd1c26bb59a..40bf1cd388c 100644 --- a/src/Build/Resources/xlf/Strings.tr.xlf +++ b/src/Build/Resources/xlf/Strings.tr.xlf @@ -901,6 +901,11 @@ Hatalar: {3} Bir SDK "{0}" ortam değişkenini "{1}" olarak ayarlamaya çalıştı ancak bu değişken zaten başka bir SDK tarafından ayarlanmıştı. + + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + + An SDK attempted set the environment variable "{0}" to "{1}". Bir SDK, "{0}" ortam değişkenini "{1}" olarak ayarlamaya çalıştı. diff --git a/src/Build/Resources/xlf/Strings.zh-Hans.xlf b/src/Build/Resources/xlf/Strings.zh-Hans.xlf index 4e0b060d4b3..86a3d1e27a5 100644 --- a/src/Build/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/Build/Resources/xlf/Strings.zh-Hans.xlf @@ -901,6 +901,11 @@ Errors: {3} SDK 尝试将环境变量 "{0}" 设置为 "{1}",但已由另一个 SDK 设置。 + + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + + An SDK attempted set the environment variable "{0}" to "{1}". SDK 尝试将环境变量 "{0}" 设置为 "{1}"。 diff --git a/src/Build/Resources/xlf/Strings.zh-Hant.xlf b/src/Build/Resources/xlf/Strings.zh-Hant.xlf index e2ae7fa5983..3d67b08c131 100644 --- a/src/Build/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/Build/Resources/xlf/Strings.zh-Hant.xlf @@ -901,6 +901,11 @@ Errors: {3} 一個 SDK 嘗試將環境變數 "{0}" 設定為 "{1}",但該變數已由另一個 SDK 設定。 + + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + An SDK set the environment variable "{0}" to "{1}", overriding the ambient environment variable value. + + An SDK attempted set the environment variable "{0}" to "{1}". 一個 SDK 嘗試將環境變數 "{0}" 設定為 "{1}"。