Skip to content
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

Strange build errors #24

Closed
houstonhaynes opened this issue Oct 24, 2023 · 53 comments
Closed

Strange build errors #24

houstonhaynes opened this issue Oct 24, 2023 · 53 comments

Comments

@houstonhaynes
Copy link
Contributor

So I re-sync'd my forked repo to yours here and then tried to build and all sorts of things started going sideways. I thought it might have been me doing something wrong in rebasing so I cloned your repo directly and tried do a workload restore and re-build. After giving me some guff about System.ReactiveUI needing to be on 5.0 (which I complied with) I got an entire litany of errors. It's been a while so I'm just wondering if a missed a memo. Any thoughts? Thanks!

image

@houstonhaynes
Copy link
Contributor Author

The library builds fine. It's the example apps that are blowing up.

@JordanMarr
Copy link
Owner

I did have to upgrade to the latest version of Avalonia recently, so that probably broke the sample. I’ll take a look!

@daz10000
Copy link
Contributor

daz10000 commented Oct 24, 2023 via email

@JordanMarr
Copy link
Owner

JordanMarr commented Oct 24, 2023

The library builds fine. It's the example apps that are blowing up.

There was a global.json file that was preventing me from even loading. After modifying that, I was able to build and run the AvaloniaExample project.

Now I'm waiting for dotnet workload restore to finish so I can try the AvaloniaXPlatExample project.

@JordanMarr
Copy link
Owner

if you’re open to it, I’d suggest setting up CI in github.  It keeps the build honest and protects against bitrot. Avalonia moves so quickly it’s hard to keep versions straight

I am bad about putting off build automation because I have so many projects.
But you're right - it always is nice to have once setup.

@daz10000
Copy link
Contributor

daz10000 commented Oct 24, 2023 via email

@JordanMarr
Copy link
Owner

I definitely setup build pipelines for all of my professional projects, but those are all on Azure DevOps.
I have avoided .yml files at all costs up to this point in my career.

Now, 15m and 6+ commits into setting up a basic build for this repo and still cannot figure out how to specify the root. lol

@JordanMarr
Copy link
Owner

I always use FAKE to do my builds because I despise the commit > wait > build > wait > pray > review error log cycle.
So much better to quickly iterate on your own machine and then the extent of your final pipeline configuration is a one-liner to call your build app/script.

I've actually been wanting to try Fun.Build for a while. Maybe now is the time!

@JordanMarr
Copy link
Owner

Feel free to help with the build. I've tried for the last 45 minutes to do the most basic yml build script.
Maybe I'm just missing where it "helps" with creating the build, because it seems like I'm editing a text file with no intellisense.

@daz10000
Copy link
Contributor

daz10000 commented Oct 24, 2023 via email

@daz10000
Copy link
Contributor

daz10000 commented Oct 24, 2023 via email

@daz10000
Copy link
Contributor

daz10000 commented Oct 24, 2023 via email

@JordanMarr
Copy link
Owner

Thank you! It's been a long day of solving problems.

@JordanMarr
Copy link
Owner

JordanMarr commented Oct 24, 2023

Now that you got that working, I went ahead an setup Fun.Build, just for fun: build.fsx
I'll try adding the other sln tomorrow. 😴

@JordanMarr
Copy link
Owner

First attempt to download workloads failed:
error

@houstonhaynes
Copy link
Contributor Author

I always use FAKE to do my builds because I despise the commit > wait > build > wait > pray > review error log cycle. So much better to quickly iterate on your own machine and then the extent of your final pipeline configuration is a one-liner to call your build app/script.

I've actually been wanting to try Fun.Build for a while. Maybe now is the time!

Right now I'm setting up miniscaffold for my project and then going into the "src" it builds to "new up" an Elmish.Avalonia project by hand. The entire reason I started this was I was expecting to just copy over the XPlat example and then wire it into the build infra.

@houstonhaynes
Copy link
Contributor Author

houstonhaynes commented Oct 24, 2023

First attempt to download workloads failed: error

Is there a wrinkle with .NET7 and mobile workloads? In most cases I've retreated to .NET6 but that's just a reflex/abundance of caution.

@JordanMarr
Copy link
Owner

I tried changing all the projects to net6, but there is still an issue with the workloads.
To be fair, I haven't really taken the time to properly vet out the build error messages yet.

