1 // Copyright (c) Microsoft. All rights reserved. 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 //----------------------------------------------------------------------- 4 // </copyright> 5 6 using System; 7 using Microsoft.Build.Shared; 8 9 namespace Microsoft.Build.Utilities 10 { 11 /// <summary> 12 /// Represents toggleable features of the MSBuild engine 13 /// </summary> 14 internal class Traits 15 { 16 private static Traits _instance = new Traits(); 17 public static Traits Instance 18 { 19 get 20 { 21 if (BuildEnvironmentHelper.Instance.RunningTests && Environment.GetEnvironmentVariable("MSBUILDRELOADTRAITSONEACHACCESS") == "1") 22 { 23 return new Traits(); 24 } 25 return _instance; 26 } 27 } 28 29 public EscapeHatches EscapeHatches { get; } 30 31 /// <summary> 32 /// Do not expand wildcards that match a certain pattern 33 /// </summary> 34 public readonly bool UseLazyWildCardEvaluation = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MsBuildSkipEagerWildCardEvaluationRegexes")); 35 public readonly bool LogExpandedWildcards = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDLOGEXPANDEDWILDCARDS")); 36 public readonly bool CacheFileExistence = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MsBuildCacheFileExistence")); 37 38 /// <summary> 39 /// Eliminate locking in OpportunisticIntern at the expense of memory 40 /// </summary> 41 public readonly bool UseSimpleInternConcurrency = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MsBuildUseSimpleInternConcurrency")); 42 43 /// <summary> 44 /// Cache wildcard expansions 45 /// </summary> 46 public readonly bool MSBuildCacheFileEnumerations = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MsBuildCacheFileEnumerations")); 47 Traits()48 public Traits() 49 { 50 EscapeHatches = new EscapeHatches(); 51 } 52 53 public readonly bool EnableAllPropertyFunctions = Environment.GetEnvironmentVariable("MSBUILDENABLEALLPROPERTYFUNCTIONS") == "1"; 54 55 /// <summary> 56 /// Enable restore first functionality in MSBuild.exe 57 /// </summary> 58 public readonly bool EnableRestoreFirst = Environment.GetEnvironmentVariable("MSBUILDENABLERESTOREFIRST") == "1"; 59 } 60 61 internal class EscapeHatches 62 { 63 /// <summary> 64 /// Force whether Project based evaluations should evaluate elements with false conditions. 65 /// </summary> 66 public readonly bool? EvaluateElementsWithFalseConditionInProjectEvaluation = ParseNullableBoolFromEnvironmentVariable("MSBUILDEVALUATEELEMENTSWITHFALSECONDITIONINPROJECTEVALUATION"); 67 68 /// <summary> 69 /// Always use the accurate-but-slow CreateFile approach to timestamp extraction. 70 /// </summary> 71 public readonly bool AlwaysUseContentTimestamp = Environment.GetEnvironmentVariable("MSBUILDALWAYSCHECKCONTENTTIMESTAMP") == "1"; 72 73 public readonly bool LogProjectImports = Environment.GetEnvironmentVariable("MSBUILDLOGIMPORTS") == "1"; 74 75 /// <summary> 76 /// Read information only once per file per ResolveAssemblyReference invocation. 77 /// </summary> 78 public readonly bool CacheAssemblyInformation = Environment.GetEnvironmentVariable("MSBUILDDONOTCACHERARASSEMBLYINFORMATION") != "1"; 79 80 public readonly ProjectInstanceTranslationMode? ProjectInstanceTranslation = ComputeProjectInstanceTranslation(); 81 82 /// <summary> 83 /// Never use the slow (but more accurate) CreateFile approach to timestamp extraction. 84 /// </summary> 85 public readonly bool UseSymlinkTimeInsteadOfTargetTime = Environment.GetEnvironmentVariable("MSBUILDUSESYMLINKTIMESTAMP") == "1"; 86 87 /// <summary> 88 /// Whether or not to ignore imports that are considered empty. See ProjectRootElement.IsEmptyXmlFile() for more info. 89 /// </summary> 90 public readonly bool IgnoreEmptyImports = Environment.GetEnvironmentVariable("MSBUILDIGNOREEMPTYIMPORTS") == "1"; 91 92 /// <summary> 93 /// Whether to to respect the TreatAsLocalProperty parameter on the Project tag. 94 /// </summary> 95 public readonly bool IgnoreTreatAsLocalProperty = Environment.GetEnvironmentVariable("MSBUILDIGNORETREATASLOCALPROPERTY") != null; 96 97 /// <summary> 98 /// Whether to write information about why we evaluate to debug output. 99 /// </summary> 100 public readonly bool DebugEvaluation = Environment.GetEnvironmentVariable("MSBUILDDEBUGEVALUATION") != null; 101 102 /// <summary> 103 /// Whether to warn when we set a property for the first time, after it was previously used. 104 /// </summary> 105 public readonly bool WarnOnUninitializedProperty = !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDWARNONUNINITIALIZEDPROPERTY")); 106 107 // MSBUILDUSECASESENSITIVEITEMNAMES is an escape hatch for the fix 108 // for https://github.com/Microsoft/msbuild/issues/1751. It should 109 // be removed (permanently set to false) after establishing that 110 // it's unneeded (at least by the 16.0 timeframe). 111 public readonly bool UseCaseSensitiveItemNames = Environment.GetEnvironmentVariable("MSBUILDUSECASESENSITIVEITEMNAMES") == "1"; 112 113 /// <summary> 114 /// Disable the use of any caching when resolving SDKs. 115 /// </summary> 116 public readonly bool DisableSdkResolutionCache = Environment.GetEnvironmentVariable("MSBUILDDISABLESDKCACHE") == "1"; 117 118 /// <summary> 119 /// Disable the NuGet-based SDK resolver. 120 /// </summary> 121 public readonly bool DisableNuGetSdkResolver = Environment.GetEnvironmentVariable("MSBUILDDISABLENUGETSDKRESOLVER") == "1"; 122 123 /// <summary> 124 /// Enables the user of autorun functionality in CMD.exe on Windows which is disabled by default in MSBuild. 125 /// </summary> 126 public readonly bool UseAutoRunWhenLaunchingProcessUnderCmd = Environment.GetEnvironmentVariable("MSBUILDUSERAUTORUNINCMD") == "1"; 127 128 /// <summary> 129 /// Workaround for https://github.com/Microsoft/vstest/issues/1503. 130 /// </summary> 131 public readonly bool EnsureStdOutForChildNodesIsPrimaryStdout = Environment.GetEnvironmentVariable("MSBUILDENSURESTDOUTFORTASKPROCESSES") == "1"; 132 133 ParseNullableBoolFromEnvironmentVariable(string environmentVariable)134 private static bool? ParseNullableBoolFromEnvironmentVariable(string environmentVariable) 135 { 136 var value = Environment.GetEnvironmentVariable(environmentVariable); 137 138 if (string.IsNullOrEmpty(value)) 139 { 140 return null; 141 } 142 143 bool result; 144 if (bool.TryParse(value, out result)) 145 { 146 return result; 147 } 148 149 ErrorUtilities.ThrowInternalError($"Environment variable \"{environmentVariable}\" should have values \"true\", \"false\" or undefined"); 150 151 return null; 152 } 153 ComputeProjectInstanceTranslation()154 private static ProjectInstanceTranslationMode? ComputeProjectInstanceTranslation() 155 { 156 var mode = Environment.GetEnvironmentVariable("MSBUILD_PROJECTINSTANCE_TRANSLATION_MODE"); 157 158 if (mode == null) 159 { 160 return null; 161 } 162 163 if (mode.Equals("full", StringComparison.OrdinalIgnoreCase)) 164 { 165 return ProjectInstanceTranslationMode.Full; 166 } 167 168 if (mode.Equals("partial", StringComparison.OrdinalIgnoreCase)) 169 { 170 return ProjectInstanceTranslationMode.Partial; 171 } 172 173 ErrorUtilities.ThrowInternalError($"Invalid escape hatch for project instance translation: {mode}"); 174 175 return null; 176 } 177 178 public enum ProjectInstanceTranslationMode 179 { 180 Full, 181 Partial 182 } 183 } 184 } 185