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

Raise error when a generator is defined in generators and generate() #12722

Merged
8 changes: 8 additions & 0 deletions conan/internal/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from conan.errors import ConanException


def check_duplicated_generator(generator, conanfile):
if generator.__class__.__name__ in conanfile.generators:
raise ConanException(f"{generator.__class__.__name__} is declared in the generators "
"attribute, but was instantiated in the generate() method too. "
"It should only be present in one of them.")
2 changes: 2 additions & 0 deletions conan/tools/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
CONAN_TOOLCHAIN_ARGS_FILE = "conanbuild.conf"
CONAN_TOOLCHAIN_ARGS_SECTION = "toolchain"


1 change: 0 additions & 1 deletion conan/tools/apple/apple.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import os

from conans.errors import ConanException
from conans.util.runners import check_output_runner
from conan.tools.build import cmd_args_to_string
from conans.errors import ConanException
Expand Down
2 changes: 0 additions & 2 deletions conan/tools/apple/xcodebuild.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import os

from conan.tools.apple import to_apple_arch
from conans.errors import ConanException

Expand Down
2 changes: 2 additions & 0 deletions conan/tools/apple/xcodedeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from jinja2 import Template

from conan.internal import check_duplicated_generator
from conans.errors import ConanException
from conans.model.dependencies import get_transitive_requires
from conans.util.files import load, save
Expand Down Expand Up @@ -115,6 +116,7 @@ def __init__(self, conanfile):
self.sdk_version = conanfile.settings.get_safe("os.sdk_version")

def generate(self):
check_duplicated_generator(self, self._conanfile)
if self.configuration is None:
raise ConanException("XcodeDeps.configuration is None, it should have a value")
if self.architecture is None:
Expand Down
2 changes: 2 additions & 0 deletions conan/tools/apple/xcodetoolchain.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import textwrap

from conan.internal import check_duplicated_generator
from conan.tools.apple.apple import to_apple_arch
from conan.tools.apple.xcodedeps import GLOBAL_XCCONFIG_FILENAME, GLOBAL_XCCONFIG_TEMPLATE, \
_add_includes_to_file_or_create, _xcconfig_settings_filename, _xcconfig_conditional
Expand Down Expand Up @@ -46,6 +47,7 @@ def __init__(self, conanfile):
self._global_ldflags = sharedlinkflags + exelinkflags

def generate(self):
check_duplicated_generator(self, self._conanfile)
save(self._agreggated_xconfig_filename, self._agreggated_xconfig_content)
save(self._vars_xconfig_filename, self._vars_xconfig_content)
if self._check_if_extra_flags:
Expand Down
2 changes: 2 additions & 0 deletions conan/tools/cmake/cmakedeps/cmakedeps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os

from conan.internal import check_duplicated_generator
from conan.tools.cmake.cmakedeps import FIND_MODE_CONFIG, FIND_MODE_NONE, FIND_MODE_BOTH, \
FIND_MODE_MODULE
from conan.tools.cmake.cmakedeps.templates.config import ConfigTemplate
Expand Down Expand Up @@ -35,6 +36,7 @@ def generate(self):
"""
This method will save the generated files to the conanfile.generators_folder
"""
check_duplicated_generator(self, self._conanfile)
# FIXME: Remove this in 2.0
if not hasattr(self._conanfile, "settings_build") and \
(self.build_context_activated or self.build_context_build_modules or
Expand Down
2 changes: 2 additions & 0 deletions conan/tools/cmake/toolchain/toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from jinja2 import Template

from conan.internal import check_duplicated_generator
from conan.tools.build import use_win_mingw
from conan.tools.cmake.presets import write_cmake_presets
from conan.tools.cmake.toolchain import CONAN_TOOLCHAIN_FILENAME
Expand Down Expand Up @@ -173,6 +174,7 @@ def generate(self):
"""
This method will save the generated files to the conanfile.generators_folder
"""
check_duplicated_generator(self, self._conanfile)
toolchain_file = self._conanfile.conf.get("tools.cmake.cmaketoolchain:toolchain_file")
if toolchain_file is None: # The main toolchain file generated only if user dont define
save(os.path.join(self._conanfile.generators_folder, self.filename), self.content)
Expand Down
3 changes: 2 additions & 1 deletion conan/tools/env/virtualbuildenv.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from conan.internal import check_duplicated_generator
from conan.tools.env import Environment
from conan.tools.env.virtualrunenv import runenv_from_cpp_info

Expand Down Expand Up @@ -78,6 +79,6 @@ def generate(self, scope="build"):

:param scope: Scope to be used.
"""

check_duplicated_generator(self, self._conanfile)
build_env = self.environment()
build_env.vars(self._conanfile, scope=scope).save_script(self._filename)
2 changes: 2 additions & 0 deletions conan/tools/env/virtualrunenv.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os

from conan.internal import check_duplicated_generator
from conan.tools.env import Environment


Expand Down Expand Up @@ -89,5 +90,6 @@ def generate(self, scope="run"):

:param scope: Scope to be used.
"""
check_duplicated_generator(self, self._conanfile)
run_env = self.environment()
run_env.vars(self._conanfile, scope=scope).save_script(self._filename)
1 change: 0 additions & 1 deletion conan/tools/files/files.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import configparser
import errno
import gzip
import hashlib
import os
import platform
import shutil
Expand Down
2 changes: 2 additions & 0 deletions conan/tools/gnu/autotoolsdeps.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from conan.internal import check_duplicated_generator
from conan.tools.env import Environment
from conan.tools.gnu.gnudeps_flags import GnuDepsFlags
from conans.model.build_info import CppInfo
Expand Down Expand Up @@ -79,4 +80,5 @@ def vars(self, scope="build"):
return self.environment.vars(self._conanfile, scope=scope)

def generate(self, scope="build"):
check_duplicated_generator(self, self._conanfile)
self.vars(scope).save_script("conanautotoolsdeps")
4 changes: 3 additions & 1 deletion conan/tools/gnu/autotoolstoolchain.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from conan.internal import check_duplicated_generator
from conan.tools.apple.apple import apple_min_version_flag, to_apple_arch
from conan.tools.apple.apple import get_apple_sdk_fullname
from conan.tools.build import cmd_args_to_string
Expand All @@ -6,7 +7,7 @@
from conan.tools.env import Environment
from conan.tools.files.files import save_toolchain_args
from conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet
from conan.tools.microsoft import VCVars, is_msvc, msvc_runtime_flag
from conan.tools.microsoft import VCVars, msvc_runtime_flag
from conans.errors import ConanException


Expand Down Expand Up @@ -158,6 +159,7 @@ def vars(self):
return self.environment().vars(self._conanfile, scope="build")

def generate(self, env=None, scope="build"):
check_duplicated_generator(self, self._conanfile)
env = env or self.environment()
env = env.vars(self._conanfile, scope=scope)
env.save_script("conanautotoolstoolchain")
Expand Down
2 changes: 2 additions & 0 deletions conan/tools/gnu/pkgconfigdeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from jinja2 import Template, StrictUndefined

from conan.internal import check_duplicated_generator
from conan.tools.gnu.gnudeps_flags import GnuDepsFlags
from conans.errors import ConanException
from conans.util.files import save
Expand Down Expand Up @@ -414,6 +415,7 @@ def generate(self):
"""
Save all the `*.pc` files
"""
check_duplicated_generator(self, self._conanfile)
# Current directory is the generators_folder
generator_files = self.content
for generator_file, content in generator_files.items():
Expand Down
2 changes: 2 additions & 0 deletions conan/tools/google/bazeldeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from jinja2 import Template

from conan.internal import check_duplicated_generator
from conans.errors import ConanException
from conans.util.files import save

Expand All @@ -13,6 +14,7 @@ def __init__(self, conanfile):
self._conanfile = conanfile

def generate(self):
check_duplicated_generator(self, self._conanfile)
local_repositories = []
generators_folder = self._conanfile.generators_folder

Expand Down
2 changes: 2 additions & 0 deletions conan/tools/google/toolchain.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from conan.internal import check_duplicated_generator
from conan.tools.files.files import save_toolchain_args


Expand All @@ -8,6 +9,7 @@ def __init__(self, conanfile, namespace=None):
self._namespace = namespace

def generate(self):
check_duplicated_generator(self, self._conanfile)
content = {}
configs = ",".join(self._conanfile.conf.get("tools.google.bazel:configs",
default=[],
Expand Down
2 changes: 2 additions & 0 deletions conan/tools/intel/intel_cc.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import platform
import textwrap

from conan.internal import check_duplicated_generator
from conans.errors import ConanException


Expand Down Expand Up @@ -72,6 +73,7 @@ def ms_toolset(self):

def generate(self, scope="build"):
"""Generate the Conan Intel file to be loaded in build environment by default"""
check_duplicated_generator(self, self._conanfile)
if platform.system() == "Windows" and not self._conanfile.win_bash:
content = textwrap.dedent("""\
@echo off
Expand Down
2 changes: 2 additions & 0 deletions conan/tools/meson/mesondeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from jinja2 import Template

from conan.internal import check_duplicated_generator
from conan.tools.gnu.gnudeps_flags import GnuDepsFlags
from conan.tools.meson.helpers import to_meson_value
from conans.model.build_info import CppInfo
Expand Down Expand Up @@ -102,4 +103,5 @@ def _content(self):
return content

def generate(self):
check_duplicated_generator(self, self._conanfile)
save(self.filename, self._content())
2 changes: 2 additions & 0 deletions conan/tools/meson/toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from jinja2 import Template

from conan.internal import check_duplicated_generator
from conan.tools.apple.apple import to_apple_arch, is_apple_os, apple_min_version_flag
from conan.tools.build.cross_building import cross_building
from conan.tools.build.flags import libcxx_flags
Expand Down Expand Up @@ -427,6 +428,7 @@ def generate(self):
``conan_meson_cross.ini`` (if cross builds) with the proper content.
If Windows OS, it will be created a ``conanvcvars.bat`` as well.
"""
check_duplicated_generator(self, self._conanfile)
filename = self.native_filename if not self.cross_build else self.cross_filename
save(filename, self._content)
# FIXME: Should we check the OS and compiler to call VCVars?
Expand Down
2 changes: 2 additions & 0 deletions conan/tools/microsoft/msbuilddeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from jinja2 import Template

from conan.internal import check_duplicated_generator
from conans.errors import ConanException
from conans.model.dependencies import get_transitive_requires
from conans.util.files import load, save
Expand Down Expand Up @@ -113,6 +114,7 @@ def generate(self):
Generates ``conan_<pkg>_<config>_vars.props``, ``conan_<pkg>_<config>.props``,
and ``conan_<pkg>.props`` files into the ``conanfile.generators_folder``.
"""
check_duplicated_generator(self, self._conanfile)
if self.configuration is None:
raise ConanException("MSBuildDeps.configuration is None, it should have a value")
if self.platform is None:
Expand Down
2 changes: 2 additions & 0 deletions conan/tools/microsoft/nmakedeps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os

from conan.internal import check_duplicated_generator
from conan.tools.env import Environment
from conans.model.build_info import CppInfo

Expand Down Expand Up @@ -58,4 +59,5 @@ def vars(self, scope="build"):
return self.environment.vars(self._conanfile, scope=scope)

def generate(self, scope="build"):
check_duplicated_generator(self, self._conanfile)
self.vars(scope).save_script("conannmakedeps")
2 changes: 2 additions & 0 deletions conan/tools/microsoft/nmaketoolchain.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from conan.internal import check_duplicated_generator
from conan.tools.build.flags import build_type_flags, cppstd_flag
from conan.tools.env import Environment

Expand Down Expand Up @@ -51,6 +52,7 @@ def vars(self, scope="build"):
return self.environment.vars(self._conanfile, scope=scope)

def generate(self, scope="build"):
check_duplicated_generator(self, self._conanfile)
self.vars(scope).save_script("conannmaketoolchain")
from conan.tools.microsoft import VCVars
VCVars(self._conanfile).generate()
2 changes: 2 additions & 0 deletions conan/tools/microsoft/toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from jinja2 import Template

from conan.internal import check_duplicated_generator
from conan.tools.build import build_jobs
from conan.tools.intel.intel_cc import IntelCC
from conan.tools.microsoft.visual import VCVars, msvc_version_to_toolset_version
Expand Down Expand Up @@ -91,6 +92,7 @@ def generate(self):
valid XML format with all the good settings like any other VS project ``*.props`` file. The
last one emulates the ``vcvarsall.bat`` env script. See also :class:`VCVars`.
"""
check_duplicated_generator(self, self._conanfile)
name, condition = self._name_condition(self._conanfile.settings)
config_filename = "conantoolchain{}.props".format(name)
# Writing the props files
Expand Down
2 changes: 2 additions & 0 deletions conan/tools/microsoft/visual.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import textwrap

from conan.internal import check_duplicated_generator
from conans.client.conf.detect_vs import vs_installation_path
from conans.errors import ConanException, ConanInvalidConfiguration
from conan.tools.scm import Version
Expand Down Expand Up @@ -90,6 +91,7 @@ def generate(self, scope="build"):
:param scope: ``str`` Launcher to be used to run all the variables. For instance,
if ``build``, then it'll be used the ``conanbuild`` launcher.
"""
check_duplicated_generator(self, self._conanfile)
conanfile = self._conanfile
os_ = conanfile.settings.get_safe("os")
if os_ != "Windows":
Expand Down
2 changes: 2 additions & 0 deletions conan/tools/premake/premakedeps.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from conan.internal import check_duplicated_generator
from conans.model.build_info import CppInfo
from conans.util.files import save

Expand Down Expand Up @@ -41,6 +42,7 @@ def __init__(self, conanfile):
self._conanfile = conanfile

def generate(self):
check_duplicated_generator(self, self._conanfile)
# Current directory is the generators_folder
generator_files = self.content
for generator_file, content in generator_files.items():
Expand Down
3 changes: 3 additions & 0 deletions conan/tools/qbs/qbsprofile.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

from io import StringIO
from jinja2 import Template

from conan.internal import check_duplicated_generator
from conans.errors import ConanException
from conans.util.files import save

Expand Down Expand Up @@ -284,6 +286,7 @@ def __init__(self, conanfile):
conanfile.options.get_safe('fPIC'))

def generate(self):
check_duplicated_generator(self, self._conanfile)
save(self.old_filename, self.content)
save(self.filename, self.content)

Expand Down
39 changes: 24 additions & 15 deletions conans/client/generators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,21 +93,30 @@ def write_generators(conanfile, hook_manager):

if conanfile.generators:
conanfile.output.info(f"Writing generators to {new_gen_folder}")
for generator_name in set(conanfile.generators):
generator_class = _get_generator_class(generator_name)
if generator_class:
try:
generator = generator_class(conanfile)
conanfile.output.highlight(f"Generator '{generator_name}' calling 'generate()'")
mkdir(new_gen_folder)
with chdir(new_gen_folder):
generator.generate()
continue
except Exception as e:
# When a generator fails, it is very useful to have the whole stacktrace
conanfile.output.error(traceback.format_exc())
raise ConanException("Error in generator '{}': {}".format(generator_name, str(e)))

# generators check that they are not present in the generators field,
# to avoid duplicates between the generators attribute and the generate() method
# They would raise an exception here if we don't invalidate the field while we call them
old_generators = set(conanfile.generators)
conanfile.generators = []
AbrilRBS marked this conversation as resolved.
Show resolved Hide resolved
try:
for generator_name in old_generators:
generator_class = _get_generator_class(generator_name)
if generator_class:
try:
generator = generator_class(conanfile)
conanfile.output.highlight(f"Generator '{generator_name}' calling 'generate()'")
mkdir(new_gen_folder)
with chdir(new_gen_folder):
generator.generate()
continue
except Exception as e:
# When a generator fails, it is very useful to have the whole stacktrace
conanfile.output.error(traceback.format_exc())
raise ConanException(f"Error in generator '{generator_name}': {str(e)}") from e
finally:
# restore the generators attribute, so it can raise
# if the user tries to instantiate a generator already present in generators
conanfile.generators = old_generators
if hasattr(conanfile, "generate"):
conanfile.output.highlight("Calling generate()")
mkdir(new_gen_folder)
Expand Down
Loading