As of now, the dotnet.yml, global.json and all the xplat fsproj files specify net 6.
Yet I still spotted some a few "net7" references in the build. Not sure if that has anything to do with it. 🤷‍♂️

@houstonhaynes
Copy link
Contributor Author

OK - I'm out-of-office for the next handful of hours - the weather is just too good and I've got some things to do that require daylight. 🌞 But I'll circle back to this after I get to a notch point. Thanks for looking into it. @daz10000 @JordanMarr 👍 👍

@JordanMarr
Copy link
Owner

I got everything updated to the latest Avalonia v11.0.5.
XPlat sln now builds.
CI build now successfully builds the XPlat sln as well. (Not sure why it took 18m though.)

https://github.com/JordanMarr/Elmish.Avalonia/actions/runs/6635424599/job/18026327450

@daz10000
Copy link
Contributor

daz10000 commented Oct 25, 2023 via email

@JordanMarr
Copy link
Owner

Yeah it definitely has to install the workloads, but it was the build of the xplat sln that takes 11m!
I wonder if building in Debug mode would be faster.

@hhaynes-rower
Copy link

I ended up spending some time last night with Jimmy Byrd's miniscafflod to grok its structure.

He just added a feature to be able to dovetail additional projects and wire them up to use the scaffold.

TheAngryByrd/MiniScaffold#283

While I'm still picturing hand-jamming Elmish.Avalonia's XPlat sample with copied files/folder structure, it inspired me to scout out the differences in tooling to see if there's a "paved path" that can be made. That's part of what I'm mucking around with this morning.

@houstonhaynes
Copy link
Contributor Author

So I got the XPlat project to build and run after refreshing my local repo to the latest. But... the Chart view is super-broken. Nothing works other than the init - and the non-Xplat demo just gives a transparent/acrylic window and title bar - nothing else.

image

@houstonhaynes
Copy link
Contributor Author

Weird - cleaned and rebuilt the library and the XPlat CHart is OK - but the "simple" sample is still just rendering a transparent window.

@daz10000
Copy link
Contributor

daz10000 commented Oct 26, 2023 via email

@JordanMarr
Copy link
Owner

Looks like building xplat in Debug mode did shave a lot of time off:
image

@JordanMarr
Copy link
Owner

Weird - cleaned and rebuilt the library and the XPlat CHart is OK - but the "simple" sample is still just rendering a transparent window.

The regular "AvaloniaExample" project "transparent window" issue should be fixed now. I just had to update to the latest Avalonia version 11.0.5.

@JordanMarr
Copy link
Owner

JordanMarr commented Oct 26, 2023

there was a residual bug for me on the cross platform version that if I click away from the chart and then come back to it, it stops working. The terminate background seems to be permanent. I didn’t have that problem with the desktop only version.

The issue occurs on the XPlat version because you changed the tab mechanism to use the Avalonia TabControl which changes the behavior to "singleton" style views.

In the original AvaloniaExample "MainView.axaml", there is a single ContentControl to display the current tab content.
Clicking a tab (button) changes the ContentVM, and then the ViewLocator Build method dynamically loads the corresponding view based on convention. In effect, this means that every time you change to a new tab, the ViewLocator constructs a new view. (The views are "transient".)

	<DockPanel LastChildFill="true">
		<StackPanel Classes="nav" Orientation="Horizontal" DockPanel.Dock="Top" HorizontalAlignment="Stretch">
			<Button Classes="tab" Content="Counter" Command="{Binding ShowCounter}" />
			<Button Classes="tab" Content="Chart" Command="{Binding ShowChart}" />
			<Button Classes="tab" Content="File Picker" Command="{Binding ShowFilePicker}" />
		    <Button Classes="tab" Content="About" Command="{Binding ShowAbout}" />
		</StackPanel>
		
		<ContentControl Content="{Binding ContentVM}" />
	</DockPanel>

Example:

  • You click on the ChartView and click the Auto Update button to start the chart
  • Then you click on a different tab -- the VM terminateOnViewUnloaded is triggered and the subscription stops (as it should)
  • Then you click back to the ChartView, and the ViewLocator re-initializes the ChartView again.

In your XPlat example, you used the TabControl. The difference here is that the tabs are hidden, but the view is still preserved.
This means that the view is not going to be reconstructed by the ViewLocator when you go back to that tab.
However, since you still have |> ElmishViewModel.terminateOnViewUnloaded Terminate, the VM is terminated (but never reinitialized). (ElmishViewModel.terminateOnViewUnloaded calls AvaloniaProgram.withTermination to terminate the Elmish loop for your VM).

