-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Self-Contained publish with multiple executables? #18282
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
To add, I had said I wondered if the problem was |
@agocke @LakshanF @vitek-karas for discussion of a having multiple apps be self-contained but sharing the same runtime bits. As far as copying deps.json files, that was fixed in the 5.0.200 SDK with #14488. You can use the latest SDK and still target earlier versions of .NET. As far as the 32 / 64-bit mismatch, the issue is probably that the RuntimeIdentifier doesn't flow across project references. If you were to set the RuntimeIdentifier in the referenced Exe projects themselves, I think it would probably work. |
I forgot about this issue or I would have updated as I learned more. I
switched to the 5.0 build tools (to continue building 3.1) and it fixed the
problems I was having with 32 bit. Something to do with the 3.1 build
tools not making some expected build properties available at build time.
Also, what you are saying about RuntimeIdentifier sounds familiar. If I
recall, the 5.0 sdk started giving a new error/warning about them missing,
and I added them to each project. Maybe 3.1 SDK would have worked if I had
just added that, but it wasn't generating the errors about it to make me
notice.
Also the deps.json issue, bear with me msbuild et al is a blackbox to me,
but I think I deduced what was happening: After trimming occurs, deps.json
is updated to reflect the smaller set of dlls. But that updating of
deps.json only happens for the actual target of the build (buildhelper
dummy project) not the additional deps.json files of the other exes added
as "dependancies". So the real exes were being built (as deps,
automatically, recursively) but the dlls not trimmed, and more relevantly,
their deps.json files were untrimmed. Then publish copies them in for
buildhelper to build against, and their un-trimmed deps.jsons come with
them. Then when buildhelper project finishes publishing, it is trimmed,
which updates it's deps.json for the reduced set of included dlls. However
the deps.jsons which were copied in with the other exes are never updated
after the trimming and are left with references to files which have been
trimmed out. Execution bootstrapping for the other exes fails because
their deps.json still point at files which have been trimmed out. This
explanation may not be 100% accurate, but the solution I found was simply
to delete all the deps.json files for all the exes, and it seems to default
to looking in the working directory for whatever it needs. I also then
delete runtimeconfig.json since it points at the deps.json, and would give
it's own error if there was one but not the other.
This is working really well for me now. But figuring out those gotchas
above (and accomodating them in my build projects/scripts) was rocky and
messy, and I distinctly felt like I was doing something not supported. So
I wanted to raise the flag that this is a useful thing that the SDK can
basically 99% already do, or really 100% but with caveats. It would be
great if there was a more streamlined/sanctioned path to go down.
…On Thu, Aug 19, 2021 at 7:47 PM Daniel Plaisted ***@***.***> wrote:
@agocke <https://github.com/agocke> @LakshanF
<https://github.com/LakshanF> @vitek-karas
<https://github.com/vitek-karas> for discussion of a having multiple apps
be self-contained but sharing the same runtime bits.
As far as copying deps.json files, that was fixed in the 5.0.200 SDK with
#14488 <#14488>. You can use the latest
SDK and still target earlier versions of .NET.
As far as the 32 / 64-bit mismatch, the issue is probably that the
RuntimeIdentifier doesn't flow across project references. If you were to
set the RuntimeIdentifier in the referenced Exe projects themselves, I
think it would probably work.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#18282 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABQGHBMZZL4SR5LJ33FT6RTT5WQ2HANCNFSM46YJVPAA>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email>
.
|
Yup, that's the current situation. Putting multiple apps in the same self-contained directory is unsupported, but it often works. Trimming makes this very dicey -- it is very likely that something will be trimmed away but the other app uses but the trimmer didn't see, simply because the apps weren't analyzed in the same trimmer pass, because trimming works one app at a time. We may decide to support something like this in the future, but it's not currently scheduled. |
To be clear, I didn't just filemerge self contained publish directories. I did try that in early experimentation and it didn't work. The "trick", so to speak, was realizing that for trimming to work (ever) it must account for the deps of deps, and thus if all exes were part of one dep tree, it would force the trimming pass to account for all of the deps of all of the exes at once. This lead me to my hack-solution, which is adding the exes as dependancies to an extra build-target exe with some place holder references between them - so that the trimming pass would theoretically parse through all of hierarchy and come out with a union of deps to trim from. |
Yes - that might make it work in the default setup where we don't trim user code. If you were to turn on full trimming even for user code this would probably break as well (as the additional exes would to even keep their |
Interesting, by "default" vs "full" trimming, are you referring to "link" vs "copyused"? I'd like to know what controls that so I can be careful to avoid it. |
It's "link" versus "copy" (copyused is now sort of deprecated) - the property is |
Thanks. Although, https://docs.microsoft.com/en-us/dotnet/core/deploying/trimming-options says the default is changing in .NET 6 from copy (it says "copyused") to "link". So maybe I should explicitly set it to "copy" (or "copyused"? I can't find "copy" documented anywhere yet) to be safe for when I forget this and upgrade my tools. |
Sorry - my bad - the property you want to avoid is |
Appreciate the clarification! |
I hope I am posting this in the right place since I'm currently using dotnet 3.1 which is in the dotnet/cli repo, but that repo has removed it's issue tracker.
I maintain an auto-updating application where external runtimes are a hazard that has cost us a lot of time and expense over the last 10 years. We are moving to a self contained build to finally leave this behind us. But our application is a bundle of several executables: a windows service, a UI agent, a handful of testing tools for users, some shims for loading other things. They cannot simply be put together into one exe and have their functionality switched by arguments because it's a mixture of winforms and cli, as well as the fact that several exes need to be easily found/run by users.
I have not been able to find any supported, official mechanism to create a self contained build of multiple projects/executables together, where the union of their dependencies are included and trimmed. If there is an official, proper way to do this and I've missed it, someone please tell me. I have however found a very easy workaround to "trick" the SDK into doing this:
This workaround for the most part works very well. If I were to make independent self contained builds of all the exes separately, the output would total well over a gigabyte, because of all the duplicated runtime overhead, which is not acceptable for my purposes. Building in the way described above produces a single self contained runtime with the multiple exes in it for around 90mb, which zips down to about 45mb. Two takeaways, 1. you can see this is a very useful thing to be able to do, 2. as simple as this workaround is, there shouldn't be much technical challenge to providing this feature out of the box so that this dance would not be necessary. It is my hope that something like this can be provided/supported in the future.
Since it is not (I don't think) currently supported, there are a few oddities with it. For one thing I have not gotten it to work on dotnet 5, although I have not spent much time trying, but there is some funniness with the inclusion of deps.json files (maybe the tip an iceberg). More relevantly to me at the moment, although normal 64 bit builds work fine, when I try to make a build that is 32 bit (by specifying -r win-x86 when publishing BuildHelper), it doesn't work. If I leave the BuildHelper files in the output, I can run that successfully on a 32 bit machine. But if I try to run any of the other included (built as dependencies) exes on a 32 bit machine, I get errors that look like they are built for 64 bit, even though the publish folder is full of only x86 dlls.
Running the exes on a 32 bit machine gives the output
Program 'MyApp.exe' failed to run: The specified executable is not a valid application for this OS
I wonder if for some reason it is including 64-bit exe-shims with the 32bit trimmed dlls for the sub-applications...
Also if I try to run the 32 bit exes on a 64 bit machine I get the output
Another oddity with the 32 bit build is that the nuget package for webview2 includes the 64bit native libraries, rather than the 32 bit ones. So it seems like the sdk is somehow not fully getting the message that the "dependency exes" (and not just BuildHelper) are being published as win-x86.
Is there a supported way to do what I'm trying to do? If not, can I request such a feature?
Also any thoughts about the 32bit build situation above are welcome.
The text was updated successfully, but these errors were encountered: