diff options
| author | Jussi Pakkanen <jpakkane@gmail.com> | 2024-04-14 12:58:30 +0300 |
|---|---|---|
| committer | Jussi Pakkanen <jpakkane@gmail.com> | 2025-02-13 23:57:48 +0200 |
| commit | d37d649b08b832d52fa684bc0506829fb40d5261 (patch) | |
| tree | c66e1461e91d6349457b826978e866fdabb19de1 /mesonbuild/backend | |
| parent | ea678ed82938ceac00682b2695b57193d36b71b4 (diff) | |
| download | meson-d37d649b08b832d52fa684bc0506829fb40d5261.tar.gz | |
Make all Meson level options overridable per subproject.
Diffstat (limited to 'mesonbuild/backend')
| -rw-r--r-- | mesonbuild/backend/backends.py | 47 | ||||
| -rw-r--r-- | mesonbuild/backend/ninjabackend.py | 62 | ||||
| -rw-r--r-- | mesonbuild/backend/vs2010backend.py | 25 | ||||
| -rw-r--r-- | mesonbuild/backend/xcodebackend.py | 9 |
4 files changed, 82 insertions, 61 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 8d9796db9..a6a42e933 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -26,7 +26,7 @@ from .. import mesonlib from .. import mlog from ..compilers import LANGUAGES_USING_LDFLAGS, detect, lang_suffixes from ..mesonlib import ( - File, MachineChoice, MesonException, OrderedSet, + File, MachineChoice, MesonException, MesonBugException, OrderedSet, ExecutableSerialisation, EnvironmentException, classify_unity_sources, get_compiler_for_source ) @@ -424,7 +424,7 @@ class Backend: abs_files: T.List[str] = [] result: T.List[mesonlib.File] = [] compsrcs = classify_unity_sources(target.compilers.values(), unity_src) - unity_size = target.get_option(OptionKey('unity_size')) + unity_size = self.get_target_option(target, 'unity_size') assert isinstance(unity_size, int), 'for mypy' def init_language_file(suffix: str, unity_file_number: int) -> T.TextIO: @@ -878,7 +878,8 @@ class Backend: object_suffix = machine.get_object_suffix() # For the TASKING compiler, in case of LTO or prelinking the object suffix has to be .mil if compiler.get_id() == 'tasking': - if target.get_option(OptionKey('b_lto')) or (isinstance(target, build.StaticLibrary) and target.prelink): + use_lto = self.get_target_option(target, 'b_lto') + if use_lto or (isinstance(target, build.StaticLibrary) and target.prelink): if not source.rsplit('.', 1)[1] in lang_suffixes['c']: if isinstance(target, build.StaticLibrary) and not target.prelink: raise EnvironmentException('Tried using MIL linking for a static library with a assembly file. This can only be done if the static library is prelinked or disable \'b_lto\'.') @@ -925,10 +926,10 @@ class Backend: # With unity builds, sources don't map directly to objects, # we only support extracting all the objects in this mode, # so just return all object files. - if extobj.target.is_unity: + if self.is_unity(extobj.target): compsrcs = classify_unity_sources(extobj.target.compilers.values(), sources) sources = [] - unity_size = extobj.target.get_option(OptionKey('unity_size')) + unity_size = self.get_target_option(extobj.target, 'unity_size') assert isinstance(unity_size, int), 'for mypy' for comp, srcs in compsrcs.items(): @@ -981,7 +982,7 @@ class Backend: def target_uses_pch(self, target: build.BuildTarget) -> bool: try: - return T.cast('bool', target.get_option(OptionKey('b_pch'))) + return T.cast('bool', self.get_target_option(target, 'b_pch')) except (KeyError, AttributeError): return False @@ -1007,7 +1008,6 @@ class Backend: # starting from hard-coded defaults followed by build options and so on. commands = compiler.compiler_args() - copt_proxy = target.get_options() # First, the trivial ones that are impossible to override. # # Add -nostdinc/-nostdinc++ if needed; can't be overridden @@ -1015,22 +1015,22 @@ class Backend: # Add things like /NOLOGO or -pipe; usually can't be overridden commands += compiler.get_always_args() # warning_level is a string, but mypy can't determine that - commands += compiler.get_warn_args(T.cast('str', target.get_option(OptionKey('warning_level')))) + commands += compiler.get_warn_args(T.cast('str', self.get_target_option(target, 'warning_level'))) # Add -Werror if werror=true is set in the build options set on the # command-line or default_options inside project(). This only sets the # action to be done for warnings if/when they are emitted, so it's ok # to set it after or get_warn_args(). - if target.get_option(OptionKey('werror')): + if self.get_target_option(target, 'werror'): commands += compiler.get_werror_args() # Add compile args for c_* or cpp_* build options set on the # command-line or default_options inside project(). - commands += compiler.get_option_compile_args(copt_proxy) + commands += compiler.get_option_compile_args(target, self.environment, target.subproject) - optimization = target.get_option(OptionKey('optimization')) + optimization = self.get_target_option(target, 'optimization') assert isinstance(optimization, str), 'for mypy' commands += compiler.get_optimization_args(optimization) - debug = target.get_option(OptionKey('debug')) + debug = self.get_target_option(target, 'debug') assert isinstance(debug, bool), 'for mypy' commands += compiler.get_debug_args(debug) @@ -1755,7 +1755,7 @@ class Backend: # TODO: Create GNUStrip/AppleStrip/etc. hierarchy for more # fine-grained stripping of static archives. can_strip = not isinstance(t, build.StaticLibrary) - should_strip = can_strip and t.get_option(OptionKey('strip')) + should_strip = can_strip and self.get_target_option(t, 'strip') assert isinstance(should_strip, bool), 'for mypy' # Install primary build output (library/executable/jar, etc) # Done separately because of strip/aliases/rpath @@ -2092,3 +2092,24 @@ class Backend: all_sources = T.cast('_ALL_SOURCES_TYPE', target.sources) + T.cast('_ALL_SOURCES_TYPE', target.generated) return self.compiler_to_generator(target, target.compiler, all_sources, target.output_templ, target.depends) + + def is_unity(self, target: build.BuildTarget) -> bool: + if isinstance(target, build.CompileTarget): + return False + val = self.get_target_option(target, 'unity') + if val == 'on': + return True + if val == 'off': + return False + if val == 'subprojects': + return target.subproject != '' + raise MesonException(f'Internal error: invalid option type for "unity": {val}') + + def get_target_option(self, target: build.BuildTarget, name: T.Union[str, OptionKey]) -> T.Union[str, int, bool, T.List[str]]: + if isinstance(name, str): + key = OptionKey(name, subproject=target.subproject) + elif isinstance(name, OptionKey): + key = name + else: + raise MesonBugException('Internal error: invalid option type.') + return self.environment.coredata.get_option_for_target(target, key) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index cabb7be04..57d73ed18 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -638,7 +638,7 @@ class NinjaBackend(backends.Backend): outfile.write('# Do not edit by hand.\n\n') outfile.write('ninja_required_version = 1.8.2\n\n') - num_pools = self.environment.coredata.optstore.get_value('backend_max_links') + num_pools = self.environment.coredata.optstore.get_value_for('backend_max_links') if num_pools > 0: outfile.write(f'''pool link_pool depth = {num_pools} @@ -671,8 +671,8 @@ class NinjaBackend(backends.Backend): self.generate_dist() mlog.log_timestamp("Dist generated") key = OptionKey('b_coverage') - if (key in self.environment.coredata.optstore and - self.environment.coredata.optstore.get_value(key)): + if key in self.environment.coredata.optstore and\ + self.environment.coredata.optstore.get_value_for('b_coverage'): gcovr_exe, gcovr_version, lcov_exe, lcov_version, genhtml_exe, llvm_cov_exe = environment.find_coverage_tools(self.environment.coredata) mlog.debug(f'Using {gcovr_exe} ({gcovr_version}), {lcov_exe} and {llvm_cov_exe} for code coverage') if gcovr_exe or (lcov_exe and genhtml_exe): @@ -957,7 +957,7 @@ class NinjaBackend(backends.Backend): # Generate rules for building the remaining source files in this target outname = self.get_target_filename(target) obj_list = [] - is_unity = target.is_unity + is_unity = self.is_unity(target) header_deps = [] unity_src = [] unity_deps = [] # Generated sources that must be built before compiling a Unity target. @@ -1117,7 +1117,9 @@ class NinjaBackend(backends.Backend): cpp = target.compilers['cpp'] if cpp.get_id() != 'msvc': return False - cppversion = target.get_option(OptionKey('cpp_std', machine=target.for_machine)) + cppversion = self.get_target_option(target, OptionKey('cpp_std', + machine=target.for_machine, + subproject=target.subproject)) if cppversion not in ('latest', 'c++latest', 'vc++latest'): return False if not mesonlib.current_vs_supports_modules(): @@ -1725,7 +1727,7 @@ class NinjaBackend(backends.Backend): valac_outputs.append(vala_c_file) args = self.generate_basic_compiler_args(target, valac) - args += valac.get_colorout_args(target.get_option(OptionKey('b_colorout'))) + args += valac.get_colorout_args(self.get_target_option(target, 'b_colorout')) # Tell Valac to output everything in our private directory. Sadly this # means it will also preserve the directory components of Vala sources # found inside the build tree (generated sources). @@ -1737,7 +1739,7 @@ class NinjaBackend(backends.Backend): # Outputted header hname = os.path.join(self.get_target_dir(target), target.vala_header) args += ['--header', hname] - if target.is_unity: + if self.is_unity(target): # Without this the declarations will get duplicated in the .c # files and cause a build failure when all of them are # #include-d in one .c file. @@ -1803,14 +1805,14 @@ class NinjaBackend(backends.Backend): args: T.List[str] = [] args += cython.get_always_args() - args += cython.get_debug_args(target.get_option(OptionKey('debug'))) - args += cython.get_optimization_args(target.get_option(OptionKey('optimization'))) - args += cython.get_option_compile_args(target.get_options()) + args += cython.get_debug_args(self.get_target_option(target, 'debug')) + args += cython.get_optimization_args(self.get_target_option(target, 'optimization')) + args += cython.get_option_compile_args(target, self.environment, target.subproject) args += self.build.get_global_args(cython, target.for_machine) args += self.build.get_project_args(cython, target.subproject, target.for_machine) args += target.get_extra_args('cython') - ext = target.get_option(OptionKey('cython_language', machine=target.for_machine)) + ext = self.get_target_option(target, OptionKey('cython_language', machine=target.for_machine)) pyx_sources = [] # Keep track of sources we're adding to build @@ -1933,10 +1935,9 @@ class NinjaBackend(backends.Backend): # Rust compiler takes only the main file as input and # figures out what other files are needed via import # statements and magic. - base_proxy = target.get_options() args = rustc.compiler_args() # Compiler args for compiling this target - args += compilers.get_base_compile_args(base_proxy, rustc, self.environment) + args += compilers.get_base_compile_args(target, rustc, self.environment) self.generate_generator_list_rules(target) # dependencies need to cause a relink, they're not just for ordering @@ -2017,8 +2018,8 @@ class NinjaBackend(backends.Backend): # https://github.com/rust-lang/rust/issues/39016 if not isinstance(target, build.StaticLibrary): try: - buildtype = target.get_option(OptionKey('buildtype')) - crt = target.get_option(OptionKey('b_vscrt')) + buildtype = self.get_target_option(target, 'buildtype') + crt = self.get_target_option(target, 'b_vscrt') args += rustc.get_crt_link_args(crt, buildtype) except (KeyError, AttributeError): pass @@ -2301,7 +2302,7 @@ class NinjaBackend(backends.Backend): return options def generate_static_link_rules(self) -> None: - num_pools = self.environment.coredata.optstore.get_value('backend_max_links') + num_pools = self.environment.coredata.optstore.get_value_for('backend_max_links') if 'java' in self.environment.coredata.compilers.host: self.generate_java_link() for for_machine in MachineChoice: @@ -2349,7 +2350,7 @@ class NinjaBackend(backends.Backend): self.add_rule(NinjaRule(rule, cmdlist, args, description, **options, extra=pool)) def generate_dynamic_link_rules(self) -> None: - num_pools = self.environment.coredata.optstore.get_value('backend_max_links') + num_pools = self.environment.coredata.optstore.get_value_for('backend_max_links') for for_machine in MachineChoice: complist = self.environment.coredata.compilers[for_machine] for langname, compiler in complist.items(): @@ -2832,11 +2833,10 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) return [] def generate_llvm_ir_compile(self, target, src: FileOrString): - base_proxy = target.get_options() compiler = get_compiler_for_source(target.compilers.values(), src) commands = compiler.compiler_args() # Compiler args for compiling this target - commands += compilers.get_base_compile_args(base_proxy, compiler, self.environment) + commands += compilers.get_base_compile_args(target, compiler, self.environment) if isinstance(src, File): if src.is_built: src_filename = os.path.join(src.subdir, src.fname) @@ -2892,7 +2892,6 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) return commands def _generate_single_compile_base_args(self, target: build.BuildTarget, compiler: 'Compiler') -> 'CompilerArgs': - base_proxy = target.get_options() # Create an empty commands list, and start adding arguments from # various sources in the order in which they must override each other commands = compiler.compiler_args() @@ -2901,7 +2900,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) # Add compiler args for compiling this target derived from 'base' build # options passed on the command-line, in default_options, etc. # These have the lowest priority. - commands += compilers.get_base_compile_args(base_proxy, + commands += compilers.get_base_compile_args(target, compiler, self.environment) return commands @@ -3312,7 +3311,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) commands += linker.gen_vs_module_defs_args(target.vs_module_defs.rel_to_builddir(self.build_to_src)) elif isinstance(target, build.SharedLibrary): if isinstance(target, build.SharedModule): - commands += linker.get_std_shared_module_link_args(target.get_options()) + commands += linker.get_std_shared_module_link_args(target) else: commands += linker.get_std_shared_lib_link_args() # All shared libraries are PIC @@ -3511,20 +3510,19 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) # options passed on the command-line, in default_options, etc. # These have the lowest priority. if isinstance(target, build.StaticLibrary): - commands += linker.get_base_link_args(target.get_options()) + commands += linker.get_base_link_args(target, linker, self.environment) else: - commands += compilers.get_base_link_args(target.get_options(), + commands += compilers.get_base_link_args(target, linker, - isinstance(target, build.SharedModule), - self.environment.get_build_dir()) + self.environment) # Add -nostdlib if needed; can't be overridden commands += self.get_no_stdlib_link_args(target, linker) # Add things like /NOLOGO; usually can't be overridden commands += linker.get_linker_always_args() # Add buildtype linker args: optimization level, etc. - commands += linker.get_optimization_link_args(target.get_option(OptionKey('optimization'))) + commands += linker.get_optimization_link_args(self.get_target_option(target, 'optimization')) # Add /DEBUG and the pdb filename when using MSVC - if target.get_option(OptionKey('debug')): + if self.get_target_option(target, 'debug'): commands += self.get_link_debugfile_args(linker, target) debugfile = self.get_link_debugfile_name(linker, target) if debugfile is not None: @@ -3595,7 +3593,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) # # We shouldn't check whether we are making a static library, because # in the LTO case we do use a real compiler here. - commands += linker.get_option_link_args(target.get_options()) + commands += linker.get_option_link_args(target, self.environment) dep_targets = [] dep_targets.extend(self.guess_external_link_dependencies(linker, target, commands, internal)) @@ -3679,7 +3677,9 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) gcda_elem.add_item('description', 'Deleting gcda files') self.add_build(gcda_elem) - def get_user_option_args(self) -> T.List[str]: + def get_user_option_args(self, shut_up_pylint: bool = True) -> T.List[str]: + if shut_up_pylint: + return [] cmds = [] for k, v in self.environment.coredata.optstore.items(): if self.environment.coredata.optstore.is_project_option(k): @@ -3827,7 +3827,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) elem.add_dep(self.generate_custom_target_clean(ctlist)) if OptionKey('b_coverage') in self.environment.coredata.optstore and \ - self.environment.coredata.optstore.get_value('b_coverage'): + self.environment.coredata.optstore.get_value_for('b_coverage'): self.generate_gcov_clean() elem.add_dep('clean-gcda') elem.add_dep('clean-gcno') diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index e837c89ce..101508315 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -271,7 +271,7 @@ class Vs2010Backend(backends.Backend): self.debug = self.environment.coredata.get_option(OptionKey('debug')) try: self.sanitize = self.environment.coredata.get_option(OptionKey('b_sanitize')) - except MesonException: + except KeyError: self.sanitize = 'none' sln_filename = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.sln') projlist = self.generate_projects(vslite_ctx) @@ -996,9 +996,9 @@ class Vs2010Backend(backends.Backend): for l, comp in target.compilers.items(): if l in file_args: file_args[l] += compilers.get_base_compile_args( - target.get_options(), comp, self.environment) + target, comp, self.environment) file_args[l] += comp.get_option_compile_args( - target.get_options()) + target, self.environment, target.subproject) # Add compile args added using add_project_arguments() for l, args in self.build.projects_args[target.for_machine].get(target.subproject, {}).items(): @@ -1012,7 +1012,7 @@ class Vs2010Backend(backends.Backend): # Compile args added from the env or cross file: CFLAGS/CXXFLAGS, etc. We want these # to override all the defaults, but not the per-target compile args. for lang in file_args.keys(): - file_args[lang] += target.get_option(OptionKey(f'{lang}_args', machine=target.for_machine)) + file_args[lang] += self.get_target_option(target, OptionKey(f'{lang}_args', machine=target.for_machine)) for args in file_args.values(): # This is where Visual Studio will insert target_args, target_defines, # etc, which are added later from external deps (see below). @@ -1302,7 +1302,7 @@ class Vs2010Backend(backends.Backend): if True in ((dep.name == 'openmp') for dep in target.get_external_deps()): ET.SubElement(clconf, 'OpenMPSupport').text = 'true' # CRT type; debug or release - vscrt_type = target.get_option(OptionKey('b_vscrt')) + vscrt_type = self.get_target_option(target, 'b_vscrt') vscrt_val = compiler.get_crt_val(vscrt_type, self.buildtype) if vscrt_val == 'mdd': ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' @@ -1340,7 +1340,7 @@ class Vs2010Backend(backends.Backend): # Exception handling has to be set in the xml in addition to the "AdditionalOptions" because otherwise # cl will give warning D9025: overriding '/Ehs' with cpp_eh value if 'cpp' in target.compilers: - eh = target.get_option(OptionKey('cpp_eh', machine=target.for_machine)) + eh = self.environment.coredata.get_option_for_target(target, OptionKey('cpp_eh', machine=target.for_machine)) if eh == 'a': ET.SubElement(clconf, 'ExceptionHandling').text = 'Async' elif eh == 's': @@ -1358,10 +1358,10 @@ class Vs2010Backend(backends.Backend): ET.SubElement(clconf, 'PreprocessorDefinitions').text = ';'.join(target_defines) ET.SubElement(clconf, 'FunctionLevelLinking').text = 'true' # Warning level - warning_level = T.cast('str', target.get_option(OptionKey('warning_level'))) + warning_level = T.cast('str', self.get_target_option(target, 'warning_level')) warning_level = 'EnableAllWarnings' if warning_level == 'everything' else 'Level' + str(1 + int(warning_level)) ET.SubElement(clconf, 'WarningLevel').text = warning_level - if target.get_option(OptionKey('werror')): + if self.get_target_option(target, 'werror'): ET.SubElement(clconf, 'TreatWarningAsError').text = 'true' # Optimization flags o_flags = split_o_flags_args(build_args) @@ -1402,7 +1402,7 @@ class Vs2010Backend(backends.Backend): ET.SubElement(link, 'GenerateDebugInformation').text = 'false' if not isinstance(target, build.StaticLibrary): if isinstance(target, build.SharedModule): - extra_link_args += compiler.get_std_shared_module_link_args(target.get_options()) + extra_link_args += compiler.get_std_shared_module_link_args(target) # Add link args added using add_project_link_arguments() extra_link_args += self.build.get_project_link_args(compiler, target.subproject, target.for_machine) # Add link args added using add_global_link_arguments() @@ -1435,7 +1435,7 @@ class Vs2010Backend(backends.Backend): # to be after all internal and external libraries so that unresolved # symbols from those can be found here. This is needed when the # *_winlibs that we want to link to are static mingw64 libraries. - extra_link_args += compiler.get_option_link_args(target.get_options()) + extra_link_args += compiler.get_option_link_args(target, self.environment, target.subproject) (additional_libpaths, additional_links, extra_link_args) = self.split_link_args(extra_link_args.to_native()) # Add more libraries to be linked if needed @@ -1534,7 +1534,8 @@ class Vs2010Backend(backends.Backend): # /nologo ET.SubElement(link, 'SuppressStartupBanner').text = 'true' # /release - if not target.get_option(OptionKey('debug')): + addchecksum = self.get_target_option(target, 'buildtype') != 'debug' + if addchecksum: ET.SubElement(link, 'SetChecksum').text = 'true' # Visual studio doesn't simply allow the src files of a project to be added with the 'Condition=...' attribute, @@ -1596,7 +1597,7 @@ class Vs2010Backend(backends.Backend): raise MesonException(f'Unknown target type for {target.get_basename()}') (sources, headers, objects, _languages) = self.split_sources(target.sources) - if target.is_unity: + if self.is_unity(target): sources = self.generate_unity_files(target, sources) if target.for_machine is MachineChoice.BUILD: platform = self.build_platform diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 0e40d0239..9f2e0a1b6 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -1686,9 +1686,8 @@ class XCodeBackend(backends.Backend): if compiler is None: continue # Start with warning args - warn_args = compiler.get_warn_args(target.get_option(OptionKey('warning_level'))) - copt_proxy = target.get_options() - std_args = compiler.get_option_compile_args(copt_proxy) + warn_args = compiler.get_warn_args(self.get_target_option(target, 'warning_level')) + std_args = compiler.get_option_compile_args(target, self.environment, target.subproject) # Add compile args added using add_project_arguments() pargs = self.build.projects_args[target.for_machine].get(target.subproject, {}).get(lang, []) # Add compile args added using add_global_arguments() @@ -1736,9 +1735,9 @@ class XCodeBackend(backends.Backend): if target.suffix: suffix = '.' + target.suffix settings_dict.add_item('EXECUTABLE_SUFFIX', suffix) - settings_dict.add_item('GCC_GENERATE_DEBUGGING_SYMBOLS', BOOL2XCODEBOOL[target.get_option(OptionKey('debug'))]) + settings_dict.add_item('GCC_GENERATE_DEBUGGING_SYMBOLS', BOOL2XCODEBOOL[self.get_target_option(target, 'debug')]) settings_dict.add_item('GCC_INLINES_ARE_PRIVATE_EXTERN', 'NO') - opt_flag = OPT2XCODEOPT[target.get_option(OptionKey('optimization'))] + opt_flag = OPT2XCODEOPT[self.get_target_option(target, 'optimization')] if opt_flag is not None: settings_dict.add_item('GCC_OPTIMIZATION_LEVEL', opt_flag) if target.has_pch: |
