Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Cargo Build Sdk #599

Merged
merged 29 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f406f8e
add rust sdk
novacole Oct 8, 2024
addaf63
add readme, add clearcargocache target
novacole Oct 9, 2024
fd8d0db
cleanup
novacole Oct 9, 2024
858ae79
Merge pull request #1 from novacole/dev/colecarter/cargobuildsdk
novacole Oct 9, 2024
5ce6c4f
check for presence of cargo.toml instead of cargo.lock
novacole Oct 9, 2024
cd14bcf
Merge pull request #2 from novacole/dev/colecarter/cargobuildsdk
novacole Oct 9, 2024
ba031a3
lock -> toml
novacole Oct 9, 2024
5c13586
Update README.md
novacole Nov 19, 2024
2a85ae9
Update README.md
novacole Nov 19, 2024
a828175
Update README.md
novacole Nov 19, 2024
270c640
Update README.md
novacole Nov 19, 2024
39f3783
add msrustup support
novacole Jan 8, 2025
1d6b224
merge
novacole Jan 8, 2025
895b951
add msrustup download script
novacole Jan 8, 2025
16a45c3
merge
novacole Jan 8, 2025
424daf5
whitespace
novacole Jan 8, 2025
4aed5ba
update project name
novacole Jan 9, 2025
e042635
readme updates, update version, cleanup
novacole Jan 10, 2025
5d85227
clean up
novacole Jan 15, 2025
10a53d4
update tests
novacole Jan 16, 2025
b0637b8
rm target
novacole Jan 16, 2025
74643fb
attempt test fix
novacole Jan 16, 2025
ad12634
rename cargobuild -> cargo, fix tests
novacole Jan 17, 2025
3406005
sdk name update, continued
novacole Jan 17, 2025
d23cff8
attempt fix linux test
novacole Jan 17, 2025
ec7f3ef
attempt fix linux test - missing props file
novacole Jan 17, 2025
c2e8aad
attempt linux test fix - file path casing
novacole Jan 17, 2025
ccc3a72
Merge branch 'main' into dev/colecarter/rustsdk
novacole Jan 17, 2025
2b048f8
whitespace change, to rerun pipeline in an attempt to get license/cla…
novacole Jan 17, 2025
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
3 changes: 3 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@
<ItemGroup>
<PackageVersion Include="CopyOnWrite" Version="0.5.0" Condition=" '$(TargetFramework)' != 'net46' " />
<PackageVersion Include="Microsoft.Build" Version="$(MicrosoftBuildPackageVersion)" />
<PackageVersion Include="Microsoft.Build.Framework" Version="$(MicrosoftBuildPackageVersion)" />
<PackageVersion Include="Microsoft.Build.Tasks.Core" Version="$(MicrosoftBuildPackageVersion)" />
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildPackageVersion)" />
<PackageVersion Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="System.CodeDom" Version="8.0.0" />
<PackageVersion Include="System.Collections.Immutable" Version="8.0.0" />
<PackageVersion Include="System.Net.Http" Version="4.3.4" />

<!-- Suppress high vuln Component Governance alert. >8.0.4 breaks downlevel VS installations. VS team working to fix. -->
<!-- https://github.com/microsoft/MSBuildSdks/issues/591 -->
Expand Down
20 changes: 16 additions & 4 deletions MSBuildSdks.sln
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Build.CopyOnWrite
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Build.RunVSTest", "src\RunTests\Microsoft.Build.RunVSTest.csproj", "{B4CA4749-4CDE-499F-8372-C71966C6DB16}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Build.Cargo", "src\Cargo\Microsoft.Build.Cargo.csproj", "{D80866C1-FF2A-441B-984F-D256164BB56E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Build.Cargo.UnitTests", "src\Cargo.UnitTests\Microsoft.Build.Cargo.UnitTests.csproj", "{D6EF1644-D06C-4877-A8F7-3543E5D3175B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -144,14 +148,22 @@ Global
{153D1183-2953-4D4D-A5AD-AA2CF99B0DE3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{153D1183-2953-4D4D-A5AD-AA2CF99B0DE3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{153D1183-2953-4D4D-A5AD-AA2CF99B0DE3}.Release|Any CPU.Build.0 = Release|Any CPU
{B4CA4749-4CDE-499F-8372-C71966C6DB16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B4CA4749-4CDE-499F-8372-C71966C6DB16}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B4CA4749-4CDE-499F-8372-C71966C6DB16}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B4CA4749-4CDE-499F-8372-C71966C6DB16}.Release|Any CPU.Build.0 = Release|Any CPU
{AF9F2AFE-04D4-40B3-B17F-54ABD3DE7E4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF9F2AFE-04D4-40B3-B17F-54ABD3DE7E4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF9F2AFE-04D4-40B3-B17F-54ABD3DE7E4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF9F2AFE-04D4-40B3-B17F-54ABD3DE7E4E}.Release|Any CPU.Build.0 = Release|Any CPU
{B4CA4749-4CDE-499F-8372-C71966C6DB16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B4CA4749-4CDE-499F-8372-C71966C6DB16}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B4CA4749-4CDE-499F-8372-C71966C6DB16}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B4CA4749-4CDE-499F-8372-C71966C6DB16}.Release|Any CPU.Build.0 = Release|Any CPU
{D80866C1-FF2A-441B-984F-D256164BB56E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D80866C1-FF2A-441B-984F-D256164BB56E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D80866C1-FF2A-441B-984F-D256164BB56E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D80866C1-FF2A-441B-984F-D256164BB56E}.Release|Any CPU.Build.0 = Release|Any CPU
{D6EF1644-D06C-4877-A8F7-3543E5D3175B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D6EF1644-D06C-4877-A8F7-3543E5D3175B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6EF1644-D06C-4877-A8F7-3543E5D3175B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6EF1644-D06C-4877-A8F7-3543E5D3175B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
334 changes: 334 additions & 0 deletions src/Cargo.UnitTests/CargoTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,334 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Licensed under the MIT license.

using Microsoft.Build.Evaluation;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using Microsoft.Build.Graph;
using Microsoft.Build.UnitTests.Common;
using Microsoft.Build.Utilities.ProjectCreation;
using Shouldly;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Xunit;

namespace Microsoft.Build.Cargo.UnitTests
{
public class CargoTest : MSBuildSdkTestBase
{
private static readonly string ThisAssemblyDirectory = Path.GetDirectoryName(typeof(CustomProjectCreatorTemplates).Assembly.Location);

[Fact]
public void CanDisableCopyFilesMarkedCopyLocal()
{
ProjectCreator.Templates.CargoProject(
path: GetTempFileWithExtension(".cargoproj"))
.Property("SkipCopyFilesMarkedCopyLocal", bool.TrueString)
.ItemInclude("ReferenceCopyLocalPaths", Assembly.GetExecutingAssembly().Location)
.TryBuild("_CopyFilesMarkedCopyLocal", out bool result, out BuildOutput buildOutput);

result.ShouldBeTrue(buildOutput.GetConsoleLog());
}

[Theory]
[InlineData("BeforeCompile")]
[InlineData("AfterCompile")]
public void CompileIsExtensibleWithBeforeAfterTargets(string targetName)
{
ProjectCreator cargoProject = ProjectCreator.Templates.CargoProject(
path: Path.Combine(TestRootPath, "Cargo", "rust.cargoproj"))
.Target("CargoFetch")
.Target("CargoBuild")
.Target(targetName)
.TaskMessage("503CF1EBA6DC415F95F4DB630E7C1817", MessageImportance.High)
.Save();

cargoProject.TryBuild(restore: true, out bool result, out BuildOutput buildOutput);

result.ShouldBeTrue(buildOutput.GetConsoleLog());

buildOutput.Messages.High.ShouldContain("503CF1EBA6DC415F95F4DB630E7C1817", buildOutput.GetConsoleLog());
}

[Fact]
public void CoreCompileIsExtensibleWithCoreCompileDependsOn()
{
ProjectCreator cargoProject = ProjectCreator.Templates.CargoProject(
path: Path.Combine(TestRootPath, "Cargo", "rust.cargoproj"))
.Property("CoreCompileDependsOn", "$(CoreCompileDependsOn);TestThatCoreCompileIsExtensible")
.Target("CargoFetch")
.Target("CargoBuild")
.Target("TestThatCoreCompileIsExtensible")
.TaskMessage("35F1C217730445E0AC0F30E70F5C7826", MessageImportance.High)
.Save();

cargoProject.TryBuild(restore: true, out bool result, out BuildOutput buildOutput);

result.ShouldBeTrue(buildOutput.GetConsoleLog());

buildOutput.Messages.High.ShouldContain("35F1C217730445E0AC0F30E70F5C7826", buildOutput.GetConsoleLog());
}

[Fact]
public void CoreCompileIsExtensibleWithTargetsTriggeredByCompilation()
{
ProjectCreator cargoProject = ProjectCreator.Templates.CargoProject(
path: Path.Combine(TestRootPath, "Cargo", "rust.cargoproj"))
.Property("TargetsTriggeredByCompilation", "TestThatCoreCompileIsExtensible")
.Property("TargetsTriggeredByCompilation", "TestThatCoreCompileIsExtensible")
.Target("CargoFetch")
.Target("CargoBuild")
.Target("TestThatCoreCompileIsExtensible")
.TaskMessage("D031211C98F1454CA47A424ADC86A8F7", MessageImportance.High)
.Save();

cargoProject.TryBuild(restore: true, out bool result, out BuildOutput buildOutput);

result.ShouldBeTrue(buildOutput.GetConsoleLog());

buildOutput.Messages.High.ShouldContain("D031211C98F1454CA47A424ADC86A8F7", buildOutput.GetConsoleLog());
}

[Fact]
public void DoNotReferenceOutputAssemblies()
{
ProjectCreator projectA = ProjectCreator.Templates.SdkCsproj(
path: Path.Combine(TestRootPath, "ProjectA", "ProjectA.csproj"),
#if NETFRAMEWORK || NET8_0
targetFramework: "net8.0")
#elif NET9_0
targetFramework: "net9.0")
#endif
.Save();

ProjectCreator cargoProject = ProjectCreator.Templates.CargoProject(
path: Path.Combine(TestRootPath, "Cargo", "rust.cargoproj"))

.Target("CargoFetch")
.Target("CargoBuild")
.ItemProjectReference(projectA)
.Save();

cargoProject.TryRestore(out bool result, out BuildOutput buildOutput);

result.ShouldBeTrue(buildOutput.GetConsoleLog());
}

[Theory]
[InlineData(".cargoproj")]
public void ProjectContainsStaticGraphImplementation(string projectExtension)
{
ProjectCreator cargoProject = ProjectCreator.Templates.CargoProject(
path: GetTempFileWithExtension(projectExtension),
globalProperties: new Dictionary<string, string>
{
["IsGraphBuild"] = bool.TrueString,
},
customAction: creator =>
{
creator.Target("TakeAction", afterTargets: "Build")
.TaskMessage("86F00AF59170450E9D687652D74A6394", MessageImportance.High);
})
.Target("CargoFetch")
.Target("CargoBuild")
.Property("GenerateDependencyFile", "false")
.Save();

ICollection<ProjectItem> projectReferenceTargets = cargoProject.Project.GetItems("ProjectReferenceTargets");

TargetProtocolShouldContainValuesForTarget("Build");
TargetProtocolShouldContainValuesForTarget("Clean");
TargetProtocolShouldContainValuesForTarget("Rebuild");
TargetProtocolShouldContainValuesForTarget("Publish");

void TargetProtocolShouldContainValuesForTarget(string target)
{
IEnumerable<string> buildTargets =
projectReferenceTargets.Where(i => i.EvaluatedInclude.Equals(target, StringComparison.OrdinalIgnoreCase))
.Select(i => i.GetMetadata("Targets")?.EvaluatedValue)
.Where(t => !string.IsNullOrEmpty(t));

buildTargets.ShouldNotBeEmpty();
}
}

[Fact]
public void ProjectsCanDependOnEachOtherProjects()
{
ProjectCreator project1 = ProjectCreator.Templates.VcxProjProject(
path: Path.Combine(TestRootPath, "project1", "project1.vcxproj"))
.Target("GetTargetPath")
.Target("_GetCopyToOutputDirectoryItemsFromTransitiveProjectReferences")
.Save();

ProjectCreator project2 = ProjectCreator.Templates.CargoProject(
path: Path.Combine(TestRootPath, "project2", "project2.cargoproj"))
.Property("DesignTimeBuild", "true")
.Property("GenerateDependencyFile", "false")

.Target("_GetProjectReferenceTargetFrameworkProperties")
.Target("_GetCopyToOutputDirectoryItemsFromTransitiveProjectReferences")
.Target("CargoFetch")
.Target("CargoBuild")
.ItemProjectReference(project1)
.Save();

project2.TryBuild(out bool result, out BuildOutput buildOutput);

result.ShouldBeTrue(buildOutput.GetConsoleLog());
}

[Theory]
[InlineData("AutomaticallyUseReferenceAssemblyPackages", "true", "true")]
[InlineData("AutomaticallyUseReferenceAssemblyPackages", null, "false")]
[InlineData("DebugSymbols", "true", "false")]
[InlineData("DebugSymbols", null, "false")]
[InlineData("DebugType", "Full", "None")]
[InlineData("DebugType", null, "None")]
[InlineData("DisableFastUpToDateCheck", "false", "false")]
[InlineData("DisableFastUpToDateCheck", null, "true")]
[InlineData("DisableImplicitFrameworkReferences", "false", "false")]
[InlineData("DisableImplicitFrameworkReferences", null, "true")]
[InlineData("EnableDefaultCompileItems", "true", "true")]
[InlineData("EnableDefaultCompileItems", null, "false")]
[InlineData("EnableDefaultEmbeddedResourceItems", "true", "true")]
[InlineData("EnableDefaultEmbeddedResourceItems", null, "false")]
[InlineData("GenerateAssemblyInfo", "true", "true")]
[InlineData("GenerateAssemblyInfo", null, "false")]
[InlineData("GenerateMSBuildEditorConfigFile", "true", "true")]
[InlineData("GenerateMSBuildEditorConfigFile", null, "false")]
[InlineData("IncludeBuildOutput", "true", "true")]
[InlineData("IncludeBuildOutput", null, "false")]
[InlineData("NoCompilerStandardLib", "true", "true")]
[InlineData("NoCompilerStandardLib", null, "false")]
[InlineData("ProduceReferenceAssembly", "true", "false")]
[InlineData("ProduceReferenceAssembly", null, "false")]
[InlineData("SkipCopyBuildProduct", "false", "false")]
[InlineData("SkipCopyBuildProduct", null, "true")]
[InlineData("SkipCopyFilesMarkedCopyLocal", "false", "false")]
[InlineData("SkipCopyFilesMarkedCopyLocal", "true", "true")]
[InlineData("SkipCopyFilesMarkedCopyLocal", null, "")]
public void PropertiesHaveExpectedValues(string propertyName, string value, string expectedValue)
{
ProjectCreator.Templates.CargoProject(
path: GetTempFileWithExtension(".cargoproj"))
.Property(propertyName, value)

.Target("CargoFetch")
.Target("CargoBuild")
.Save()
.TryGetPropertyValue(propertyName, out string actualValue);

actualValue.ShouldBe(expectedValue, StringComparer.OrdinalIgnoreCase, customMessage: $"Property {propertyName} should have a value of \"{expectedValue}\" but its value was \"{actualValue}\"");
}

[Theory]
[InlineData(".cargoproj")]
public void PublishWithNoBuild(string projectExtension)
{
ProjectCreator.Templates.CargoProject(
path: GetTempFileWithExtension(projectExtension),
customAction: creator =>
{
creator
.Property("RuntimeIdentifier", "win-x64")
.Property("Platforms", "x64")
.Target("TakeAction", afterTargets: "Build")
.TaskMessage("2EA26E6FC5C842B682AA26096A769E07", MessageImportance.High);
})

.Target("CargoFetch")
.Target("CargoBuild")
.Save()
.TryBuild(restore: true, "Build", out bool buildResult, out BuildOutput buildOutput)
.TryBuild("Publish", new Dictionary<string, string> { ["NoBuild"] = "true" }, out bool publishResult, out BuildOutput publishOutput);

buildResult.ShouldBeTrue(buildOutput.GetConsoleLog());

buildOutput.Messages.High.ShouldContain("2EA26E6FC5C842B682AA26096A769E07");

publishResult.ShouldBeTrue(publishOutput.GetConsoleLog());

publishOutput.Messages.High.ShouldNotContain("2EA26E6FC5C842B682AA26096A769E07");
}

[Theory]
[InlineData(".cargoproj")]
public void SimpleBuild(string projectExtension)
{
ProjectCreator.Templates.CargoProject(
path: GetTempFileWithExtension(projectExtension),
projectCollection: new ProjectCollection(
new Dictionary<string, string>
{
["DesignTimeBuild"] = "true",
}),
customAction: creator =>
{
creator.Target("TakeAction", afterTargets: "Build")
.TaskMessage("86F00AF59170450E9D687652D74A6394", MessageImportance.High);
})
.Property("GenerateDependencyFile", "false")

.Target("CargoFetch")
.Target("CargoBuild")
.Save()
.TryBuild("Build", out bool result, out BuildOutput buildOutput);

result.ShouldBeTrue(buildOutput.GetConsoleLog());

buildOutput.Messages.High.ShouldContain("86F00AF59170450E9D687652D74A6394");
}

[Theory]
[InlineData(".cargoproj", "Build")]
[InlineData(".cargoproj", "Compile")]
[InlineData(".cargoproj", "CoreCompile")]
[InlineData(".msbuildproj", "Build")]
[InlineData(".msbuildproj", "Compile")]
[InlineData(".msbuildproj", "CoreCompile")]
public void SupportedTargetsExecute(string extension, string target)
{
Dictionary<string, string> globalProperties = new Dictionary<string, string>
{
["DesignTimeBuild"] = bool.TrueString,
};

bool result;
BuildOutput buildOutput;

using (ProjectCollection projectCollection = new ProjectCollection(globalProperties))
{
ProjectCreator.Create()
.Target("EnableIntermediateOutputPathMismatchWarning")
.Save(Path.Combine(TestRootPath, "Directory.Build.targets"));

ProjectCreator.Templates.CargoProject(
path: GetTempFileWithExtension(extension),
projectCollection: projectCollection)
.Property("GenerateDependencyFile", "false")

.Target("CargoFetch")
.Target("CargoBuild")
.Save()
.TryBuild(target, out result, out buildOutput);
}

result.ShouldBeTrue(buildOutput.GetConsoleLog());
}

[Fact]
public void UsingMicrosofCargoSdkValueSet()
{
ProjectCreator.Templates.CargoProject(
path: GetTempFileWithExtension(".cargoproj"))
.TryGetPropertyValue("UsingMicrosoftCargoSdk", out string propertyValue);

propertyValue.ShouldBe("true");
}
}
}
Loading