From 92ef12fd95af8615205592c61ac9f672a0751c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Wed, 24 Jun 2026 13:49:46 +0100 Subject: [PATCH 1/2] Re-host MDP pipeline as single GenerateNanoPeFile target - Collapse 3 MetaDataProcessorTask calls into one GenerateNanoPeFile target (AfterTargets=CoreCompile); regular/core split in properties. - Replace *DependsOn chain redefinitions with appends; drop _NanoCopyAssemblyToOutDir; rewire output/copy targets via AfterTargets. - Add Inputs/Outputs for incrementality; surface NativeChecksum as $(NanoNativeMethodsChecksum) via dedicated NanoReportChecksum target. - Gate NanoGenerateBinaryOutput on NanoIsCoreLibrary != True (match legacy). - Fix dead core "no-stubs" branch; dump-exports, dependency-map and strings now actually emitted for core builds. - Drop undefined _NanoMdpStub* params and empty Dat/DependencyMap placeholder targets. - SmokeTest: add NativeLibrary.cs InternalCall fixture, AllowUnsafeBlocks, AssemblyNativeVersion, and _NanoMdpGenerateStubs. Assisted by Claude Opus 4.8 --- .gitignore | 1 + .../Sdk/nanoFramework.Mdp.targets | 243 +++++++----------- .../Sdk/nanoFramework.Output.targets | 85 +++--- test/SmokeTest/AssemblyInfo.cs | 6 + test/SmokeTest/HelloNano.cs | 5 +- test/SmokeTest/NativeLibrary.cs | 34 +++ test/SmokeTest/SmokeTest.csproj | 5 + 7 files changed, 198 insertions(+), 181 deletions(-) create mode 100644 test/SmokeTest/AssemblyInfo.cs create mode 100644 test/SmokeTest/NativeLibrary.cs diff --git a/.gitignore b/.gitignore index b844a83..d0699af 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,4 @@ TestResult.xml ## macOS .DS_Store +test/SmokeTest/Stubs diff --git a/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Mdp.targets b/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Mdp.targets index 9148e62..b618d88 100644 --- a/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Mdp.targets +++ b/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Mdp.targets @@ -13,15 +13,28 @@ Imported from Sdk.targets AFTER the Microsoft.NET.Sdk targets import, so that $(TargetName), $(TargetDir), $(IntermediateOutputPath) and the standard build - targets (Compile, ResolveReferences, ...) are available for the MDP properties - and targets below. + targets (CoreCompile, ResolveReferences, ...) are available for the MDP + properties and targets below. Holds: - the auto-injected MDP PackageReference + NanoMdpVersion default, - the MDP property defaults (verbosity, NanoIsCoreLibrary-driven switches), - the _NanoMdpTasksTfm / task-DLL resolution and UsingTask declarations, - - the build pipeline overrides + all MDP / copy / clean / resource / binary - output targets that produce the .pe / .pdbx / resources. + - the single GenerateNanoPeFile target that emits the .pe / .pdbx (and, for + core assemblies, the stubs / dump-exports / dependency-map / strings). + + Ordering strategy (see GenerateNanoPeFile): the PE stage is hooked with + AfterTargets="CoreCompile" rather than by redefining Microsoft's + *DependsOn chains. We only *append* to the standard chains (never replace + them), so the SDK stays robust to Microsoft.NET.Sdk changes: + + ResolveReferences -> CoreCompile -> GenerateNanoPeFile (.pe/.pdbx) + | + NanoGenerateBinaryOutput / NanoReportChecksum + | + CopyFilesToOutputDirectory -> NanoCopyOutputFiles + + The binary-output / copy / clean targets live in nanoFramework.Output.targets. Import paths use $(MSBuildThisFileDirectory) so they resolve inside the packed SDK. --> @@ -74,14 +87,12 @@ - <_NanoMdpGeneratePe Condition="'$(_NanoMdpGeneratePe)' == ''">true <_NanoMdpDumpMetadata Condition="'$(_NanoMdpDumpMetadata)' == ''">true <_NanoMdpGenerateStubs Condition="'$(_NanoMdpGenerateStubs)' == ''">true <_NanoMdpGenerateDatFiles Condition="'$(_NanoMdpGenerateDatFiles)' == ''">true <_NanoMdpGenerateXmlFiles Condition="'$(_NanoMdpGenerateXmlFiles)' == ''">true - <_NanoMdpGeneratePe Condition="'$(_NanoMdpGeneratePe)' == ''">false <_NanoMdpDumpMetadata Condition="'$(_NanoMdpDumpMetadata)' == ''">false <_NanoMdpGenerateStubs Condition="'$(_NanoMdpGenerateStubs)' == ''">false <_NanoMdpGenerateDatFiles Condition="'$(_NanoMdpGenerateDatFiles)' == ''">false @@ -140,185 +151,101 @@ - + + + + + + + + + - - Compile;_NanoCopyAssemblyToOutDir - - - BuildOnlySettings; - PrepareForBuild; - PreBuildEvent; - ResolveReferences; - PrepareResources; - ResolveKeySource; - Compile; - GenerateSerializationAssemblies; - CreateSatelliteAssemblies; - GetTargetPath; - PrepareForRun; - IncrementalClean; - NanoMetadataProcessor; - PostBuildEvent - - - - NanoMetadataProcessor; - CopyFilesToOutputDirectory; - NanoCopyOutputFiles; - _NanoCopyReferencesToIntermediate - + + <_NanoMdpParseInput>$(ProjectDir)$(IntermediateOutputPath)$(TargetFileName) + <_NanoMdpCompileOutput>$(_NanoIntermediateAssembly).pe + <_NanoMdpCompileOutputNoExt>$(_NanoIntermediateAssembly) - - PrepareResourceNames; - ResGen; - CompileLicxFiles; - NanoGenerateResources - + + <_NanoMdpStubSkeletonProject Condition="'$(_NanoMdpStubSkeletonProject)' == ''">$(NanoGenerateSkeletonProjectName) + <_NanoMdpStubSkeletonName Condition="'$(_NanoMdpStubSkeletonName)' == ''">$(NanoGenerateStubsRootName) + <_NanoMdpStubSkeletonFile Condition="'$(_NanoMdpStubSkeletonFile)' == ''">$(NanoGenerateSkeletonFile) + - - BeforeResolveReferences; - ResolveProjectReferences; - ResolveAssemblyReferences; - ResolveRuntimeDependencies; - AfterResolveReferences - + + + <_NanoMdpStubSkeletonWithoutInterop Condition="'$(_NanoMdpStubSkeletonWithoutInterop)' == ''">false - - - + - $(CoreBuildDependsOn);NanoMetadataProcessorCompile - $(PrepareResourcesDependsOn);NanoGenerateResources - $(CleanDependsOn);_NanoCleanExtraFiles - $(ResolveReferencesDependsOn);ResolveRuntimeDependencies - $(CoreBuildDependsOn);_NanoCreateDatabaseAndDependencyMap - <_NanoMdpGenerateStubs>true - - <_NanoMdpParseInput>$(ProjectDir)$(IntermediateOutputPath)$(TargetFileName) - <_NanoMdpCompileOutput>$(ProjectDir)$(IntermediateOutputPath)$(TargetName).pe - <_NanoMdpCompileOutputNoExt>$(ProjectDir)$(IntermediateOutputPath)$(TargetName) + <_NanoMdpStubSkeletonWithoutInterop Condition="'$(_NanoMdpStubSkeletonWithoutInterop)' == ''">true <_NanoMdpSaveStringsFile>$(ProjectDir)$(IntermediateOutputPath)$(TargetName).strings <_NanoMdpDumpExportsFile>$(ProjectDir)$(IntermediateOutputPath)$(TargetName)_exports.txt <_NanoMdpDependencyMapFile>$(ProjectDir)$(IntermediateOutputPath)$(TargetName)_dependency_map.xml - <_NanoMdpStubSkeletonName>$(AssemblyName) - <_NanoMdpStubResolve>true - + + + + - - - - <_NanoMdpStubSkeletonProject>$(NanoGenerateSkeletonProjectName) - <_NanoMdpStubSkeletonName>$(NanoGenerateStubsRootName) - <_NanoMdpStubSkeletonFile>$(NanoGenerateSkeletonFile) - <_NanoMdpStubSkeletonWithoutInterop>false - - - - - - - - - - - - - + + $(ResolveReferencesDependsOn);ResolveRuntimeDependencies + $(PrepareResourcesDependsOn);NanoGenerateResources + + + $(CleanDependsOn);_NanoCleanExtraFiles + - + + + + + + + + + - + - - <_NanoMdpStubSkeletonProject Condition="'$(_NanoMdpStubSkeletonProject)' == ''">$(NanoGenerateSkeletonProjectName) - <_NanoMdpStubSkeletonName Condition="'$(_NanoMdpStubSkeletonName)' == ''">$(NanoGenerateStubsRootName) - <_NanoMdpStubSkeletonFile Condition="'$(_NanoMdpStubSkeletonFile)' == ''">$(NanoGenerateSkeletonFile) - <_NanoMdpStubSkeletonWithoutInterop>true - - - - - - - - - + LoadHints="@(ReferencePath);@(ReferenceDependencyPaths);@(ReferenceSatellitePaths)" + ImportResources="@(_NanoResources)"> - + - - - - - - - + + + + - - - - - @@ -331,4 +258,20 @@ StartProgramReferences="@(_NanoStartProgramResolvedFiles);@(_NanoStartProgramResolvedDependencyFiles)" /> + + + + + + + + + + + + + + + + diff --git a/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Output.targets b/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Output.targets index 1e7621d..c806976 100644 --- a/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Output.targets +++ b/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Output.targets @@ -11,15 +11,22 @@ Incorrect changes will break .NET nanoFramework project builds. ******************************************************************************** - Produces the deployable binary (GenerateBinaryOutputTask), copies the .pe / - .pdbx artifacts between the intermediate and output directories, and cleans - the generated nanoFramework files. These run after the MetadataProcessor has - emitted the .pe. + Produces the deployable binary (GenerateBinaryOutputTask), surfaces the native + methods checksum, copies the .pe / .pdbx artifacts to the output directory, and + cleans the generated nanoFramework files. + + Ordering (hooked via AfterTargets, see nanoFramework.Mdp.targets): + GenerateNanoPeFile (.pe / .pdbx in intermediate dir) + -> NanoGenerateBinaryOutput (deployable .bin; runs BEFORE the + standard copy so a library's OutDir + .dll is left intact afterwards) + -> NanoReportChecksum (surface $(NanoNativeMethodsChecksum)) + CopyFilesToOutputDirectory (Microsoft.NET.Sdk) + -> NanoCopyOutputFiles (.pe / .pdbx -> OutDir) + -> _NanoCopyReferencesToIntermediate Imported by Sdk.targets AFTER nanoFramework.Mdp.targets, which defines the - shared $(_NanoBuildTasksDir) and $(_Nano*) properties used below and - wires these targets into the build pipeline (PrepareForRunDependsOn, - CleanDependsOn) and the NanoMetadataProcessor* targets (via CallTarget). + shared $(_NanoBuildTasksDir) and $(_Nano*) properties used below. --> @@ -31,25 +38,46 @@ AssemblyFile="$(NF_MSBUILDTASK_PATH)\nanoFramework.Tools.BuildTasks.dll" /> - + + + + + + - - - + + + + - + + + + - - - - + + + - + + + + @@ -72,7 +100,9 @@ - + @@ -81,21 +111,16 @@ - + - - - - + + + - diff --git a/test/SmokeTest/AssemblyInfo.cs b/test/SmokeTest/AssemblyInfo.cs new file mode 100644 index 0000000..88e487a --- /dev/null +++ b/test/SmokeTest/AssemblyInfo.cs @@ -0,0 +1,6 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Reflection; + +[assembly: AssemblyNativeVersion("1.0.0.0")] diff --git a/test/SmokeTest/HelloNano.cs b/test/SmokeTest/HelloNano.cs index ae91bf3..383f7c4 100644 --- a/test/SmokeTest/HelloNano.cs +++ b/test/SmokeTest/HelloNano.cs @@ -1,4 +1,7 @@ -namespace SmokeTest +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace SmokeTest { public class HelloNano { diff --git a/test/SmokeTest/NativeLibrary.cs b/test/SmokeTest/NativeLibrary.cs new file mode 100644 index 0000000..be013c5 --- /dev/null +++ b/test/SmokeTest/NativeLibrary.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; + +namespace SmokeTest +{ + internal class NativeLibrary + { + public void Method() + { + NativeMethod(); + + byte a = 0; + ushort b = 0; + NativeMethodWithReferenceParameters(ref a, ref b); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern void NativeMethod(); + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern void NativeMethodWithReferenceParameters(ref byte refByteParam, ref ushort refUshortParam); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void NativeStaticMethod(); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern byte NativeStaticMethodReturningByte(char charParam); + + [MethodImpl(MethodImplOptions.InternalCall)] + public extern unsafe void MethodWithPointerParm(void* pointer, int length); + } +} diff --git a/test/SmokeTest/SmokeTest.csproj b/test/SmokeTest/SmokeTest.csproj index 1161733..9594137 100644 --- a/test/SmokeTest/SmokeTest.csproj +++ b/test/SmokeTest/SmokeTest.csproj @@ -4,6 +4,11 @@ Library SmokeTest SmokeTest + true + + + + <_NanoMdpGenerateStubs>true From f41f128917929fd42ddea344fccd0a928fe4fb9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Wed, 24 Jun 2026 14:10:10 +0100 Subject: [PATCH 2/2] Adressing code review --- .../Sdk/nanoFramework.Mdp.targets | 27 ++++++++++++++++++- .../Sdk/nanoFramework.Output.targets | 25 ++++++++++++----- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Mdp.targets b/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Mdp.targets index b618d88..9555b0d 100644 --- a/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Mdp.targets +++ b/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Mdp.targets @@ -185,6 +185,14 @@ <_NanoMdpDependencyMapFile>$(ProjectDir)$(IntermediateOutputPath)$(TargetName)_dependency_map.xml + + + <_NanoMdpStubMainHeader Condition="'$(_NanoMdpGenerateStubs)' == 'true'">$(_NanoMdpStubSkeletonFile)\$(NanoGenerateStubsRootName).h + + @@ -215,7 +223,7 @@ AfterTargets="CoreCompile" DependsOnTargets="ResolveReferences;ResolveRuntimeDependencies;NanoGenerateResources" Inputs="$(_NanoMdpParseInput);@(ReferencePath);@(ReferenceDependencyPaths);@(_NanoResources)" - Outputs="$(_NanoMdpCompileOutput);$(_NanoMdpCompileOutputNoExt).pdbx"> + Outputs="$(_NanoMdpCompileOutput);$(_NanoMdpCompileOutputNoExt).pdbx;$(_NanoMdpDumpExportsFile);$(_NanoMdpDependencyMapFile);$(_NanoMdpSaveStringsFile);$(_NanoMdpStubMainHeader)"> + + + + + + + + diff --git a/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Output.targets b/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Output.targets index c806976..9e3cde1 100644 --- a/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Output.targets +++ b/src/nanoFramework.NET.Sdk/Sdk/nanoFramework.Output.targets @@ -50,7 +50,7 @@ Condition="'$(DisableNanoMdp)' != 'true' and '$(NanoIsCoreLibrary)' != 'True'" DependsOnTargets="ResolveReferences"> @@ -59,16 +59,27 @@ - - - + + + + + + + - + + + + + <_NanoNativeMethodsChecksumPersisted>@(_NanoChecksumLines) + + -