Skip to content

Commit

Permalink
Merge pull request #159 from dsplaisted/netcore-port
Browse files Browse the repository at this point in the history
Port Microsoft.Build to .NET Core
  • Loading branch information
dsplaisted committed Aug 26, 2015
2 parents 14004e7 + 9a1e383 commit 3be2996
Show file tree
Hide file tree
Showing 26 changed files with 248 additions and 31 deletions.
4 changes: 4 additions & 0 deletions dir.props
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
<DefineConstants>$(DefineConstants);FEATURE_APARTMENT_STATE</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_APM</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_APPDOMAIN</DefineConstants>
<FeatureAppDomain>true</FeatureAppDomain>
<DefineConstants>$(DefineConstants);FEATURE_APPDOMAIN_UNHANDLED_EXCEPTION</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_ASSEMBLY_LOADFROM</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_ASSEMBLY_LOCATION</DefineConstants>
Expand All @@ -122,13 +123,16 @@
<DefineConstants>$(DefineConstants);FEATURE_HANDLEREF</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_MEMORYSTREAM_GETBUFFER</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_OSVERSION</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_PARALLEL_BUILD</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_REFLECTION_EMIT_DEBUG_INFO</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_REGISTRYHIVE_DYNDATA</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_RESOURCE_EXPOSURE</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_SECURITY_PERMISSIONS</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_SECURITY_PRINCIPAL_WINDOWS</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_SPECIAL_FOLDERS</DefineConstants>
<FeatureSpecialFolders>true</FeatureSpecialFolders>
<DefineConstants>$(DefineConstants);FEATURE_SYSTEM_CONFIGURATION</DefineConstants>
<FeatureSystemConfiguration>true</FeatureSystemConfiguration>
<DefineConstants>$(DefineConstants);FEATURE_THREAD_ABORT</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_THREAD_CULTURE</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_THREAD_PRIORITY</DefineConstants>
Expand Down
2 changes: 2 additions & 0 deletions src/Shared/CommunicationsUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ internal static void SetEnvironment(IDictionary<string, string> newEnvironment)
/// </summary>
internal static long GenerateHostHandshakeFromBase(long baseHandshake, long clientHandshake)
{
#if FEATURE_SECURITY_PRINCIPAL_WINDOWS
// If we are running in elevated privs, we will only accept a handshake from an elevated process as well.
WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());

Expand All @@ -328,6 +329,7 @@ internal static long GenerateHostHandshakeFromBase(long baseHandshake, long clie
baseHandshake = ~baseHandshake;
}
}
#endif

// Mask out the first byte. That's because old
// builds used a single, non zero initial byte,
Expand Down
2 changes: 2 additions & 0 deletions src/Shared/FrameworkLocationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
using Microsoft.Build.Evaluation;
using Microsoft.Win32;

#if FEATURE_SYSTEM_CONFIGURATION
using PropertyElement = Microsoft.Build.Evaluation.ToolsetElement.PropertyElement;
#endif
using System.Reflection;
using System.Runtime.InteropServices;

Expand Down
8 changes: 8 additions & 0 deletions src/Shared/LogMessagePacketBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

using Microsoft.Build.Framework;
using Microsoft.Build.BackEnd;
#if FEATURE_APPDOMAIN
using TaskEngineAssemblyResolver = Microsoft.Build.BackEnd.Logging.TaskEngineAssemblyResolver;
#endif

namespace Microsoft.Build.Shared
{
Expand Down Expand Up @@ -136,10 +138,12 @@ private static int GetDefaultPacketVersion()
/// </summary>
private static HashSet<string> s_customEventsLoaded = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

#if FEATURE_APPDOMAIN
/// <summary>
/// The resolver used to load custom event types.
/// </summary>
private static TaskEngineAssemblyResolver s_resolver;
#endif

/// <summary>
/// The object used to synchronize access to shared data.
Expand Down Expand Up @@ -389,12 +393,14 @@ internal void ReadFromStream(INodePacketTranslator translator)
}
}

#if FEATURE_APPDOMAIN
if (resolveAssembly)
{
s_resolver = new TaskEngineAssemblyResolver();
s_resolver.InstallHandler();
s_resolver.Initialize(fileLocation);
}
#endif

try
{
Expand All @@ -404,11 +410,13 @@ internal void ReadFromStream(INodePacketTranslator translator)
}
finally
{
#if FEATURE_APPDOMAIN
if (resolveAssembly)
{
s_resolver.RemoveHandler();
s_resolver = null;
}
#endif
}
}

Expand Down
4 changes: 0 additions & 4 deletions src/Shared/TaskEngineAssemblyResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ namespace Microsoft.Build.BackEnd.Logging
/// This is a helper class to install an AssemblyResolver event handler in whatever AppDomain this class is created in.
/// </summary>
internal class TaskEngineAssemblyResolver
#if FEATURE_APPDOMAIN
: MarshalByRefObject
#endif
{
/// <summary>
/// This public default constructor is needed so that instances of this class can be created by NDP.
Expand Down Expand Up @@ -114,7 +112,6 @@ internal Assembly ResolveAssembly(object sender, ResolveEventArgs args)
return null;
}

#if FEATURE_APPDOMAIN
/// <summary>
/// Overridden to give this class infinite lease time. Otherwise we end up with a limited
/// lease (5 minutes I think) and instances can expire if they take long time processing.
Expand All @@ -125,7 +122,6 @@ public override object InitializeLifetimeService()
// null means infinite lease time
return null;
}
#endif

// path to the task assembly, but only if it's loaded using LoadFrom. If it's loaded with Load, this is null.
private string _taskAssemblyFile = null;
Expand Down
27 changes: 27 additions & 0 deletions src/Shared/TaskHostConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using System.Text;

using Microsoft.Build.Shared;
using System.Reflection;

namespace Microsoft.Build.BackEnd
{
Expand Down Expand Up @@ -49,10 +50,12 @@ internal class TaskHostConfiguration : INodePacket
/// </summary>
private CultureInfo _uiCulture = CultureInfo.CurrentUICulture;

#if FEATURE_APPDOMAIN
/// <summary>
/// The AppDomainSetup that we may want to use on AppDomainIsolated tasks.
/// </summary>
private AppDomainSetup _appDomainSetup;
#endif

/// <summary>
/// Line number where the instance of this task is defined.
Expand All @@ -79,10 +82,14 @@ internal class TaskHostConfiguration : INodePacket
/// </summary>
private string _taskName;

#if FEATURE_ASSEMBLY_LOADFROM
/// <summary>
/// Location of the assembly containing the task to be executed.
/// </summary>
private string _taskLocation;
#else
private AssemblyName _taskAssemblyName;
#endif

/// <summary>
/// The set of parameters to apply to the task prior to execution.
Expand Down Expand Up @@ -112,18 +119,26 @@ public TaskHostConfiguration
IDictionary<string, string> buildProcessEnvironment,
CultureInfo culture,
CultureInfo uiCulture,
#if FEATURE_APPDOMAIN
AppDomainSetup appDomainSetup,
#endif
int lineNumberOfTask,
int columnNumberOfTask,
string projectFileOfTask,
bool continueOnError,
string taskName,
#if FEATURE_ASSEMBLY_LOADFROM
string taskLocation,
#else
AssemblyName taskAssemblyName,
#endif
IDictionary<string, object> taskParameters
)
{
ErrorUtilities.VerifyThrowInternalLength(taskName, "taskName");
#if FEATURE_ASSEMBLY_LOADFROM
ErrorUtilities.VerifyThrowInternalLength(taskLocation, "taskLocation");
#endif

_nodeId = nodeId;
_startupDirectory = startupDirectory;
Expand All @@ -140,13 +155,19 @@ public TaskHostConfiguration

_culture = culture;
_uiCulture = uiCulture;
#if FEATURE_ASSEMBLY_LOADFROM
_appDomainSetup = appDomainSetup;
#endif
_lineNumberOfTask = lineNumberOfTask;
_columnNumberOfTask = columnNumberOfTask;
_projectFileOfTask = projectFileOfTask;
_continueOnError = continueOnError;
_taskName = taskName;
#if FEATURE_ASSEMBLY_LOADFROM
_taskLocation = taskLocation;
#else
_taskAssemblyName = taskAssemblyName;
#endif

if (taskParameters != null)
{
Expand Down Expand Up @@ -216,6 +237,7 @@ public CultureInfo UICulture
{ return _uiCulture; }
}

#if FEATURE_APPDOMAIN
/// <summary>
/// The AppDomain configuration bytes that we may want to use to initialize
/// AppDomainIsolated tasks.
Expand All @@ -226,6 +248,7 @@ public AppDomainSetup AppDomainSetup
get
{ return _appDomainSetup; }
}
#endif

/// <summary>
/// Line number where the instance of this task is defined.
Expand Down Expand Up @@ -277,6 +300,7 @@ public string TaskName
{ return _taskName; }
}

#if FEATURE_ASSEMBLY_LOADFROM
/// <summary>
/// Path to the assembly to load the task from.
/// </summary>
Expand All @@ -286,6 +310,7 @@ public string TaskLocation
get
{ return _taskLocation; }
}
#endif

