Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
37 changes: 31 additions & 6 deletions src/Microsoft.DotNet.CMake.Sdk/Microsoft.DotNet.CMake.Sdk.csproj
Original file line number Diff line number Diff line change
@@ -1,19 +1,44 @@
<Project Sdk="Microsoft.Build.NoTargets">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(NetToolCurrent)</TargetFramework>
<TargetFrameworks>$(NetToolCurrent);$(NetFrameworkToolCurrent)</TargetFrameworks>
<IsPackable>true</IsPackable>
<IsBuildTaskProject>true</IsBuildTaskProject>
<Description>Common toolset for calling into CMake from MSBuild and easily reference native assets from managed projects.</Description>
<PackageType>MSBuildSdk</PackageType>
<NoWarn>$(NoWarn);NU5128</NoWarn>
<NoWarn>$(NoWarn);NU5128;CS0649</NoWarn>
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>

<ItemGroup>
<None Include="**/*.props;**/*.targets"
<PackageReference Include="Microsoft.Build.Utilities.Core" />
<PackageReference Include="Microsoft.Build.Framework" />
<PackageReference Include="System.Text.Json" />
</ItemGroup>

<ItemGroup>
<Compile Include="src\**\*.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
<Compile Include="..\Common\Internal\AssemblyResolver.cs" />
<Compile Include="..\Common\Internal\AssemblyResolution.cs" />
<Compile Include="..\Common\Internal\BuildTask.Desktop.cs" />
<Reference Include="WindowsBase" />
</ItemGroup>

<ItemGroup>
<Compile Include="..\Common\Internal\BuildTask.cs" />
</ItemGroup>

<ItemGroup>
<None Include="build\**\*.props;build\**\*.targets"
Pack="true"
PackagePath="build\%(RecursiveDir)%(Filename)%(Extension)" />
<None Include="sdk\**\*.props;sdk\**\*.targets"
Pack="true"
PackagePath="%(RecursiveDir)%(Filename)%(Extension)" />
<None Include="$(RepoRoot)LICENSE.TXT;$(RepoRoot)THIRD-PARTY-NOTICES.TXT" Pack="true" PackagePath="%(Filename)%(Extension)" />
PackagePath="sdk\%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. -->
<Project DefaultTargets="Build">

<PropertyGroup>
<MicrosoftDotNetCMakeSdkTaskAssembly Condition="'$(MSBuildRuntimeType)' == 'Core'">$(MSBuildThisFileDirectory)..\tools\net\Microsoft.DotNet.CMake.Sdk.dll</MicrosoftDotNetCMakeSdkTaskAssembly>
<MicrosoftDotNetCMakeSdkTaskAssembly Condition="'$(MSBuildRuntimeType)' != 'Core'">$(MSBuildThisFileDirectory)..\tools\netframework\Microsoft.DotNet.CMake.Sdk.dll</MicrosoftDotNetCMakeSdkTaskAssembly>
</PropertyGroup>

<UsingTask TaskName="Microsoft.DotNet.CMake.Sdk.CreateCMakeFileApiQuery" AssemblyFile="$(MicrosoftDotNetCMakeSdkTaskAssembly)" />
<UsingTask TaskName="Microsoft.DotNet.CMake.Sdk.GetCMakeArtifactsFromFileApi" AssemblyFile="$(MicrosoftDotNetCMakeSdkTaskAssembly)" />

<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />

<PropertyGroup>
<VSWhereVersion Condition="'$(VSWhereVersion)' == ''">3.1.7</VSWhereVersion>
Copy link
Member

Choose a reason for hiding this comment

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

do we really need this? VSWhereVersion should always be defined by arcade SDK's DefaultVersions.props

Copy link
Member

Choose a reason for hiding this comment

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

@copilot remove this VSWhereVersion property.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in commit {short_hash}. Removed the redundant VSWhereVersion property since it's already defined by Arcade SDK's DefaultVersions.props.

</PropertyGroup>

<ItemGroup>
<PackageReference Include="vswhere" Version="$(VSWhereVersion)" IsImplicitlyDefined="true" GeneratePathProperty="true" />
</ItemGroup>
Expand Down Expand Up @@ -92,6 +104,12 @@
</ItemGroup>
</Target>

<Target Name="GetCMakeOutputDirProperty" Returns="$(CMakeOutputDir)">
</Target>

<Target Name="GetConfigurationProperty" Returns="$(Configuration)">
</Target>

