Closed NightOwl888 closed 1 year ago
I take that back. The solution isn't so simple because not all of my published projects depend on MavenReference.
This is worse than I thought. The publish fails because of the duplicate file error. However, MavenReference doesn't actually copy the satellite assemblies. It just puts their names in a list somewhere that MSBuild checks to ensure there are no duplicates. So, the satellite assemblies still need to be copied manually it just cannot be done with the basic <None Include=""/>
element inline with the publish.
This is complicated by the fact that the copy only exists in 1 project and then the copy happens in every project that depends on it. I haven't worked out a way to figure out which project is actually requesting the copy.
I'll be honest, I am lost about what you're trying to describe. Maven Reference doesn't do anything with your custom copy stuff.
It just makes IkvmReferences.
It doesn't add items to publish. It doesn't add items to build. It doesn't mess with any item groups other than IkvmReference.
It does one other thing: add a POM file to Package files. But that's it.
It doesn't copy any assemblies at all. Satellite or not.
I suspect something else is going on. It is probably unintentional. Like enabling or disabling a MSBuild feature that causes it to read the files from the bin directory into a list somewhere, and then it uses that list for validation to ensure there are no duplicate destination paths even though no copy operation takes place.
Whatever the case, simply adding IKVM breaks the build and removing it makes it work again.
I don't have time to deal with it now, but after this project is done I will setup a repro project and link it here so you can investigate.
I finally got past the duplicate file issue using:
<ItemGroup Label="Specifies generated sattelite assemblies should be copied to the output folder (and dependent projects as well)"
Condition=" '$(_IsPublishing)' != 'true' ">
<None Include="$(ICU4NSatelliteAssemblyOutputDir)/**/*.resources.dll" CopyToOutputDirectory="PreserveNewest" Visible="false" />
</ItemGroup>
<Target Name="PublishSatelliteAssemblies" AfterTargets="Publish" Condition=" '$(_IsPublishing)' == 'true' ">
<ItemGroup>
<SatelliteAssemblies Include="$(ICU4NSatelliteAssemblyOutputDir)/**/*.resources.dll"/>
</ItemGroup>
<Message Importance="high" Text="Publishing Satellite Assemblies for $(TargetFramework)..."/>
<Copy SourceFiles="@(SatelliteAssemblies)"
DestinationFolder="$(PublishDir)"
SkipUnchangedFiles="true" />
</Target>
and now I am seeing the original issue happen again.
2023-01-17T18:21:11.7997159Z ##[error]C:\Users\VssAdministrator\.nuget\packages\ikvm\8.4.0\buildTransitive\netstandard2.0\IKVM.Tasks.targets(31,9): Error MSB4018: The "IkvmCompiler" task failed unexpectedly.
System.IO.DirectoryNotFoundException: Could not find a part of the path 'D:\a\1\s\tests\ICU4N.Tests.Collation\obj\Release\net461\ikvm\stage\1\7b2eef3348259756ae2190ad641d7985\icu4j.dll.rsp'.
at Microsoft.Win32.SafeHandles.SafeFileHandle.CreateFile(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options)
at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize)
at System.IO.Strategies.OSFileStreamStrategy..ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize)
at System.IO.File.WriteAllText(String path, String contents)
at IKVM.Tools.Runner.Compiler.IkvmCompilerLauncher.ExecuteAsync(IkvmCompilerOptions options, Cancellation*** cancellation***) in D:\a\ikvm\ikvm\src\IKVM.Tools.Runner\Compiler\IkvmCompilerLauncher.cs:line 259
at IKVM.MSBuild.Tasks.IkvmCompiler.ExecuteAsync(IkvmToolTaskDiagnosticWriter writer, Cancellation*** cancellation***) in D:\a\ikvm\ikvm\src\IKVM.MSBuild.Tasks\IkvmCompiler.cs:line 273
at IKVM.MSBuild.Tasks.IkvmToolExecTask.Execute() in D:\a\ikvm\ikvm\src\IKVM.MSBuild.Tasks\IkvmToolExecTask.cs:line 79
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(ITaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask)
2023-01-17T18:21:11.8033493Z 3>C:\Users\VssAdministrator\.nuget\packages\ikvm\8.4.0\buildTransitive\netstandard2.0\IKVM.Tasks.targets(31,9): error MSB4018: The "IkvmCompiler" task failed unexpectedly. [D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj]
2023-01-17T18:21:11.8038302Z C:\Users\VssAdministrator\.nuget\packages\ikvm\8.4.0\buildTransitive\netstandard2.0\IKVM.Tasks.targets(31,9): error MSB4018: System.IO.DirectoryNotFoundException: Could not find a part of the path 'D:\a\1\s\tests\ICU4N.Tests.Collation\obj\Release\net461\ikvm\stage\1\7b2eef3348259756ae2190ad641d7985\icu4j.dll.rsp'. [D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj]
2023-01-17T18:21:11.8057197Z C:\Users\VssAdministrator\.nuget\packages\ikvm\8.4.0\buildTransitive\netstandard2.0\IKVM.Tasks.targets(31,9): error MSB4018: at Microsoft.Win32.SafeHandles.SafeFileHandle.CreateFile(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options) [D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj]
2023-01-17T18:21:11.8066323Z C:\Users\VssAdministrator\.nuget\packages\ikvm\8.4.0\buildTransitive\netstandard2.0\IKVM.Tasks.targets(31,9): error MSB4018: at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize) [D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj]
2023-01-17T18:21:11.8070185Z C:\Users\VssAdministrator\.nuget\packages\ikvm\8.4.0\buildTransitive\netstandard2.0\IKVM.Tasks.targets(31,9): error MSB4018: at System.IO.Strategies.OSFileStreamStrategy..ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize) [D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj]
2023-01-17T18:21:11.8078614Z C:\Users\VssAdministrator\.nuget\packages\ikvm\8.4.0\buildTransitive\netstandard2.0\IKVM.Tasks.targets(31,9): error MSB4018: at System.IO.File.WriteAllText(String path, String contents) [D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj]
2023-01-17T18:21:11.8082119Z C:\Users\VssAdministrator\.nuget\packages\ikvm\8.4.0\buildTransitive\netstandard2.0\IKVM.Tasks.targets(31,9): error MSB4018: at IKVM.Tools.Runner.Compiler.IkvmCompilerLauncher.ExecuteAsync(IkvmCompilerOptions options, Cancellation*** cancellation***) in D:\a\ikvm\ikvm\src\IKVM.Tools.Runner\Compiler\IkvmCompilerLauncher.cs:line 259 [D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj]
2023-01-17T18:21:11.8265423Z C:\Users\VssAdministrator\.nuget\packages\ikvm\8.4.0\buildTransitive\netstandard2.0\IKVM.Tasks.targets(31,9): error MSB4018: at IKVM.MSBuild.Tasks.IkvmCompiler.ExecuteAsync(IkvmToolTaskDiagnosticWriter writer, Cancellation*** cancellation***) in D:\a\ikvm\ikvm\src\IKVM.MSBuild.Tasks\IkvmCompiler.cs:line 273 [D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj]
2023-01-17T18:21:11.8269311Z C:\Users\VssAdministrator\.nuget\packages\ikvm\8.4.0\buildTransitive\netstandard2.0\IKVM.Tasks.targets(31,9): error MSB4018: at IKVM.MSBuild.Tasks.IkvmToolExecTask.Execute() in D:\a\ikvm\ikvm\src\IKVM.MSBuild.Tasks\IkvmToolExecTask.cs:line 79 [D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj]
2023-01-17T18:21:11.8271167Z C:\Users\VssAdministrator\.nuget\packages\ikvm\8.4.0\buildTransitive\netstandard2.0\IKVM.Tasks.targets(31,9): error MSB4018: at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute() [D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj]
2023-01-17T18:21:11.8273169Z C:\Users\VssAdministrator\.nuget\packages\ikvm\8.4.0\buildTransitive\netstandard2.0\IKVM.Tasks.targets(31,9): error MSB4018: at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(ITaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask) [D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj]
2023-01-17T18:21:11.8376620Z 3>Done Building Project "D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj" (Build target(s)) -- FAILED.
2023-01-17T18:21:11.8378740Z 1>Done Building Project "D:\a\1\s\ICU4N.sln" (default targets) -- FAILED.
2023-01-17T18:21:11.8379667Z 3>Done Building Project "D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj" (default targets) -- FAILED.
2023-01-17T18:21:11.8381228Z 4>Done Building Project "D:\a\1\s\tests\ICU4N.Tests.Collation\ICU4N.Tests.Collation.csproj" (default targets) -- FAILED.
2023-01-17T18:21:11.8382808Z 3>Done Building Project "D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj" (Build target(s)) -- FAILED.
2023-01-17T18:21:11.8384376Z 3>Done Building Project "D:\a\1\s\tests\ICU4N.Tests\ICU4N.Tests.csproj" (Build target(s)) -- FAILED.
2023-01-17T18:21:11.8648499Z 4>Done Building Project "D:\a\1\s\tests\ICU4N.Tests.Collation\ICU4N.Tests.Collation.csproj" (Build target(s)) -- FAILED.
2023-01-17T18:21:11.9595325Z 7>Done Building Project "D:\a\1\s\src\ICU4N.TestFramework\ICU4N.TestFramework.csproj" (default targets) -- FAILED.
Not sure why a project that doesn't reference IKVM at all is looking for a .rsp
file, but that is another can of worms.
We do all building, packing and publishing at the solution level using the IsPackable
and IsPublishable
properties to configure the projects that opt in or out of the step. Perhaps that has something to do with this.
So the error you finally resolved to appears to be from IKVM. Some sort of race condition when it's trying to create the cache directory or something.
There appears to be at least 2 different things going on here:
dotnet publish
with the --no-build
option, it appears to be attempting to build the Maven assemblies rather than simply publishing them without building.IsPublishable
property that we have set when running dotnet publish
.There may also be a race condition, not sure. But the main issue is that we are separating our build into separate steps and IKVM doesn't seem to recognize that publish can be done as an independent step that doesn't do an implicit build.
We have been using a "build once, run everywhere" strategy for our tests. We do a build
and a pack
prior to doing publish
. We don't allow the publish to build again to ensure that we test the same binaries that are in the NuGet package. And due to the fact that we multi-target on multiple projects, we cannot do all of this in one step (publish requires a single TFM and pack requires all TFMs to be built).
Let me put together an example project with the structure that we use to organize our projects and run the builds in Azure DevOps so you can troubleshoot.
yeah, I don't know about any of that stuff.
IkvmReference isn't exactly complicated. Before RAR, it just makes sure the assemblies exist. It doesn't pay attention to build, compile, etc. It emits <Reference>
values, just like anything else. It pays no attention to any of those MSBuild things you're talking about.
But the last error you mentioned was explicit: directory does not exist. We know what that is.
Okay, I have isolated the issues. They don't seem to always happen, although they happen most of the time. To reproduce, use the ikvm-publish branch. The same setup is on the main branch without IKVM dependencies and it works fine as can be seen here.
The satellite assembly copy issue can be reproduced by running the following commands locally. The output directory must exist prior to running the publish
command.
dotnet build --configuration Release --verbosity normal /p:Platform="Any CPU" /p:InformationalVersion=60.1.0 /p:FileVersion=60.1.0.0 /p:PackageVersion=60.1.0 /p:AssemblyVersion=60.1.0.0 /p: /p:TestAllTargetFrameworks=true /p:PortableDebugTypeOnly=true
dotnet publish --output "F:\publishTemp" --framework "net6.0" --configuration "Release" --no-build --no-restore --verbosity normal /p:TestAllTargetFrameworks=true /p:IgnoreSatelliteAssemblyCopy=true
This produces the error(s):
Indeed, this looks like a race condition when copying files.
The .rsp
issue can be seen on Azure DevOps here.
Or, you can set up your own Azure DevOps pipeline by loading the azure-pipelines.yml
file and then running the pipeline based on the ikvm-publish branch. All of the variables have sensible defaults so there is nothing else to configure.
It should be reproducible locally by doing the following replacement in ICU4N.csproj
. Note that you don't need to do this change if the above issue is fixed.
<!-- This is the bit that fails in https://github.com/ikvm-revived/ikvm-maven/issues/29 -->
<ItemGroup Label="Specifies generated sattelite assemblies should be copied to the output folder (and dependent projects as well)">
<None Include="$(ICU4NSatelliteAssemblyOutputDir)/**/*.resources.dll" CopyToOutputDirectory="PreserveNewest" Visible="false" />
</ItemGroup>
<ItemGroup Label="Specifies generated sattelite assemblies should be copied to the output folder (and dependent projects as well)"
Condition=" '$(_IsPublishing)' != 'true' ">
<None Include="$(ICU4NSatelliteAssemblyOutputDir)/**/*.resources.dll" CopyToOutputDirectory="PreserveNewest" Visible="false" />
</ItemGroup>
<Target Name="PublishSatelliteAssemblies" AfterTargets="Publish" Condition=" '$(_IsPublishing)' == 'true' ">
<ItemGroup>
<SatelliteAssemblies Include="$(ICU4NSatelliteAssemblyOutputDir)/**/*.resources.dll"/>
</ItemGroup>
<Message Importance="high" Text="Publishing Satellite Assemblies for $(TargetFramework)..."/>
<Copy SourceFiles="@(SatelliteAssemblies)"
DestinationFolder="$(PublishDir)"
SkipUnchangedFiles="true" />
</Target>
The _IsPublishing
property is described here. Do note that it doesn't work when specifying the /t:Publish
target directly.
Use the same build and publish commands above to reproduce.
I can't quite dig apart what's supposed to be broken about what. Are there three issues?
I checked out your branch, and ran your two commands, a dozen times, and they ran fine.
I can tell from the errors regarding CodeCoverage that you have some multi threading stuff happening that has nothing to do with IKVM......
And the assembly conflict stuff, though it won't happen for me..... he problem is listed in the error output. You have multiple items in the itemgroup being published with the same relative path.
In fact, I can see why this would happen. You're publishing a SLN file with multiple projects to the same output directory. That's not supported by the .NET SDK.
In fact, I can see why this would happen. You're publishing a SLN file with multiple projects to the same output directory. That's not supported by the .NET SDK.
Actually it is. This is the only way to test for real-world dependency conflicts.
The thing is, there is only 1 reference to each of those files. But when doing the publish with IKVM in the mix, it runs the command more than once.
Without IKVM, only the <IsPublishable>
projects are supposed to be published. One of the projects that is erroring out ICU4N.TestFramework
should not be published at all. But IKVM is trying to look for an .rsp
file in the project folder anyway.
And all of the projects (including those with no reference at all to IKVM) are also being scanned for an .rsp
file.
https://github.com/MicrosoftDocs/visualstudio-docs/issues/6643 - IsPublishable is now a thing (and has been for several years). That link is from 2016.
And you've set it on three different projects.....
The link from 2016 hasn't been closed yet, since then. It describes exactly what and why it fail and under what situations.
The gist is that the SDK scripts attempt to run the publish target for each of the projects. And then the relative paths of the output are combined. And then in .NET 6 they introduced an error, which is the very error your receiving, to protect against the situation of duplicate files from diamond dependencies. You are hitting the error they added in .NET 5 to prevent you from doing what you're trying to do.
https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#ispublishable
This property is useful if you run dotnet publish on a solution file, as it allows automatic selection of projects that should be published.
Uh huh. But you can only set it on one project at a time. If there are duplicate files between projects. Which you seem to have.
You have it set in a props file specific to tests/*, which applies to each of the test projects. So it is trying to publish each test project. And since they contain (when you're running it at least) files with duplicate relative output paths, it's erroring.
If you want to clobber files you have to opt in with ErrorOnDuplicatePublishOutputFiles
. Though this can have indeterministic results if you don't know exactly what you're doing.
That makes no sense. The whole idea is that we are publishing all of the projects for a TFM into the same directory. We publish multiple projects together. This even works with dotnet tool publishing just fine. Except it doesn't work with IKVM.
We have been using this same build for half a dozen projects for several years and every new feature thrown at us has worked. Except IKVM.
Well, I don't know what to tell you. I can read the code of the SDK and tell you how it works. Also, it works perfectly fine for me, with IKVM. But without your satellite assemblies I guess? I have no idea where those are.
We used to have it set up with a really complicated double loop that had to conditionally run. However, we removed that when I found out about IsPublishable
, which works fine on multiple projects at the same time. We just let MSBuild handle that part and it doesn't have any duplication or locking issues. Something that IKVM is doing is causing that.
Imagine the following structure:
Project A
| \
Project B Project C
If you try to publish ProjectB and ProjectC into the same output directory, they will both include the full closure of files. That means they'll each include both their own files, and ProjectA's files. Since they each have a copy of ProjectA's files, with the same relative output paths, the SDK will error, telling you what it's telling you.
The error exists to prevent a situation where a dependency of B or C is inadvertidly upversioned by ProjectB, replacing the other's version of that file with a version it wasn't expecting.
You can ignore the error by setting the property I mentioned, but then you have the potential of clobbering a file that you didn't mean to. If you know exactly what you're doing, and have no such concerns, it's fine. In fact, we do it in the IKVM source base in a few places because the versions are unified. For instance, the tools and bin drops.
But yeah... I mean... that's what the SDK does.
One proposal in the bug I posted was to make -o publishDir to automatically add a sub directory per project to even prevent you from targeting the same directory. Never got implemented. Nothing really did. The bug remains with no overall solution.
which works fine on multiple projects at the same time.
It works fine where fine is defined as "if there are duplicate files between the projects and you've specified a specific output path, it will error, but if there aren't, it won't."
Well, for now, I would say focus on the .rsp
file issue. You can simply remove the satellite assembly copy line.
<!-- This is the bit that fails in https://github.com/ikvm-revived/ikvm-maven/issues/29 -->
<ItemGroup Label="Specifies generated sattelite assemblies should be copied to the output folder (and dependent projects as well)">
<None Include="$(ICU4NSatelliteAssemblyOutputDir)/**/*.resources.dll" CopyToOutputDirectory="PreserveNewest" Visible="false" />
</ItemGroup>
That is new and not tested very well, although it seems to work fine without IKVM. Although, the docs for Generate error for duplicate files in publish output, say that it is only a problem if CopyToOutputDirectory
is set to Always
and we aren't doing that.
The .rsp
file is something that shouldn't even be looked for when doing a dotnet publish --no-build
. All we should be doing is copying the already built assemblies to the publish output.
which works fine on multiple projects at the same time.
It works fine where fine is defined as "if there are duplicate files between the projects, it will error, but if there aren't, it won't."
Not true. MSBuild knows how to weed out the duplicate dependencies and doesn't cause any file copy errors in the build output. This is something I checked before switching to IsPublishable
instead of looping through each project and publishing each one individually.
Not true. MSBuild knows how to weed out the duplicate dependencies and doesn't cause any file copy errors in the build output. This is something I checked before switching to IsPublishable instead of looping through each project and publishing each one individually.
Build output yes, not publish output. Build output is unified based on the PackageReference graph. Project B/C upversion based on the most compatible version with their ProjectReferences.
I meant publish output. Setting IsPublishable
on a single project in a solution makes absolutely no sense. That would basically mean there is no advantage at all over publishing at the project level. The whole point of publishing at the solution level is to weed out all of the duplicate publish operations that would end up copying the same files to the publish output multiple times. That is what it is for. But it fails to work as soon as IKVM is referenced. Works fine when IKVM is not referenced.
But again, focus on the .rsp
file issue. There is no reason it should even be looking for that file in projects that don't reference IKVM, but it does.
I suspect both of these will end up being similar. IKVM is probably overriding a target that gets executed during both build and publish, but not distinguishing between the two operations.
I meant publish output. Setting IsPublishable on a single project in a solution makes absolutely no sense. That would basically mean there is no advantage at all over publishing at the project level.
The real problem is the specifics are poorly documented. You can use IsPublishable, on multiple projects, but only if you don't specify PublishDir, or have a different one per project, or don't have overlapping files.
I suspect both of these will end up being similar. IKVM is probably overriding a target that gets executed during both build and publish, but not distinguishing between the two operations.
We override no targets, and do not distinguish between publish and build. As we should not.
IkvmReference's only goal is to ensure the Reference ItemGroup exists before ResolveAssemblyReferences, and that the assemblies it points to exists. That can happen at Publish just as it can happen at Build. If they already exist in either, nothing should be happening. The .rsp file is simply the list of command line arguments to pass to ikvmc. It's involvement only happens if ikvmc is being executed. The only way ikvmc can be executed here is if the proper assemblies don't already exist.
So if you are truly seeing an attempt to generate IkvmReference assemblies during publish, it probably means they don't exist in the cache path. Are you clearing the cache path between runs or something? Or changing any of the dependencies? Or doing stuff that would be unexpected.
The failure to create the .rsp file is a real problem. There's some actual bug where the directory it wants to put the file in doesn't exist at the time it tries to put the file in it. That's being tracked down.
I suspect both of these will end up being similar. IKVM is probably overriding a target that gets executed during both build and publish, but not distinguishing between the two operations.
We override no targets, and do not distinguish between publish and build. As we should not.
IkvmReference's only goal is to ensure the Reference ItemGroup exists before ResolveAssemblyReferences, and that the assemblies it points to exists. That can happen at Publish just as it can happen at Build. If they already exist in either, nothing should be happening. The .rsp file is simply the list of command line arguments to pass to ikvmc. It's involvement only happens if ikvmc is being executed. The only way ikvmc can be executed here is if the proper assemblies don't already exist.
So if you are truly seeing an attempt to generate IkvmReference assemblies during publish, it probably means they don't exist in the cache path. Are you clearing the cache path between runs or something? Or changing any of the dependencies? Or doing stuff that would be unexpected.
The failure to create the .rsp file is a real problem. There's some actual bug where the directory it wants to put the file in doesn't exist at the time it tries to put the file in it. That's being tracked down.
No, it is the opposite of this. The build doesn't create the .rsp
files because the projects don't reference IKVM. This is correct.
Then when the dotnet publish --no-build
command is run, it looks for .rsp
files that don't exist. All of the test projects as well as ICU4N.TestFramework are looking for an .rsp
file even though they never generated one. It shouldn't even be trying to generate the files because this is not a build it is a publish.
Then when the dotnet publish --no-build command is run, it looks for .rsp files that don't exist.
Nothing in your errors you've presented looks for an rsp file and fails if it doesn't exist. The messages involving the .rsp file is the code that CREATES the RSP file. What's missing in your error is the DIRECTORY in which the file is supposed to be created.
And the directory doesn't exist because the project in question doesn't reference IKVM. And it shouldn't exist.
Does it depend on a project that does? If so it does.
Yes, the only project that references IKVM is ICU4N.Tests.csproj
.
So it does.... I'm confused. PackageReferences are transitive.
Oops. I read your question wrong.
No project depends on ICU4N.Tests.csproj. But when doing the publish at the solution level, IKVM is attempting to find an .rsp
file in all of the projects in the solution.
Right. The build fails at that point. Previously I attempted to fix this by making all of the test projects depend on IKVM and com.ibm.icu:icu4j even though they don't need to. That got past the error for the test projects, then it tried to find .rsp
files in ICU4N.TestFramework.
I haven't seen it look for ICU4N, but I suspect if I added IKVM to ICU4N.TestFramework (which I can't because it references netstandard2.0) it would look for an .rsp
file in ICU4N, also.
Okay. I have a suspicion here. I think because Response is considered a relative path, and because you're publishing multiple projects at the same time, MSBuild is not properly protecting Environment.CurrentDirectory. So it's a race condition, with differnet projects overwriting each other's values.
Ahh, no. It's because IkvmCompiler allows Yield to the engine while ikvmc is executing, allowing another simultanious instance of IkvmCompiler to run, and the Environment.CurrentDirectory path might get swapped to a different projects.
The original issue reported had 2 contributors:
Continued from #28 (although unrelated).
Our build makes custom satellite assemblies. We had to go entirely custom because we have cultures that may not be included in .NET. We had to make these satellite assemblies from scratch by using
al.exe
to do the linking. Another reason we do this is so we don't have to include multiple copies of the resource data in the NuGet package, we simply depend on a singlenetstandard1.0
targeted NuGet package that has a single copy of the resources that can be used by all target frameworks.Now, because we do this all outside of MSBuild, it doesn't recognize our satellite assemblies. IIRC, MSBuild will automatically keep a manifest of satellite assemblies in the
.deps.json
file and that is what it uses to decide which assemblies to include in the publish. If you use a "normal" satellite assembly process it should update that manifest. But since we build them outside of this process, we simply added a copy operation to our project to ensure the satellite assemblies are included whenever a build or publish happens. We only need to worry about this in our own project - after that NuGet manages the satellite assembly copy.$(ICU4NSatelliteAssemblyOutputDir)
is a single directory that services all target frameworks in the project.This worked for both build and publish until a reference was added to
IKVM.Maven.Sdk
with a MavenReference dependency. With that added, upon publish it attempts to copy the satellite assemblies again from the original copy the build does. I suspect that is probably because it ignores the.deps.json
manifest and just makes decisions on what is in the obj and/or bin directory when it does the publish.So, the workaround is simple - just add an optional parameter and pass it to the build during publish.
With that in place, the publish succeeds. Maybe I am being petty, but it feels like this should work the same way whether I use MavenReference or not. Or does IKVM also not update the
.deps.json
file from what it does and that is why it just grabs everything?Apparently, it is possible to disable .deps.json
files using
PreserveCompilationContext` which I haven't tried.According to the docs:
MyApp.deps.json
- A list of dependencies, compilation dependencies and version information used to address assembly conflicts. Not technically required, but required to use the servicing or package cache/shared package install features, and to assist during roll-forward scenarios to select the newest version of any assembly that exists more than once in the application and framework(s). If the file is not present, all assemblies in the current folder are used instead.So, without generating the file, the publish process will grab everything. Does MavenReference respect
PreserveCompilationContext
or if that is set to false will it try to copy all of the files in the directory twice?