Skip to content

Commit

Permalink
New ilm0 logic to fix other possible errors with PDB + Pre-Proc
Browse files Browse the repository at this point in the history
+ Fixed DllExportFilesToPublish for MSBuild (VS is ok)
+ Fallback for DllExport.bat 1.7.4(and older) that rely on hMSBuild.bat (modern contains built-in)
  • Loading branch information
3F committed Dec 17, 2024
1 parent 3af5534 commit 61420e8
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 60 deletions.
56 changes: 40 additions & 16 deletions .tools/net.r_eg.DllExport.targets
Original file line number Diff line number Diff line change
Expand Up @@ -49,33 +49,45 @@
<DllExportAttributeFullName Condition="'$(DllExportNamespace)'!=''">$(DllExportNamespace).$(DllExportMetaLibAttr)</DllExportAttributeFullName>
<DllExportAttributeFullName Condition="'$(DllExportNamespace)'==''">$(DllExportMetaLibAttr)</DllExportAttributeFullName>

<DllExportDefPlatform>$(PlatformTarget)</DllExportDefPlatform>
<DllExportDefPlatform Condition="'$(DllExportDefPlatform)'==''">AnyCPU</DllExportDefPlatform>
<DllExportDefPlatform>$(PlatformTarget.ToLower())</DllExportDefPlatform>
<DllExportDefPlatform Condition="'$(DllExportDefPlatform)'==''">anycpu</DllExportDefPlatform>
</PropertyGroup>

<PropertyGroup>
<DllExportCopyToPublishDirectoryType Condition="'$(DllExportCopyToPublishDirectoryType)'==''">PreserveNewest</DllExportCopyToPublishDirectoryType>
</PropertyGroup>
<ItemGroup Condition="'$(DllExportResolvePublish)'!='false'">

<!-- https://github.com/3F/DllExport/issues/224#issuecomment-1546883382 -->
<DllExportFilesToPublish
Include="$(TargetDir)x86\*.*;$(TargetDir)x64\*.*"
PlatformDir="$([System.IO.Directory]::GetParent(%(DllExportFilesToPublish.Directory)).Name)\" />
<ResolvedFileToPublish Include="@(DllExportFilesToPublish)" RelativePath="%(PlatformDir)%(Filename)%(Extension)" CopyToPublishDirectory="$(DllExportCopyToPublishDirectoryType)" />
<Target Condition="'$(DllExportResolvePublish)'!='false' and '$(DllExportDefPlatform)'=='anycpu'"
Name="DllExportComputeResolvedFilesToPublishList"
BeforeTargets="ComputeResolvedFilesToPublishList">
<ItemGroup>
<!-- Regarding my old solution from https://github.com/3F/DllExport/issues/224#issuecomment-1546883382
either wildcards (*) is only ok for Visual Studio but problematic when building directly in MSBuild (empty Include) because yeah at that stage paths are not ready to be resolved;
or requires ::GetParent() workaround to use inside Targets like this.
-->
<DllExportFilesToPublish Include="$(TargetDir)x86\*" PlatformDir="x86\" />
<DllExportFilesToPublish Include="$(TargetDir)x64\*" PlatformDir="x64\" />
<ResolvedFileToPublish Include="@(DllExportFilesToPublish)" RelativePath="%(PlatformDir)%(Filename)%(Extension)"
CopyToPublishDirectory="$(DllExportCopyToPublishDirectoryType)" />
</ItemGroup>
</Target>

<!-- F-262, for a single platform -->
<ResolvedFileToPublish Condition="'$(DllExportResolvePublishForSingle)'!='false'"
Include="$(TargetPath)" RelativePath="%(Filename)%(Extension)" CopyToPublishDirectory="$(DllExportCopyToPublishDirectoryType)" />
<!-- F-262, for a single platform -->
<ItemGroup Condition="'$(DllExportResolvePublish)'!='false' And '$(DllExportDefPlatform)'!='anycpu' And '$(DllExportResolvePublishForSingle)'!='false'">
<ResolvedFileToPublish Include="$(TargetPath)" RelativePath="%(Filename)%(Extension)"
CopyToPublishDirectory="$(DllExportCopyToPublishDirectoryType)" />