/// <summary>
/// Parameters to set on the instantiated task prior to execution.
Expand Down Expand Up @@ -325,7 +350,9 @@ public void Translate(INodePacketTranslator translator)
translator.Translate(ref _columnNumberOfTask);
translator.Translate(ref _projectFileOfTask);
translator.Translate(ref _taskName);
#if FEATURE_ASSEMBLY_LOADFROM
translator.Translate(ref _taskLocation);
#endif
translator.TranslateDictionary(ref _taskParameters, StringComparer.OrdinalIgnoreCase, TaskParameter.FactoryForDeserialization);
translator.Translate(ref _continueOnError);
}
Expand Down
24 changes: 23 additions & 1 deletion src/Shared/TaskLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,30 @@ internal static bool IsTaskClass(Type type, object unused)
/// <summary>
/// Creates an ITask instance and returns it.
/// </summary>
internal static ITask CreateTask(LoadedType loadedType, string taskName, string taskLocation, int taskLine, int taskColumn, LogError logError, AppDomainSetup appDomainSetup, bool isOutOfProc, out AppDomain taskAppDomain)
internal static ITask CreateTask(LoadedType loadedType, string taskName, string taskLocation, int taskLine, int taskColumn, LogError logError
#if FEATURE_APPDOMAIN
, AppDomainSetup appDomainSetup
#endif
, bool isOutOfProc
#if FEATURE_APPDOMAIN
, out AppDomain taskAppDomain
#endif
)
{
#if FEATURE_APPDOMAIN
bool separateAppDomain = loadedType.HasLoadInSeparateAppDomainAttribute();
#else
bool separateAppDomain = false;
#endif
s_resolverLoadedType = null;
#if FEATURE_APPDOMAIN
taskAppDomain = null;
#endif
ITask taskInstanceInOtherAppDomain = null;

try
{
#if FEATURE_APPDOMAIN
if (separateAppDomain)
{
if (!loadedType.Type.GetTypeInfo().IsMarshalByRef)
Expand Down Expand Up @@ -109,12 +124,14 @@ internal static ITask CreateTask(LoadedType loadedType, string taskName, string
}
}
else
#endif
{
// perf improvement for the same appdomain case - we already have the type object
// and don't want to go through reflection to recreate it from the name.
return (ITask)Activator.CreateInstance(loadedType.Type);
}

#if FEATURE_APPDOMAIN
if (loadedType.Assembly.AssemblyFile != null)
{
taskInstanceInOtherAppDomain = (ITask)taskAppDomain.CreateInstanceFromAndUnwrap(loadedType.Assembly.AssemblyFile, loadedType.Type.FullName);
Expand Down Expand Up @@ -146,18 +163,22 @@ internal static ITask CreateTask(LoadedType loadedType, string taskName, string
}

return taskInstanceInOtherAppDomain;
#endif
}
finally
{
#if FEATURE_APPDOMAIN
// Don't leave appdomains open
if (taskAppDomain != null && taskInstanceInOtherAppDomain == null)
{
AppDomain.Unload(taskAppDomain);
RemoveAssemblyResolver();
}
#endif
}
}

#if FEATURE_APPDOMAIN
/// <summary>
/// This is a resolver to help created AppDomains when they are unable to load an assembly into their domain we will help
/// them succeed by providing the already loaded one in the currentdomain so that they can derive AssemblyName info from it
Expand Down Expand Up @@ -187,5 +208,6 @@ internal static void RemoveAssemblyResolver()
s_resolverLoadedType = null;
}
}
#endif
}
}
4 changes: 4 additions & 0 deletions src/Shared/TaskLoggingHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
using System.IO;
using System.Resources;
using System.Text;
#if FEATURE_APPDOMAIN
using System.Runtime.Remoting.Lifetime;
using System.Runtime.Remoting;
#endif

using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
Expand Down Expand Up @@ -64,12 +66,14 @@ public TaskLoggingHelper(IBuildEngine buildEngine, string taskName)

#region Properties

#if FEATURE_APPDOMAIN
/// <summary>
/// A client sponsor is a class
/// which will respond to a lease renewal request and will
/// increase the lease time allowing the object to stay in memory
/// </summary>
private ClientSponsor _sponsor;
#endif

// We have to pass an instance of ITask to BuildEngine, and since we call into the engine from this class we
// need to store the actual task instance.
Expand Down
6 changes: 4 additions & 2 deletions src/XMakeBuildEngine/BackEnd/BuildManager/BuildManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1626,8 +1626,10 @@ private NodeConfiguration GetNodeConfiguration()
(
-1, /* must be assigned by the NodeManager */
_buildParameters,
remoteLoggers.ToArray(),
AppDomain.CurrentDomain.SetupInformation
remoteLoggers.ToArray()
#if FEATURE_APPDOMAIN
, AppDomain.CurrentDomain.SetupInformation
#endif
);
}

Expand Down
Loading

0 comments on commit 3be2996

Please sign in to comment.