Jon (00:05.998) Welcome back to Nethergon Mobile. Alan, are you out of the winter yet up there? Allan Ritchie (00:10.062) Nope, but it looks nice outside, but it's still cold. Jon (00:14.51) So no snow though, just the cold. Allan Ritchie (00:15.47) No, no snow. It's almost shorts weather for Canadians, so. Jon (00:20.237) Yeah, exactly. It's, it's creeping up warmer and warmer here today is kind of the sunny, you know, warm wind and then blah. So still not quite, you know, great weather to be wanting to be outside like crazy, which is good if you want to learn more about, you know, things that you would otherwise not want to do if it was nice weather outside, like Emma's build. Allan Ritchie (00:45.966) I don't know, I like working with, oh, but you said MSBuild, but I generally like coding even when it's sunny outside. Jon (00:52.75) Yeah, I like coding too. But MSBuild, I think I've internally here even, I've kind of thought and we've talked about it with a few people that it's almost, you kind of love it or you hate it. Do you find that about it? Allan Ritchie (01:08.622) Yeah, I'm somewhere in between. Jon (01:12.686) Yeah, it's something that I feel like has an acquired taste and slowly grows on you and is not super well understood by everyone. So I thought it was worth talking a little bit about some MSBuild stuff in detail. We have a... Allan Ritchie (01:27.534) The easiest thing to say is it's in your CS Proj, whether you know it or not. Get comfortable with it. Jon (01:30.67) It's it. Yeah. Yeah. So like you've, you've been using Ms build, whether you want to admit it or not, right? Just depends on, you know, how, what the varying levels of, uh, things you've done with Ms build are. So, you know, it might be worth, um, I don't know if it's worth talking about the, the old days, the dark times, but do you ever remember? Of course you remember you used like the whole full project format, you know, CS project with all the. project type quids and all the different things and like historically CS projects and project files were kind of a scary thing to look at. Like what was your progression of getting more comfortable with those things? Allan Ritchie (02:09.998) Well, I think the biggest thing is why you didn't touch them out of the box was because CS Proj was considered off limits for a lot of projects, right? Because it was managed by the IDE, or it was assumed in a lot of cases. Now you could go in there, edit stuff, but the file would be so darn big that every time you wanted to make a change to the CS Proj file, you were guaranteed that you were going to get a merge conflict when you shipped it over the wire. Jon (02:31.372) Mm -hmm. Jon (02:36.494) Yeah, merge conflict. And honestly, like a lot of the stuff in there was not super well understood. At least that's where I started. I kind of, you know, early, early days was always afraid to touch too much in there. Um, but one of the things that I think has helped that or, or made it less scary has been the introduction of the S like we called them SDK style projects, right? Um, so there's like the old format that how these things, and then there, there was a newer format that finally the, the .net team was like, Hey, this. This is a thing that people need to use and we want to make it a little bit more approachable and have less junk in there and less opportunity for those kind of merge conflicts and stuff like that. Allan Ritchie (03:15.854) The Slim CS Proj. Jon (03:17.998) This slim, yes, they should have had it named by us, focused CS project. Yeah. So that, like what, you know, have, do you know what a new project file looks like today? Not like a Maui one necessarily, like, yes, well, we can talk about that, but if you just do like a new console app. Allan Ritchie (03:20.776) It's very focused. Allan Ritchie (03:35.022) Well, it's like five lines, I think. It's basically specifying the language version of C sharp, which is usually the latest. If you want to implicit usings, I believe nullability, cause those are all things you kind of some love, some hate. So you go, you get to pick your poison and then obviously the target framework, right? Is it just plain net eight? Is it? Jon (03:39.822) Yeah. Jon (03:45.326) Is that in the template? Nullability. Jon (03:59.31) Yes. Allan Ritchie (04:03.264) You know, what the hell, where are you targeting with this thing? Oh, and I guess obviously the program type, is it a library or an executable? I think for the console app, it has to specify that. Jon (04:10.734) Yeah, and I think. Yeah, I think the default and that was another thing that that kind of was brought in with these projects, right? There's you can change those properties and stuff, but there's usually kind of a sensible default. So I think by default output type is, you know, library and you don't have to necessarily specify that. I'm not sure if that's in the template or not, but yeah. So the point being that these things are really kind of slim to begin with, right? Um, and that's kind of the starting point of the whole conversation. Um, one thing that, as we were building Maui and we realized that we needed to do some kind of sensible defaults for people. We had the conversation like, what do you kind of try to hide from being in that default project file and what do you put in there to give people sort of a breadcrumb to understanding what is available to them or how it works even? So, kind of quiz time on this, what do you know what's in a default Maui? project, what kind of things are in that template. Allan Ritchie (05:14.582) And we'll see, I work with the templates quite a bit, right? So I generally know, I think I'm ahead of you guys in terms of what's out of the box template. Jon (05:16.974) Yeah. Jon (05:23.502) Yeah, you've definitely added or augmented more. We have to, you know, for many reasons, move slowly and keep it more slim. Yeah. Allan Ritchie (05:27.054) You have to keep it slim. You got to keep it slim. But what's in there today, I think out of the box from you guys is obviously a NuGet packages. Obviously the uses Maui flag. Those are kind of a given. Maui version you don't put out of the box, which I'm kind of hoping you'll change, but we'll see. You can do that with NuGets. Jon (05:47.214) No see I mean yeah well that's a new gets we're not in the box until net eight in the template um so Allan Ritchie (05:54.038) Yeah, okay. Fair. So that's not there. But then you also have your base target, like target platforms, like is it iOS? What's your what's your lowest common denominator? If it's Android, etc, blah, blah, blah. I think that's pretty much it. Jon (06:03.278) Mm -hmm. Jon (06:10.798) Oh, but there's more. Wait, there's more. We also have, I'm just gonna open up a project that I created just to look at it. I know some of the things. There's actually quite a few things in here. Maybe it's gotten to the point where it needs another look at slimming it down. So we've got a bunch of properties, right? We've got, like you said, they use Maui and they use the single project and all that, but we've got things like application title and ID and versions. Allan Ritchie (06:16.398) You don't even remember. Allan Ritchie (06:36.142) Oh yeah, all that stuff. I forgot all about that stuff, see? The assets. Okay. Jon (06:40.014) Yeah, exactly. The Maui icon, the splash screen, the images, the fonts, the assets. And then we've got kind of the supported OS platform version for each platform, right? So if it's iOS, there's a different minimum supported version that you can specify in your app with that. So there's a bunch of different things. And so like I said, when we were starting to do this, one of my goals since I've become, you know, Tolerable of of Emma spilled or almost to the point of liking it. I kind of think it's it's almost Stockholm syndrome ish because it's it's like you you get enough knowledge into how these things work and I don't know if I love it or hate it, but I still keep going back to it I mean, I have to keep going back to it but there's there's a there's a weird appreciation that I feel like, you know you come up with after enough work with it and Allan Ritchie (07:35.886) I find I tend to go into these a lot now because of CI working with MSBuild and stuff. If you don't like doing a lot of top heavies at YAML, which I don't, because it's hard as hell to test YAML. You basically have to go through a day of test failures or test build failures to get it. But here, I could just run the .NET command line. Jon (07:56.334) Yeah, like the old like hundred commits to get the thing working, right? Mm -hmm. Allan Ritchie (08:02.638) see if it's building with whatever stupid things I've done or not done. And at the end of the day, that's gonna produce a version, probably a deployment target, et cetera. Like .NET does all the packaging stuff. And you just pass it environment variables and it figures out the rest. So I tend to do a ton of stuff here now in the CS Proj. Jon (08:26.478) Well, and this is what I want more people to get comfortable with because we get a lot of questions too with, you know, something as simple as I'll take like my app. I have a Maui icon in it. And because of the way that I want my icon to look on each platform, I kind of don't want to use the same values for everything on all the different platforms. So on Android, like you've got the things that compose. of it from a foreground and a background file, right? And we'll do the work to like overlay, like build the resources out for Android so that it's a supported adaptive icon for that platform. That's like one of their features. And then you can specify like what the scale of the foreground image is. And that changes how, you know, how things get put together. So in theory, you can have all that beat the same value. And then we do like our best job of everything for every platform. But in reality, I want things to look a little bit different between platforms. And so like, we'll see this from people over and over again, whether it's your icon or maybe it's an image, like you've got an SVG that you're letting Maui resize to use on a tab bar. Well, on Android, maybe the tab bar size is different than iOS, maybe with the native controls or with whatever you're doing. And so people are starting to be like, well, how do I, so do I have to copy this image twice? And it's like, Well, no, like start learning a little bit of how to use these project files and how to use MS build and learn how to use some basic conditions, right? And so you can do a lot in your own project if you know just a little bit about how to do some of these things. And this is, this is the thing that I keep meaning to build a talk on and maybe doing this episode will help me do that at some point. Cause like a lot of this is hard to explain over a podcast for sure too. But it's kind of that notion of like, Hey, like maybe. let's give everybody the idea that there's stuff to learn in this space and it's not that hard. I mean, there's concepts that are, but if you learn just a little bit, you can do a whole lot more with your app than you maybe realized or did things other ways that was a much harder way to do it. Allan Ritchie (10:38.862) Here's an immediate upsell. If you, if you work with CS proj and you let's actually know, you know what the everybody likes to use the new get package manager, right? Go in, right click, add a new get package. I don't know about you, but when you start to put in Android packages, it takes forever to resolve versions. It goes out and tries to download the internet. Just copy and paste what you need. Stick it in the CS proj, save the file. Boom. It's there. You don't have to wait. I just do it. Jon (10:57.422) Yeah. Jon (11:06.67) Well, I find too, when I'm updating NuGet, sometimes I have enough conflicts that like when I'm trying to update a version of one thing, it's like, oh no, like all these projects need this other version and this other dependency pulls in a different one. And then you can end up in a mode that, you know, isn't super easy to know necessarily how to get out of when you're upgrading. So I kind of, yeah, yeah, exactly. Yeah. Allan Ritchie (11:26.222) and the new get package manager can't figure it out. It's like you tell me, go into your CS Proj anyway. So just go into CS Proj and do it. Jon (11:33.646) Yeah, so, and then that's what I, yeah, exactly. So then you kind of go look up what versions I need, just put it all in there, make it what you want and you're done. And it's easier. Allan Ritchie (11:41.678) Yeah, you know, it's funny because there's not really a thing in like, if you go to the JavaScript world, there is no package. There is a package manager, but there's no real package manager UI. You just do NPM, install this, NPX, install this, right? It's, it's, so just, it's the same thing. Some people even edit the, the, the, the package files directly as well. Jon (11:52.398) Yeah. Yeah, it's all command line. Jon (12:00.654) and Jon (12:05.422) Yeah, and .NET has, like the command line in .NET has those commands too. I'm not sure if you're aware of those, but you can do like .NET NuGet add, you know, whatever version. Allan Ritchie (12:14.254) I did know you could do them. I don't think I've ever done them personally. I don't think I've ever even remotely considered. Yeah. Jon (12:19.342) I never remember this syntax, right? Like I'd, I know to go in the CS project, that's easier than trying to remember what the command is. Allan Ritchie (12:25.856) Right, and in MSBuild, a lot of the stuff in your CS project, a lot of it in IntelliSense, so you don't need... Jon (12:36.078) Yeah, exactly. Allan Ritchie (12:37.528) a command line where it doesn't necessarily IntelliSense any of the additional arguments or maybe that's something they need to do. They need to do AI for command line. Anybody listening? Anybody on the, the, the, okay. Jon (12:47.598) Yeah, that would be great. Yeah, I'm sure there is. I'm sure it's coming up. So with MSBuild, with C Sharp projects, with those files, just to give a little bit of the lesson part of it, I guess, is the main concepts here, if you're new to this, you basically have properties and you have items. You have property groups and item groups. And so properties are just a... you've set a property and that's the value of it and you can change it or update it or unset it by clearing it out. Very, yeah, exactly. It's a variable. And yeah, exactly. It's like a list almost, right? Yeah. Allan Ritchie (13:20.758) Variables. Variables. Item groups, collections. Kind of. Kind of. Kind of. You can have a collection of things with attributes on it. Specific attributes. Jon (13:35.47) Yeah, exactly. It's like objects. It's like items have properties, right? They're just objects. And you can do some interesting things with item groups. And like this is, you know, we won't get into the weeds too much, but like there's, you can compose lists of them. You can remove things from lists. You can use globbing patterns on files and stuff. Now you can do batching operations so that you might have like a list of files you've globbed in and you want to run a target against every one of those files in that list. And that's how MSBuild works. You can do it. Allan Ritchie (14:02.51) with conditions, with the condition on every one of them, right? Jon (14:05.934) Yeah, with the condition, yep. And so that's the other kind of big part of the project files. And I think where most people gain the most value from understanding it is having the conditions, right? So you can say, and going back to my example of the icon, so if I wanna use a different icon on Android, all I have to do is put a condition on either the Maui icon item itself, like that XML element, or on the item group. element that it's contained inside. I can do either of those, right? Obviously where you put that condition is going to apply in a different scope. So if you put that condition on the item group node, it's going to apply to everything in that particular XML node. Allan Ritchie (14:51.726) It's a very order of operations, right? That's the other thing about MSBuild. As you look at these files, it's very much, it looks at it very sequentially, line by line. Jon (14:54.83) Yeah. Jon (15:03.374) Yeah, you kind of read through it. Now there are some weird gotchas in that and saying that like item groups and property groups are evaluated somewhat differently. And so if you open up a Maui project, if you've ever seen, you know, where we use like the, in the condition, we'll use like the MS build function and then get target platform identifier. And then we pass it the target framework property. It's a, it's really long. Like I hate it. And it's something that, um, Allan Ritchie (15:13.966) Mm -hmm. Allan Ritchie (15:29.868) Yep. Jon (15:32.718) I'd really like to see improved and we've had conversations around it. It's hard to get MSBuild team to want to buy into adding like a special kind of attribute to describe this. But one of the operations that we've, as Maui made more common is to say, I want to pivot and condition based on the target platform. So iOS or Mac catalyst or Android. So you've seen that big ugly function. Allan Ritchie (16:01.742) Yeah, I've been told that you don't need to do that full thing anymore. You're saying that messaging is false because I'll be honest doing just the target framework contains works in 99 .9 % of the cases that I abused with it. Jon (16:11.598) Yeah. Jon (16:17.486) Yes, so that does work. You can do the target platform contains. That's an option. The nice thing about, or the thing about using the, yeah, sorry, yeah. So like originally when I didn't know as much about how to spell it, and I still don't fully understand this particular case, but I know that it can break. We would just use, there would be a target platform identifier property. Allan Ritchie (16:26.446) All right, target framework, target framework. Jon (16:44.876) All right, so you kind of think like, well, why don't you just condition on target platform identifier equals iOS. Great. Well, that's where the weirdness comes in with like the order of how things are evaluated. And for a property group, sometimes that in this case, it wasn't, you know, the target platform identifier wasn't filled out by the time the property groups were evaluated, is essentially what happened. And so that wouldn't actually do what you think it would do. Allan Ritchie (16:53.354) Yeah Allan Ritchie (17:12.334) Or you'd stick a version on it, right? So it'd be net eight zero dash iOS 17 point something later on. That's what it comes out to. Jon (17:20.462) Yeah, that could happen for the target framework, but there was specifically a target platform identifier property that should just contain iOS in theory. But again, it's back to sometimes the order of operations is a bit weird. So there are some nuances like that. But generally speaking, like you said, it's pretty easy, straight down. One cool thing you can do is import various files to another file. You can do that explicitly, but... Allan Ritchie (17:26.606) Okay. Jon (17:46.606) One of the things that I know a lot of people have gotten more familiar with is the directory build props files, right? Allan Ritchie (17:52.366) Yep. I use them for pretty much everything. If you're doing any large, any, any Maui projects beyond one single project, which I, you know, once you start to get into the enterprise groups, they'll often have like a lot of projects that are being referenced into the main Maui app. And now they're, they're still using single projects. So they'll still have like an iOS and Android identifier. The problem is, is that the IDE still isn't good at saying, look, just compile the Android side of things or just compile the iOS side of things. So you're able to do stuff in like the target frameworks, right in the directory build props and say, yeah, I don't care about Android today. I just, I'm working in iOS, go away. Right. And it speeds up your build exponentially. So I do that. I do that everywhere. Jon (18:40.366) Yeah, we do that in our repo too. Yeah. And it's kind of a convenient way. So those things kind of get automatically included, depending where you put them in the right directory. So I think it looks like in the current path and keeps traversing up to find them. I think that's true, right? Allan Ritchie (18:55.64) Yep. Yep. I think it's correct me if I'm wrong. I only usually have ever have one like I won't have like a root directory platform or root directory props. I have I have them in the folders and I don't tend to nest. Jon (19:04.128) Yeah. Jon (19:08.366) Now I want, yeah, and I don't know actually if it will keep traversing up if it finds one, like if it, yeah, it might just stop. So that's a really handy thing or way to do it too. One of the other things that I think is interesting is, you know, in your project element at the top of a project file, there's that SDK, right? And so it's like, usually it's microsoft .net .sdk. That actually refers to a, Allan Ritchie (19:13.71) I think it stops. I think it stops at a level. Allan Ritchie (19:28.302) Mm -hmm. Jon (19:36.206) I mean, it refers to an SDK, but that SDK actually could come from a NuGet package. And I don't know if you remember back in the Xamarin days, again, I'm sure you do, what was declared on these SDK extras? Yeah. Allan Ritchie (19:48.886) MSBuild SDK Extras, which every I used it like everywhere, everywhere. Jon (19:56.462) It basically allowed you to do multi to use an SDK style project to build Xamarin stuff for one. Right. And then to multi target with Xamarin stuff. Allan Ritchie (20:06.638) You always could multi -turk it. What it did for you nice was allowed you to be lazy. So you didn't need to necessarily know the version that was like it figured it all out for you. So at the end of the day, we were just putting Xamarin .iOS 10 and mono Android 9 .0, right? Like that's all we were doing, but it was actually under the hood. It was, you had to put a lot more detail and you had to include, again, if we went back to the old big CS proj files, Jon (20:16.366) Yeah. Allan Ritchie (20:35.822) If it was an Android project, there'd be like 5 million extra properties that you'd have to set. MSBuildExtra said, yeah, we'll just do all that junk for you. You don't worry about it. Jon (20:45.646) Yeah, it's like we know what most people want. And if you want to override it, you still can. Like that's the other thing about MSBuild stuff is there might be all of these default set. And we do this to an extent in Maui itself too. But you can always override them, right? If it's a property, you can just change the property, make the value something else that you want it to be. Allan Ritchie (21:05.166) Yeah, because you're at the end of the scale. Your CS Proj is pretty much the last in line unless you tell it it's not the last in line. If you start importing stuff later on, you're the end of the line. So you can change all those variables according to what you need. More or less. Jon (21:10.348) Yes. Jon (21:20.078) And that's the kind of magic sauce for like the workload stuff for Maui too. And the SDK import, right? So that, like I said, that Microsoft net SDK, that's actually pulling in it's saying, okay, like I'm looking for this SDK that is this name. And then that SDK, I forget all the specifics, but there's like a, an SDK dot props and an auto SDK, you know, or auto imports or something. And so it's basically looking for these files by convention and saying, okay, I'm going to import this into the MSBuild evaluation before, you know, there'll be props that go before, which is gives you an opportunity to like the convention is supposed to be you, you set kind of default values and stuff there, right? You're not doing so much like targets and logic of things, but you're setting default values there up top so that. Allan Ritchie (22:05.166) Mm -hmm. Jon (22:08.974) You declare those and then after that imports, your project stuff is evaluated, which gives it the opportunity to override those values. And that's kind of how things fit together. Allan Ritchie (22:19.534) Now, let me ask, here's a good question before you, cause I, you did say workloads. So the pitchforks are about to come out, but let's go back. There is one thing that you guys did. This drives me personally insane. So maybe this is a good, good chance to explain it is so I am doing a lot more of the, the Maui blazer hybrid stuff, right? That was one of those weird ones where you guys decided to flip the SDK as opposed to have a flag, like a use Maui blazer or. Jon (22:25.806) Hehehe Allan Ritchie (22:49.934) So why change the SDK for that one? Right. So why not have like a, like a Maui SDK and that's, that's, that's the Maui SDK. And then you can say, yes, use blazer or don't use blazer or whatever. Why the different SDK only for the, the native? Is it, is it actually not, it's more because of razor and not because of. Jon (22:50.254) So like you mean like the razor SDK that gets set? Yeah. Jon (23:13.87) Yeah, it is a good question. And actually, to be honest, at this point, I don't know if I could recall the nuances to some of it. And maybe we're even at a point where we could look at making that less weird. But I seem to recall early on, there was maybe some tooling stuff or something related to like, no, obviously we needed to pull in the Razor SDK for. Blazor apps to be able to use Razor. Like that, that pulls in a bunch of stuff. But one of the interesting things about how MSBuild is set up this way and like, yes, there's project and there's an SDK attribute, but you can actually specify multiple SDKs that you want to import. There's a syntax for that. And basically you move that one SDK attribute out into its own element within the project element. And you can say like SDK import, right? Allan Ritchie (24:07.662) Yeah, it's important. Jon (24:10.382) So you can compose multiple SDKs that way. So, you know, in theory, yeah, maybe we could have done something a bit different there. I think we needed to import their SDK, but maybe we could have done it, you know, in our own props file and kind of hidden that from people. But I think there was a problem with doing that for some reason or another. So here we are. Yeah. But with the workload stuff, so like the workloads are almost like an SDK in the sense that, Allan Ritchie (24:29.774) All right, one of my questions. One of my questions. Here they come. Jon (24:40.11) So what happens is there's basically we are workload. If you're a workload, you have like a, an entry point, like a, like just like the SDK dot props or targets or whatever. And in that you're always in that file is always imported. Like every workload that is installed will have this file. It gets imported into every MS build evaluation. And that's kind of the entry point where you have to do the lightest thing you can do. Cause like one other thing is they don't. nobody wants their build slow down because your SDK is doing all sorts of crazy stuff when it shouldn't be, right? So it's like, so what we did is our entry point for Maui for the workload is pretty much just a condition on use Maui true. It's a little more nuanced than that, but like that's kind of the story. And as soon as, and I think even that is only checked if the target framework is new enough or whatever, like we do another check there. So like, Allan Ritchie (25:12.27) is evaluating the world. Yep. Jon (25:36.302) We bail very early as a workload if you're not gonna do something Maui related so that we don't impact the evaluation performance. But once we know that we're in, then we're like, okay, pull in our big file of everything, right? And we start messing around with all sorts of different properties and item groups and defaults and stuff. So that's kinda how those things fit together. But interestingly, I think in theory, we could have been just another SDK that gets imported too. But there's kind of implications around compatibility with other workloads and runtime versions that are shipping with the SDK and not with the SDK and stuff like that. So similar mechanism. Allan Ritchie (26:17.39) and workloads. So workloads, because you guys are pretty much every SDK right now is pretty much microsoft .net .sdk unless you're getting wild. There's very few, I think in all fairness, there's probably very few people changing that nowadays. I think that's probably going to change again. I know there's some companies doing some stuff around it because they're getting crazier and hairier with their, their stuff, but Jon (26:32.366) Yeah. Allan Ritchie (26:42.542) So your SDK or the Microsoft .net SDK basically pulls in the world but tries to get rid of the world real quick. So whatever workloads I have installed, which I love to say Pitchforks because there's a lot of people that hate on the workloads. I get it. I get it. We won't tackle that one today. Well, that'll be specifically John talking about it and answering the tough questions. That's one I will get involved because... Jon (27:02.062) That's a whole other episode I think we could do, we could talk about. Allan Ritchie (27:11.15) I think the community in general doesn't understand them and what they do understand, they don't like them, but. Jon (27:15.374) Yeah, there's some friction points. And I mean, it's something that's kind of still a work in progress. Like there are some new things that will be coming to workloads that should help make some of that, the understanding and management a bit easier. I think what happened is the idea of workloads was good. For one, you want to give some sort of... assurance or comfort in people knowing that like, Maui is a part of .NET, even if it's a workload, it's still like a very official part of .NET, right? So like there was some kind of element of how that feels from a trust perspective, I think. And the goal ultimately with workloads and why, so like Maui could have been part of the just pure .NET SDK. The problem is that adds a lot of size to the SDK. And the goal is not to keep loading the dotnet SDK in solar size, but rather to shrink it down. So, you know, longer term, I know there's some talks of looking at like, well, how do, how could we turn, you know, ASP net into a workload? How could we turn, um, WPF into a workload, that kind of stuff, right? Because that, if you want to download .net and you can say, here's the core SDK itself and it's like 30 megs, that'd be nice. And then. Maybe I want to use ASP .net. Maybe I don't. Maybe I want WPF. Maybe I don't. But those things are in the box today. And so extracting them out is kind of a common or a logical next step, right? And so workloads, when Maui, we had the opportunity to come in, there's like, well, let's not bloat things right from the bat, off the bat. And so like this concept of workloads was created. But I think the reality is somewhere that, you know, like Maui in terms of quality and the We're sitting at the top of this big pyramid of different things that we have very little influence over, right? Like from Xcode to Android to whatever. And then it bubbles up the chain, like from, you know, the runtime, which we have more control over because that's part of Microsoft. Um, but we're at the very top and it's really hard to get the layer that we have of all these abstractions perfect. And it's just a very, it's a much more volatile, um, piece of the whole puzzle. Jon (29:38.19) Right? So we want to iterate more rapidly than I think originally the idea for workloads was created, which was essentially like major .net release. Good for a year. Like, well, no, that doesn't really cut it for mobile. Allan Ritchie (29:51.854) So did John sell people on the workloads? Leave us a comment. I'd love to know. There's our sell. Because I know most people will come out of the woodworks with their pitchforks and their fire torches and stuff with workloads. But I think I get them. I know why they're there, because you guys need to be involved later in the process before all this other craziness gets involved. So it's almost before Nougat can really get going or any of the transitive old stuff. Jon (29:57.358) So. Jon (30:05.422) Yeah, I think it's... Jon (30:20.846) Yeah. Yeah. So that is the main reason. Yeah. We do need to be in injected into the build earlier than you get allows us. And, and, you know, so I think it's fair to say though that, you know, workloads was a big thing to bite off and, and maybe didn't do the best job of it all up. Obviously. I mean, that's fine. We we've struggled internally with workloads. Like this, I don't want to try and pretend like this whole thing was excellent and perfect and everyone loves them. There's still a lot of pain and. Allan Ritchie (30:22.306) So it's at the lowest level. Jon (30:49.038) One of the things we did to kind of ease that pain in the interim while things get better is to do more of our stuff in NuGet. So there's still like the Maui workload itself, but the workload contains actually very little now. And it actually brings in implicit NuGet references to the NuGets. So the idea is like, yeah, you can just install the Maui workload. You might have like the same one from GA, although I think... Allan Ritchie (31:09.134) to do the stuff. Jon (31:18.318) you need to go newer now for iOS. It's a whole other subject. But then you can install a newer NuGet package and that's given people an easier way to like kick out, you know, kick the tires on nightly builds and service releases that are kind of coming up before we push them into the workload and that sort of thing. Allan Ritchie (31:35.15) But I think that's the key point to bring up. If we're talking about MS build and we're talking about workloads, the key thing that you said there is basically the workloads, again, they need to be in the box in a kind of manner of speaking or at least official, but they need to be involved before anything else, right? Before Nougat can get involved. So you guys need to be at the bottom layer. So regardless of implementation of workloads being good or bad for the community, there's obviously some challenges. Jon (31:40.62) Mm -hmm. Jon (31:49.42) Mm -hmm. Allan Ritchie (32:03.118) But the main premise of why they exist is so that you can, you could do all that MS build stuff before anything else, right? Because you're at the core of the product, right? You need the core SDK stuff to spin up before, you know, me, the peon starts really screwing up your stuff. Jon (32:21.806) Yeah. And that's not to say, so like, you know, keeping on the subject of, of MS build and stuff. One of the things that I find very cool about how MS build works is the fact that you can import some MS building things from new gets, right? So that we, we need that injection point, but at the same time, if you have a new get package, you can ship prop files and target files. And if you do it in the certain convention, right? Like this is kind of an aha moment for everyone when they see this and use it. which is basically I stick a file in my new get package in the right folder. And if it's named, you know, the right name, which is like the package identifier dot props or dot targets, I must build. Yeah. And Ms. Build automatically then imports that, you know, into the project that's referencing that new get, which is really cool. So I know like shiny does a ton of this, right? Allan Ritchie (33:01.07) in a bill holder. Allan Ritchie (33:12.59) I don't do anything with targets right now. I took it out. I was doing some auto imports and stuff and people like, no, no, no. Okay. So I took that out. And I've switched to a lot of source generator stuff. So I don't need to do as much. It's coming back. I think recently, you know, you and I have been talking about entitlements and all the permission stuff and all that wacky stuff that's coming out and. Jon (33:15.694) No? Okay. Jon (33:28.622) Okay. Jon (33:36.174) Mm -hmm. Allan Ritchie (33:40.78) MSBuild has some stuff there, not necessarily for code generation, because if you're going to do code generation, you want it to be part of the compiler. That's how you got me out of my madness, because I was like, I'm going back to MSBuild everything. And you're like, no, no, no, no. If you needed to be involved in code genning so that the IDE can see it, you have to do it in MSBuild. Or you have to do it in source. OK, fine. But something that I am doing is before all the build stuff is when I've got complicated custom entitlements. Jon (33:52.222) Nah. Jon (33:57.934) Yeah. Yep. Allan Ritchie (34:09.838) I can generate them based on a whole lack of like, cause MSBuild sees the world, right? Source generators, you have to ask forgiveness, right? Jon (34:18.35) Yeah, you can see some MSBuild things passed into them if you ask and do the right things. Allan Ritchie (34:22.382) You have to say, please give me these files. And then you have to check them because sometimes they're not available. MSBuild doesn't care. It can see everything from the ground up. It can navigate directories. It's great. So I've been looking at that for building custom entitlements because there's a whole bunch of whack. There's a whack job going on there. I mean, the iOS team has made some improvements there, but I think this was like even more hardcore. Jon (34:34.924) Mm -hmm. Allan Ritchie (34:47.438) So I go through, I iterate the packages, MSBuild generates it before the build, it generates an entitlements file, the build includes it, it's great, right? So, and I'm doing that with a target, a target early. Jon (34:57.934) Yeah. And this is like, you know, a good example of, you know, that's a little bit more leaning advanced, but you know, one, one thing we have seen a bunch too, as customers who are trying to make like, either you're trying to make a new get package that you're, you're sending out to the world for someone else to use. I've seen some customers trying to do like their own new get packages for their own internal use, which I, I generally shy away from unless, you know, the customer is obviously. knowledgeable in the area or willing to be knowledgeable in the area, right? Because what often happens is like, well, I have this Maui library project. We have Maui images in it. We pack up a NuGet and then we reference the NuGet and the images aren't there, right? So it's like, okay, well, I'd love for that in some ways to automatically happen for you. But at the same time, I don't want it to automatically happen because That's when people like start including all sorts of junk that they didn't think they or didn't know they didn't want to include. But for example, like this is a good opportunity. If you want to do something like this, you can add a targets file to your NuGet package that has, you know, Maui image item group items, and you pack the image file itself in the NuGet package and you pack this targets file in it. And then a project imports this NuGet or references this NuGet. And those item group items will then get added to the build. And that's how you would actually get those images to flow through from the new get package into your app. Allan Ritchie (36:29.262) That's interesting because that's something I've never done. But when you think about it, if somebody wanted to include some asset, like a theme library, for example, or icons, I guess, icons is a good one, right? They actually have to copy over because they're... I actually haven't done that. I need three docs on that one. Jon (36:41.262) Yep, sure. Jon (36:47.214) Well, and same idea for maybe not entitlements, maybe not entitlements how you're using them, but, um, you know, one thought that comes to mind, like if I, if I have a plugin that I'm building that does something specific, that is always going to need a certain entitlement. Um, I just don't want title menses. No, we can do it. No, I'm a spill now. Right? I could include a props file that were a target or a targets file. I forget where you might need to do that one. Uh, that would add the right, like entitlement item group item. that my library is always going to need. And then that will just flow through the app that the user is building and referencing your NuGet package in and do the right thing for them. So there's some really cool things you can do in libraries as that level of author to make people's apps just automatically work with them. I always love being able to do that in a library. Allan Ritchie (37:17.838) Right. Allan Ritchie (37:38.99) And funny enough, what you were talking about with the entitlements. So there is now an item group item called custom entitlement that you can actually add as if it was going to go into the iOS entitlements, because that's something a lot of things need to change for builds, right? So if you're going to certain environments, your push entitlements, your app groups, all that stuff that tends to change based on release processes. So now that it's an MS build. Jon (37:47.212) Mm -hmm. Allan Ritchie (38:07.63) or the CS Proj, I guess it's the better place to say it. You can change all that dynamically without having to do, you know, without having to have like 600 entitlement files, you can just do it right in your CS Proj dynamically. Add conditions. I do it in the Shiny template. I basically say if you're using a push library, if it's debug, you're going to development APNS. If you're release, you're going to the production one. It's great. It's great. You can do it all there. Jon (38:36.91) Yeah, yeah, and then you don't have to have separate files and that. Allan Ritchie (38:37.134) without multiple entitlement files. The case I was talking about with MSBuild though, the one that I'm working on is far more complicated. It's going through a whole lack of libraries and stuff, so. Jon (38:46.862) Yeah. Um, and I think, so you mentioned earlier too, that you do a bunch of stuff like build related in your, your project files or, or maybe not project files, but in MS build in a directory build props or something like that's another area that I think is, is a really neat place to explore for people. Like if you're doing got to download some zip file from some server that you need to use assets from that you don't want to have to like, manually do before the build, right? Like in theory, most people could make their project always buildable from .NET Build, even if you had like some weird pre -steps that you have to do, right? There's tasks in MS Build for things like this. There's stuff for downloading files, there's stuff for zipping or unzipping files, for modifying XML files, all that kind of thing. Like what kind of stuff do you end up doing in that space? Allan Ritchie (39:40.43) I don't go crazy like that. I don't want to be downloading or zipping files. That's for sure. I'm glad you can. And it makes sense that you can. Thankfully I don't. What I'm doing from a global kind of target perspective, I know there's central package management now for NuGet. I don't really work with that yet because I've been using targets forever and it just works. But I'll do stuff like install my global packages. So when I'm authoring, Jon (39:57.068) Mm -hmm. Allan Ritchie (40:08.406) Components so like shine the shiny library. There's two libraries. I need an everything I need git versioning nerd bank git versioning and I need source link It just it goes into every single library that gets built. So I install them at a global level I like to control I know John and the Maui team didn't like it, but I like to control kind of how I'm globbing the directories for Cross -platform so I do all that stuff there. So it applies through all of the libraries. That's just the way I like to work Jon (40:36.718) Mm -hmm. Allan Ritchie (40:38.35) I deal with all the NuGet packaging, like the icon, the read me and how that gets packaged. And then the other, I guess, kind of the wild thing I do there is, is how I set up the targeting for target frameworks that I'm going to use like iOS. For a while there, I was building net six, net seven, net eight. And I was building the classic Xamarin, Xamarin iOS 1 .0, mono Android 12. So, which was complicated. We won't even get into how I had to get around that. Jon (40:54.06) Mm -hmm. Jon (41:02.798) Oh yeah, all the things. Allan Ritchie (41:08.365) So I said to say it was tough. Anyhow, I did a lot of that at a global level in a directory build props and targets to do all that work. Cause I didn't want to do it in, you know, the 13 or 14 libraries that I had at the time. Jon (41:10.382) Yeah. Jon (41:24.11) Yeah, yeah. So like that's, I mean, that's a common pattern, I think. And I use that too often where I, even if I, you know, even if it's like copying and pasting, like, you know, the directory build props between different repos or projects that I have, so that at least it's like one place that I know and all my different totally unrelated projects to go to like set, you know, my new get package copyright name and all the different stuff, right? It's just kind of a nice way to, to be able to do it. Allan Ritchie (41:46.71) Yeah. Allan Ritchie (41:50.926) I think I do. Oh, yes, I do do that as well. And that's the thing. It's all in there. It's all at a global level. Jon (41:54.542) Have you, have you? Have. So you've you've not you're not doing a lot in terms of like, you know, doing weird like zipping and downloading and stuff like that. Have you gotten into doing custom tasks at all? Allan Ritchie (42:10.094) Yeah, I do a bunch. Not so much with Shiny, more in terms of professional projects, right? So like I said, that entitlement's one that I'm doing. That was a custom scenario where custom entitlements wasn't quite fit in the bill. It wasn't rich enough. Custom entitlements, that item group type is relatively new. So this guy... Jon (42:21.132) Mm -hmm. Jon (42:26.22) Yep. Jon (42:34.318) Yeah. Allan Ritchie (42:36.878) doesn't have any of the restrictions. So I just said, look, I'm building a custom MS build task. It will iterate the project, how it knows to do it. It'll figure out all the entitlements that need to happen from each one of those projects. Again, it's a weird professional project. I don't need to go too much into detail, but that thing has the view of the world. It gets the world and it generates the entitlement that needs to happen. Jon (43:01.486) So is that a custom task that you're truly writing in C sharp and building into a library? So that, I think, is one of the really powerful things. I kind of look at it as different layers. First of all, it's like, is there something that's just baked into MSBuild that helps me do what I want to do? If not, maybe I can make a custom target. So a target is kind of a just. Allan Ritchie (43:06.126) Yep. Yep. Jon (43:28.27) declaration in the XML in the MS build of a thing that runs and it could have dependencies and can have ordering kind of relating to other targets. And in those targets, you can have, you know, you run different tasks and stuff, right? Um, and so like the task is within your customizing, you might build a target, but that's not a C sharp thing. Really. It's just a, an XML like, Hey, here's my target name. I want this to run before. core compile because you know, I want to have something available, you know, after that. And then it's going to invoke my tasks. And so often it's starting with a target and then maybe that target you're able to like use existing MS build tasks. I know there's also like new get packages out there that add more commonly desirable type tasks that aren't available out of the box. And you might be able to cobble together like your solution for what you're trying to do with that. But then if that doesn't work, kind of the next level is like, yeah, go get into C sharp, you know, subclass the MS build task API or class and implement the thing yourself, right? Which is super powerful and not that hard to do really. Allan Ritchie (44:36.942) No, it's pretty much an input output, right? And even taking variables from like input variables and output variables, they're just attributes on properties in MSBuild, like an MSBuild task. So it's not even like the classic, because basically you can look at an MSBuild task almost like a console app, right? It's essentially one line. You implement an abstract class, you have to implement the one method that they have, but you can have it all. Jon (44:48.878) Yeah, but those are. Allan Ritchie (45:06.488) all your inputs and outputs instead of trying to parse it and validate it. You can have, this is the type I'm expecting to come from MSBuild. It's an input variable. This is the name and it's all in attributes. It's actually quite beautiful. I wish all the console frameworks worked like it. Jon (45:13.806) Mm -hmm. Jon (45:21.966) Yeah. Yeah. And then like for the targets, the inputs and outputs are, you know, super important too. And not, you don't have to use them. Um, but the cool thing is once you, this is getting more into the weeds, but yeah, I mean, if you, if so, if you specify, you know, inputs, which might be like, I have a bunch of text files that I want to do something with something special. And so that might be your set of inputs and then your outputs might be, Oh, I have like one. Allan Ritchie (45:32.686) Yeah, we're definitely getting in the weeds. Jon (45:50.228) weird binary format that I transformed these text files into that it needs to be included in my app for something special, or it might be multiple files or whatever. But if you specify both of those things, MSBuild will be smart enough to kind of detect like, did any of the inputs change since the output file that exists, you know, was created? And so it'll know to skip targets and stuff during builds when it doesn't need to run because it knows, because you told it what... what it's getting and what it should be outputting. And it's going to kind of reconcile that for you to see if it needs to run or not. Allan Ritchie (46:27.346) Is resized attizer as an MSBuild task, is it not? Jon (46:31.118) It's it's a it's a it's several tasks and targets and you know the new get package of the props and targets files including all those things. Yeah, it's there's quite a few things in there. Allan Ritchie (46:34.03) Okay. Allan Ritchie (46:42.126) It's important to understand because you can do a lot of things with source generators. Like you can read text files. It's just source generators build into the compiler. So as things are generating from those files, your compiler sees it right away. MSBuild, like I said, John saved me from going just insane with them. But it really happens before or outside of the main C Sharp compiler. Jon (46:57.326) Yeah. Jon (47:08.462) Yeah, I think the rule of thumb is basically if you need to emit source code that needs to end up, you know, in, in the resulting app, you need to use source generators. And one of the big reasons for that, like we used to even with, with Xamarin forms and stuff. And actually we still, so, uh, yeah, Rosalyn is the problem, but we used to emit like IL and we still actually do emit IL for XAML compilation. Cause the XAML compilation, Allan Ritchie (47:27.818) Roslyn. It's Roslyn's problem. Jon (47:39.182) we don't use during debug mode. And that's the key point here in what I'm going to say. Um, but if you need to emit code that you're going to, to have in the app that you're debugging, if you don't use source code generators, Roslyn doesn't understand anything about the code that you are emitting. And in our case for a Maui app, that was basically making hot reload, like C sharp hot reload just not work because we would, we need to emit code for like when you have a XAML, control and you give it a name, right? The X name attribute. We emit some code for the kind of the code behind stuff that creates like the field on the class and everything for you to be able to reference that from code. And so originally we didn't do it that way. And that just is a non -starter with hot reload stuff. So if you need to emit code, you gotta use source gen. And then for most other things, you know, if you can avoid source gen, that's probably best for. your own sanity and for performance and all that kind of stuff. But yeah, then MSBuild is your friend. Allan Ritchie (48:40.526) Source generation can be tough. That's for sure. It's tough to debug. It's tough to work with. MS build task. I know it sounds scary. Sometimes the registration of it can be a bit of a pain in the arse depending on how you're registering it and pulling it into the NuGet package. But once you've got the pattern down, it's pretty stupid simple. And it's basically, you don't have to obey any permissions. You can iterate directories. I mean, Jon (48:46.286) Yeah, it's not easy. Jon (48:52.846) Mm -hmm. Allan Ritchie (49:08.942) If you wanted to do a virus, not that I'm suggesting do a virus. If you're going to do a virus, I can see this is the place to do it. Don't go mate rating virus though. Leave Nougat alone. Jon (49:18.094) Yeah, it's a super powerful area for sure. And so yeah, like for resizatizer, we're not emitting any code anywhere. We're just changing like some images and we're emitting like resources and stuff that Android will compile in eventually, but nothing that .NET, that C -sharp or the Roslyn needs to care about. So that's an obvious choice to use that. It's not too bad to make those things like testable and debug them either. You can, you know, there's, there's packages that you can kind of wire into a test project that let you basically new up your task and invoke it and test it out that way. Right. So, it's not too bad. It's definitely powerful. And if you're, if you're really, you know, the best developer out there and write zero bugs, you can actually just paste your C sharp. for a task inline into your MSBuild C Sharp project. Yeah, it's really ugly, but it's kind of handy in a pinch. Like if you have just a really little bit of C Sharp that you're like, I know this works. You can just drop it in, but yeah, that's you. Allan Ritchie (50:18.285) Oh. Yeah. Allan Ritchie (50:28.59) So whenever I have MSBuild tasks, I usually go to Dan Siegel or I go to John and I call both of them Mr. MSBuild. The only problem is John keeps telling me to do it as inline. I'm like, no, no, icky. It's like C sharp mode in XML. It doesn't IntelliSense. It looks like hell. And to debug it's even harder. Just put it in a task and debug it. It's just easy. Jon (50:42.798) Yeah, it is gross, but like. No, yeah. Yeah. Jon (50:52.174) Yeah, that is the right way. I only say to do that because I'm super lazy and I'm like, I don't want to set up a whole project for this and then have to include the DLL and I'll just, no, I'll just do it in the task, but you're right. Allan Ritchie (50:56.75) Hey. Allan Ritchie (51:03.79) But he kept asking me, did you do it in an inline? No, I didn't do it in an inline, John. I put it in a task. That's what's gonna go. Jon (51:12.32) Yep, yep. And also when you ask me questions, I often don't know the answer because I'm not actually Mr. MSBuild. I always go to another favorite Jonathan, which is Jonathan Peppers, who seems to know most of the MSBuild answers that I need. So I have a resource there that I get to cheat with. Allan Ritchie (51:29.198) Oh, well, see then. You do more MSBuild stuff than I do, let's be fair. Jon (51:37.966) I have maybe, yeah, in the past. Yeah. Allan Ritchie (51:39.118) Eh, probably. Probably. But anyhow, it is a powerful system. I'm using it for a lot of stuff now. I do some of the guinea pig stuff for John apparently now. I know it now. He's just admitted to me. He's not really Mr. MSBuild. But again, you can do a lot of stuff outside of it. It's just easier. Source generators are painful. I've gone that route. I will go that route because it really is the only route to go, but I wish they were easier to make. Jon (51:53.23) That's great. Yep. Allan Ritchie (52:08.046) is this. Some of that stuff is really tough. And then to make it perform with your builds is really tough. Jon (52:08.078) And honestly. I... Yes. So that's the hardest part, I think. And I think that's been fixed a bit with, you know, requiring, like doing the incremental source gen stuff. But I know... Allan Ritchie (52:21.87) which made source generators that much harder by the way. Jon (52:25.742) Yes, yeah. And I know that those teams would like, you know, if I think if you had to ask them, they would say like, don't build a source generator unless you really know that you need to build a source generator. And if you think, if you don't know for sure, or you think you're not sure, you probably don't want to do it, right? Cause the other part of it is, you know, we I've seen this in other packages too, where there's a source generator that if you try and do things kind of too broadly, for instance, and kind of inspect too many different. possibilities, it's not going to perform well. And then that team eventually is going to come knocking on your door and ask you, can you please fix your source generator so it's not slowing everybody's Roslyn sessions down? So that's something that they have to struggle with too. Allan Ritchie (53:08.622) Yeah, I had that with the source generator in version two of Shiny and the VS for Mac team was like, hey, this guy's coming up. And I was like, well, yeah, I know. Jon (53:22.478) Yeah, it's one of those like, please don't abuse it. Like, don't do something you shouldn't even if you think you maybe want to. Allan Ritchie (53:29.902) Well, and then I started putting attributes on things and then people were like, what do I have to put an attribute on it? Like, cause I'm not skiing in the world for you. This is it. You pick your poison, man. This is how it's going to go. Jon (53:35.398) Yeah, exactly. Yep, yep. Well, that's a lot of MSBuild stuff. One of the things for this week's plugin package or product, I know that you had brought up Michaela's MSBuild editor extension for VS, which is a really cool thing. Even if you don't want to write a lot of complicated MSBuild stuff. Have you used this one yet? Allan Ritchie (54:00.622) Yes, I actually, this has been in a beta for a while. And I think actually today, so now they know the date of this episode when we recorded it. But I think today they released like an F it's an official preview now, right? So it's like a thing that you should use if you do an MS build. So I've been using it in visual studio for, I don't know. I think it's been out for like a year though. And just iterating on constantly, but it works well. It IntelliSense stuff like NuGet packages, other properties that you've created. So if you put a property in as a group. Jon (54:04.268) Mm -hmm. Jon (54:13.838) Mm -hmm. Jon (54:22.318) Yeah, it's been out a while. Allan Ritchie (54:30.712) It'll tell you what the current evaluation should be. It's pretty cool. It's actually quite helpful. Jon (54:36.238) And and one yeah, I think just even the new get package, you know versions and search kind of thing in itself is just handy, right? Allan Ritchie (54:41.078) Yeah. Yeah, it goes into IntelliSense that you type in like something like shiny. and it goes, here's all the packages that manage. I'm like, oh, wow. And it's so that that's pretty cool because like I said, I forget versions. Try doing that with support packages. Jon (54:52.172) Yeah. Jon (54:58.126) Oh yeah, no way. No, thank you. Allan Ritchie (54:59.438) But that's awesome. This thing does it for me. So now I still don't, I still, I know that was one of my big gripes. If you don't like editing CS Proj, but you, but you hate NuGet performance, edit CS Proj. It's just faster. You just go in there and type exactly what you want, press save and it's there. No fighting. Jon (55:14.092) Yeah. Jon (55:19.022) Yeah, no, I almost exclusively now edit my projects directly. Like I know, and really even in VS now, like the double click is opening the project file, right? It's not like in VS Mac, unless I had to do a setting for that, I don't know. Allan Ritchie (55:33.678) Is it? I think you did a setting for that. I don't think that's true. Jon (55:37.294) Uh, well, I like it that way. I want it that way everywhere because I just double click the project now and it's just like, oh, boom, here's your CS project. And then I can just edit it. Allan Ritchie (55:39.336) I'm Allan Ritchie (55:44.462) Are you sure that's not VS code, John? Jon (55:47.662) Yeah, no, I'm doing it right now as we speak. To get the property page, I have to actually go right click and go to properties. Otherwise, it just... Allan Ritchie (55:49.878) Okay. Allan Ritchie (55:54.926) Just making sure because you tend you know VS code is the latest and greatest and you're approaching 40 So memory starts to go a little bit after that Jon (56:02.126) It's true, yeah it's true. But no, this is the way. So yeah, I think that's a pretty good first shot at MSBuild. Anything we missed? I don't think so. I mean, we missed lots, there's tons more you can do, but that's kind of the first thing. Allan Ritchie (56:19.63) Well, it's hard to it's also hard to do a podcast on it because there's so many things involved like hey, hey type dollar sign phrase brackets here right like. No. Jon (56:22.606) Yeah. Jon (56:27.886) Yeah, yeah, we can't really show you examples. But what I hope to achieve from this is that if you've listened to this, that you put on your brave big kid shoes. I don't know why that's a thing, brave. Yeah, no, I'm not suggesting that you go figure out workloads, but I'm suggesting that you just give, looking at your CS project and really starting to think about how you might use it. Allan Ritchie (56:42.702) Here come the pitchforks again. Jon (56:57.102) and use like conditions and use different things here and there, give it a try. Learn a little bit about it, get comfortable with it. And you know, it's gonna serve you well if you learn a little bit about it. Allan Ritchie (57:09.998) I agree. That's all I got. I use it everywhere. I've been editing CS Proj for a while. Jon (57:17.934) Great, well, I think that'll do it this week. So, you know, get out there and try your CS project. Let us know on gontenmobile .io if you have more questions about CS projects or if you want to tell us that, you know, your world has now changed because you've discovered this and it'll never be the same and your apps are awesome now. And if that's also the case, obviously you owe us a five -star review on app. Apple podcasts or some other podcasting platform. So get out there and do that as well. Allan Ritchie (57:50.158) Leave some feedback for John's dad jokes. Jon (57:52.91) That's right. No. Oh yeah, sure. Why not? All right. Thanks all. We'll see you next time. Allan Ritchie (57:57.902) Thanks everybody.