ravibpatel / ILRepack.Lib.MSBuild.Task

MSBuild task for ILRepack which is an open-source alternative to ILMerge.
Other
107 stars 30 forks source link

`ILRepack` runs twice only when `Configuration` is `Release` #54

Closed just-ero closed 2 months ago

just-ero commented 2 months ago

Description

In my setup, the ILRepack task runs twice, but only when I set the build configuration to Release. It works correctly for Debug.

Here's what I'm doing:

SampleProject.Build.proj

<Project Sdk="Microsoft.Build.NoTargets">
  <PropertyGroup>
    <TargetFramework>net4.8.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\SampleProject.Foo\SampleProject.Foo.csproj" />
    <ProjectReference Include="..\SampleProject.Bar\SampleProject.Bar.csproj" />
  </ItemGroup>

  <Import Project="_MergeAssemblies.targets" />
</Project>

_MergeAssemblies.targets

<Project>
  <ItemGroup>
    <PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.34" />
  </ItemGroup>

  <Target Name="_MergeAssemblies" AfterTargets="Build">
    <ItemGroup>
      <AssembliesToMerge Include="$(OutputPath)\SampleProject.Foo.dll" />
      <AssembliesToMerge Include="$(OutputPath)\SampleProject.Bar.dll" />
    </ItemGroup>

    <ILRepack
      Parallel="true"
      InputAssemblies="@(AssembliesToMerge)"
      OutputFile="$(OutputPath)\SampleProject.Final.dll"
    />
  </Target>
</Project>
Output from dotnet build -c Debug ``` Determining projects to restore... All projects are up-to-date for restore. SampleProject.Foo -> D:\Code\SampleProject\artifacts\bin\SampleProject.Foo\release\SampleProject.Foo.dll SampleProject.Bar -> D:\Code\SampleProject\artifacts\bin\SampleProject.Bar\release\SampleProject.Bar.dll Added assembly 'D:\Code\SampleProject\artifacts\bin\SampleProject.Build\release\SampleProject.Foo.dll' Added assembly 'D:\Code\SampleProject\artifacts\bin\SampleProject.Build\release\SampleProject.Bar.dll' Merging 2 assembies to 'D:\Code\SampleProject\artifacts\bin\SampleProject.Build\release\SampleProject.Final.dll' Merge succeeded in 0.2354729 s Build succeeded. 0 Warning(s) 0 Error(s) ```
Output from dotnet build -c Release ``` Determining projects to restore... All projects are up-to-date for restore. SampleProject.Foo -> D:\Code\SampleProject\artifacts\bin\SampleProject.Foo\release\SampleProject.Foo.dll SampleProject.Bar -> D:\Code\SampleProject\artifacts\bin\SampleProject.Bar\release\SampleProject.Bar.dll Added assembly 'D:\Code\SampleProject\artifacts\bin\SampleProject.Build\release\SampleProject.Foo.dll' Added assembly 'D:\Code\SampleProject\artifacts\bin\SampleProject.Build\release\SampleProject.Bar.dll' Merging 2 assembies to 'D:\Code\SampleProject\artifacts\bin\SampleProject.Build\release\SampleProject.Final.dll' Merge succeeded in 0.2244052 s Added assembly 'D:\Code\SampleProject\artifacts\bin\SampleProject.Build\release\SampleProject.Final.dll' Added assembly 'D:\Code\SampleProject\artifacts\bin\SampleProject.Build\release\SampleProject.Foo.dll' Added assembly 'D:\Code\SampleProject\artifacts\bin\SampleProject.Build\release\SampleProject.Bar.dll' Added assembly 'D:\Code\SampleProject\artifacts\bin\SampleProject.Build\release\System.Buffers.dll' Added assembly 'D:\Code\SampleProject\artifacts\bin\SampleProject.Build\release\System.Memory.dll' Added assembly 'D:\Code\SampleProject\artifacts\bin\SampleProject.Build\release\System.Numerics.Vectors.dll' Added assembly 'D:\Code\SampleProject\artifacts\bin\SampleProject.Build\release\System.Runtime.CompilerServices.Unsafe.dll' Merging 7 assembies to 'D:\Code\SampleProject\artifacts\bin\SampleProject.Build\release\SampleProject.Final.dll' C:\Users\Ero\.nuget\packages\ilrepack.lib.msbuild.task\2.0.34\build\ILRepack.Lib.MSBuild.Task.targets(16,9): error : Duplicate type Class1 from SampleProject.Foo.dll, was also present in SampleProject.Final, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null [D:\Code\SampleProject\src\SampleProject.Build\SampleProject.Build.csproj] Build FAILED. C:\Users\Ero\.nuget\packages\ilrepack.lib.msbuild.task\2.0.34\build\ILRepack.Lib.MSBuild.Task.targets(16,9): error : Duplicate type Class1 from SampleProject.Foo.dll, was also present in SampleProject.Final, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null [D:\Code\SampleProject\src\SampleProject.Build\SampleProject.Build.csproj] 0 Warning(s) 1 Error(s) ```

