-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Inject CMake build_modules after targets are created #8130
Conversation
390d329
to
0866da8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good, I think it is ready, somethings could be improved now, but I wouldn't oppose if they are fixed later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR is a bit challenging. I'm assuming these expectations:
- build modules are included after the element they refer to:
- global build-modules at the very end
- build-modules per component, after corresponding component is defined (nice to have, but they could go at the bottom too).
- per-component build-modules are not included as global ones as well.
- build-modules for a given configuration are added only when that configuration is used (requires some generator expression).
Please, tell me if I'm wrong with any of the previous points.
class TestCMakeFindPackageGenerator: | ||
|
||
@pytest.mark.parametrize("use_components", [False, True]) | ||
def test_build_modules_alias_target(self, use_components): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this test, when use_components =True
, I can see the following:
Findhello.cmake
...
set(namespace_BUILD_MODULES_PATHS "/private/var/folders/fc/6mvcrc952dqcjfhl4c7c11ph0000gn/T/tmphcq2mp5yconans/path with spaces/data/hello/1.0/_/_/package/f83037eff23ab3a94190d7f3f7b37a2d6d522241/share/cmake/target-alias.cmake")
...
set(namespace_comp_BUILD_MODULES_PATHS "/private/var/folders/fc/6mvcrc952dqcjfhl4c7c11ph0000gn/T/tmphcq2mp5yconans/path with spaces/data/hello/1.0/_/_/package/f83037eff23ab3a94190d7f3f7b37a2d6d522241/share/cmake/target-alias.cmake")
...
...
foreach(_BUILD_MODULE_PATH ${namespace_BUILD_MODULES_PATHS})
include(${_BUILD_MODULE_PATH})
endforeach()
I would expect the build-module to appear only at the component level... and, of course, a loop calling include
for each one of them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still the same, the same build-module appear at component and global level.
include(${_BUILD_MODULE_PATH}) | ||
endforeach() | ||
{%- endfor %} | ||
""") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we are adding unconditionally all the build-modules. The resulting cmake file contain these lines:
# Build modules
foreach(_BUILD_MODULE_PATH ${hello_BUILD_MODULES_PATHS_DEBUG})
include(${_BUILD_MODULE_PATH})
endforeach()
foreach(_BUILD_MODULE_PATH ${hello_BUILD_MODULES_PATHS_MINSIZEREL})
include(${_BUILD_MODULE_PATH})
endforeach()
foreach(_BUILD_MODULE_PATH ${hello_BUILD_MODULES_PATHS_RELWITHDEBINFO})
include(${_BUILD_MODULE_PATH})
endforeach()
foreach(_BUILD_MODULE_PATH ${hello_BUILD_MODULES_PATHS_RELEASE})
include(${_BUILD_MODULE_PATH})
endforeach()
All of them are included regardless of the build_type used. We need a generator expression to expand and use only the build-modules for the matching build-type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have tried modifying this to use generator expressions here, but those only work in target properties as generator expressions are specific for CMake generators. I have also tried using CMAKE_BUILD_TYPE to make the conditionals but it is not available. I am leaving this as it is right now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right. Generator expressions only work with target-related properties... so for multi-generators this is unsolvable. 🤔 . Maybe something to document.
Then it is clearly a CMake limitation and I'd extend it to non-multi generators as well (for consistency). It means that the list of build-modules to include cannot be different based on the configuration name (typically build_type
), recipe authors need to implement the build-module with this circumstance in mind. We'd go crazy trying to protect the user from it given our cpp_info
object.
include(${_BUILD_MODULE_PATH}) | ||
endforeach() | ||
|
||
{%- endfor %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above, here we add all the build-modules unconditionally, we need a generator expression to include
only the ones for the matching config
.
This is current output:
########## BUILD MODULES ####################################################################
#############################################################################################
########## GLOBAL BUILD MODULES #############################################################
foreach(_BUILD_MODULE_PATH ${namespace_BUILD_MODULES_PATHS_DEBUG})
include(${_BUILD_MODULE_PATH})
endforeach()
foreach(_BUILD_MODULE_PATH ${namespace_BUILD_MODULES_PATHS_MINSIZEREL})
include(${_BUILD_MODULE_PATH})
endforeach()
foreach(_BUILD_MODULE_PATH ${namespace_BUILD_MODULES_PATHS_RELWITHDEBINFO})
include(${_BUILD_MODULE_PATH})
endforeach()
foreach(_BUILD_MODULE_PATH ${namespace_BUILD_MODULES_PATHS_RELEASE})
include(${_BUILD_MODULE_PATH})
endforeach()
@@ -139,6 +139,105 @@ def build(self): | |||
client.run("create .") | |||
self.assertIn("Printing using a external module!", client.out) | |||
|
|||
@parameterized.expand([(False,), (True,)]) | |||
def test_build_modules_alias_target(self, use_components): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue as the one with the cmake_find_package
generator:
helloTarget-release.cmake
...
set(namespace_BUILD_MODULES_PATHS_RELEASE "/private/var/folders/fc/6mvcrc952dqcjfhl4c7c11ph0000gn/T/tmpf8fefhlrconans/path with spaces/data/hello/1.0/_/_/package/f83037eff23ab3a94190d7f3f7b37a2d6d522241/share/cmake/target-alias.cmake")
...
set(namespace_comp_BUILD_MODULES_PATHS_RELEASE "/private/var/folders/fc/6mvcrc952dqcjfhl4c7c11ph0000gn/T/tmpf8fefhlrconans/path with spaces/data/hello/1.0/_/_/package/f83037eff23ab3a94190d7f3f7b37a2d6d522241/share/cmake/target-alias.cmake")
...
I expect the build-module to appear listed only under the namespace_comp
ones...
hello-config.cmake
...
########## BUILD MODULES ####################################################################
#############################################################################################
########## GLOBAL BUILD MODULES #############################################################
foreach(_BUILD_MODULE_PATH ${namespace_BUILD_MODULES_PATHS_DEBUG})
include(${_BUILD_MODULE_PATH})
endforeach()
foreach(_BUILD_MODULE_PATH ${namespace_BUILD_MODULES_PATHS_MINSIZEREL})
include(${_BUILD_MODULE_PATH})
endforeach()
foreach(_BUILD_MODULE_PATH ${namespace_BUILD_MODULES_PATHS_RELWITHDEBINFO})
include(${_BUILD_MODULE_PATH})
endforeach()
foreach(_BUILD_MODULE_PATH ${namespace_BUILD_MODULES_PATHS_RELEASE})
include(${_BUILD_MODULE_PATH})
endforeach()
...
Build-modules per component are not included.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree we cannot decide which build-modules to include based on the configuration for multi-config generator (the include
function cannot use generator expressions). Agree we shouldn't add the feature to non-multi generator for consistency too.
But, I think we can include only build-modules at the level where they are declared.
I'll have a look to the implementation.
class TestCMakeFindPackageGenerator: | ||
|
||
@pytest.mark.parametrize("use_components", [False, True]) | ||
def test_build_modules_alias_target(self, use_components): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still the same, the same build-module appear at component and global level.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, I'm no longer sure if it is worth fixing/adding that in this PR. After having a look at the sources I can see that we are populating global variables even if we are using components. This is intended and it is good according to the docs where we list the CMake variables that are available for the different generators.
And I see current implementations include
only the proper build-modules: global ones or components, depending on the generator.
Good!
Changelog: Fix: Inject build modules after CMake targets are created
Docs: conan-io/docs#1944
This allows uisng build modules to generate non-namespaced targets. --
build_modules
after targets are created in generated CMake find modules #7261, closes [feature] cmake_find_package[_multi] generators: provide a way to create non namespaced imported targets #7615develop
branch, documenting this one.Note: By default this PR will skip the slower tests and will use a limited set of python versions. Check here how to increase the testing level by writing some tags in the current PR body text.