premake / premake-core

Premake
https://premake.github.io/
BSD 3-Clause "New" or "Revised" License
3.22k stars 620 forks source link

How to deal with Visual Studio 2017 mid-release project format changes? #971

Open tvandijck opened 6 years ago

tvandijck commented 6 years ago

So, we ran into the following issue.... Premake for Visual Studio 2017, while it works, if falling behind, because the amount of changes from VS 15.0.0 to VS 15.5.1 is quite large. More importantly, premake doesn't know which one it is targeting... we just say "vs2017", and I certainly wouldn't want to start making a new action for each new vs2017 release either...

but both toolchain, as well as the IDE has new settings, others have been removed, etc...

Anyone have a solid idea?

RevoluPowered commented 6 years ago

I think you would be best to design a template like system for your .sln generator which lets you turn tags on and off. You can then use a config file to have the various version number tag changes based on the version, horrible idea but maybe you can expand on this idea.

Then in the file just have something like: "vs2017.json" { { "version" = "vs2017.2" "disabled_flags" = "some feature or depreciated setting list" "enabled_flags" = "some flags which need manually turned on" } { "version" = "vs2017.3" "disabled_flags" = "some feature or depreciated setting list" "enabled_flags" = "some flags which need manually turned on" } }

Obviously the version flag stuff is annoying because it also means you will have to detect the IDE version reliably.

Or alternatively output a vs2010 sln files and make people upgrade them and let Microsoft handle the upgrade for you in their IDE :)

Both are horrible workarounds, maybe try getting in touch with Microsoft Directly, they might be able to help you out.

starkos commented 6 years ago

Well…presumably VS can handle upgrading from version to version. I'd say just add things as they are needed, or as they become an issue. I wouldn't try to keep up for the sake of keeping up, but just address things as they come (as we do with upgrades to older versions of VS, even if those happen less frequently).

tvandijck commented 6 years ago

The problem isn't so much keeping up... it's keeping things working for those that do not...

if premake for example outputs <LanguageStandard>stdcpp17</LanguageStandard> Visual Studio 2017 15.2 will no longer build, because stdcpp17 is an unknown value... C++17 used to be C++latest, but now C++latest means C++20.

Basically Microsoft is changing the meaning of settings, adding new settings, and older versions of VS2017 will break, not load the project, or not build successfully due to unknown settings.

We have a wide variety of versions in the company, and new versions of VS2017 have in the past introduced compiler bugs, that prevents an entire team from upgrading to latest. Meaning that from team to team there is a spread of versions in use, and I can't make Premake do the right thing for everyone at once.

Basically... it's a mess.

ratzlaff commented 6 years ago

Is <LanguageStandard> a required setting in VS2017? Will Visual Studio "do the right thing" if premake leaves it out?

tvandijck commented 6 years ago

Premake doesn't generate it, unless you set cppdialect to a value, but the current code: https://github.com/premake/premake-core/blob/master/modules/vstudio/vs2010_vcxproj.lua#L1260

no longer does the right thing for VS 2017 15.5 but for 15.3 it generates the correct output.

LanguageStandard is just one example... Between 15.0 and 15.5.1 there is handful of settings, new, changed or removed. Premake either has no support for them at all, or it outputs something but it has since been removed, or the meaning has changed, LaguangeStandard just being one example of the later.

samsinsane commented 6 years ago

I think a pretty good way would be to have a projectversion API. What you've described above also applies to the premake-android module, so the checking of projectversion would need to not occur at the element level, but more at the callarray level - ideally. A 15.5 element might also apply to Android v3.0, and obviously 15.5 ~= 3.0 - so I'd prefer if this was factored in from the start.

pdoane commented 6 years ago

How does the user distinguish between the generation of a 15.5 vs 15.3? They either need to be different actions or there needs to be another command line option.

Compared to previous VS development cycles, the rate of change between VS 2017 15.0, 15.1, 15.3, 15.5, and the upcoming 15.6 are almost as large as what we saw between VS 2010, 2012, and 2013.

What I'd like to see is that the compiler version number can be used in the action (i.e. vs15.5) and we can map the product name (vs2017) to a reasonable version.