It may be of note here that I have a separate SampleProject.Build project, which collects the necessary output assemblies and moves some files around.
I have no clue why the above behavior would happen. Anyone able to help me figure out what I'm doing wrong?

just-ero commented 2 months ago

Moving the PackageReference to SampleProject.Build.proj, renaming _MergeAssemblies.targets to ILRepack.targets, and removing the Import element from the .proj file fixes this.

It's quite frustrating to be forced into this structure. Setting <ILRepackTargetsFile>_MergeAssemblies.targets</ILRepackTargetsFile> does not work, no merging takes place.

ravibpatel commented 2 months ago

Did you try setting in ILRepack.Config.props file? You can try creating ILRepack.Config.props file in your project root with following content, and it should use your targets file.

<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <ILRepackTargetsFile>$(SolutionDir)_MergeAssemblies.targets</ILRepackTargetsFile>
  </PropertyGroup>
</Project>
just-ero commented 2 months ago

Yes, I have tried that, as described in https://github.com/ravibpatel/ILRepack.Lib.MSBuild.Task/issues/54#issuecomment-2169636517.

just-ero commented 2 months ago

Coming back to this; the following ILRepackTargetsFile value does work:

<ILRepackTargetsFile>$(MSBuildThisFileDirectory)\_MergeAssemblies.targets</ILRepackTargetsFile>

However, this version does not work:

<ILRepackTargetsFile>_MergeAssemblies.targets</ILRepackTargetsFile>

Really bizarre.

ravibpatel commented 2 months ago

Yes, It may require full path of the file. The props file is basically imported into the default targets file, and it uses variables defined in this props file. You can check it here.

just-ero commented 2 months ago

A .props file is not necessary and I have no idea what it has to do with the issue. I set ILRepackTargetsFile in my .csproj file.

ravibpatel commented 2 months ago

Adding ILRepackTargetsFile directly to project works same as .props file, cause default targets file is imported later in the build process, and it will use that variable. It must have a fully qualified path to work, I think. Without it, it won't be able to import your targets file.

just-ero commented 2 months ago

Should I open a separate issue for that? I don't expect to have to provide a full path in MSBuild. Every other (official) MSBuild task is capable of using relative paths.

ravibpatel commented 2 months ago

I can hard code the $(MSBuildThisFileDirectory) inside the default targets file to do this, but it will break the compatibility for other users, so I don't think I can change this behavior.

just-ero commented 2 months ago

I would presume you can check Path.IsPathRooted or call Path.GetFullPath on the input.

MadTekN1 commented 2 months ago

Hello, really cool tool to merge assemblies. But how can i delete the default behavior and set my own behavior in .csproj instead ?

Just like so:

net6.0-windows enable enable

Because it's pretty frustrating that it's running twice and merging file inside my /release folder when I don't want it to.

ravibpatel commented 2 months ago

@MadTekN1 Just create "ILRepack.targets" file as mentioned here and it should work.

ravibpatel commented 2 months ago

@just-ero I think I will stick with the current behavior. It is simple as adding the $(SolutionDir), $(ProjectDir) or $(MSBuildThisFileDirectory) in front of the file to provide the path to your custom targets file.

just-ero commented 2 months ago

This does not address the actual issue of the task running twice only when building for Release. Please reopen.

ravibpatel commented 2 months ago

Is it possible to provide a sample project that can reproduce this behavior? It looks impossible to run it twice if you provide your 'ILRepack.targets' file in the project or via 'ILRepack.Config.props' file or directly setting ILRepackTargetsFile variable in your .csproj.

just-ero commented 2 months ago

But you realize how unconventional and frustrating it is to force the user into this architecture? I have never experienced that in any other MSBuild task.

ravibpatel commented 2 months ago

Do you mean providing full path instead of relative? I personally find it more readable as I have projects that use a single solution to house multiple projects, and they use a common targets file. Specifying it like "$(SolutionDir)ILRepack.targets" is more readable for me, as I know each project is using the targets file from solution level. Also, using the Path function will be hideous in the msbuild file as you can see here.