diff options
33 files changed, 312 insertions, 51 deletions
diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 39e41e9..90ebeff 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -136,6 +136,7 @@ jobs: git ^ mercurial ^ mingw-w64-$(MSYS2_ARCH)-cmake ^ + mingw-w64-$(MSYS2_ARCH)-ninja ^ mingw-w64-$(MSYS2_ARCH)-pkg-config ^ mingw-w64-$(MSYS2_ARCH)-python2 ^ mingw-w64-$(MSYS2_ARCH)-python3 ^ @@ -144,7 +145,6 @@ jobs: displayName: Install Dependencies - script: | set PATH=%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem - %MSYS2_ROOT%\usr\bin\bash -lc "wget https://github.com/mesonbuild/cidata/raw/master/ninja.exe; mv ninja.exe /$MSYSTEM/bin" set PATHEXT=%PATHEXT%;.py if %compiler%==clang ( set CC=clang && set CXX=clang++ ) %MSYS2_ROOT%\usr\bin\bash -lc "MSYSTEM= python3 run_tests.py --backend=ninja" diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md index 288bd79..0d1a16b 100644 --- a/docs/markdown/Builtin-options.md +++ b/docs/markdown/Builtin-options.md @@ -42,7 +42,7 @@ Installation options are all relative to the prefix, except: | werror | false | Treat warnings as errors | | warning_level {1, 2, 3} | 1 | Set the warning level. From 1 = lowest to 3 = highest | | layout {mirror,flat} | mirror | Build directory layout. | -| default-library {shared, static, both} | shared | Default library type. | +| default_library {shared, static, both} | shared | Default library type. | | backend {ninja, vs,<br>vs2010, vs2015, vs2017, xcode} | | Backend to use (default: ninja). | | stdsplit | | Split stdout and stderr in test logs. | | errorlogs | | Whether to print the logs from failing tests. | diff --git a/docs/markdown/Configuring-a-build-directory.md b/docs/markdown/Configuring-a-build-directory.md index 0c7487f..91ad6f7 100644 --- a/docs/markdown/Configuring-a-build-directory.md +++ b/docs/markdown/Configuring-a-build-directory.md @@ -111,3 +111,8 @@ you would issue the following command. Then you would run your build command (usually `ninja`), which would cause Meson to detect that the build setup has changed and do all the work required to bring your build tree up to date. + +Since 0.50.0, it is also possible to get a list of all build options +by invoking `meson configure` with the project source directory or +the path to the root `meson.build`. In this case, meson will print the +default values of all options similar to the example output from above. diff --git a/docs/markdown/Cuda-module.md b/docs/markdown/Cuda-module.md index 6e7be47..caa1756 100644 --- a/docs/markdown/Cuda-module.md +++ b/docs/markdown/Cuda-module.md @@ -6,7 +6,7 @@ authors: has-copyright: false ... -# Unstable CUDA Module (`unstable-cuda`) +# Unstable CUDA Module _Since: 0.50.0_ This module provides helper functionality related to the CUDA Toolkit and diff --git a/docs/markdown/snippets/configure_default_opts.md b/docs/markdown/snippets/configure_default_opts.md new file mode 100644 index 0000000..4b88bdf --- /dev/null +++ b/docs/markdown/snippets/configure_default_opts.md @@ -0,0 +1,6 @@ +## meson configure can now print the default options of an unconfigured project + +With this release, it is also possible to get a list of all build options +by invoking `meson configure` with the project source directory or +the path to the root `meson.build`. In this case, meson will print the +default values of all options. diff --git a/docs/markdown/snippets/fortran_submodule.md b/docs/markdown/snippets/fortran_submodule.md new file mode 100644 index 0000000..9e4b9cc --- /dev/null +++ b/docs/markdown/snippets/fortran_submodule.md @@ -0,0 +1,12 @@ +## Fortran submodule support + +Initial support for Fortran ``submodule`` was added, where the submodule is in +the same or different file than the parent ``module``. +The submodule hierarchy specified in the source Fortran code `submodule` +statements are used by Meson to resolve source file dependencies. +For example: + +```fortran +submodule (ancestor:parent) child +``` + diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 87f9b38..afef9a9 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - +from typing import List import os import re import shlex @@ -29,7 +29,7 @@ from .. import build from .. import mlog from .. import dependencies from .. import compilers -from ..compilers import CompilerArgs, CCompiler, VisualStudioCCompiler +from ..compilers import CompilerArgs, CCompiler, VisualStudioCCompiler, FortranCompiler from ..linkers import ArLinker from ..mesonlib import File, MachineChoice, MesonException, OrderedSet from ..mesonlib import get_compiler_for_source, has_path_sep @@ -428,12 +428,7 @@ int dummy; # Generate rules for building the remaining source files in this target outname = self.get_target_filename(target) obj_list = [] - use_pch = self.environment.coredata.base_options.get('b_pch', False) is_unity = self.is_unity(target) - if use_pch and target.has_pch(): - pch_objects = self.generate_pch(target, outfile) - else: - pch_objects = [] header_deps = [] unity_src = [] unity_deps = [] # Generated sources that must be built before compiling a Unity target. @@ -486,6 +481,12 @@ int dummy; header_deps=header_deps) obj_list.append(o) + use_pch = self.environment.coredata.base_options.get('b_pch', False) + if use_pch and target.has_pch(): + pch_objects = self.generate_pch(target, outfile, header_deps=header_deps) + else: + pch_objects = [] + # Generate compilation targets for C sources generated from Vala # sources. This can be extended to other $LANG->C compilers later if # necessary. This needs to be separate for at least Vala @@ -1826,7 +1827,8 @@ rule FORTRAN_DEP_HACK%s if compiler is None: self.fortran_deps[target.get_basename()] = {} return - modre = re.compile(r"\bmodule\s+(\w+)\s*$", re.IGNORECASE) + modre = re.compile(r"\s*\bmodule\b\s+(\w+)\s*$", re.IGNORECASE) + submodre = re.compile(r"\s*\bsubmodule\b\s+\((\w+:?\w+)\)\s+(\w+)\s*$", re.IGNORECASE) module_files = {} for s in target.get_sources(): # FIXME, does not work for Fortran sources generated by @@ -1836,9 +1838,8 @@ rule FORTRAN_DEP_HACK%s continue filename = s.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) - # Some Fortran editors save in weird encodings, - # but all the parts we care about are in ASCII. - with open(filename, errors='ignore') as f: + # Fortran keywords must be ASCII. + with open(filename, encoding='ascii', errors='ignore') as f: for line in f: modmatch = modre.match(line) if modmatch is not None: @@ -1849,18 +1850,32 @@ rule FORTRAN_DEP_HACK%s 'two files %s and %s.' % (modname, module_files[modname], s)) module_files[modname] = s + else: + submodmatch = submodre.match(line) + if submodmatch is not None: + submodname = submodmatch.group(2).lower() + if submodname in module_files: + raise InvalidArguments( + 'Namespace collision: submodule %s defined in ' + 'two files %s and %s.' % + (submodname, module_files[submodname], s)) + module_files[submodname] = s + self.fortran_deps[target.get_basename()] = module_files - def get_fortran_deps(self, compiler, src, target): + def get_fortran_deps(self, compiler: FortranCompiler, src: str, target) -> List[str]: mod_files = [] - usere = re.compile(r"\s*use\s+(\w+)", re.IGNORECASE) + usere = re.compile(r"\s*use,?\s*(?:non_intrinsic)?\s*(?:::)?\s*(\w+)", re.IGNORECASE) + submodre = re.compile(r"\s*\bsubmodule\b\s+\((\w+:?\w+)\)\s+(\w+)\s*$", re.IGNORECASE) dirname = self.get_target_private_dir(target) tdeps = self.fortran_deps[target.get_basename()] - with open(src) as f: + with open(src, encoding='ascii', errors='ignore') as f: for line in f: usematch = usere.match(line) if usematch is not None: usename = usematch.group(1).lower() + if usename == 'intrinsic': # this keeps the regex simpler + continue if usename not in tdeps: # The module is not provided by any source file. This # is due to: @@ -1879,9 +1894,23 @@ rule FORTRAN_DEP_HACK%s # the same name. if mod_source_file.fname == os.path.basename(src): continue - mod_name = compiler.module_name_to_filename( - usematch.group(1)) + mod_name = compiler.module_name_to_filename(usename) mod_files.append(os.path.join(dirname, mod_name)) + else: + submodmatch = submodre.match(line) + if submodmatch is not None: + parents = submodmatch.group(1).lower().split(':') + assert len(parents) in (1, 2), ( + 'submodule ancestry must be specified as' + ' ancestor:parent but Meson found {}'.parents) + for parent in parents: + if parent not in tdeps: + raise MesonException("submodule {} relies on parent module {} that was not found.".format(submodmatch.group(2).lower(), parent)) + if tdeps[parent].fname == os.path.basename(src): # same file + continue + mod_name = compiler.module_name_to_filename(parent) + mod_files.append(os.path.join(dirname, mod_name)) + return mod_files def get_cross_stdlib_args(self, target, compiler): @@ -2181,12 +2210,7 @@ rule FORTRAN_DEP_HACK%s commands += compiler.get_module_outdir_args(self.get_target_private_dir(target)) element = NinjaBuildElement(self.all_outputs, rel_obj, compiler_name, rel_src) - for d in header_deps: - if isinstance(d, File): - d = d.rel_to_builddir(self.build_to_src) - elif not self.has_dir_part(d): - d = os.path.join(self.get_target_private_dir(target), d) - element.add_dep(d) + self.add_header_deps(target, element, header_deps) for d in extra_deps: element.add_dep(d) for d in order_deps: @@ -2195,7 +2219,14 @@ rule FORTRAN_DEP_HACK%s elif not self.has_dir_part(d): d = os.path.join(self.get_target_private_dir(target), d) element.add_orderdep(d) - element.add_orderdep(pch_dep) + if compiler.id == 'msvc': + # MSVC does not show includes coming from the PCH with '/showIncludes', + # thus we must add an implicit dependency to the generated PCH. + element.add_dep(pch_dep) + else: + # All other compilers properly handle includes through the PCH, so only an + # orderdep is needed to make the initial build without depfile work. + element.add_orderdep(pch_dep) # Convert from GCC-style link argument naming to the naming used by the # current compiler. commands = commands.to_native() @@ -2206,6 +2237,14 @@ rule FORTRAN_DEP_HACK%s element.write(outfile) return rel_obj + def add_header_deps(self, target, ninja_element, header_deps): + for d in header_deps: + if isinstance(d, File): + d = d.rel_to_builddir(self.build_to_src) + elif not self.has_dir_part(d): + d = os.path.join(self.get_target_private_dir(target), d) + ninja_element.add_dep(d) + def has_dir_part(self, fname): # FIXME FIXME: The usage of this is a terrible and unreliable hack if isinstance(fname, File): @@ -2236,6 +2275,7 @@ rule FORTRAN_DEP_HACK%s just_name = os.path.basename(header) (objname, pch_args) = compiler.gen_pch_args(just_name, source, dst) commands += pch_args + commands += self._generate_single_compile(target, compiler) commands += self.get_compile_debugfile_args(compiler, target, objname) dep = dst + '.' + compiler.get_depfile_suffix() return commands, dep, dst, [objname] @@ -2251,7 +2291,7 @@ rule FORTRAN_DEP_HACK%s dep = dst + '.' + compiler.get_depfile_suffix() return commands, dep, dst, [] # Gcc does not create an object file during pch generation. - def generate_pch(self, target, outfile): + def generate_pch(self, target, outfile, header_deps=[]): cstr = '' pch_objects = [] if target.is_cross: @@ -2282,6 +2322,7 @@ rule FORTRAN_DEP_HACK%s elem = NinjaBuildElement(self.all_outputs, dst, rulename, src) if extradep is not None: elem.add_dep(extradep) + self.add_header_deps(target, elem, header_deps) elem.add_item('ARGS', commands) elem.add_item('DEPFILE', dep) elem.write(outfile) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 074c3a9..8029d58 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -312,8 +312,6 @@ class Vs2010Backend(backends.Backend): target_dict, recursive=True) ofile.write('\tProjectSection(ProjectDependencies) = ' 'postProject\n') - regen_guid = self.environment.coredata.regen_guid - ofile.write('\t\t{%s} = {%s}\n' % (regen_guid, regen_guid)) for dep in all_deps.keys(): guid = self.environment.coredata.target_guids[dep] ofile.write('\t\t{%s} = {%s}\n' % (guid, guid)) @@ -520,6 +518,7 @@ class Vs2010Backend(backends.Backend): ET.SubElement(customstep, 'Command').text = cmd_templ % tuple(cmd) ET.SubElement(customstep, 'Message').text = 'Running custom command.' ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') + self.add_regen_dependency(root) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) def gen_custom_target_vcxproj(self, target, ofname, guid): @@ -547,6 +546,7 @@ class Vs2010Backend(backends.Backend): ET.SubElement(customstep, 'Inputs').text = ';'.join([exe_data] + srcs + depend_files) ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') self.generate_custom_generator_commands(target, root) + self.add_regen_dependency(root) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) @classmethod @@ -1213,9 +1213,7 @@ class Vs2010Backend(backends.Backend): self.add_generated_objects(inc_objs, gen_objs) ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') - # Reference the regen target. - regen_vcxproj = os.path.join(self.environment.get_build_dir(), 'REGEN.vcxproj') - self.add_project_reference(root, regen_vcxproj, self.environment.coredata.regen_guid) + self.add_regen_dependency(root) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) def gen_regenproj(self, project_name, ofname): @@ -1366,6 +1364,7 @@ if %%errorlevel%% neq 0 goto :VCEnd''' ET.SubElement(postbuild, 'Command').text =\ cmd_templ % ('" "'.join(test_command)) ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') + self.add_regen_dependency(root) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) def gen_installproj(self, target_name, ofname): @@ -1434,8 +1433,13 @@ if %%errorlevel%% neq 0 goto :VCEnd''' ET.SubElement(postbuild, 'Command').text =\ cmd_templ % ('" "'.join(test_command)) ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') + self.add_regen_dependency(root) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) def generate_debug_information(self, link): # valid values for vs2015 is 'false', 'true', 'DebugFastLink' ET.SubElement(link, 'GenerateDebugInformation').text = 'true' + + def add_regen_dependency(self, root): + regen_vcxproj = os.path.join(self.environment.get_build_dir(), 'REGEN.vcxproj') + self.add_project_reference(root, regen_vcxproj, self.environment.coredata.regen_guid) diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 1390694..40906c5 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -380,7 +380,7 @@ class DCompiler(Compiler): # translate library link flag dcargs.append('-L=' + arg) continue - elif arg.startswith('-L'): + elif arg.startswith('-L/') or arg.startswith('-L./'): # we need to handle cases where -L is set by e.g. a pkg-config # setting to select a linker search path. We can however not # unconditionally prefix '-L' with '-L' because the user might diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index eea1660..8c50736 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -179,7 +179,7 @@ class FortranCompiler(Compiler): return parameter_list - def module_name_to_filename(self, module_name): + def module_name_to_filename(self, module_name: str) -> str: return module_name.lower() + '.mod' def get_std_shared_lib_link_args(self): diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 9da0d7c..8196124 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -1674,9 +1674,9 @@ class DubDependency(ExternalDependency): return '' # Ex.: library-debug-linux.posix-x86_64-ldc_2081-EF934983A3319F8F8FF2F0E107A363BA - build_name = 'library-{}-{}-{}-{}_{}'.format(description['buildType'], '.'.join(description['platform']), '.'.join(description['architecture']), comp, d_ver) + build_name = '-{}-{}-{}-{}_{}'.format(description['buildType'], '.'.join(description['platform']), '.'.join(description['architecture']), comp, d_ver) for entry in os.listdir(module_build_path): - if entry.startswith(build_name): + if build_name in entry: for file in os.listdir(os.path.join(module_build_path, entry)): if file == lib_file_name: if folder_only: diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index a3feebe..18bb37b 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -13,8 +13,7 @@ # limitations under the License. import os -from . import (coredata, mesonlib, build) -from . import mintro +from . import coredata, environment, mesonlib, build, mintro, mlog def add_arguments(parser): coredata.register_builtin_arguments(parser) @@ -38,11 +37,28 @@ class ConfException(mesonlib.MesonException): class Conf: def __init__(self, build_dir): - self.build_dir = build_dir - if not os.path.isdir(os.path.join(build_dir, 'meson-private')): - raise ConfException('Directory %s does not seem to be a Meson build directory.' % build_dir) - self.build = build.load(self.build_dir) - self.coredata = coredata.load(self.build_dir) + self.build_dir = os.path.abspath(os.path.realpath(build_dir)) + if 'meson.build' in [os.path.basename(self.build_dir), self.build_dir]: + self.build_dir = os.path.dirname(self.build_dir) + self.build = None + + if os.path.isdir(os.path.join(self.build_dir, 'meson-private')): + self.build = build.load(self.build_dir) + self.source_dir = self.build.environment.get_source_dir() + self.coredata = coredata.load(self.build_dir) + self.default_values_only = False + elif os.path.isfile(os.path.join(self.build_dir, environment.build_filename)): + # Make sure that log entries in other parts of meson don't interfere with the JSON output + mlog.disable() + self.source_dir = os.path.abspath(os.path.realpath(self.build_dir)) + intr = mintro.IntrospectionInterpreter(self.source_dir, '', 'ninja') + intr.analyze() + # Reenable logging just in case + mlog.enable() + self.coredata = intr.coredata + self.default_values_only = True + else: + raise ConfException('Directory {} is neither a Meson build directory nor a project source directory.'.format(build_dir)) def clear_cache(self): self.coredata.deps = {} @@ -51,18 +67,22 @@ class Conf: self.coredata.set_options(options) def save(self): + # Do nothing when using introspection + if self.default_values_only: + return # Only called if something has changed so overwrite unconditionally. coredata.save(self.coredata, self.build_dir) # We don't write the build file because any changes to it # are erased when Meson is executed the next time, i.e. when # Ninja is run. - @staticmethod - def print_aligned(arr): + def print_aligned(self, arr): if not arr: return titles = {'name': 'Option', 'descr': 'Description', 'value': 'Current Value', 'choices': 'Possible Values'} + if self.default_values_only: + titles['value'] = 'Default Value' name_col = [titles['name'], '-' * len(titles['name'])] value_col = [titles['value'], '-' * len(titles['value'])] @@ -110,9 +130,18 @@ class Conf: self.print_aligned(arr) def print_conf(self): + def print_default_values_warning(): + mlog.warning('The source directory instead of the build directory was specified.') + mlog.warning('Only the default values for the project are printed, and all command line parameters are ignored.') + + if self.default_values_only: + print_default_values_warning() + print('') + print('Core properties:') - print(' Source dir', self.build.environment.source_dir) - print(' Build dir ', self.build.environment.build_dir) + print(' Source dir', self.source_dir) + if not self.default_values_only: + print(' Build dir ', self.build_dir) dir_option_names = ['bindir', 'datadir', @@ -144,6 +173,10 @@ class Conf: self.print_options('Project options', self.coredata.user_options) self.print_options('Testing options', test_options) + # Print the warning twice so that the user shouldn't be able to miss it + if self.default_values_only: + print('') + print_default_values_warning() def run(options): coredata.parse_cmd_line_options(options) @@ -151,6 +184,10 @@ def run(options): c = None try: c = Conf(builddir) + if c.default_values_only: + c.print_conf() + return 0 + save = False if len(options.cmd_line_options) > 0: c.set_options(options.cmd_line_options) diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 5eecb67..2d01c11 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -321,7 +321,7 @@ def run(options): if options.builddir is not None: datadir = os.path.join(options.builddir, datadir) infodir = os.path.join(options.builddir, infodir) - if options.builddir.endswith('/meson.build') or options.builddir.endswith('\\meson.build') or options.builddir == 'meson.build': + if 'meson.build' in [os.path.basename(options.builddir), options.builddir]: sourcedir = '.' if options.builddir == 'meson.build' else options.builddir[:-11] if options.projectinfo: list_projinfo_from_source(sourcedir, indent) diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index b4bd4f2..6536558 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -438,6 +438,8 @@ class TestHarness: current = self.build_data.test_setups[full_name] if not options.gdb: options.gdb = current.gdb + if options.gdb: + options.verbose = True if options.timeout_multiplier is None: options.timeout_multiplier = current.timeout_multiplier # if options.env is None: @@ -693,18 +695,17 @@ Timeout: %4d for _ in range(self.options.repeat): for i, test in enumerate(tests): visible_name = self.get_pretty_suite(test) + single_test = self.get_test_runner(test) - if not test.is_parallel or self.options.gdb: + if not test.is_parallel or single_test.options.gdb: self.drain_futures(futures) futures = [] - single_test = self.get_test_runner(test) res = single_test.run() self.process_test_result(res) self.print_stats(numlen, tests, visible_name, res, i) else: if not executor: executor = conc.ThreadPoolExecutor(max_workers=self.options.num_processes) - single_test = self.get_test_runner(test) f = executor.submit(single_test.run) futures.append((f, numlen, tests, visible_name, i)) if self.options.repeat > 1 and self.fail_count: diff --git a/test cases/common/13 pch/generated/gen_custom.py b/test cases/common/13 pch/generated/gen_custom.py new file mode 100644 index 0000000..650e03c --- /dev/null +++ b/test cases/common/13 pch/generated/gen_custom.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 +import sys + +with open(sys.argv[1], 'w') as f: + f.write("#define FOO 0") diff --git a/test cases/common/13 pch/generated/gen_generator.py b/test cases/common/13 pch/generated/gen_generator.py new file mode 100644 index 0000000..a245e7a --- /dev/null +++ b/test cases/common/13 pch/generated/gen_generator.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 +import sys + +with open(sys.argv[1]) as f: + content = f.read() +with open(sys.argv[2], 'w') as f: + f.write(content) diff --git a/test cases/common/13 pch/generated/generated_generator.in b/test cases/common/13 pch/generated/generated_generator.in new file mode 100644 index 0000000..1a00ebd --- /dev/null +++ b/test cases/common/13 pch/generated/generated_generator.in @@ -0,0 +1 @@ +#define BAR 0 diff --git a/test cases/common/13 pch/generated/meson.build b/test cases/common/13 pch/generated/meson.build new file mode 100644 index 0000000..372a00e --- /dev/null +++ b/test cases/common/13 pch/generated/meson.build @@ -0,0 +1,16 @@ +cc = meson.get_compiler('c') +cc_id = cc.get_id() +if cc_id == 'lcc' + error('MESON_SKIP_TEST: Elbrus compiler does not support PCH.') +endif + +generated_customTarget = custom_target('makeheader', + output: 'generated_customTarget.h', + command : [find_program('gen_custom.py'), '@OUTPUT0@']) + +generated_generator = generator(find_program('gen_generator.py'), + output: '@BASENAME@.h', + arguments: ['@INPUT@', '@OUTPUT@']) + +exe = executable('prog', 'prog.c', generated_customTarget, generated_generator.process('generated_generator.in'), + c_pch: ['pch/prog_pch.c', 'pch/prog.h']) diff --git a/test cases/common/13 pch/generated/pch/prog.h b/test cases/common/13 pch/generated/pch/prog.h new file mode 100644 index 0000000..15fec38 --- /dev/null +++ b/test cases/common/13 pch/generated/pch/prog.h @@ -0,0 +1,2 @@ +#include "generated_customTarget.h" +#include "generated_generator.h" diff --git a/test cases/common/13 pch/generated/pch/prog_pch.c b/test cases/common/13 pch/generated/pch/prog_pch.c new file mode 100644 index 0000000..4960505 --- /dev/null +++ b/test cases/common/13 pch/generated/pch/prog_pch.c @@ -0,0 +1,5 @@ +#if !defined(_MSC_VER) +#error "This file is only for use with MSVC." +#endif + +#include "prog.h" diff --git a/test cases/common/13 pch/generated/prog.c b/test cases/common/13 pch/generated/prog.c new file mode 100644 index 0000000..9b2e2ef --- /dev/null +++ b/test cases/common/13 pch/generated/prog.c @@ -0,0 +1,6 @@ +// No includes here, they need to come from the PCH + +int main(int argc, char **argv) { + return FOO + BAR; +} + diff --git a/test cases/common/13 pch/meson.build b/test cases/common/13 pch/meson.build index d39527b..43129c9 100644 --- a/test cases/common/13 pch/meson.build +++ b/test cases/common/13 pch/meson.build @@ -2,6 +2,8 @@ project('pch test', 'c', 'cpp') subdir('c') subdir('cpp') +subdir('generated') +subdir('withIncludeDirectories') if meson.backend() == 'xcode' warning('Xcode backend only supports one precompiled header per target. Skipping "mixed" which has various precompiled headers.') diff --git a/test cases/common/13 pch/withIncludeDirectories/include/lib/lib.h b/test cases/common/13 pch/withIncludeDirectories/include/lib/lib.h new file mode 100644 index 0000000..53c5fdf --- /dev/null +++ b/test cases/common/13 pch/withIncludeDirectories/include/lib/lib.h @@ -0,0 +1 @@ +#include <stdio.h> diff --git a/test cases/common/13 pch/withIncludeDirectories/meson.build b/test cases/common/13 pch/withIncludeDirectories/meson.build new file mode 100644 index 0000000..2ab2cd8 --- /dev/null +++ b/test cases/common/13 pch/withIncludeDirectories/meson.build @@ -0,0 +1,9 @@ +cc = meson.get_compiler('c') +cc_id = cc.get_id() +if cc_id == 'lcc' + error('MESON_SKIP_TEST: Elbrus compiler does not support PCH.') +endif + +exe = executable('prog', 'prog.c', + include_directories: 'include', + c_pch : ['pch/prog_pch.c', 'pch/prog.h']) diff --git a/test cases/common/13 pch/withIncludeDirectories/pch/prog.h b/test cases/common/13 pch/withIncludeDirectories/pch/prog.h new file mode 100644 index 0000000..383b2c5 --- /dev/null +++ b/test cases/common/13 pch/withIncludeDirectories/pch/prog.h @@ -0,0 +1 @@ +#include<lib/lib.h> diff --git a/test cases/common/13 pch/withIncludeDirectories/pch/prog_pch.c b/test cases/common/13 pch/withIncludeDirectories/pch/prog_pch.c new file mode 100644 index 0000000..4960505 --- /dev/null +++ b/test cases/common/13 pch/withIncludeDirectories/pch/prog_pch.c @@ -0,0 +1,5 @@ +#if !defined(_MSC_VER) +#error "This file is only for use with MSVC." +#endif + +#include "prog.h" diff --git a/test cases/common/13 pch/withIncludeDirectories/prog.c b/test cases/common/13 pch/withIncludeDirectories/prog.c new file mode 100644 index 0000000..0ce3d0a --- /dev/null +++ b/test cases/common/13 pch/withIncludeDirectories/prog.c @@ -0,0 +1,10 @@ +// No includes here, they need to come from the PCH + +void func() { + fprintf(stdout, "This is a function that fails if stdio is not #included.\n"); +} + +int main(int argc, char **argv) { + return 0; +} + diff --git a/test cases/fortran/12 submodule/a1.f90 b/test cases/fortran/12 submodule/a1.f90 new file mode 100644 index 0000000..cb44916 --- /dev/null +++ b/test cases/fortran/12 submodule/a1.f90 @@ -0,0 +1,25 @@ +module a1 +implicit none + +interface +module elemental real function pi2tau(pi) + real, intent(in) :: pi +end function pi2tau + +module real function get_pi() +end function get_pi +end interface + +end module a1 + +program hierN + +use a1 + +pi = get_pi() + +tau = pi2tau(pi) + +print *,'pi=',pi,'tau=',tau + +end program diff --git a/test cases/fortran/12 submodule/a2.f90 b/test cases/fortran/12 submodule/a2.f90 new file mode 100644 index 0000000..b3ce1f0 --- /dev/null +++ b/test cases/fortran/12 submodule/a2.f90 @@ -0,0 +1,10 @@ +submodule (a1) a2 + +contains + +module procedure pi2tau + pi2tau = 2*pi +end procedure pi2tau + + +end submodule a2 diff --git a/test cases/fortran/12 submodule/a3.f90 b/test cases/fortran/12 submodule/a3.f90 new file mode 100644 index 0000000..d6929b0 --- /dev/null +++ b/test cases/fortran/12 submodule/a3.f90 @@ -0,0 +1,10 @@ +submodule (a1:a2) a3 + +contains + +module procedure get_pi + get_pi = 4.*atan(1.) +end procedure get_pi + + +end submodule a3 diff --git a/test cases/fortran/12 submodule/child.f90 b/test cases/fortran/12 submodule/child.f90 new file mode 100644 index 0000000..aa5bb5e --- /dev/null +++ b/test cases/fortran/12 submodule/child.f90 @@ -0,0 +1,10 @@ +submodule (mother) daughter + +contains + +module procedure pi2tau + pi2tau = 2*pi +end procedure pi2tau + +end submodule daughter + diff --git a/test cases/fortran/12 submodule/meson.build b/test cases/fortran/12 submodule/meson.build new file mode 100644 index 0000000..cd62a30 --- /dev/null +++ b/test cases/fortran/12 submodule/meson.build @@ -0,0 +1,7 @@ +project('submodule single level', 'fortran') + +hier2 = executable('single', 'parent.f90','child.f90') +test('single-level hierarchy', hier2) + +hierN = executable('multi', 'a1.f90', 'a2.f90', 'a3.f90') +test('multi-level hierarchy', hierN) diff --git a/test cases/fortran/12 submodule/parent.f90 b/test cases/fortran/12 submodule/parent.f90 new file mode 100644 index 0000000..05fe431 --- /dev/null +++ b/test cases/fortran/12 submodule/parent.f90 @@ -0,0 +1,23 @@ +module mother +real, parameter :: pi = 4.*atan(1.) +real :: tau + +interface +module elemental real function pi2tau(pi) + real, intent(in) :: pi +end function pi2tau +end interface + +contains + +end module mother + + +program hier1 +use mother + +tau = pi2tau(pi) + +print *,'pi=',pi, 'tau=', tau + +end program |