<ResolvedFileToPublish Include="$(TargetDir)$(TargetName).pdb" RelativePath="%(Filename)%(Extension)"
CopyToPublishDirectory="$(DllExportCopyToPublishDirectoryType)" />
</ItemGroup>
<!-- fallback -->
<Target Condition="'$(DllExportResolvePublish)'!='false' And '$(DllExportResolvePublishForSingle)'!='false'"
Name="DllExportComputeResolvedFilesToPublishList"
BeforeTargets="ComputeResolvedFilesToPublishList">
Name="DllExportComputeResolvedFilesToPublishListFallback"
BeforeTargets="ComputeResolvedFilesToPublishList"
AfterTargets="DllExportComputeResolvedFilesToPublishList">

<PropertyGroup>
<CopyBuildOutputToPublishDirectory>false</CopyBuildOutputToPublishDirectory>
<CopyOutputSymbolsToPublishDirectory>false</CopyOutputSymbolsToPublishDirectory>
</PropertyGroup>

<!-- TODO: tl;dr @(IntermediateAssembly) includes the build product (.dll or .exe); so... do we have other cases where this is really necessary? -->
Expand All @@ -87,11 +99,23 @@
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</ResolvedFileToPublish>
</ItemGroup>
<!-- .pdb -->
<ItemGroup Condition="'$(DllExportFallbackDontCopyOutputSymbolsToPublishDirectory)'!='false' And '$(CopyOutputSymbolsToPublishDirectory)'=='false'">
<DllExportDebugSymbolsIntermediatePathResolvedFileToPublish Include="@(_DebugSymbolsIntermediatePath)" Condition="'%(Filename)'!='$(TargetName)'" />

<ResolvedFileToPublish Include="@(DllExportDebugSymbolsIntermediatePathResolvedFileToPublish)">
<RelativePath>@(DllExportDebugSymbolsIntermediatePathResolvedFileToPublish->'%(Filename)%(Extension)')</RelativePath>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<ExcludeFromSingleFile Condition="'$(IncludeSymbolsInSingleFile)'!='true'">true</ExcludeFromSingleFile>
</ResolvedFileToPublish>
</ItemGroup>
</Target>

<Target Condition="'$(DllExportRefreshObj)'=='true'" Name="DllExportRefreshObjTarget" AfterTargets="DllExportMod">
<Copy SourceFiles="$(TargetPath)" DestinationFiles="$(IntermediateOutputPath)$(TargetFileName)"
<Target Condition="'$(DllExportRefreshObj)'=='true'" Name="DllExportRefreshObjTarget" BeforeTargets="ComputeResolvedFilesToPublishList">
<Copy SourceFiles="$(TargetPath)" DestinationFolder="$(IntermediateOutputPath)"
OverwriteReadOnlyFiles="true" SkipUnchangedFiles="true" />

<Copy SourceFiles="$(TargetDir)$(TargetName).pdb" DestinationFolder="$(IntermediateOutputPath)"
OverwriteReadOnlyFiles="true" SkipUnchangedFiles="true" />
</Target>

Expand Down
3 changes: 3 additions & 0 deletions .vssbe
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,9 @@
"#[IO copy.file({\".tools/*.nuspec\", \".tools/.pkg.*.txt\"}, \"$(odir)/\", true)]",
"#[IO replace(\"$(odir)/DllExport.nuspec\", \"$-version-$\", \"$(pVerRel)\")]",
"",
"Fallback for DllExport.bat 1.7.4(and older) that rely on hMSBuild.bat (modern contains built-in)",
"#[IO copy.file(\".tools\\hMSBuild.bat\", \"$(odir)/\", true)]",
"",
"#[IO copy.file(",
"{",
" \"$(OutDir:Core)*.*\",",
Expand Down
18 changes: 18 additions & 0 deletions src/DllExport/Wizard/Extensions/XProjectExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,23 @@ internal static void SetProperties(this IXProject xp, IEnumerable<KeyValuePair<s
p.Value.If(v => v != null, v => group.SetProperty(p.Key, v))
)
);

