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
40 changes: 34 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,47 @@
<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" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
<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,6 +1,14 @@
<!-- 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" />

<ItemGroup>
Expand Down Expand Up @@ -92,6 +100,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 +189,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
142 changes: 57 additions & 85 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 All @@ -11,80 +18,6 @@
<MSBuild Projects="%(NativeProjectReferenceNormalized.CMakeProject)" Targets="Restore" RemoveProperties="RestoreGraphProjectInput" />
</Target>

<Target Name="CopyNativeProjectBinaries">
<ItemGroup Condition="'$(IsMultiConfigurationGenerator)' == 'true'">
<NativeProjectBinaries Include="$(NativeProjectOutputFolder)\*.*" />
</ItemGroup>
<ItemGroup Condition="'$(IsMultiConfigurationGenerator)' != 'true'">

<!-- ############################################################### -->
<!-- The following is required because the single configuration -->
<!-- generators, unlike multi-configuration generators, -->
<!-- do not place the binaries built into a separate -->
<!-- Debug/Checked/Release directory. Therefore we must filter -->
<!-- the folder to only include dynamic libraries, static libraries -->
<!-- and executables. -->
<!-- -->
<!-- Please take care when modifying the following lines of code. -->
<!-- ############################################################### -->

<!-- Include everything and then filter. -->
<NativeProjectBinariesMatched Include="$(NativeProjectOutputFolder)\*.*" />

<!-- Filter executables on unix -->
<NativeProjectBinariesExeFilter Condition="'%(Extension)' == ''" Include="@(NativeProjectBinariesMatched)" />

<!-- Filter executables on Windows -->
<NativeProjectBinariesExeFilter Condition="'%(Extension)' == '.exe'" Include="@(NativeProjectBinariesMatched)" />

<!-- Filter out the *Make* files -->
<NativeProjectBinariesExeFilterRemovedMakeFile Condition="'%(FileName)' != 'Makefile'" Include="@(NativeProjectBinariesExeFilter)" />

<!-- Filter .dylib files for OSX -->
<NativeProjectBinariesDyLibFilter Condition="'%(Extension)' == '.dylib'" Include="@(NativeProjectBinariesMatched)" />

<!-- Filter .so files for Linux -->
<NativeProjectBinariesDyLibFilter Condition="'%(Extension)' == '.so'" Include="@(NativeProjectBinariesMatched)" />

<!-- Filter static lib files for Unix -->
<NativeProjectBinariesStaticLibFilter Condition="'%(Extension)' == '.a'" Include="@(NativeProjectBinariesMatched)" />

<!-- Filter dynamic lib files for Windows -->
<NativeProjectBinariesDyLibFilter Condition="'%(Extension)' == '.dll'" Include="@(NativeProjectBinariesMatched)" />

<!-- Filter symbol files for Windows -->
<NativeProjectsBinariesSymbolsFilter Condition="'%(Extension)' == '.pdb'" Include="@(NativeProjectBinariesMatched)" />

<!-- Filter static lib files for Windows -->
<NativeProjectBinariesStaticLibFilter Condition="'%(Extension)' == '.lib'" Include="@(NativeProjectBinariesMatched)" />

<!-- Merge the filtered lists -->
<NativeProjectBinaries Include="@(NativeProjectBinariesExeFilterRemovedMakeFile)" />
<NativeProjectBinaries Include="@(NativeProjectBinariesDyLibFilter)" />
<NativeProjectBinaries Include="@(NativeProjectBinariesStaticLibFilter)" />
<NativeProjectBinaries Include="@(NativeProjectsBinariesSymbolsFilter)" />

</ItemGroup>

<Error Text="The native project files are missing in '$(NativeProjectOutputFolder)'. Please build '$(ReferencedCMakeProject)' at least once."
Condition="'@(NativeProjectBinaries)' == ''" />

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

<ItemGroup>
<FileWrites Include="@(NativeProjectBinaries -> '$(OutDir)%(Filename)%(Extension)')" />
</ItemGroup>
</Target>

<Target Name="NormalizeNativeProjectReferences"
Condition="'@(NativeProjectReference)' != ''"
BeforeTargets="ConsolidateNativeProjectReference" >
Expand Down Expand Up @@ -116,12 +49,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 +62,62 @@
<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>

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

<!-- Copy the binaries -->
<ItemGroup>
<_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)">
<Output TaskParameter="DestinationFiles" ItemName="FileWrites" />
</Copy>

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

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

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

using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace Microsoft.DotNet.CMake.Sdk
{
/// <summary>
/// C# object models for the CMake File API.
/// These types represent a subset of the CMake File API that we use for discovering build artifacts.
///
/// For the full CMake File API specification, see:
/// https://cmake.org/cmake/help/latest/manual/cmake-file-api.7.html
///
/// Specifically, we use:
/// - Index file: https://cmake.org/cmake/help/latest/manual/cmake-file-api.7.html#index-file
/// - Codemodel object (v2): https://cmake.org/cmake/help/latest/manual/cmake-file-api.7.html#codemodel-version-2
/// </summary>

internal sealed class CMakeFileApiIndex
{
public CMakeFileApiIndexReply Reply { get; set; }
}

internal sealed class CMakeFileApiIndexReply
{
[JsonPropertyName("client-Microsoft.DotNet.CMake.Sdk")]
public CMakeFileApiClientReply ClientReply { get; set; }
}

internal sealed class CMakeFileApiClientReply
{
[JsonPropertyName("codemodel-v2")]
public CMakeFileApiIndexCodeModel CodemodelV2 { get; set; }
}

internal sealed class CMakeFileApiIndexCodeModel
{
public string JsonFile { get; set; }
}

internal sealed class CMakeCodeModel
{
public CMakeCodeModelPaths Paths { get; set; }
public List<CMakeConfiguration> Configurations { get; set; }
}

internal sealed class CMakeCodeModelPaths
{
public string Source { get; set; }
public string Build { get; set; }
}

internal sealed class CMakeConfiguration
{
public string Name { get; set; }
public List<CMakeDirectory> Directories { get; set; }
public List<CMakeTarget> Targets { get; set; }
}

internal sealed class CMakeDirectory
{
public string Source { get; set; }
public string Build { get; set; }
public List<int> TargetIndexes { get; set; }
}

internal sealed class CMakeTarget
{
public string Name { get; set; }
public string JsonFile { get; set; }
}

internal sealed class CMakeTargetDetails
{
public List<CMakeArtifact> Artifacts { get; set; }
}

internal sealed class CMakeArtifact
{
public string Path { get; set; }
}
}
Loading
Loading