Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 53 additions & 26 deletions dotnet/targets/Xamarin.Shared.Sdk.targets

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions msbuild/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"command": "make",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$msCompile"
],
"label": "make"
}
]
}
1 change: 1 addition & 0 deletions msbuild/ILMerge.targets
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<MergedAssemblies Include="@(ReferenceDependencyPaths)" Condition="'%(FileName)' == 'AssemblyStripper'" />
<MergedAssemblies Include="@(ReferencePath)" Condition="'%(FileName)' == 'MonoTargetsTasks'" />
<MergedAssemblies Include="@(ReferencePath)" Condition="'%(FileName)' == 'Xamarin.Apple.Tools.MaciOS'" />
<MergedAssemblies Include="@(ReferencePath)" Condition="'%(FileName)' == 'assembly-preparer'" />
<MergedAssemblies Include="@(ReferencePath)" Condition="'%(FileName)' == 'DotNetZip'" />
<MergedAssemblies Include="@(ReferencePath)" Condition="'%(FileName)' == 'ILLink.Tasks'" />
<MergedAssemblies Include="@(ReferencePath)" Condition="'%(FileName)' == 'ILStrip'" />
Expand Down
5 changes: 5 additions & 0 deletions msbuild/Xamarin.Localization.MSBuild/MSBStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1661,4 +1661,9 @@
<comment>Shown when the tool reports a simulator runtime version mismatch.
{0} - The platform name (e.g. "iOS" or "tvOS").</comment>
</data>
<data name="E7178" xml:space="preserve">
<value>Console.StandardOutput or Console.StandardError was accessed during a build task. This should not happen, use the MSBuild logging infrastructure instead. Stack trace: {0}</value>
<comment>Shown when an MSBuild task writes to the console instead of using MSBuild logging.
{0} - The stack trace of the offending call.</comment>
</data>
</root>
4 changes: 4 additions & 0 deletions msbuild/Xamarin.MacDev.Tasks.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@
<BuildType Solution="Debug-net461|*" Project="Debug" />
<BuildType Solution="Debug-netstandard2.0|*" Project="Debug" />
</Project>
<Project Path="../tools/assembly-preparer/assembly-preparer.csproj">
<BuildType Solution="Debug-net461|*" Project="Debug" />
<BuildType Solution="Debug-netstandard2.0|*" Project="Debug" />
</Project>
</Solution>
103 changes: 103 additions & 0 deletions msbuild/Xamarin.MacDev.Tasks/ConsoleToTaskWriter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.IO;
using System.Text;

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

#nullable enable

namespace Xamarin.Utils;

class ConsoleToTaskWriter : TextWriter {
TaskLoggingHelper helper;
bool errorShown;

public ConsoleToTaskWriter (TaskLoggingHelper helper)
{
this.helper = helper;
}

public override Encoding Encoding => Encoding.UTF8;

public override void Write (char value)
{
ShowError ();
helper.LogMessage (MessageImportance.Low, value.ToString ());
}

public override void Write (char [] buffer, int index, int count)
{
ShowError ();
helper.LogMessage (MessageImportance.Low, new string (buffer, index, count));
}

public override void Write (string? value)
{
ShowError ();
helper.LogMessage (MessageImportance.Low, value ?? string.Empty);
}

public override void WriteLine ()
{
ShowError ();
}

public override void WriteLine (string? value)
{
ShowError ();
helper.LogMessage (MessageImportance.Low, value ?? string.Empty);
}

void ShowError ()
{
if (errorShown)
return;
errorShown = true;

helper.LogError (null, "MT7178" /* Console.StandardOutput or Console.StandardError was accessed during a build task. This should not happen, use the MSBuild logging infrastructure instead. Stack trace: {0} */, null, null, 0, 0, 0, 0, Xamarin.Localization.MSBuild.MSBStrings.E7178, Environment.StackTrace);
}

public static IDisposable EnsureNoConsoleUsage (TaskLoggingHelper log)
{
return new NoConsoleUsage (new ConsoleToTaskWriter (log));
}

class NoConsoleUsage : IDisposable {
TextWriter? originalStdout;
TextWriter? originalStderr;

public NoConsoleUsage (ConsoleToTaskWriter redirector)
{
originalStdout = Console.Out;
originalStderr = Console.Error;
Console.SetOut (redirector);
Console.SetError (redirector);
}

~NoConsoleUsage ()
{
Restore ();
}

void IDisposable.Dispose ()
{
Restore ();
GC.SuppressFinalize (this);
}

void Restore ()
{
if (originalStdout is not null) {
Console.SetOut (originalStdout);
originalStdout = null;
}
if (originalStderr is not null) {
Console.SetError (originalStderr);
originalStderr = null;
}
}
}
}
54 changes: 0 additions & 54 deletions msbuild/Xamarin.MacDev.Tasks/ErrorHelper.msbuild.cs

This file was deleted.

23 changes: 23 additions & 0 deletions msbuild/Xamarin.MacDev.Tasks/LoggingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,19 @@ public static void LogTaskProperty (this TaskLoggingHelper log, string propertyN
log.LogMessage (TaskPropertyImportance, " {0}: {1}", propertyName, value);
}

/// <summary>
/// Creates an MSBuild error following our MTErrors convention.</summary>
/// <remarks>
/// For every new error we need to update "docs/website/mtouch-errors.md" and "tools/mtouch/error.cs".</remarks>
/// <param name="errorCode">In the 7xxx range for MSBuild error.</param>
/// <param name="message">The error's message to be displayed in the error pad.</param>
/// <param name="fileName">Path to the known guilty file or null.</param>
/// <param name="lineNumber">Line number in the file where the error was found, or 0 if unknown.</param>
public static void LogError (this TaskLoggingHelper log, int errorCode, string? fileName, int lineNumber, string message, params object? [] args)
{
log.LogError (null, $"{ErrorPrefix}{errorCode}", null, fileName ?? "MSBuild", lineNumber, 0, 0, 0, message, args);
}

/// <summary>
/// Creates an MSBuild error following our MTErrors convention.</summary>
/// <remarks>
Expand All @@ -91,6 +104,16 @@ public static void LogWarning (this TaskLoggingHelper log, int errorCode, string
log.LogWarning (null, $"{ErrorPrefix}{errorCode}", null, fileName ?? "MSBuild", 0, 0, 0, 0, message, args);
}

public static void LogWarning (this TaskLoggingHelper log, int errorCode, string? fileName, int lineNumber, string message, params object? [] args)
{
log.LogWarning (null, $"{ErrorPrefix}{errorCode}", null, fileName ?? "MSBuild", lineNumber, 0, 0, 0, message, args);
}

public static void LogMessage (this TaskLoggingHelper log, MessageImportance importance, int errorCode, string? fileName, int lineNumber, string message, params object? [] args)
{
log.LogMessage (null, $"{ErrorPrefix}{errorCode}", null, fileName ?? "MSBuild", lineNumber, 0, 0, 0, importance, message, args);
}

public static bool LogErrorsFromException (this TaskLoggingHelper log, Exception exception, bool showStackTrace = true, bool showDetail = true)
{
var exceptions = new List<Exception> ();
Expand Down
109 changes: 109 additions & 0 deletions msbuild/Xamarin.MacDev.Tasks/Tasks/PrepareAssemblies.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

using Xamarin.Build;
using Xamarin.Bundler;
using Xamarin.Utils;

#nullable enable

namespace Xamarin.MacDev.Tasks {
public class PrepareAssemblies : XamarinTask {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 💡 MSBuild tasks — Consider whether this task needs SessionId and IsMacEnabled properties for remote execution support when building from Windows.

Most MSBuild tasks in this repository that perform Mac-specific operations include:

SessionId="$(BuildSessionId)"
Condition="'$(IsMacEnabled)' == 'true'"

Since this task processes assemblies and may eventually need to run on the Mac (or already does for certain operations), verify whether remote execution support is needed. If assembly preparation must always happen on the Mac, add these properties and conditions.

Rule: SessionId for remote execution

const string ErrorPrefix = "MX";

#region Inputs
[Required]
public ITaskItem [] InputAssemblies { get; set; } = [];

public string MakeReproPath { get; set; } = "";

public string OutputDirectory { get; set; } = "";

[Required]
public ITaskItem? OptionsFile { get; set; }
#endregion

#region Outputs
[Output]
public ITaskItem [] OutputAssemblies { get; set; } = [];
#endregion

Dictionary<AssemblyPreparerInfo, ITaskItem> map = new ();

AssemblyPreparerInfo GetAssemblyInfo (ITaskItem item)
{
var inputPath = item.ItemSpec;
var outputPath = Path.Combine (OutputDirectory, Path.GetFileName (inputPath));
var isTrimmableString = item.GetMetadata ("IsTrimmable");
var isTrimmable = string.IsNullOrEmpty (isTrimmableString) ? (bool?) null : string.Equals (isTrimmableString, "true", StringComparison.OrdinalIgnoreCase);
var trimMode = item.GetMetadata ("TrimMode");
var rv = new AssemblyPreparerInfo (inputPath, outputPath, isTrimmable, trimMode);
map [rv] = item;
return rv;
}

public override bool Execute ()
{
// Capture Console usage and show an error if anything uses Console.[Error.]Write*
using var consoleToLog = ConsoleToTaskWriter.EnsureNoConsoleUsage (Log);

try {
var infos = InputAssemblies.Select (GetAssemblyInfo).ToArray ();
using var preparer = new AssemblyPreparer (this, infos, OptionsFile?.ItemSpec ?? "");
preparer.MakeReproPath = MakeReproPath;
var rv = preparer.Prepare (out var exceptions);
Comment on lines +61 to +65

foreach (var pe in exceptions) {
if (pe.IsError (this)) {
((IToolLog) this).LogError (pe);
} else {
((IToolLog) this).LogWarning (pe);
}
}

var outputAssemblies = preparer.Assemblies.Select (v => {
var item = new TaskItem (v.OutputPath);
map [v].CopyMetadataTo (item);
item.SetMetadata ("BeforePrepareAssembliesPath", v.InputPath);
return (ITaskItem) item;
}).ToList ();

outputAssemblies.AddRange (preparer.AddedAssemblies.Select (v => {
var rv = new TaskItem (v.Path);
rv.SetMetadata ("PostprocessAssembly", "true");
rv.SetMetadata ("RelativePath", preparer.Configuration.AssemblyPublishDir + Path.GetFileName (v.Path));
if (v.OriginatingAssembly is not null) {
var originatingItem = map.SingleOrDefault (kvp => Path.GetFileName (kvp.Key.InputPath) == Path.GetFileName (v.OriginatingAssembly)).Value;
if (originatingItem is null) {
Log.LogMessage (MessageImportance.Low, $"Could not find originating assembly for {v.Path} with originating assembly name {v.OriginatingAssembly}");
} else {
var metadata = originatingItem.MetadataNames.Cast<string> ().ToList ();
if (metadata.Contains ("TrimMode"))
rv.SetMetadata ("TrimMode", originatingItem.GetMetadata ("TrimMode"));
if (metadata.Contains ("IsTrimmable"))
rv.SetMetadata ("IsTrimmable", originatingItem.GetMetadata ("IsTrimmable"));
}
}
return rv;
}));

OutputAssemblies = outputAssemblies.ToArray ();
return rv && !Log.HasLoggedErrors;
} catch (Exception e) {
((IToolLog) this).LogException (e);
return false;
}
}
}
}
Loading
Loading