diff options
34 files changed, 459 insertions, 97 deletions
diff --git a/docs/markdown/Wrap-dependency-system-manual.md b/docs/markdown/Wrap-dependency-system-manual.md index ff092e8..eb5de1b 100644 --- a/docs/markdown/Wrap-dependency-system-manual.md +++ b/docs/markdown/Wrap-dependency-system-manual.md @@ -189,6 +189,9 @@ endif `dependency('foo-1.0', required: get_option('foo_opt'))` will only fallback when the user sets `foo_opt` to `enabled` instead of `auto`. +*Since 0.58.0* optional dependency like above will fallback to the subproject +defined in the wrap file in the case `wrap_mode` is set to `forcefallback` +or `force_fallback_for` contains the subproject. If it is desired to fallback for an optional dependency, the `fallback` or `allow_fallback` keyword arguments must be passed diff --git a/docs/markdown/snippets/forcefallback.md b/docs/markdown/snippets/forcefallback.md new file mode 100644 index 0000000..7af5d39 --- /dev/null +++ b/docs/markdown/snippets/forcefallback.md @@ -0,0 +1,21 @@ +## Use fallback from wrap file when force fallback + +Optional dependency like below will now fallback to the subproject +defined in the wrap file in the case `wrap_mode` is set to `forcefallback` +or `force_fallback_for` contains the subproject. + +```meson +# required is false because we could fallback to cc.find_library(), but in the +# forcefallback case this now configure the subproject. +dep = dependency('foo-1.0', required: false) +if not dep.found() + dep = cc.find_library('foo', has_headers: 'foo.h') +endif +``` + +```ini +[wrap-file] +... +[provide] +dependency_names = foo-1.0 +``` diff --git a/docs/markdown/snippets/subprojects_purge.md b/docs/markdown/snippets/subprojects_purge.md new file mode 100644 index 0000000..86e1064 --- /dev/null +++ b/docs/markdown/snippets/subprojects_purge.md @@ -0,0 +1,18 @@ +## Purge subprojects folder + +It is now possible to purge a subprojects folder of artifacts created +from wrap-based subprojects including anything in `packagecache`. This is useful +when you want to return to a completely clean source tree or busting caches with +stale patch directories or caches. By default the command will only print out +what it is removing. You need to pass `--confirm` to the command for actual +artifacts to be purged. + +By default all wrap-based subprojects will be purged. + +- `meson subprojects purge` prints non-cache wrap artifacts which will be +purged. +- `meson subprojects purge --confirm` purges non-cache wrap artifacts. +- `meson subprojects purge --confirm --include-cache` also removes the cache +artifacts. +- `meson subprojects purge --confirm subproj1 subproj2` removes non-cache wrap +artifacts associated with the listed subprojects. diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 04f3d23..ee5f446 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -417,6 +417,12 @@ class Backend: raise MesonException('Unknown data type in object list.') return obj_list + def is_swift_target(self, target): + for s in target.sources: + if s.endswith('swift'): + return True + return False + def get_executable_serialisation(self, cmd, workdir=None, extra_bdeps=None, capture=None, env: T.Optional[build.EnvironmentVariables] = None): @@ -1169,7 +1175,7 @@ class Backend: def get_normpath_target(self, source) -> str: return os.path.normpath(source) - def get_custom_target_dir_include_args(self, target, compiler, *, absolute_path=False): + def get_custom_target_dirs(self, target, compiler, *, absolute_path=False): custom_target_include_dirs = [] for i in target.get_generated_sources(): # Generator output goes into the target private dir which is @@ -1184,11 +1190,15 @@ class Backend: idir = os.path.join(self.environment.get_build_dir(), idir) if idir not in custom_target_include_dirs: custom_target_include_dirs.append(idir) + return custom_target_include_dirs + + def get_custom_target_dir_include_args(self, target, compiler, *, absolute_path=False): incs = [] - for i in custom_target_include_dirs: + for i in self.get_custom_target_dirs(target, compiler, absolute_path=absolute_path): incs += compiler.get_include_args(i, False) return incs + def eval_custom_target_command(self, target, absolute_outputs=False): # We want the outputs to be absolute only when using the VS backend # XXX: Maybe allow the vs backend to use relative paths too? @@ -1513,6 +1523,8 @@ class Backend: source_list += [j.absolute_path(self.source_dir, self.build_dir)] elif isinstance(j, str): source_list += [os.path.join(self.source_dir, j)] + elif isinstance(j, (build.CustomTarget, build.BuildTarget)): + source_list += [os.path.join(self.build_dir, j.get_subdir(), o) for o in j.get_outputs()] source_list = list(map(lambda x: os.path.normpath(x), source_list)) compiler = [] diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index e8a7d4b..fa07235 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1701,12 +1701,6 @@ int dummy; def target_swift_modulename(self, target): return target.name - def is_swift_target(self, target): - for s in target.sources: - if s.endswith('swift'): - return True - return False - def determine_swift_dep_modules(self, target): result = [] for l in target.link_targets: diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 2a72b19..aeaee5c 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -37,6 +37,7 @@ XCODETYPEMAP = {'c': 'sourcecode.c.c', 'hxx': 'sourcecode.cpp.h', 'hh': 'sourcecode.cpp.hh', 'inc': 'sourcecode.c.h', + 'swift': 'sourcecode.swift', 'dylib': 'compiled.mach-o.dylib', 'o': 'compiled.mach-o.objfile', 's': 'sourcecode.asm', @@ -448,9 +449,18 @@ class XCodeBackend(backends.Backend): self.target_dependency_map = {} for tname, t in self.build_targets.items(): for target in t.link_targets: - k = (tname, target.get_basename()) - assert(k not in self.target_dependency_map) + if isinstance(target, build.CustomTargetIndex): + k = (tname, target.target.get_basename()) + if k in self.target_dependency_map: + continue + else: + k = (tname, target.get_basename()) + assert(k not in self.target_dependency_map) self.target_dependency_map[k] = self.gen_id() + for tname, t in self.custom_targets.items(): + k = tname + assert(k not in self.target_dependency_map) + self.target_dependency_map[k] = self.gen_id() def generate_pbxdep_map(self): self.pbx_dep_map = {} @@ -777,7 +787,10 @@ class XCodeBackend(backends.Backend): path = '"%s"' % t.get_filename() target_dict.add_item('isa', 'PBXFileReference') target_dict.add_item('explicitFileType', '"' + typestr + '"') - target_dict.add_item('path', path) + if ' ' in path and path[0] != '"': + target_dict.add_item('path', f'"{path}"') + else: + target_dict.add_item('path', path) target_dict.add_item('refType', reftype) target_dict.add_item('sourceTree', 'BUILT_PRODUCTS_DIR') @@ -796,8 +809,8 @@ class XCodeBackend(backends.Backend): typestr = self.get_xcodetype(s) custom_dict.add_item('isa', 'PBXFileReference') custom_dict.add_item('explicitFileType', '"' + typestr + '"') - custom_dict.add_item('name', s) - custom_dict.add_item('path', s) + custom_dict.add_item('name', f'"{s}"') + custom_dict.add_item('path', f'"{s}"') custom_dict.add_item('refType', 0) custom_dict.add_item('sourceTree', 'SOURCE_ROOT') objects_dict.add_item(self.fileref_ids[(tname, s)], custom_dict) @@ -993,8 +1006,13 @@ class XCodeBackend(backends.Backend): for lt in self.build_targets[tname].link_targets: # NOT DOCUMENTED, may need to make different links # to same target have different targetdependency item. - idval = self.pbx_dep_map[lt.get_id()] - dep_array.add_item(idval, 'PBXTargetDependency') + if isinstance(lt, build.CustomTarget): + dep_array.add_item(self.pbx_custom_dep_map[lt.get_id()], lt.name) + elif isinstance(lt, build.CustomTargetIndex): + dep_array.add_item(self.pbx_custom_dep_map[lt.target.get_id()], lt.target.name) + else: + idval = self.pbx_dep_map[lt.get_id()] + dep_array.add_item(idval, 'PBXTargetDependency') for o in t.objects: if isinstance(o, build.ExtractedObjects): source_target_id = o.target.get_id() @@ -1004,8 +1022,8 @@ class XCodeBackend(backends.Backend): for o in t.generated: if isinstance(o, build.CustomTarget): dep_array.add_item(self.pbx_custom_dep_map[o.get_id()], o.name) - if not isinstance(o, build.GeneratedList): - continue + elif isinstance(o, build.CustomTargetIndex): + dep_array.add_item(self.pbx_custom_dep_map[o.target.get_id()], o.target.name) generator_id += 1 @@ -1111,7 +1129,10 @@ class XCodeBackend(backends.Backend): custom_dict.add_item('runOnlyForDeploymentPostprocessing', 0) custom_dict.add_item('shellPath', '/bin/sh') workdir = self.environment.get_build_dir() - cmdstr = ' '.join([f'\\"{x}\\"' for x in fixed_cmd]) + quoted_cmd = [] + for c in fixed_cmd: + quoted_cmd.append(c.replace('"', chr(92) + '"')) + cmdstr = ' '.join([f"\\'{x}\\'" for x in quoted_cmd]) custom_dict.add_item('shellScript', f'"cd {workdir}; {cmdstr}"') custom_dict.add_item('showEnvVarsInLog', 0) @@ -1159,7 +1180,12 @@ class XCodeBackend(backends.Backend): base_args = generator.get_arglist(infilename) for o_base in genlist.get_outputs_for(i): o = os.path.join(self.get_target_private_dir(t), o_base) - args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', o).replace('@BUILD_DIR@', self.get_target_private_dir(t)) for x in base_args] + args = [] + for arg in base_args: + arg = arg.replace("@INPUT@", infilename) + arg = arg.replace('@OUTPUT@', o).replace('@BUILD_DIR@', self.get_target_private_dir(t)) + arg = arg.replace("@CURRENT_SOURCE_DIR@", os.path.join(self.build_to_src, t.subdir)) + args.append(arg) args = self.replace_outputs(args, self.get_target_private_dir(t), outfilelist) args = self.replace_extra_args(args, genlist) if generator.capture: @@ -1204,11 +1230,17 @@ class XCodeBackend(backends.Backend): for o in ofilenames: file_arr.add_item(self.custom_target_output_buildfile[o], os.path.join(self.environment.get_build_dir(), o)) + elif isinstance(gt, build.CustomTargetIndex): + for o in gt.get_outputs(): + file_arr.add_item(self.custom_target_output_buildfile[o], + os.path.join(self.environment.get_build_dir(), o)) elif isinstance(gt, build.GeneratedList): genfiles = self.generator_buildfile_ids[(name, generator_id)] generator_id += 1 for o in genfiles: file_arr.add_item(o) + else: + raise RuntimeError('Unknown input type: ' + str(gt)) phase_dict.add_item('runOnlyForDeploymentPostprocessing', 0) def generate_pbx_target_dependency(self, objects_dict): @@ -1246,6 +1278,7 @@ class XCodeBackend(backends.Backend): bt_dict.add_item('buildSettings', settings_dict) settings_dict.add_item('ARCHS', '"$(NATIVE_ARCH_ACTUAL)"') settings_dict.add_item('ONLY_ACTIVE_ARCH', 'YES') + settings_dict.add_item('SWIFT_VERSION', '4.0') settings_dict.add_item('SDKROOT', '"macosx"') settings_dict.add_item('SYMROOT', '"%s/build"' % self.environment.get_build_dir()) bt_dict.add_item('name', f'"{buildtype}"') @@ -1298,8 +1331,18 @@ class XCodeBackend(backends.Backend): links_dylib = False dep_libs = [] for l in target.link_targets: - abs_path = os.path.join(self.environment.get_build_dir(), - l.subdir, buildtype, l.get_filename()) + if isinstance(target, build.SharedModule) and isinstance(l, build.Executable): + continue + if isinstance(l, build.CustomTargetIndex): + rel_dir = self.get_custom_target_output_dir(l.target) + libname = l.get_filename() + elif isinstance(l, build.CustomTarget): + rel_dir = self.get_custom_target_output_dir(l) + libname = l.get_filename() + else: + rel_dir = self.get_target_dir(l) + libname = l.get_filename() + abs_path = os.path.join(self.environment.get_build_dir(), rel_dir, libname) dep_libs.append("'%s'" % abs_path) if isinstance(l, build.SharedLibrary): links_dylib = True @@ -1341,9 +1384,14 @@ class XCodeBackend(backends.Backend): else: product_name = target.get_basename() ldargs += target.link_args - linker, stdlib_args = self.determine_linker_and_stdlib_args(target) - ldargs += self.build.get_project_link_args(linker, target.subproject, target.for_machine) + # Swift is special. Again. You can't mix Swift with other languages + # in the same target. Thus for Swift we only use + if self.is_swift_target(target): + linker, stdlib_args = target.compilers['swift'], [] + else: + linker, stdlib_args = self.determine_linker_and_stdlib_args(target) if not isinstance(target, build.StaticLibrary): + ldargs += self.build.get_project_link_args(linker, target.subproject, target.for_machine) ldargs += self.build.get_global_link_args(linker, target.for_machine) cargs = [] for dep in target.get_external_deps(): @@ -1367,10 +1415,17 @@ class XCodeBackend(backends.Backend): if o_abs.endswith('.o') or o_abs.endswith('.obj'): ldargs += [r'\"' + o_abs + r'\"'] else: - (srcs, ofilenames, cmd) = self.eval_custom_target_command(o) - for ofname in ofilenames: - if os.path.splitext(ofname)[-1] in LINKABLE_EXTENSIONS: - ldargs += [r'\"' + os.path.join(self.environment.get_build_dir(), ofname) + r'\"'] + if isinstance(o, build.CustomTarget): + (srcs, ofilenames, cmd) = self.eval_custom_target_command(o) + for ofname in ofilenames: + if os.path.splitext(ofname)[-1] in LINKABLE_EXTENSIONS: + ldargs += [r'\"' + os.path.join(self.environment.get_build_dir(), ofname) + r'\"'] + elif isinstance(o, build.CustomTargetIndex): + for ofname in o.get_outputs(): + if os.path.splitext(ofname)[-1] in LINKABLE_EXTENSIONS: + ldargs += [r'\"' + os.path.join(self.environment.get_build_dir(), ofname) + r'\"'] + else: + raise RuntimeError(o) if isinstance(target, build.SharedModule): options = self.environment.coredata.options ldargs += linker.get_std_shared_module_link_args(options) @@ -1397,16 +1452,23 @@ class XCodeBackend(backends.Backend): targs = target.get_extra_args(lang) args = warn_args + std_args + pargs + gargs + targs if args: - langname = LANGNAMEMAP[lang] lang_cargs = cargs if compiler and target.implicit_include_directories: # It is unclear what is the cwd when xcode runs. -I. does not seem to # add the root build dir to the search path. So add an absolute path instead. # This may break reproducible builds, in which case patches are welcome. - lang_cargs += self.get_build_dir_include_args(target, compiler, absolute_path=True) - lang_cargs += self.get_source_dir_include_args(target, compiler, absolute_path=True) lang_cargs += self.get_custom_target_dir_include_args(target, compiler, absolute_path=True) - langargs[langname] = args + # Xcode can not handle separate compilation flags for C and ObjectiveC. They are both + # put in OTHER_CFLAGS. Same with C++ and ObjectiveC++. + if lang == 'objc': + lang = 'c' + elif lang == 'objcpp': + lang = 'cpp' + langname = LANGNAMEMAP[lang] + if langname in langargs: + langargs[langname] += args + else: + langargs[langname] = args langargs[langname] += lang_cargs symroot = os.path.join(self.environment.get_build_dir(), target.subdir) bt_dict = PbxDict() @@ -1420,7 +1482,7 @@ class XCodeBackend(backends.Backend): settings_dict.add_item('DYLIB_COMPATIBILITY_VERSION', '""') else: if dylib_version is not None: - settings_dict.add_item('DYLIB_CURRENT_VERSION', f'"{dylib_version}') + settings_dict.add_item('DYLIB_CURRENT_VERSION', f'"{dylib_version}"') if target.prefix: settings_dict.add_item('EXECUTABLE_PREFIX', target.prefix) if target.suffix: @@ -1444,12 +1506,19 @@ class XCodeBackend(backends.Backend): settings_dict.add_item('GCC_PREFIX_HEADER', f'"$(PROJECT_DIR)/{relative_pch_path}"') settings_dict.add_item('GCC_PREPROCESSOR_DEFINITIONS', '""') settings_dict.add_item('GCC_SYMBOLS_PRIVATE_EXTERN', 'NO') + header_arr = PbxArray() + unquoted_headers = [] + unquoted_headers.append(self.get_target_private_dir_abs(target)) + if target.implicit_include_directories: + unquoted_headers.append(os.path.join(self.environment.get_build_dir(), target.get_subdir())) + unquoted_headers.append(os.path.join(self.environment.get_source_dir(), target.get_subdir())) if headerdirs: - header_arr = PbxArray() for i in headerdirs: i = os.path.normpath(i) - header_arr.add_item(f'"\\"{i}\\""') - settings_dict.add_item('HEADER_SEARCH_PATHS', header_arr) + unquoted_headers.append(i) + for i in unquoted_headers: + header_arr.add_item(f'"\\"{i}\\""') + settings_dict.add_item('HEADER_SEARCH_PATHS', header_arr) settings_dict.add_item('INSTALL_PATH', f'"{install_path}"') settings_dict.add_item('LIBRARY_SEARCH_PATHS', '""') if isinstance(target, build.SharedModule): @@ -1460,7 +1529,10 @@ class XCodeBackend(backends.Backend): self.add_otherargs(settings_dict, langargs) settings_dict.add_item('OTHER_LDFLAGS', f'"{ldstr}"') settings_dict.add_item('OTHER_REZFLAGS', '""') - settings_dict.add_item('PRODUCT_NAME', product_name) + if ' ' in product_name: + settings_dict.add_item('PRODUCT_NAME', f'"{product_name}"') + else: + settings_dict.add_item('PRODUCT_NAME', product_name) settings_dict.add_item('SECTORDER_FLAGS', '""') settings_dict.add_item('SYMROOT', f'"{symroot}"') sysheader_arr = PbxArray() @@ -1484,7 +1556,7 @@ class XCodeBackend(backends.Backend): # b) I don't know why it works or why every backslash must be escaped into eight backslashes a = a.replace(chr(92), 8*chr(92)) # chr(92) is backslash, this how we smuggle it in without Python's quoting grabbing it. a = a.replace(r'"', r'\\\"') - if ' ' in a: + if ' ' in a or "'" in a: a = r'\"' + a + r'\"' quoted_args.append(a) settings_dict.add_item(f'OTHER_{langname}FLAGS', '"' + ' '.join(quoted_args) + '"') diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 64f65b2..d7bacc1 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -401,6 +401,11 @@ class CoreData: self.cross_files = self.__load_config_files(options, scratch_dir, 'cross') self.compilers = PerMachine(OrderedDict(), OrderedDict()) # type: PerMachine[T.Dict[str, Compiler]] + # Set of subprojects that have already been initialized once, this is + # required to be stored and reloaded with the coredata, as we don't + # want to overwrite options for such subprojects. + self.initialized_subprojects: T.Set[str] = set() + build_cache = DependencyCache(self.options, MachineChoice.BUILD) host_cache = DependencyCache(self.options, MachineChoice.HOST) self.deps = PerMachine(build_cache, host_cache) # type: PerMachine[DependencyCache] diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 1010494..270e891 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -692,6 +692,7 @@ external dependencies (including libraries) must go to "dependencies".''') sub = SubprojectHolder(None, os.path.join(self.subproject_dir, subp_name), disabled_feature=disabled_feature, exception=exception) self.subprojects[subp_name] = sub + self.coredata.initialized_subprojects.add(subp_name) return sub def get_subproject(self, subp_name): @@ -807,6 +808,7 @@ external dependencies (including libraries) must go to "dependencies".''') self.build_def_files = list(set(self.build_def_files + subi.build_def_files)) self.build.merge(subi.build) self.build.subprojects[subp_name] = subi.project_version + self.coredata.initialized_subprojects.add(subp_name) self.summary.update(subi.summary) return self.subprojects[subp_name] @@ -975,7 +977,7 @@ external dependencies (including libraries) must go to "dependencies".''') # If this is the first invocation we alway sneed to initialize # builtins, if this is a subproject that is new in a re-invocation we # need to initialize builtins for that - if self.environment.first_invocation or (self.subproject != '' and self.subproject not in self.subprojects): + if self.environment.first_invocation or (self.subproject != '' and self.subproject not in self.coredata.initialized_subprojects): default_options = self.project_default_options.copy() default_options.update(self.default_project_options) self.coredata.init_builtins(self.subproject) @@ -1598,6 +1600,11 @@ external dependencies (including libraries) must go to "dependencies".''') if not isinstance(allow_fallback, bool): raise InvalidArguments('"allow_fallback" argument must be boolean') + wrap_mode = self.coredata.get_option(OptionKey('wrap_mode')) + force_fallback_for = self.coredata.get_option(OptionKey('force_fallback_for')) + force_fallback |= (wrap_mode == WrapMode.forcefallback or + name in force_fallback_for) + # If "fallback" is absent, look for an implicit fallback. if name and fallback is None and allow_fallback is not False: # Add an implicit fallback if we have a wrap file or a directory with the same name, @@ -1609,7 +1616,8 @@ external dependencies (including libraries) must go to "dependencies".''') if not provider and allow_fallback is True: raise InvalidArguments('Fallback wrap or subproject not found for dependency \'%s\'' % name) subp_name = mesonlib.listify(provider)[0] - if provider and (allow_fallback is True or required or self.get_subproject(subp_name)): + force_fallback |= subp_name in force_fallback_for + if provider and (allow_fallback is True or required or self.get_subproject(subp_name) or force_fallback): fallback = provider if 'default_options' in kwargs and not fallback: @@ -1640,13 +1648,7 @@ external dependencies (including libraries) must go to "dependencies".''') subp_name, varname = self.get_subproject_infos(fallback) if self.get_subproject(subp_name): return self.get_subproject_dep(name, display_name, subp_name, varname, kwargs) - - wrap_mode = self.coredata.get_option(OptionKey('wrap_mode')) - force_fallback_for = self.coredata.get_option(OptionKey('force_fallback_for')) - force_fallback = (force_fallback or - wrap_mode == WrapMode.forcefallback or - name in force_fallback_for or - subp_name in force_fallback_for) + force_fallback |= subp_name in force_fallback_for if name != '' and (not fallback or not force_fallback): self._handle_featurenew_dependencies(name) @@ -2452,7 +2454,7 @@ subproject. This is a problem as it hardcodes the relative paths of these two pr This makes it impossible to compile the project in any other directory layout and also prevents the subproject from changing its own directory layout. -Instead of poking directly at the internals the subproject should be executed and +Instead of poking directly at the internals the subproject should be executed and it should set a variable that the caller can then use. Something like: # In subproject @@ -2462,7 +2464,7 @@ some_dep = declare_depencency(include_directories: include_directories('include' some_dep = depencency('some') executable(..., dependencies: [some_dep]) -This warning will become a hard error in a future Meson release. +This warning will become a hard error in a future Meson release. ''') absdir_src = os.path.join(absbase_src, a) absdir_build = os.path.join(absbase_build, a) @@ -2732,7 +2734,18 @@ Try setting b_lundef to false instead.'''.format(self.coredata.options[OptionKey elif key in self.environment.coredata.options: pic = self.environment.coredata.options[key].value - if pic: + if self.backend.name == 'xcode': + # Xcode is a bit special in that you can't (at least for the moment) + # form a library only from object file inputs. The simple but inefficient + # solution is to use the sources directly. This will lead to them being + # built twice. This is unfortunate and slow, but at least it works. + # Feel free to submit patches to get this fixed if it is an + # issue for you. + reuse_object_files = False + else: + reuse_object_files = pic + + if reuse_object_files: # Exclude sources from args and kwargs to avoid building them twice static_args = [args[0]] static_kwargs = kwargs.copy() diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py index 36bad71..22c5b44 100644 --- a/mesonbuild/mdist.py +++ b/mesonbuild/mdist.py @@ -29,6 +29,7 @@ from mesonbuild import mlog, build from .scripts.meson_exe import run_exe archive_choices = ['gztar', 'xztar', 'zip'] + archive_extension = {'gztar': '.tar.gz', 'xztar': '.tar.xz', 'zip': '.zip'} @@ -36,8 +37,8 @@ archive_extension = {'gztar': '.tar.gz', def add_arguments(parser): parser.add_argument('-C', default='.', dest='wd', help='directory to cd into before running') - parser.add_argument('--formats', default='xztar', choices=archive_choices, - help='Comma separated list of archive types to create.') + parser.add_argument('--formats', default='xztar', + help='Comma separated list of archive types to create. Supports xztar (default), gztar, and zip.') parser.add_argument('--include-subprojects', action='store_true', help='Include source code of subprojects that have been used for the build.') parser.add_argument('--no-tests', action='store_true', diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py index d038fa7..b50c986 100755 --- a/mesonbuild/msubprojects.py +++ b/mesonbuild/msubprojects.py @@ -4,7 +4,7 @@ from pathlib import Path from . import mlog from .mesonlib import quiet_git, verbose_git, GitException, Popen_safe, MesonException, windows_proof_rmtree -from .wrap.wrap import API_ROOT, Resolver, WrapException, ALL_TYPES +from .wrap.wrap import API_ROOT, PackageDefinition, Resolver, WrapException, ALL_TYPES from .wrap import wraptool ALL_TYPES_STRING = ', '.join(ALL_TYPES) @@ -312,6 +312,63 @@ def foreach(r, wrap, repo_dir, options): mlog.log(out, end='') return True +def purge(r: Resolver, wrap: PackageDefinition, repo_dir: str, options: argparse.Namespace) -> bool: + # if subproject is not wrap-based, then don't remove it + if not wrap.type: + return True + + if wrap.type == 'redirect': + redirect_file = Path(wrap.filename).resolve() + if options.confirm: + redirect_file.unlink() + mlog.log(f'Deleting {redirect_file}') + + if options.include_cache: + packagecache = Path(r.cachedir).resolve() + try: + subproject_cache_file = packagecache / wrap.get("source_filename") + if subproject_cache_file.is_file(): + if options.confirm: + subproject_cache_file.unlink() + mlog.log(f'Deleting {subproject_cache_file}') + except WrapException: + pass + + try: + subproject_patch_file = packagecache / wrap.get("patch_filename") + if subproject_patch_file.is_file(): + if options.confirm: + subproject_patch_file.unlink() + mlog.log(f'Deleting {subproject_patch_file}') + except WrapException: + pass + + # Don't log that we will remove an empty directory + if packagecache.exists() and not any(packagecache.iterdir()): + packagecache.rmdir() + + subproject_source_dir = Path(repo_dir).resolve() + + # Don't follow symlink. This is covered by the next if statement, but why + # not be doubly sure. + if subproject_source_dir.is_symlink(): + if options.confirm: + subproject_source_dir.unlink() + mlog.log(f'Deleting {subproject_source_dir}') + return True + if not subproject_source_dir.is_dir(): + return True + + try: + if options.confirm: + windows_proof_rmtree(str(subproject_source_dir)) + mlog.log(f'Deleting {subproject_source_dir}') + except OSError as e: + mlog.error(f'Unable to remove: {subproject_source_dir}: {e}') + return False + + return True + def add_common_arguments(p): p.add_argument('--sourcedir', default='.', help='Path to source directory') @@ -361,6 +418,13 @@ def add_arguments(parser): p.set_defaults(subprojects=[]) p.set_defaults(subprojects_func=foreach) + p = subparsers.add_parser('purge', help='Remove all wrap-based subproject artifacts') + add_common_arguments(p) + add_subprojects_argument(p) + p.add_argument('--include-cache', action='store_true', default=False, help='Remove the package cache as well') + p.add_argument('--confirm', action='store_true', default=False, help='Confirm the removal of subproject artifacts') + p.set_defaults(subprojects_func=purge) + def run(options): src_dir = os.path.relpath(os.path.realpath(options.sourcedir)) if not os.path.isfile(os.path.join(src_dir, 'meson.build')): diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index f8e19c9..5fe8b33 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -415,7 +415,7 @@ class Resolver: verbose_git(['remote', 'add', 'origin', self.wrap.get('url')], self.dirname, check=True) revno = self.wrap.get('revision') verbose_git(['fetch', *depth_option, 'origin', revno], self.dirname, check=True) - verbose_git(['checkout', revno], self.dirname, check=True) + verbose_git(['checkout', revno, '--'], self.dirname, check=True) if self.wrap.values.get('clone-recursive', '').lower() == 'true': verbose_git(['submodule', 'update', '--init', '--checkout', '--recursive', *depth_option], self.dirname, check=True) @@ -426,9 +426,9 @@ class Resolver: if not is_shallow: verbose_git(['clone', self.wrap.get('url'), self.directory], self.subdir_root, check=True) if revno.lower() != 'head': - if not verbose_git(['checkout', revno], self.dirname): + if not verbose_git(['checkout', revno, '--'], self.dirname): verbose_git(['fetch', self.wrap.get('url'), revno], self.dirname, check=True) - verbose_git(['checkout', revno], self.dirname, check=True) + verbose_git(['checkout', revno, '--'], self.dirname, check=True) else: verbose_git(['clone', *depth_option, '--branch', revno, self.wrap.get('url'), self.directory], self.subdir_root, check=True) diff --git a/run_tests.py b/run_tests.py index 4d737ee..b2a25f0 100755 --- a/run_tests.py +++ b/run_tests.py @@ -225,9 +225,7 @@ def get_backend_commands(backend: Backend, debug: bool = False) -> \ test_cmd = cmd + ['RUN_TESTS.vcxproj'] elif backend is Backend.xcode: cmd = ['xcodebuild'] - # In Xcode9 new build system's clean command fails when using a custom build directory. - # Maybe use it when CI uses Xcode10 we can remove '-UseNewBuildSystem=FALSE' - clean_cmd = cmd + ['-alltargets', 'clean', '-UseNewBuildSystem=FALSE'] + clean_cmd = cmd + ['-alltargets', 'clean'] test_cmd = cmd + ['-target', 'RUN_TESTS'] elif backend is Backend.ninja: global NINJA_CMD diff --git a/run_unittests.py b/run_unittests.py index b6e349d..3faa20c 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -2513,6 +2513,14 @@ class AllPlatformTests(BasePlatformTests): self.build() self.run_tests() + def test_implicit_forcefallback(self): + testdir = os.path.join(self.unit_test_dir, '95 implicit force fallback') + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testdir) + self.init(testdir, extra_args=['--wrap-mode=forcefallback']) + self.new_builddir() + self.init(testdir, extra_args=['--force-fallback-for=something']) + def test_nopromote(self): testdir = os.path.join(self.common_test_dir, '99 subproject subdir') with self.assertRaises(subprocess.CalledProcessError) as cm: @@ -3222,6 +3230,8 @@ class AllPlatformTests(BasePlatformTests): ''')) xz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.xz') xz_checksumfile = xz_distfile + '.sha256sum' + gz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.gz') + gz_checksumfile = gz_distfile + '.sha256sum' zip_distfile = os.path.join(self.distdir, 'disttest-1.4.3.zip') zip_checksumfile = zip_distfile + '.sha256sum' vcs_init(project_dir) @@ -3235,12 +3245,32 @@ class AllPlatformTests(BasePlatformTests): self.build('dist') self.assertPathExists(xz_distfile) self.assertPathExists(xz_checksumfile) + self.assertPathDoesNotExist(gz_distfile) + self.assertPathDoesNotExist(gz_checksumfile) self.assertPathDoesNotExist(zip_distfile) self.assertPathDoesNotExist(zip_checksumfile) + self._run(self.meson_command + ['dist', '--formats', 'gztar'], + workdir=self.builddir) + self.assertPathExists(gz_distfile) + self.assertPathExists(gz_checksumfile) self._run(self.meson_command + ['dist', '--formats', 'zip'], workdir=self.builddir) self.assertPathExists(zip_distfile) self.assertPathExists(zip_checksumfile) + os.remove(xz_distfile) + os.remove(xz_checksumfile) + os.remove(gz_distfile) + os.remove(gz_checksumfile) + os.remove(zip_distfile) + os.remove(zip_checksumfile) + self._run(self.meson_command + ['dist', '--formats', 'xztar,gztar,zip'], + workdir=self.builddir) + self.assertPathExists(xz_distfile) + self.assertPathExists(xz_checksumfile) + self.assertPathExists(gz_distfile) + self.assertPathExists(gz_checksumfile) + self.assertPathExists(zip_distfile) + self.assertPathExists(zip_checksumfile) if include_subprojects: # Verify that without --include-subprojects we have files from @@ -4313,7 +4343,7 @@ class AllPlatformTests(BasePlatformTests): def test_reconfigure(self): testdir = os.path.join(self.unit_test_dir, '48 reconfigure') - self.init(testdir, extra_args=['-Dopt1=val1']) + self.init(testdir, extra_args=['-Dopt1=val1', '-Dsub1:werror=true']) self.setconf('-Dopt2=val2') self.__reconfigure() @@ -4324,6 +4354,7 @@ class AllPlatformTests(BasePlatformTests): self.assertRegex(out, 'opt2 val2') self.assertRegex(out, 'opt3 val3') self.assertRegex(out, 'opt4 default4') + self.assertRegex(out, 'sub1:werror True') self.build() self.run_tests() @@ -4337,6 +4368,7 @@ class AllPlatformTests(BasePlatformTests): self.assertRegex(out, 'opt2 val2') self.assertRegex(out, 'opt3 val3') self.assertRegex(out, 'opt4 val4') + self.assertRegex(out, 'sub1:werror True') self.assertTrue(Path(self.builddir, '.gitignore').exists()) self.build() self.run_tests() @@ -4668,10 +4700,12 @@ class AllPlatformTests(BasePlatformTests): # Match target ids to input and output files for ease of reference src_to_id = {} out_to_id = {} + name_to_out = {} for i in res['targets']: print(json.dump(i, sys.stdout)) out_to_id.update({os.path.relpath(out, self.builddir): i['id'] for out in i['filename']}) + name_to_out.update({i['name']: i['filename']}) for group in i['target_sources']: src_to_id.update({os.path.relpath(src, testdir): i['id'] for src in group['sources']}) @@ -4680,7 +4714,7 @@ class AllPlatformTests(BasePlatformTests): tests_to_find = ['test case 1', 'test case 2', 'benchmark 1'] deps_to_find = {'test case 1': [src_to_id['t1.cpp']], 'test case 2': [src_to_id['t2.cpp'], src_to_id['t3.cpp']], - 'benchmark 1': [out_to_id['file2'], src_to_id['t3.cpp']]} + 'benchmark 1': [out_to_id['file2'], out_to_id['file3'], out_to_id['file4'], src_to_id['t3.cpp']]} for i in res['benchmarks'] + res['tests']: assertKeyTypes(test_keylist, i) if i['name'] in tests_to_find: @@ -4727,11 +4761,22 @@ class AllPlatformTests(BasePlatformTests): # Check targets targets_to_find = { - 'sharedTestLib': ('shared library', True, False, 'sharedlib/meson.build'), - 'staticTestLib': ('static library', True, False, 'staticlib/meson.build'), - 'test1': ('executable', True, True, 'meson.build'), - 'test2': ('executable', True, False, 'meson.build'), - 'test3': ('executable', True, False, 'meson.build'), + 'sharedTestLib': ('shared library', True, False, 'sharedlib/meson.build', + [os.path.join(testdir, 'sharedlib', 'shared.cpp')]), + 'staticTestLib': ('static library', True, False, 'staticlib/meson.build', + [os.path.join(testdir, 'staticlib', 'static.c')]), + 'custom target test 1': ('custom', False, False, 'meson.build', + [os.path.join(testdir, 'cp.py')]), + 'custom target test 2': ('custom', False, False, 'meson.build', + name_to_out['custom target test 1']), + 'test1': ('executable', True, True, 'meson.build', + [os.path.join(testdir, 't1.cpp')]), + 'test2': ('executable', True, False, 'meson.build', + [os.path.join(testdir, 't2.cpp')]), + 'test3': ('executable', True, False, 'meson.build', + [os.path.join(testdir, 't3.cpp')]), + 'custom target test 3': ('custom', False, False, 'meson.build', + name_to_out['test3']), } for i in res['targets']: assertKeyTypes(targets_typelist, i) @@ -4744,6 +4789,7 @@ class AllPlatformTests(BasePlatformTests): targets_to_find.pop(i['name'], None) for j in i['target_sources']: assertKeyTypes(targets_sources_typelist, j) + self.assertEqual(j['sources'], [os.path.normpath(f) for f in tgt[4]]) self.assertDictEqual(targets_to_find, {}) def test_introspect_file_dump_equals_all(self): @@ -9675,6 +9721,8 @@ class SubprojectsCommandTests(BasePlatformTests): self.subprojects_dir = self.project_dir / 'subprojects' os.makedirs(str(self.subprojects_dir)) + self.packagecache_dir = self.subprojects_dir / 'packagecache' + os.makedirs(str(self.packagecache_dir)) def _create_project(self, path, project_name='dummy'): os.makedirs(str(path), exist_ok=True) @@ -9752,10 +9800,12 @@ class SubprojectsCommandTests(BasePlatformTests): path = self.root_dir / tarball with open(str((self.subprojects_dir / name).with_suffix('.wrap')), 'w') as f: f.write(textwrap.dedent( - ''' + f''' [wrap-file] - source_url={} - '''.format(os.path.abspath(str(path))))) + source_url={os.path.abspath(str(path))} + source_filename={tarball} + ''')) + Path(self.packagecache_dir / tarball).touch() def _subprojects_cmd(self, args): return self._run(self.meson_command + ['subprojects'] + args, workdir=str(self.project_dir)) @@ -9864,6 +9914,30 @@ class SubprojectsCommandTests(BasePlatformTests): out = self._subprojects_cmd(['foreach', '--types', 'git'] + dummy_cmd) self.assertEqual(ran_in(out), ['subprojects/sub_git']) + def test_purge(self): + self._create_project(self.subprojects_dir / 'sub_file') + self._wrap_create_file('sub_file') + self._git_create_local_repo('sub_git') + self._wrap_create_git('sub_git') + + def deleting(s) -> T.List[str]: + ret = [] + prefix = 'Deleting ' + for l in s.splitlines(): + if l.startswith(prefix): + ret.append(l[len(prefix):]) + return sorted(ret) + + out = self._subprojects_cmd(['purge']) + self.assertEqual(deleting(out), [str(self.subprojects_dir / 'sub_file'), str(self.subprojects_dir / 'sub_git')]) + out = self._subprojects_cmd(['purge', '--include-cache']) + self.assertEqual(deleting(out), [str(self.subprojects_dir / 'packagecache' / 'dummy.tar.gz'), str(self.subprojects_dir / 'sub_file'), str(self.subprojects_dir / 'sub_git')]) + out = self._subprojects_cmd(['purge', '--include-cache', '--confirm']) + self.assertEqual(deleting(out), [str(self.subprojects_dir / 'packagecache' / 'dummy.tar.gz'), str(self.subprojects_dir / 'sub_file'), str(self.subprojects_dir / 'sub_git')]) + self.assertFalse(Path(self.subprojects_dir / 'packagecache' / 'dummy.tar.gz').exists()) + self.assertFalse(Path(self.subprojects_dir / 'sub_file').exists()) + self.assertFalse(Path(self.subprojects_dir / 'sub_git').exists()) + def _clang_at_least(compiler: 'Compiler', minver: str, apple_minver: T.Optional[str]) -> bool: """ check that Clang compiler is at least a specified version, whether AppleClang or regular Clang diff --git a/test cases/common/138 whole archive/meson.build b/test cases/common/138 whole archive/meson.build index 012df33..33fe1ea 100644 --- a/test cases/common/138 whole archive/meson.build +++ b/test cases/common/138 whole archive/meson.build @@ -1,5 +1,9 @@ project('whole archive', 'c') +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST: whole-archive not supported in Xcode. Patches welcome.') +endif + add_project_arguments('-I' + meson.source_root(), language : 'c') cc = meson.get_compiler('c') diff --git a/test cases/common/139 C and CPP link/meson.build b/test cases/common/139 C and CPP link/meson.build index a93a981..32d1843 100644 --- a/test cases/common/139 C and CPP link/meson.build +++ b/test cases/common/139 C and CPP link/meson.build @@ -14,6 +14,16 @@ project('C and C++ static link test', ['c', 'cpp']) +if meson.backend() == 'xcode' + error('''MESON_SKIP_TEST: overriding link language is not supported in Xcode. + +If you really need this, then patches are welcome. The only known way is +to create a dummy C++ file in the meson-private directory and adding +that to the target's source list when needed. The primitives exist +but may need some tweaking. Grep for language_stdlib_only_link_flags to find +where this is handled in other backends.''') +endif + # Verify that adding link arguments works. add_global_link_arguments('', language : 'c') add_project_link_arguments('', language : 'c') diff --git a/test cases/common/141 custom target multiple outputs/meson.build b/test cases/common/141 custom target multiple outputs/meson.build index 382c9b2..3030505 100644 --- a/test cases/common/141 custom target multiple outputs/meson.build +++ b/test cases/common/141 custom target multiple outputs/meson.build @@ -32,8 +32,13 @@ foreach i : targets.to_list() paths += i.full_path() endforeach +# The Xcode backend has a different output naming scheme. +if meson.backend() == 'xcode' + assert(paths == [meson.project_build_root() / get_option('buildtype') / 'second.h', + meson.project_build_root() / get_option('buildtype') / 'second.sh']) + # Skip on Windows because paths are not identical, '/' VS '\'. -if host_machine.system() != 'windows' +elif host_machine.system() != 'windows' assert(paths == [meson.current_build_dir() / 'second.h', meson.current_build_dir() / 'second.sh']) endif diff --git a/test cases/common/15 if/meson.build b/test cases/common/15 if/meson.build index b0288db..f8d8295 100644 --- a/test cases/common/15 if/meson.build +++ b/test cases/common/15 if/meson.build @@ -58,3 +58,15 @@ elif false else message('Ok') endif + +# Test plain else + +var = false + +if var + exe = executable('break', 'break.c') +else + exe = executable('eprog', 'prog.c') +endif + +test('elsetest', exe) diff --git a/test cases/common/152 duplicate source names/meson.build b/test cases/common/152 duplicate source names/meson.build index cac5194..635aa8c 100644 --- a/test cases/common/152 duplicate source names/meson.build +++ b/test cases/common/152 duplicate source names/meson.build @@ -1,5 +1,17 @@ project('proj', 'c') +if meson.backend() == 'xcode' + # Xcode gives object files unique names but only if they would clash. For example + # two files named lib.o instead get the following names: + # + # lib-4fbe522d8ba4cb1f1b89cc2df640a2336b92e1a5565f0a4c5a79b5b5e2969eb9.o + # lib-4fbe522d8ba4cb1f1b89cc2df640a2336deeff2bc2297affaadbe20f5cbfee56.o + # + # No-one has reverse engineered the naming scheme so we would access them. + # IF you feel up to the challenge, patches welcome. + error('MESON_SKIP_TEST, Xcode can not extract objs when they would have the same filename.') +endif + sources = [] subdir('dir1') subdir('dir2') diff --git a/test cases/common/16 else/meson.build b/test cases/common/16 else/meson.build deleted file mode 100644 index 99cb927..0000000 --- a/test cases/common/16 else/meson.build +++ /dev/null @@ -1,11 +0,0 @@ -project('else test', 'c') - -var = false - -if var - exe = executable('break', 'break.c') -else - exe = executable('prog', 'prog.c') -endif - -test('elsetest', exe) diff --git a/test cases/common/16 else/prog.c b/test cases/common/16 else/prog.c deleted file mode 100644 index 78f2de1..0000000 --- a/test cases/common/16 else/prog.c +++ /dev/null @@ -1 +0,0 @@ -int main(void) { return 0; } diff --git a/test cases/common/171 generator link whole/meson.build b/test cases/common/171 generator link whole/meson.build index 30ae9c6..106153a 100644 --- a/test cases/common/171 generator link whole/meson.build +++ b/test cases/common/171 generator link whole/meson.build @@ -1,5 +1,9 @@ project('generator link_whole', 'c') +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST: whole-archive not supported in Xcode. Patches welcome.') +endif + cc = meson.get_compiler('c') if cc.get_id() == 'msvc' if cc.version().version_compare('<19') diff --git a/test cases/common/173 identical target name in subproject flat layout/meson.build b/test cases/common/173 identical target name in subproject flat layout/meson.build index d859fda..ce1d4b8 100644 --- a/test cases/common/173 identical target name in subproject flat layout/meson.build +++ b/test cases/common/173 identical target name in subproject flat layout/meson.build @@ -1,5 +1,9 @@ project('subproject targets', 'c') +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST: many targets with the same name not supported in Xcode. Patches welcome.') +endif + # Idea behind this test is to create targets with identical name # but different output files. We can do this by choosing different # name_prefix of libraries. Target id does not depend on name_prefix. diff --git a/test cases/common/182 same target name flat layout/meson.build b/test cases/common/182 same target name flat layout/meson.build index a3c95fa..cfad2c2 100644 --- a/test cases/common/182 same target name flat layout/meson.build +++ b/test cases/common/182 same target name flat layout/meson.build @@ -1,5 +1,9 @@ project('subdir targets', 'c') +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST: many targets with the same name not supported in Xcode. Patches welcome.') +endif + # Idea behind this test is to create targets with identical name # but different output files. We can do this by choosing different # name_prefix of libraries. Target id does not depend on name_prefix. diff --git a/test cases/common/209 link custom/meson.build b/test cases/common/209 link custom/meson.build index 837e960..4d4f655 100644 --- a/test cases/common/209 link custom/meson.build +++ b/test cases/common/209 link custom/meson.build @@ -28,13 +28,17 @@ test('linkcustom2', exe2) # Link whole tests -exe3 = executable('prog3', 'prog.c', link_whole: clib) -test('linkwhole', exe) +if meson.backend() == 'xcode' + message('Xcode does not support link whole so skipping.') +else + exe3 = executable('prog3', 'prog.c', link_whole: clib) + test('linkwhole', exe) -d2 = declare_dependency(link_whole: clib) + d2 = declare_dependency(link_whole: clib) -exe4 = executable('prog4', 'prog.c', dependencies: d2) -test('linkwhole2', exe2) + exe4 = executable('prog4', 'prog.c', dependencies: d2) + test('linkwhole2', exe2) +endif # custom_target[i] tests @@ -46,17 +50,21 @@ d_i = declare_dependency(link_with: clib[0]) exe2_i = executable('prog2_i', 'prog.c', dependencies: d_i) test('linkcustom2_i', exe2_i) -shared_library('lib1', 'lib.c', link_whole: clib) - # Link whole tests -exe3_i = executable('prog3_i', 'prog.c', link_whole: clib[0]) -test('linkwhole', exe) +if meson.backend() == 'xcode' + message('Xcode does not support link whole so skipping.') +else + shared_library('lib1', 'lib.c', link_whole: clib) + + exe3_i = executable('prog3_i', 'prog.c', link_whole: clib[0]) + test('linkwhole', exe) -d2_i = declare_dependency(link_whole: clib[0]) + d2_i = declare_dependency(link_whole: clib[0]) -exe4_i = executable('prog4_i', 'prog.c', dependencies: d2_i) -test('linkwhole2_i', exe2_i) + exe4_i = executable('prog4_i', 'prog.c', dependencies: d2_i) + test('linkwhole2_i', exe2_i) +endif # Link with custom target diff --git a/test cases/common/210 link custom_i single from multiple/meson.build b/test cases/common/210 link custom_i single from multiple/meson.build index eee1fe1..7aadb17 100644 --- a/test cases/common/210 link custom_i single from multiple/meson.build +++ b/test cases/common/210 link custom_i single from multiple/meson.build @@ -28,6 +28,11 @@ test('linkcustom2', exe2) # Link whole tests +if meson.backend() == 'xcode' + message('Xcode does not support link whole so skipping.') + subdir_done() +endif + exe3 = executable('prog3', 'prog.c', link_whole: clib_2) test('linkwhole', exe) diff --git a/test cases/common/211 link custom_i multiple from multiple/meson.build b/test cases/common/211 link custom_i multiple from multiple/meson.build index e5236e5..ede059e 100644 --- a/test cases/common/211 link custom_i multiple from multiple/meson.build +++ b/test cases/common/211 link custom_i multiple from multiple/meson.build @@ -28,6 +28,11 @@ test('linkcustom2', exe2) # Link whole tests +if meson.backend() == 'xcode' + message('Xcode does not support link whole so skipping.') + subdir_done() +endif + exe3 = executable('prog3', 'prog.c', link_whole: clibs) test('linkwhole', exe) diff --git a/test cases/common/217 custom target input extracted objects/meson.build b/test cases/common/217 custom target input extracted objects/meson.build index 579308c..8f8b22f 100644 --- a/test cases/common/217 custom target input extracted objects/meson.build +++ b/test cases/common/217 custom target input extracted objects/meson.build @@ -1,5 +1,10 @@ project('custom target input extracted objects', 'c') +if meson.backend() == 'xcode' + error('MESON_SKIP_TEST: sometimes Xcode puts object files in weird paths and we can not extract them.') +endif + + checker = find_program('check_object.py') cc = meson.get_compiler('c').cmd_array().get(-1) diff --git a/test cases/swift/1 exe/prog.swift b/test cases/swift/1 exe/main.swift index 1b489de..1b489de 100644 --- a/test cases/swift/1 exe/prog.swift +++ b/test cases/swift/1 exe/main.swift diff --git a/test cases/swift/1 exe/meson.build b/test cases/swift/1 exe/meson.build index f986e9a..4436a8e 100644 --- a/test cases/swift/1 exe/meson.build +++ b/test cases/swift/1 exe/meson.build @@ -1,3 +1,3 @@ project('swift exe', 'swift') -test('swifttest', executable('swifttest', 'prog.swift')) +test('swifttest', executable('swifttest', 'main.swift')) diff --git a/test cases/unit/48 reconfigure/meson.build b/test cases/unit/48 reconfigure/meson.build index 6eaac5d..4f35458 100644 --- a/test cases/unit/48 reconfigure/meson.build +++ b/test cases/unit/48 reconfigure/meson.build @@ -7,3 +7,5 @@ message('opt4 ' + get_option('opt4')) exe = executable('test1', 'main.c') test('test1', exe) + +sub1 = subproject('sub1') diff --git a/test cases/unit/48 reconfigure/subprojects/sub1/meson.build b/test cases/unit/48 reconfigure/subprojects/sub1/meson.build new file mode 100644 index 0000000..4f3d2fc --- /dev/null +++ b/test cases/unit/48 reconfigure/subprojects/sub1/meson.build @@ -0,0 +1,3 @@ +project('sub1') + +message('sub1:werror', get_option('werror')) diff --git a/test cases/unit/57 introspection/meson.build b/test cases/unit/57 introspection/meson.build index 2b38151..2f666f3 100644 --- a/test cases/unit/57 introspection/meson.build +++ b/test cases/unit/57 introspection/meson.build @@ -27,13 +27,18 @@ var1 = '1' var2 = 2.to_string() var3 = 'test3' -cus = custom_target('custom target test', output: 'file2', input: 'cp.py', - command: [find_program('cp.py'), '@INPUT@', '@OUTPUT@']) +cus1 = custom_target('custom target test 1', output: 'file2', input: 'cp.py', + command: [find_program('cp.py'), '@INPUT@', '@OUTPUT@']) +cus2 = custom_target('custom target test 2', output: 'file3', input: cus1, + command: [find_program('cp.py'), '@INPUT@', '@OUTPUT@']) t1 = executable('test' + var1, ['t1.cpp'], link_with: [sharedlib], install: not false, build_by_default: get_option('test_opt2')) t2 = executable('test@0@'.format('@0@'.format(var2)), sources: ['t2.cpp'], link_with: [staticlib]) t3 = executable(var3, 't3.cpp', link_with: [sharedlib, staticlib], dependencies: [dep1]) +cus3 = custom_target('custom target test 3', output: 'file4', input: t3, + command: [find_program('cp.py'), '@INPUT@', '@OUTPUT@']) + ### BEGIN: Test inspired by taisei: https://github.com/taisei-project/taisei/blob/master/meson.build#L293 systype = '@0@'.format(host_machine.system()) systype = '@0@, @1@, @2@'.format(systype, host_machine.cpu_family(), host_machine.cpu()) @@ -49,7 +54,7 @@ message(osmesa_lib_name) # Infinite recursion gets triggered here when the param test('test case 1', t1) test('test case 2', t2, depends: t3) -benchmark('benchmark 1', t3, args: cus) +benchmark('benchmark 1', t3, args: [cus1, cus2, cus3]) ### Stuff to test the AST JSON printer foreach x : ['a', 'b', 'c'] diff --git a/test cases/unit/95 implicit force fallback/meson.build b/test cases/unit/95 implicit force fallback/meson.build new file mode 100644 index 0000000..623a338 --- /dev/null +++ b/test cases/unit/95 implicit force fallback/meson.build @@ -0,0 +1,8 @@ +project('implicit force fallback') + +# The dependency 'something' is provided by a subproject. Normally this won't +# use the fallback subproject because required is false. However this unit test +# is configured with wrap_mode=forcefallback and force_fallback_for=something +# in which case we are expecting the fallback to be done. +d = dependency('something', required: false) +assert(d.found()) diff --git a/test cases/unit/95 implicit force fallback/subprojects/something/meson.build b/test cases/unit/95 implicit force fallback/subprojects/something/meson.build new file mode 100644 index 0000000..89a4727 --- /dev/null +++ b/test cases/unit/95 implicit force fallback/subprojects/something/meson.build @@ -0,0 +1,3 @@ +project('something') + +meson.override_dependency('something', declare_dependency()) |