starkos commented 6 years ago

Adding new command line options is easy enough, so we could certainly support something like:

premake5 vs2017   # target the most up-to-date settings
premake5 vs2017 --target-version=15.5  # or something like this
premake5 vs2017 --target=15.5          # or something like this

The vs2017 action can read _OPTIONS['target-version'] and store it somewhere convenient for the exporter code to reference.

pdoane commented 6 years ago

Sometimes we need to know toolset version for gcc/clang though too so it's probably a good opportunity to have a consistent mechanism to handle this issue. That said, from a user perspective, this would be a lot nicer to type:

premake5 vs15.5
samsinsane commented 6 years ago

The vs2017 action can read _OPTIONS['target-version'] and store it somewhere convenient for the exporter code to reference.

Using the option system sounds nice, but that name seems a bit confusing. If I saw premake5 xcode4 --target-version=15.5, I would assume that was the macOS version number not the XCode internal version number. action-version or project-version makes more sense to me, the latter allows for extensions to VS to also take advantage of this, as per my example above with Android.

Sometimes we need to know toolset version for gcc/clang though too so it's probably a good opportunity to have a consistent mechanism to handle this issue.

This sounds like a nice idea, however, using my Android example there would be a conflict here. How do you specify Android project version 3.0 and Clang 3.8? Maybe I'm just looking at this wrong, the modules for VStudio extensions probably should continue to maintain their own versioning and this new system should pull Clang and GCC into the fold. However, you could specify Clang or GCC version via --toolset and that would be more consistent with how you specify MSC versions, msc-v141 or just v141. I don't recall how this is handled internally but splitting on - would give us toolset and version, in most cases toolset is used and where required version is utilized.

Thoughts?

tvandijck commented 6 years ago

It should be relatively easy to create a new action "vs15.5", that simply wraps the vs2017 action, and sets a variable to indicate what version of vs2017... if that 'variable' was an option, then you can basically have it both ways...

the harder part in making the action follow the version number of visual studio, instead of it's year number, is that there is quite a few places in the premake where there is a simple string compare like: if _ACTION > "vs2015" then, which will obviously break down when you go to a different versioning schema. after all, vs15.5 < vs2010 !

So either the 'wrapping' action needs to fixup _ACTION and set an additional variable to record the version of vs2017 selected... or all that code has to be fixed to correctly respond to toolset. Quite frankly I actually think that a lot of settings injected into the vcxproj should probably be based on toolset anyway, because even in vs2017 I can target toolset vc100, which does not support a lot of the options premake is currently emitting, because _ACTION is vs2017. As well, for example if the toolset is clang while _ACTION is vs2017, the vcxproj is basically just broken, Visual Studio will load it, but compiling is not really an option, and that is ultimately because the msbuild property sheets used change when the toolset changes. So maybe we should fix that in the process as well.

pdoane commented 6 years ago

Another issue here is that toolset for msc includes version numbers but doesn't for clang/gcc. The android module adds another setting toolchainversion which specifies that version number.

englercj commented 2 years ago

Hit by this a little today. I use cppdialect "C++20" currently, which resolves to /std:c++latest but in my version of vs2019 I want it to resolve to /std:c++20. Obviously that doesn't exist in older compilers.

nickclark2016 commented 2 years ago

Hit by this a little today. I use cppdialect "C++20" currently, which resolves to /std:c++latest but in my version of vs2019 I want it to resolve to /std:c++20. Obviously that doesn't exist in older compilers.

Let's open this up as a separate issue and we can talk about how to handle that there 😊

starkos commented 2 years ago

FYI, I have most of this working in Premake6, though most of the features which would use it haven't been ported yet. I've modified how options are parsed on the command line so you can say any of:

premake6 vstudio
premake6 vstudio=2017
premake6 vstudio=15.5

Then I have a few methods to allow comparing versions and mapping them to values. I'm also hoping to add more conditional operators to the filter syntax to support things like (not done yet, may change):

filter { 'action:studio', 'version<=15.5' }
   -- settings go here

Nothing that's rocket science, shouldn't be excessively difficult to backport to v5 if someone is interested (I'm intending to keep my focus on v6 right now).