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

[question] Issue with extra_cxxflags not initializing CMAKE_CXX_FLAGS_INIT in Ninja Multi-Config CMake projects since Conan 2.1.0 #3660

Open
1 task done
solarispika opened this issue Mar 26, 2024 · 6 comments
Assignees
Milestone

Comments

@solarispika
Copy link
Contributor

What is your question?

I have a Ninja Multi-Config CMake project whose Conan recipe has a build() method that configures and builds the project. Before Conan 2.1.0, I could build the project for different configurations using the following commands:

  1. conan build -s:h build_type=Release
  2. conan build -s:h build_type=Debug

These commands could be run in any order, and the second command would work correctly.

However, after upgrading to Conan 2.1.0, the second command fails due to missing C++ flags. Upon investigation, I found that the commit conan-io/conan@7d93ccc, introduced by conan-io/conan#15654, changed the behavior of extra_cxxflags.

Instead of initializing CMAKE_CXX_FLAGS_INIT, the extra_cxxflags now initialize CMAKE_CXX_FLAGS_<CONFIG>_INIT. This means that when my recipe's build() method immediately configures CMake, it only sets up the flags for the first build configuration, and the subsequent configurations do not have access to the desired flags.

My project sets up extra_cxxflags in the conanfile.py and expects to use it across all configurations. According to the CMake documentation, CMAKE_<LANG>_FLAGS is supposed to be used for "Language-wide flags for language used when building for all configurations," and "The flags in this variable will be passed before those in the per-configuration CMAKE_<LANG>_FLAGS_<CONFIG> variable." Furthermore, CMAKE_<LANG>_FLAGS is initialized by CMAKE_<LANG>_FLAGS_INIT.

My question is: How can I achieve the same behavior as before Conan 2.1.0 with CMakeToolchain and Ninja Multi-Config? Is there a way to set CMAKE_CXX_FLAGS_INIT or equivalent flags that apply to all configurations in a Ninja Multi-Config CMake project when using Conan?

I have tried using conan install instead of conan build, and manually configuring CMake afterwards, which seems to work correctly. However, I would like to understand if there is a better solution that allows me to use conan build and have the desired flags applied across all configurations.

Any guidance or suggestions would be appreciated.

Have you read the CONTRIBUTING guide?

  • I've read the CONTRIBUTING guide
@memsharded memsharded self-assigned this Mar 26, 2024
@memsharded
Copy link
Member

Hi @solarispika

Thanks for your detailed report.

I think this is expected behavior for multi-config setups.
As the conan build calls conan install + build() method, which in turns do cmake configure + cmake build, then, the extra flags are really per-configuration flags. It cannot be simply assumed that the flags provided at Release install time will be the same as the ones in Debug time. This behavior was a declared bug that was affecting users before the fix.

I have tried using conan install instead of conan build, and manually configuring CMake afterwards, which seems to work correctly. However, I would like to understand if there is a better solution that allows me to use conan build and have the desired flags applied across all configurations.

This is indeed the recommended flow, for multi-config setups it is necessary to install first the different configs, then cmake configure the project, there is not much that Conan can do in this regard, because CMake do not "re-configure" when some things change.

If you really want the independent flow, why using Ninja Multi-Config? It seems that using Ninja is what you want and it will achieve you exactly the behavior that you expect, isn't it?

@solarispika
Copy link
Contributor Author

Hi @memsharded

Thank you for the detailed explanation. I appreciate you taking the time to clarify the expected behavior and the rationale behind it.

To provide some context, our project was initially a Visual Studio solution, and we later migrated it to Ninja for better performance while retaining the multi-config aspect, leading to the Ninja Multi-Config setup.

Initially, we followed the conan install + cmake configure/build flow, and our Conan 1.x recipe had no build() method since we were only consuming other packages. However, when migrating to Conan 2.x, I added the build() method to simplify the development flow by running a single command as an alternative to the mentioned flow. This approach worked as expected before Conan 2.1.0, so I didn't question its rationality at the time.

With your explanation, I now understand that the conan install + cmake configure flow is the recommended approach, especially for multi-config setups. This is because CMake does not "re-configure" when certain things change, and Conan cannot assume that the flags provided at one configuration (e.g., Release) will be the same as another (e.g., Debug).

Based on your response, I have a couple of suggestions/questions:

  1. Do you think it would be beneficial to add more detailed explanations to the Conan documentation regarding how the extra_*flags variables are handled in single-config vs. multi-config cases? Clearly explaining which CMake variables are set by these flags in each scenario could help users better understand the expected behavior and potential limitations.

  2. Would it be possible for Conan to display a warning when a user tries to install another build configuration after the project has already been configured? This warning could explain that the newly installed configuration might not have the desired flags applied and recommend using the conan install + cmake configure flow instead.

  3. In what scenarios would you recommend using the build() method in a multi-config project? Are there any specific use cases or project setups where it might be appropriate or advantageous to use the build() method over the recommended conan install + cmake configure flow?

I appreciate your guidance on this issue and welcome any further suggestions or recommendations you may have.

@memsharded
Copy link
Member

Do you think it would be beneficial to add more detailed explanations to the Conan documentation regarding how the extra_*flags variables are handled in single-config vs. multi-config cases? Clearly explaining which CMake variables are set by these flags in each scenario could help users better understand the expected behavior and potential limitations.

Yes, we can add some clarifications to the docs regarding this.

Would it be possible for Conan to display a warning when a user tries to install another build configuration after the project has already been configured? This warning could explain that the newly installed configuration might not have the desired flags applied and recommend using the conan install + cmake configure flow instead.

The problem with this is false positives. There are some things, depending on the CACHE status that might work fine, and printing warnings might annoy some users that are ok with their usage.

In what scenarios would you recommend using the build() method in a multi-config project? Are there any specific use cases or project setups where it might be appropriate or advantageous to use the build() method over the recommended conan install + cmake configure flow?

We have worked hard to make sure that the build system integrations are as transparent as possible, in this regard, the "canonical" flow could be conan install (x configuration) + cmake --preset + cmake --build --preset, which should achieve exactly the same as conan build. This would be the "developer" flow, in which using "Ninja Multi-Config" might have some benefit (to be clear, the multi-config setups mostly makes sense when there is an IDE that support it and allow changing from one configuration to the other directly in the IDE) to quickly change config within the same project.

The conan build is more oriented to quick testing or convenient launching the build for other build systems that are not as convenient to launch manually, like autotools, for example. It can be perfectly used for local building, but it is true that users should be aware of multi-config limitations.

@solarispika
Copy link
Contributor Author

Hi @memsharded

Thank you for the comprehensive explanation.
If the documentation is improved with more clarity around multi-config scenarios, it would be beneficial for users like myself.
I have no further questions at this time.

@solarispika
Copy link
Contributor Author

This question can be closed

@memsharded
Copy link
Member

Thanks for the feedback!

I was further trying yesterday in code to see if there could be any possibility, but the way CMake caches and processes the CMAKE_CXX_FLAGS makes this impossible.

I'll move this to the docs repo to add some clarifications

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

2 participants