#region temp; update MvsSln

internal static ProjectTaskElement AddTask(this ProjectTargetElement target, string name, bool continueOnError, Action<ProjectTaskElement> act = null)
{
return target.AddTask(name, condition: null, continueOnError, act);
}

internal static ProjectTaskElement AddTask(this ProjectTargetElement target, string name, string condition, bool continueOnError, Action<ProjectTaskElement> act = null)
{
ProjectTaskElement task = target.AddTask(name);
if(condition != null) task.Condition = condition;
act?.Invoke(task);
task.ContinueOnError = continueOnError.ToString().ToLower();
return task;
}

#endregion
}
}
90 changes: 46 additions & 44 deletions src/DllExport/Wizard/Gears/PreProcGear.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,68 +107,70 @@ private void AddPreProcTarget(string fxCmd, string corCmd, CmdType type)
)
.Condition = "'%(RuntimeFrameworkName)'=='Microsoft.NETCore.App'";

var tCopy = target.AddTask("Copy");
tCopy.SetParameter("SourceFiles", $"$({MSBuildProperties.DXP_METALIB_FPATH})");
tCopy.SetParameter("DestinationFolder", $"$({MSBuildProperties.PRJ_TARGET_DIR})");
tCopy.SetParameter("SkipUnchangedFiles", "true");
tCopy.SetParameter("OverwriteReadOnlyFiles", "true");

bool ignoreErr = (type & CmdType.IgnoreErr) == CmdType.IgnoreErr;
ProjectTaskElement tExec;

if(corCmd != fxCmd)
{
tExec = AddExecTask(target, fxCmd, "'$(IsNetCoreBased)'!='true'", ignoreErr);
AddExecTask(target, corCmd, "'$(IsNetCoreBased)'=='true'", ignoreErr);
}
else
target.AddTask("Copy", ignoreErr, t =>
{
tExec = AddExecTask(target, fxCmd, null, ignoreErr);
}
t.SetParameter("SourceFiles", $"$({MSBuildProperties.DXP_METALIB_FPATH})");
t.SetParameter("DestinationFolder", $"$({MSBuildProperties.PRJ_TARGET_DIR})");
t.SetParameter("SkipUnchangedFiles", "true");
t.SetParameter("OverwriteReadOnlyFiles", "true");
});

if((type & CmdType.DebugInfo) == CmdType.DebugInfo)
AddILMergeWrapper(target, ignoreErr, _=>
{
AddPreProcAfterTarget(target, tExec);
}

var tDelete = target.AddTask("Delete");
tDelete.SetParameter("Files", $"$({MSBuildProperties.PRJ_TARGET_DIR})$({MSBuildProperties.DXP_METALIB_NAME})");
tDelete.ContinueOnError = "true";
if(corCmd != fxCmd)
{
AddExecTask(target, fxCmd, "'$(IsNetCoreBased)'!='true'", ignoreErr);
AddExecTask(target, corCmd, "'$(IsNetCoreBased)'=='true'", ignoreErr);
}
else
{
AddExecTask(target, fxCmd, null, ignoreErr);
}
});

target.AddTask("Delete", continueOnError: true,
t => t.SetParameter("Files", $"$({MSBuildProperties.PRJ_TARGET_DIR})$({MSBuildProperties.DXP_METALIB_NAME})")
);
}

private void AddPreProcAfterTarget(ProjectTargetElement ppTarget, ProjectTaskElement tExec)
private void AddILMergeWrapper(ProjectTargetElement target, bool continueOnError, Action<ProjectTargetElement> act)
{
var tMove = ppTarget.AddTask("Move");
tMove.SetParameter("SourceFiles", $"$({MSBuildProperties.PRJ_TARGET_DIR})$({MSBuildProperties.PRJ_TARGET_F}){ILMERGE_TMP}.dll");
tMove.SetParameter("DestinationFiles", $"$({MSBuildProperties.PRJ_TARGET_DIR})$({MSBuildProperties.PRJ_TARGET_F})");
tMove.SetParameter("OverwriteReadOnlyFiles", "true");
tMove.ContinueOnError = tExec.ContinueOnError;

var target = prj.AddTarget(MSBuildTargets.DXP_PRE_PROC_AFTER);
target.AfterTargets = MSBuildTargets.DXP_MAIN;
target.Label = Id;
AddMoveTask(target, "$(TargetPath)", $"$(TargetDir){ILMERGE_TMP}\\$(TargetName).dll", continueOnError);
AddMoveTask(target, "$(TargetDir)$(TargetName).pdb", $"$(TargetDir){ILMERGE_TMP}\\$(TargetName).pdb", continueOnError);

var tDelete = target.AddTask("Delete");
tDelete.SetParameter("Files", $"$({MSBuildProperties.PRJ_TARGET_DIR})$({MSBuildProperties.PRJ_TARGET_F}){ILMERGE_TMP}.pdb");
tDelete.ContinueOnError = "true";
act?.Invoke(target);
target.AddTask("RemoveDir", continueOnError, t => t.SetParameter("Directories", "$(TargetDir)" + ILMERGE_TMP));
}

private ProjectTaskElement AddExecTask(ProjectTargetElement target, string cmd, string condition, bool continueOnError)
private void AddMoveTask(ProjectTargetElement target, string src, string dst, bool continueOnError)
{
var tExec = target.AddTask("Exec");
tExec.Condition = condition;
tExec.SetParameter("Command", cmd ?? throw new ArgumentNullException(nameof(cmd)));
tExec.SetParameter("WorkingDirectory", $"$({MSBuildProperties.PRJ_TARGET_DIR})");
tExec.ContinueOnError = continueOnError.ToString().ToLower();
target.AddTask("Move", continueOnError, t =>
{
t.SetParameter("SourceFiles", src);
t.SetParameter("DestinationFiles", dst);
t.SetParameter("OverwriteReadOnlyFiles", "true");
});
}

return tExec;
private ProjectTaskElement AddExecTask(ProjectTargetElement target, string cmd, string condition, bool continueOnError)
{
return target.AddTask("Exec", condition, continueOnError, t =>
{
t.SetParameter("Command", cmd ?? throw new ArgumentNullException(nameof(cmd)));
t.SetParameter("WorkingDirectory", $"$({MSBuildProperties.PRJ_TARGET_DIR})");
});
}

private void RemovePreProcTarget(bool hardReset)
{
Log.send(this, $"Attempt to delete pre-proc-targets: `{MSBuildTargets.DXP_PRE_PROC}`, `{MSBuildTargets.DXP_PRE_PROC_AFTER}`");
while(prj.RemoveXmlTarget(MSBuildTargets.DXP_PRE_PROC)) { }

#region unused since 1.8
while(prj.RemoveXmlTarget(MSBuildTargets.DXP_PRE_PROC_AFTER)) { }
#endregion

if(hardReset)
{
Expand All @@ -183,8 +185,8 @@ private string FormatPreProcCmd(CmdType type, StringBuilder sb)

if((type & CmdType.ILMerge) == CmdType.ILMerge)
{
return $"$(ILMergeConsolePath) {cmd} $(TargetFileName) /out:$(TargetFileName)"
+ (((type & CmdType.DebugInfo) == 0) ? " /ndebug" : $"{ILMERGE_TMP}.dll");
return $"$(ILMergeConsolePath) {cmd} {ILMERGE_TMP}\\$(TargetName).dll /out:$(TargetFileName)"
+ (((type & CmdType.DebugInfo) == 0) ? " /ndebug" : string.Empty);
}
return cmd;
}
Expand Down

0 comments on commit 61420e8

Please sign in to comment.