<Target Name="_ResolveVSCompilerToolchainForNonVSGenerators"
Condition="$([MSBuild]::IsOsPlatform(Windows)) and !$(CMakeGenerator.StartsWith('Visual Studio')) and '$(CMakeCompilerToolchain)' == 'MSVC' and '$(CMakeCompilerSearchScript)' == ''">
<Error Condition="'$(_VSNativeCompilerComponentArchName)' == ''" Text="Unable to determine location of MSVC tools installed for the '$(Platform)' architecture." />
Expand Down Expand Up @@ -175,8 +193,14 @@
</PropertyGroup>
</Target>

<Target Name="CreateFileApiQuery"
DependsOnTargets="GetConfigScript"
BeforeTargets="Configure">
<CreateCMakeFileApiQuery CMakeOutputDir="$(CMakeOutputDir)" />
</Target>

<Target Name="Configure"
DependsOnTargets="GetConfigScript">
DependsOnTargets="GetConfigScript;CreateFileApiQuery">
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" Command="
$(CMakeCompilerSearchScript)
$(CMakeConfigScript)" />
Expand Down
101 changes: 90 additions & 11 deletions src/Microsoft.DotNet.CMake.Sdk/sdk/ProjectReference.targets
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. -->
<Project>

<PropertyGroup>
<MicrosoftDotNetCMakeSdkTaskAssembly Condition="'$(MSBuildRuntimeType)' == 'Core'">$(MSBuildThisFileDirectory)..\tools\net\Microsoft.DotNet.CMake.Sdk.dll</MicrosoftDotNetCMakeSdkTaskAssembly>
<MicrosoftDotNetCMakeSdkTaskAssembly Condition="'$(MSBuildRuntimeType)' != 'Core'">$(MSBuildThisFileDirectory)..\tools\netframework\Microsoft.DotNet.CMake.Sdk.dll</MicrosoftDotNetCMakeSdkTaskAssembly>
</PropertyGroup>

<UsingTask TaskName="Microsoft.DotNet.CMake.Sdk.GetCMakeArtifactsFromFileApi" AssemblyFile="$(MicrosoftDotNetCMakeSdkTaskAssembly)" />

<ItemDefinitionGroup>
<NativeProjectReference>
<CMakeProject></CMakeProject>
Expand Down Expand Up @@ -116,12 +123,6 @@
<Target Name="ConsolidateNativeProjectReference"
BeforeTargets="Build" >

<MSBuild Projects="%(NativeProjectReferenceNormalized.CMakeProject)"
Targets="GetOutputPathForProjectReference"
Properties="ReferencedCMakeLists=%(NativeProjectReferenceNormalized.Identity);%(NativeProjectReferenceNormalized.AdditionalProperties)">
<Output TaskParameter="TargetOutputs" ItemName="NativeProjectOutputFoldersToCopy" />
</MSBuild>

<ItemGroup>
<_NativeProjectReferenceToBuild Include="%(NativeProjectReferenceNormalized.CMakeProject)"
Condition="'%(NativeProjectReferenceNormalized.BuildNative)' == 'true'"
Expand All @@ -135,17 +136,95 @@
<MSBuild Projects="@(_UniqueNativeProjectReferenceToBuild)" />

<Message Text= "Full native project references are :%(NativeProjectReferenceNormalized.Identity)" />
<Message Text= "Native binaries will be copied from :%(NativeProjectOutputFoldersToCopy.Identity)" />

<MSBuild Projects="$(MSBuildProjectFile)"
Targets="CopyNativeProjectBinaries"
Properties="NativeProjectOutputFolder=%(NativeProjectOutputFoldersToCopy.Identity);
ReferencedCMakeProject=%(NativeProjectOutputFoldersToCopy.MSBuildSourceProjectFile);
IsMultiConfigurationGenerator=%(NativeProjectOutputFoldersToCopy.IsMultiConfigurationGenerator)"
Targets="CopyNativeProjectBinariesFromFileApi"
Properties="ReferencedCMakeLists=%(NativeProjectReferenceNormalized.Identity);
ReferencedCMakeProject=%(NativeProjectReferenceNormalized.CMakeProject);
%(NativeProjectReferenceNormalized.AdditionalProperties)"
Condition="'@(NativeProjectReference)' != ''" />

</Target>

<Target Name="CopyNativeProjectBinariesFromFileApi">
<!-- Get CMakeOutputDir from the CMake project -->
<MSBuild Projects="$(ReferencedCMakeProject)"
Targets="GetCMakeOutputDirProperty">
<Output TaskParameter="TargetOutputs" PropertyName="_CMakeOutputDir" />
</MSBuild>

<!-- Get Configuration from the CMake project -->
<MSBuild Projects="$(ReferencedCMakeProject)"
Targets="GetConfigurationProperty">
<Output TaskParameter="TargetOutputs" PropertyName="_Configuration" />
</MSBuild>

<PropertyGroup>
<_SourceDirectory>$([System.IO.Path]::GetDirectoryName($(ReferencedCMakeLists)))</_SourceDirectory>
</PropertyGroup>

<!-- Try to get artifacts from File API -->
<GetCMakeArtifactsFromFileApi
CMakeOutputDir="$(_CMakeOutputDir)"
SourceDirectory="$(_SourceDirectory)"
Configuration="$(_Configuration)">
<Output TaskParameter="Artifacts" ItemName="_FileApiArtifacts" />
</GetCMakeArtifactsFromFileApi>

<!-- If File API returned artifacts, use them. Otherwise fall back to old logic -->
<PropertyGroup>
<_UseFileApi Condition="'@(_FileApiArtifacts)' != ''">true</_UseFileApi>
</PropertyGroup>

<ItemGroup Condition="'$(_UseFileApi)' == 'true'">
<NativeProjectBinaries Include="@(_FileApiArtifacts)" />
</ItemGroup>

<Message Text="Using CMake File API to locate artifacts" Condition="'$(_UseFileApi)' == 'true'" />
<Message Text="File API not available, falling back to legacy path detection" Condition="'$(_UseFileApi)' != 'true'" />

<!-- Fall back to old logic if File API didn't work -->
<MSBuild Projects="$(ReferencedCMakeProject)"
Targets="GetOutputPathForProjectReference"
Properties="ReferencedCMakeLists=$(ReferencedCMakeLists)"
Condition="'$(_UseFileApi)' != 'true'">
<Output TaskParameter="TargetOutputs" ItemName="_LegacyOutputFolder" />
</MSBuild>

<PropertyGroup Condition="'$(_UseFileApi)' != 'true'">
<_LegacyOutputPath>%(_LegacyOutputFolder.Identity)</_LegacyOutputPath>
<_IsMultiConfigurationGenerator>%(_LegacyOutputFolder.IsMultiConfigurationGenerator)</_IsMultiConfigurationGenerator>
</PropertyGroup>

<MSBuild Projects="$(MSBuildProjectFile)"
Targets="CopyNativeProjectBinaries"
Properties="NativeProjectOutputFolder=$(_LegacyOutputPath);
ReferencedCMakeProject=$(ReferencedCMakeProject);
IsMultiConfigurationGenerator=$(_IsMultiConfigurationGenerator)"
Condition="'$(_UseFileApi)' != 'true'" />

<!-- Copy the binaries from File API if we have them -->
<ItemGroup Condition="'$(_UseFileApi)' == 'true'">
<_ArtifactsToCopy Include="@(NativeProjectBinaries)" Condition="Exists('%(Identity)')" />
</ItemGroup>

<Copy
SourceFiles="@(_ArtifactsToCopy)"
DestinationFiles="@(_ArtifactsToCopy -> '$(OutDir)%(Filename)%(Extension)')"
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
Retries="$(CopyRetryCount)"
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
Condition="'$(_UseFileApi)' == 'true'">
<Output TaskParameter="DestinationFiles" ItemName="FileWrites" />
</Copy>

<ItemGroup Condition="'$(_UseFileApi)' == 'true'">
<FileWrites Include="@(_ArtifactsToCopy -> '$(OutDir)%(Filename)%(Extension)')" />
</ItemGroup>
</Target>

<Target Name="CopyAllNativeProjectReferenceBinaries" DependsOnTargets="ResolveCMakeNativeProjectReference;ConsolidateNativeProjectReference" />

</Project>
45 changes: 45 additions & 0 deletions src/Microsoft.DotNet.CMake.Sdk/src/CreateCMakeFileApiQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System;
using System.IO;

namespace Microsoft.DotNet.CMake.Sdk
{
/// <summary>
/// Creates a CMake File API query file to request codemodel information.
/// </summary>
public class CreateCMakeFileApiQuery : Task
{
/// <summary>
/// The CMake build output directory where the query should be created.
/// </summary>
[Required]
public string CMakeOutputDir { get; set; }

public override bool Execute()
{
try
{
string queryDir = Path.Combine(CMakeOutputDir, ".cmake", "api", "v1", "query");
Directory.CreateDirectory(queryDir);

string queryFile = Path.Combine(queryDir, "codemodel-v2");

// Create an empty file to request codemodel-v2 information
File.WriteAllText(queryFile, string.Empty);

Log.LogMessage(MessageImportance.Low, $"Created CMake File API query at: {queryFile}");

return true;
}
catch (Exception ex)
{
Log.LogErrorFromException(ex);
return false;
}
}
}
}
Loading