So, if you want to use the TabControl, you can't call ElmishViewModel.terminateOnViewUnloaded Terminate because it will terminate your vm and your view is essential a singleton that is never reinitialized.

Just know that getting rid of ElmishViewModel.terminateOnViewUnloaded Terminate means that graph "auto update" will continue running in the background when you switch tabs. But maybe that's ok if you do want your views to be singletons.

I went ahead and removed ElmishViewModel.terminateOnViewUnloaded Terminate from all the viewmodels as it was causing the same problem for all of them.

@JordanMarr
Copy link
Owner

I fixed ChartViewModel.fs so that AutoUpdate is disabled on view.Unloaded event (without fully terminating the vm):

let vm =
    AvaloniaProgram.mkSimple init update bindings
    |> AvaloniaProgram.withSubscription subscriptions
    |> ElmishViewModel.create
    |> ElmishViewModel.subscribe (fun view model dispatch ->
        view.Unloaded |> Observable.subscribe (fun _ ->
            dispatch (Msg.SetIsAutoUpdateChecked false)
        )
    )

Pretty cool that ElmishViewModel.subscribe gives you a view, a model and dispatch, eh? 😎

@houstonhaynes
Copy link
Contributor Author

That is fascinating... and useful.

On a total side note - as I was clicking through the site I noticed that the color scheme of the button controls in the Chart view had changed, and the "Ok" buttons had gone missing from a few views. I thought it was a good example of that global message but has become a bit ragged now that it's even missing from the About View. Is there any reason for that? It's not a deal breaker - just curious.

@JordanMarr
Copy link
Owner

Looks like the Ok buttons were commented out in the XPlat views.
Probably because the change to use TabControl for navigation would break the GoHome message.
You could hook it back up if you wanted to, but the implementation would have to change.

  • Subscribe to GoHome message in MainViewModel
  • Create a "SelectedTab" binding to programmatically set the currently selected tab

@daz10000
Copy link
Contributor

daz10000 commented Oct 26, 2023 via email

@houstonhaynes
Copy link
Contributor Author

You make a good point - it begs the question of what to show in an "example" for interactivity in navigation. I wouldn't necessarily want to over complicate things by having two navigation styles in one app. Does it warrant two branches?

Either way this is relatively new to me so I'm learning as I go.

@houstonhaynes
Copy link
Contributor Author

It's interesting that I got prompted again this morning to do a workload restore and it started pulling bits for .NET7 (which asked my question if those workloads were there for .NET7)

image

@houstonhaynes
Copy link
Contributor Author

houstonhaynes commented Oct 26, 2023

Then I run fun.build and I'm getting the Android .NET6 +7 bits...

image

PIPELINE CI is finished in 304694 ms

It keeps hinting I have a reboot pending so will do the honors and come back (this is all just to get the Avalonia previewer in VSCode to give me something back - I have Rider but I'm a curious type ) :)

@houstonhaynes
Copy link
Contributor Author

So - rebooted and re-ran fun.build and seemed to go OK other than the fact that after the run the Avalonia extension still doesn't recognize that the project has been built (and therefore the preview should display)

image

@houstonhaynes
Copy link
Contributor Author

It's also interesting to note that in one case there's an error message in the build-on-boot process where I'm seeing a prompt to go and download wasm-tools-net7 as opposed to what I've seen for other workloads and fun.build just fetching what it needs.

  Determining projects to restore...
C:\Program Files\dotnet\sdk\8.0.100-preview.7.23376.3\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.ImportWorkloads.targets(38,5): error NETSDK1147: To build this project, the following workloads must be installed: wasm-tools-net7 [C:\repos\Elmish.Marr.Avalonia\src\Samples\AvaloniaXPlatExample\AvaloniaXPlatExample.Web\AvaloniaXPlatExample.Web.fsproj]
C:\Program Files\dotnet\sdk\8.0.100-preview.7.23376.3\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.ImportWorkloads.targets(38,5): error NETSDK1147: To install these workloads, run the following command: dotnet workload restore [C:\repos\Elmish.Marr.Avalonia\src\Samples\AvaloniaXPlatExample\AvaloniaXPlatExample.Web\AvaloniaXPlatExample.Web.fsproj]

So in a fit of pique I decided to run dotnet workload restore to see what comes back and it says that everything was successfully loaded.

 dotnet workload restore
Installing workloads: 


Successfully installed workload(s) android ios macos wasm-tools.

So again I don't want to get wrapped around the axle but it seems like there's a bit of a misalignment between what fun.build is building and what VSCode's Avalonia extension can "see" as having been built.

@houstonhaynes
Copy link
Contributor Author

Sorry for spamming the thread - just an FYI that Rider seems fine.

image

@houstonhaynes
Copy link
Contributor Author

Oh wait - desktop runs but web fails

C:\Users\h3tec\AppData\Local\Programs\Rider\plugins\dpa\DotFiles\JetBrains.DPA.Runner.exe --handle=8396 --backend-pid=14268 --etw-collect-flags=3 --detach-event-name=dpa.detach.8396 "C:\Program Files\dotnet\dotnet.exe" C:/repos/Elmish.Marr.Avalonia/src/Samples/AvaloniaXPlatExample/AvaloniaXPlatExample.Web/bin/Debug/net7.0/browser-wasm/AvaloniaXPlatExample.Web.dll
A fatal error was encountered. The library 'hostpolicy.dll' required to execute the application was not found in 'C:\repos\Elmish.Marr.Avalonia\src\Samples\AvaloniaXPlatExample\AvaloniaXPlatExample.Web\bin\Debug\net7.0\browser-wasm\'.
Failed to run as a self-contained app.
  - The application was run as a self-contained app because 'C:\repos\Elmish.Marr.Avalonia\src\Samples\AvaloniaXPlatExample\AvaloniaXPlatExample.Web\bin\Debug\net7.0\browser-wasm\AvaloniaXPlatExample.Web.runtimeconfig.json' did not specify a framework.
  - If this should be a framework-dependent app, specify the appropriate framework in 'C:\repos\Elmish.Marr.Avalonia\src\Samples\AvaloniaXPlatExample\AvaloniaXPlatExample.Web\bin\Debug\net7.0\browser-wasm\AvaloniaXPlatExample.Web.runtimeconfig.json'.

Process finished with exit code -2,147,450,749.

@houstonhaynes
Copy link
Contributor Author

OK - so after putting ALL projects on .NET7 I get web to build - but now it just gives me the "powered by Avalonia UI" splash page and nothing else.

image

@houstonhaynes
Copy link
Contributor Author

Well I'm out of ideas with the XPlat for now but have the desktop sample app running on .net6 with no complaints. So that's where I'm going to focus for the moment. 👍

@JordanMarr
Copy link
Owner

JordanMarr commented Oct 26, 2023

Could be that the global.json is affecting things wrt net6/net7?

@houstonhaynes
Copy link
Contributor Author

houstonhaynes commented Oct 26, 2023

Could be that the global.json is affecting things wrt net6/net7?

I went through and updated all of the global.json files as well as retargeted the fsprojs and so far only the desktop on .net6 will build and run.

What I'm seeing is some complaints about the Avalonia version not supporting .net6 - I understand why there's a push to get everything on 11.0.5/.NET7 - I'm just not sure "how to square the circle" in the build script such that those dependencies are changed consistently when the target(s) change.

C:\repos\Elmish.Marr.Avalonia\src\Samples\AvaloniaXPlatExample\AvaloniaXPlatExample.Android\AvaloniaXPlatExample.Android.fsproj : error NU1202: Package Avalonia.Android 11.0.5 is not compatible with net6.0-android31.0 (.NETCoreApp,Versio
n=v6.0). Package Avalonia.Android 11.0.5 supports: net7.0-android33.0 (.NETCoreApp,Version=v7.0) [C:\repos\Elmish.Marr.Avalonia\src\Samples\AvaloniaXPlatExample\AvaloniaXPlatExample.sln]

@daz10000
Copy link
Contributor

daz10000 commented Oct 26, 2023 via email

@houstonhaynes
Copy link
Contributor Author

well hell - I partially take it back - moving EVERYTHING to .NET7 and upgrading deps on Elmish.Avalonia to Avalonia 11.0.5 meant that XPlat desktop works. There's still the wrinkle of the WASM client not behaving - and Android doesn't like my target being set to <TargetFramework>net7.0-android</TargetFramework>. I did a little sniffing around SO and the web to see if there's something I can suss out - but no joy for the few things I've tried.

@houstonhaynes
Copy link
Contributor Author

houstonhaynes commented Oct 26, 2023

Has the iOS project ALWAYS been a .csproj?

image

I could have sworn I ran this on my iPhone and it didn't jump out at me at the time.

@daz10000
Copy link
Contributor

daz10000 commented Oct 26, 2023 via email

@houstonhaynes
Copy link
Contributor Author

OK - yeah I guess I didn't move the change back to the sample project because I definitely make is an fsproj in my "SunFlwr" project. Sorry about that - pretty high-distraction environment. 😄 I was trying to get Bluetooth to work between the phone and my WildernessLabs Meadow board.

@JordanMarr
Copy link
Owner

JordanMarr commented Oct 26, 2023

Re: "Ok" buttons

IMO, it's not worth creating a new branch just for that since it already exists in the original non-xplat example.

Navigation

It would be nice to have a more formalized navigation subsystem baked into the project.
The current version works, but is kind of ad-hoc.

A fully-fledged nav system would:

  • Encapsulate the navigation mechanism (be it pub/sub or something else)
  • Provide some sort of "leaving" and intercept events for pages to handle
  • Help to provide concepts around transient vs singleton pages and establish patterns around each.

Not sure if that has a place in a library like this, or if it would be more a 3rd party library concern, but it would be nice to have. Might make it a little less like the "wild west".

Re: net6/7

I agree that we are so close to net8 that we should probably just keep looking forward as much as possible. Especially considering that this is all very bleeding edge. net6 is soon to be behind us!

Re: workloads

I had lots of issues with getting the workloads working properly in the build. Unfortunately, what worked on my machine when I ran the script locally did not always work on the build machine.
For example, I originally wanted to just do a dotnet workload restore {sln path} as that worked locally, but it failed on the build server. I ended up manually installing certain workloads in the build script which made the build server happy.
So, the build.fsx is kind of targeted specifically to the GitHub build environment at this point (for better or for worse).

Workloads are still new to me, (although I am also doing a MAUI project which uses them as well), so I'm totally stumbling along here.

@houstonhaynes
Copy link
Contributor Author

I hear you on all counts. The wrinkles in Avalonia-vs-dotnet with the added "stretch goal" of making this buildable in a scaffold is a LOT of ambition. Once it's "in the can" and can reliably be built in a fire-and-forget manner it'll be incredibly compelling. 🚀

It does beg the question of where Avalonia stands with .NET8 -- and whether the lead time to getting them to play well together is going to be shorter. 🤔

I'm working on a POC that takes my attention as much to the backplane as it's tugging me toward giving attention to UX. So I'll be hopping back and forth a bit. For now I can be relatively conservative and run the desktop app on .NET6 which will let my team plow ahead a bit. I will come back to XPlat from time to time, though, as part of our use case is to showcase a full mobile app experience.

https://github.com/Rower-Consulting/Aiden

I agree with your summation on navigation, and definitely want to help come up with a "paved path" for that sub-domain which makes sense for more than one common scenario. That's why I appreciated seeing the TabControl method and stretching my brain a bit over how you suggested some modifications.

Probably because the change to use TabControl for navigation would break the GoHome message.
You could hook it back up if you wanted to, but the implementation would have to change.

Subscribe to GoHome message in MainViewModel
Create a "SelectedTab" binding to programmatically set the currently selected tab

It would be nice to have a pattern which allowed appropriate control/context switching that didn't step on one model over another. Though now that I think of it I wonder if they really need to coexist or would the user simply choose one over the other... 🤔

For my own case, I'm considering some options in how much work to do "at the edge" versus pushing things down to the backplane when the user's eyes aren't on the screen/view. I've thought about the client app "minding the store" on sliding windows of data (via pub/sub using SignalR) and therefore keep certain processes running in-app even if it's not the "visible" thing from the user's point of view. The idea is that the user can see everything the "machine" sees as the data surfaces. I'll just have to experiment to see if the typical "rehydrate on making a view active" model will have the immediacy I'm looking for.

This is fun! I really appreciate you both helping me with deepening my understanding here. 🧠 ❤️

@houstonhaynes
Copy link
Contributor Author

And FWIW when I run the build locally it does chunk through checking that the workloads are installed which has some lag. I had wondered if there's a way to structure the build process to simply look for the presence of the workload instead of simply "install workload" and letting the tool figure out it's already there... if I get a hot second to check into that it might help improve local build times.

@daz10000
Copy link
Contributor

daz10000 commented Oct 27, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants