Created
May 30, 2018 07:39
-
-
Save lucasmeijer/bb8c4e9cd08285a1e6bdb6e9e96ddd01 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Visual Studio project generation is quite a topic. Grab a coffee. | |
A visual studio _project_ always has a "Configuration" string, and a "Platform" string. | |
You're free to choose whatever configuration string you want, but the platform string has | |
to be from a finite set of known values. ("Win32","x64","ARM", "ORBIS","CRT"}. | |
Some visual studio features (I'm not sure exactly which, but at minimum debugging, and some console things), | |
require that the platform value is set correctly. You cannnot debug an orbis executable without having its | |
platform set to ORBIS. Platforms that don't have any fancy VS features (like emscripten) are free to just set Platform to x64. | |
So far so good, all very reasonable. | |
Now a solution has multiple projects. Some of them might share similar configuration strings, some might not. | |
A solution also has a list of Configurations, as well as a list of "SolutionPlatforms". both of these lists | |
can contrain arbitrary values. In the .sln file, each combination of SolutionConfiguration/SolutionPlatform needs | |
to be mapped for each project in the solution, to which ProjectConfiguration/ProjectPlatform combo it should map. | |
The two dropdowns that you see in the visual studio user interface, they control the SolutionConfiguration, and the | |
SolutionPlatform. The mapping of solutioncombo to per-project combo is stored in the .sln file, and can be visually | |
inspected using the configuration manager UI. | |
Traditional projects use the ProjectPlatform to switch between different architectures. Win32/x64/ARM for instance. | |
Bee's project generation chooses to not do that, and instead to only use the configuration string. A ProjectConfiguration string | |
for a NativeProgramConfiguration would look like "Debug_UWP_ARMv7_Lump". | |
The only thing we do with the projectplatform string, is to ensure it's set to the value that VS requires it to be for a project | |
to properly function. On the solution level, we only setup a single "Default" SolutionPlatform, and have that map to the only | |
valid value for each project. | |
Different NativeProgramConfigurations that have different architectures are "encoded" by making multiple ProjectConfigurations for them. | |
This choice is made like this for 1) simplicity, 2) it makes it much harder to select through the UI a combination that | |
does not exist. (traditional setup allows you to choose ARM platform for a PS4 configuration, just because there is another | |
program in the solution that does have ARM as a valid platform. 3) for symmetry wih other IDE's who tend to have | |
a simpler setup that has one list of configs. | |
Ok, so we have a bunch of projects that each have a list of valid ProjectConfigurations. (ala "Debug_UWP_ARMv7_Lump) | |
Now we need to make a list of SolutionConfigurations. The strings we use for solution configurations have some more constraints, | |
because it's the list that shows up in the UI. The UI they show up in is very narrow, so really short names help a lot. | |
The list is also used to choose what is the default SolutionConfiguration, so we want to make sure we setup a reasonable default. | |
The UI is consumed by humans, so it would be nice if it's not 200 items long, and it would be nice if popular configs are near the top. | |
All ProjectConfiguration/ProjectPlatform combos for all projects need to be "selectable" by selecting a SolutionConfiguration. | |
If a NativeProgram only has one NativeProgramConfiguration, there is no need for that NativeProgram to cause an extra SolutionConfiguration | |
to be created. Any SolutionConfiguration will map the the only ProjectConfiguration. | |
We always make a "Debug" and a "Release" solution configuration. If a NativeProgram only has 2 NativeProgramConfigurations, that only | |
differ in CodeGen, we make Debug solutionconfig map to the CodeGen.Debug one, and Release solution config map to the CodeGen.Release one. | |
In this case there's also no reason for this NativeProgram to cause an additional SolutionConfiguration to be added. | |
If a NativeProgram has these NativeProgramConfigurations, we would create these additional solutionconfigurations: | |
(CodeGen.Debug, WindowsPlatform, x86, Lump) Win_x86 | |
(CodeGen.Release, WindowsPlatform, x86, Lump) Win_x86_Release | |
(CodeGen.Debug, WindowsPlatform, x64, Lump) Win | |
(CodeGen.Debug, WindowsPlatform, x64,NoLump) Win_NoLump | |
(CodeGen.Release, WindowsPlatform, x64, Lump) Win_Release | |
(CodeGen.Debug, UniversalWindowsPlatform, x64, Lump) UWP | |
(CodeGen.Release, UniversalWindowsPlatform, x64, Lump) UWP_Release | |
(CodeGen.Debug, UniversalWindowsPlatform, ARMv7, Lump) UWP_ARMv7 | |
(CodeGen.Release, UniversalWindowsPlatform, ARMv7, Lump) UAP_ARMv7_Release | |
(CodeGen.Release, EmsciprtenPlatform, AsmJs, Lump) Emscripten | |
Notice how we always start with the platform name. And then only encode the architecture if there are 1) multiple NativeProgramConfigurations in the solution | |
with that specific platform, that have different architectures, 2) _and_ the architecture is different from what is the "most natural" architecture for this | |
platform. Same logic is applied to codegen and lumping. Most natural codegen is always debug, most natural lump setting is lumping. We then sort the list | |
by making entries that have more of their values set to the "natural" value to be at the top, so the sorted list ends up being: | |
Debug | |
Release | |
Win | |
Win_x86 | |
UWP | |
UWP_ARMv7 | |
Emscripten | |
Win_Relase | |
Win_x86_Release | |
UWP_Release | |
UWP_ARMv7_Release | |
//TODO: Talk to aras about "ehm, can we even sort?!" | |
The reason we always make a Debug and Release config, is that it's often desirable to have a solution config that just makes all projects map to their "most natural platform, | |
most natural architecture.". | |
Now that we have our list of SolutionConfigurations, the only thing left to do is decide for each project, which ProjectConfiguration this SolutionConfiguration maps to. | |
For many programs there will not be a perfect match. Like when my project is not setup for Emscripten, but the SolutionConfiguration is set to "Emscripten" anyway. We do the | |
mapping process like this: | |
- we need to choose a NativeProgramConfiguration this solutionconfiguration maps to, from our finite set of valid NativeProgramConfiguration. | |
- our candidate list starts with all valid NativeProgramConfigurations for this NativeProgram. | |
- if any NativeProgramConfigurations match the Platform of the chosen SolutionConfiguration, our candidate list narrows to those. If none match, candidate list stays the same. | |
- If any of the remaining candidates have a matching architecture as the chosen SolutionConfiguration, our candidatelist narrows to those. If none match, candidate list stays the same. | |
- if any of the remaining candidates have a matching codegen as the chosen SolutionConfiguration, our candidate list narrows to those. If none match, candidate list stays the same. | |
- If any of the remaining candidates have a matching lumpsetting as the chosen SolutionConfiguration, our candidateslist narrows to those. If none match, cadidate list stays the same. | |
- we choose the first of the remaining candidates. | |
- If NativeProgramConfiguration is subclassed and more settings have been addded (UnityPlayerConfiguration adds ScriptingBackend and DevelopmentPlayer settings), those get processed the same way. | |
The order in which all settings are filtered should be in "most important settings first, least important settings last" | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment