CMake 4.0.1 and CXX_STANDARD on Cinder project

Hey 'embers,

Anyone tried a recent CMake on Cinder?

I’ve recently begun migrating my Cinder based project to my new PC and updated some build software. I’ve found that CMake’s command to set the C++ standard no longer appears to ‘stick’, i.e.:

set_property(TARGET sandbox PROPERTY CXX_STANDARD 23)

no longer appears to do the trick. I’ve yet to get to the bottom, but I can confirm that on my old PC using CMake 3.12.2 this worked fine on my Cinder project.

With CMake 4.0.1 it works fine on a simple dummy project, i.e. a single executable target with an attached source file. But when I try to make a proper Cinder project and pass a target to ci_make_app I now seem to be unable to change the C++ standard on the project.

Cheers,
Gazoo

I’m able to reproduce this issue (happen to be setting up a new dev machine myself), and have narrowed it down to cinder’s use of INTERFACE_COMPILE_OPTIONS and it being preferred over CXX_STANDARD for some reason.

I was able to make it work by overriding that value by adding

set_property(TARGET cinder PROPERTY INTERFACE_COMPILE_OPTIONS "/std:c++23")

Edit: Setting it to an empty string is probably better, this way whatever your CXX_STANDARD is set to will now kick in.

after the call to ci_make_app in your project’s CMakeLists, but since I have no idea what that actually does, I can’t recommend that as a fix. Hopefully it gives you something to add to your googling that may help tease out the root problem though.

A

1 Like

You’re a life saver @lithium. I very much appreciate your solution.

I dug a bit more and found the INTERFACE_COMPILE_OPTIONS are indeed set inside libcinder_target.cmake line 125.

I wanted to make sure I wasn’t wrecking any other settings stored inside INTERFACE_COMPILE_OPTIONS, so I tried doing a get_property:

get_property(EXISTING_SETTINGS TARGET cinder PROPERTY INTERFACE_COMPILE_OPTIONS)

But it appears the only entry in the string is /std:c++17 O_o

It’s confusing to me, because my limited understanding of CMake is that by setting this interface-based property, the LibCinder CMake code is signalling that any target which uses/includes the libcinder library, should set its C++ standard to C++17, which doesn’t seem to make much sense to me.

Usually anyone linking with LibCinder should be able to set whatever standard of C++ they want as the ABI should ensure correct linkage regardless. Ultimately, your suggestion I think is the best one, i.e. setting the string to nothing and then setting the C++ standard with the most modern CMake command, i.e.

target_compile_features(sandbox PUBLIC cxx_std_20)

Thoughts on why the LibCinder CMake is written like this?

Cheers,
Gazoo

It looks like cinder’s detecting the latest supported version and setting the CINDER_CXX_FLAGS accordingly, it’s just that at the time it was written, vs2019 / c++17 was the latest and greatest so that’s what it gets set to.

Seems like it’d be trivial to add a few more cases to the function i linked to detect vs2022 and the various newer c++ versions, there may even be a PR in github for it already or perhaps some updates in the dev branch?

But - unless I’m missing something here - the INTERFACE_COMPILE_OPTIONS setting is dictating that anything that links to libcinder gets the latest C++ standard (C++17 at the time of writing) applied to it.

I acknowledge that CMake was more lax and that this property could be more easily overridden, but even with the setting being lax, I’m not sure I see the wisdom in massaging the C++ standard for user-code towards a newer standard?

Especially since libcinder is compiled and could link with any compiled standard? I’d think I could even code my application with the 98 standard if I was so inclined?

As I understand it, ABI compatibility across toolsets on MSVC is only relatively new, and even if it wasn’t, I don’t think cinder will compile with anything older than c++11. Furthermore, even that may be spotty with the newer (i.e > vs2019) toolsets due to missing boost polyfills and std::tr2 namespace trickery and shit like that that allowed things like std::filesystem to be present in cinder prior to them being officially supported by the standard, so you may be talking about a distinction without a difference in practice.

That said, you will likely have different requirements/concerns than me, so you’ll just have to decide what suits you with the information presented, I guess.

Your response makes a lot of sense. I was simply keen to understand, as when something doesn’t make sense to me, it’s an opportunity to learn, and thanks to you - I have.

I really appreciate you taking the time to explain the matter. I actually thought ABI compatibility wasn’t new, and even worked more well into the past. So again - I’ve grown wiser thanks to you!

:heart:

Here’s the source I was basically paraphrasing, it also doubles as a strong exhibit for why I personally just upgrade everything at the same time and keep everything in lockstep (toolset, c++std, etc). One less thing to worry about. :slight_smile:

A

1 Like

On that note, I would, but I currently rely on the AX-MediaPlayer Cinder block, which I believe breaks with the C++23 standard, so I’m delighted that I’m able to keep that in C++20 land for a bit longer.

I’ve looked at the code and it looks scary to fix :E

(But yes, keeping everything in lock-step is definitely the way to reduce the endless amount of things that can go sideways)

This commit fixes the c++23 compile issue you were seeing with AX-MediaPlayer. It was to do with changes to constexpr destructors for std::unique_ptr in c++23 that prevent using unique_ptr on forward declared types without a bit of faffing around.

A

1 Like