conan icon indicating copy to clipboard operation
conan copied to clipboard

[question] How to make sure my global custom generator is called last ?

Open todorico opened this issue 1 year ago • 5 comments

What is your question?

Hi,

The order in which generators are called seems to vary, which is problematic for my use case. I have a custom generator, NoCMakeUserPresets, intended to execute after all other generators.

This generator's purpose is to remove the CMakeUserPresets.json file created by the CMakeToolchain of my project conanfile, if it exists. Here's the generator's code for reference:

from conan import ConanFile
from conan.tools.files import rm

class NoCMakeUserPresets:
    def __init__(self, conanfile: ConanFile):
        self._conanfile = conanfile

    def generate(self):
        cf = self._conanfile
        rm(cf, "CMakeUserPresets.json", cf.source_folder)

I use this generator in my projects with the command conan install . -g NoCMakeUserPresets to prevent IDEs like VSCode from prioritizing CMakeUserPresets.json as a settings provider, which is not always desired.

The inconsistency occurs in the execution order of this generator. Sometimes NoCMakeUserPresets is called first, and other times last. This was unexpected, as I assumed that generators specified in the command line would execute after those defined in my project's conanfile.py.

I would appreciate any guidance or resolution for ensuring a consistent execution order for generators.

Thanks!

Have you read the CONTRIBUTING guide?

  • [x] I've read the CONTRIBUTING guide

todorico avatar Feb 15 '24 07:02 todorico

After further investigation, I noticed that The inconsistency in generator execution order occurs only when using the generators attribute in my Conanfile. For instance:

class ProjectRecipe(ConanFile):
    name = "my_project"
    package_type = "library"
...
    generators = "CMakeDeps", "CMakeToolchain"

However, when I invoke my generators within the generate method, the execution order is consistent, but my custom generator is always called first, which is the opposite of what I want:

class ProjectRecipe(ConanFile):
    name = "my_project"
    package_type = "library"
...
    def generate(self):
        deps = CMakeDeps(self)
        deps.generate()
        tc = CMakeToolchain(self)
        tc.generate()

todorico avatar Feb 15 '24 07:02 todorico

Hi! Thanks a lot for your question.

To me this seems to be a better fit for hooks, which extend Conan functionality by providing custom entry points after different steps of the package creation process, see docs here.

With this you lose the ability to directly specify in the CLI when to run the code, it will always be done after every generate() step (There are ways to avoid this by passing user defined confs, for example), but gain certainty about when your code will run.

I'm not saying either that this is the solution to your use-case, if any (Generator order varies because we can't guarantee any order of execution for the ones defined as attributes right now as they are backed by an unordered data structure), so maybe @memsharded has more insights than I do :)

AbrilRBS avatar Feb 15 '24 07:02 AbrilRBS

Thank you for suggesting hooks as a potential solution. I agree that hooks could be suitable for this scenario. I'm considering implementing it like this:

...
def post_generate(conanfile):
    skip_cmake_presets = conanfile.conf.get("user.tools.cmake.cmaketoolchain:skip_presets", default=False, check_type=bool)
    if skip_cmake_presets:
        rm(conanfile, "CMakeUserPresets.json", conanfile.source_folder)

While this approach might work for my current needs, I still believe there could be scenarios where a predictable generator execution order is beneficial, particularly when one generator relies on the output of another.

todorico avatar Feb 15 '24 08:02 todorico

Nevertheless, I've proposed #15678 to guarantee order of execution for generators to avoid future problems regarding that :)

We're also thinking about adding a built-in conf to remove the CMakeUserPresets file, will circle back on that once we think about it

AbrilRBS avatar Feb 15 '24 09:02 AbrilRBS

Awesome! Thanks a lot!

todorico avatar Feb 16 '24 05:02 todorico