aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/FAQ.md33
-rw-r--r--docs/markdown/snippets/buildtyperemains.md10
-rw-r--r--docs/markdown/snippets/msvc_no_zi.md14
-rw-r--r--mesonbuild/backend/backends.py9
-rw-r--r--mesonbuild/backend/ninjabackend.py68
-rw-r--r--mesonbuild/build.py29
-rw-r--r--mesonbuild/compilers/mixins/visualstudio.py4
-rw-r--r--mesonbuild/coredata.py48
-rw-r--r--mesonbuild/mconf.py11
-rw-r--r--mesonbuild/modules/unstable_external_project.py9
-rw-r--r--mesonbuild/modules/unstable_rust.py2
-rw-r--r--mesonbuild/wrap/wrap.py22
-rwxr-xr-xrun_unittests.py75
-rw-r--r--test cases/rust/11 generated main/gen.py16
-rw-r--r--test cases/rust/11 generated main/meson.build16
-rw-r--r--test cases/unit/89 pkgconfig build rpath order/dummy.pc7
-rw-r--r--test cases/unit/89 pkgconfig build rpath order/meson.build20
-rw-r--r--test cases/unit/89 pkgconfig build rpath order/prog.c5
-rw-r--r--test cases/unit/89 pkgconfig build rpath order/prog.cc8
-rw-r--r--test cases/unit/89 pkgconfig build rpath order/sub/meson.build1
-rw-r--r--test cases/unit/89 pkgconfig build rpath order/sub/stuff.c3
21 files changed, 284 insertions, 126 deletions
diff --git a/docs/markdown/FAQ.md b/docs/markdown/FAQ.md
index 7a41443..4ea4d8d 100644
--- a/docs/markdown/FAQ.md
+++ b/docs/markdown/FAQ.md
@@ -500,3 +500,36 @@ meson -Dcpp_eh=none -Dcpp_rtti=false <other options>
```
The RTTI option is only available since Meson version 0.53.0.
+
+## Should I check for `buildtype` or individual options like `debug` in my build files?
+
+This depends highly on what you actually need to happen. The
+´buildtype` option is meant do describe the current build's
+_intent_. That is, what it will be used for. Individual options are
+for determining what the exact state is. This becomes clearer with a
+few examples.
+
+Suppose you have a source file that is known to miscompile when using
+`-O3` and requires a workaround. Then you'd write something like this:
+
+```meson
+if get_option('optimization') == '3'
+ add_project_arguments('-DOPTIMIZATION_WORKAROUND', ...)
+endif
+```
+
+On the other hand if your project has extra logging and sanity checks
+that you would like to be enabled during the day to day development
+work (which uses the `debug` buildtype), you'd do this instead:
+
+```meson
+if get_option('buildtype') == 'debug'
+ add_project_arguments('-DENABLE_EXTRA_CHECKS', ...)
+endif
+```
+
+In this way the extra options are automatically used during
+development but are not compiled in release builds. Note that (since
+Meson 0.57.0) you can set optimization to, say, 2 in your debug builds
+if you want to. If you tried to set this flag based on optimization
+level, it would fail in this case.
diff --git a/docs/markdown/snippets/buildtyperemains.md b/docs/markdown/snippets/buildtyperemains.md
new file mode 100644
index 0000000..4eb6243
--- /dev/null
+++ b/docs/markdown/snippets/buildtyperemains.md
@@ -0,0 +1,10 @@
+## Buildtype remains even if dependent options are changed
+
+Setting the `buildtype' option to a value sets the `debug` and
+`optimization` options to predefined values. Traditionally setting the
+options to other values would then change the buildtype to `custom`.
+This is confusing and means that you can't use, for example, debug
+level `g` in `debug` buildtype even though it would make sense under
+many circumstances. Starting with the buildtype is only changed when
+the user explicitly sets it. Setting the build type sets the other
+options to their default values as before. \ No newline at end of file
diff --git a/docs/markdown/snippets/msvc_no_zi.md b/docs/markdown/snippets/msvc_no_zi.md
new file mode 100644
index 0000000..711598d
--- /dev/null
+++ b/docs/markdown/snippets/msvc_no_zi.md
@@ -0,0 +1,14 @@
+## "Edit and continue" (/ZI) is no longer used by default for Visual Studio
+
+Meson was adding the `/ZI` compiler argument as an argument for Visual Studio
+in debug mode. This enables the `edit-and-continue` debugging in
+Visual Studio IDE's.
+
+Unfortunately, it is also extremely expensive and breaks certain use cases such
+as link time code generation. Edit and continue can be enabled by manually by
+adding `/ZI` to compiler arguments.
+
+The `/ZI` argument has now been replaced by the `/Zi` argument for debug builds.
+
+If this is an important issue for you and would like a builtin toggle option,
+please file an issue in the Meson bug tracker. \ No newline at end of file
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 92e6c15..ced1d7d 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -717,15 +717,16 @@ class Backend:
commands += compiler.get_buildtype_args(self.get_option_for_target(OptionKey('buildtype'), target))
commands += compiler.get_optimization_args(self.get_option_for_target(OptionKey('optimization'), target))
commands += compiler.get_debug_args(self.get_option_for_target(OptionKey('debug'), target))
- # MSVC debug builds have /ZI argument by default and /Zi is added with debug flag
- # /ZI needs to be removed in that case to avoid cl's warning to that effect (D9025 : overriding '/ZI' with '/Zi')
- if ('/ZI' in commands) and ('/Zi' in commands):
- commands.remove('/Zi')
# Add compile args added using add_project_arguments()
commands += self.build.get_project_args(compiler, target.subproject, target.for_machine)
# Add compile args added using add_global_arguments()
# These override per-project arguments
commands += self.build.get_global_args(compiler, target.for_machine)
+ # Using both /ZI and /Zi at the same times produces a compiler warning.
+ # We do not add /ZI by default. If it is being used it is because the user has explicitly enabled it.
+ # /ZI needs to be removed in that case to avoid cl's warning to that effect (D9025 : overriding '/ZI' with '/Zi')
+ if ('/ZI' in commands) and ('/Zi' in commands):
+ commands.remove('/Zi')
# Compile args added from the env: CFLAGS/CXXFLAGS, etc, or the cross
# file. We want these to override all the defaults, but not the
# per-target compile args.
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index d66708c..400433f 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -45,7 +45,7 @@ from ..mesonlib import (
)
from ..mesonlib import get_compiler_for_source, has_path_sep, OptionKey
from .backends import CleanTrees
-from ..build import InvalidArguments
+from ..build import GeneratedList, InvalidArguments
from ..interpreter import Interpreter
if T.TYPE_CHECKING:
@@ -691,13 +691,6 @@ int dummy;
src_block['sources'] += sources
src_block['generated_sources'] += generated_sources
- def is_rust_target(self, target):
- if len(target.sources) > 0:
- first_file = target.sources[0]
- if first_file.fname.endswith('.rs'):
- return True
- return False
-
def generate_target(self, target):
try:
if isinstance(target, build.BuildTarget):
@@ -723,7 +716,7 @@ int dummy;
if isinstance(target, build.Jar):
self.generate_jar_target(target)
return
- if self.is_rust_target(target):
+ if target.uses_rust():
self.generate_rust_target(target)
return
if 'cs' in target.compilers:
@@ -1588,12 +1581,27 @@ int dummy;
args = rustc.compiler_args()
# Compiler args for compiling this target
args += compilers.get_base_compile_args(base_proxy, rustc)
+ self.generate_generator_list_rules(target)
+
+ orderdeps = [os.path.join(t.subdir, t.get_filename()) for t in target.link_targets]
+
main_rust_file = None
for i in target.get_sources():
if not rustc.can_compile(i):
raise InvalidArguments('Rust target {} contains a non-rust source file.'.format(target.get_basename()))
if main_rust_file is None:
main_rust_file = i.rel_to_builddir(self.build_to_src)
+ for g in target.get_generated_sources():
+ for i in g.get_outputs():
+ if not rustc.can_compile(i):
+ raise InvalidArguments('Rust target {} contains a non-rust source file.'.format(target.get_basename()))
+ if isinstance(g, GeneratedList):
+ fname = os.path.join(self.get_target_private_dir(target), i)
+ else:
+ fname = i
+ if main_rust_file is None:
+ main_rust_file = fname
+ orderdeps.append(fname)
if main_rust_file is None:
raise RuntimeError('A Rust target has no Rust sources. This is weird. Also a bug. Please report')
target_name = os.path.join(target.subdir, target.get_filename())
@@ -1631,7 +1639,6 @@ int dummy;
args += target.get_extra_args('rust')
args += rustc.get_output_args(os.path.join(target.subdir, target.get_filename()))
args += self.environment.coredata.get_external_args(target.for_machine, rustc.language)
- orderdeps = [os.path.join(t.subdir, t.get_filename()) for t in target.link_targets]
linkdirs = OrderedDict()
for d in target.link_targets:
linkdirs[d.subdir] = True
@@ -1678,7 +1685,7 @@ int dummy;
args += ['-C', 'link-arg=' + rpath_arg + ':' + os.path.join(rustc.get_sysroot(), 'lib')]
compiler_name = self.get_compiler_rule_name('rust', target.for_machine)
element = NinjaBuildElement(self.all_outputs, target_name, compiler_name, main_rust_file)
- if len(orderdeps) > 0:
+ if orderdeps:
element.add_orderdep(orderdeps)
element.add_item('ARGS', args)
element.add_item('targetdep', depfile)
@@ -2897,6 +2904,26 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
# Now we will add libraries and library paths from various sources
+ # Set runtime-paths so we can run executables without needing to set
+ # LD_LIBRARY_PATH, etc in the environment. Doesn't work on Windows.
+ if has_path_sep(target.name):
+ # Target names really should not have slashes in them, but
+ # unfortunately we did not check for that and some downstream projects
+ # now have them. Once slashes are forbidden, remove this bit.
+ target_slashname_workaround_dir = os.path.join(
+ os.path.dirname(target.name),
+ self.get_target_dir(target))
+ else:
+ target_slashname_workaround_dir = self.get_target_dir(target)
+ (rpath_args, target.rpath_dirs_to_remove) = (
+ linker.build_rpath_args(self.environment,
+ self.environment.get_build_dir(),
+ target_slashname_workaround_dir,
+ self.determine_rpath_dirs(target),
+ target.build_rpath,
+ target.install_rpath))
+ commands += rpath_args
+
# Add link args to link to all internal libraries (link_with:) and
# internal dependencies needed by this target.
if linker_base == 'STATIC':
@@ -2944,25 +2971,6 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
dep_targets = []
dep_targets.extend(self.guess_external_link_dependencies(linker, target, commands, internal))
- # Set runtime-paths so we can run executables without needing to set
- # LD_LIBRARY_PATH, etc in the environment. Doesn't work on Windows.
- if has_path_sep(target.name):
- # Target names really should not have slashes in them, but
- # unfortunately we did not check for that and some downstream projects
- # now have them. Once slashes are forbidden, remove this bit.
- target_slashname_workaround_dir = os.path.join(
- os.path.dirname(target.name),
- self.get_target_dir(target))
- else:
- target_slashname_workaround_dir = self.get_target_dir(target)
- (rpath_args, target.rpath_dirs_to_remove) = (
- linker.build_rpath_args(self.environment,
- self.environment.get_build_dir(),
- target_slashname_workaround_dir,
- self.determine_rpath_dirs(target),
- target.build_rpath,
- target.install_rpath))
- commands += rpath_args
# Add libraries generated by custom targets
custom_target_libraries = self.get_custom_target_provided_libraries(target)
commands += extra_args
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 017b0f0..13783d1 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -569,7 +569,7 @@ class BuildTarget(Target):
unity_opt = environment.coredata.get_option(OptionKey('unity'))
self.is_unity = unity_opt == 'on' or (unity_opt == 'subprojects' and subproject != '')
self.environment = environment
- self.sources = []
+ self.sources: T.List[File] = []
self.compilers = OrderedDict() # type: OrderedDict[str, Compiler]
self.objects = []
self.external_deps = []
@@ -588,7 +588,7 @@ class BuildTarget(Target):
self.need_install = False
self.pch = {}
self.extra_args: T.Dict[str, T.List['FileOrString']] = {}
- self.generated = []
+ self.generated: T.Sequence[T.Union[GeneratedList, CustomTarget, CustomTargetIndex]] = []
self.d_features = {}
self.pic = False
self.pie = False
@@ -1412,9 +1412,16 @@ You probably should put it in link_with instead.''')
m = 'Could not get a dynamic linker for build target {!r}'
raise AssertionError(m.format(self.name))
- def get_using_rustc(self) -> bool:
+ def uses_rust(self) -> bool:
"""Is this target a rust target."""
- return self.sources and self.sources[0].fname.endswith('.rs')
+ if self.sources:
+ first_file = self.sources[0]
+ if first_file.fname.endswith('.rs'):
+ return True
+ elif self.generated:
+ if self.generated[0].get_outputs()[0].endswith('.rs'):
+ return True
+ return False
def get_using_msvc(self):
'''
@@ -1434,11 +1441,13 @@ You probably should put it in link_with instead.''')
2. If the target contains only objects, process_compilers guesses and
picks the first compiler that smells right.
'''
- compiler, _ = self.get_clink_dynamic_linker_and_stdlibs()
+ # Rustc can use msvc style linkers
+ if self.uses_rust():
+ compiler = self.environment.coredata.compilers[self.for_machine]['rust']
+ else:
+ compiler, _ = self.get_clink_dynamic_linker_and_stdlibs()
# Mixing many languages with MSVC is not supported yet so ignore stdlibs.
- if compiler and compiler.get_linker_id() in {'link', 'lld-link', 'xilink', 'optlink'}:
- return True
- return False
+ return compiler and compiler.get_linker_id() in {'link', 'lld-link', 'xilink', 'optlink'}
def check_module_linking(self):
'''
@@ -1687,7 +1696,7 @@ class Executable(BuildTarget):
self.import_filename = self.gcc_import_filename
if m.is_windows() and ('cs' in self.compilers or
- self.get_using_rustc() or
+ self.uses_rust() or
self.get_using_msvc()):
self.debug_filename = self.name + '.pdb'
@@ -1877,7 +1886,7 @@ class SharedLibrary(BuildTarget):
suffix = 'dll'
self.vs_import_filename = '{0}{1}.lib'.format(self.prefix if self.prefix is not None else '', self.name)
self.gcc_import_filename = '{0}{1}.dll.a'.format(self.prefix if self.prefix is not None else 'lib', self.name)
- if self.get_using_rustc():
+ if self.uses_rust():
# Shared library is of the form foo.dll
prefix = ''
# Import library is called foo.dll.lib
diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py
index 92f4fcd..61ee7cf 100644
--- a/mesonbuild/compilers/mixins/visualstudio.py
+++ b/mesonbuild/compilers/mixins/visualstudio.py
@@ -62,14 +62,14 @@ vs64_instruction_set_args = {
msvc_buildtype_args = {
'plain': [],
- 'debug': ["/ZI", "/RTC1"],
+ 'debug': ["/RTC1"],
'debugoptimized': [],
'release': [],
'minsize': [],
'custom': [],
} # type: T.Dict[str, T.List[str]]
-# Clang-cl doesn't have /ZI, and /Zi and /Z7 do the same thing
+# Clang-cl /Zi and /Z7 do the same thing
# quoting the docs (https://clang.llvm.org/docs/MSVCCompatibility.html):
#
# Clang emits relatively complete CodeView debug information if /Z7 or /Zi is
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 39da863..211efec 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -582,8 +582,35 @@ class CoreData:
if key.name == 'buildtype':
self._set_others_from_buildtype(value)
- elif key.name in {'debug', 'optimization'}:
- self._set_buildtype_from_others()
+
+ def get_nondefault_buildtype_args(self):
+ result= []
+ value = self.options[OptionKey('buildtype')].value
+ if value == 'plain':
+ opt = '0'
+ debug = False
+ elif value == 'debug':
+ opt = '0'
+ debug = True
+ elif value == 'debugoptimized':
+ opt = '2'
+ debug = True
+ elif value == 'release':
+ opt = '3'
+ debug = False
+ elif value == 'minsize':
+ opt = 's'
+ debug = True
+ else:
+ assert(value == 'custom')
+ return []
+ actual_opt = self.options[OptionKey('optimization')].value
+ actual_debug = self.options[OptionKey('debug')].value
+ if actual_opt != opt:
+ result.append(('optimization', actual_opt, opt))
+ if actual_debug != debug:
+ result.append(('debug', actual_debug, debug))
+ return result
def _set_others_from_buildtype(self, value: str) -> None:
if value == 'plain':
@@ -607,23 +634,6 @@ class CoreData:
self.options[OptionKey('optimization')].set_value(opt)
self.options[OptionKey('debug')].set_value(debug)
- def _set_buildtype_from_others(self) -> None:
- opt = self.options[OptionKey('optimization')].value
- debug = self.options[OptionKey('debug')].value
- if opt == '0' and not debug:
- mode = 'plain'
- elif opt == '0' and debug:
- mode = 'debug'
- elif opt == '2' and debug:
- mode = 'debugoptimized'
- elif opt == '3' and not debug:
- mode = 'release'
- elif opt == 's' and debug:
- mode = 'minsize'
- else:
- mode = 'custom'
- self.options[OptionKey('buildtype')].set_value(mode)
-
@staticmethod
def is_per_machine_option(optname: OptionKey) -> bool:
if optname.name in BUILTIN_OPTIONS_PER_MACHINE:
diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py
index 686a336..5233d88 100644
--- a/mesonbuild/mconf.py
+++ b/mesonbuild/mconf.py
@@ -243,6 +243,17 @@ class Conf:
print('')
print_default_values_warning()
+ self.print_nondefault_buildtype_options()
+
+ def print_nondefault_buildtype_options(self):
+ mismatching = self.coredata.get_nondefault_buildtype_args()
+ if not mismatching:
+ return
+ print("\nThe following option(s) have a different value than the build type default\n")
+ print(f' current default')
+ for m in mismatching:
+ print(f'{m[0]:21}{m[1]:10}{m[2]:10}')
+
def run(options):
coredata.parse_cmd_line_options(options)
builddir = os.path.abspath(os.path.realpath(options.builddir))
diff --git a/mesonbuild/modules/unstable_external_project.py b/mesonbuild/modules/unstable_external_project.py
index 1604e25..e2205e5 100644
--- a/mesonbuild/modules/unstable_external_project.py
+++ b/mesonbuild/modules/unstable_external_project.py
@@ -162,12 +162,17 @@ class ExternalProject(InterpreterObject):
def _run(self, step: str, command: T.List[str]):
mlog.log('External project {}:'.format(self.name), mlog.bold(step))
- output = None if self.verbose else subprocess.DEVNULL
+ log_filename = Path(mlog.log_dir, '{}-{}.log'.format(self.name, step))
+ output = None
+ if not self.verbose:
+ output = open(log_filename, 'w')
p, o, e = Popen_safe(command, cwd=str(self.build_dir), env=self.run_env,
stderr=subprocess.STDOUT,
stdout=output)
if p.returncode != 0:
- m = '{} step failed:\n{}'.format(step, e)
+ m = '{} step returned error code {}.'.format(step, p.returncode)
+ if not self.verbose:
+ m += '\nSee logs: ' + str(log_filename)
raise MesonException(m)
def _create_targets(self):
diff --git a/mesonbuild/modules/unstable_rust.py b/mesonbuild/modules/unstable_rust.py
index 02369b6..d215376 100644
--- a/mesonbuild/modules/unstable_rust.py
+++ b/mesonbuild/modules/unstable_rust.py
@@ -85,7 +85,7 @@ class RustModule(ExtensionModule):
base_target: BuildTarget = unholder(args[1])
if not isinstance(base_target, BuildTarget):
raise InterpreterException('Second positional argument to rustmod.test() must be a library or executable')
- if not base_target.get_using_rustc():
+ if not base_target.uses_rust():
raise InterpreterException('Second positional argument to rustmod.test() must be a rust based target')
extra_args = stringlistify(kwargs.get('args', []))
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index bb153c5..34e58e3 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -114,11 +114,11 @@ class PackageDefinition:
def parse_wrap(self) -> None:
try:
- self.config = configparser.ConfigParser(interpolation=None)
- self.config.read(self.filename)
+ config = configparser.ConfigParser(interpolation=None)
+ config.read(self.filename)
except configparser.Error as e:
raise WrapException('Failed to parse {}: {}'.format(self.basename, str(e)))
- self.parse_wrap_section()
+ self.parse_wrap_section(config)
if self.type == 'redirect':
# [wrap-redirect] have a `filename` value pointing to the real wrap
# file we should parse instead. It must be relative to the current
@@ -140,21 +140,21 @@ class PackageDefinition:
self.filename = str(fname)
self.parse_wrap()
return
- self.parse_provide_section()
+ self.parse_provide_section(config)
- def parse_wrap_section(self) -> None:
- if len(self.config.sections()) < 1:
+ def parse_wrap_section(self, config: configparser.ConfigParser) -> None:
+ if len(config.sections()) < 1:
raise WrapException('Missing sections in {}'.format(self.basename))
- self.wrap_section = self.config.sections()[0]
+ self.wrap_section = config.sections()[0]
if not self.wrap_section.startswith('wrap-'):
m = '{!r} is not a valid first section in {}'
raise WrapException(m.format(self.wrap_section, self.basename))
self.type = self.wrap_section[5:]
- self.values = dict(self.config[self.wrap_section])
+ self.values = dict(config[self.wrap_section])
- def parse_provide_section(self) -> None:
- if self.config.has_section('provide'):
- for k, v in self.config['provide'].items():
+ def parse_provide_section(self, config: configparser.ConfigParser) -> None:
+ if config.has_section('provide'):
+ for k, v in config['provide'].items():
if k == 'dependency_names':
# A comma separated list of dependency names that does not
# need a variable name
diff --git a/run_unittests.py b/run_unittests.py
index e40ebc4..da6d329 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -3378,7 +3378,7 @@ class AllPlatformTests(BasePlatformTests):
self.assertFalse(os.path.isdir(scommondir))
self.assertNotEqual(subprocess.call(self.wrap_command + ['promote', 'scommon'],
cwd=workdir,
- stdout=subprocess.DEVNULL), 0)
+ stderr=subprocess.DEVNULL), 0)
self.assertNotEqual(subprocess.call(self.wrap_command + ['promote', 'invalid/path/to/scommon'],
cwd=workdir,
stderr=subprocess.DEVNULL), 0)
@@ -3401,7 +3401,7 @@ class AllPlatformTests(BasePlatformTests):
ambiguous_wrap = os.path.join(spdir, 'ambiguous.wrap')
self.assertNotEqual(subprocess.call(self.wrap_command + ['promote', 'ambiguous'],
cwd=workdir,
- stdout=subprocess.DEVNULL), 0)
+ stderr=subprocess.DEVNULL), 0)
self.assertFalse(os.path.isfile(ambiguous_wrap))
subprocess.check_call(self.wrap_command + ['promote', 'subprojects/s2/subprojects/ambiguous.wrap'], cwd=workdir)
self.assertTrue(os.path.isfile(ambiguous_wrap))
@@ -3929,51 +3929,13 @@ class AllPlatformTests(BasePlatformTests):
self.setconf('-Ddebug=false')
opts = self.get_opts_as_dict()
self.assertEqual(opts['debug'], False)
- self.assertEqual(opts['buildtype'], 'plain')
+ self.assertEqual(opts['buildtype'], 'debug')
self.assertEqual(opts['optimization'], '0')
-
- # Setting optimizations to 3 should cause buildtype
- # to go to release mode.
- self.setconf('-Doptimization=3')
+ self.setconf('-Doptimization=g')
opts = self.get_opts_as_dict()
- self.assertEqual(opts['buildtype'], 'release')
self.assertEqual(opts['debug'], False)
- self.assertEqual(opts['optimization'], '3')
-
- # Going to debug build type should reset debugging
- # and optimization
- self.setconf('-Dbuildtype=debug')
- opts = self.get_opts_as_dict()
self.assertEqual(opts['buildtype'], 'debug')
- self.assertEqual(opts['debug'], True)
- self.assertEqual(opts['optimization'], '0')
-
- # Command-line parsing of buildtype settings should be the same as
- # setting with `meson configure`.
- #
- # Setting buildtype should set optimization/debug
- self.new_builddir()
- self.init(testdir, extra_args=['-Dbuildtype=debugoptimized'])
- opts = self.get_opts_as_dict()
- self.assertEqual(opts['debug'], True)
- self.assertEqual(opts['optimization'], '2')
- self.assertEqual(opts['buildtype'], 'debugoptimized')
- # Setting optimization/debug should set buildtype
- self.new_builddir()
- self.init(testdir, extra_args=['-Doptimization=2', '-Ddebug=true'])
- opts = self.get_opts_as_dict()
- self.assertEqual(opts['debug'], True)
- self.assertEqual(opts['optimization'], '2')
- self.assertEqual(opts['buildtype'], 'debugoptimized')
- # Setting both buildtype and debug on the command-line should work, and
- # should warn not to do that. Also test that --debug is parsed as -Ddebug=true
- self.new_builddir()
- out = self.init(testdir, extra_args=['-Dbuildtype=debugoptimized', '--debug'])
- self.assertRegex(out, 'Recommend using either.*buildtype.*debug.*redundant')
- opts = self.get_opts_as_dict()
- self.assertEqual(opts['debug'], True)
- self.assertEqual(opts['optimization'], '2')
- self.assertEqual(opts['buildtype'], 'debugoptimized')
+ self.assertEqual(opts['optimization'], 'g')
@skipIfNoPkgconfig
@unittest.skipIf(is_windows(), 'Help needed with fixing this test on windows')
@@ -6720,18 +6682,37 @@ class LinuxlikeTests(BasePlatformTests):
testdir = os.path.join(self.unit_test_dir, '10 build_rpath')
self.init(testdir)
self.build()
- # C program RPATH
build_rpath = get_rpath(os.path.join(self.builddir, 'prog'))
self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar')
+ build_rpath = get_rpath(os.path.join(self.builddir, 'progcxx'))
+ self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar')
self.install()
install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/prog'))
self.assertEqual(install_rpath, '/baz')
- # C++ program RPATH
+ install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/progcxx'))
+ self.assertEqual(install_rpath, 'baz')
+
+ @skipIfNoPkgconfig
+ def test_build_rpath_pkgconfig(self):
+ '''
+ Test that current build artefacts (libs) are found first on the rpath,
+ manually specified rpath comes second and additional rpath elements (from
+ pkg-config files) come last
+ '''
+ if is_cygwin():
+ raise unittest.SkipTest('Windows PE/COFF binaries do not use RPATH')
+ testdir = os.path.join(self.unit_test_dir, '89 pkgconfig build rpath order')
+ self.init(testdir, override_envvars={'PKG_CONFIG_PATH': testdir})
+ self.build()
+ build_rpath = get_rpath(os.path.join(self.builddir, 'prog'))
+ self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar:/foo/dummy')
build_rpath = get_rpath(os.path.join(self.builddir, 'progcxx'))
- self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar')
+ self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar:/foo/dummy')
self.install()
+ install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/prog'))
+ self.assertEqual(install_rpath, '/baz:/foo/dummy')
install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/progcxx'))
- self.assertEqual(install_rpath, 'baz')
+ self.assertEqual(install_rpath, 'baz:/foo/dummy')
def test_global_rpath(self):
if is_cygwin():
diff --git a/test cases/rust/11 generated main/gen.py b/test cases/rust/11 generated main/gen.py
new file mode 100644
index 0000000..ebbc2a7
--- /dev/null
+++ b/test cases/rust/11 generated main/gen.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python3
+
+import argparse
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument('out')
+ args = parser.parse_args()
+
+ with open(args.out, 'w') as f:
+ f.write('fn main() { println!("I prefer tarnish, actually.") }')
+
+
+if __name__ == "__main__":
+ main()
diff --git a/test cases/rust/11 generated main/meson.build b/test cases/rust/11 generated main/meson.build
new file mode 100644
index 0000000..4749816
--- /dev/null
+++ b/test cases/rust/11 generated main/meson.build
@@ -0,0 +1,16 @@
+project('generated rust main', 'rust')
+
+gen = find_program('gen.py')
+
+c = custom_target(
+ 'custom_target',
+ command : [gen, '@OUTPUT@'],
+ output : ['main.rs'],
+)
+
+executable('custom_target_main', c)
+executable('custom_target_index_main', c[0])
+
+gen = generator(gen, arguments : ['@OUTPUT@'], output : '@BASENAME@.rs')
+# Doesn't actually use gen.py as input, just a limitation of generators
+executable('generator_main', gen.process(['gen.py']))
diff --git a/test cases/unit/89 pkgconfig build rpath order/dummy.pc b/test cases/unit/89 pkgconfig build rpath order/dummy.pc
new file mode 100644
index 0000000..9e3048b
--- /dev/null
+++ b/test cases/unit/89 pkgconfig build rpath order/dummy.pc
@@ -0,0 +1,7 @@
+prefix=/foo
+libdir=${prefix}/dummy
+
+Name: dummy
+Description: Nonexisting lib but add an rpath
+Version: 1.0.0
+Libs: -Wl,-rpath,${libdir}
diff --git a/test cases/unit/89 pkgconfig build rpath order/meson.build b/test cases/unit/89 pkgconfig build rpath order/meson.build
new file mode 100644
index 0000000..76ed8de
--- /dev/null
+++ b/test cases/unit/89 pkgconfig build rpath order/meson.build
@@ -0,0 +1,20 @@
+project('build rpath', 'c', 'cpp')
+
+subdir('sub')
+pkgconf_dep = dependency('dummy')
+
+executable('prog', 'prog.c',
+ dependencies : pkgconf_dep,
+ link_with : l,
+ build_rpath : '/foo/bar',
+ install_rpath : '/baz',
+ install : true,
+ )
+
+executable('progcxx', 'prog.cc',
+ dependencies : pkgconf_dep,
+ link_with : l,
+ build_rpath : '/foo/bar',
+ install_rpath : 'baz',
+ install : true,
+ )
diff --git a/test cases/unit/89 pkgconfig build rpath order/prog.c b/test cases/unit/89 pkgconfig build rpath order/prog.c
new file mode 100644
index 0000000..45b2fa3
--- /dev/null
+++ b/test cases/unit/89 pkgconfig build rpath order/prog.c
@@ -0,0 +1,5 @@
+int get_stuff();
+
+int main(int argc, char **argv) {
+ return get_stuff();
+}
diff --git a/test cases/unit/89 pkgconfig build rpath order/prog.cc b/test cases/unit/89 pkgconfig build rpath order/prog.cc
new file mode 100644
index 0000000..c7c2123
--- /dev/null
+++ b/test cases/unit/89 pkgconfig build rpath order/prog.cc
@@ -0,0 +1,8 @@
+#include <string>
+#include <iostream>
+
+int main(int argc, char **argv) {
+ std::string* s = new std::string("Hello");
+ delete s;
+ return 0;
+}
diff --git a/test cases/unit/89 pkgconfig build rpath order/sub/meson.build b/test cases/unit/89 pkgconfig build rpath order/sub/meson.build
new file mode 100644
index 0000000..6879ec6
--- /dev/null
+++ b/test cases/unit/89 pkgconfig build rpath order/sub/meson.build
@@ -0,0 +1 @@
+l = shared_library('stuff', 'stuff.c')
diff --git a/test cases/unit/89 pkgconfig build rpath order/sub/stuff.c b/test cases/unit/89 pkgconfig build rpath order/sub/stuff.c
new file mode 100644
index 0000000..d56d8b0
--- /dev/null
+++ b/test cases/unit/89 pkgconfig build rpath order/sub/stuff.c
@@ -0,0 +1,3 @@
+int get_stuff() {
+ return 0;
+}