meson-0.45.1/0000755000175000017500000000000013254552752014326 5ustar jpakkanejpakkane00000000000000meson-0.45.1/PKG-INFO0000644000175000017500000000206013254552752015421 0ustar jpakkanejpakkane00000000000000Metadata-Version: 1.1 Name: meson Version: 0.45.1 Summary: A high performance build system Home-page: http://mesonbuild.com Author: Jussi Pakkanen Author-email: jpakkane@gmail.com License: Apache License, Version 2.0 Description: Meson is a cross-platform build system designed to be both as fast and as user friendly as possible. It supports many languages and compilers, including GCC, Clang and Visual Studio. Its build definitions are written in a simple non-turing complete DSL. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License Classifier: Natural Language :: English Classifier: Operating System :: MacOS :: MacOS X Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: POSIX :: BSD Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python :: 3 :: Only Classifier: Topic :: Software Development :: Build Tools meson-0.45.1/run_cross_test.py0000755000175000017500000000340213026303756017751 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 # Copyright 2013-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. '''Runs the basic test suite through a cross compiler. Not part of the main test suite because of two reasons: 1) setup of the cross build is platform specific 2) it can be slow (e.g. when invoking test apps via wine) Eventually migrate to something fancier.''' import sys, os from run_project_tests import gather_tests, run_tests, StopException, setup_commands from run_project_tests import failing_logs def runtests(cross_file): commontests = [('common', gather_tests('test cases/common'), False)] try: (passing_tests, failing_tests, skipped_tests) = run_tests(commontests, 'meson-cross-test-run', ['--cross', cross_file]) except StopException: pass print('\nTotal passed cross tests:', passing_tests) print('Total failed cross tests:', failing_tests) print('Total skipped cross tests:', skipped_tests) if failing_tests > 0 and ('TRAVIS' in os.environ or 'APPVEYOR' in os.environ): print('\nMesonlogs of failing tests\n') for l in failing_logs: print(l, '\n') sys.exit(failing_tests) if __name__ == '__main__': setup_commands('ninja') cross_file = sys.argv[1] runtests(cross_file) meson-0.45.1/run_project_tests.py0000755000175000017500000006710313254550710020456 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 # Copyright 2012-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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 glob import glob import itertools import os, subprocess, shutil, sys, signal from io import StringIO from ast import literal_eval from enum import Enum import tempfile from mesonbuild import mtest from mesonbuild import environment from mesonbuild import mesonlib from mesonbuild import mlog from mesonbuild.mesonlib import stringlistify, Popen_safe from mesonbuild.coredata import backendlist import argparse import xml.etree.ElementTree as ET import time import multiprocessing from concurrent.futures import ProcessPoolExecutor import re from run_unittests import get_fake_options, run_configure from run_tests import get_backend_commands, get_backend_args_for_dir, Backend from run_tests import ensure_backend_detects_changes class BuildStep(Enum): configure = 1 build = 2 test = 3 install = 4 clean = 5 validate = 6 class TestResult: def __init__(self, msg, step, stdo, stde, mlog, conftime=0, buildtime=0, testtime=0): self.msg = msg self.step = step self.stdo = stdo self.stde = stde self.mlog = mlog self.conftime = conftime self.buildtime = buildtime self.testtime = testtime class AutoDeletedDir: def __init__(self, d): self.dir = d def __enter__(self): os.makedirs(self.dir, exist_ok=True) return self.dir def __exit__(self, _type, value, traceback): # We don't use tempfile.TemporaryDirectory, but wrap the # deletion in the AutoDeletedDir class because # it fails on Windows due antivirus programs # holding files open. mesonlib.windows_proof_rmtree(self.dir) failing_logs = [] print_debug = 'MESON_PRINT_TEST_OUTPUT' in os.environ under_ci = not {'TRAVIS', 'APPVEYOR'}.isdisjoint(os.environ) do_debug = under_ci or print_debug no_meson_log_msg = 'No meson-log.txt found.' system_compiler = None meson_command = os.path.join(os.getcwd(), 'meson') if not os.path.exists(meson_command): meson_command += '.py' if not os.path.exists(meson_command): raise RuntimeError('Could not find main Meson script to run.') class StopException(Exception): def __init__(self): super().__init__('Stopped by user') stop = False def stop_handler(signal, frame): global stop stop = True signal.signal(signal.SIGINT, stop_handler) signal.signal(signal.SIGTERM, stop_handler) def setup_commands(optbackend): global do_debug, backend, backend_flags global compile_commands, clean_commands, test_commands, install_commands, uninstall_commands backend = optbackend msbuild_exe = shutil.which('msbuild') # Auto-detect backend if unspecified if backend is None: if msbuild_exe is not None: backend = 'vs' # Meson will auto-detect VS version to use elif mesonlib.is_osx(): backend = 'xcode' else: backend = 'ninja' # Set backend arguments for Meson if backend.startswith('vs'): backend_flags = ['--backend=' + backend] backend = Backend.vs elif backend == 'xcode': backend_flags = ['--backend=xcode'] backend = Backend.xcode elif backend == 'ninja': backend_flags = ['--backend=ninja'] backend = Backend.ninja else: raise RuntimeError('Unknown backend: {!r}'.format(backend)) compile_commands, clean_commands, test_commands, install_commands, \ uninstall_commands = get_backend_commands(backend, do_debug) def get_relative_files_list_from_dir(fromdir): paths = [] for (root, _, files) in os.walk(fromdir): reldir = os.path.relpath(root, start=fromdir) for f in files: path = os.path.join(reldir, f).replace('\\', '/') if path.startswith('./'): path = path[2:] paths.append(path) return paths def platform_fix_name(fname, compiler): if '?lib' in fname: if mesonlib.is_cygwin(): fname = re.sub(r'lib/\?lib(.*)\.so$', r'bin/cyg\1.dll', fname) fname = re.sub(r'\?lib(.*)\.dll$', r'cyg\1.dll', fname) else: fname = re.sub(r'\?lib', 'lib', fname) if fname.endswith('?exe'): fname = fname[:-4] if mesonlib.is_windows() or mesonlib.is_cygwin(): return fname + '.exe' if fname.startswith('?msvc:'): fname = fname[6:] if compiler != 'cl': return None if fname.startswith('?gcc:'): fname = fname[5:] if compiler == 'cl': return None return fname def validate_install(srcdir, installdir, compiler): # List of installed files info_file = os.path.join(srcdir, 'installed_files.txt') # If this exists, the test does not install any other files noinst_file = 'usr/no-installed-files' expected = {} ret_msg = '' # Generate list of expected files if os.path.exists(os.path.join(installdir, noinst_file)): expected[noinst_file] = False elif os.path.exists(info_file): with open(info_file) as f: for line in f: line = platform_fix_name(line.strip(), compiler) if line: expected[line] = False # Check if expected files were found for fname in expected: file_path = os.path.join(installdir, fname) if os.path.exists(file_path) or os.path.islink(file_path): expected[fname] = True for (fname, found) in expected.items(): if not found: # Ignore missing PDB files if we aren't using cl if fname.endswith('.pdb') and compiler != 'cl': continue ret_msg += 'Expected file {0} missing.\n'.format(fname) # Check if there are any unexpected files found = get_relative_files_list_from_dir(installdir) for fname in found: # Windows-specific tests check for the existence of installed PDB # files, but common tests do not, for obvious reasons. Ignore any # extra PDB files found. if fname not in expected and not fname.endswith('.pdb') and compiler == 'cl': ret_msg += 'Extra file {0} found.\n'.format(fname) return ret_msg def log_text_file(logfile, testdir, stdo, stde): global stop, executor, futures logfile.write('%s\nstdout\n\n---\n' % testdir) logfile.write(stdo) logfile.write('\n\n---\n\nstderr\n\n---\n') logfile.write(stde) logfile.write('\n\n---\n\n') if print_debug: print(stdo) print(stde, file=sys.stderr) if stop: print("Aborting..") for f in futures: f[2].cancel() executor.shutdown() raise StopException() def bold(text): return mlog.bold(text).get_text(mlog.colorize_console) def green(text): return mlog.green(text).get_text(mlog.colorize_console) def red(text): return mlog.red(text).get_text(mlog.colorize_console) def yellow(text): return mlog.yellow(text).get_text(mlog.colorize_console) def run_test_inprocess(testdir): old_stdout = sys.stdout sys.stdout = mystdout = StringIO() old_stderr = sys.stderr sys.stderr = mystderr = StringIO() old_cwd = os.getcwd() os.chdir(testdir) test_log_fname = 'meson-logs/testlog.txt' try: returncode_test = mtest.run(['--no-rebuild']) if os.path.exists(test_log_fname): test_log = open(test_log_fname, errors='ignore').read() else: test_log = '' returncode_benchmark = mtest.run(['--no-rebuild', '--benchmark', '--logbase', 'benchmarklog']) finally: sys.stdout = old_stdout sys.stderr = old_stderr os.chdir(old_cwd) return max(returncode_test, returncode_benchmark), mystdout.getvalue(), mystderr.getvalue(), test_log def parse_test_args(testdir): args = [] try: with open(os.path.join(testdir, 'test_args.txt'), 'r') as f: content = f.read() try: args = literal_eval(content) except Exception: raise Exception('Malformed test_args file.') args = stringlistify(args) except FileNotFoundError: pass return args # Build directory name must be the same so CCache works over # consecutive invocations. def create_deterministic_builddir(src_dir): import hashlib rel_dirname = 'b ' + hashlib.sha256(src_dir.encode(errors='ignore')).hexdigest()[0:10] os.mkdir(rel_dirname) abs_pathname = os.path.join(os.getcwd(), rel_dirname) return abs_pathname def run_test(skipped, testdir, extra_args, compiler, backend, flags, commands, should_fail): if skipped: return None with AutoDeletedDir(create_deterministic_builddir(testdir)) as build_dir: with AutoDeletedDir(tempfile.mkdtemp(prefix='i ', dir=os.getcwd())) as install_dir: try: return _run_test(testdir, build_dir, install_dir, extra_args, compiler, backend, flags, commands, should_fail) finally: mlog.shutdown() # Close the log file because otherwise Windows wets itself. def pass_prefix_to_test(dirname): if '40 prefix' in dirname: return False return True def pass_libdir_to_test(dirname): if '8 install' in dirname: return False if '39 libdir' in dirname: return False return True def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backend, flags, commands, should_fail): compile_commands, clean_commands, install_commands, uninstall_commands = commands test_args = parse_test_args(testdir) gen_start = time.time() # Configure in-process if pass_prefix_to_test(testdir): gen_args = ['--prefix', '/usr'] else: gen_args = [] if pass_libdir_to_test(testdir): gen_args += ['--libdir', 'lib'] gen_args += [testdir, test_build_dir] + flags + test_args + extra_args (returncode, stdo, stde) = run_configure(meson_command, gen_args) try: logfile = os.path.join(test_build_dir, 'meson-logs/meson-log.txt') with open(logfile, errors='ignore') as f: mesonlog = f.read() except Exception: mesonlog = no_meson_log_msg gen_time = time.time() - gen_start if should_fail == 'meson': if returncode == 1: return TestResult('', BuildStep.configure, stdo, stde, mesonlog, gen_time) elif returncode != 0: return TestResult('Test exited with unexpected status {}'.format(returncode), BuildStep.configure, stdo, stde, mesonlog, gen_time) else: return TestResult('Test that should have failed succeeded', BuildStep.configure, stdo, stde, mesonlog, gen_time) if returncode != 0: return TestResult('Generating the build system failed.', BuildStep.configure, stdo, stde, mesonlog, gen_time) # Touch the meson.build file to force a regenerate so we can test that # regeneration works before a build is run. ensure_backend_detects_changes(backend) os.utime(os.path.join(testdir, 'meson.build')) # Build with subprocess dir_args = get_backend_args_for_dir(backend, test_build_dir) build_start = time.time() pc, o, e = Popen_safe(compile_commands + dir_args, cwd=test_build_dir) build_time = time.time() - build_start stdo += o stde += e if should_fail == 'build': if pc.returncode != 0: return TestResult('', BuildStep.build, stdo, stde, mesonlog, gen_time) return TestResult('Test that should have failed to build succeeded', BuildStep.build, stdo, stde, mesonlog, gen_time) if pc.returncode != 0: return TestResult('Compiling source code failed.', BuildStep.build, stdo, stde, mesonlog, gen_time, build_time) # Touch the meson.build file to force a regenerate so we can test that # regeneration works after a build is complete. ensure_backend_detects_changes(backend) os.utime(os.path.join(testdir, 'meson.build')) test_start = time.time() # Test in-process (returncode, tstdo, tstde, test_log) = run_test_inprocess(test_build_dir) test_time = time.time() - test_start stdo += tstdo stde += tstde mesonlog += test_log if should_fail == 'test': if returncode != 0: return TestResult('', BuildStep.test, stdo, stde, mesonlog, gen_time) return TestResult('Test that should have failed to run unit tests succeeded', BuildStep.test, stdo, stde, mesonlog, gen_time) if returncode != 0: return TestResult('Running unit tests failed.', BuildStep.test, stdo, stde, mesonlog, gen_time, build_time, test_time) # Do installation, if the backend supports it if install_commands: env = os.environ.copy() env['DESTDIR'] = install_dir # Install with subprocess pi, o, e = Popen_safe(install_commands, cwd=test_build_dir, env=env) stdo += o stde += e if pi.returncode != 0: return TestResult('Running install failed.', BuildStep.install, stdo, stde, mesonlog, gen_time, build_time, test_time) # Clean with subprocess env = os.environ.copy() pi, o, e = Popen_safe(clean_commands + dir_args, cwd=test_build_dir, env=env) stdo += o stde += e if pi.returncode != 0: return TestResult('Running clean failed.', BuildStep.clean, stdo, stde, mesonlog, gen_time, build_time, test_time) if not install_commands: return TestResult('', BuildStep.install, '', '', mesonlog, gen_time, build_time, test_time) return TestResult(validate_install(testdir, install_dir, compiler), BuildStep.validate, stdo, stde, mesonlog, gen_time, build_time, test_time) def gather_tests(testdir): tests = [t.replace('\\', '/').split('/', 2)[2] for t in glob(testdir + '/*')] testlist = [(int(t.split()[0]), t) for t in tests] testlist.sort() tests = [os.path.join(testdir, t[1]) for t in testlist] return tests def have_d_compiler(): if shutil.which("ldc2"): return True elif shutil.which("ldc"): return True elif shutil.which("gdc"): return True elif shutil.which("dmd"): return True return False def have_objc_compiler(): with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir: env = environment.Environment(None, build_dir, None, get_fake_options('/'), []) try: objc_comp = env.detect_objc_compiler(False) except mesonlib.MesonException: return False if not objc_comp: return False try: objc_comp.sanity_check(env.get_scratch_dir(), env) except mesonlib.MesonException: return False return True def have_objcpp_compiler(): with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir: env = environment.Environment(None, build_dir, None, get_fake_options('/'), []) try: objcpp_comp = env.detect_objcpp_compiler(False) except mesonlib.MesonException: return False if not objcpp_comp: return False try: objcpp_comp.sanity_check(env.get_scratch_dir(), env) except mesonlib.MesonException: return False return True def have_java(): if shutil.which('javac') and shutil.which('java'): return True return False def skippable(suite, test): if not under_ci: return True if not suite.endswith('frameworks'): return True # gtk-doc test may be skipped, pending upstream fixes for spaces in # filenames landing in the distro used for CI if test.endswith('10 gtk-doc'): return True # No frameworks test should be skipped on linux CI, as we expect all # prerequisites to be installed if mesonlib.is_linux(): return False # Boost test should only be skipped for windows CI build matrix entries # which don't define BOOST_ROOT if test.endswith('1 boost'): if mesonlib.is_windows(): return 'BOOST_ROOT' not in os.environ return False # Other framework tests are allowed to be skipped on other platforms return True def skip_csharp(backend): if backend is not Backend.ninja: return True if not shutil.which('resgen'): return True if shutil.which('mcs'): return False if shutil.which('csc'): # Only support VS2017 for now. Earlier versions fail # under CI in mysterious ways. try: stdo = subprocess.check_output(['csc', '/version']) except subprocess.CalledProcessError: return True # Having incrementing version numbers would be too easy. # Microsoft reset the versioning back to 1.0 (from 4.x) # when they got the Roslyn based compiler. Thus there # is NO WAY to reliably do version number comparisons. # Only support the version that ships with VS2017. return not stdo.startswith(b'2.') return True def detect_tests_to_run(): # Name, subdirectory, skip condition. all_tests = [ ('common', 'common', False), ('failing-meson', 'failing', False), ('failing-build', 'failing build', False), ('failing-tests', 'failing tests', False), ('platform-osx', 'osx', not mesonlib.is_osx()), ('platform-windows', 'windows', not mesonlib.is_windows() and not mesonlib.is_cygwin()), ('platform-linux', 'linuxlike', mesonlib.is_osx() or mesonlib.is_windows()), ('java', 'java', backend is not Backend.ninja or mesonlib.is_osx() or not have_java()), ('C#', 'csharp', skip_csharp(backend)), ('vala', 'vala', backend is not Backend.ninja or not shutil.which('valac')), ('rust', 'rust', backend is not Backend.ninja or not shutil.which('rustc')), ('d', 'd', backend is not Backend.ninja or not have_d_compiler()), ('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or mesonlib.is_windows() or not have_objc_compiler()), ('objective c++', 'objcpp', backend not in (Backend.ninja, Backend.xcode) or mesonlib.is_windows() or not have_objcpp_compiler()), ('fortran', 'fortran', backend is not Backend.ninja or not shutil.which('gfortran')), ('swift', 'swift', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('swiftc')), ('python3', 'python3', backend is not Backend.ninja), ('fpga', 'fpga', shutil.which('yosys') is None), ('frameworks', 'frameworks', False), ] gathered_tests = [(name, gather_tests('test cases/' + subdir), skip) for name, subdir, skip in all_tests] return gathered_tests def run_tests(all_tests, log_name_base, extra_args): global logfile txtname = log_name_base + '.txt' with open(txtname, 'w', encoding="utf_8") as lf: logfile = lf return _run_tests(all_tests, log_name_base, extra_args) def _run_tests(all_tests, log_name_base, extra_args): global stop, executor, futures, system_compiler xmlname = log_name_base + '.xml' junit_root = ET.Element('testsuites') conf_time = 0 build_time = 0 test_time = 0 passing_tests = 0 failing_tests = 0 skipped_tests = 0 commands = (compile_commands, clean_commands, install_commands, uninstall_commands) try: # This fails in some CI environments for unknown reasons. num_workers = multiprocessing.cpu_count() except Exception as e: print('Could not determine number of CPUs due to the following reason:' + str(e)) print('Defaulting to using only one process') num_workers = 1 # Due to Ninja deficiency, almost 50% of build time # is spent waiting. Do something useful instead. # # Remove this once the following issue has been resolved: # https://github.com/mesonbuild/meson/pull/2082 num_workers *= 2 executor = ProcessPoolExecutor(max_workers=num_workers) for name, test_cases, skipped in all_tests: current_suite = ET.SubElement(junit_root, 'testsuite', {'name': name, 'tests': str(len(test_cases))}) print() if skipped: print(bold('Not running %s tests.' % name)) else: print(bold('Running %s tests.' % name)) print() futures = [] for t in test_cases: # Jenkins screws us over by automatically sorting test cases by name # and getting it wrong by not doing logical number sorting. (testnum, testbase) = os.path.split(t)[-1].split(' ', 1) testname = '%.3d %s' % (int(testnum), testbase) should_fail = False if name.startswith('failing'): should_fail = name.split('failing-')[1] result = executor.submit(run_test, skipped, t, extra_args, system_compiler, backend, backend_flags, commands, should_fail) futures.append((testname, t, result)) for (testname, t, result) in futures: sys.stdout.flush() result = result.result() if (result is None) or (('MESON_SKIP_TEST' in result.stdo) and (skippable(name, t))): print(yellow('Skipping:'), t) current_test = ET.SubElement(current_suite, 'testcase', {'name': testname, 'classname': name}) ET.SubElement(current_test, 'skipped', {}) skipped_tests += 1 else: without_install = "" if len(install_commands) > 0 else " (without install)" if result.msg != '': print(red('Failed test{} during {}: {!r}'.format(without_install, result.step.name, t))) print('Reason:', result.msg) failing_tests += 1 if result.step == BuildStep.configure and result.mlog != no_meson_log_msg: # For configure failures, instead of printing stdout, # print the meson log if available since it's a superset # of stdout and often has very useful information. failing_logs.append(result.mlog) else: failing_logs.append(result.stdo) failing_logs.append(result.stde) else: print('Succeeded test%s: %s' % (without_install, t)) passing_tests += 1 conf_time += result.conftime build_time += result.buildtime test_time += result.testtime total_time = conf_time + build_time + test_time log_text_file(logfile, t, result.stdo, result.stde) current_test = ET.SubElement(current_suite, 'testcase', {'name': testname, 'classname': name, 'time': '%.3f' % total_time}) if result.msg != '': ET.SubElement(current_test, 'failure', {'message': result.msg}) stdoel = ET.SubElement(current_test, 'system-out') stdoel.text = result.stdo stdeel = ET.SubElement(current_test, 'system-err') stdeel.text = result.stde print("\nTotal configuration time: %.2fs" % conf_time) print("Total build time: %.2fs" % build_time) print("Total test time: %.2fs" % test_time) ET.ElementTree(element=junit_root).write(xmlname, xml_declaration=True, encoding='UTF-8') return passing_tests, failing_tests, skipped_tests def check_file(fname): linenum = 1 with open(fname, 'rb') as f: lines = f.readlines() for line in lines: if line.startswith(b'\t'): print("File %s contains a literal tab on line %d. Only spaces are permitted." % (fname, linenum)) sys.exit(1) if b'\r' in line: print("File %s contains DOS line ending on line %d. Only unix-style line endings are permitted." % (fname, linenum)) sys.exit(1) linenum += 1 def check_format(): for (root, _, files) in os.walk('.'): for file in files: if file.endswith('.py') or file.endswith('.build') or file == 'meson_options.txt': fullname = os.path.join(root, file) check_file(fullname) def check_meson_commands_work(): global backend, meson_command, compile_commands, test_commands, install_commands testdir = 'test cases/common/1 trivial' with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir: print('Checking that configuring works...') gen_cmd = mesonlib.meson_command + [testdir, build_dir] + backend_flags pc, o, e = Popen_safe(gen_cmd) if pc.returncode != 0: raise RuntimeError('Failed to configure {!r}:\n{}\n{}'.format(testdir, e, o)) print('Checking that building works...') dir_args = get_backend_args_for_dir(backend, build_dir) pc, o, e = Popen_safe(compile_commands + dir_args, cwd=build_dir) if pc.returncode != 0: raise RuntimeError('Failed to build {!r}:\n{}\n{}'.format(testdir, e, o)) print('Checking that testing works...') pc, o, e = Popen_safe(test_commands, cwd=build_dir) if pc.returncode != 0: raise RuntimeError('Failed to test {!r}:\n{}\n{}'.format(testdir, e, o)) if install_commands: print('Checking that installing works...') pc, o, e = Popen_safe(install_commands, cwd=build_dir) if pc.returncode != 0: raise RuntimeError('Failed to install {!r}:\n{}\n{}'.format(testdir, e, o)) def detect_system_compiler(): global system_compiler if shutil.which('cl'): system_compiler = 'cl' elif shutil.which('cc'): system_compiler = 'cc' elif shutil.which('gcc'): system_compiler = 'gcc' else: raise RuntimeError("Could not find C compiler.") if __name__ == '__main__': parser = argparse.ArgumentParser(description="Run the test suite of Meson.") parser.add_argument('extra_args', nargs='*', help='arguments that are passed directly to Meson (remember to have -- before these).') parser.add_argument('--backend', default=None, dest='backend', choices=backendlist) options = parser.parse_args() setup_commands(options.backend) detect_system_compiler() script_dir = os.path.split(__file__)[0] if script_dir != '': os.chdir(script_dir) check_format() check_meson_commands_work() try: all_tests = detect_tests_to_run() (passing_tests, failing_tests, skipped_tests) = run_tests(all_tests, 'meson-test-run', options.extra_args) except StopException: pass print('\nTotal passed tests:', green(str(passing_tests))) print('Total failed tests:', red(str(failing_tests))) print('Total skipped tests:', yellow(str(skipped_tests))) if failing_tests > 0: print('\nMesonlogs of failing tests\n') for l in failing_logs: print(l, '\n') for name, dirs, skip in all_tests: dirs = (os.path.basename(x) for x in dirs) for k, g in itertools.groupby(dirs, key=lambda x: x.split()[0]): tests = list(g) if len(tests) != 1: print('WARNING: The %s suite contains duplicate "%s" tests: "%s"' % (name, k, '", "'.join(tests))) sys.exit(failing_tests) meson-0.45.1/ghwt.py0000755000175000017500000000760113254550710015650 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 # Copyright 2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. # ghwt - GitHub WrapTool # # An emergency wraptool(1) replacement downloader that downloads # directly from GitHub in case wrapdb.mesonbuild.com is down. import urllib.request, json, sys, os, shutil, subprocess import configparser, hashlib private_repos = {'meson', 'wrapweb', 'meson-ci'} def gh_get(url): r = urllib.request.urlopen(url) jd = json.loads(r.read().decode('utf-8')) return jd def list_projects(): jd = gh_get('https://api.github.com/orgs/mesonbuild/repos') entries = [entry['name'] for entry in jd] entries = [e for e in entries if e not in private_repos] entries.sort() for i in entries: print(i) return 0 def unpack(sproj, branch, outdir): subprocess.check_call(['git', 'clone', '-b', branch, 'https://github.com/mesonbuild/%s.git' % sproj, outdir]) usfile = os.path.join(outdir, 'upstream.wrap') assert(os.path.isfile(usfile)) config = configparser.ConfigParser() config.read(usfile) us_url = config['wrap-file']['source_url'] us = urllib.request.urlopen(us_url).read() h = hashlib.sha256() h.update(us) dig = h.hexdigest() should = config['wrap-file']['source_hash'] if dig != should: print('Incorrect hash on download.') print(' expected:', dig) print(' obtained:', should) return 1 spdir = os.path.split(outdir)[0] ofilename = os.path.join(spdir, config['wrap-file']['source_filename']) with open(ofilename, 'wb') as ofile: ofile.write(us) if 'lead_directory_missing' in config['wrap-file']: os.mkdir(outdir) shutil.unpack_archive(ofilename, outdir) else: shutil.unpack_archive(ofilename, spdir) extdir = os.path.join(spdir, config['wrap-file']['directory']) assert(os.path.isdir(extdir)) shutil.move(os.path.join(outdir, '.git'), extdir) subprocess.check_call(['git', 'reset', '--hard'], cwd=extdir) shutil.rmtree(outdir) shutil.move(extdir, outdir) shutil.rmtree(os.path.join(outdir, '.git')) os.unlink(ofilename) def install(sproj): sproj_dir = os.path.join('subprojects', sproj) if not os.path.isdir('subprojects'): print('Run this in your source root and make sure there is a subprojects directory in it.') return 1 if os.path.isdir(sproj_dir): print('Subproject is already there. To update, nuke the dir and reinstall.') return 1 blist = gh_get('https://api.github.com/repos/mesonbuild/%s/branches' % sproj) blist = [b['name'] for b in blist] blist = [b for b in blist if b != 'master'] blist.sort() branch = blist[-1] print('Using branch', branch) return unpack(sproj, branch, sproj_dir) def run(args): if not args or args[0] == '-h' or args[0] == '--help': print(sys.argv[0], 'list/install', 'package_name') return 1 command = args[0] args = args[1:] if command == 'list': list_projects() return 0 elif command == 'install': if len(args) != 1: print('Install requires exactly one argument.') return 1 return install(args[0]) else: print('Unknown command') return 1 if __name__ == '__main__': print('This is an emergency wrap downloader. Use only when wrapdb is down.') sys.exit(run(sys.argv[1:])) meson-0.45.1/mesonbuild/0000755000175000017500000000000013254552745016471 5ustar jpakkanejpakkane00000000000000meson-0.45.1/mesonbuild/modules/0000755000175000017500000000000013254552746020142 5ustar jpakkanejpakkane00000000000000meson-0.45.1/mesonbuild/modules/qt5.py0000644000175000017500000000202413174155432021213 0ustar jpakkanejpakkane00000000000000# Copyright 2015 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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 .. import mlog from .qt import QtBaseModule from . import ExtensionModule class Qt5Module(ExtensionModule, QtBaseModule): def __init__(self): QtBaseModule.__init__(self, qt_version=5) ExtensionModule.__init__(self) def initialize(): mlog.warning('rcc dependencies will not work reliably until this upstream issue is fixed:', mlog.bold('https://bugreports.qt.io/browse/QTBUG-45460')) return Qt5Module() meson-0.45.1/mesonbuild/modules/rpm.py0000644000175000017500000001644513174155420021311 0ustar jpakkanejpakkane00000000000000# Copyright 2015 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. '''This module provides helper functions for RPM related functionality such as generating template RPM spec file.''' from .. import build from .. import compilers import datetime from .. import mlog from . import GirTarget, TypelibTarget from . import ModuleReturnValue from . import ExtensionModule from ..interpreterbase import noKwargs import os class RPMModule(ExtensionModule): @noKwargs def generate_spec_template(self, state, args, kwargs): compiler_deps = set() for compiler in state.compilers.values(): if isinstance(compiler, compilers.GnuCCompiler): compiler_deps.add('gcc') elif isinstance(compiler, compilers.GnuCPPCompiler): compiler_deps.add('gcc-c++') elif isinstance(compiler, compilers.ValaCompiler): compiler_deps.add('vala') elif isinstance(compiler, compilers.GnuFortranCompiler): compiler_deps.add('gcc-gfortran') elif isinstance(compiler, compilers.GnuObjCCompiler): compiler_deps.add('gcc-objc') elif compiler == compilers.GnuObjCPPCompiler: compiler_deps.add('gcc-objc++') else: mlog.log('RPM spec file will not created, generating not allowed for:', mlog.bold(compiler.get_id())) return proj = state.project_name.replace(' ', '_').replace('\t', '_') so_installed = False devel_subpkg = False files = set() files_devel = set() to_delete = set() for target in state.targets.values(): if isinstance(target, build.Executable) and target.need_install: files.add('%%{_bindir}/%s' % target.get_filename()) elif isinstance(target, build.SharedLibrary) and target.need_install: files.add('%%{_libdir}/%s' % target.get_filename()) for alias in target.get_aliases(): if alias.endswith('.so'): files_devel.add('%%{_libdir}/%s' % alias) else: files.add('%%{_libdir}/%s' % alias) so_installed = True elif isinstance(target, build.StaticLibrary) and target.need_install: to_delete.add('%%{buildroot}%%{_libdir}/%s' % target.get_filename()) mlog.warning('removing', mlog.bold(target.get_filename()), 'from package because packaging static libs not recommended') elif isinstance(target, GirTarget) and target.should_install(): files_devel.add('%%{_datadir}/gir-1.0/%s' % target.get_filename()[0]) elif isinstance(target, TypelibTarget) and target.should_install(): files.add('%%{_libdir}/girepository-1.0/%s' % target.get_filename()[0]) for header in state.headers: if len(header.get_install_subdir()) > 0: files_devel.add('%%{_includedir}/%s/' % header.get_install_subdir()) else: for hdr_src in header.get_sources(): files_devel.add('%%{_includedir}/%s' % hdr_src) for man in state.man: for man_file in man.get_sources(): files.add('%%{_mandir}/man%u/%s.*' % (int(man_file.split('.')[-1]), man_file)) if len(files_devel) > 0: devel_subpkg = True filename = os.path.join(state.environment.get_build_dir(), '%s.spec' % proj) with open(filename, 'w+') as fn: fn.write('Name: %s\n' % proj) fn.write('Version: # FIXME\n') fn.write('Release: 1%{?dist}\n') fn.write('Summary: # FIXME\n') fn.write('License: # FIXME\n') fn.write('\n') fn.write('Source0: %{name}-%{version}.tar.xz # FIXME\n') fn.write('\n') for compiler in compiler_deps: fn.write('BuildRequires: %s\n' % compiler) for dep in state.environment.coredata.deps: fn.write('BuildRequires: pkgconfig(%s)\n' % dep[0]) for lib in state.environment.coredata.ext_libs.values(): name = lib.get_name() fn.write('BuildRequires: {} # FIXME\n'.format(name)) mlog.warning('replace', mlog.bold(name), 'with the real package.', 'You can use following command to find package which ' 'contains this lib:', mlog.bold("dnf provides '*/lib{}.so'".format(name))) for prog in state.environment.coredata.ext_progs.values(): if not prog.found(): fn.write('BuildRequires: %%{_bindir}/%s # FIXME\n' % prog.get_name()) else: fn.write('BuildRequires: {}\n'.format(prog.get_path())) fn.write('BuildRequires: meson\n') fn.write('\n') fn.write('%description\n') fn.write('\n') if devel_subpkg: fn.write('%package devel\n') fn.write('Summary: Development files for %{name}\n') fn.write('Requires: %{name}%{?_isa} = %{?epoch:%{epoch}:}{version}-%{release}\n') fn.write('\n') fn.write('%description devel\n') fn.write('Development files for %{name}.\n') fn.write('\n') fn.write('%prep\n') fn.write('%autosetup\n') fn.write('\n') fn.write('%build\n') fn.write('%meson\n') fn.write('%meson_build\n') fn.write('\n') fn.write('%install\n') fn.write('%meson_install\n') if len(to_delete) > 0: fn.write('rm -vf %s\n' % ' '.join(to_delete)) fn.write('\n') fn.write('%check\n') fn.write('%meson_test\n') fn.write('\n') fn.write('%files\n') for f in files: fn.write('%s\n' % f) fn.write('\n') if devel_subpkg: fn.write('%files devel\n') for f in files_devel: fn.write('%s\n' % f) fn.write('\n') if so_installed: fn.write('%post -p /sbin/ldconfig\n') fn.write('%postun -p /sbin/ldconfig\n') fn.write('\n') fn.write('%changelog\n') fn.write('* %s meson - \n' % datetime.date.today().strftime('%a %b %d %Y')) fn.write('- \n') fn.write('\n') mlog.log('RPM spec template written to %s.spec.\n' % proj) return ModuleReturnValue(None, []) def initialize(): return RPMModule() meson-0.45.1/mesonbuild/modules/qt4.py0000644000175000017500000000202413174155432021212 0ustar jpakkanejpakkane00000000000000# Copyright 2015 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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 .. import mlog from .qt import QtBaseModule from . import ExtensionModule class Qt4Module(ExtensionModule, QtBaseModule): def __init__(self): QtBaseModule.__init__(self, qt_version=4) ExtensionModule.__init__(self) def initialize(): mlog.warning('rcc dependencies will not work properly until this upstream issue is fixed:', mlog.bold('https://bugreports.qt.io/browse/QTBUG-45460')) return Qt4Module() meson-0.45.1/mesonbuild/modules/unstable_simd.py0000644000175000017500000000667313174155420023346 0ustar jpakkanejpakkane00000000000000# Copyright 2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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 .. import mesonlib, compilers, mlog from . import ExtensionModule class SimdModule(ExtensionModule): def __init__(self): super().__init__() self.snippets.add('check') # FIXME add Altivec and AVX512. self.isets = ('mmx', 'sse', 'sse2', 'sse3', 'ssse3', 'sse41', 'sse42', 'avx', 'avx2', 'neon', ) def check(self, interpreter, state, args, kwargs): result = [] if len(args) != 1: raise mesonlib.MesonException('Check requires one argument, a name prefix for checks.') prefix = args[0] if not isinstance(prefix, str): raise mesonlib.MesonException('Argument must be a string.') if 'compiler' not in kwargs: raise mesonlib.MesonException('Must specify compiler keyword') if 'sources' in kwargs: raise mesonlib.MesonException('SIMD module does not support the "sources" keyword') basic_kwargs = {} for key, value in kwargs.items(): if key not in self.isets and key != 'compiler': basic_kwargs[key] = value compiler = kwargs['compiler'].compiler if not isinstance(compiler, compilers.compilers.Compiler): raise mesonlib.MesonException('Compiler argument must be a compiler object.') cdata = interpreter.func_configuration_data(None, [], {}) conf = cdata.held_object for iset in self.isets: if iset not in kwargs: continue iset_fname = kwargs[iset] # Migth also be an array or Files. static_library will validate. args = compiler.get_instruction_set_args(iset) if args is None: mlog.log('Compiler supports %s:' % iset, mlog.red('NO')) continue if len(args) > 0: if not compiler.has_multi_arguments(args, state.environment): mlog.log('Compiler supports %s:' % iset, mlog.red('NO')) continue mlog.log('Compiler supports %s:' % iset, mlog.green('YES')) conf.values['HAVE_' + iset.upper()] = ('1', 'Compiler supports %s.' % iset) libname = prefix + '_' + iset lib_kwargs = {'sources': iset_fname, } lib_kwargs.update(basic_kwargs) langarg_key = compiler.get_language() + '_args' old_lang_args = mesonlib.extract_as_list(lib_kwargs, langarg_key) all_lang_args = old_lang_args + args lib_kwargs[langarg_key] = all_lang_args result.append(interpreter.func_static_lib(None, [libname], lib_kwargs)) return [result, cdata] def initialize(): return SimdModule() meson-0.45.1/mesonbuild/modules/windows.py0000644000175000017500000001075613243342167022207 0ustar jpakkanejpakkane00000000000000# Copyright 2015 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os from .. import mlog from .. import mesonlib, dependencies, build from ..mesonlib import MesonException, extract_as_list from . import get_include_args from . import ModuleReturnValue from . import ExtensionModule from ..interpreterbase import permittedKwargs class WindowsModule(ExtensionModule): def detect_compiler(self, compilers): for l in ('c', 'cpp'): if l in compilers: return compilers[l] raise MesonException('Resource compilation requires a C or C++ compiler.') @permittedKwargs({'args', 'include_directories'}) def compile_resources(self, state, args, kwargs): comp = self.detect_compiler(state.compilers) extra_args = mesonlib.stringlistify(kwargs.get('args', [])) inc_dirs = extract_as_list(kwargs, 'include_directories', pop = True) for incd in inc_dirs: if not isinstance(incd.held_object, (str, build.IncludeDirs)): raise MesonException('Resource include dirs should be include_directories().') extra_args += get_include_args(inc_dirs) if comp.id == 'msvc': rescomp = dependencies.ExternalProgram('rc', silent=True) res_args = extra_args + ['/nologo', '/fo@OUTPUT@', '@INPUT@'] suffix = 'res' else: m = 'Argument {!r} has a space which may not work with windres due to ' \ 'a MinGW bug: https://sourceware.org/bugzilla/show_bug.cgi?id=4933' for arg in extra_args: if ' ' in arg: mlog.warning(m.format(arg)) rescomp_name = None # FIXME: Does not handle `native: true` executables, see # https://github.com/mesonbuild/meson/issues/1531 if state.environment.is_cross_build(): # If cross compiling see if windres has been specified in the # cross file before trying to find it another way. rescomp_name = state.environment.cross_info.config['binaries'].get('windres') if rescomp_name is None: # Pick-up env var WINDRES if set. This is often used for # specifying an arch-specific windres. rescomp_name = os.environ.get('WINDRES', 'windres') rescomp = dependencies.ExternalProgram(rescomp_name, silent=True) res_args = extra_args + ['@INPUT@', '@OUTPUT@'] suffix = 'o' if not rescomp.found(): raise MesonException('Could not find Windows resource compiler %s.' % ' '.join(rescomp.get_command())) res_targets = [] def add_target(src): if isinstance(src, list): for subsrc in src: add_target(subsrc) return if hasattr(src, 'held_object'): src = src.held_object res_kwargs = { 'output': '@BASENAME@.' + suffix, 'input': [src], 'command': [rescomp] + res_args, } if isinstance(src, (str, mesonlib.File)): name = 'file {!r}'.format(str(src)) elif isinstance(src, build.CustomTarget): if len(src.get_outputs()) > 1: raise MesonException('windows.compile_resources does not accept custom targets with more than 1 output.') name = 'target {!r}'.format(src.get_id()) else: raise MesonException('Unexpected source type {!r}. windows.compile_resources accepts only strings, files, custom targets, and lists thereof.'.format(src)) # Path separators are not allowed in target names name = name.replace('/', '_').replace('\\', '_') res_targets.append(build.CustomTarget('Windows resource for ' + name, state.subdir, state.subproject, res_kwargs)) add_target(args) return ModuleReturnValue(res_targets, [res_targets]) def initialize(): return WindowsModule() meson-0.45.1/mesonbuild/modules/i18n.py0000644000175000017500000001376413177703474021306 0ustar jpakkanejpakkane00000000000000# Copyright 2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import shutil from os import path from .. import coredata, mesonlib, build from ..mesonlib import MesonException from . import ModuleReturnValue from . import ExtensionModule from ..interpreterbase import permittedKwargs PRESET_ARGS = { 'glib': [ '--from-code=UTF-8', '--add-comments', # https://developer.gnome.org/glib/stable/glib-I18N.html '--keyword=_', '--keyword=N_', '--keyword=C_:1c,2', '--keyword=NC_:1c,2', '--keyword=g_dcgettext:2', '--keyword=g_dngettext:2,3', '--keyword=g_dpgettext2:2c,3', '--flag=N_:1:pass-c-format', '--flag=C_:2:pass-c-format', '--flag=NC_:2:pass-c-format', '--flag=g_dngettext:2:pass-c-format', '--flag=g_strdup_printf:1:c-format', '--flag=g_string_printf:2:c-format', '--flag=g_string_append_printf:2:c-format', '--flag=g_error_new:3:c-format', '--flag=g_set_error:4:c-format', ] } class I18nModule(ExtensionModule): @staticmethod def _get_data_dirs(state, dirs): """Returns source directories of relative paths""" src_dir = path.join(state.environment.get_source_dir(), state.subdir) return [path.join(src_dir, d) for d in dirs] @permittedKwargs({'languages', 'data_dirs', 'preset', 'args', 'po_dir', 'type', 'input', 'output', 'install', 'install_dir'}) def merge_file(self, state, args, kwargs): podir = kwargs.pop('po_dir', None) if not podir: raise MesonException('i18n: po_dir is a required kwarg') podir = path.join(state.build_to_src, state.subdir, podir) file_type = kwargs.pop('type', 'xml') VALID_TYPES = ('xml', 'desktop') if file_type not in VALID_TYPES: raise MesonException('i18n: "{}" is not a valid type {}'.format(file_type, VALID_TYPES)) datadirs = self._get_data_dirs(state, mesonlib.stringlistify(kwargs.pop('data_dirs', []))) datadirs = '--datadirs=' + ':'.join(datadirs) if datadirs else None command = state.environment.get_build_command() + [ '--internal', 'msgfmthelper', '@INPUT@', '@OUTPUT@', file_type, podir ] if datadirs: command.append(datadirs) kwargs['command'] = command ct = build.CustomTarget(kwargs['output'] + '_merge', state.subdir, state.subproject, kwargs) return ModuleReturnValue(ct, [ct]) @permittedKwargs({'po_dir', 'data_dirs', 'type', 'languages', 'args', 'preset', 'install'}) def gettext(self, state, args, kwargs): if len(args) != 1: raise coredata.MesonException('Gettext requires one positional argument (package name).') if not shutil.which('xgettext'): raise coredata.MesonException('Can not do gettext because xgettext is not installed.') packagename = args[0] languages = mesonlib.stringlistify(kwargs.get('languages', [])) datadirs = self._get_data_dirs(state, mesonlib.stringlistify(kwargs.get('data_dirs', []))) extra_args = mesonlib.stringlistify(kwargs.get('args', [])) preset = kwargs.pop('preset', None) if preset: preset_args = PRESET_ARGS.get(preset) if not preset_args: raise coredata.MesonException('i18n: Preset "{}" is not one of the valid options: {}'.format( preset, list(PRESET_ARGS.keys()))) extra_args = set(preset_args + extra_args) pkg_arg = '--pkgname=' + packagename lang_arg = '--langs=' + '@@'.join(languages) if languages else None datadirs = '--datadirs=' + ':'.join(datadirs) if datadirs else None extra_args = '--extra-args=' + '@@'.join(extra_args) if extra_args else None potargs = state.environment.get_build_command() + ['--internal', 'gettext', 'pot', pkg_arg] if datadirs: potargs.append(datadirs) if extra_args: potargs.append(extra_args) pottarget = build.RunTarget(packagename + '-pot', potargs[0], potargs[1:], [], state.subdir, state.subproject) gmoargs = state.environment.get_build_command() + ['--internal', 'gettext', 'gen_gmo'] if lang_arg: gmoargs.append(lang_arg) gmotarget = build.RunTarget(packagename + '-gmo', gmoargs[0], gmoargs[1:], [], state.subdir, state.subproject) updatepoargs = state.environment.get_build_command() + ['--internal', 'gettext', 'update_po', pkg_arg] if lang_arg: updatepoargs.append(lang_arg) if datadirs: updatepoargs.append(datadirs) if extra_args: updatepoargs.append(extra_args) updatepotarget = build.RunTarget(packagename + '-update-po', updatepoargs[0], updatepoargs[1:], [], state.subdir, state.subproject) targets = [pottarget, gmotarget, updatepotarget] install = kwargs.get('install', True) if install: script = state.environment.get_build_command() args = ['--internal', 'gettext', 'install', '--subdir=' + state.subdir, '--localedir=' + state.environment.coredata.get_builtin_option('localedir'), pkg_arg] if lang_arg: args.append(lang_arg) iscript = build.RunScript(script, args) targets.append(iscript) return ModuleReturnValue(None, targets) def initialize(): return I18nModule() meson-0.45.1/mesonbuild/modules/qt.py0000644000175000017500000002140313243342167021130 0ustar jpakkanejpakkane00000000000000# Copyright 2015 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os from .. import mlog from .. import build from ..mesonlib import MesonException, Popen_safe, extract_as_list from ..dependencies import Qt4Dependency, Qt5Dependency import xml.etree.ElementTree as ET from . import ModuleReturnValue, get_include_args from ..interpreterbase import permittedKwargs _QT_DEPS_LUT = { 4: Qt4Dependency, 5: Qt5Dependency } class QtBaseModule: tools_detected = False def __init__(self, qt_version=5): self.qt_version = qt_version def _detect_tools(self, env, method): if self.tools_detected: return mlog.log('Detecting Qt{version} tools'.format(version=self.qt_version)) # FIXME: We currently require QtX to exist while importing the module. # We should make it gracefully degrade and not create any targets if # the import is marked as 'optional' (not implemented yet) kwargs = {'required': 'true', 'modules': 'Core', 'silent': 'true', 'method': method} qt = _QT_DEPS_LUT[self.qt_version](env, kwargs) # Get all tools and then make sure that they are the right version self.moc, self.uic, self.rcc, self.lrelease = qt.compilers_detect() # Moc, uic and rcc write their version strings to stderr. # Moc and rcc return a non-zero result when doing so. # What kind of an idiot thought that was a good idea? for compiler, compiler_name in ((self.moc, "Moc"), (self.uic, "Uic"), (self.rcc, "Rcc"), (self.lrelease, "lrelease")): if compiler.found(): # Workaround since there is no easy way to know which tool/version support which flag for flag in ['-v', '-version']: p, stdout, stderr = Popen_safe(compiler.get_command() + [flag])[0:3] if p.returncode == 0: break stdout = stdout.strip() stderr = stderr.strip() if 'Qt {}'.format(self.qt_version) in stderr: compiler_ver = stderr elif 'version {}.'.format(self.qt_version) in stderr: compiler_ver = stderr elif ' {}.'.format(self.qt_version) in stdout: compiler_ver = stdout else: raise MesonException('{name} preprocessor is not for Qt {version}. Output:\n{stdo}\n{stderr}'.format( name=compiler_name, version=self.qt_version, stdo=stdout, stderr=stderr)) mlog.log(' {}:'.format(compiler_name.lower()), mlog.green('YES'), '({path}, {version})'.format( path=compiler.get_path(), version=compiler_ver.split()[-1])) else: mlog.log(' {}:'.format(compiler_name.lower()), mlog.red('NO')) self.tools_detected = True def parse_qrc(self, state, fname): abspath = os.path.join(state.environment.source_dir, state.subdir, fname) relative_part = os.path.dirname(fname) try: tree = ET.parse(abspath) root = tree.getroot() result = [] for child in root[0]: if child.tag != 'file': mlog.warning("malformed rcc file: ", os.path.join(state.subdir, fname)) break else: result.append(os.path.join(relative_part, child.text)) return result except Exception: return [] @permittedKwargs({'moc_headers', 'moc_sources', 'moc_extra_arguments', 'include_directories', 'ui_files', 'qresources', 'method'}) def preprocess(self, state, args, kwargs): rcc_files, ui_files, moc_headers, moc_sources, moc_extra_arguments, sources, include_directories \ = extract_as_list(kwargs, 'qresources', 'ui_files', 'moc_headers', 'moc_sources', 'moc_extra_arguments', 'sources', 'include_directories', pop = True) sources += args[1:] method = kwargs.get('method', 'auto') self._detect_tools(state.environment, method) err_msg = "{0} sources specified and couldn't find {1}, " \ "please check your qt{2} installation" if len(moc_headers) + len(moc_sources) > 0 and not self.moc.found(): raise MesonException(err_msg.format('MOC', 'moc-qt{}'.format(self.qt_version), self.qt_version)) if len(rcc_files) > 0: if not self.rcc.found(): raise MesonException(err_msg.format('RCC', 'rcc-qt{}'.format(self.qt_version), self.qt_version)) qrc_deps = [] for i in rcc_files: qrc_deps += self.parse_qrc(state, i) # custom output name set? -> one output file, multiple otherwise if len(args) > 0: name = args[0] rcc_kwargs = {'input': rcc_files, 'output': name + '.cpp', 'command': [self.rcc, '-name', name, '-o', '@OUTPUT@', '@INPUT@'], 'depend_files': qrc_deps} res_target = build.CustomTarget(name, state.subdir, state.subproject, rcc_kwargs) sources.append(res_target) else: for rcc_file in rcc_files: basename = os.path.basename(rcc_file) name = 'qt' + str(self.qt_version) + '-' + basename.replace('.', '_') rcc_kwargs = {'input': rcc_file, 'output': name + '.cpp', 'command': [self.rcc, '-name', '@BASENAME@', '-o', '@OUTPUT@', '@INPUT@'], 'depend_files': qrc_deps} res_target = build.CustomTarget(name, state.subdir, state.subproject, rcc_kwargs) sources.append(res_target) if len(ui_files) > 0: if not self.uic.found(): raise MesonException(err_msg.format('UIC', 'uic-qt' + self.qt_version)) ui_kwargs = {'output': 'ui_@BASENAME@.h', 'arguments': ['-o', '@OUTPUT@', '@INPUT@']} ui_gen = build.Generator([self.uic], ui_kwargs) ui_output = ui_gen.process_files('Qt{} ui'.format(self.qt_version), ui_files, state) sources.append(ui_output) inc = get_include_args(include_dirs=include_directories) if len(moc_headers) > 0: arguments = moc_extra_arguments + inc + ['@INPUT@', '-o', '@OUTPUT@'] moc_kwargs = {'output': 'moc_@BASENAME@.cpp', 'arguments': arguments} moc_gen = build.Generator([self.moc], moc_kwargs) moc_output = moc_gen.process_files('Qt{} moc header'.format(self.qt_version), moc_headers, state) sources.append(moc_output) if len(moc_sources) > 0: arguments = moc_extra_arguments + inc + ['@INPUT@', '-o', '@OUTPUT@'] moc_kwargs = {'output': '@BASENAME@.moc', 'arguments': arguments} moc_gen = build.Generator([self.moc], moc_kwargs) moc_output = moc_gen.process_files('Qt{} moc source'.format(self.qt_version), moc_sources, state) sources.append(moc_output) return ModuleReturnValue(sources, sources) @permittedKwargs({'ts_files', 'install', 'install_dir', 'build_by_default', 'method'}) def compile_translations(self, state, args, kwargs): ts_files, install_dir = extract_as_list(kwargs, 'ts_files', 'install_dir', pop=True) self._detect_tools(state.environment, kwargs.get('method', 'auto')) translations = [] for ts in ts_files: cmd = [self.lrelease, '@INPUT@', '-qm', '@OUTPUT@'] lrelease_kwargs = {'output': '@BASENAME@.qm', 'input': ts, 'install': kwargs.get('install', False), 'build_by_default': kwargs.get('build_by_default', False), 'command': cmd} if install_dir is not None: lrelease_kwargs['install_dir'] = install_dir lrelease_target = build.CustomTarget('qt{}-compile-{}'.format(self.qt_version, ts), state.subdir, state.subproject, lrelease_kwargs) translations.append(lrelease_target) return ModuleReturnValue(translations, translations) meson-0.45.1/mesonbuild/modules/gnome.py0000644000175000017500000017544313254550710021624 0ustar jpakkanejpakkane00000000000000# Copyright 2015-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. '''This module provides helper functions for Gnome/GLib related functionality such as gobject-introspection, gresources and gtk-doc''' import os import copy import subprocess from .. import build from .. import mlog from .. import mesonlib from .. import compilers from .. import interpreter from . import GResourceTarget, GResourceHeaderTarget, GirTarget, TypelibTarget, VapiTarget from . import find_program, get_include_args from . import ExtensionModule from . import ModuleReturnValue from ..mesonlib import MesonException, OrderedSet, Popen_safe, extract_as_list from ..dependencies import Dependency, PkgConfigDependency, InternalDependency from ..interpreterbase import noKwargs, permittedKwargs # gresource compilation is broken due to the way # the resource compiler and Ninja clash about it # # https://github.com/ninja-build/ninja/issues/1184 # https://bugzilla.gnome.org/show_bug.cgi?id=774368 gresource_dep_needed_version = '>= 2.51.1' native_glib_version = None girwarning_printed = False gdbuswarning_printed = False gresource_warning_printed = False _gir_has_extra_lib_arg = None def gir_has_extra_lib_arg(): global _gir_has_extra_lib_arg if _gir_has_extra_lib_arg is not None: return _gir_has_extra_lib_arg _gir_has_extra_lib_arg = False try: g_ir_scanner = find_program('g-ir-scanner', '').get_command() opts = Popen_safe(g_ir_scanner + ['--help'], stderr=subprocess.STDOUT)[1] _gir_has_extra_lib_arg = '--extra-library' in opts except (MesonException, FileNotFoundError, subprocess.CalledProcessError): pass return _gir_has_extra_lib_arg class GnomeModule(ExtensionModule): gir_dep = None @staticmethod def _get_native_glib_version(state): global native_glib_version if native_glib_version is None: glib_dep = PkgConfigDependency('glib-2.0', state.environment, {'native': True}) native_glib_version = glib_dep.get_version() return native_glib_version def __print_gresources_warning(self, state): global gresource_warning_printed if not gresource_warning_printed: if not mesonlib.version_compare(self._get_native_glib_version(state), gresource_dep_needed_version): mlog.warning('GLib compiled dependencies do not work reliably with \n' 'the current version of GLib. See the following upstream issue:', mlog.bold('https://bugzilla.gnome.org/show_bug.cgi?id=774368')) gresource_warning_printed = True return [] @staticmethod def _print_gdbus_warning(): global gdbuswarning_printed if not gdbuswarning_printed: mlog.warning('Code generated with gdbus_codegen() requires the root directory be added to\n' ' include_directories of targets with GLib < 2.51.3:', mlog.bold('https://github.com/mesonbuild/meson/issues/1387')) gdbuswarning_printed = True @permittedKwargs({'source_dir', 'c_name', 'dependencies', 'export', 'gresource_bundle', 'install_header', 'install', 'install_dir', 'extra_args', 'build_by_default'}) def compile_resources(self, state, args, kwargs): self.__print_gresources_warning(state) glib_version = self._get_native_glib_version(state) cmd = ['glib-compile-resources', '@INPUT@'] source_dirs, dependencies = mesonlib.extract_as_list(kwargs, 'source_dir', 'dependencies', pop=True) if len(args) < 2: raise MesonException('Not enough arguments; the name of the resource ' 'and the path to the XML file are required') # Validate dependencies for (ii, dep) in enumerate(dependencies): if hasattr(dep, 'held_object'): dependencies[ii] = dep = dep.held_object if not isinstance(dep, (mesonlib.File, build.CustomTarget, build.CustomTargetIndex)): m = 'Unexpected dependency type {!r} for gnome.compile_resources() ' \ '"dependencies" argument.\nPlease pass the return value of ' \ 'custom_target() or configure_file()' raise MesonException(m.format(dep)) if isinstance(dep, (build.CustomTarget, build.CustomTargetIndex)): if not mesonlib.version_compare(glib_version, gresource_dep_needed_version): m = 'The "dependencies" argument of gnome.compile_resources() can not\n' \ 'be used with the current version of glib-compile-resources due to\n' \ '' raise MesonException(m) ifile = args[1] if isinstance(ifile, mesonlib.File): # glib-compile-resources will be run inside the source dir, # so we need either 'src_to_build' or the absolute path. # Absolute path is the easiest choice. if ifile.is_built: ifile = os.path.join(state.environment.get_build_dir(), ifile.subdir, ifile.fname) else: ifile = os.path.join(ifile.subdir, ifile.fname) elif isinstance(ifile, str): ifile = os.path.join(state.subdir, ifile) elif isinstance(ifile, (interpreter.CustomTargetHolder, interpreter.CustomTargetIndexHolder, interpreter.GeneratedObjectsHolder)): m = 'Resource xml files generated at build-time cannot be used ' \ 'with gnome.compile_resources() because we need to scan ' \ 'the xml for dependencies. Use configure_file() instead ' \ 'to generate it at configure-time.' raise MesonException(m) else: raise MesonException('Invalid file argument: {!r}'.format(ifile)) depend_files, depends, subdirs = self._get_gresource_dependencies( state, ifile, source_dirs, dependencies) # Make source dirs relative to build dir now source_dirs = [os.path.join(state.build_to_src, state.subdir, d) for d in source_dirs] # Always include current directory, but after paths set by user source_dirs.append(os.path.join(state.build_to_src, state.subdir)) # Ensure build directories of generated deps are included source_dirs += subdirs for source_dir in OrderedSet(source_dirs): cmd += ['--sourcedir', source_dir] if 'c_name' in kwargs: cmd += ['--c-name', kwargs.pop('c_name')] export = kwargs.pop('export', False) if not export: cmd += ['--internal'] cmd += ['--generate', '--target', '@OUTPUT@'] cmd += mesonlib.stringlistify(kwargs.pop('extra_args', [])) gresource = kwargs.pop('gresource_bundle', False) if gresource: output = args[0] + '.gresource' name = args[0] + '_gresource' else: output = args[0] + '.c' name = args[0] + '_c' if kwargs.get('install', False) and not gresource: raise MesonException('The install kwarg only applies to gresource bundles, see install_header') install_header = kwargs.pop('install_header', False) if install_header and gresource: raise MesonException('The install_header kwarg does not apply to gresource bundles') if install_header and not export: raise MesonException('GResource header is installed yet export is not enabled') kwargs['input'] = args[1] kwargs['output'] = output kwargs['depends'] = depends if not mesonlib.version_compare(glib_version, gresource_dep_needed_version): # This will eventually go out of sync if dependencies are added kwargs['depend_files'] = depend_files kwargs['command'] = cmd else: depfile = kwargs['output'] + '.d' kwargs['depfile'] = depfile kwargs['command'] = copy.copy(cmd) + ['--dependency-file', '@DEPFILE@'] target_c = GResourceTarget(name, state.subdir, state.subproject, kwargs) if gresource: # Only one target for .gresource files return ModuleReturnValue(target_c, [target_c]) h_kwargs = { 'command': cmd, 'input': args[1], 'output': args[0] + '.h', # The header doesn't actually care about the files yet it errors if missing 'depends': depends } if 'build_by_default' in kwargs: h_kwargs['build_by_default'] = kwargs['build_by_default'] if install_header: h_kwargs['install'] = install_header h_kwargs['install_dir'] = kwargs.get('install_dir', state.environment.coredata.get_builtin_option('includedir')) target_h = GResourceHeaderTarget(args[0] + '_h', state.subdir, state.subproject, h_kwargs) rv = [target_c, target_h] return ModuleReturnValue(rv, rv) def _get_gresource_dependencies(self, state, input_file, source_dirs, dependencies): cmd = ['glib-compile-resources', input_file, '--generate-dependencies'] # Prefer generated files over source files cmd += ['--sourcedir', state.subdir] # Current build dir for source_dir in source_dirs: cmd += ['--sourcedir', os.path.join(state.subdir, source_dir)] pc, stdout, stderr = Popen_safe(cmd, cwd=state.environment.get_source_dir()) if pc.returncode != 0: m = 'glib-compile-resources failed to get dependencies for {}:\n{}' mlog.warning(m.format(cmd[1], stderr)) raise subprocess.CalledProcessError(pc.returncode, cmd) dep_files = stdout.split('\n')[:-1] depends = [] subdirs = [] for resfile in dep_files[:]: resbasename = os.path.basename(resfile) for dep in dependencies: if hasattr(dep, 'held_object'): dep = dep.held_object if isinstance(dep, mesonlib.File): if dep.fname != resbasename: continue dep_files.remove(resfile) dep_files.append(dep) subdirs.append(dep.subdir) break elif isinstance(dep, (build.CustomTarget, build.CustomTargetIndex)): fname = None outputs = {(o, os.path.basename(o)) for o in dep.get_outputs()} for o, baseo in outputs: if baseo == resbasename: fname = o break if fname is not None: dep_files.remove(resfile) depends.append(dep) subdirs.append(dep.get_subdir()) break else: # In generate-dependencies mode, glib-compile-resources doesn't raise # an error for missing resources but instead prints whatever filename # was listed in the input file. That's good because it means we can # handle resource files that get generated as part of the build, as # follows. # # If there are multiple generated resource files with the same basename # then this code will get confused. try: f = mesonlib.File.from_source_file(state.environment.get_source_dir(), ".", resfile) except MesonException: raise MesonException( 'Resource "%s" listed in "%s" was not found. If this is a ' 'generated file, pass the target that generates it to ' 'gnome.compile_resources() using the "dependencies" ' 'keyword argument.' % (resfile, input_file)) dep_files.remove(resfile) dep_files.append(f) return dep_files, depends, subdirs def _get_link_args(self, state, lib, depends=None, include_rpath=False, use_gir_args=False): link_command = [] # Construct link args if isinstance(lib, build.SharedLibrary): libdir = os.path.join(state.environment.get_build_dir(), state.backend.get_target_dir(lib)) link_command.append('-L' + libdir) # Needed for the following binutils bug: # https://github.com/mesonbuild/meson/issues/1911 # However, g-ir-scanner does not understand -Wl,-rpath # so we need to use -L instead for d in state.backend.determine_rpath_dirs(lib): d = os.path.join(state.environment.get_build_dir(), d) link_command.append('-L' + d) if include_rpath: link_command.append('-Wl,-rpath,' + d) if include_rpath: link_command.append('-Wl,-rpath,' + libdir) if depends: depends.append(lib) if gir_has_extra_lib_arg() and use_gir_args: link_command.append('--extra-library=' + lib.name) else: link_command.append('-l' + lib.name) return link_command def _get_dependencies_flags(self, deps, state, depends=None, include_rpath=False, use_gir_args=False): cflags = OrderedSet() ldflags = OrderedSet() gi_includes = OrderedSet() deps = mesonlib.listify(deps, unholder=True) for dep in deps: if isinstance(dep, InternalDependency): cflags.update(get_include_args(dep.include_directories)) for lib in dep.libraries: if hasattr(lib, 'held_object'): lib = lib.held_object ldflags.update(self._get_link_args(state, lib, depends, include_rpath)) libdepflags = self._get_dependencies_flags(lib.get_external_deps(), state, depends, include_rpath, use_gir_args) cflags.update(libdepflags[0]) ldflags.update(libdepflags[1]) gi_includes.update(libdepflags[2]) extdepflags = self._get_dependencies_flags(dep.ext_deps, state, depends, include_rpath, use_gir_args) cflags.update(extdepflags[0]) ldflags.update(extdepflags[1]) gi_includes.update(extdepflags[2]) for source in dep.sources: if hasattr(source, 'held_object'): source = source.held_object if isinstance(source, GirTarget): gi_includes.update([os.path.join(state.environment.get_build_dir(), source.get_subdir())]) # This should be any dependency other than an internal one. elif isinstance(dep, Dependency): cflags.update(dep.get_compile_args()) for lib in dep.get_link_args(): if (os.path.isabs(lib) and # For PkgConfigDependency only: getattr(dep, 'is_libtool', False)): lib_dir = os.path.dirname(lib) ldflags.update(["-L%s" % lib_dir]) if include_rpath: ldflags.update(['-Wl,-rpath {}'.format(lib_dir)]) libname = os.path.basename(lib) if libname.startswith("lib"): libname = libname[3:] libname = libname.split(".so")[0] lib = "-l%s" % libname # Hack to avoid passing some compiler options in if lib.startswith("-W"): continue ldflags.update([lib]) if isinstance(dep, PkgConfigDependency): girdir = dep.get_pkgconfig_variable("girdir", {'default': ''}) if girdir: gi_includes.update([girdir]) elif isinstance(dep, (build.StaticLibrary, build.SharedLibrary)): cflags.update(get_include_args(dep.get_include_dirs())) else: mlog.log('dependency {!r} not handled to build gir files'.format(dep)) continue if gir_has_extra_lib_arg() and use_gir_args: fixed_ldflags = OrderedSet() for ldflag in ldflags: if ldflag.startswith("-l"): fixed_ldflags.add(ldflag.replace('-l', '--extra-library=', 1)) else: fixed_ldflags.add(ldflag) ldflags = fixed_ldflags return cflags, ldflags, gi_includes @permittedKwargs({'sources', 'nsversion', 'namespace', 'symbol_prefix', 'identifier_prefix', 'export_packages', 'includes', 'dependencies', 'link_with', 'include_directories', 'install', 'install_dir_gir', 'install_dir_typelib', 'extra_args', 'packages', 'header', 'build_by_default'}) def generate_gir(self, state, args, kwargs): if len(args) != 1: raise MesonException('Gir takes one argument') if kwargs.get('install_dir'): raise MesonException('install_dir is not supported with generate_gir(), see "install_dir_gir" and "install_dir_typelib"') giscanner = find_program('g-ir-scanner', 'Gir') gicompiler = find_program('g-ir-compiler', 'Gir') girtarget = args[0] while hasattr(girtarget, 'held_object'): girtarget = girtarget.held_object if not isinstance(girtarget, (build.Executable, build.SharedLibrary)): raise MesonException('Gir target must be an executable or shared library') try: if not self.gir_dep: self.gir_dep = PkgConfigDependency('gobject-introspection-1.0', state.environment, {'native': True}) pkgargs = self.gir_dep.get_compile_args() except Exception: raise MesonException('gobject-introspection dependency was not found, gir cannot be generated.') ns = kwargs.pop('namespace') nsversion = kwargs.pop('nsversion') libsources = mesonlib.extract_as_list(kwargs, 'sources', pop=True) girfile = '%s-%s.gir' % (ns, nsversion) srcdir = os.path.join(state.environment.get_source_dir(), state.subdir) builddir = os.path.join(state.environment.get_build_dir(), state.subdir) depends = [girtarget] gir_inc_dirs = [] scan_command = [giscanner] scan_command += pkgargs scan_command += ['--no-libtool', '--namespace=' + ns, '--nsversion=' + nsversion, '--warn-all', '--output', '@OUTPUT@'] header = kwargs.pop('header', None) if header: if not isinstance(header, str): raise MesonException('header must be a string') scan_command += ['--c-include=' + header] extra_args = mesonlib.stringlistify(kwargs.pop('extra_args', [])) scan_command += extra_args scan_command += ['-I' + srcdir, '-I' + builddir] scan_command += get_include_args(girtarget.get_include_dirs()) gir_filelist_dir = state.backend.get_target_private_dir_abs(girtarget) if not os.path.isdir(gir_filelist_dir): os.mkdir(gir_filelist_dir) gir_filelist_filename = os.path.join(gir_filelist_dir, '%s_%s_gir_filelist' % (ns, nsversion)) with open(gir_filelist_filename, 'w', encoding='utf-8') as gir_filelist: for s in libsources: if hasattr(s, 'held_object'): s = s.held_object if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)): gir_filelist.write(os.path.join(state.environment.get_build_dir(), state.backend.get_target_dir(s), s.get_outputs()[0]) + '\n') elif isinstance(s, mesonlib.File): gir_filelist.write(s.rel_to_builddir(state.build_to_src) + '\n') elif isinstance(s, build.GeneratedList): for gen_src in s.get_outputs(): gir_filelist.write(os.path.join(srcdir, gen_src) + '\n') else: gir_filelist.write(os.path.join(srcdir, s) + '\n') scan_command += ['--filelist=' + gir_filelist_filename] if 'link_with' in kwargs: link_with = mesonlib.extract_as_list(kwargs, 'link_with', pop = True) for link in link_with: scan_command += self._get_link_args(state, link.held_object, depends, use_gir_args=True) if 'includes' in kwargs: includes = mesonlib.extract_as_list(kwargs, 'includes', pop = True) for inc in includes: if hasattr(inc, 'held_object'): inc = inc.held_object if isinstance(inc, str): scan_command += ['--include=%s' % (inc, )] elif isinstance(inc, GirTarget): gir_inc_dirs += [ os.path.join(state.environment.get_build_dir(), inc.get_subdir()), ] scan_command += [ "--include-uninstalled=%s" % (os.path.join(inc.get_subdir(), inc.get_basename()), ) ] depends += [inc] else: raise MesonException( 'Gir includes must be str, GirTarget, or list of them') cflags = [] ldflags = [] for lang, compiler in girtarget.compilers.items(): # XXX: Can you use g-i with any other language? if lang in ('c', 'cpp', 'objc', 'objcpp', 'd'): break else: lang = None compiler = None if lang and compiler: if state.global_args.get(lang): cflags += state.global_args[lang] if state.project_args.get(lang): cflags += state.project_args[lang] if 'b_sanitize' in compiler.base_options: sanitize = state.environment.coredata.base_options['b_sanitize'].value cflags += compilers.sanitizer_compile_args(sanitize) if 'address' in sanitize.split(','): ldflags += ['-lasan'] # FIXME: Linking directly to libasan is not recommended but g-ir-scanner # does not understand -f LDFLAGS. https://bugzilla.gnome.org/show_bug.cgi?id=783892 # ldflags += compilers.sanitizer_link_args(sanitize) if 'symbol_prefix' in kwargs: sym_prefixes = mesonlib.stringlistify(kwargs.pop('symbol_prefix', [])) scan_command += ['--symbol-prefix=%s' % sym_prefix for sym_prefix in sym_prefixes] if 'identifier_prefix' in kwargs: identifier_prefix = kwargs.pop('identifier_prefix') if not isinstance(identifier_prefix, str): raise MesonException('Gir identifier prefix must be str') scan_command += ['--identifier-prefix=%s' % identifier_prefix] if 'export_packages' in kwargs: pkgs = kwargs.pop('export_packages') if isinstance(pkgs, str): scan_command += ['--pkg-export=%s' % pkgs] elif isinstance(pkgs, list): scan_command += ['--pkg-export=%s' % pkg for pkg in pkgs] else: raise MesonException('Gir export packages must be str or list') deps = (girtarget.get_all_link_deps() + girtarget.get_external_deps() + extract_as_list(kwargs, 'dependencies', pop=True, unholder=True)) # Need to recursively add deps on GirTarget sources from our # dependencies and also find the include directories needed for the # typelib generation custom target below. typelib_includes = [] for dep in deps: if hasattr(dep, 'held_object'): dep = dep.held_object # Add a dependency on each GirTarget listed in dependencies and add # the directory where it will be generated to the typelib includes if isinstance(dep, InternalDependency): for source in dep.sources: if hasattr(source, 'held_object'): source = source.held_object if isinstance(source, GirTarget) and source not in depends: depends.append(source) subdir = os.path.join(state.environment.get_build_dir(), source.get_subdir()) if subdir not in typelib_includes: typelib_includes.append(subdir) # Do the same, but for dependencies of dependencies. These are # stored in the list of generated sources for each link dep (from # girtarget.get_all_link_deps() above). # FIXME: Store this in the original form from declare_dependency() # so it can be used here directly. elif isinstance(dep, build.SharedLibrary): for source in dep.generated: if isinstance(source, GirTarget): subdir = os.path.join(state.environment.get_build_dir(), source.get_subdir()) if subdir not in typelib_includes: typelib_includes.append(subdir) elif isinstance(dep, PkgConfigDependency): girdir = dep.get_pkgconfig_variable("girdir", {'default': ''}) if girdir and girdir not in typelib_includes: typelib_includes.append(girdir) # ldflags will be misinterpreted by gir scanner (showing # spurious dependencies) but building GStreamer fails if they # are not used here. dep_cflags, dep_ldflags, gi_includes = self._get_dependencies_flags(deps, state, depends, use_gir_args=True) cflags += list(dep_cflags) ldflags += list(dep_ldflags) scan_command += ['--cflags-begin'] scan_command += cflags scan_command += state.environment.coredata.external_args[lang] scan_command += ['--cflags-end'] # need to put our output directory first as we need to use the # generated libraries instead of any possibly installed system/prefix # ones. if isinstance(girtarget, build.SharedLibrary): scan_command += ["-L@PRIVATE_OUTDIR_ABS_%s@" % girtarget.get_id()] scan_command += list(ldflags) for i in gi_includes: scan_command += ['--add-include-path=%s' % i] inc_dirs = mesonlib.extract_as_list(kwargs, 'include_directories', pop = True) for incd in inc_dirs: if not isinstance(incd.held_object, (str, build.IncludeDirs)): raise MesonException( 'Gir include dirs should be include_directories().') scan_command += get_include_args(inc_dirs) scan_command += get_include_args(gir_inc_dirs + inc_dirs, prefix='--add-include-path=') if isinstance(girtarget, build.Executable): scan_command += ['--program', girtarget] elif isinstance(girtarget, build.SharedLibrary): libname = girtarget.get_basename() # Needed for the following binutils bug: # https://github.com/mesonbuild/meson/issues/1911 # However, g-ir-scanner does not understand -Wl,-rpath # so we need to use -L instead for d in state.backend.determine_rpath_dirs(girtarget): d = os.path.join(state.environment.get_build_dir(), d) scan_command.append('-L' + d) scan_command += ['--library', libname] for link_arg in state.environment.coredata.external_link_args[lang]: if link_arg.startswith('-L'): scan_command.append(link_arg) scankwargs = {'output': girfile, 'command': scan_command, 'depends': depends} if 'install' in kwargs: scankwargs['install'] = kwargs['install'] scankwargs['install_dir'] = kwargs.get('install_dir_gir', os.path.join(state.environment.get_datadir(), 'gir-1.0')) if 'build_by_default' in kwargs: scankwargs['build_by_default'] = kwargs['build_by_default'] scan_target = GirTarget(girfile, state.subdir, state.subproject, scankwargs) typelib_output = '%s-%s.typelib' % (ns, nsversion) typelib_cmd = [gicompiler, scan_target, '--output', '@OUTPUT@'] typelib_cmd += get_include_args(gir_inc_dirs, prefix='--includedir=') for incdir in typelib_includes: typelib_cmd += ["--includedir=" + incdir] typelib_kwargs = { 'output': typelib_output, 'command': typelib_cmd, } if 'install' in kwargs: typelib_kwargs['install'] = kwargs['install'] typelib_kwargs['install_dir'] = kwargs.get('install_dir_typelib', os.path.join(state.environment.get_libdir(), 'girepository-1.0')) if 'build_by_default' in kwargs: typelib_kwargs['build_by_default'] = kwargs['build_by_default'] typelib_target = TypelibTarget(typelib_output, state.subdir, state.subproject, typelib_kwargs) rv = [scan_target, typelib_target] return ModuleReturnValue(rv, rv) @permittedKwargs({'build_by_default', 'depend_files'}) def compile_schemas(self, state, args, kwargs): if args: raise MesonException('Compile_schemas does not take positional arguments.') srcdir = os.path.join(state.build_to_src, state.subdir) outdir = state.subdir cmd = [find_program('glib-compile-schemas', 'gsettings-compile')] cmd += ['--targetdir', outdir, srcdir] kwargs['command'] = cmd kwargs['input'] = [] kwargs['output'] = 'gschemas.compiled' if state.subdir == '': targetname = 'gsettings-compile' else: targetname = 'gsettings-compile-' + state.subdir.replace('/', '_') target_g = build.CustomTarget(targetname, state.subdir, state.subproject, kwargs) return ModuleReturnValue(target_g, [target_g]) @permittedKwargs({'sources', 'media', 'symlink_media', 'languages'}) def yelp(self, state, args, kwargs): if len(args) < 1: raise MesonException('Yelp requires a project id') project_id = args[0] sources = mesonlib.stringlistify(kwargs.pop('sources', [])) if not sources: if len(args) > 1: sources = mesonlib.stringlistify(args[1:]) if not sources: raise MesonException('Yelp requires a list of sources') source_str = '@@'.join(sources) langs = mesonlib.stringlistify(kwargs.pop('languages', [])) if langs: mlog.log(mlog.red('DEPRECATION:'), '''The "languages" argument of gnome.yelp() is deprecated. Use a LINGUAS file in the sources directory instead. This will become a hard error in the future.''') media = mesonlib.stringlistify(kwargs.pop('media', [])) symlinks = kwargs.pop('symlink_media', True) if not isinstance(symlinks, bool): raise MesonException('symlink_media must be a boolean') if kwargs: raise MesonException('Unknown arguments passed: {}'.format(', '.join(kwargs.keys()))) script = state.environment.get_build_command() args = ['--internal', 'yelphelper', 'install', '--subdir=' + state.subdir, '--id=' + project_id, '--installdir=' + os.path.join(state.environment.get_datadir(), 'help'), '--sources=' + source_str] if symlinks: args.append('--symlinks=true') if media: args.append('--media=' + '@@'.join(media)) if langs: args.append('--langs=' + '@@'.join(langs)) inscript = build.RunScript(script, args) potargs = state.environment.get_build_command() + [ '--internal', 'yelphelper', 'pot', '--subdir=' + state.subdir, '--id=' + project_id, '--sources=' + source_str, ] pottarget = build.RunTarget('help-' + project_id + '-pot', potargs[0], potargs[1:], [], state.subdir, state.subproject) poargs = state.environment.get_build_command() + [ '--internal', 'yelphelper', 'update-po', '--subdir=' + state.subdir, '--id=' + project_id, '--sources=' + source_str, '--langs=' + '@@'.join(langs), ] potarget = build.RunTarget('help-' + project_id + '-update-po', poargs[0], poargs[1:], [], state.subdir, state.subproject) rv = [inscript, pottarget, potarget] return ModuleReturnValue(None, rv) @permittedKwargs({'main_xml', 'main_sgml', 'src_dir', 'dependencies', 'install', 'install_dir', 'scan_args', 'scanobjs_args', 'gobject_typesfile', 'fixxref_args', 'html_args', 'html_assets', 'content_files', 'mkdb_args', 'ignore_headers', 'include_directories', 'namespace', 'mode', 'expand_content_files'}) def gtkdoc(self, state, args, kwargs): if len(args) != 1: raise MesonException('Gtkdoc must have one positional argument.') modulename = args[0] if not isinstance(modulename, str): raise MesonException('Gtkdoc arg must be string.') if 'src_dir' not in kwargs: raise MesonException('Keyword argument src_dir missing.') main_file = kwargs.get('main_sgml', '') if not isinstance(main_file, str): raise MesonException('Main sgml keyword argument must be a string.') main_xml = kwargs.get('main_xml', '') if not isinstance(main_xml, str): raise MesonException('Main xml keyword argument must be a string.') if main_xml != '': if main_file != '': raise MesonException('You can only specify main_xml or main_sgml, not both.') main_file = main_xml targetname = modulename + '-doc' command = state.environment.get_build_command() namespace = kwargs.get('namespace', '') mode = kwargs.get('mode', 'auto') VALID_MODES = ('xml', 'sgml', 'none', 'auto') if mode not in VALID_MODES: raise MesonException('gtkdoc: Mode {} is not a valid mode: {}'.format(mode, VALID_MODES)) src_dirs = mesonlib.extract_as_list(kwargs, 'src_dir') header_dirs = [] for src_dir in src_dirs: if hasattr(src_dir, 'held_object'): src_dir = src_dir.held_object if not isinstance(src_dir, build.IncludeDirs): raise MesonException('Invalid keyword argument for src_dir.') for inc_dir in src_dir.get_incdirs(): header_dirs.append(os.path.join(state.environment.get_source_dir(), src_dir.get_curdir(), inc_dir)) header_dirs.append(os.path.join(state.environment.get_build_dir(), src_dir.get_curdir(), inc_dir)) else: header_dirs.append(src_dir) args = ['--internal', 'gtkdoc', '--sourcedir=' + state.environment.get_source_dir(), '--builddir=' + state.environment.get_build_dir(), '--subdir=' + state.subdir, '--headerdirs=' + '@@'.join(header_dirs), '--mainfile=' + main_file, '--modulename=' + modulename, '--mode=' + mode] if namespace: args.append('--namespace=' + namespace) args += self._unpack_args('--htmlargs=', 'html_args', kwargs) args += self._unpack_args('--scanargs=', 'scan_args', kwargs) args += self._unpack_args('--scanobjsargs=', 'scanobjs_args', kwargs) args += self._unpack_args('--gobjects-types-file=', 'gobject_typesfile', kwargs, state) args += self._unpack_args('--fixxrefargs=', 'fixxref_args', kwargs) args += self._unpack_args('--mkdbargs=', 'mkdb_args', kwargs) args += self._unpack_args('--html-assets=', 'html_assets', kwargs, state) depends = [] content_files = [] for s in mesonlib.extract_as_list(kwargs, 'content_files'): if hasattr(s, 'held_object'): s = s.held_object if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)): depends.append(s) content_files.append(os.path.join(state.environment.get_build_dir(), state.backend.get_target_dir(s), s.get_outputs()[0])) elif isinstance(s, mesonlib.File): content_files.append(s.rel_to_builddir(state.build_to_src)) elif isinstance(s, build.GeneratedList): depends.append(s) for gen_src in s.get_outputs(): content_files.append(os.path.join(state.environment.get_source_dir(), state.subdir, gen_src)) elif isinstance(s, str): content_files.append(os.path.join(state.environment.get_source_dir(), state.subdir, s)) else: raise MesonException( 'Invalid object type: {!r}'.format(s.__class__.__name__)) args += ['--content-files=' + '@@'.join(content_files)] args += self._unpack_args('--expand-content-files=', 'expand_content_files', kwargs, state) args += self._unpack_args('--ignore-headers=', 'ignore_headers', kwargs) args += self._unpack_args('--installdir=', 'install_dir', kwargs, state) args += self._get_build_args(kwargs, state) res = [build.RunTarget(targetname, command[0], command[1:] + args, depends, state.subdir, state.subproject)] if kwargs.get('install', True): res.append(build.RunScript(command, args)) return ModuleReturnValue(None, res) def _get_build_args(self, kwargs, state): args = [] deps = extract_as_list(kwargs, 'dependencies', unholder=True) cflags, ldflags, gi_includes = self._get_dependencies_flags(deps, state, include_rpath=True) inc_dirs = mesonlib.extract_as_list(kwargs, 'include_directories') for incd in inc_dirs: if not isinstance(incd.held_object, (str, build.IncludeDirs)): raise MesonException( 'Gir include dirs should be include_directories().') cflags.update(get_include_args(inc_dirs)) cflags.update(state.environment.coredata.external_args['c']) ldflags.update(state.environment.coredata.external_link_args['c']) if cflags: args += ['--cflags=%s' % ' '.join(cflags)] if ldflags: args += ['--ldflags=%s' % ' '.join(ldflags)] compiler = state.environment.coredata.compilers.get('c') if compiler: args += ['--cc=%s' % ' '.join(compiler.get_exelist())] args += ['--ld=%s' % ' '.join(compiler.get_linker_exelist())] return args @noKwargs def gtkdoc_html_dir(self, state, args, kwargs): if len(args) != 1: raise MesonException('Must have exactly one argument.') modulename = args[0] if not isinstance(modulename, str): raise MesonException('Argument must be a string') return ModuleReturnValue(os.path.join('share/gtk-doc/html', modulename), []) @staticmethod def _unpack_args(arg, kwarg_name, kwargs, expend_file_state=None): if kwarg_name not in kwargs: return [] new_args = mesonlib.extract_as_list(kwargs, kwarg_name) args = [] for i in new_args: if expend_file_state and isinstance(i, mesonlib.File): i = i.absolute_path(expend_file_state.environment.get_source_dir(), expend_file_state.environment.get_build_dir()) elif not isinstance(i, str): raise MesonException(kwarg_name + ' values must be strings.') args.append(i) if args: return [arg + '@@'.join(args)] return [] @permittedKwargs({'interface_prefix', 'namespace', 'object_manager', 'build_by_default', 'annotations', 'docbook'}) def gdbus_codegen(self, state, args, kwargs): if len(args) != 2: raise MesonException('Gdbus_codegen takes two arguments, name and xml file.') namebase = args[0] xml_file = args[1] target_name = namebase + '-gdbus' cmd = [find_program('gdbus-codegen', target_name)] if 'interface_prefix' in kwargs: cmd += ['--interface-prefix', kwargs.pop('interface_prefix')] if 'namespace' in kwargs: cmd += ['--c-namespace', kwargs.pop('namespace')] if kwargs.get('object_manager', False): cmd += ['--c-generate-object-manager'] if 'docbook' in kwargs: cmd += ['--generate-docbook', kwargs.pop('docbook')] # Annotations are a bit ugly in that they are a list of lists of strings... annotations = kwargs.pop('annotations', []) if not isinstance(annotations, list): raise MesonException('annotations takes a list') if annotations and isinstance(annotations, list) and not isinstance(annotations[0], list): annotations = [annotations] for annotation in annotations: if len(annotation) != 3 or not all(isinstance(i, str) for i in annotation): raise MesonException('Annotations must be made up of 3 strings for ELEMENT, KEY, and VALUE') cmd += ['--annotate'] + annotation # https://git.gnome.org/browse/glib/commit/?id=ee09bb704fe9ccb24d92dd86696a0e6bb8f0dc1a if mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.51.3'): cmd += ['--output-directory', '@OUTDIR@', '--generate-c-code', namebase, '@INPUT@'] else: self._print_gdbus_warning() cmd += ['--generate-c-code', '@OUTDIR@/' + namebase, '@INPUT@'] outputs = [namebase + '.c', namebase + '.h'] custom_kwargs = {'input': xml_file, 'output': outputs, 'command': cmd } if 'build_by_default' in kwargs: custom_kwargs['build_by_default'] = kwargs['build_by_default'] ct = build.CustomTarget(target_name, state.subdir, state.subproject, custom_kwargs) return ModuleReturnValue(ct, [ct]) @permittedKwargs({'sources', 'c_template', 'h_template', 'install_header', 'install_dir', 'comments', 'identifier_prefix', 'symbol_prefix', 'eprod', 'vprod', 'fhead', 'fprod', 'ftail', 'vhead', 'vtail', 'depends'}) def mkenums(self, state, args, kwargs): if len(args) != 1: raise MesonException('Mkenums requires one positional argument.') basename = args[0] if 'sources' not in kwargs: raise MesonException('Missing keyword argument "sources".') sources = kwargs.pop('sources') if isinstance(sources, str): sources = [sources] elif not isinstance(sources, list): raise MesonException( 'Sources keyword argument must be a string or array.') cmd = [] known_kwargs = ['comments', 'eprod', 'fhead', 'fprod', 'ftail', 'identifier_prefix', 'symbol_prefix', 'template', 'vhead', 'vprod', 'vtail'] known_custom_target_kwargs = ['install_dir', 'build_always', 'depends', 'depend_files'] c_template = h_template = None install_header = False for arg, value in kwargs.items(): if arg == 'sources': raise AssertionError("sources should've already been handled") elif arg == 'c_template': c_template = value if 'template' in kwargs: raise MesonException('Mkenums does not accept both ' 'c_template and template keyword ' 'arguments at the same time.') elif arg == 'h_template': h_template = value if 'template' in kwargs: raise MesonException('Mkenums does not accept both ' 'h_template and template keyword ' 'arguments at the same time.') elif arg == 'install_header': install_header = value elif arg in known_kwargs: cmd += ['--' + arg.replace('_', '-'), value] elif arg not in known_custom_target_kwargs: raise MesonException( 'Mkenums does not take a %s keyword argument.' % (arg, )) cmd = [find_program('glib-mkenums', 'mkenums')] + cmd custom_kwargs = {} for arg in known_custom_target_kwargs: if arg in kwargs: custom_kwargs[arg] = kwargs[arg] targets = [] if h_template is not None: h_output = os.path.splitext(h_template)[0] # We always set template as the first element in the source array # so --template consumes it. h_cmd = cmd + ['--template', '@INPUT@'] h_sources = [h_template] + sources custom_kwargs['install'] = install_header if 'install_dir' not in custom_kwargs: custom_kwargs['install_dir'] = \ state.environment.coredata.get_builtin_option('includedir') h_target = self._make_mkenum_custom_target(state, h_sources, h_output, h_cmd, custom_kwargs) targets.append(h_target) if c_template is not None: c_output = os.path.splitext(c_template)[0] # We always set template as the first element in the source array # so --template consumes it. c_cmd = cmd + ['--template', '@INPUT@'] c_sources = [c_template] + sources # Never install the C file. Complain on bug tracker if you need it. custom_kwargs['install'] = False if h_template is not None: if 'depends' in custom_kwargs: custom_kwargs['depends'] += [h_target] else: custom_kwargs['depends'] = h_target c_target = self._make_mkenum_custom_target(state, c_sources, c_output, c_cmd, custom_kwargs) targets.insert(0, c_target) if c_template is None and h_template is None: generic_cmd = cmd + ['@INPUT@'] custom_kwargs['install'] = install_header if 'install_dir' not in custom_kwargs: custom_kwargs['install_dir'] = \ state.environment.coredata.get_builtin_option('includedir') target = self._make_mkenum_custom_target(state, sources, basename, generic_cmd, custom_kwargs) return ModuleReturnValue(target, [target]) elif len(targets) == 1: return ModuleReturnValue(targets[0], [targets[0]]) else: return ModuleReturnValue(targets, targets) def mkenums_simple(self, state, args, kwargs): hdr_filename = args[0] + '.h' body_filename = args[0] + '.c' # not really needed, just for sanity checking forbidden_kwargs = ['c_template', 'h_template', 'eprod', 'fhead', 'fprod', 'ftail', 'vhead', 'vtail', 'comments'] for arg in forbidden_kwargs: if arg in kwargs: raise MesonException('mkenums_simple() does not take a %s keyword argument' % (arg, )) # kwargs to pass as-is from mkenums_simple() to mkenums() shared_kwargs = ['sources', 'install_header', 'install_dir', 'identifier_prefix', 'symbol_prefix'] mkenums_kwargs = {} for arg in shared_kwargs: if arg in kwargs: mkenums_kwargs[arg] = kwargs[arg] # .c file generation c_file_kwargs = copy.deepcopy(mkenums_kwargs) if 'sources' not in kwargs: raise MesonException('Missing keyword argument "sources".') sources = kwargs['sources'] if isinstance(sources, str): sources = [sources] elif not isinstance(sources, list): raise MesonException( 'Sources keyword argument must be a string or array.') header_prefix = kwargs.get('header_prefix', '') decl_decorator = kwargs.get('decorator', '') func_prefix = kwargs.get('function_prefix', '') body_prefix = kwargs.get('body_prefix', '') # Maybe we should write our own template files into the build dir # instead, but that seems like much more work, nice as it would be. fhead = '' if body_prefix != '': fhead += '%s\n' % body_prefix fhead += '#include "%s"\n' % hdr_filename for hdr in sources: fhead += '#include "%s"\n' % hdr fhead += ''' #define C_ENUM(v) ((gint) v) #define C_FLAGS(v) ((guint) v) ''' c_file_kwargs['fhead'] = fhead c_file_kwargs['fprod'] = ''' /* enumerations from "@basename@" */ ''' c_file_kwargs['vhead'] = ''' GType %s@enum_name@_get_type (void) { static volatile gsize gtype_id = 0; static const G@Type@Value values[] = {''' % func_prefix c_file_kwargs['vprod'] = ' { C_@TYPE@(@VALUENAME@), "@VALUENAME@", "@valuenick@" },' c_file_kwargs['vtail'] = ''' { 0, NULL, NULL } }; if (g_once_init_enter (>ype_id)) { GType new_type = g_@type@_register_static ("@EnumName@", values); g_once_init_leave (>ype_id, new_type); } return (GType) gtype_id; }''' rv = self.mkenums(state, [body_filename], c_file_kwargs) c_file = rv.return_value # .h file generation h_file_kwargs = copy.deepcopy(mkenums_kwargs) h_file_kwargs['fhead'] = '''#pragma once #include {} G_BEGIN_DECLS '''.format(header_prefix) h_file_kwargs['fprod'] = ''' /* enumerations from "@basename@" */ ''' h_file_kwargs['vhead'] = ''' {} GType {}@enum_name@_get_type (void); #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ ({}@enum_name@_get_type())'''.format(decl_decorator, func_prefix, func_prefix) h_file_kwargs['ftail'] = ''' G_END_DECLS''' rv = self.mkenums(state, [hdr_filename], h_file_kwargs) h_file = rv.return_value return ModuleReturnValue([c_file, h_file], [c_file, h_file]) @staticmethod def _make_mkenum_custom_target(state, sources, output, cmd, kwargs): custom_kwargs = { 'input': sources, 'output': output, 'capture': True, 'command': cmd } custom_kwargs.update(kwargs) return build.CustomTarget(output, state.subdir, state.subproject, custom_kwargs, # https://github.com/mesonbuild/meson/issues/973 absolute_paths=True) @permittedKwargs({'sources', 'prefix', 'install_header', 'install_dir', 'stdinc', 'nostdinc', 'internal', 'skip_source', 'valist_marshallers', 'extra_args'}) def genmarshal(self, state, args, kwargs): if len(args) != 1: raise MesonException( 'Genmarshal requires one positional argument.') output = args[0] if 'sources' not in kwargs: raise MesonException('Missing keyword argument "sources".') sources = kwargs.pop('sources') if isinstance(sources, str): sources = [sources] elif not isinstance(sources, list): raise MesonException( 'Sources keyword argument must be a string or array.') new_genmarshal = mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.53.3') cmd = [find_program('glib-genmarshal', output + '_genmarshal')] known_kwargs = ['internal', 'nostdinc', 'skip_source', 'stdinc', 'valist_marshallers', 'extra_args'] known_custom_target_kwargs = ['build_always', 'depends', 'depend_files', 'install_dir', 'install_header'] for arg, value in kwargs.items(): if arg == 'prefix': cmd += ['--prefix', value] elif arg == 'extra_args': if new_genmarshal: cmd += mesonlib.stringlistify(value) else: mlog.warning('The current version of GLib does not support extra arguments \n' 'for glib-genmarshal. You need at least GLib 2.53.3. See ', mlog.bold('https://github.com/mesonbuild/meson/pull/2049')) elif arg in known_kwargs and value: cmd += ['--' + arg.replace('_', '-')] elif arg not in known_custom_target_kwargs: raise MesonException( 'Genmarshal does not take a %s keyword argument.' % ( arg, )) install_header = kwargs.pop('install_header', False) install_dir = kwargs.pop('install_dir', None) custom_kwargs = { 'input': sources, } # https://github.com/GNOME/glib/commit/0fbc98097fac4d3e647684f344e508abae109fdf if mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.51.0'): cmd += ['--output', '@OUTPUT@'] else: custom_kwargs['capture'] = True for arg in known_custom_target_kwargs: if arg in kwargs: custom_kwargs[arg] = kwargs[arg] header_file = output + '.h' custom_kwargs['command'] = cmd + ['--body', '@INPUT@'] if mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.53.4'): # Silence any warnings about missing prototypes custom_kwargs['command'] += ['--include-header', header_file] custom_kwargs['output'] = output + '.c' body = build.CustomTarget(output + '_c', state.subdir, state.subproject, custom_kwargs) custom_kwargs['install'] = install_header if install_dir is not None: custom_kwargs['install_dir'] = install_dir if new_genmarshal: cmd += ['--pragma-once'] custom_kwargs['command'] = cmd + ['--header', '@INPUT@'] custom_kwargs['output'] = header_file header = build.CustomTarget(output + '_h', state.subdir, state.subproject, custom_kwargs) rv = [body, header] return ModuleReturnValue(rv, rv) @staticmethod def _vapi_args_to_command(prefix, variable, kwargs, accept_vapi=False): arg_list = mesonlib.extract_as_list(kwargs, variable) ret = [] for arg in arg_list: if not isinstance(arg, str): types = 'strings' + ' or InternalDependencys' if accept_vapi else '' raise MesonException('All {} must be {}'.format(variable, types)) ret.append(prefix + arg) return ret def _extract_vapi_packages(self, state, kwargs): ''' Packages are special because we need to: - Get a list of packages for the .deps file - Get a list of depends for any VapiTargets - Get package name from VapiTargets - Add include dirs for any VapiTargets ''' arg_list = kwargs.get('packages') if not arg_list: return [], [], [], [] arg_list = mesonlib.listify(arg_list) vapi_depends = [] vapi_packages = [] vapi_includes = [] ret = [] remaining_args = [] for arg in arg_list: if hasattr(arg, 'held_object'): arg = arg.held_object if isinstance(arg, InternalDependency): targets = [t for t in arg.sources if isinstance(t, VapiTarget)] for target in targets: srcdir = os.path.join(state.environment.get_source_dir(), target.get_subdir()) outdir = os.path.join(state.environment.get_build_dir(), target.get_subdir()) outfile = target.get_outputs()[0][:-5] # Strip .vapi ret.append('--vapidir=' + outdir) ret.append('--girdir=' + outdir) ret.append('--pkg=' + outfile) vapi_depends.append(target) vapi_packages.append(outfile) vapi_includes.append(srcdir) else: vapi_packages.append(arg) remaining_args.append(arg) kwargs['packages'] = remaining_args vapi_args = ret + self._vapi_args_to_command('--pkg=', 'packages', kwargs, accept_vapi=True) return vapi_args, vapi_depends, vapi_packages, vapi_includes def _generate_deps(self, state, library, packages, install_dir): outdir = state.environment.scratch_dir fname = os.path.join(outdir, library + '.deps') with open(fname, 'w') as ofile: for package in packages: ofile.write(package + '\n') return build.Data(mesonlib.File(True, outdir, fname), install_dir) def _get_vapi_link_with(self, target): link_with = [] for dep in target.get_target_dependencies(): if isinstance(dep, build.SharedLibrary): link_with.append(dep) elif isinstance(dep, GirTarget): link_with += self._get_vapi_link_with(dep) return link_with @permittedKwargs({'sources', 'packages', 'metadata_dirs', 'gir_dirs', 'vapi_dirs', 'install', 'install_dir'}) def generate_vapi(self, state, args, kwargs): if len(args) != 1: raise MesonException('The library name is required') if not isinstance(args[0], str): raise MesonException('The first argument must be the name of the library') created_values = [] library = args[0] build_dir = os.path.join(state.environment.get_build_dir(), state.subdir) source_dir = os.path.join(state.environment.get_source_dir(), state.subdir) pkg_cmd, vapi_depends, vapi_packages, vapi_includes = self._extract_vapi_packages(state, kwargs) target_name = 'generate_vapi({})'.format(library) if 'VAPIGEN' in os.environ: cmd = [find_program(os.environ['VAPIGEN'], target_name)] else: cmd = [find_program('vapigen', target_name)] cmd += ['--quiet', '--library=' + library, '--directory=' + build_dir] cmd += self._vapi_args_to_command('--vapidir=', 'vapi_dirs', kwargs) cmd += self._vapi_args_to_command('--metadatadir=', 'metadata_dirs', kwargs) cmd += self._vapi_args_to_command('--girdir=', 'gir_dirs', kwargs) cmd += pkg_cmd cmd += ['--metadatadir=' + source_dir] if 'sources' not in kwargs: raise MesonException('sources are required to generate the vapi file') inputs = mesonlib.extract_as_list(kwargs, 'sources') link_with = [] for i in inputs: if isinstance(i, str): cmd.append(os.path.join(source_dir, i)) elif hasattr(i, 'held_object') and isinstance(i.held_object, GirTarget): link_with += self._get_vapi_link_with(i.held_object) subdir = os.path.join(state.environment.get_build_dir(), i.held_object.get_subdir()) gir_file = os.path.join(subdir, i.held_object.get_outputs()[0]) cmd.append(gir_file) else: raise MesonException('Input must be a str or GirTarget') vapi_output = library + '.vapi' custom_kwargs = { 'command': cmd, 'input': inputs, 'output': vapi_output, 'depends': vapi_depends, } install_dir = kwargs.get('install_dir', os.path.join(state.environment.coredata.get_builtin_option('datadir'), 'vala', 'vapi')) if kwargs.get('install'): custom_kwargs['install'] = kwargs['install'] custom_kwargs['install_dir'] = install_dir # We shouldn't need this locally but we install it deps_target = self._generate_deps(state, library, vapi_packages, install_dir) created_values.append(deps_target) vapi_target = VapiTarget(vapi_output, state.subdir, state.subproject, custom_kwargs) # So to try our best to get this to just work we need: # - link with with the correct library # - include the vapi and dependent vapi files in sources # - add relevant directories to include dirs incs = [build.IncludeDirs(state.subdir, ['.'] + vapi_includes, False)] sources = [vapi_target] + vapi_depends rv = InternalDependency(None, incs, [], [], link_with, sources, []) created_values.append(rv) return ModuleReturnValue(rv, created_values) def initialize(): return GnomeModule() meson-0.45.1/mesonbuild/modules/python3.py0000644000175000017500000000565413254550710022117 0ustar jpakkanejpakkane00000000000000# Copyright 2016-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import sys import sysconfig from .. import mesonlib, dependencies from . import ExtensionModule from mesonbuild.modules import ModuleReturnValue from . import permittedSnippetKwargs from ..interpreterbase import noKwargs from ..interpreter import shlib_kwargs mod_kwargs = set() mod_kwargs.update(shlib_kwargs) class Python3Module(ExtensionModule): def __init__(self): super().__init__() self.snippets.add('extension_module') @permittedSnippetKwargs(mod_kwargs) def extension_module(self, interpreter, state, args, kwargs): if 'name_prefix' in kwargs: raise mesonlib.MesonException('Name_prefix is set automatically, specifying it is forbidden.') if 'name_suffix' in kwargs: raise mesonlib.MesonException('Name_suffix is set automatically, specifying it is forbidden.') host_system = state.host_machine.system if host_system == 'darwin': # Default suffix is 'dylib' but Python does not use it for extensions. suffix = 'so' elif host_system == 'windows': # On Windows the extension is pyd for some unexplainable reason. suffix = 'pyd' else: suffix = [] kwargs['name_prefix'] = '' kwargs['name_suffix'] = suffix return interpreter.func_shared_module(None, args, kwargs) @noKwargs def find_python(self, state, args, kwargs): py3 = dependencies.ExternalProgram('python3', mesonlib.python_command, silent=True) return ModuleReturnValue(py3, [py3]) @noKwargs def language_version(self, state, args, kwargs): return ModuleReturnValue(sysconfig.get_python_version(), []) @noKwargs def sysconfig_path(self, state, args, kwargs): if len(args) != 1: raise mesonlib.MesonException('sysconfig_path() requires passing the name of path to get.') path_name = args[0] valid_names = sysconfig.get_path_names() if path_name not in valid_names: raise mesonlib.MesonException('{} is not a valid path name {}.'.format(path_name, valid_names)) # Get a relative path without a prefix, e.g. lib/python3.6/site-packages path = sysconfig.get_path(path_name, vars={'base': '', 'platbase': '', 'installed_base': ''})[1:] return ModuleReturnValue(path, []) def initialize(): return Python3Module() meson-0.45.1/mesonbuild/modules/modtest.py0000644000175000017500000000164513174155420022166 0ustar jpakkanejpakkane00000000000000# Copyright 2015 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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 . import ModuleReturnValue from . import ExtensionModule from ..interpreterbase import noKwargs class TestModule(ExtensionModule): @noKwargs def print_hello(self, state, args, kwargs): print('Hello from a Meson module') rv = ModuleReturnValue(None, []) return rv def initialize(): return TestModule() meson-0.45.1/mesonbuild/modules/unstable_icestorm.py0000644000175000017500000000715713254550710024235 0ustar jpakkanejpakkane00000000000000# Copyright 2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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 .. import mesonlib, compilers, mlog from . import ExtensionModule class IceStormModule(ExtensionModule): def __init__(self): super().__init__() self.snippets.add('project') self.yosys_bin = None def detect_binaries(self, interpreter): self.yosys_bin = interpreter.func_find_program(None, ['yosys'], {}) self.arachne_bin = interpreter.func_find_program(None, ['arachne-pnr'], {}) self.icepack_bin = interpreter.func_find_program(None, ['icepack'], {}) self.iceprog_bin = interpreter.func_find_program(None, ['iceprog'], {}) self.icetime_bin = interpreter.func_find_program(None, ['icetime'], {}) def project(self, interpreter, state, args, kwargs): if not self.yosys_bin: self.detect_binaries(interpreter) result = [] if not len(args): raise mesonlib.MesonException('Project requires at least one argument, which is the project name.') proj_name = args[0] arg_sources = args[1:] if not isinstance(proj_name, str): raise mesonlib.MesonException('Argument must be a string.') kwarg_sources = kwargs.get('sources', []) if not isinstance(kwarg_sources, list): kwarg_sources = [kwarg_sources] all_sources = interpreter.source_strings_to_files(interpreter.flatten(arg_sources + kwarg_sources)) if 'constraint_file' not in kwargs: raise mesonlib.MesonException('Constraint file not specified.') constraint_file = interpreter.source_strings_to_files(kwargs['constraint_file']) if len(constraint_file) != 1: raise mesonlib.MesonException('Constraint file must contain one and only one entry.') blif_name = proj_name + '_blif' blif_fname = proj_name + '.blif' asc_name = proj_name + '_asc' asc_fname = proj_name + '.asc' bin_name = proj_name + '_bin' bin_fname = proj_name + '.bin' time_name = proj_name + '-time' upload_name = proj_name + '-upload' blif_target = interpreter.func_custom_target(None, [blif_name], { 'input': all_sources, 'output': blif_fname, 'command': [self.yosys_bin, '-q', '-p', 'synth_ice40 -blif @OUTPUT@', '@INPUT@']}) asc_target = interpreter.func_custom_target(None, [asc_name], { 'input': blif_target, 'output': asc_fname, 'command': [self.arachne_bin, '-q', '-d', '1k', '-p', constraint_file, '@INPUT@', '-o', '@OUTPUT@']}) bin_target = interpreter.func_custom_target(None, [bin_name], { 'input': asc_target, 'output': bin_fname, 'command': [self.icepack_bin, '@INPUT@', '@OUTPUT@'], 'build_by_default' : True}) up_target = interpreter.func_run_target(None, [upload_name], { 'command': [self.iceprog_bin, bin_target]}) time_target = interpreter.func_run_target(None, [time_name], { 'command' : [self.icetime_bin, bin_target]}) def initialize(): return IceStormModule() meson-0.45.1/mesonbuild/modules/__init__.py0000644000175000017500000000632313177703474022257 0ustar jpakkanejpakkane00000000000000import os from .. import build from .. import dependencies from .. import mlog from ..mesonlib import MesonException class permittedSnippetKwargs: def __init__(self, permitted): self.permitted = permitted def __call__(self, f): def wrapped(s, interpreter, state, args, kwargs): for k in kwargs: if k not in self.permitted: mlog.warning('Passed invalid keyword argument "%s". This will become a hard error in the future.' % k) return f(s, interpreter, state, args, kwargs) return wrapped _found_programs = {} class ExtensionModule: def __init__(self): self.snippets = set() # List of methods that operate only on the interpreter. def is_snippet(self, funcname): return funcname in self.snippets def find_program(program_name, target_name): if program_name in _found_programs: return _found_programs[program_name] program = dependencies.ExternalProgram(program_name) if not program.found(): m = "Target {!r} can't be generated as {!r} could not be found" raise MesonException(m.format(target_name, program_name)) _found_programs[program_name] = program return program def get_include_args(include_dirs, prefix='-I'): ''' Expand include arguments to refer to the source and build dirs by using @SOURCE_ROOT@ and @BUILD_ROOT@ for later substitution ''' if not include_dirs: return [] dirs_str = [] for incdirs in include_dirs: if hasattr(incdirs, "held_object"): dirs = incdirs.held_object else: dirs = incdirs if isinstance(dirs, str): dirs_str += ['%s%s' % (prefix, dirs)] continue # Should be build.IncludeDirs object. basedir = dirs.get_curdir() for d in dirs.get_incdirs(): expdir = os.path.join(basedir, d) srctreedir = os.path.join('@SOURCE_ROOT@', expdir) buildtreedir = os.path.join('@BUILD_ROOT@', expdir) dirs_str += ['%s%s' % (prefix, buildtreedir), '%s%s' % (prefix, srctreedir)] for d in dirs.get_extra_build_dirs(): dirs_str += ['%s%s' % (prefix, d)] return dirs_str class ModuleReturnValue: def __init__(self, return_value, new_objects): self.return_value = return_value assert(isinstance(new_objects, list)) self.new_objects = new_objects class GResourceTarget(build.CustomTarget): def __init__(self, name, subdir, subproject, kwargs): super().__init__(name, subdir, subproject, kwargs) class GResourceHeaderTarget(build.CustomTarget): def __init__(self, name, subdir, subproject, kwargs): super().__init__(name, subdir, subproject, kwargs) class GirTarget(build.CustomTarget): def __init__(self, name, subdir, subproject, kwargs): super().__init__(name, subdir, subproject, kwargs) class TypelibTarget(build.CustomTarget): def __init__(self, name, subdir, subproject, kwargs): super().__init__(name, subdir, subproject, kwargs) class VapiTarget(build.CustomTarget): def __init__(self, name, subdir, subproject, kwargs): super().__init__(name, subdir, subproject, kwargs) meson-0.45.1/mesonbuild/modules/pkgconfig.py0000644000175000017500000003316713254550710022462 0ustar jpakkanejpakkane00000000000000# Copyright 2015 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os from pathlib import PurePath from .. import build from .. import dependencies from .. import mesonlib from .. import mlog from . import ModuleReturnValue from . import ExtensionModule from ..interpreterbase import permittedKwargs class DependenciesHelper: def __init__(self, name): self.name = name self.pub_libs = [] self.pub_reqs = [] self.priv_libs = [] self.priv_reqs = [] self.cflags = [] def add_pub_libs(self, libs): libs, reqs, cflags = self._process_libs(libs, True) self.pub_libs += libs self.pub_reqs += reqs self.cflags += cflags def add_priv_libs(self, libs): libs, reqs, _ = self._process_libs(libs, False) self.priv_libs += libs self.priv_reqs += reqs def add_pub_reqs(self, reqs): self.pub_reqs += mesonlib.stringlistify(reqs) def add_priv_reqs(self, reqs): self.priv_reqs += mesonlib.stringlistify(reqs) def add_cflags(self, cflags): self.cflags += mesonlib.stringlistify(cflags) def _process_libs(self, libs, public): libs = mesonlib.listify(libs) processed_libs = [] processed_reqs = [] processed_cflags = [] for obj in libs: if hasattr(obj, 'held_object'): obj = obj.held_object if hasattr(obj, 'pcdep'): pcdeps = mesonlib.listify(obj.pcdep) processed_reqs += [i.name for i in pcdeps] elif hasattr(obj, 'generated_pc'): processed_reqs.append(obj.generated_pc) elif isinstance(obj, dependencies.PkgConfigDependency): if obj.found(): processed_reqs.append(obj.name) elif isinstance(obj, dependencies.ThreadDependency): processed_libs += obj.get_compiler().thread_link_flags(obj.env) processed_cflags += obj.get_compiler().thread_flags(obj.env) elif isinstance(obj, dependencies.Dependency): if obj.found(): processed_libs += obj.get_link_args() processed_cflags += obj.get_compile_args() elif isinstance(obj, build.SharedLibrary): processed_libs.append(obj) if public: if not hasattr(obj, 'generated_pc'): obj.generated_pc = self.name elif isinstance(obj, build.StaticLibrary): # Due to a "feature" in pkgconfig, it leaks out private dependencies. # Thus we will not add them to the pc file unless the target # we are processing is a static library. # # This way (hopefully) "pkgconfig --libs --static foobar" works # and "pkgconfig --cflags/--libs foobar" does not have any trace # of dependencies that the build file creator has not explicitly # added to the dependency list. processed_libs.append(obj) if public: if not hasattr(obj, 'generated_pc'): obj.generated_pc = self.name self.add_priv_libs(obj.get_dependencies()) self.add_priv_libs(obj.get_external_deps()) elif isinstance(obj, str): processed_libs.append(obj) else: raise mesonlib.MesonException('library argument not a string, library or dependency object.') return processed_libs, processed_reqs, processed_cflags def remove_dups(self): self.pub_libs = list(set(self.pub_libs)) self.pub_reqs = list(set(self.pub_reqs)) self.priv_libs = list(set(self.priv_libs)) self.priv_reqs = list(set(self.priv_reqs)) self.cflags = list(set(self.cflags)) # Remove from pivate libs/reqs if they are in public already self.priv_libs = [i for i in self.priv_libs if i not in self.pub_libs] self.priv_reqs = [i for i in self.priv_reqs if i not in self.pub_reqs] class PkgConfigModule(ExtensionModule): def _get_lname(self, l, msg, pcfile): # Nothing special if not l.name_prefix_set: return l.name # Sometimes people want the library to start with 'lib' everywhere, # which is achieved by setting name_prefix to '' and the target name to # 'libfoo'. In that case, try to get the pkg-config '-lfoo' arg correct. if l.prefix == '' and l.name.startswith('lib'): return l.name[3:] # If the library is imported via an import library which is always # named after the target name, '-lfoo' is correct. if l.import_filename: return l.name # In other cases, we can't guarantee that the compiler will be able to # find the library via '-lfoo', so tell the user that. mlog.warning(msg.format(l.name, 'name_prefix', l.name, pcfile)) return l.name def _escape(self, value): ''' We cannot use shlex.quote because it quotes with ' and " which does not work with pkg-config and pkgconf at all. ''' # We should always write out paths with / because pkg-config requires # spaces to be quoted with \ and that messes up on Windows: # https://bugs.freedesktop.org/show_bug.cgi?id=103203 if isinstance(value, PurePath): value = value.as_posix() return value.replace(' ', '\ ') def _make_relative(self, prefix, subdir): if isinstance(prefix, PurePath): prefix = prefix.as_posix() if isinstance(subdir, PurePath): subdir = subdir.as_posix() if subdir.startswith(prefix): subdir = subdir.replace(prefix, '') return subdir def generate_pkgconfig_file(self, state, deps, subdirs, name, description, url, version, pcfile, conflicts, variables): deps.remove_dups() coredata = state.environment.get_coredata() outdir = state.environment.scratch_dir fname = os.path.join(outdir, pcfile) prefix = PurePath(coredata.get_builtin_option('prefix')) # These always return paths relative to prefix libdir = PurePath(coredata.get_builtin_option('libdir')) incdir = PurePath(coredata.get_builtin_option('includedir')) with open(fname, 'w') as ofile: ofile.write('prefix={}\n'.format(self._escape(prefix))) ofile.write('libdir={}\n'.format(self._escape('${prefix}' / libdir))) ofile.write('includedir={}\n'.format(self._escape('${prefix}' / incdir))) if variables: ofile.write('\n') for k, v in variables: ofile.write('{}={}\n'.format(k, self._escape(v))) ofile.write('\n') ofile.write('Name: %s\n' % name) if len(description) > 0: ofile.write('Description: %s\n' % description) if len(url) > 0: ofile.write('URL: %s\n' % url) ofile.write('Version: %s\n' % version) if len(deps.pub_reqs) > 0: ofile.write('Requires: {}\n'.format(' '.join(deps.pub_reqs))) if len(deps.priv_reqs) > 0: ofile.write( 'Requires.private: {}\n'.format(' '.join(deps.priv_reqs))) if len(conflicts) > 0: ofile.write('Conflicts: {}\n'.format(' '.join(conflicts))) def generate_libs_flags(libs): msg = 'Library target {0!r} has {1!r} set. Compilers ' \ 'may not find it from its \'-l{2}\' linker flag in the ' \ '{3!r} pkg-config file.' Lflags = [] for l in libs: if isinstance(l, str): yield l else: install_dir = l.get_custom_install_dir()[0] if install_dir is False: continue if isinstance(install_dir, str): Lflag = '-L${prefix}/%s ' % self._escape(self._make_relative(prefix, install_dir)) else: # install_dir is True Lflag = '-L${libdir}' if Lflag not in Lflags: Lflags.append(Lflag) yield Lflag lname = self._get_lname(l, msg, pcfile) # If using a custom suffix, the compiler may not be able to # find the library if l.name_suffix_set: mlog.warning(msg.format(l.name, 'name_suffix', lname, pcfile)) yield '-l%s' % lname if len(deps.pub_libs) > 0: ofile.write('Libs: {}\n'.format(' '.join(generate_libs_flags(deps.pub_libs)))) if len(deps.priv_libs) > 0: ofile.write('Libs.private: {}\n'.format(' '.join(generate_libs_flags(deps.priv_libs)))) ofile.write('Cflags:') for h in subdirs: ofile.write(' ') if h == '.': ofile.write('-I${includedir}') else: ofile.write(self._escape(PurePath('-I${includedir}') / h)) for f in deps.cflags: ofile.write(' ') ofile.write(self._escape(f)) ofile.write('\n') @permittedKwargs({'libraries', 'version', 'name', 'description', 'filebase', 'subdirs', 'requires', 'requires_private', 'libraries_private', 'install_dir', 'extra_cflags', 'variables', 'url', 'd_module_versions'}) def generate(self, state, args, kwargs): if len(args) > 0: raise mesonlib.MesonException('Pkgconfig_gen takes no positional arguments.') subdirs = mesonlib.stringlistify(kwargs.get('subdirs', ['.'])) version = kwargs.get('version', None) if not isinstance(version, str): raise mesonlib.MesonException('Version must be specified.') name = kwargs.get('name', None) if not isinstance(name, str): raise mesonlib.MesonException('Name not specified.') filebase = kwargs.get('filebase', name) if not isinstance(filebase, str): raise mesonlib.MesonException('Filebase must be a string.') description = kwargs.get('description', None) if not isinstance(description, str): raise mesonlib.MesonException('Description is not a string.') url = kwargs.get('url', '') if not isinstance(url, str): raise mesonlib.MesonException('URL is not a string.') conflicts = mesonlib.stringlistify(kwargs.get('conflicts', [])) deps = DependenciesHelper(filebase) deps.add_pub_libs(kwargs.get('libraries', [])) deps.add_priv_libs(kwargs.get('libraries_private', [])) deps.add_pub_reqs(kwargs.get('requires', [])) deps.add_priv_reqs(kwargs.get('requires_private', [])) deps.add_cflags(kwargs.get('extra_cflags', [])) dversions = kwargs.get('d_module_versions', None) if dversions: compiler = state.environment.coredata.compilers.get('d') if compiler: deps.add_cflags(compiler.get_feature_args({'versions': dversions})) def parse_variable_list(stringlist): reserved = ['prefix', 'libdir', 'includedir'] variables = [] for var in stringlist: # foo=bar=baz is ('foo', 'bar=baz') l = var.split('=', 1) if len(l) < 2: raise mesonlib.MesonException('Invalid variable "{}". Variables must be in \'name=value\' format'.format(var)) name, value = l[0].strip(), l[1].strip() if not name or not value: raise mesonlib.MesonException('Invalid variable "{}". Variables must be in \'name=value\' format'.format(var)) # Variable names must not contain whitespaces if any(c.isspace() for c in name): raise mesonlib.MesonException('Invalid whitespace in assignment "{}"'.format(var)) if name in reserved: raise mesonlib.MesonException('Variable "{}" is reserved'.format(name)) variables.append((name, value)) return variables variables = parse_variable_list(mesonlib.stringlistify(kwargs.get('variables', []))) pcfile = filebase + '.pc' pkgroot = kwargs.get('install_dir', None) if pkgroot is None: pkgroot = os.path.join(state.environment.coredata.get_builtin_option('libdir'), 'pkgconfig') if not isinstance(pkgroot, str): raise mesonlib.MesonException('Install_dir must be a string.') self.generate_pkgconfig_file(state, deps, subdirs, name, description, url, version, pcfile, conflicts, variables) res = build.Data(mesonlib.File(True, state.environment.get_scratch_dir(), pcfile), pkgroot) return ModuleReturnValue(res, [res]) def initialize(): return PkgConfigModule() meson-0.45.1/mesonbuild/mparser.py0000644000175000017500000005766513243342213020520 0ustar jpakkanejpakkane00000000000000# Copyright 2014-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import re from .mesonlib import MesonException from . import mlog class ParseException(MesonException): def __init__(self, text, line, lineno, colno): # Format as error message, followed by the line with the error, followed by a caret to show the error column. super().__init__("%s\n%s\n%s" % (text, line, '%s^' % (' ' * colno))) self.lineno = lineno self.colno = colno class BlockParseException(MesonException): def __init__(self, text, line, lineno, colno, start_line, start_lineno, start_colno): # This can be formatted in two ways - one if the block start and end are on the same line, and a different way if they are on different lines. if lineno == start_lineno: # If block start and end are on the same line, it is formatted as: # Error message # Followed by the line with the error # Followed by a caret to show the block start # Followed by underscores # Followed by a caret to show the block end. super().__init__("%s\n%s\n%s" % (text, line, '%s^%s^' % (' ' * start_colno, '_' * (colno - start_colno - 1)))) else: # If block start and end are on different lines, it is formatted as: # Error message # Followed by the line with the error # Followed by a caret to show the error column. # Followed by a message saying where the block started. # Followed by the line of the block start. # Followed by a caret for the block start. super().__init__("%s\n%s\n%s\nFor a block that started at %d,%d\n%s\n%s" % (text, line, '%s^' % (' ' * colno), start_lineno, start_colno, start_line, "%s^" % (' ' * start_colno))) self.lineno = lineno self.colno = colno class Token: def __init__(self, tid, subdir, line_start, lineno, colno, bytespan, value): self.tid = tid self.subdir = subdir self.line_start = line_start self.lineno = lineno self.colno = colno self.bytespan = bytespan self.value = value def __eq__(self, other): if isinstance(other, str): return self.tid == other return self.tid == other.tid class Lexer: def __init__(self, code): self.code = code self.keywords = {'true', 'false', 'if', 'else', 'elif', 'endif', 'and', 'or', 'not', 'foreach', 'endforeach'} self.token_specification = [ # Need to be sorted longest to shortest. ('ignore', re.compile(r'[ \t]')), ('id', re.compile('[_a-zA-Z][_0-9a-zA-Z]*')), ('hexnumber', re.compile('0[xX][0-9a-fA-F]+')), ('number', re.compile(r'\d+')), ('eol_cont', re.compile(r'\\\n')), ('eol', re.compile(r'\n')), ('multiline_string', re.compile(r"'''(.|\n)*?'''", re.M)), ('comment', re.compile(r'#.*')), ('lparen', re.compile(r'\(')), ('rparen', re.compile(r'\)')), ('lbracket', re.compile(r'\[')), ('rbracket', re.compile(r'\]')), ('dblquote', re.compile(r'"')), ('string', re.compile(r"'([^'\\]|(\\.))*'")), ('comma', re.compile(r',')), ('plusassign', re.compile(r'\+=')), ('dot', re.compile(r'\.')), ('plus', re.compile(r'\+')), ('dash', re.compile(r'-')), ('star', re.compile(r'\*')), ('percent', re.compile(r'%')), ('fslash', re.compile(r'/')), ('colon', re.compile(r':')), ('equal', re.compile(r'==')), ('nequal', re.compile(r'!=')), ('assign', re.compile(r'=')), ('le', re.compile(r'<=')), ('lt', re.compile(r'<')), ('ge', re.compile(r'>=')), ('gt', re.compile(r'>')), ('questionmark', re.compile(r'\?')), ] def getline(self, line_start): return self.code[line_start:self.code.find('\n', line_start)] def lex(self, subdir): line_start = 0 lineno = 1 loc = 0 par_count = 0 bracket_count = 0 col = 0 newline_rx = re.compile(r'(? 1: lineno += len(lines) - 1 line_start = mo.end() - len(lines[-1]) elif tid == 'number': value = int(match_text) elif tid == 'hexnumber': tid = 'number' value = int(match_text, base=16) elif tid == 'eol' or tid == 'eol_cont': lineno += 1 line_start = loc if par_count > 0 or bracket_count > 0: break elif tid == 'id': if match_text in self.keywords: tid = match_text else: value = match_text yield Token(tid, subdir, curline_start, curline, col, bytespan, value) break if not matched: raise ParseException('lexer', self.getline(line_start), lineno, col) class ElementaryNode: def __init__(self, token): self.lineno = token.lineno self.subdir = token.subdir self.colno = token.colno self.value = token.value self.bytespan = token.bytespan class BooleanNode(ElementaryNode): def __init__(self, token, value): super().__init__(token) self.value = value assert(isinstance(self.value, bool)) class IdNode(ElementaryNode): def __init__(self, token): super().__init__(token) assert(isinstance(self.value, str)) def __str__(self): return "Id node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno) class NumberNode(ElementaryNode): def __init__(self, token): super().__init__(token) assert(isinstance(self.value, int)) class StringNode(ElementaryNode): def __init__(self, token): super().__init__(token) assert(isinstance(self.value, str)) def __str__(self): return "String node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno) class ArrayNode: def __init__(self, args): self.subdir = args.subdir self.lineno = args.lineno self.colno = args.colno self.args = args class EmptyNode: def __init__(self, lineno, colno): self.subdir = '' self.lineno = lineno self.colno = colno self.value = None class OrNode: def __init__(self, left, right): self.subdir = left.subdir self.lineno = left.lineno self.colno = left.colno self.left = left self.right = right class AndNode: def __init__(self, left, right): self.subdir = left.subdir self.lineno = left.lineno self.colno = left.colno self.left = left self.right = right class ComparisonNode: def __init__(self, ctype, left, right): self.lineno = left.lineno self.colno = left.colno self.subdir = left.subdir self.left = left self.right = right self.ctype = ctype class ArithmeticNode: def __init__(self, operation, left, right): self.subdir = left.subdir self.lineno = left.lineno self.colno = left.colno self.left = left self.right = right self.operation = operation class NotNode: def __init__(self, location_node, value): self.subdir = location_node.subdir self.lineno = location_node.lineno self.colno = location_node.colno self.value = value class CodeBlockNode: def __init__(self, location_node): self.subdir = location_node.subdir self.lineno = location_node.lineno self.colno = location_node.colno self.lines = [] class IndexNode: def __init__(self, iobject, index): self.iobject = iobject self.index = index self.subdir = iobject.subdir self.lineno = iobject.lineno self.colno = iobject.colno class MethodNode: def __init__(self, subdir, lineno, colno, source_object, name, args): self.subdir = subdir self.lineno = lineno self.colno = colno self.source_object = source_object self.name = name assert(isinstance(self.name, str)) self.args = args class FunctionNode: def __init__(self, subdir, lineno, colno, func_name, args): self.subdir = subdir self.lineno = lineno self.colno = colno self.func_name = func_name assert(isinstance(func_name, str)) self.args = args class AssignmentNode: def __init__(self, lineno, colno, var_name, value): self.lineno = lineno self.colno = colno self.var_name = var_name assert(isinstance(var_name, str)) self.value = value class PlusAssignmentNode: def __init__(self, lineno, colno, var_name, value): self.lineno = lineno self.colno = colno self.var_name = var_name assert(isinstance(var_name, str)) self.value = value class ForeachClauseNode: def __init__(self, lineno, colno, varname, items, block): self.lineno = lineno self.colno = colno self.varname = varname self.items = items self.block = block class IfClauseNode: def __init__(self, lineno, colno): self.lineno = lineno self.colno = colno self.ifs = [] self.elseblock = EmptyNode(lineno, colno) class UMinusNode: def __init__(self, current_location, value): self.subdir = current_location.subdir self.lineno = current_location.lineno self.colno = current_location.colno self.value = value class IfNode: def __init__(self, lineno, colno, condition, block): self.lineno = lineno self.colno = colno self.condition = condition self.block = block class TernaryNode: def __init__(self, lineno, colno, condition, trueblock, falseblock): self.lineno = lineno self.colno = colno self.condition = condition self.trueblock = trueblock self.falseblock = falseblock class ArgumentNode: def __init__(self, token): self.lineno = token.lineno self.colno = token.colno self.subdir = token.subdir self.arguments = [] self.commas = [] self.kwargs = {} self.order_error = False def prepend(self, statement): if self.num_kwargs() > 0: self.order_error = True if not isinstance(statement, EmptyNode): self.arguments = [statement] + self.arguments def append(self, statement): if self.num_kwargs() > 0: self.order_error = True if not isinstance(statement, EmptyNode): self.arguments += [statement] def set_kwarg(self, name, value): if name in self.kwargs: mlog.warning('Keyword argument "{}" defined multiple times.'.format(name), location=self) mlog.warning('This will be an error in future Meson releases.') self.kwargs[name] = value def num_args(self): return len(self.arguments) def num_kwargs(self): return len(self.kwargs) def incorrect_order(self): return self.order_error def __len__(self): return self.num_args() # Fixme comparison_map = {'equal': '==', 'nequal': '!=', 'lt': '<', 'le': '<=', 'gt': '>', 'ge': '>=' } # Recursive descent parser for Meson's definition language. # Very basic apart from the fact that we have many precedence # levels so there are not enough words to describe them all. # Enter numbering: # # 1 assignment # 2 or # 3 and # 4 comparison # 5 arithmetic # 6 negation # 7 funcall, method call # 8 parentheses # 9 plain token class Parser: def __init__(self, code, subdir): self.lexer = Lexer(code) self.stream = self.lexer.lex(subdir) self.current = Token('eof', '', 0, 0, 0, (0, 0), None) self.getsym() self.in_ternary = False def getsym(self): try: self.current = next(self.stream) except StopIteration: self.current = Token('eof', '', self.current.line_start, self.current.lineno, self.current.colno + self.current.bytespan[1] - self.current.bytespan[0], (0, 0), None) def getline(self): return self.lexer.getline(self.current.line_start) def accept(self, s): if self.current.tid == s: self.getsym() return True return False def expect(self, s): if self.accept(s): return True raise ParseException('Expecting %s got %s.' % (s, self.current.tid), self.getline(), self.current.lineno, self.current.colno) def block_expect(self, s, block_start): if self.accept(s): return True raise BlockParseException('Expecting %s got %s.' % (s, self.current.tid), self.getline(), self.current.lineno, self.current.colno, self.lexer.getline(block_start.line_start), block_start.lineno, block_start.colno) def parse(self): block = self.codeblock() self.expect('eof') return block def statement(self): return self.e1() def e1(self): left = self.e2() if self.accept('plusassign'): value = self.e1() if not isinstance(left, IdNode): raise ParseException('Plusassignment target must be an id.', self.getline(), left.lineno, left.colno) return PlusAssignmentNode(left.lineno, left.colno, left.value, value) elif self.accept('assign'): value = self.e1() if not isinstance(left, IdNode): raise ParseException('Assignment target must be an id.', self.getline(), left.lineno, left.colno) return AssignmentNode(left.lineno, left.colno, left.value, value) elif self.accept('questionmark'): if self.in_ternary: raise ParseException('Nested ternary operators are not allowed.', self.getline(), left.lineno, left.colno) self.in_ternary = True trueblock = self.e1() self.expect('colon') falseblock = self.e1() self.in_ternary = False return TernaryNode(left.lineno, left.colno, left, trueblock, falseblock) return left def e2(self): left = self.e3() while self.accept('or'): if isinstance(left, EmptyNode): raise ParseException('Invalid or clause.', self.getline(), left.lineno, left.colno) left = OrNode(left, self.e3()) return left def e3(self): left = self.e4() while self.accept('and'): if isinstance(left, EmptyNode): raise ParseException('Invalid and clause.', self.getline(), left.lineno, left.colno) left = AndNode(left, self.e4()) return left def e4(self): left = self.e5() for nodename, operator_type in comparison_map.items(): if self.accept(nodename): return ComparisonNode(operator_type, left, self.e5()) return left def e5(self): return self.e5add() def e5add(self): left = self.e5sub() if self.accept('plus'): return ArithmeticNode('add', left, self.e5add()) return left def e5sub(self): left = self.e5mod() if self.accept('dash'): return ArithmeticNode('sub', left, self.e5sub()) return left def e5mod(self): left = self.e5mul() if self.accept('percent'): return ArithmeticNode('mod', left, self.e5mod()) return left def e5mul(self): left = self.e5div() if self.accept('star'): return ArithmeticNode('mul', left, self.e5mul()) return left def e5div(self): left = self.e6() if self.accept('fslash'): return ArithmeticNode('div', left, self.e5div()) return left def e6(self): if self.accept('not'): return NotNode(self.current, self.e7()) if self.accept('dash'): return UMinusNode(self.current, self.e7()) return self.e7() def e7(self): left = self.e8() block_start = self.current if self.accept('lparen'): args = self.args() self.block_expect('rparen', block_start) if not isinstance(left, IdNode): raise ParseException('Function call must be applied to plain id', self.getline(), left.lineno, left.colno) left = FunctionNode(left.subdir, left.lineno, left.colno, left.value, args) go_again = True while go_again: go_again = False if self.accept('dot'): go_again = True left = self.method_call(left) if self.accept('lbracket'): go_again = True left = self.index_call(left) return left def e8(self): block_start = self.current if self.accept('lparen'): e = self.statement() self.block_expect('rparen', block_start) return e elif self.accept('lbracket'): args = self.args() self.block_expect('rbracket', block_start) return ArrayNode(args) else: return self.e9() def e9(self): t = self.current if self.accept('true'): return BooleanNode(t, True) if self.accept('false'): return BooleanNode(t, False) if self.accept('id'): return IdNode(t) if self.accept('number'): return NumberNode(t) if self.accept('string'): return StringNode(t) return EmptyNode(self.current.lineno, self.current.colno) def args(self): s = self.statement() a = ArgumentNode(s) while not isinstance(s, EmptyNode): potential = self.current if self.accept('comma'): a.commas.append(potential) a.append(s) elif self.accept('colon'): if not isinstance(s, IdNode): raise ParseException('Keyword argument must be a plain identifier.', self.getline(), s.lineno, s.colno) a.set_kwarg(s.value, self.statement()) potential = self.current if not self.accept('comma'): return a a.commas.append(potential) else: a.append(s) return a s = self.statement() return a def method_call(self, source_object): methodname = self.e9() if not(isinstance(methodname, IdNode)): raise ParseException('Method name must be plain id', self.getline(), self.current.lineno, self.current.colno) self.expect('lparen') args = self.args() self.expect('rparen') method = MethodNode(methodname.subdir, methodname.lineno, methodname.colno, source_object, methodname.value, args) if self.accept('dot'): return self.method_call(method) return method def index_call(self, source_object): index_statement = self.statement() self.expect('rbracket') return IndexNode(source_object, index_statement) def foreachblock(self): t = self.current self.expect('id') varname = t self.expect('colon') items = self.statement() block = self.codeblock() return ForeachClauseNode(varname.lineno, varname.colno, varname, items, block) def ifblock(self): condition = self.statement() clause = IfClauseNode(condition.lineno, condition.colno) self.expect('eol') block = self.codeblock() clause.ifs.append(IfNode(clause.lineno, clause.colno, condition, block)) self.elseifblock(clause) clause.elseblock = self.elseblock() return clause def elseifblock(self, clause): while self.accept('elif'): s = self.statement() self.expect('eol') b = self.codeblock() clause.ifs.append(IfNode(s.lineno, s.colno, s, b)) def elseblock(self): if self.accept('else'): self.expect('eol') return self.codeblock() def line(self): block_start = self.current if self.current == 'eol': return EmptyNode(self.current.lineno, self.current.colno) if self.accept('if'): block = self.ifblock() self.block_expect('endif', block_start) return block if self.accept('foreach'): block = self.foreachblock() self.block_expect('endforeach', block_start) return block return self.statement() def codeblock(self): block = CodeBlockNode(self.current) cond = True while cond: curline = self.line() if not isinstance(curline, EmptyNode): block.lines.append(curline) cond = self.accept('eol') return block meson-0.45.1/mesonbuild/interpreter.py0000644000175000017500000044254213254550710021407 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2018 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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 . import mparser from . import environment from . import coredata from . import dependencies from . import mlog from . import build from . import optinterpreter from . import compilers from .wrap import wrap, WrapMode from . import mesonlib from .mesonlib import FileMode, Popen_safe, listify, extract_as_list from .dependencies import ExternalProgram from .dependencies import InternalDependency, Dependency, DependencyException from .interpreterbase import InterpreterBase from .interpreterbase import check_stringlist, noPosargs, noKwargs, stringArgs, permittedKwargs from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode from .interpreterbase import InterpreterObject, MutableInterpreterObject, Disabler from .modules import ModuleReturnValue import os, sys, shutil, uuid import re, shlex from collections import namedtuple from pathlib import PurePath import importlib def stringifyUserArguments(args): if isinstance(args, list): return '[%s]' % ', '.join([stringifyUserArguments(x) for x in args]) elif isinstance(args, int): return str(args) elif isinstance(args, str): return "'%s'" % args raise InvalidArguments('Function accepts only strings, integers, lists and lists thereof.') class ObjectHolder: def __init__(self, obj): self.held_object = obj def __repr__(self): return ''.format(self.held_object) class TryRunResultHolder(InterpreterObject): def __init__(self, res): super().__init__() self.res = res self.methods.update({'returncode': self.returncode_method, 'compiled': self.compiled_method, 'stdout': self.stdout_method, 'stderr': self.stderr_method, }) def returncode_method(self, args, kwargs): return self.res.returncode def compiled_method(self, args, kwargs): return self.res.compiled def stdout_method(self, args, kwargs): return self.res.stdout def stderr_method(self, args, kwargs): return self.res.stderr class RunProcess(InterpreterObject): def __init__(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False): super().__init__() if not isinstance(cmd, ExternalProgram): raise AssertionError('BUG: RunProcess must be passed an ExternalProgram') pc, self.stdout, self.stderr = self.run_command(cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir) self.returncode = pc.returncode self.methods.update({'returncode': self.returncode_method, 'stdout': self.stdout_method, 'stderr': self.stderr_method, }) def run_command(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir): command_array = cmd.get_command() + args env = {'MESON_SOURCE_ROOT': source_dir, 'MESON_BUILD_ROOT': build_dir, 'MESON_SUBDIR': subdir, 'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in mesonintrospect]), } if in_builddir: cwd = os.path.join(build_dir, subdir) else: cwd = os.path.join(source_dir, subdir) child_env = os.environ.copy() child_env.update(env) mlog.debug('Running command:', ' '.join(command_array)) try: p, o, e = Popen_safe(command_array, env=child_env, cwd=cwd) mlog.debug('--- stdout----') mlog.debug(o) mlog.debug('----stderr----') mlog.debug(e) mlog.debug('') return p, o, e except FileNotFoundError: raise InterpreterException('Could not execute command "%s".' % ' '.join(command_array)) def returncode_method(self, args, kwargs): return self.returncode def stdout_method(self, args, kwargs): return self.stdout def stderr_method(self, args, kwargs): return self.stderr class ConfigureFileHolder(InterpreterObject, ObjectHolder): def __init__(self, subdir, sourcename, targetname, configuration_data): InterpreterObject.__init__(self) ObjectHolder.__init__(self, build.ConfigureFile(subdir, sourcename, targetname, configuration_data)) class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder): def __init__(self): MutableInterpreterObject.__init__(self) ObjectHolder.__init__(self, build.EnvironmentVariables()) self.methods.update({'set': self.set_method, 'append': self.append_method, 'prepend': self.prepend_method, }) def __repr__(self): repr_str = "<{0}: {1}>" return repr_str.format(self.__class__.__name__, self.held_object.envvars) @stringArgs def add_var(self, method, args, kwargs): if not isinstance(kwargs.get("separator", ""), str): raise InterpreterException("EnvironmentVariablesHolder methods 'separator'" " argument needs to be a string.") if len(args) < 2: raise InterpreterException("EnvironmentVariablesHolder methods require at least" "2 arguments, first is the name of the variable and" " following one are values") self.held_object.envvars.append((method, args[0], args[1:], kwargs)) def set_method(self, args, kwargs): self.add_var(self.held_object.set, args, kwargs) def append_method(self, args, kwargs): self.add_var(self.held_object.append, args, kwargs) def prepend_method(self, args, kwargs): self.add_var(self.held_object.prepend, args, kwargs) class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder): def __init__(self): MutableInterpreterObject.__init__(self) self.used = False # These objects become immutable after use in configure_file. ObjectHolder.__init__(self, build.ConfigurationData()) self.methods.update({'set': self.set_method, 'set10': self.set10_method, 'set_quoted': self.set_quoted_method, 'has': self.has_method, 'get': self.get_method, 'get_unquoted': self.get_unquoted_method, 'merge_from': self.merge_from_method, }) def is_used(self): return self.used def mark_used(self): self.used = True def validate_args(self, args, kwargs): if len(args) != 2: raise InterpreterException("Configuration set requires 2 arguments.") if self.used: raise InterpreterException("Can not set values on configuration object that has been used.") name = args[0] val = args[1] desc = kwargs.get('description', None) if not isinstance(name, str): raise InterpreterException("First argument to set must be a string.") if desc is not None and not isinstance(desc, str): raise InterpreterException('Description must be a string.') return name, val, desc def set_method(self, args, kwargs): (name, val, desc) = self.validate_args(args, kwargs) self.held_object.values[name] = (val, desc) def set_quoted_method(self, args, kwargs): (name, val, desc) = self.validate_args(args, kwargs) if not isinstance(val, str): raise InterpreterException("Second argument to set_quoted must be a string.") escaped_val = '\\"'.join(val.split('"')) self.held_object.values[name] = ('"' + escaped_val + '"', desc) def set10_method(self, args, kwargs): (name, val, desc) = self.validate_args(args, kwargs) if val: self.held_object.values[name] = (1, desc) else: self.held_object.values[name] = (0, desc) def has_method(self, args, kwargs): return args[0] in self.held_object.values def get_method(self, args, kwargs): if len(args) < 1 or len(args) > 2: raise InterpreterException('Get method takes one or two arguments.') name = args[0] if name in self.held_object: return self.held_object.get(name)[0] if len(args) > 1: return args[1] raise InterpreterException('Entry %s not in configuration data.' % name) def get_unquoted_method(self, args, kwargs): if len(args) < 1 or len(args) > 2: raise InterpreterException('Get method takes one or two arguments.') name = args[0] if name in self.held_object: val = self.held_object.get(name)[0] elif len(args) > 1: val = args[1] else: raise InterpreterException('Entry %s not in configuration data.' % name) if val[0] == '"' and val[-1] == '"': return val[1:-1] return val def get(self, name): return self.held_object.values[name] # (val, desc) def keys(self): return self.held_object.values.keys() def merge_from_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('Merge_from takes one positional argument.') from_object = args[0] if not isinstance(from_object, ConfigurationDataHolder): raise InterpreterException('Merge_from argument must be a configuration data object.') from_object = from_object.held_object for k, v in from_object.values.items(): self.held_object.values[k] = v # Interpreter objects can not be pickled so we must have # these wrappers. class DependencyHolder(InterpreterObject, ObjectHolder): def __init__(self, dep): InterpreterObject.__init__(self) ObjectHolder.__init__(self, dep) self.methods.update({'found': self.found_method, 'type_name': self.type_name_method, 'version': self.version_method, 'get_pkgconfig_variable': self.pkgconfig_method, 'get_configtool_variable': self.configtool_method, }) def type_name_method(self, args, kwargs): return self.held_object.type_name def found_method(self, args, kwargs): if self.held_object.type_name == 'internal': return True return self.held_object.found() def version_method(self, args, kwargs): return self.held_object.get_version() def pkgconfig_method(self, args, kwargs): args = listify(args) if len(args) != 1: raise InterpreterException('get_pkgconfig_variable takes exactly one argument.') varname = args[0] if not isinstance(varname, str): raise InterpreterException('Variable name must be a string.') return self.held_object.get_pkgconfig_variable(varname, kwargs) def configtool_method(self, args, kwargs): args = listify(args) if len(args) != 1: raise InterpreterException('get_configtool_variable takes exactly one argument.') varname = args[0] if not isinstance(varname, str): raise InterpreterException('Variable name must be a string.') return self.held_object.get_configtool_variable(varname) class InternalDependencyHolder(InterpreterObject, ObjectHolder): def __init__(self, dep): InterpreterObject.__init__(self) ObjectHolder.__init__(self, dep) self.methods.update({'found': self.found_method, 'version': self.version_method, }) def found_method(self, args, kwargs): return True def version_method(self, args, kwargs): return self.held_object.get_version() class ExternalProgramHolder(InterpreterObject, ObjectHolder): def __init__(self, ep): InterpreterObject.__init__(self) ObjectHolder.__init__(self, ep) self.methods.update({'found': self.found_method, 'path': self.path_method}) def found_method(self, args, kwargs): return self.found() def path_method(self, args, kwargs): return self.held_object.get_path() def found(self): return self.held_object.found() def get_command(self): return self.held_object.get_command() def get_name(self): return self.held_object.get_name() class ExternalLibraryHolder(InterpreterObject, ObjectHolder): def __init__(self, el): InterpreterObject.__init__(self) ObjectHolder.__init__(self, el) self.methods.update({'found': self.found_method}) def found(self): return self.held_object.found() def found_method(self, args, kwargs): return self.found() def get_name(self): return self.held_object.name def get_compile_args(self): return self.held_object.get_compile_args() def get_link_args(self): return self.held_object.get_link_args() def get_exe_args(self): return self.held_object.get_exe_args() class GeneratorHolder(InterpreterObject, ObjectHolder): def __init__(self, interpreter, args, kwargs): InterpreterObject.__init__(self) self.interpreter = interpreter ObjectHolder.__init__(self, build.Generator(args, kwargs)) self.methods.update({'process': self.process_method}) def process_method(self, args, kwargs): extras = mesonlib.stringlistify(kwargs.get('extra_args', [])) if 'preserve_path_from' in kwargs: preserve_path_from = kwargs['preserve_path_from'] if not isinstance(preserve_path_from, str): raise InvalidArguments('Preserve_path_from must be a string.') preserve_path_from = os.path.normpath(preserve_path_from) if not os.path.isabs(preserve_path_from): # This is a bit of a hack. Fix properly before merging. raise InvalidArguments('Preserve_path_from must be an absolute path for now. Sorry.') else: preserve_path_from = None gl = self.held_object.process_files('Generator', args, self.interpreter, preserve_path_from, extra_args=extras) return GeneratedListHolder(gl) class GeneratedListHolder(InterpreterObject, ObjectHolder): def __init__(self, arg1, extra_args=[]): InterpreterObject.__init__(self) if isinstance(arg1, GeneratorHolder): ObjectHolder.__init__(self, build.GeneratedList(arg1.held_object, extra_args)) else: ObjectHolder.__init__(self, arg1) def __repr__(self): r = '<{}: {!r}>' return r.format(self.__class__.__name__, self.held_object.get_outputs()) def add_file(self, a): self.held_object.add_file(a) class BuildMachine(InterpreterObject, ObjectHolder): def __init__(self, compilers): self.compilers = compilers InterpreterObject.__init__(self) held_object = environment.MachineInfo(environment.detect_system(), environment.detect_cpu_family(self.compilers), environment.detect_cpu(self.compilers), sys.byteorder) ObjectHolder.__init__(self, held_object) self.methods.update({'system': self.system_method, 'cpu_family': self.cpu_family_method, 'cpu': self.cpu_method, 'endian': self.endian_method, }) def cpu_family_method(self, args, kwargs): return self.held_object.cpu_family def cpu_method(self, args, kwargs): return self.held_object.cpu def system_method(self, args, kwargs): return self.held_object.system def endian_method(self, args, kwargs): return self.held_object.endian # This class will provide both host_machine and # target_machine class CrossMachineInfo(InterpreterObject, ObjectHolder): def __init__(self, cross_info): InterpreterObject.__init__(self) minimum_cross_info = {'cpu', 'cpu_family', 'endian', 'system'} if set(cross_info) < minimum_cross_info: raise InterpreterException( 'Machine info is currently {}\n'.format(cross_info) + 'but is missing {}.'.format(minimum_cross_info - set(cross_info))) self.info = cross_info minfo = environment.MachineInfo(cross_info['system'], cross_info['cpu_family'], cross_info['cpu'], cross_info['endian']) ObjectHolder.__init__(self, minfo) self.methods.update({'system': self.system_method, 'cpu': self.cpu_method, 'cpu_family': self.cpu_family_method, 'endian': self.endian_method, }) def cpu_family_method(self, args, kwargs): return self.held_object.cpu_family def cpu_method(self, args, kwargs): return self.held_object.cpu def system_method(self, args, kwargs): return self.held_object.system def endian_method(self, args, kwargs): return self.held_object.endian class IncludeDirsHolder(InterpreterObject, ObjectHolder): def __init__(self, idobj): InterpreterObject.__init__(self) ObjectHolder.__init__(self, idobj) class Headers(InterpreterObject): def __init__(self, sources, kwargs): InterpreterObject.__init__(self) self.sources = sources self.install_subdir = kwargs.get('subdir', '') self.custom_install_dir = kwargs.get('install_dir', None) if self.custom_install_dir is not None: if not isinstance(self.custom_install_dir, str): raise InterpreterException('Custom_install_dir must be a string.') def set_install_subdir(self, subdir): self.install_subdir = subdir def get_install_subdir(self): return self.install_subdir def get_sources(self): return self.sources def get_custom_install_dir(self): return self.custom_install_dir class DataHolder(InterpreterObject, ObjectHolder): def __init__(self, data): InterpreterObject.__init__(self) ObjectHolder.__init__(self, data) def get_source_subdir(self): return self.held_object.source_subdir def get_sources(self): return self.held_object.sources def get_install_dir(self): return self.held_object.install_dir class InstallDir(InterpreterObject): def __init__(self, src_subdir, inst_subdir, install_dir, install_mode, exclude, strip_directory): InterpreterObject.__init__(self) self.source_subdir = src_subdir self.installable_subdir = inst_subdir self.install_dir = install_dir self.install_mode = install_mode self.exclude = exclude self.strip_directory = strip_directory class Man(InterpreterObject): def __init__(self, sources, kwargs): InterpreterObject.__init__(self) self.sources = sources self.validate_sources() self.custom_install_dir = kwargs.get('install_dir', None) if self.custom_install_dir is not None and not isinstance(self.custom_install_dir, str): raise InterpreterException('Custom_install_dir must be a string.') def validate_sources(self): for s in self.sources: try: num = int(s.split('.')[-1]) except (IndexError, ValueError): num = 0 if num < 1 or num > 8: raise InvalidArguments('Man file must have a file extension of a number between 1 and 8') def get_custom_install_dir(self): return self.custom_install_dir def get_sources(self): return self.sources class GeneratedObjectsHolder(InterpreterObject, ObjectHolder): def __init__(self, held_object): InterpreterObject.__init__(self) ObjectHolder.__init__(self, held_object) class TargetHolder(InterpreterObject, ObjectHolder): def __init__(self, target, interp): InterpreterObject.__init__(self) ObjectHolder.__init__(self, target) self.interpreter = interp class BuildTargetHolder(TargetHolder): def __init__(self, target, interp): super().__init__(target, interp) self.methods.update({'extract_objects': self.extract_objects_method, 'extract_all_objects': self.extract_all_objects_method, 'get_id': self.get_id_method, 'outdir': self.outdir_method, 'full_path': self.full_path_method, 'private_dir_include': self.private_dir_include_method, }) def __repr__(self): r = '<{} {}: {}>' h = self.held_object return r.format(self.__class__.__name__, h.get_id(), h.filename) def is_cross(self): return self.held_object.is_cross() def private_dir_include_method(self, args, kwargs): return IncludeDirsHolder(build.IncludeDirs('', [], False, [self.interpreter.backend.get_target_private_dir(self.held_object)])) def full_path_method(self, args, kwargs): return self.interpreter.backend.get_target_filename_abs(self.held_object) def outdir_method(self, args, kwargs): return self.interpreter.backend.get_target_dir(self.held_object) def extract_objects_method(self, args, kwargs): gobjs = self.held_object.extract_objects(args) return GeneratedObjectsHolder(gobjs) def extract_all_objects_method(self, args, kwargs): gobjs = self.held_object.extract_all_objects() return GeneratedObjectsHolder(gobjs) def get_id_method(self, args, kwargs): return self.held_object.get_id() class ExecutableHolder(BuildTargetHolder): def __init__(self, target, interp): super().__init__(target, interp) class StaticLibraryHolder(BuildTargetHolder): def __init__(self, target, interp): super().__init__(target, interp) class SharedLibraryHolder(BuildTargetHolder): def __init__(self, target, interp): super().__init__(target, interp) class SharedModuleHolder(BuildTargetHolder): def __init__(self, target, interp): super().__init__(target, interp) class JarHolder(BuildTargetHolder): def __init__(self, target, interp): super().__init__(target, interp) class CustomTargetIndexHolder(InterpreterObject, ObjectHolder): def __init__(self, object_to_hold): InterpreterObject.__init__(self) ObjectHolder.__init__(self, object_to_hold) class CustomTargetHolder(TargetHolder): def __init__(self, target, interp): super().__init__(target, interp) self.methods.update({'full_path': self.full_path_method, }) def __repr__(self): r = '<{} {}: {}>' h = self.held_object return r.format(self.__class__.__name__, h.get_id(), h.command) def full_path_method(self, args, kwargs): return self.interpreter.backend.get_target_filename_abs(self.held_object) def __getitem__(self, index): return CustomTargetIndexHolder(self.held_object[index]) def __setitem__(self, index, value): raise InterpreterException('Cannot set a member of a CustomTarget') def __delitem__(self, index): raise InterpreterException('Cannot delete a member of a CustomTarget') class RunTargetHolder(InterpreterObject, ObjectHolder): def __init__(self, name, command, args, dependencies, subdir, subproject): InterpreterObject.__init__(self) ObjectHolder.__init__(self, build.RunTarget(name, command, args, dependencies, subdir, subproject)) def __repr__(self): r = '<{} {}: {}>' h = self.held_object return r.format(self.__class__.__name__, h.get_id(), h.command) class Test(InterpreterObject): def __init__(self, name, project, suite, exe, is_parallel, cmd_args, env, should_fail, timeout, workdir): InterpreterObject.__init__(self) self.name = name self.suite = suite self.project_name = project self.exe = exe self.is_parallel = is_parallel self.cmd_args = cmd_args self.env = env self.should_fail = should_fail self.timeout = timeout self.workdir = workdir def get_exe(self): return self.exe def get_name(self): return self.name class SubprojectHolder(InterpreterObject, ObjectHolder): def __init__(self, subinterpreter): InterpreterObject.__init__(self) ObjectHolder.__init__(self, subinterpreter) self.methods.update({'get_variable': self.get_variable_method, }) def get_variable_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('Get_variable takes one argument.') varname = args[0] if not isinstance(varname, str): raise InterpreterException('Get_variable takes a string argument.') if varname not in self.held_object.variables: raise InvalidArguments('Requested variable "{0}" not found.'.format(varname)) return self.held_object.variables[varname] class CompilerHolder(InterpreterObject): def __init__(self, compiler, env): InterpreterObject.__init__(self) self.compiler = compiler self.environment = env self.methods.update({'compiles': self.compiles_method, 'links': self.links_method, 'get_id': self.get_id_method, 'compute_int': self.compute_int_method, 'sizeof': self.sizeof_method, 'get_define': self.get_define_method, 'has_header': self.has_header_method, 'has_header_symbol': self.has_header_symbol_method, 'run': self.run_method, 'has_function': self.has_function_method, 'has_member': self.has_member_method, 'has_members': self.has_members_method, 'has_type': self.has_type_method, 'alignment': self.alignment_method, 'version': self.version_method, 'cmd_array': self.cmd_array_method, 'find_library': self.find_library_method, 'has_argument': self.has_argument_method, 'has_multi_arguments': self.has_multi_arguments_method, 'get_supported_arguments': self.get_supported_arguments_method, 'first_supported_argument': self.first_supported_argument_method, 'unittest_args': self.unittest_args_method, 'symbols_have_underscore_prefix': self.symbols_have_underscore_prefix_method, }) def version_method(self, args, kwargs): return self.compiler.version def cmd_array_method(self, args, kwargs): return self.compiler.exelist def determine_args(self, kwargs): nobuiltins = kwargs.get('no_builtin_args', False) if not isinstance(nobuiltins, bool): raise InterpreterException('Type of no_builtin_args not a boolean.') args = [] incdirs = extract_as_list(kwargs, 'include_directories') for i in incdirs: if not isinstance(i, IncludeDirsHolder): raise InterpreterException('Include directories argument must be an include_directories object.') for idir in i.held_object.get_incdirs(): idir = os.path.join(self.environment.get_source_dir(), i.held_object.get_curdir(), idir) args += self.compiler.get_include_args(idir, False) if not nobuiltins: opts = self.environment.coredata.compiler_options args += self.compiler.get_option_compile_args(opts) args += self.compiler.get_option_link_args(opts) args += mesonlib.stringlistify(kwargs.get('args', [])) return args def determine_dependencies(self, kwargs): deps = kwargs.get('dependencies', None) if deps is not None: deps = listify(deps) final_deps = [] for d in deps: try: d = d.held_object except Exception: pass if isinstance(d, InternalDependency) or not isinstance(d, Dependency): raise InterpreterException('Dependencies must be external dependencies') final_deps.append(d) deps = final_deps return deps def alignment_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('Alignment method takes exactly one positional argument.') check_stringlist(args) typename = args[0] prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of sizeof must be a string.') extra_args = mesonlib.stringlistify(kwargs.get('args', [])) deps = self.determine_dependencies(kwargs) result = self.compiler.alignment(typename, prefix, self.environment, extra_args, deps) mlog.log('Checking for alignment of "', mlog.bold(typename), '": ', result, sep='') return result def run_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('Run method takes exactly one positional argument.') code = args[0] if isinstance(code, mesonlib.File): code = mesonlib.File.from_absolute_file( code.rel_to_builddir(self.environment.source_dir)) elif not isinstance(code, str): raise InvalidArguments('Argument must be string or file.') testname = kwargs.get('name', '') if not isinstance(testname, str): raise InterpreterException('Testname argument must be a string.') extra_args = self.determine_args(kwargs) deps = self.determine_dependencies(kwargs) result = self.compiler.run(code, self.environment, extra_args, deps) if len(testname) > 0: if not result.compiled: h = mlog.red('DID NOT COMPILE') elif result.returncode == 0: h = mlog.green('YES') else: h = mlog.red('NO (%d)' % result.returncode) mlog.log('Checking if "', mlog.bold(testname), '" runs: ', h, sep='') return TryRunResultHolder(result) def get_id_method(self, args, kwargs): return self.compiler.get_id() def symbols_have_underscore_prefix_method(self, args, kwargs): ''' Check if the compiler prefixes _ (underscore) to global C symbols See: https://en.wikipedia.org/wiki/Name_mangling#C ''' return self.compiler.symbols_have_underscore_prefix(self.environment) def unittest_args_method(self, args, kwargs): ''' This function is deprecated and should not be used. It can be removed in a future version of Meson. ''' if not hasattr(self.compiler, 'get_feature_args'): raise InterpreterException('This {} compiler has no feature arguments.'.format(self.compiler.get_display_language())) build_to_src = os.path.relpath(self.environment.get_source_dir(), self.environment.get_build_dir()) return self.compiler.get_feature_args({'unittest': 'true'}, build_to_src) def has_member_method(self, args, kwargs): if len(args) != 2: raise InterpreterException('Has_member takes exactly two arguments.') check_stringlist(args) typename = args[0] membername = args[1] prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_member must be a string.') extra_args = self.determine_args(kwargs) deps = self.determine_dependencies(kwargs) had = self.compiler.has_members(typename, [membername], prefix, self.environment, extra_args, deps) if had: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') mlog.log('Checking whether type "', mlog.bold(typename), '" has member "', mlog.bold(membername), '": ', hadtxt, sep='') return had def has_members_method(self, args, kwargs): check_stringlist(args) typename = args[0] membernames = args[1:] prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_members must be a string.') extra_args = self.determine_args(kwargs) deps = self.determine_dependencies(kwargs) had = self.compiler.has_members(typename, membernames, prefix, self.environment, extra_args, deps) if had: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') members = mlog.bold(', '.join(['"{}"'.format(m) for m in membernames])) mlog.log('Checking whether type "', mlog.bold(typename), '" has members ', members, ': ', hadtxt, sep='') return had def has_function_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('Has_function takes exactly one argument.') check_stringlist(args) funcname = args[0] prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_function must be a string.') extra_args = self.determine_args(kwargs) deps = self.determine_dependencies(kwargs) had = self.compiler.has_function(funcname, prefix, self.environment, extra_args, deps) if had: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') mlog.log('Checking for function "', mlog.bold(funcname), '": ', hadtxt, sep='') return had def has_type_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('Has_type takes exactly one argument.') check_stringlist(args) typename = args[0] prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_type must be a string.') extra_args = self.determine_args(kwargs) deps = self.determine_dependencies(kwargs) had = self.compiler.has_type(typename, prefix, self.environment, extra_args, deps) if had: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') mlog.log('Checking for type "', mlog.bold(typename), '": ', hadtxt, sep='') return had def compute_int_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('Compute_int takes exactly one argument.') check_stringlist(args) expression = args[0] prefix = kwargs.get('prefix', '') l = kwargs.get('low', -1024) h = kwargs.get('high', 1024) guess = kwargs.get('guess', None) if not isinstance(prefix, str): raise InterpreterException('Prefix argument of compute_int must be a string.') if not isinstance(l, int): raise InterpreterException('Low argument of compute_int must be an int.') if not isinstance(h, int): raise InterpreterException('High argument of compute_int must be an int.') if guess is not None and not isinstance(guess, int): raise InterpreterException('Guess argument of compute_int must be an int.') extra_args = self.determine_args(kwargs) deps = self.determine_dependencies(kwargs) res = self.compiler.compute_int(expression, l, h, guess, prefix, self.environment, extra_args, deps) mlog.log('Computing int of "%s": %d' % (expression, res)) return res def sizeof_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('Sizeof takes exactly one argument.') check_stringlist(args) element = args[0] prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of sizeof must be a string.') extra_args = self.determine_args(kwargs) deps = self.determine_dependencies(kwargs) esize = self.compiler.sizeof(element, prefix, self.environment, extra_args, deps) mlog.log('Checking for size of "%s": %d' % (element, esize)) return esize def get_define_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('get_define() takes exactly one argument.') check_stringlist(args) element = args[0] prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of get_define() must be a string.') extra_args = self.determine_args(kwargs) deps = self.determine_dependencies(kwargs) value = self.compiler.get_define(element, prefix, self.environment, extra_args, deps) mlog.log('Fetching value of define "%s": %s' % (element, value)) return value def compiles_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('compiles method takes exactly one argument.') code = args[0] if isinstance(code, mesonlib.File): code = mesonlib.File.from_absolute_file( code.rel_to_builddir(self.environment.source_dir)) elif not isinstance(code, str): raise InvalidArguments('Argument must be string or file.') testname = kwargs.get('name', '') if not isinstance(testname, str): raise InterpreterException('Testname argument must be a string.') extra_args = self.determine_args(kwargs) deps = self.determine_dependencies(kwargs) result = self.compiler.compiles(code, self.environment, extra_args, deps) if len(testname) > 0: if result: h = mlog.green('YES') else: h = mlog.red('NO') mlog.log('Checking if "', mlog.bold(testname), '" compiles: ', h, sep='') return result def links_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('links method takes exactly one argument.') code = args[0] if isinstance(code, mesonlib.File): code = mesonlib.File.from_absolute_file( code.rel_to_builddir(self.environment.source_dir)) elif not isinstance(code, str): raise InvalidArguments('Argument must be string or file.') testname = kwargs.get('name', '') if not isinstance(testname, str): raise InterpreterException('Testname argument must be a string.') extra_args = self.determine_args(kwargs) deps = self.determine_dependencies(kwargs) result = self.compiler.links(code, self.environment, extra_args, deps) if len(testname) > 0: if result: h = mlog.green('YES') else: h = mlog.red('NO') mlog.log('Checking if "', mlog.bold(testname), '" links: ', h, sep='') return result def has_header_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('has_header method takes exactly one argument.') check_stringlist(args) hname = args[0] prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_header must be a string.') extra_args = self.determine_args(kwargs) deps = self.determine_dependencies(kwargs) haz = self.compiler.has_header(hname, prefix, self.environment, extra_args, deps) if haz: h = mlog.green('YES') else: h = mlog.red('NO') mlog.log('Has header "%s":' % hname, h) return haz def has_header_symbol_method(self, args, kwargs): if len(args) != 2: raise InterpreterException('has_header_symbol method takes exactly two arguments.') check_stringlist(args) hname = args[0] symbol = args[1] prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_header_symbol must be a string.') extra_args = self.determine_args(kwargs) deps = self.determine_dependencies(kwargs) haz = self.compiler.has_header_symbol(hname, symbol, prefix, self.environment, extra_args, deps) if haz: h = mlog.green('YES') else: h = mlog.red('NO') mlog.log('Header <{0}> has symbol "{1}":'.format(hname, symbol), h) return haz def find_library_method(self, args, kwargs): # TODO add dependencies support? if len(args) != 1: raise InterpreterException('find_library method takes one argument.') libname = args[0] if not isinstance(libname, str): raise InterpreterException('Library name not a string.') required = kwargs.get('required', True) if not isinstance(required, bool): raise InterpreterException('required must be boolean.') search_dirs = mesonlib.stringlistify(kwargs.get('dirs', [])) for i in search_dirs: if not os.path.isabs(i): raise InvalidCode('Search directory %s is not an absolute path.' % i) linkargs = self.compiler.find_library(libname, self.environment, search_dirs) if required and not linkargs: raise InterpreterException('{} library {!r} not found'.format(self.compiler.get_display_language(), libname)) lib = dependencies.ExternalLibrary(libname, linkargs, self.environment, self.compiler.language) return ExternalLibraryHolder(lib) def has_argument_method(self, args, kwargs): args = mesonlib.stringlistify(args) if len(args) != 1: raise InterpreterException('Has_arg takes exactly one argument.') result = self.compiler.has_argument(args[0], self.environment) if result: h = mlog.green('YES') else: h = mlog.red('NO') mlog.log('Compiler for {} supports argument {}:'.format(self.compiler.get_display_language(), args[0]), h) return result def has_multi_arguments_method(self, args, kwargs): args = mesonlib.stringlistify(args) result = self.compiler.has_multi_arguments(args, self.environment) if result: h = mlog.green('YES') else: h = mlog.red('NO') mlog.log( 'Compiler for {} supports arguments {}:'.format( self.compiler.get_display_language(), ' '.join(args)), h) return result def get_supported_arguments_method(self, args, kwargs): args = mesonlib.stringlistify(args) result = self.compiler.get_supported_arguments(args, self.environment) if len(result) == len(args): h = mlog.green('YES') elif len(result) > 0: h = mlog.yellow('SOME') else: h = mlog.red('NO') mlog.log( 'Compiler for {} supports arguments {}:'.format( self.compiler.get_display_language(), ' '.join(args)), h) return result def first_supported_argument_method(self, args, kwargs): for i in mesonlib.stringlistify(args): if self.compiler.has_argument(i, self.environment): mlog.log('First supported argument:', mlog.bold(i)) return [i] mlog.log('First supported argument:', mlog.red('None')) return [] ModuleState = namedtuple('ModuleState', [ 'build_to_src', 'subproject', 'subdir', 'current_lineno', 'environment', 'project_name', 'project_version', 'backend', 'compilers', 'targets', 'data', 'headers', 'man', 'global_args', 'project_args', 'build_machine', 'host_machine', 'target_machine']) class ModuleHolder(InterpreterObject, ObjectHolder): def __init__(self, modname, module, interpreter): InterpreterObject.__init__(self) ObjectHolder.__init__(self, module) self.modname = modname self.interpreter = interpreter def method_call(self, method_name, args, kwargs): try: fn = getattr(self.held_object, method_name) except AttributeError: raise InvalidArguments('Module %s does not have method %s.' % (self.modname, method_name)) if method_name.startswith('_'): raise InvalidArguments('Function {!r} in module {!r} is private.'.format(method_name, self.modname)) # This is not 100% reliable but we can't use hash() # because the Build object contains dicts and lists. num_targets = len(self.interpreter.build.targets) state = ModuleState( build_to_src=os.path.relpath(self.interpreter.environment.get_source_dir(), self.interpreter.environment.get_build_dir()), subproject=self.interpreter.subproject, subdir=self.interpreter.subdir, current_lineno=self.interpreter.current_lineno, environment=self.interpreter.environment, project_name=self.interpreter.build.project_name, project_version=self.interpreter.build.dep_manifest[self.interpreter.active_projectname], # The backend object is under-used right now, but we will need it: # https://github.com/mesonbuild/meson/issues/1419 backend=self.interpreter.backend, compilers=self.interpreter.build.compilers, targets=self.interpreter.build.targets, data=self.interpreter.build.data, headers=self.interpreter.build.get_headers(), man=self.interpreter.build.get_man(), global_args=self.interpreter.build.global_args, project_args=self.interpreter.build.projects_args.get(self.interpreter.subproject, {}), build_machine=self.interpreter.builtin['build_machine'].held_object, host_machine=self.interpreter.builtin['host_machine'].held_object, target_machine=self.interpreter.builtin['target_machine'].held_object, ) if self.held_object.is_snippet(method_name): value = fn(self.interpreter, state, args, kwargs) return self.interpreter.holderify(value) else: value = fn(state, args, kwargs) if num_targets != len(self.interpreter.build.targets): raise InterpreterException('Extension module altered internal state illegally.') return self.interpreter.module_method_callback(value) class MesonMain(InterpreterObject): def __init__(self, build, interpreter): InterpreterObject.__init__(self) self.build = build self.interpreter = interpreter self._found_source_scripts = {} self.methods.update({'get_compiler': self.get_compiler_method, 'is_cross_build': self.is_cross_build_method, 'has_exe_wrapper': self.has_exe_wrapper_method, 'is_unity': self.is_unity_method, 'is_subproject': self.is_subproject_method, 'current_source_dir': self.current_source_dir_method, 'current_build_dir': self.current_build_dir_method, 'source_root': self.source_root_method, 'build_root': self.build_root_method, 'add_install_script': self.add_install_script_method, 'add_postconf_script': self.add_postconf_script_method, 'install_dependency_manifest': self.install_dependency_manifest_method, 'project_version': self.project_version_method, 'project_license': self.project_license_method, 'version': self.version_method, 'project_name': self.project_name_method, 'get_cross_property': self.get_cross_property_method, 'backend': self.backend_method, }) def _find_source_script(self, name, args): # Prefer scripts in the current source directory search_dir = os.path.join(self.interpreter.environment.source_dir, self.interpreter.subdir) key = (name, search_dir) if key in self._found_source_scripts: found = self._found_source_scripts[key] else: found = dependencies.ExternalProgram(name, search_dir=search_dir) if found.found(): self._found_source_scripts[key] = found else: m = 'Script or command {!r} not found or not executable' raise InterpreterException(m.format(name)) return build.RunScript(found.get_command(), args) def add_install_script_method(self, args, kwargs): if len(args) < 1: raise InterpreterException('add_install_script takes one or more arguments') check_stringlist(args, 'add_install_script args must be strings') script = self._find_source_script(args[0], args[1:]) self.build.install_scripts.append(script) def add_postconf_script_method(self, args, kwargs): if len(args) < 1: raise InterpreterException('add_postconf_script takes one or more arguments') check_stringlist(args, 'add_postconf_script arguments must be strings') script = self._find_source_script(args[0], args[1:]) self.build.postconf_scripts.append(script) def current_source_dir_method(self, args, kwargs): src = self.interpreter.environment.source_dir sub = self.interpreter.subdir if sub == '': return src return os.path.join(src, sub) def current_build_dir_method(self, args, kwargs): src = self.interpreter.environment.build_dir sub = self.interpreter.subdir if sub == '': return src return os.path.join(src, sub) def backend_method(self, args, kwargs): return self.interpreter.backend.name def source_root_method(self, args, kwargs): return self.interpreter.environment.source_dir def build_root_method(self, args, kwargs): return self.interpreter.environment.build_dir def has_exe_wrapper_method(self, args, kwargs): if self.is_cross_build_method(None, None) and \ 'binaries' in self.build.environment.cross_info.config and \ self.build.environment.cross_info.need_exe_wrapper(): exe_wrap = self.build.environment.cross_info.config['binaries'].get('exe_wrapper', None) if exe_wrap is None: return False # We return True when exe_wrap is defined, when it's not needed, and # when we're compiling natively. The last two are semantically confusing. # Need to revisit this. return True def is_cross_build_method(self, args, kwargs): return self.build.environment.is_cross_build() def get_compiler_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('get_compiler_method must have one and only one argument.') cname = args[0] native = kwargs.get('native', None) if native is None: if self.build.environment.is_cross_build(): native = False else: native = True if not isinstance(native, bool): raise InterpreterException('Type of "native" must be a boolean.') if native: clist = self.build.compilers else: clist = self.build.cross_compilers if cname in clist: return CompilerHolder(clist[cname], self.build.environment) raise InterpreterException('Tried to access compiler for unspecified language "%s".' % cname) def is_unity_method(self, args, kwargs): optval = self.interpreter.environment.coredata.get_builtin_option('unity') if optval == 'on' or (optval == 'subprojects' and self.interpreter.subproject != ''): return True return False def is_subproject_method(self, args, kwargs): return self.interpreter.is_subproject() def install_dependency_manifest_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('Must specify manifest install file name') if not isinstance(args[0], str): raise InterpreterException('Argument must be a string.') self.build.dep_manifest_name = args[0] def project_version_method(self, args, kwargs): return self.build.dep_manifest[self.interpreter.active_projectname]['version'] def project_license_method(self, args, kwargs): return self.build.dep_manifest[self.interpreter.active_projectname]['license'] def version_method(self, args, kwargs): return coredata.version def project_name_method(self, args, kwargs): return self.interpreter.active_projectname def get_cross_property_method(self, args, kwargs): if len(args) < 1 or len(args) > 2: raise InterpreterException('Must have one or two arguments.') propname = args[0] if not isinstance(propname, str): raise InterpreterException('Property name must be string.') try: props = self.interpreter.environment.cross_info.get_properties() return props[propname] except Exception: if len(args) == 2: return args[1] raise InterpreterException('Unknown cross property: %s.' % propname) pch_kwargs = set(['c_pch', 'cpp_pch']) lang_arg_kwargs = set([ 'c_args', 'cpp_args', 'd_args', 'd_import_dirs', 'd_unittest', 'd_module_versions', 'fortran_args', 'java_args', 'objc_args', 'objcpp_args', 'rust_args', 'vala_args', 'cs_args', ]) vala_kwargs = set(['vala_header', 'vala_gir', 'vala_vapi']) rust_kwargs = set(['rust_crate_type']) cs_kwargs = set(['resources', 'cs_args']) buildtarget_kwargs = set([ 'build_by_default', 'build_rpath', 'dependencies', 'extra_files', 'gui_app', 'link_with', 'link_whole', 'link_args', 'link_depends', 'implicit_include_directories', 'include_directories', 'install', 'install_rpath', 'install_dir', 'name_prefix', 'name_suffix', 'native', 'objects', 'override_options', 'pic', 'sources', 'vs_module_defs', ]) build_target_common_kwargs = ( buildtarget_kwargs | lang_arg_kwargs | pch_kwargs | vala_kwargs | rust_kwargs | cs_kwargs) exe_kwargs = (build_target_common_kwargs) | {'implib', 'export_dynamic'} shlib_kwargs = (build_target_common_kwargs) | {'version', 'soversion'} shmod_kwargs = shlib_kwargs stlib_kwargs = shlib_kwargs jar_kwargs = exe_kwargs.copy() jar_kwargs.update(['main_class']) build_target_kwargs = exe_kwargs.copy() build_target_kwargs.update(['target_type']) permitted_kwargs = {'add_global_arguments': {'language'}, 'add_global_link_arguments': {'language'}, 'add_project_link_arguments': {'language'}, 'add_languages': {'required'}, 'add_project_arguments': {'language'}, 'add_test_setup': {'exe_wrapper', 'gdb', 'timeout_multiplier', 'env'}, 'benchmark': {'args', 'env', 'should_fail', 'timeout', 'workdir', 'suite'}, 'build_target': build_target_kwargs, 'configure_file': {'input', 'output', 'configuration', 'command', 'install_dir', 'capture', 'install'}, 'custom_target': {'input', 'output', 'command', 'install', 'install_dir', 'build_always', 'capture', 'depends', 'depend_files', 'depfile', 'build_by_default'}, 'dependency': {'default_options', 'fallback', 'language', 'main', 'method', 'modules', 'optional_modules', 'native', 'required', 'static', 'version'}, 'declare_dependency': {'include_directories', 'link_with', 'sources', 'dependencies', 'compile_args', 'link_args', 'version'}, 'executable': exe_kwargs, 'find_program': {'required', 'native'}, 'generator': {'arguments', 'output', 'depfile', 'capture', 'preserve_path_from'}, 'include_directories': {'is_system'}, 'install_data': {'install_dir', 'install_mode', 'sources'}, 'install_headers': {'install_dir', 'subdir'}, 'install_man': {'install_dir'}, 'install_subdir': {'exclude_files', 'exclude_directories', 'install_dir', 'install_mode', 'strip_directory'}, 'jar': jar_kwargs, 'project': {'version', 'meson_version', 'default_options', 'license', 'subproject_dir'}, 'run_target': {'command', 'depends'}, 'shared_library': shlib_kwargs, 'shared_module': shmod_kwargs, 'static_library': stlib_kwargs, 'subdir': {'if_found'}, 'subproject': {'version', 'default_options'}, 'test': {'args', 'env', 'is_parallel', 'should_fail', 'timeout', 'workdir', 'suite'}, 'vcs_tag': {'input', 'output', 'fallback', 'command', 'replace_string'}, } class Interpreter(InterpreterBase): def __init__(self, build, backend, subproject='', subdir='', subproject_dir='subprojects', default_project_options=[]): super().__init__(build.environment.get_source_dir(), subdir) self.an_unpicklable_object = mesonlib.an_unpicklable_object self.build = build self.environment = build.environment self.coredata = self.environment.get_coredata() self.backend = backend self.subproject = subproject # Subproject directory is usually the name of the subproject, but can # be different for dependencies provided by wrap files. self.subproject_directory_name = subdir.split(os.path.sep)[-1] self.subproject_dir = subproject_dir self.option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt') self.load_root_meson_file() self.sanity_check_ast() self.builtin.update({'meson': MesonMain(build, self)}) self.generators = [] self.visited_subdirs = {} self.project_args_frozen = False self.global_args_frozen = False # implies self.project_args_frozen self.subprojects = {} self.subproject_stack = [] self.default_project_options = default_project_options[:] # Passed from the outside, only used in subprojects. self.build_func_dict() # build_def_files needs to be defined before parse_project is called self.build_def_files = [os.path.join(self.subdir, environment.build_filename)] self.parse_project() self.builtin['build_machine'] = BuildMachine(self.coredata.compilers) if not self.build.environment.is_cross_build(): self.builtin['host_machine'] = self.builtin['build_machine'] self.builtin['target_machine'] = self.builtin['build_machine'] else: cross_info = self.build.environment.cross_info if cross_info.has_host(): self.builtin['host_machine'] = CrossMachineInfo(cross_info.config['host_machine']) else: self.builtin['host_machine'] = self.builtin['build_machine'] if cross_info.has_target(): self.builtin['target_machine'] = CrossMachineInfo(cross_info.config['target_machine']) else: self.builtin['target_machine'] = self.builtin['host_machine'] def build_func_dict(self): self.funcs.update({'add_global_arguments': self.func_add_global_arguments, 'add_project_arguments': self.func_add_project_arguments, 'add_global_link_arguments': self.func_add_global_link_arguments, 'add_project_link_arguments': self.func_add_project_link_arguments, 'add_test_setup': self.func_add_test_setup, 'add_languages': self.func_add_languages, 'assert': self.func_assert, 'benchmark': self.func_benchmark, 'build_target': self.func_build_target, 'configuration_data': self.func_configuration_data, 'configure_file': self.func_configure_file, 'custom_target': self.func_custom_target, 'declare_dependency': self.func_declare_dependency, 'dependency': self.func_dependency, 'disabler': self.func_disabler, 'environment': self.func_environment, 'error': self.func_error, 'executable': self.func_executable, 'generator': self.func_generator, 'gettext': self.func_gettext, 'get_option': self.func_get_option, 'get_variable': self.func_get_variable, 'files': self.func_files, 'find_library': self.func_find_library, 'find_program': self.func_find_program, 'include_directories': self.func_include_directories, 'import': self.func_import, 'install_data': self.func_install_data, 'install_headers': self.func_install_headers, 'install_man': self.func_install_man, 'install_subdir': self.func_install_subdir, 'is_variable': self.func_is_variable, 'jar': self.func_jar, 'join_paths': self.func_join_paths, 'library': self.func_library, 'message': self.func_message, 'warning': self.func_warning, 'option': self.func_option, 'project': self.func_project, 'run_target': self.func_run_target, 'run_command': self.func_run_command, 'set_variable': self.func_set_variable, 'subdir': self.func_subdir, 'subproject': self.func_subproject, 'shared_library': self.func_shared_lib, 'shared_module': self.func_shared_module, 'static_library': self.func_static_lib, 'test': self.func_test, 'vcs_tag': self.func_vcs_tag, }) if 'MESON_UNIT_TEST' in os.environ: self.funcs.update({'exception': self.func_exception}) def holderify(self, item): if isinstance(item, list): return [self.holderify(x) for x in item] if isinstance(item, build.CustomTarget): return CustomTargetHolder(item, self) elif isinstance(item, (int, str)) or item is None: return item elif isinstance(item, build.Executable): return ExecutableHolder(item, self) elif isinstance(item, build.GeneratedList): return GeneratedListHolder(item) elif isinstance(item, build.RunTarget): raise RuntimeError('This is not a pipe.') elif isinstance(item, build.RunScript): raise RuntimeError('Do not do this.') elif isinstance(item, build.Data): return DataHolder(item) elif isinstance(item, dependencies.InternalDependency): return InternalDependencyHolder(item) elif isinstance(item, dependencies.ExternalProgram): return ExternalProgramHolder(item) elif hasattr(item, 'held_object'): return item else: raise InterpreterException('Module returned a value of unknown type.') def process_new_values(self, invalues): invalues = listify(invalues) for v in invalues: if isinstance(v, (build.BuildTarget, build.CustomTarget, build.RunTarget)): self.add_target(v.name, v) elif isinstance(v, list): self.module_method_callback(v) elif isinstance(v, build.GeneratedList): pass elif isinstance(v, build.RunScript): self.build.install_scripts.append(v) elif isinstance(v, build.Data): self.build.data.append(v) elif isinstance(v, dependencies.ExternalProgram): return ExternalProgramHolder(v) elif isinstance(v, dependencies.InternalDependency): # FIXME: This is special cased and not ideal: # The first source is our new VapiTarget, the rest are deps self.process_new_values(v.sources[0]) elif hasattr(v, 'held_object'): pass else: raise InterpreterException('Module returned a value of unknown type.') def module_method_callback(self, return_object): if not isinstance(return_object, ModuleReturnValue): raise InterpreterException('Bug in module, it returned an invalid object') invalues = return_object.new_objects self.process_new_values(invalues) return self.holderify(return_object.return_value) def get_build_def_files(self): return self.build_def_files def get_variables(self): return self.variables def check_cross_stdlibs(self): if self.build.environment.is_cross_build(): cross_info = self.build.environment.cross_info for l, c in self.build.cross_compilers.items(): try: di = mesonlib.stringlistify(cross_info.get_stdlib(l)) if len(di) != 2: raise InterpreterException('Stdlib definition for %s should have exactly two elements.' % l) projname, depname = di subproj = self.do_subproject(projname, {}) self.build.cross_stdlibs[l] = subproj.get_variable_method([depname], {}) except KeyError: pass except InvalidArguments: pass @stringArgs @noKwargs def func_import(self, node, args, kwargs): if len(args) != 1: raise InvalidCode('Import takes one argument.') modname = args[0] if modname.startswith('unstable-'): plainname = modname.split('-', 1)[1] mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases.' % modname, location=node) modname = 'unstable_' + plainname if modname not in self.environment.coredata.modules: try: module = importlib.import_module('mesonbuild.modules.' + modname) except ImportError: raise InvalidArguments('Module "%s" does not exist' % (modname, )) self.environment.coredata.modules[modname] = module.initialize() return ModuleHolder(modname, self.environment.coredata.modules[modname], self) @stringArgs @noKwargs def func_files(self, node, args, kwargs): return [mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, fname) for fname in args] @permittedKwargs(permitted_kwargs['declare_dependency']) @noPosargs def func_declare_dependency(self, node, args, kwargs): version = kwargs.get('version', self.project_version) if not isinstance(version, str): raise InterpreterException('Version must be a string.') incs = extract_as_list(kwargs, 'include_directories', unholder=True) libs = extract_as_list(kwargs, 'link_with', unholder=True) sources = extract_as_list(kwargs, 'sources') sources = listify(self.source_strings_to_files(sources), unholder=True) deps = extract_as_list(kwargs, 'dependencies', unholder=True) compile_args = mesonlib.stringlistify(kwargs.get('compile_args', [])) link_args = mesonlib.stringlistify(kwargs.get('link_args', [])) final_deps = [] for d in deps: try: d = d.held_object except Exception: pass if not isinstance(d, (dependencies.Dependency, dependencies.ExternalLibrary, dependencies.InternalDependency)): raise InterpreterException('Dependencies must be external deps') final_deps.append(d) for l in libs: if isinstance(l, dependencies.Dependency): raise InterpreterException('''Entries in "link_with" may only be self-built targets, external dependencies (including libraries) must go to "dependencies".''') dep = dependencies.InternalDependency(version, incs, compile_args, link_args, libs, sources, final_deps) return DependencyHolder(dep) @noKwargs def func_assert(self, node, args, kwargs): if len(args) != 2: raise InterpreterException('Assert takes exactly two arguments') value, message = args if not isinstance(value, bool): raise InterpreterException('Assert value not bool.') if not isinstance(message, str): raise InterpreterException('Assert message not a string.') if not value: raise InterpreterException('Assert failed: ' + message) def validate_arguments(self, args, argcount, arg_types): if argcount is not None: if argcount != len(args): raise InvalidArguments('Expected %d arguments, got %d.' % (argcount, len(args))) for i in range(min(len(args), len(arg_types))): wanted = arg_types[i] actual = args[i] if wanted is not None: if not isinstance(actual, wanted): raise InvalidArguments('Incorrect argument type.') @noKwargs def func_run_command(self, node, args, kwargs): return self.run_command_impl(node, args, kwargs) def run_command_impl(self, node, args, kwargs, in_builddir=False): if len(args) < 1: raise InterpreterException('Not enough arguments') cmd = args[0] cargs = args[1:] srcdir = self.environment.get_source_dir() builddir = self.environment.get_build_dir() m = 'must be a string, or the output of find_program(), files(), or ' \ 'configure_file(); not {!r}' if isinstance(cmd, ExternalProgramHolder): cmd = cmd.held_object else: if isinstance(cmd, mesonlib.File): cmd = cmd.absolute_path(srcdir, builddir) elif not isinstance(cmd, str): raise InterpreterException('First argument ' + m.format(cmd)) # Prefer scripts in the current source directory search_dir = os.path.join(srcdir, self.subdir) prog = ExternalProgram(cmd, silent=True, search_dir=search_dir) if not prog.found(): raise InterpreterException('Program or command {!r} not found ' 'or not executable'.format(cmd)) cmd = prog try: cmd_path = os.path.relpath(cmd.get_path(), start=srcdir) except ValueError: # On Windows a relative path can't be evaluated for # paths on two different drives (i.e. c:\foo and f:\bar). # The only thing left to is is to use the original absolute # path. cmd_path = cmd.get_path() if not cmd_path.startswith('..') and cmd_path not in self.build_def_files: self.build_def_files.append(cmd_path) expanded_args = [] for a in listify(cargs): if isinstance(a, str): expanded_args.append(a) elif isinstance(a, mesonlib.File): expanded_args.append(a.absolute_path(srcdir, builddir)) elif isinstance(a, ExternalProgramHolder): expanded_args.append(a.held_object.get_path()) else: raise InterpreterException('Arguments ' + m.format(a)) for a in expanded_args: if not os.path.isabs(a): a = os.path.join(builddir if in_builddir else srcdir, self.subdir, a) if os.path.isfile(a): a = os.path.relpath(a, start=srcdir) if not a.startswith('..'): if a not in self.build_def_files: self.build_def_files.append(a) return RunProcess(cmd, expanded_args, srcdir, builddir, self.subdir, self.environment.get_build_command() + ['introspect'], in_builddir) @stringArgs def func_gettext(self, nodes, args, kwargs): raise InterpreterException('Gettext() function has been moved to module i18n. Import it and use i18n.gettext() instead') def func_option(self, nodes, args, kwargs): raise InterpreterException('Tried to call option() in build description file. All options must be in the option file.') @permittedKwargs(permitted_kwargs['subproject']) @stringArgs def func_subproject(self, nodes, args, kwargs): if len(args) != 1: raise InterpreterException('Subproject takes exactly one argument') dirname = args[0] return self.do_subproject(dirname, kwargs) def do_subproject(self, dirname, kwargs): if dirname == '': raise InterpreterException('Subproject dir name must not be empty.') if dirname[0] == '.': raise InterpreterException('Subproject dir name must not start with a period.') if '..' in dirname: raise InterpreterException('Subproject name must not contain a ".." path segment.') if os.path.isabs(dirname): raise InterpreterException('Subproject name must not be an absolute path.') if '\\' in dirname or '/' in dirname: mlog.warning('Subproject name has a path separator. This may cause unexpected behaviour.') if dirname in self.subproject_stack: fullstack = self.subproject_stack + [dirname] incpath = ' => '.join(fullstack) raise InvalidCode('Recursive include of subprojects: %s.' % incpath) if dirname in self.subprojects: return self.subprojects[dirname] subproject_dir_abs = os.path.join(self.environment.get_source_dir(), self.subproject_dir) r = wrap.Resolver(subproject_dir_abs, self.coredata.wrap_mode) try: resolved = r.resolve(dirname) except RuntimeError as e: msg = 'Subproject directory {!r} does not exist and cannot be downloaded:\n{}' raise InterpreterException(msg.format(os.path.join(self.subproject_dir, dirname), e)) subdir = os.path.join(self.subproject_dir, resolved) os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True) self.global_args_frozen = True mlog.log('\nExecuting subproject ', mlog.bold(dirname), '.\n', sep='') subi = Interpreter(self.build, self.backend, dirname, subdir, self.subproject_dir, mesonlib.stringlistify(kwargs.get('default_options', []))) subi.subprojects = self.subprojects subi.subproject_stack = self.subproject_stack + [dirname] current_active = self.active_projectname subi.run() if 'version' in kwargs: pv = subi.project_version wanted = kwargs['version'] if pv == 'undefined' or not mesonlib.version_compare(pv, wanted): raise InterpreterException('Subproject %s version is %s but %s required.' % (dirname, pv, wanted)) self.active_projectname = current_active mlog.log('\nSubproject', mlog.bold(dirname), 'finished.') self.build.subprojects[dirname] = subi.project_version self.subprojects.update(subi.subprojects) self.subprojects[dirname] = SubprojectHolder(subi) self.build_def_files += subi.build_def_files return self.subprojects[dirname] @stringArgs @noKwargs def func_get_option(self, nodes, args, kwargs): if len(args) != 1: raise InterpreterException('Argument required for get_option.') undecorated_optname = optname = args[0] if ':' in optname: raise InterpreterException('''Having a colon in option name is forbidden, projects are not allowed to directly access options of other subprojects.''') try: return self.environment.get_coredata().base_options[optname].value except KeyError: pass try: return self.environment.coredata.get_builtin_option(optname) except RuntimeError: pass try: return self.environment.coredata.compiler_options[optname].value except KeyError: pass if not coredata.is_builtin_option(optname) and self.is_subproject(): optname = self.subproject + ':' + optname try: opt = self.environment.coredata.user_options[optname] if opt.yielding and ':' in optname: # If option not present in superproject, keep the original. opt = self.environment.coredata.user_options.get(undecorated_optname, opt) return opt.value except KeyError: pass if optname.endswith('_link_args'): try: lang = optname[:-10] return self.coredata.external_link_args[lang] except KeyError: pass if optname.endswith('_args'): try: lang = optname[:-5] return self.coredata.external_args[lang] except KeyError: pass # Some base options are not defined in some environments, return the default value. try: return compilers.base_options[optname].value except KeyError: pass raise InterpreterException('Tried to access unknown option "%s".' % optname) @noKwargs def func_configuration_data(self, node, args, kwargs): if args: raise InterpreterException('configuration_data takes no arguments') return ConfigurationDataHolder() def parse_default_options(self, default_options): default_options = listify(default_options) for option in default_options: if not isinstance(option, str): mlog.debug(option) raise InterpreterException('Default options must be strings') if '=' not in option: raise InterpreterException('All default options must be of type key=value.') key, value = option.split('=', 1) if coredata.is_builtin_option(key): if self.subproject != '': continue # Only the master project is allowed to set global options. # If this was set on the command line, do not override. if not self.environment.had_argument_for(key): self.coredata.set_builtin_option(key, value) # If we are setting the prefix, then other options which # have prefix-dependent defaults need their value updating, # if they haven't been explicitly set (i.e. have their # default value) if key == 'prefix': for option in coredata.builtin_dir_noprefix_options: if not (self.environment.had_argument_for(option) or any([k.startswith(option + '=') for k in default_options])): self.coredata.set_builtin_option(option, coredata.get_builtin_option_default(option, value)) else: # Option values set with subproject() default_options override those # set in project() default_options. pref = key + '=' for i in self.default_project_options: if i.startswith(pref): option = i break # If we are in a subproject, add the subproject prefix to option # name. if self.subproject != '': option = self.subproject + ':' + option newoptions = [option] + self.environment.cmd_line_options.projectoptions self.environment.cmd_line_options.projectoptions = newoptions # Add options that are only in default_options. for defopt in self.default_project_options: key, value = defopt.split('=') pref = key + '=' for i in default_options: if i.startswith(pref): break else: defopt = self.subproject + ':' + defopt newoptions = [defopt] + self.environment.cmd_line_options.projectoptions self.environment.cmd_line_options.projectoptions = newoptions @stringArgs @permittedKwargs(permitted_kwargs['project']) def func_project(self, node, args, kwargs): if len(args) < 1: raise InvalidArguments('Not enough arguments to project(). Needs at least the project name.') proj_name = args[0] proj_langs = args[1:] if ':' in proj_name: raise InvalidArguments("Project name {!r} must not contain ':'".format(proj_name)) default_options = kwargs.get('default_options', []) if self.environment.first_invocation and (len(default_options) > 0 or len(self.default_project_options) > 0): self.parse_default_options(default_options) if not self.is_subproject(): self.build.project_name = proj_name if os.path.exists(self.option_file): oi = optinterpreter.OptionInterpreter(self.subproject, self.build.environment.cmd_line_options.projectoptions, ) oi.process(self.option_file) self.build.environment.merge_options(oi.options) self.active_projectname = proj_name self.project_version = kwargs.get('version', 'undefined') if self.build.project_version is None: self.build.project_version = self.project_version proj_license = mesonlib.stringlistify(kwargs.get('license', 'unknown')) self.build.dep_manifest[proj_name] = {'version': self.project_version, 'license': proj_license} if self.subproject in self.build.projects: raise InvalidCode('Second call to project().') if not self.is_subproject() and 'subproject_dir' in kwargs: spdirname = kwargs['subproject_dir'] if not isinstance(spdirname, str): raise InterpreterException('Subproject_dir must be a string') if os.path.isabs(spdirname): raise InterpreterException('Subproject_dir must not be an absolute path.') if spdirname.startswith('.'): raise InterpreterException('Subproject_dir must not begin with a period.') if '..' in spdirname: raise InterpreterException('Subproject_dir must not contain a ".." segment.') self.subproject_dir = spdirname if 'meson_version' in kwargs: cv = coredata.version pv = kwargs['meson_version'] if not mesonlib.version_compare(cv, pv): raise InterpreterException('Meson version is %s but project requires %s.' % (cv, pv)) self.build.projects[self.subproject] = proj_name mlog.log('Project name: ', mlog.bold(proj_name), sep='') self.add_languages(proj_langs, True) langs = self.coredata.compilers.keys() if 'vala' in langs: if 'c' not in langs: raise InterpreterException('Compiling Vala requires C. Add C to your project languages and rerun Meson.') if not self.is_subproject(): self.check_cross_stdlibs() @permittedKwargs(permitted_kwargs['add_languages']) @stringArgs def func_add_languages(self, node, args, kwargs): return self.add_languages(args, kwargs.get('required', True)) def get_message_string_arg(self, node): # reduce arguments again to avoid flattening posargs (posargs, _) = self.reduce_arguments(node.args) if len(posargs) != 1: raise InvalidArguments('Expected 1 argument, got %d' % len(posargs)) arg = posargs[0] if isinstance(arg, list): argstr = stringifyUserArguments(arg) elif isinstance(arg, str): argstr = arg elif isinstance(arg, int): argstr = str(arg) else: raise InvalidArguments('Function accepts only strings, integers, lists and lists thereof.') return argstr @noKwargs def func_message(self, node, args, kwargs): argstr = self.get_message_string_arg(node) mlog.log(mlog.bold('Message:'), argstr) @noKwargs def func_warning(self, node, args, kwargs): argstr = self.get_message_string_arg(node) mlog.warning(argstr, location=node) @noKwargs def func_error(self, node, args, kwargs): self.validate_arguments(args, 1, [str]) raise InterpreterException('Problem encountered: ' + args[0]) @noKwargs def func_exception(self, node, args, kwargs): self.validate_arguments(args, 0, []) raise Exception() def detect_compilers(self, lang, need_cross_compiler): cross_comp = None if lang == 'c': comp = self.environment.detect_c_compiler(False) if need_cross_compiler: cross_comp = self.environment.detect_c_compiler(True) elif lang == 'cpp': comp = self.environment.detect_cpp_compiler(False) if need_cross_compiler: cross_comp = self.environment.detect_cpp_compiler(True) elif lang == 'objc': comp = self.environment.detect_objc_compiler(False) if need_cross_compiler: cross_comp = self.environment.detect_objc_compiler(True) elif lang == 'objcpp': comp = self.environment.detect_objcpp_compiler(False) if need_cross_compiler: cross_comp = self.environment.detect_objcpp_compiler(True) elif lang == 'java': comp = self.environment.detect_java_compiler() if need_cross_compiler: cross_comp = comp # Java is platform independent. elif lang == 'cs': comp = self.environment.detect_cs_compiler() if need_cross_compiler: cross_comp = comp # C# is platform independent. elif lang == 'vala': comp = self.environment.detect_vala_compiler() if need_cross_compiler: cross_comp = comp # Vala compiles to platform-independent C elif lang == 'd': comp = self.environment.detect_d_compiler(False) if need_cross_compiler: cross_comp = self.environment.detect_d_compiler(True) elif lang == 'rust': comp = self.environment.detect_rust_compiler(False) if need_cross_compiler: cross_comp = self.environment.detect_rust_compiler(True) elif lang == 'fortran': comp = self.environment.detect_fortran_compiler(False) if need_cross_compiler: cross_comp = self.environment.detect_fortran_compiler(True) elif lang == 'swift': comp = self.environment.detect_swift_compiler() if need_cross_compiler: raise InterpreterException('Cross compilation with Swift is not working yet.') # cross_comp = self.environment.detect_fortran_compiler(True) else: raise InvalidCode('Tried to use unknown language "%s".' % lang) comp.sanity_check(self.environment.get_scratch_dir(), self.environment) self.coredata.compilers[lang] = comp # Native compiler always exist so always add its options. new_options = comp.get_options() if cross_comp is not None: cross_comp.sanity_check(self.environment.get_scratch_dir(), self.environment) self.coredata.cross_compilers[lang] = cross_comp new_options.update(cross_comp.get_options()) optprefix = lang + '_' for i in new_options: if not i.startswith(optprefix): raise InterpreterException('Internal error, %s has incorrect prefix.' % i) cmd_prefix = i + '=' for cmd_arg in self.environment.cmd_line_options.projectoptions: if cmd_arg.startswith(cmd_prefix): value = cmd_arg.split('=', 1)[1] new_options[i].set_value(value) new_options.update(self.coredata.compiler_options) self.coredata.compiler_options = new_options return comp, cross_comp def add_languages(self, args, required): success = True need_cross_compiler = self.environment.is_cross_build() and self.environment.cross_info.need_cross_compiler() for lang in sorted(args, key=compilers.sort_clike): lang = lang.lower() if lang in self.coredata.compilers: comp = self.coredata.compilers[lang] cross_comp = self.coredata.cross_compilers.get(lang, None) else: try: (comp, cross_comp) = self.detect_compilers(lang, need_cross_compiler) except Exception: if not required: mlog.log('Compiler for language', mlog.bold(lang), 'not found.') success = False continue else: raise if comp.full_version is not None: version_string = ' (%s %s "%s")' % (comp.id, comp.version, comp.full_version) else: version_string = ' (%s %s)' % (comp.id, comp.version) mlog.log('Native %s compiler: ' % comp.get_display_language(), mlog.bold(' '.join(comp.get_exelist())), version_string, sep='') if not comp.get_language() in self.coredata.external_args: (preproc_args, compile_args, link_args) = environment.get_args_from_envvars(comp) self.coredata.external_preprocess_args[comp.get_language()] = preproc_args self.coredata.external_args[comp.get_language()] = compile_args self.coredata.external_link_args[comp.get_language()] = link_args self.build.add_compiler(comp) if need_cross_compiler: mlog.log('Cross %s compiler: ' % cross_comp.get_display_language(), mlog.bold(' '.join(cross_comp.get_exelist())), ' (%s %s)' % (cross_comp.id, cross_comp.version), sep='') self.build.add_cross_compiler(cross_comp) if self.environment.is_cross_build() and not need_cross_compiler: self.build.add_cross_compiler(comp) self.add_base_options(comp) return success def add_base_options(self, compiler): proj_opt = self.environment.cmd_line_options.projectoptions for optname in compiler.base_options: if optname in self.coredata.base_options: continue oobj = compilers.base_options[optname] for po in proj_opt: if po.startswith(optname + '='): oobj.set_value(po.split('=', 1)[1]) break self.coredata.base_options[optname] = oobj def program_from_cross_file(self, prognames): bins = self.environment.cross_info.config['binaries'] for p in prognames: if hasattr(p, 'held_object'): p = p.held_object if isinstance(p, mesonlib.File): continue # Always points to a local (i.e. self generated) file. if not isinstance(p, str): raise InterpreterException('Executable name must be a string.') if p in bins: exename = bins[p] extprog = dependencies.ExternalProgram(exename) progobj = ExternalProgramHolder(extprog) return progobj def program_from_system(self, args): # Search for scripts relative to current subdir. # Do not cache found programs because find_program('foobar') # might give different results when run from different source dirs. source_dir = os.path.join(self.environment.get_source_dir(), self.subdir) for exename in args: if isinstance(exename, mesonlib.File): if exename.is_built: search_dir = os.path.join(self.environment.get_build_dir(), exename.subdir) else: search_dir = os.path.join(self.environment.get_source_dir(), exename.subdir) exename = exename.fname elif isinstance(exename, str): search_dir = source_dir else: raise InvalidArguments('find_program only accepts strings and ' 'files, not {!r}'.format(exename)) extprog = dependencies.ExternalProgram(exename, search_dir=search_dir) progobj = ExternalProgramHolder(extprog) if progobj.found(): return progobj @permittedKwargs(permitted_kwargs['find_program']) def func_find_program(self, node, args, kwargs): if not args: raise InterpreterException('No program name specified.') required = kwargs.get('required', True) if not isinstance(required, bool): raise InvalidArguments('"required" argument must be a boolean.') progobj = None if self.build.environment.is_cross_build(): use_native = kwargs.get('native', False) if not isinstance(use_native, bool): raise InvalidArguments('Argument to "native" must be a boolean.') if not use_native: progobj = self.program_from_cross_file(args) if progobj is None: progobj = self.program_from_system(args) if required and (progobj is None or not progobj.found()): raise InvalidArguments('Program(s) {!r} not found or not executable'.format(args)) if progobj is None: return ExternalProgramHolder(dependencies.NonExistingExternalProgram()) return progobj def func_find_library(self, node, args, kwargs): raise InvalidCode('find_library() is removed, use the corresponding method in a compiler object instead.') def _find_cached_dep(self, name, kwargs): # Check if we want this as a cross-dep or a native-dep # FIXME: Not all dependencies support such a distinction right now, # and we repeat this check inside dependencies that do. We need to # consolidate this somehow. is_cross = self.environment.is_cross_build() if 'native' in kwargs and is_cross: want_cross = not kwargs['native'] else: want_cross = is_cross identifier = dependencies.get_dep_identifier(name, kwargs, want_cross) cached_dep = None # Check if we've already searched for and found this dep if identifier in self.coredata.deps: cached_dep = self.coredata.deps[identifier] mlog.log('Dependency', mlog.bold(name), 'found:', mlog.green('YES'), '(cached)') else: # Check if exactly the same dep with different version requirements # was found already. wanted = identifier[1] for trial, trial_dep in self.coredata.deps.items(): # trial[1], identifier[1] are the version requirements if trial[0] != identifier[0] or trial[2:] != identifier[2:]: continue found = trial_dep.get_version() if not wanted or mesonlib.version_compare_many(found, wanted)[0]: # We either don't care about the version, or our # version requirements matched the trial dep's version. cached_dep = trial_dep break return identifier, cached_dep @staticmethod def check_subproject_version(wanted, found): if wanted == 'undefined': return True if found == 'undefined' or not mesonlib.version_compare(found, wanted): return False return True def get_subproject_dep(self, name, dirname, varname, required): try: dep = self.subprojects[dirname].get_variable_method([varname], {}) except InvalidArguments as e: if required: raise DependencyException('Could not find dependency {} in subproject {}; {}' ''.format(varname, dirname, str(e))) # If the dependency is not required, don't raise an exception subproj_path = os.path.join(self.subproject_dir, dirname) mlog.log('Dependency', mlog.bold(name), 'from subproject', mlog.bold(subproj_path), 'found:', mlog.red('NO')) return None if not isinstance(dep, DependencyHolder): raise InvalidCode('Fetched variable {!r} in the subproject {!r} is ' 'not a dependency object.'.format(varname, dirname)) return dep def _find_cached_fallback_dep(self, name, dirname, varname, wanted, required): if dirname not in self.subprojects: return False dep = self.get_subproject_dep(name, dirname, varname, required) if not dep: return False found = dep.version_method([], {}) if self.check_subproject_version(wanted, found): subproj_path = os.path.join(self.subproject_dir, dirname) mlog.log('Dependency', mlog.bold(name), 'from subproject', mlog.bold(subproj_path), 'found:', mlog.green('YES'), '(cached)') return dep if required: raise DependencyException('Version {} of subproject dependency {} already ' 'cached, requested incompatible version {} for ' 'dep {}'.format(found, dirname, wanted, name)) return None @permittedKwargs(permitted_kwargs['dependency']) def func_dependency(self, node, args, kwargs): self.validate_arguments(args, 1, [str]) required = kwargs.get('required', True) if not isinstance(required, bool): raise DependencyException('Keyword "required" must be a boolean.') name = args[0] if name == '': if required: raise InvalidArguments('Dependency is both required and not-found') return DependencyHolder(Dependency('not-found', {})) if '<' in name or '>' in name or '=' in name: raise InvalidArguments('Characters <, > and = are forbidden in dependency names. To specify' 'version\n requirements use the \'version\' keyword argument instead.') identifier, cached_dep = self._find_cached_dep(name, kwargs) if cached_dep: if required and not cached_dep.found(): m = 'Dependency {!r} was already checked and was not found' raise DependencyException(m.format(name)) dep = cached_dep else: # If the dependency has already been configured, possibly by # a higher level project, try to use it first. if 'fallback' in kwargs: dirname, varname = self.get_subproject_infos(kwargs) wanted = kwargs.get('version', 'undefined') dep = self._find_cached_fallback_dep(name, dirname, varname, wanted, required) if dep: return dep # We need to actually search for this dep exception = None dep = None # Search for it outside the project try: dep = dependencies.find_external_dependency(name, self.environment, kwargs) except DependencyException as e: exception = e # Search inside the projects list if not dep or not dep.found(): if 'fallback' in kwargs: fallback_dep = self.dependency_fallback(name, kwargs) if fallback_dep: # Never add fallback deps to self.coredata.deps since we # cannot cache them. They must always be evaluated else # we won't actually read all the build files. return fallback_dep if not dep: self.print_nested_info(name) assert(exception is not None) raise exception # Only store found-deps in the cache if dep.found(): self.coredata.deps[identifier] = dep return DependencyHolder(dep) @noKwargs @noPosargs def func_disabler(self, node, args, kwargs): return Disabler() def print_nested_info(self, dependency_name): message_templ = '''\nDependency %s not found but it is available in a sub-subproject. To use it in the current project, promote it by going in the project source root and issuing %s. ''' sprojs = mesonlib.detect_subprojects('subprojects', self.source_root) if dependency_name not in sprojs: return found = sprojs[dependency_name] if len(found) > 1: suffix = 'one of the following commands' else: suffix = 'the following command' message = message_templ % (dependency_name, suffix) cmds = [] command_templ = 'meson wrap promote ' for l in found: cmds.append(command_templ + l[len(self.source_root)+1:]) final_message = message + '\n'.join(cmds) print(final_message) def get_subproject_infos(self, kwargs): fbinfo = kwargs['fallback'] check_stringlist(fbinfo) if len(fbinfo) != 2: raise InterpreterException('Fallback info must have exactly two items.') return fbinfo def dependency_fallback(self, name, kwargs): if self.coredata.wrap_mode in (WrapMode.nofallback, WrapMode.nodownload): mlog.log('Not looking for a fallback subproject for the dependency', mlog.bold(name), 'because:\nAutomatic wrap-based fallback ' 'dependency downloading is disabled.') return None dirname, varname = self.get_subproject_infos(kwargs) # Try to execute the subproject try: sp_kwargs = {} try: sp_kwargs['default_options'] = kwargs['default_options'] except KeyError: pass self.do_subproject(dirname, sp_kwargs) # Invalid code is always an error except InvalidCode: raise # If the subproject execution failed in a non-fatal way, don't raise an # exception; let the caller handle things. except Exception as e: mlog.log('Also couldn\'t find a fallback subproject in', mlog.bold(os.path.join(self.subproject_dir, dirname)), 'for the dependency', mlog.bold(name), '\nReason:', str(e)) return None dep = self.get_subproject_dep(name, dirname, varname, kwargs.get('required', True)) if not dep: return None subproj_path = os.path.join(self.subproject_dir, dirname) # Check if the version of the declared dependency matches what we want if 'version' in kwargs: wanted = kwargs['version'] found = dep.version_method([], {}) if not self.check_subproject_version(wanted, found): mlog.log('Subproject', mlog.bold(subproj_path), 'dependency', mlog.bold(varname), 'version is', mlog.bold(found), 'but', mlog.bold(wanted), 'is required.') return None mlog.log('Dependency', mlog.bold(name), 'from subproject', mlog.bold(subproj_path), 'found:', mlog.green('YES')) return dep @permittedKwargs(permitted_kwargs['executable']) def func_executable(self, node, args, kwargs): return self.build_target(node, args, kwargs, ExecutableHolder) @permittedKwargs(permitted_kwargs['static_library']) def func_static_lib(self, node, args, kwargs): return self.build_target(node, args, kwargs, StaticLibraryHolder) @permittedKwargs(permitted_kwargs['shared_library']) def func_shared_lib(self, node, args, kwargs): return self.build_target(node, args, kwargs, SharedLibraryHolder) @permittedKwargs(permitted_kwargs['shared_module']) def func_shared_module(self, node, args, kwargs): return self.build_target(node, args, kwargs, SharedModuleHolder) def func_library(self, node, args, kwargs): if self.coredata.get_builtin_option('default_library') == 'shared': return self.func_shared_lib(node, args, kwargs) return self.func_static_lib(node, args, kwargs) @permittedKwargs(permitted_kwargs['jar']) def func_jar(self, node, args, kwargs): kwargs['target_type'] = 'jar' return self.build_target(node, args, kwargs, JarHolder) @permittedKwargs(permitted_kwargs['build_target']) def func_build_target(self, node, args, kwargs): if 'target_type' not in kwargs: raise InterpreterException('Missing target_type keyword argument') target_type = kwargs.pop('target_type') if target_type == 'executable': return self.func_executable(node, args, kwargs) elif target_type == 'shared_library': return self.func_shared_lib(node, args, kwargs) elif target_type == 'static_library': return self.func_static_lib(node, args, kwargs) elif target_type == 'library': return self.func_library(node, args, kwargs) elif target_type == 'jar': return self.func_jar(node, args, kwargs) else: raise InterpreterException('Unknown target_type.') @permittedKwargs(permitted_kwargs['vcs_tag']) def func_vcs_tag(self, node, args, kwargs): if 'input' not in kwargs or 'output' not in kwargs: raise InterpreterException('Keyword arguments input and output must exist') fallback = kwargs.pop('fallback', self.project_version) if not isinstance(fallback, str): raise InterpreterException('Keyword argument fallback must be a string.') replace_string = kwargs.pop('replace_string', '@VCS_TAG@') regex_selector = '(.*)' # default regex selector for custom command: use complete output vcs_cmd = kwargs.get('command', None) if vcs_cmd and not isinstance(vcs_cmd, list): vcs_cmd = [vcs_cmd] source_dir = os.path.normpath(os.path.join(self.environment.get_source_dir(), self.subdir)) if vcs_cmd: # Is the command an executable in path or maybe a script in the source tree? vcs_cmd[0] = shutil.which(vcs_cmd[0]) or os.path.join(source_dir, vcs_cmd[0]) else: vcs = mesonlib.detect_vcs(source_dir) if vcs: mlog.log('Found %s repository at %s' % (vcs['name'], vcs['wc_dir'])) vcs_cmd = vcs['get_rev'].split() regex_selector = vcs['rev_regex'] else: vcs_cmd = [' '] # executing this cmd will fail in vcstagger.py and force to use the fallback string # vcstagger.py parameters: infile, outfile, fallback, source_dir, replace_string, regex_selector, command... kwargs['command'] = self.environment.get_build_command() + \ ['--internal', 'vcstagger', '@INPUT0@', '@OUTPUT0@', fallback, source_dir, replace_string, regex_selector] + vcs_cmd kwargs.setdefault('build_always', True) return self.func_custom_target(node, [kwargs['output']], kwargs) @stringArgs @permittedKwargs(permitted_kwargs['custom_target']) def func_custom_target(self, node, args, kwargs): if len(args) != 1: raise InterpreterException('custom_target: Only one positional argument is allowed, and it must be a string name') name = args[0] tg = CustomTargetHolder(build.CustomTarget(name, self.subdir, self.subproject, kwargs), self) self.add_target(name, tg.held_object) return tg @permittedKwargs(permitted_kwargs['run_target']) def func_run_target(self, node, args, kwargs): if len(args) > 1: raise InvalidCode('Run_target takes only one positional argument: the target name.') elif len(args) == 1: if 'command' not in kwargs: raise InterpreterException('Missing "command" keyword argument') all_args = extract_as_list(kwargs, 'command') deps = extract_as_list(kwargs, 'depends') else: raise InterpreterException('Run_target needs at least one positional argument.') cleaned_args = [] for i in listify(all_args, unholder=True): if not isinstance(i, (str, build.BuildTarget, build.CustomTarget, dependencies.ExternalProgram, mesonlib.File)): mlog.debug('Wrong type:', str(i)) raise InterpreterException('Invalid argument to run_target.') cleaned_args.append(i) name = args[0] if not isinstance(name, str): raise InterpreterException('First argument must be a string.') cleaned_deps = [] for d in deps: try: d = d.held_object except AttributeError: pass if not isinstance(d, (build.BuildTarget, build.CustomTarget)): raise InterpreterException('Depends items must be build targets.') cleaned_deps.append(d) command = cleaned_args[0] cmd_args = cleaned_args[1:] tg = RunTargetHolder(name, command, cmd_args, cleaned_deps, self.subdir, self.subproject) self.add_target(name, tg.held_object) return tg @permittedKwargs(permitted_kwargs['generator']) def func_generator(self, node, args, kwargs): gen = GeneratorHolder(self, args, kwargs) self.generators.append(gen) return gen @permittedKwargs(permitted_kwargs['benchmark']) def func_benchmark(self, node, args, kwargs): self.add_test(node, args, kwargs, False) @permittedKwargs(permitted_kwargs['test']) def func_test(self, node, args, kwargs): self.add_test(node, args, kwargs, True) def unpack_env_kwarg(self, kwargs): envlist = kwargs.get('env', EnvironmentVariablesHolder()) if isinstance(envlist, EnvironmentVariablesHolder): env = envlist.held_object else: envlist = listify(envlist) # Convert from array to environment object env = EnvironmentVariablesHolder() for e in envlist: if '=' not in e: raise InterpreterException('Env var definition must be of type key=val.') (k, val) = e.split('=', 1) k = k.strip() val = val.strip() if ' ' in k: raise InterpreterException('Env var key must not have spaces in it.') env.set_method([k, val], {}) env = env.held_object return env def add_test(self, node, args, kwargs, is_base_test): if len(args) != 2: raise InterpreterException('Incorrect number of arguments') if not isinstance(args[0], str): raise InterpreterException('First argument of test must be a string.') exe = args[1] if not isinstance(exe, (ExecutableHolder, JarHolder, ExternalProgramHolder)): if isinstance(exe, mesonlib.File): exe = self.func_find_program(node, (args[1], ), {}) else: raise InterpreterException('Second argument must be executable.') par = kwargs.get('is_parallel', True) if not isinstance(par, bool): raise InterpreterException('Keyword argument is_parallel must be a boolean.') cmd_args = extract_as_list(kwargs, 'args', unholder=True) for i in cmd_args: if not isinstance(i, (str, mesonlib.File, build.Target)): raise InterpreterException('Command line arguments must be strings, files or targets.') env = self.unpack_env_kwarg(kwargs) should_fail = kwargs.get('should_fail', False) if not isinstance(should_fail, bool): raise InterpreterException('Keyword argument should_fail must be a boolean.') timeout = kwargs.get('timeout', 30) if 'workdir' in kwargs: workdir = kwargs['workdir'] if not isinstance(workdir, str): raise InterpreterException('Workdir keyword argument must be a string.') if not os.path.isabs(workdir): raise InterpreterException('Workdir keyword argument must be an absolute path.') else: workdir = None if not isinstance(timeout, int): raise InterpreterException('Timeout must be an integer.') suite = [] prj = self.subproject if self.is_subproject() else self.build.project_name for s in mesonlib.stringlistify(kwargs.get('suite', '')): if len(s) > 0: s = ':' + s suite.append(prj.replace(' ', '_').replace(':', '_') + s) t = Test(args[0], prj, suite, exe.held_object, par, cmd_args, env, should_fail, timeout, workdir) if is_base_test: self.build.tests.append(t) mlog.debug('Adding test "', mlog.bold(args[0]), '".', sep='') else: self.build.benchmarks.append(t) mlog.debug('Adding benchmark "', mlog.bold(args[0]), '".', sep='') @permittedKwargs(permitted_kwargs['install_headers']) def func_install_headers(self, node, args, kwargs): source_files = self.source_strings_to_files(args) h = Headers(source_files, kwargs) self.build.headers.append(h) return h @permittedKwargs(permitted_kwargs['install_man']) def func_install_man(self, node, args, kwargs): fargs = self.source_strings_to_files(args) m = Man(fargs, kwargs) self.build.man.append(m) return m @permittedKwargs(permitted_kwargs['subdir']) def func_subdir(self, node, args, kwargs): self.validate_arguments(args, 1, [str]) mesonlib.check_direntry_issues(args) if '..' in args[0]: raise InvalidArguments('Subdir contains ..') if self.subdir == '' and args[0] == self.subproject_dir: raise InvalidArguments('Must not go into subprojects dir with subdir(), use subproject() instead.') if self.subdir == '' and args[0].startswith('meson-'): raise InvalidArguments('The "meson-" prefix is reserved and cannot be used for top-level subdir().') for i in mesonlib.extract_as_list(kwargs, 'if_found'): if not hasattr(i, 'found_method'): raise InterpreterException('Object used in if_found does not have a found method.') if not i.found_method([], {}): return prev_subdir = self.subdir subdir = os.path.join(prev_subdir, args[0]) if os.path.isabs(subdir): raise InvalidArguments('Subdir argument must be a relative path.') absdir = os.path.join(self.environment.get_source_dir(), subdir) symlinkless_dir = os.path.realpath(absdir) if symlinkless_dir in self.visited_subdirs: raise InvalidArguments('Tried to enter directory "%s", which has already been visited.' % subdir) self.visited_subdirs[symlinkless_dir] = True self.subdir = subdir os.makedirs(os.path.join(self.environment.build_dir, subdir), exist_ok=True) buildfilename = os.path.join(self.subdir, environment.build_filename) self.build_def_files.append(buildfilename) absname = os.path.join(self.environment.get_source_dir(), buildfilename) if not os.path.isfile(absname): self.subdir = prev_subdir raise InterpreterException('Non-existent build file {!r}'.format(buildfilename)) with open(absname, encoding='utf8') as f: code = f.read() assert(isinstance(code, str)) try: codeblock = mparser.Parser(code, self.subdir).parse() except mesonlib.MesonException as me: me.file = buildfilename raise me self.evaluate_codeblock(codeblock) self.subdir = prev_subdir def _get_kwarg_install_mode(self, kwargs): if 'install_mode' not in kwargs: return None install_mode = [] mode = mesonlib.typeslistify(kwargs.get('install_mode', []), (str, int)) for m in mode: # We skip any arguments that are set to `false` if m is False: m = None install_mode.append(m) if len(install_mode) > 3: raise InvalidArguments('Keyword argument install_mode takes at ' 'most 3 arguments.') if len(install_mode) > 0 and install_mode[0] is not None and \ not isinstance(install_mode[0], str): raise InvalidArguments('Keyword argument install_mode requires the ' 'permissions arg to be a string or false') return FileMode(*install_mode) @permittedKwargs(permitted_kwargs['install_data']) def func_install_data(self, node, args, kwargs): kwsource = mesonlib.stringlistify(kwargs.get('sources', [])) raw_sources = args + kwsource sources = [] source_strings = [] for s in raw_sources: if isinstance(s, mesonlib.File): sources.append(s) else: source_strings.append(s) sources += self.source_strings_to_files(source_strings) install_dir = kwargs.get('install_dir', None) if not isinstance(install_dir, (str, type(None))): raise InvalidArguments('Keyword argument install_dir not a string.') install_mode = self._get_kwarg_install_mode(kwargs) data = DataHolder(build.Data(sources, install_dir, install_mode)) self.build.data.append(data.held_object) return data @permittedKwargs(permitted_kwargs['install_subdir']) @stringArgs def func_install_subdir(self, node, args, kwargs): if len(args) != 1: raise InvalidArguments('Install_subdir requires exactly one argument.') subdir = args[0] if 'install_dir' not in kwargs: raise InvalidArguments('Missing keyword argument install_dir') install_dir = kwargs['install_dir'] if not isinstance(install_dir, str): raise InvalidArguments('Keyword argument install_dir not a string.') if 'strip_directory' in kwargs: if not isinstance(kwargs['strip_directory'], bool): raise InterpreterException('"strip_directory" keyword must be a boolean.') strip_directory = kwargs['strip_directory'] else: strip_directory = False if 'exclude_files' in kwargs: exclude = extract_as_list(kwargs, 'exclude_files') for f in exclude: if not isinstance(f, str): raise InvalidArguments('Exclude argument not a string.') elif os.path.isabs(f): raise InvalidArguments('Exclude argument cannot be absolute.') exclude_files = set(exclude) else: exclude_files = set() if 'exclude_directories' in kwargs: exclude = extract_as_list(kwargs, 'exclude_directories') for d in exclude: if not isinstance(d, str): raise InvalidArguments('Exclude argument not a string.') elif os.path.isabs(d): raise InvalidArguments('Exclude argument cannot be absolute.') exclude_directories = set(exclude) else: exclude_directories = set() exclude = (exclude_files, exclude_directories) install_mode = self._get_kwarg_install_mode(kwargs) idir = InstallDir(self.subdir, subdir, install_dir, install_mode, exclude, strip_directory) self.build.install_dirs.append(idir) return idir @permittedKwargs(permitted_kwargs['configure_file']) def func_configure_file(self, node, args, kwargs): if len(args) > 0: raise InterpreterException("configure_file takes only keyword arguments.") if 'output' not in kwargs: raise InterpreterException('Required keyword argument "output" not defined.') if 'configuration' in kwargs and 'command' in kwargs: raise InterpreterException('Must not specify both "configuration" ' 'and "command" keyword arguments since ' 'they are mutually exclusive.') if 'capture' in kwargs: if not isinstance(kwargs['capture'], bool): raise InterpreterException('"capture" keyword must be a boolean.') if 'command' not in kwargs: raise InterpreterException('"capture" keyword requires "command" keyword.') # Validate input inputfile = None ifile_abs = None if 'input' in kwargs: inputfile = kwargs['input'] if isinstance(inputfile, list): if len(inputfile) != 1: m = "Keyword argument 'input' requires exactly one file" raise InterpreterException(m) inputfile = inputfile[0] if not isinstance(inputfile, (str, mesonlib.File)): raise InterpreterException('Input must be a string or a file') if isinstance(inputfile, str): inputfile = mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, inputfile) ifile_abs = inputfile.absolute_path(self.environment.source_dir, self.environment.build_dir) elif 'command' in kwargs and '@INPUT@' in kwargs['command']: raise InterpreterException('@INPUT@ used as command argument, but no input file specified.') # Validate output output = kwargs['output'] if not isinstance(output, str): raise InterpreterException('Output file name must be a string') if ifile_abs: values = mesonlib.get_filenames_templates_dict([ifile_abs], None) outputs = mesonlib.substitute_values([output], values) output = outputs[0] if os.path.dirname(output) != '': raise InterpreterException('Output file name must not contain a subdirectory.') (ofile_path, ofile_fname) = os.path.split(os.path.join(self.subdir, output)) ofile_abs = os.path.join(self.environment.build_dir, ofile_path, ofile_fname) if 'configuration' in kwargs: conf = kwargs['configuration'] if not isinstance(conf, ConfigurationDataHolder): raise InterpreterException('Argument "configuration" is not of type configuration_data') mlog.log('Configuring', mlog.bold(output), 'using configuration') if inputfile is not None: os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True) missing_variables = mesonlib.do_conf_file(ifile_abs, ofile_abs, conf.held_object) if missing_variables: var_list = ", ".join(map(repr, sorted(missing_variables))) mlog.warning( "The variable(s) %s in the input file %s are not " "present in the given configuration data." % ( var_list, inputfile), location=node) else: mesonlib.dump_conf_header(ofile_abs, conf.held_object) conf.mark_used() elif 'command' in kwargs: # We use absolute paths for input and output here because the cwd # that the command is run from is 'unspecified', so it could change. # Currently it's builddir/subdir for in_builddir else srcdir/subdir. if ifile_abs: values = mesonlib.get_filenames_templates_dict([ifile_abs], [ofile_abs]) else: values = mesonlib.get_filenames_templates_dict(None, [ofile_abs]) # Substitute @INPUT@, @OUTPUT@, etc here. cmd = mesonlib.substitute_values(kwargs['command'], values) mlog.log('Configuring', mlog.bold(output), 'with command') res = self.run_command_impl(node, cmd, {}, True) if res.returncode != 0: raise InterpreterException('Running configure command failed.\n%s\n%s' % (res.stdout, res.stderr)) if 'capture' in kwargs and kwargs['capture']: dst_tmp = ofile_abs + '~' with open(dst_tmp, 'w', encoding='utf-8') as f: f.writelines(res.stdout) if ifile_abs: shutil.copymode(ifile_abs, dst_tmp) mesonlib.replace_if_different(ofile_abs, dst_tmp) else: raise InterpreterException('Configure_file must have either "configuration" or "command".') # If the input is a source file, add it to the list of files that we # need to reconfigure on when they change. FIXME: Do the same for # files() objects in the command: kwarg. if inputfile and not inputfile.is_built: # Normalize the path of the conffile (relative to the # source root) to avoid duplicates. This is especially # important to convert '/' to '\' on Windows conffile = os.path.normpath(inputfile.relative_name()) if conffile not in self.build_def_files: self.build_def_files.append(conffile) # Install file if requested, we check for the empty string # for backwards compatibility. That was the behaviour before # 0.45.0 so preserve it. idir = kwargs.get('install_dir', None) if isinstance(idir, str) and idir: cfile = mesonlib.File.from_built_file(ofile_path, ofile_fname) self.build.data.append(build.Data([cfile], idir)) return mesonlib.File.from_built_file(self.subdir, output) @permittedKwargs(permitted_kwargs['include_directories']) @stringArgs def func_include_directories(self, node, args, kwargs): return self.build_incdir_object(args, kwargs.get('is_system', False)) def build_incdir_object(self, incdir_strings, is_system=False): if not isinstance(is_system, bool): raise InvalidArguments('Is_system must be boolean.') src_root = self.environment.get_source_dir() build_root = self.environment.get_build_dir() absbase_src = os.path.join(src_root, self.subdir) absbase_build = os.path.join(build_root, self.subdir) for a in incdir_strings: if a.startswith(src_root): raise InvalidArguments('''Tried to form an absolute path to a source dir. You should not do that but use relative paths instead. To get include path to any directory relative to the current dir do incdir = include_directories(dirname) After this incdir will contain both the current source dir as well as the corresponding build dir. It can then be used in any subdirectory and Meson will take care of all the busywork to make paths work. Dirname can even be '.' to mark the current directory. Though you should remember that the current source and build directories are always put in the include directories by default so you only need to do include_directories('.') if you intend to use the result in a different subdirectory. ''') absdir_src = os.path.join(absbase_src, a) absdir_build = os.path.join(absbase_build, a) if not os.path.isdir(absdir_src) and not os.path.isdir(absdir_build): raise InvalidArguments('Include dir %s does not exist.' % a) i = IncludeDirsHolder(build.IncludeDirs(self.subdir, incdir_strings, is_system)) return i @permittedKwargs(permitted_kwargs['add_test_setup']) @stringArgs def func_add_test_setup(self, node, args, kwargs): if len(args) != 1: raise InterpreterException('Add_test_setup needs one argument for the setup name.') setup_name = args[0] if re.fullmatch('([_a-zA-Z][_0-9a-zA-Z]*:)?[_a-zA-Z][_0-9a-zA-Z]*', setup_name) is None: raise InterpreterException('Setup name may only contain alphanumeric characters.') if ":" not in setup_name: setup_name = (self.subproject if self.subproject else self.build.project_name) + ":" + setup_name try: inp = extract_as_list(kwargs, 'exe_wrapper') exe_wrapper = [] for i in inp: if hasattr(i, 'held_object'): i = i.held_object if isinstance(i, str): exe_wrapper.append(i) elif isinstance(i, dependencies.ExternalProgram): if not i.found(): raise InterpreterException('Tried to use non-found executable.') exe_wrapper += i.get_command() else: raise InterpreterException('Exe wrapper can only contain strings or external binaries.') except KeyError: exe_wrapper = None gdb = kwargs.get('gdb', False) if not isinstance(gdb, bool): raise InterpreterException('Gdb option must be a boolean') timeout_multiplier = kwargs.get('timeout_multiplier', 1) if not isinstance(timeout_multiplier, int): raise InterpreterException('Timeout multiplier must be a number.') env = self.unpack_env_kwarg(kwargs) self.build.test_setups[setup_name] = build.TestSetup(exe_wrapper=exe_wrapper, gdb=gdb, timeout_multiplier=timeout_multiplier, env=env) @permittedKwargs(permitted_kwargs['add_global_arguments']) @stringArgs def func_add_global_arguments(self, node, args, kwargs): self.add_global_arguments(node, self.build.global_args, args, kwargs) @permittedKwargs(permitted_kwargs['add_global_link_arguments']) @stringArgs def func_add_global_link_arguments(self, node, args, kwargs): self.add_global_arguments(node, self.build.global_link_args, args, kwargs) @permittedKwargs(permitted_kwargs['add_project_arguments']) @stringArgs def func_add_project_arguments(self, node, args, kwargs): self.add_project_arguments(node, self.build.projects_args, args, kwargs) @permittedKwargs(permitted_kwargs['add_project_link_arguments']) @stringArgs def func_add_project_link_arguments(self, node, args, kwargs): self.add_project_arguments(node, self.build.projects_link_args, args, kwargs) def add_global_arguments(self, node, argsdict, args, kwargs): if self.subproject != '': msg = 'Function \'{}\' cannot be used in subprojects because ' \ 'there is no way to make that reliable.\nPlease only call ' \ 'this if is_subproject() returns false. Alternatively, ' \ 'define a variable that\ncontains your language-specific ' \ 'arguments and add it to the appropriate *_args kwarg ' \ 'in each target.'.format(node.func_name) raise InvalidCode(msg) frozen = self.project_args_frozen or self.global_args_frozen self.add_arguments(node, argsdict, frozen, args, kwargs) def add_project_arguments(self, node, argsdict, args, kwargs): if self.subproject not in argsdict: argsdict[self.subproject] = {} self.add_arguments(node, argsdict[self.subproject], self.project_args_frozen, args, kwargs) def add_arguments(self, node, argsdict, args_frozen, args, kwargs): if args_frozen: msg = 'Tried to use \'{}\' after a build target has been declared.\n' \ 'This is not permitted. Please declare all ' \ 'arguments before your targets.'.format(node.func_name) raise InvalidCode(msg) if 'language' not in kwargs: raise InvalidCode('Missing language definition in {}'.format(node.func_name)) for lang in mesonlib.stringlistify(kwargs['language']): lang = lang.lower() argsdict[lang] = argsdict.get(lang, []) + args @noKwargs @noPosargs def func_environment(self, node, args, kwargs): return EnvironmentVariablesHolder() @stringArgs @noKwargs def func_join_paths(self, node, args, kwargs): return os.path.join(*args).replace('\\', '/') def run(self): super().run() mlog.log('Build targets in project:', mlog.bold(str(len(self.build.targets)))) def evaluate_subproject_info(self, path_from_source_root, subproject_dirname): depth = 0 subproj_name = '' segs = PurePath(path_from_source_root).parts segs_spd = PurePath(subproject_dirname).parts while segs and segs[0] == segs_spd[0]: if len(segs_spd) == 1: subproj_name = segs[1] segs = segs[2:] depth += 1 else: segs_spd = segs_spd[1:] segs = segs[1:] return (depth, subproj_name) # Check that the indicated file is within the same subproject # as we currently are. This is to stop people doing # nasty things like: # # f = files('../../master_src/file.c') # # Note that this is validated only when the file # object is generated. The result can be used in a different # subproject than it is defined in (due to e.g. a # declare_dependency). def validate_within_subproject(self, subdir, fname): norm = os.path.normpath(os.path.join(subdir, fname)) if os.path.isabs(norm): if not norm.startswith(self.environment.source_dir): # Grabbing files outside the source tree is ok. # This is for vendor stuff like: # # /opt/vendorsdk/src/file_with_license_restrictions.c return norm = os.path.relpath(norm, self.environment.source_dir) assert(not os.path.isabs(norm)) (num_sps, sproj_name) = self.evaluate_subproject_info(norm, self.subproject_dir) plain_filename = os.path.basename(norm) if num_sps == 0: if self.subproject == '': return raise InterpreterException('Sandbox violation: Tried to grab file %s from a different subproject.' % plain_filename) if num_sps > 1: raise InterpreterException('Sandbox violation: Tried to grab file %s from a nested subproject.' % plain_filename) if sproj_name != self.subproject_directory_name: raise InterpreterException('Sandbox violation: Tried to grab file %s from a different subproject.' % plain_filename) def source_strings_to_files(self, sources): results = [] mesonlib.check_direntry_issues(sources) if not isinstance(sources, list): sources = [sources] for s in sources: if isinstance(s, (mesonlib.File, GeneratedListHolder, CustomTargetHolder, CustomTargetIndexHolder)): pass elif isinstance(s, str): self.validate_within_subproject(self.subdir, s) s = mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, s) else: raise InterpreterException('Source item is {!r} instead of ' 'string or File-type object'.format(s)) results.append(s) return results def add_target(self, name, tobj): if name == '': raise InterpreterException('Target name must not be empty.') if name.strip() == '': raise InterpreterException('Target name must not consist only of whitespace.') if name.startswith('meson-'): raise InvalidArguments("Target names starting with 'meson-' are reserved " "for Meson's internal use. Please rename.") if name in coredata.forbidden_target_names: raise InvalidArguments("Target name '%s' is reserved for Meson's " "internal use. Please rename." % name) # To permit an executable and a shared library to have the # same name, such as "foo.exe" and "libfoo.a". idname = tobj.get_id() if idname in self.build.targets: raise InvalidCode('Tried to create target "%s", but a target of that name already exists.' % name) self.build.targets[idname] = tobj if idname not in self.coredata.target_guids: self.coredata.target_guids[idname] = str(uuid.uuid4()).upper() def build_target(self, node, args, kwargs, targetholder): if not args: raise InterpreterException('Target does not have a name.') name = args[0] sources = listify(args[1:]) if self.environment.is_cross_build(): if kwargs.get('native', False): is_cross = False else: is_cross = True else: is_cross = False if 'sources' in kwargs: sources += listify(kwargs['sources']) sources = self.source_strings_to_files(sources) objs = extract_as_list(kwargs, 'objects') kwargs['dependencies'] = extract_as_list(kwargs, 'dependencies') if 'extra_files' in kwargs: ef = extract_as_list(kwargs, 'extra_files') kwargs['extra_files'] = self.source_strings_to_files(ef) self.check_sources_exist(os.path.join(self.source_root, self.subdir), sources) if targetholder is ExecutableHolder: targetclass = build.Executable elif targetholder is SharedLibraryHolder: targetclass = build.SharedLibrary elif targetholder is SharedModuleHolder: targetclass = build.SharedModule elif targetholder is StaticLibraryHolder: targetclass = build.StaticLibrary elif targetholder is JarHolder: targetclass = build.Jar else: mlog.debug('Unknown target type:', str(targetholder)) raise RuntimeError('Unreachable code') self.kwarg_strings_to_includedirs(kwargs) target = targetclass(name, self.subdir, self.subproject, is_cross, sources, objs, self.environment, kwargs) if is_cross: self.add_cross_stdlib_info(target) l = targetholder(target, self) self.add_target(name, l.held_object) self.project_args_frozen = True return l def kwarg_strings_to_includedirs(self, kwargs): if 'd_import_dirs' in kwargs: items = mesonlib.extract_as_list(kwargs, 'd_import_dirs') cleaned_items = [] for i in items: if isinstance(i, str): # BW compatibility. This was permitted so we must support it # for a few releases so people can transition to "correct" # path declarations. if i.startswith(self.environment.get_source_dir()): mlog.warning('''Building a path to the source dir is not supported. Use a relative path instead. This will become a hard error in the future.''') i = os.path.relpath(i, os.path.join(self.environment.get_source_dir(), self.subdir)) i = self.build_incdir_object([i]) cleaned_items.append(i) kwargs['d_import_dirs'] = cleaned_items def get_used_languages(self, target): result = {} for i in target.sources: for lang, c in self.build.compilers.items(): if c.can_compile(i): result[lang] = True break return result def add_cross_stdlib_info(self, target): for l in self.get_used_languages(target): if self.environment.cross_info.has_stdlib(l) \ and self.subproject != self.environment.cross_info.get_stdlib(l)[0]: target.add_deps(self.build.cross_stdlibs[l]) def check_sources_exist(self, subdir, sources): for s in sources: if not isinstance(s, str): continue # This means a generated source and they always exist. fname = os.path.join(subdir, s) if not os.path.isfile(fname): raise InterpreterException('Tried to add non-existing source file %s.' % s) def format_string(self, templ, args): if isinstance(args, mparser.ArgumentNode): args = args.arguments arg_strings = [] for arg in args: arg = self.evaluate_statement(arg) if isinstance(arg, bool): # Python boolean is upper case. arg = str(arg).lower() arg_strings.append(str(arg)) def arg_replace(match): idx = int(match.group(1)) if idx >= len(arg_strings): raise InterpreterException('Format placeholder @{}@ out of range.'.format(idx)) return arg_strings[idx] return re.sub(r'@(\d+)@', arg_replace, templ) # Only permit object extraction from the same subproject def validate_extraction(self, buildtarget): if not self.subdir.startswith(self.subproject_dir): if buildtarget.subdir.startswith(self.subproject_dir): raise InterpreterException('Tried to extract objects from a subproject target.') else: if not buildtarget.subdir.startswith(self.subproject_dir): raise InterpreterException('Tried to extract objects from the main project from a subproject.') if self.subdir.split('/')[1] != buildtarget.subdir.split('/')[1]: raise InterpreterException('Tried to extract objects from a different subproject.') def check_contains(self, obj, args): if len(args) != 1: raise InterpreterException('Contains method takes exactly one argument.') item = args[0] for element in obj: if isinstance(element, list): found = self.check_contains(element, args) if found: return True if element == item: return True return False def is_subproject(self): return self.subproject != '' @noKwargs def func_set_variable(self, node, args, kwargs): if len(args) != 2: raise InvalidCode('Set_variable takes two arguments.') varname = args[0] value = args[1] self.set_variable(varname, value) @noKwargs def func_get_variable(self, node, args, kwargs): if len(args) < 1 or len(args) > 2: raise InvalidCode('Get_variable takes one or two arguments.') varname = args[0] if not isinstance(varname, str): raise InterpreterException('First argument must be a string.') try: return self.variables[varname] except KeyError: pass if len(args) == 2: return args[1] raise InterpreterException('Tried to get unknown variable "%s".' % varname) @stringArgs @noKwargs def func_is_variable(self, node, args, kwargs): if len(args) != 1: raise InvalidCode('Is_variable takes two arguments.') varname = args[0] return varname in self.variables meson-0.45.1/mesonbuild/mtest.py0000644000175000017500000005716513254550710020203 0ustar jpakkanejpakkane00000000000000# Copyright 2016-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. # A tool to run tests in many different ways. import shlex import subprocess, sys, os, argparse import pickle from mesonbuild import build from mesonbuild import environment from mesonbuild.dependencies import ExternalProgram from mesonbuild import mesonlib from mesonbuild import mlog import time, datetime, multiprocessing, json import concurrent.futures as conc import platform import signal import random from copy import deepcopy # GNU autotools interprets a return code of 77 from tests it executes to # mean that the test should be skipped. GNU_SKIP_RETURNCODE = 77 def is_windows(): platname = platform.system().lower() return platname == 'windows' or 'mingw' in platname def is_cygwin(): platname = platform.system().lower() return 'cygwin' in platname def determine_worker_count(): varname = 'MESON_TESTTHREADS' if varname in os.environ: try: num_workers = int(os.environ[varname]) except ValueError: print('Invalid value in %s, using 1 thread.' % varname) num_workers = 1 else: try: # Fails in some weird environments such as Debian # reproducible build. num_workers = multiprocessing.cpu_count() except Exception: num_workers = 1 return num_workers parser = argparse.ArgumentParser(prog='meson test') parser.add_argument('--repeat', default=1, dest='repeat', type=int, help='Number of times to run the tests.') parser.add_argument('--no-rebuild', default=False, action='store_true', help='Do not rebuild before running tests.') parser.add_argument('--gdb', default=False, dest='gdb', action='store_true', help='Run test under gdb.') parser.add_argument('--list', default=False, dest='list', action='store_true', help='List available tests.') parser.add_argument('--wrapper', default=None, dest='wrapper', type=shlex.split, help='wrapper to run tests with (e.g. Valgrind)') parser.add_argument('-C', default='.', dest='wd', help='directory to cd into before running') parser.add_argument('--suite', default=[], dest='include_suites', action='append', metavar='SUITE', help='Only run tests belonging to the given suite.') parser.add_argument('--no-suite', default=[], dest='exclude_suites', action='append', metavar='SUITE', help='Do not run tests belonging to the given suite.') parser.add_argument('--no-stdsplit', default=True, dest='split', action='store_false', help='Do not split stderr and stdout in test logs.') parser.add_argument('--print-errorlogs', default=False, action='store_true', help="Whether to print failing tests' logs.") parser.add_argument('--benchmark', default=False, action='store_true', help="Run benchmarks instead of tests.") parser.add_argument('--logbase', default='testlog', help="Base name for log file.") parser.add_argument('--num-processes', default=determine_worker_count(), type=int, help='How many parallel processes to use.') parser.add_argument('-v', '--verbose', default=False, action='store_true', help='Do not redirect stdout and stderr') parser.add_argument('-q', '--quiet', default=False, action='store_true', help='Produce less output to the terminal.') parser.add_argument('-t', '--timeout-multiplier', type=float, default=None, help='Define a multiplier for test timeout, for example ' ' when running tests in particular conditions they might take' ' more time to execute.') parser.add_argument('--setup', default=None, dest='setup', help='Which test setup to use.') parser.add_argument('--test-args', default=[], type=shlex.split, help='Arguments to pass to the specified test(s) or all tests') parser.add_argument('args', nargs='*', help='Optional list of tests to run') class TestException(mesonlib.MesonException): pass class TestRun: def __init__(self, res, returncode, should_fail, duration, stdo, stde, cmd, env): self.res = res self.returncode = returncode self.duration = duration self.stdo = stdo self.stde = stde self.cmd = cmd self.env = env self.should_fail = should_fail def get_log(self): res = '--- command ---\n' if self.cmd is None: res += 'NONE\n' else: res += "%s%s\n" % (''.join(["%s='%s' " % (k, v) for k, v in self.env.items()]), ' ' .join(self.cmd)) if self.stdo: res += '--- stdout ---\n' res += self.stdo if self.stde: if res[-1:] != '\n': res += '\n' res += '--- stderr ---\n' res += self.stde if res[-1:] != '\n': res += '\n' res += '-------\n\n' return res def decode(stream): if stream is None: return '' try: return stream.decode('utf-8') except UnicodeDecodeError: return stream.decode('iso-8859-1', errors='ignore') def write_json_log(jsonlogfile, test_name, result): jresult = {'name': test_name, 'stdout': result.stdo, 'result': result.res, 'duration': result.duration, 'returncode': result.returncode, 'command': result.cmd} if isinstance(result.env, dict): jresult['env'] = result.env else: jresult['env'] = result.env.get_env(os.environ) if result.stde: jresult['stderr'] = result.stde jsonlogfile.write(json.dumps(jresult) + '\n') def run_with_mono(fname): if fname.endswith('.exe') and not (is_windows() or is_cygwin()): return True return False def load_benchmarks(build_dir): datafile = os.path.join(build_dir, 'meson-private', 'meson_benchmark_setup.dat') if not os.path.isfile(datafile): raise TestException('Directory ${!r} does not seem to be a Meson build directory.'.format(build_dir)) with open(datafile, 'rb') as f: obj = pickle.load(f) return obj def load_tests(build_dir): datafile = os.path.join(build_dir, 'meson-private', 'meson_test_setup.dat') if not os.path.isfile(datafile): raise TestException('Directory ${!r} does not seem to be a Meson build directory.'.format(build_dir)) with open(datafile, 'rb') as f: obj = pickle.load(f) return obj class TestHarness: def __init__(self, options): self.options = options self.collected_logs = [] self.fail_count = 0 self.success_count = 0 self.skip_count = 0 self.timeout_count = 0 self.is_run = False self.tests = None self.suites = None self.logfilename = None self.logfile = None self.jsonlogfile = None if self.options.benchmark: self.tests = load_benchmarks(options.wd) else: self.tests = load_tests(options.wd) self.load_suites() def __del__(self): if self.logfile: self.logfile.close() if self.jsonlogfile: self.jsonlogfile.close() def merge_suite_options(self, options, test): if ":" in options.setup: if options.setup not in self.build_data.test_setups: sys.exit("Unknown test setup '%s'." % options.setup) current = self.build_data.test_setups[options.setup] else: full_name = test.project_name + ":" + options.setup if full_name not in self.build_data.test_setups: sys.exit("Test setup '%s' not found from project '%s'." % (options.setup, test.project_name)) current = self.build_data.test_setups[full_name] if not options.gdb: options.gdb = current.gdb if options.timeout_multiplier is None: options.timeout_multiplier = current.timeout_multiplier # if options.env is None: # options.env = current.env # FIXME, should probably merge options here. if options.wrapper is not None and current.exe_wrapper is not None: sys.exit('Conflict: both test setup and command line specify an exe wrapper.') if options.wrapper is None: options.wrapper = current.exe_wrapper return current.env.get_env(os.environ.copy()) def get_test_env(self, options, test): if options.setup: env = self.merge_suite_options(options, test) else: env = os.environ.copy() if isinstance(test.env, build.EnvironmentVariables): test.env = test.env.get_env(env) env.update(test.env) return env def run_single_test(self, test): if test.fname[0].endswith('.jar'): cmd = ['java', '-jar'] + test.fname elif not test.is_cross_built and run_with_mono(test.fname[0]): cmd = ['mono'] + test.fname else: if test.is_cross_built: if test.exe_runner is None: # Can not run test on cross compiled executable # because there is no execute wrapper. cmd = None else: cmd = [test.exe_runner] + test.fname else: cmd = test.fname if cmd is None: res = 'SKIP' duration = 0.0 stdo = 'Not run because can not execute cross compiled binaries.' stde = None returncode = GNU_SKIP_RETURNCODE else: test_opts = deepcopy(self.options) test_env = self.get_test_env(test_opts, test) wrap = self.get_wrapper(test_opts) if test_opts.gdb: test.timeout = None cmd = wrap + cmd + test.cmd_args + self.options.test_args starttime = time.time() if len(test.extra_paths) > 0: test_env['PATH'] = os.pathsep.join(test.extra_paths + ['']) + test_env['PATH'] # If MALLOC_PERTURB_ is not set, or if it is set to an empty value, # (i.e., the test or the environment don't explicitly set it), set # it ourselves. We do this unconditionally for regular tests # because it is extremely useful to have. # Setting MALLOC_PERTURB_="0" will completely disable this feature. if ('MALLOC_PERTURB_' not in test_env or not test_env['MALLOC_PERTURB_']) and not self.options.benchmark: test_env['MALLOC_PERTURB_'] = str(random.randint(1, 255)) setsid = None stdout = None stderr = None if not self.options.verbose: stdout = subprocess.PIPE stderr = subprocess.PIPE if self.options and self.options.split else subprocess.STDOUT if not is_windows(): setsid = os.setsid p = subprocess.Popen(cmd, stdout=stdout, stderr=stderr, env=test_env, cwd=test.workdir, preexec_fn=setsid) timed_out = False kill_test = False if test.timeout is None: timeout = None elif test_opts.timeout_multiplier is not None: timeout = test.timeout * test_opts.timeout_multiplier else: timeout = test.timeout try: (stdo, stde) = p.communicate(timeout=timeout) except subprocess.TimeoutExpired: if self.options.verbose: print("%s time out (After %d seconds)" % (test.name, timeout)) timed_out = True except KeyboardInterrupt: mlog.warning("CTRL-C detected while running %s" % (test.name)) kill_test = True if kill_test or timed_out: # Python does not provide multiplatform support for # killing a process and all its children so we need # to roll our own. if is_windows(): subprocess.call(['taskkill', '/F', '/T', '/PID', str(p.pid)]) else: try: os.killpg(os.getpgid(p.pid), signal.SIGKILL) except ProcessLookupError: # Sometimes (e.g. with Wine) this happens. # There's nothing we can do (maybe the process # already died) so carry on. pass (stdo, stde) = p.communicate() endtime = time.time() duration = endtime - starttime stdo = decode(stdo) if stde: stde = decode(stde) if timed_out: res = 'TIMEOUT' self.timeout_count += 1 self.fail_count += 1 elif p.returncode == GNU_SKIP_RETURNCODE: res = 'SKIP' self.skip_count += 1 elif test.should_fail == bool(p.returncode): res = 'OK' self.success_count += 1 else: res = 'FAIL' self.fail_count += 1 returncode = p.returncode result = TestRun(res, returncode, test.should_fail, duration, stdo, stde, cmd, test.env) return result def print_stats(self, numlen, tests, name, result, i): startpad = ' ' * (numlen - len('%d' % (i + 1))) num = '%s%d/%d' % (startpad, i + 1, len(tests)) padding1 = ' ' * (38 - len(name)) padding2 = ' ' * (8 - len(result.res)) result_str = '%s %s %s%s%s%5.2f s' % \ (num, name, padding1, result.res, padding2, result.duration) if not self.options.quiet or result.res != 'OK': if result.res != 'OK' and mlog.colorize_console: if result.res == 'FAIL' or result.res == 'TIMEOUT': decorator = mlog.red elif result.res == 'SKIP': decorator = mlog.yellow else: sys.exit('Unreachable code was ... well ... reached.') print(decorator(result_str).get_text(True)) else: print(result_str) result_str += "\n\n" + result.get_log() if (result.returncode != GNU_SKIP_RETURNCODE) \ and (result.returncode != 0) != result.should_fail: if self.options.print_errorlogs: self.collected_logs.append(result_str) if self.logfile: self.logfile.write(result_str) if self.jsonlogfile: write_json_log(self.jsonlogfile, name, result) def print_summary(self): msg = ''' OK: %4d FAIL: %4d SKIP: %4d TIMEOUT: %4d ''' % (self.success_count, self.fail_count, self.skip_count, self.timeout_count) print(msg) if self.logfile: self.logfile.write(msg) def print_collected_logs(self): if len(self.collected_logs) > 0: if len(self.collected_logs) > 10: print('\nThe output from 10 first failed tests:\n') else: print('\nThe output from the failed tests:\n') for log in self.collected_logs[:10]: lines = log.splitlines() if len(lines) > 104: print('\n'.join(lines[0:4])) print('--- Listing only the last 100 lines from a long log. ---') lines = lines[-100:] for line in lines: print(line) def doit(self): if self.is_run: raise RuntimeError('Test harness object can only be used once.') self.is_run = True tests = self.get_tests() if not tests: return 0 self.run_tests(tests) return self.fail_count @staticmethod def split_suite_string(suite): if ':' in suite: return suite.split(':', 1) else: return suite, "" @staticmethod def test_in_suites(test, suites): for suite in suites: (prj_match, st_match) = TestHarness.split_suite_string(suite) for prjst in test.suite: (prj, st) = TestHarness.split_suite_string(prjst) if prj_match and prj != prj_match: continue if st_match and st != st_match: continue return True return False def test_suitable(self, test): return (not self.options.include_suites or TestHarness.test_in_suites(test, self.options.include_suites)) \ and not TestHarness.test_in_suites(test, self.options.exclude_suites) def load_suites(self): ss = set() for t in self.tests: for s in t.suite: ss.add(s) self.suites = list(ss) def get_tests(self): if not self.tests: print('No tests defined.') return [] if len(self.options.include_suites) or len(self.options.exclude_suites): tests = [] for tst in self.tests: if self.test_suitable(tst): tests.append(tst) else: tests = self.tests if self.options.args: tests = [t for t in tests if t.name in self.options.args] if not tests: print('No suitable tests defined.') return [] for test in tests: test.rebuilt = False return tests def open_log_files(self): if not self.options.logbase or self.options.verbose: return None, None, None, None namebase = None logfile_base = os.path.join(self.options.wd, 'meson-logs', self.options.logbase) if self.options.wrapper: namebase = os.path.basename(self.get_wrapper(self.options)[0]) elif self.options.setup: namebase = self.options.setup.replace(":", "_") if namebase: logfile_base += '-' + namebase.replace(' ', '_') self.logfilename = logfile_base + '.txt' self.jsonlogfilename = logfile_base + '.json' self.jsonlogfile = open(self.jsonlogfilename, 'w') self.logfile = open(self.logfilename, 'w') self.logfile.write('Log of Meson test suite run on %s\n\n' % datetime.datetime.now().isoformat()) def get_wrapper(self, options): wrap = [] if options.gdb: wrap = ['gdb', '--quiet', '--nh'] if options.repeat > 1: wrap += ['-ex', 'run', '-ex', 'quit'] # Signal the end of arguments to gdb wrap += ['--args'] if options.wrapper: wrap += options.wrapper assert(isinstance(wrap, list)) return wrap def get_pretty_suite(self, test): if len(self.suites) > 1: rv = TestHarness.split_suite_string(test.suite[0])[0] s = "+".join(TestHarness.split_suite_string(s)[1] for s in test.suite) if len(s): rv += ":" return rv + s + " / " + test.name else: return test.name def run_tests(self, tests): executor = None futures = [] numlen = len('%d' % len(tests)) self.open_log_files() startdir = os.getcwd() if self.options.wd: os.chdir(self.options.wd) self.build_data = build.load(os.getcwd()) try: for _ in range(self.options.repeat): for i, test in enumerate(tests): visible_name = self.get_pretty_suite(test) if not test.is_parallel or self.options.gdb: self.drain_futures(futures) futures = [] res = self.run_single_test(test) self.print_stats(numlen, tests, visible_name, res, i) else: if not executor: executor = conc.ThreadPoolExecutor(max_workers=self.options.num_processes) f = executor.submit(self.run_single_test, test) futures.append((f, numlen, tests, visible_name, i)) if self.options.repeat > 1 and self.fail_count: break if self.options.repeat > 1 and self.fail_count: break self.drain_futures(futures) self.print_summary() self.print_collected_logs() if self.logfilename: print('Full log written to %s' % self.logfilename) finally: os.chdir(startdir) def drain_futures(self, futures): for i in futures: (result, numlen, tests, name, i) = i if self.options.repeat > 1 and self.fail_count: result.cancel() if self.options.verbose: result.result() self.print_stats(numlen, tests, name, result.result(), i) def run_special(self): 'Tests run by the user, usually something like "under gdb 1000 times".' if self.is_run: raise RuntimeError('Can not use run_special after a full run.') tests = self.get_tests() if not tests: return 0 self.run_tests(tests) return self.fail_count def list_tests(th): tests = th.get_tests() for t in tests: print(th.get_pretty_suite(t)) def rebuild_all(wd): if not os.path.isfile(os.path.join(wd, 'build.ninja')): print("Only ninja backend is supported to rebuild tests before running them.") return True ninja = environment.detect_ninja() if not ninja: print("Can't find ninja, can't rebuild test.") return False p = subprocess.Popen([ninja, '-C', wd]) p.communicate() if p.returncode != 0: print("Could not rebuild") return False return True def run(args): options = parser.parse_args(args) if options.benchmark: options.num_processes = 1 if options.verbose and options.quiet: print('Can not be both quiet and verbose at the same time.') return 1 check_bin = None if options.gdb: options.verbose = True if options.wrapper: print('Must not specify both a wrapper and gdb at the same time.') return 1 check_bin = 'gdb' if options.wrapper: check_bin = options.wrapper[0] if check_bin is not None: exe = ExternalProgram(check_bin, silent=True) if not exe.found(): sys.exit("Could not find requested program: %s" % check_bin) options.wd = os.path.abspath(options.wd) if not options.list and not options.no_rebuild: if not rebuild_all(options.wd): sys.exit(-1) try: th = TestHarness(options) if options.list: list_tests(th) return 0 if not options.args: return th.doit() return th.run_special() except TestException as e: print('Meson test encountered an error:\n') print(e) return 1 meson-0.45.1/mesonbuild/mintro.py0000644000175000017500000002275713254550710020356 0ustar jpakkanejpakkane00000000000000# Copyright 2014-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. """This is a helper script for IDE developers. It allows you to extract information such as list of targets, files, compiler flags, tests and so on. All output is in JSON for simple parsing. Currently only works for the Ninja backend. Others use generated project files and don't need this info.""" import json from . import build, mtest, coredata as cdata from .backend import ninjabackend import argparse import sys, os import pathlib parser = argparse.ArgumentParser(prog='meson introspect') parser.add_argument('--targets', action='store_true', dest='list_targets', default=False, help='List top level targets.') parser.add_argument('--installed', action='store_true', dest='list_installed', default=False, help='List all installed files and directories.') parser.add_argument('--target-files', action='store', dest='target_files', default=None, help='List source files for a given target.') parser.add_argument('--buildsystem-files', action='store_true', dest='buildsystem_files', default=False, help='List files that make up the build system.') parser.add_argument('--buildoptions', action='store_true', dest='buildoptions', default=False, help='List all build options.') parser.add_argument('--tests', action='store_true', dest='tests', default=False, help='List all unit tests.') parser.add_argument('--benchmarks', action='store_true', dest='benchmarks', default=False, help='List all benchmarks.') parser.add_argument('--dependencies', action='store_true', dest='dependencies', default=False, help='List external dependencies.') parser.add_argument('--projectinfo', action='store_true', dest='projectinfo', default=False, help='Information about projects.') parser.add_argument('builddir', nargs='?', help='The build directory') def determine_installed_path(target, installdata): install_target = None for i in installdata.targets: if os.path.basename(i[0]) == target.get_filename(): # FIXME, might clash due to subprojects. install_target = i break if install_target is None: raise RuntimeError('Something weird happened. File a bug.') fname = i[0] outdir = i[1] outname = os.path.join(installdata.prefix, outdir, os.path.basename(fname)) # Normalize the path by using os.path.sep consistently, etc. # Does not change the effective path. return str(pathlib.PurePath(outname)) def list_installed(installdata): res = {} if installdata is not None: for path, installdir, aliases, unknown1, unknown2 in installdata.targets: res[os.path.join(installdata.build_dir, path)] = os.path.join(installdata.prefix, installdir, os.path.basename(path)) for path, installpath, unused_prefix in installdata.data: res[path] = os.path.join(installdata.prefix, installpath) for path, installdir in installdata.headers: res[path] = os.path.join(installdata.prefix, installdir, os.path.basename(path)) for path, installpath in installdata.man: res[path] = os.path.join(installdata.prefix, installpath) print(json.dumps(res)) def list_targets(coredata, builddata, installdata): tlist = [] for (idname, target) in builddata.get_targets().items(): t = {'name': target.get_basename(), 'id': idname} fname = target.get_filename() if isinstance(fname, list): fname = [os.path.join(target.subdir, x) for x in fname] else: fname = os.path.join(target.subdir, fname) t['filename'] = fname if isinstance(target, build.Executable): typename = 'executable' elif isinstance(target, build.SharedLibrary): typename = 'shared library' elif isinstance(target, build.StaticLibrary): typename = 'static library' elif isinstance(target, build.CustomTarget): typename = 'custom' elif isinstance(target, build.RunTarget): typename = 'run' else: typename = 'unknown' t['type'] = typename if installdata and target.should_install(): t['installed'] = True t['install_filename'] = determine_installed_path(target, installdata) else: t['installed'] = False t['build_by_default'] = target.build_by_default tlist.append(t) print(json.dumps(tlist)) def list_target_files(target_name, coredata, builddata): try: t = builddata.targets[target_name] sources = t.sources + t.extra_files except KeyError: print("Unknown target %s." % target_name) sys.exit(1) sources = [os.path.join(i.subdir, i.fname) for i in sources] print(json.dumps(sources)) def list_buildoptions(coredata, builddata): optlist = [] add_keys(optlist, coredata.user_options) add_keys(optlist, coredata.compiler_options) add_keys(optlist, coredata.base_options) add_keys(optlist, coredata.builtins) print(json.dumps(optlist)) def add_keys(optlist, options): keys = list(options.keys()) keys.sort() for key in keys: opt = options[key] optdict = {'name': key, 'value': opt.value} if isinstance(opt, cdata.UserStringOption): typestr = 'string' elif isinstance(opt, cdata.UserBooleanOption): typestr = 'boolean' elif isinstance(opt, cdata.UserComboOption): optdict['choices'] = opt.choices typestr = 'combo' elif isinstance(opt, cdata.UserIntegerOption): typestr = 'integer' elif isinstance(opt, cdata.UserArrayOption): typestr = 'array' else: raise RuntimeError("Unknown option type") optdict['type'] = typestr optdict['description'] = opt.description optlist.append(optdict) def list_buildsystem_files(builddata): src_dir = builddata.environment.get_source_dir() # I feel dirty about this. But only slightly. filelist = [] for root, _, files in os.walk(src_dir): for f in files: if f == 'meson.build' or f == 'meson_options.txt': filelist.append(os.path.relpath(os.path.join(root, f), src_dir)) print(json.dumps(filelist)) def list_deps(coredata): result = [] for d in coredata.deps.values(): if d.found(): result += [{'name': d.name, 'compile_args': d.get_compile_args(), 'link_args': d.get_link_args()}] print(json.dumps(result)) def list_tests(testdata): result = [] for t in testdata: to = {} if isinstance(t.fname, str): fname = [t.fname] else: fname = t.fname to['cmd'] = fname + t.cmd_args if isinstance(t.env, build.EnvironmentVariables): to['env'] = t.env.get_env(os.environ) else: to['env'] = t.env to['name'] = t.name to['workdir'] = t.workdir to['timeout'] = t.timeout to['suite'] = t.suite result.append(to) print(json.dumps(result)) def list_projinfo(builddata): result = {'name': builddata.project_name, 'version': builddata.project_version} subprojects = [] for k, v in builddata.subprojects.items(): c = {'name': k, 'version': v} subprojects.append(c) result['subprojects'] = subprojects print(json.dumps(result)) def run(args): datadir = 'meson-private' options = parser.parse_args(args) if options.builddir is not None: datadir = os.path.join(options.builddir, datadir) if not os.path.isdir(datadir): print('Current directory is not a build dir. Please specify it or ' 'change the working directory to it.') return 1 coredata = cdata.load(options.builddir) builddata = build.load(options.builddir) testdata = mtest.load_tests(options.builddir) benchmarkdata = mtest.load_benchmarks(options.builddir) # Install data is only available with the Ninja backend try: installdata = ninjabackend.load(options.builddir) except FileNotFoundError: installdata = None if options.list_targets: list_targets(coredata, builddata, installdata) elif options.list_installed: list_installed(installdata) elif options.target_files is not None: list_target_files(options.target_files, coredata, builddata) elif options.buildsystem_files: list_buildsystem_files(builddata) elif options.buildoptions: list_buildoptions(coredata, builddata) elif options.tests: list_tests(testdata) elif options.benchmarks: list_tests(benchmarkdata) elif options.dependencies: list_deps(coredata) elif options.projectinfo: list_projinfo(builddata) else: print('No command specified') return 1 return 0 if __name__ == '__main__': sys.exit(run(sys.argv[1:])) meson-0.45.1/mesonbuild/linkers.py0000644000175000017500000000562013213234217020477 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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 .mesonlib import Popen_safe class StaticLinker: pass class VisualStudioLinker(StaticLinker): always_args = ['/NOLOGO'] def __init__(self, exelist): self.exelist = exelist def get_exelist(self): return self.exelist[:] def get_std_link_args(self): return [] def get_buildtype_linker_args(self, buildtype): return [] def get_output_args(self, target): return ['/OUT:' + target] def get_coverage_link_args(self): return [] def get_always_args(self): return VisualStudioLinker.always_args[:] def get_linker_always_args(self): return VisualStudioLinker.always_args[:] def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return [] def thread_link_flags(self, env): return [] def get_option_link_args(self, options): return [] @classmethod def unix_args_to_native(cls, args): from .compilers import VisualStudioCCompiler return VisualStudioCCompiler.unix_args_to_native(args) def get_link_debugfile_args(self, targetfile): # Static libraries do not have PDB files return [] class ArLinker(StaticLinker): def __init__(self, exelist): self.exelist = exelist self.id = 'ar' pc, stdo = Popen_safe(self.exelist + ['-h'])[0:2] # Enable deterministic builds if they are available. if '[D]' in stdo: self.std_args = ['csrD'] else: self.std_args = ['csr'] def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return [] def get_exelist(self): return self.exelist[:] def get_std_link_args(self): return self.std_args def get_output_args(self, target): return [target] def get_buildtype_linker_args(self, buildtype): return [] def get_linker_always_args(self): return [] def get_coverage_link_args(self): return [] def get_always_args(self): return [] def thread_link_flags(self, env): return [] def get_option_link_args(self, options): return [] @classmethod def unix_args_to_native(cls, args): return args[:] def get_link_debugfile_args(self, targetfile): return [] meson-0.45.1/mesonbuild/scripts/0000755000175000017500000000000013254552746020161 5ustar jpakkanejpakkane00000000000000meson-0.45.1/mesonbuild/scripts/dist.py0000644000175000017500000001352713134457406021500 0ustar jpakkanejpakkane00000000000000# Copyright 2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import lzma import os import shutil import subprocess import pickle import hashlib import tarfile, zipfile import tempfile from glob import glob from mesonbuild.environment import detect_ninja from mesonbuild.mesonlib import windows_proof_rmtree def create_hash(fname): hashname = fname + '.sha256sum' m = hashlib.sha256() m.update(open(fname, 'rb').read()) with open(hashname, 'w') as f: f.write('%s %s\n' % (m.hexdigest(), os.path.basename(fname))) def create_zip(zipfilename, packaging_dir): prefix = os.path.dirname(packaging_dir) removelen = len(prefix) + 1 with zipfile.ZipFile(zipfilename, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as zf: zf.write(packaging_dir, packaging_dir[removelen:]) for root, dirs, files in os.walk(packaging_dir): for d in dirs: dname = os.path.join(root, d) zf.write(dname, dname[removelen:]) for f in files: fname = os.path.join(root, f) zf.write(fname, fname[removelen:]) def del_gitfiles(dirname): for f in glob(os.path.join(dirname, '.git*')): if os.path.isdir(f) and not os.path.islink(f): windows_proof_rmtree(f) else: os.unlink(f) def process_submodules(dirname): module_file = os.path.join(dirname, '.gitmodules') if not os.path.exists(module_file): return subprocess.check_call(['git', 'submodule', 'update', '--init'], cwd=dirname) for line in open(module_file): line = line.strip() if '=' not in line: continue k, v = line.split('=', 1) k = k.strip() v = v.strip() if k != 'path': continue del_gitfiles(os.path.join(dirname, v)) def create_dist_git(dist_name, src_root, bld_root, dist_sub): distdir = os.path.join(dist_sub, dist_name) if os.path.exists(distdir): shutil.rmtree(distdir) os.makedirs(distdir) subprocess.check_call(['git', 'clone', '--shared', src_root, distdir]) process_submodules(distdir) del_gitfiles(distdir) xzname = distdir + '.tar.xz' # Should use shutil but it got xz support only in 3.5. with tarfile.open(xzname, 'w:xz') as tf: tf.add(distdir, dist_name) # Create only .tar.xz for now. # zipname = distdir + '.zip' # create_zip(zipname, distdir) shutil.rmtree(distdir) return (xzname, ) def create_dist_hg(dist_name, src_root, bld_root, dist_sub): os.makedirs(dist_sub, exist_ok=True) tarname = os.path.join(dist_sub, dist_name + '.tar') xzname = tarname + '.xz' subprocess.check_call(['hg', 'archive', '-R', src_root, '-S', '-t', 'tar', tarname]) with lzma.open(xzname, 'wb') as xf, open(tarname, 'rb') as tf: shutil.copyfileobj(tf, xf) os.unlink(tarname) # Create only .tar.xz for now. # zipname = os.path.join(dist_sub, dist_name + '.zip') # subprocess.check_call(['hg', 'archive', '-R', src_root, '-S', '-t', 'zip', zipname]) return (xzname, ) def check_dist(packagename, meson_command): print('Testing distribution package %s.' % packagename) unpackdir = tempfile.mkdtemp() builddir = tempfile.mkdtemp() installdir = tempfile.mkdtemp() ninja_bin = detect_ninja() try: tf = tarfile.open(packagename) tf.extractall(unpackdir) srcdir = glob(os.path.join(unpackdir, '*'))[0] if subprocess.call(meson_command + ['--backend=ninja', srcdir, builddir]) != 0: print('Running Meson on distribution package failed') return 1 if subprocess.call([ninja_bin], cwd=builddir) != 0: print('Compiling the distribution package failed.') return 1 if subprocess.call([ninja_bin, 'test'], cwd=builddir) != 0: print('Running unit tests on the distribution package failed.') return 1 myenv = os.environ.copy() myenv['DESTDIR'] = installdir if subprocess.call([ninja_bin, 'install'], cwd=builddir, env=myenv) != 0: print('Installing the distribution package failed.') return 1 finally: shutil.rmtree(unpackdir) shutil.rmtree(builddir) shutil.rmtree(installdir) print('Distribution package %s tested.' % packagename) return 0 def run(args): src_root = args[0] bld_root = args[1] meson_command = args[2:] priv_dir = os.path.join(bld_root, 'meson-private') dist_sub = os.path.join(bld_root, 'meson-dist') buildfile = os.path.join(priv_dir, 'build.dat') build = pickle.load(open(buildfile, 'rb')) dist_name = build.project_name + '-' + build.project_version if os.path.isdir(os.path.join(src_root, '.git')): names = create_dist_git(dist_name, src_root, bld_root, dist_sub) elif os.path.isdir(os.path.join(src_root, '.hg')): names = create_dist_hg(dist_name, src_root, bld_root, dist_sub) else: print('Dist currently only works with Git or Mercurial repos.') return 1 if names is None: return 1 error_count = 0 for name in names: rc = check_dist(name, meson_command) # Check only one. if rc == 0: create_hash(name) error_count += rc return 1 if error_count else 0 meson-0.45.1/mesonbuild/scripts/meson_install.py0000644000175000017500000003665713254550710023410 0ustar jpakkanejpakkane00000000000000# Copyright 2013-2014 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import sys, pickle, os, shutil, subprocess, gzip, platform, errno import shlex from glob import glob from . import depfixer from . import destdir_join from ..mesonlib import is_windows, Popen_safe install_log_file = None selinux_updates = [] class DirMaker: def __init__(self): self.dirs = [] def makedirs(self, path, exist_ok=False): dirname = os.path.normpath(path) dirs = [] while dirname != os.path.dirname(dirname): if not os.path.exists(dirname): dirs.append(dirname) dirname = os.path.dirname(dirname) os.makedirs(path, exist_ok=exist_ok) # store the directories in creation order, with the parent directory # before the child directories. Future calls of makedir() will not # create the parent directories, so the last element in the list is # the last one to be created. That is the first one to be removed on # __exit__ dirs.reverse() self.dirs += dirs def __enter__(self): return self def __exit__(self, type, value, traceback): self.dirs.reverse() for d in self.dirs: append_to_log(d) def set_mode(path, mode): if mode is None: # Keep mode unchanged return if (mode.perms_s or mode.owner or mode.group) is None: # Nothing to set return # No chown() on Windows, and must set one of owner/group if not is_windows() and (mode.owner or mode.group) is not None: try: shutil.chown(path, mode.owner, mode.group) except PermissionError as e: msg = '{!r}: Unable to set owner {!r} and group {!r}: {}, ignoring...' print(msg.format(path, mode.owner, mode.group, e.strerror)) except LookupError: msg = '{!r}: Non-existent owner {!r} or group {!r}: ignoring...' print(msg.format(path, mode.owner, mode.group)) except OSError as e: if e.errno == errno.EINVAL: msg = '{!r}: Non-existent numeric owner {!r} or group {!r}: ignoring...' print(msg.format(path, mode.owner, mode.group)) else: raise # Must set permissions *after* setting owner/group otherwise the # setuid/setgid bits will get wiped by chmod # NOTE: On Windows you can set read/write perms; the rest are ignored if mode.perms_s is not None: try: os.chmod(path, mode.perms) except PermissionError as e: msg = '{!r}: Unable to set permissions {!r}: {}, ignoring...' print(msg.format(path, mode.perms_s, e.strerror)) def restore_selinux_contexts(): ''' Restores the SELinux context for files in @selinux_updates If $DESTDIR is set, do not warn if the call fails. ''' try: subprocess.check_call(['selinuxenabled']) except (FileNotFoundError, PermissionError, subprocess.CalledProcessError) as e: # If we don't have selinux or selinuxenabled returned 1, failure # is ignored quietly. return with subprocess.Popen(['restorecon', '-F', '-f-', '-0'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc: out, err = proc.communicate(input=b'\0'.join(os.fsencode(f) for f in selinux_updates) + b'\0') if proc.returncode != 0 and not os.environ.get('DESTDIR'): print('Failed to restore SELinux context of installed files...', 'Standard output:', out.decode(), 'Standard error:', err.decode(), sep='\n') def append_to_log(line): install_log_file.write(line) if not line.endswith('\n'): install_log_file.write('\n') install_log_file.flush() def do_copyfile(from_file, to_file): if not os.path.isfile(from_file): raise RuntimeError('Tried to install something that isn\'t a file:' '{!r}'.format(from_file)) # copyfile fails if the target file already exists, so remove it to # allow overwriting a previous install. If the target is not a file, we # want to give a readable error. if os.path.exists(to_file): if not os.path.isfile(to_file): raise RuntimeError('Destination {!r} already exists and is not ' 'a file'.format(to_file)) os.unlink(to_file) shutil.copyfile(from_file, to_file) shutil.copystat(from_file, to_file) selinux_updates.append(to_file) append_to_log(to_file) def do_copydir(data, src_dir, dst_dir, exclude): ''' Copies the contents of directory @src_dir into @dst_dir. For directory /foo/ bar/ excluded foobar file do_copydir(..., '/foo', '/dst/dir', {'bar/excluded'}) creates /dst/ dir/ bar/ foobar file Args: src_dir: str, absolute path to the source directory dst_dir: str, absolute path to the destination directory exclude: (set(str), set(str)), tuple of (exclude_files, exclude_dirs), each element of the set is a path relative to src_dir. ''' if not os.path.isabs(src_dir): raise ValueError('src_dir must be absolute, got %s' % src_dir) if not os.path.isabs(dst_dir): raise ValueError('dst_dir must be absolute, got %s' % dst_dir) if exclude is not None: exclude_files, exclude_dirs = exclude else: exclude_files = exclude_dirs = set() for root, dirs, files in os.walk(src_dir): assert os.path.isabs(root) for d in dirs[:]: abs_src = os.path.join(root, d) filepart = os.path.relpath(abs_src, start=src_dir) abs_dst = os.path.join(dst_dir, filepart) # Remove these so they aren't visited by os.walk at all. if filepart in exclude_dirs: dirs.remove(d) continue if os.path.isdir(abs_dst): continue if os.path.exists(abs_dst): print('Tried to copy directory %s but a file of that name already exists.' % abs_dst) sys.exit(1) data.dirmaker.makedirs(abs_dst) shutil.copystat(abs_src, abs_dst) for f in files: abs_src = os.path.join(root, f) filepart = os.path.relpath(abs_src, start=src_dir) if filepart in exclude_files: continue abs_dst = os.path.join(dst_dir, filepart) if os.path.isdir(abs_dst): print('Tried to copy file %s but a directory of that name already exists.' % abs_dst) if os.path.exists(abs_dst): os.unlink(abs_dst) parent_dir = os.path.dirname(abs_dst) if not os.path.isdir(parent_dir): os.mkdir(parent_dir) shutil.copystat(os.path.dirname(abs_src), parent_dir) shutil.copy2(abs_src, abs_dst, follow_symlinks=False) append_to_log(abs_dst) def get_destdir_path(d, path): if os.path.isabs(path): output = destdir_join(d.destdir, path) else: output = os.path.join(d.fullprefix, path) return output def do_install(datafilename): with open(datafilename, 'rb') as ifile: d = pickle.load(ifile) d.destdir = os.environ.get('DESTDIR', '') d.fullprefix = destdir_join(d.destdir, d.prefix) d.dirmaker = DirMaker() with d.dirmaker: install_subdirs(d) # Must be first, because it needs to delete the old subtree. install_targets(d) install_headers(d) install_man(d) install_data(d) restore_selinux_contexts() run_install_script(d) def install_subdirs(d): for (src_dir, dst_dir, mode, exclude) in d.install_subdirs: full_dst_dir = get_destdir_path(d, dst_dir) print('Installing subdir %s to %s' % (src_dir, full_dst_dir)) d.dirmaker.makedirs(full_dst_dir, exist_ok=True) do_copydir(d, src_dir, full_dst_dir, exclude) set_mode(full_dst_dir, mode) def install_data(d): for i in d.data: fullfilename = i[0] outfilename = get_destdir_path(d, i[1]) mode = i[2] outdir = os.path.dirname(outfilename) d.dirmaker.makedirs(outdir, exist_ok=True) print('Installing %s to %s' % (fullfilename, outdir)) do_copyfile(fullfilename, outfilename) set_mode(outfilename, mode) def install_man(d): for m in d.man: full_source_filename = m[0] outfilename = get_destdir_path(d, m[1]) outdir = os.path.dirname(outfilename) d.dirmaker.makedirs(outdir, exist_ok=True) print('Installing %s to %s' % (full_source_filename, outdir)) if outfilename.endswith('.gz') and not full_source_filename.endswith('.gz'): with open(outfilename, 'wb') as of: with open(full_source_filename, 'rb') as sf: # Set mtime and filename for reproducibility. with gzip.GzipFile(fileobj=of, mode='wb', filename='', mtime=0) as gz: gz.write(sf.read()) shutil.copystat(full_source_filename, outfilename) append_to_log(outfilename) else: do_copyfile(full_source_filename, outfilename) def install_headers(d): for t in d.headers: fullfilename = t[0] fname = os.path.basename(fullfilename) outdir = get_destdir_path(d, t[1]) outfilename = os.path.join(outdir, fname) print('Installing %s to %s' % (fname, outdir)) d.dirmaker.makedirs(outdir, exist_ok=True) do_copyfile(fullfilename, outfilename) def run_install_script(d): env = {'MESON_SOURCE_ROOT': d.source_dir, 'MESON_BUILD_ROOT': d.build_dir, 'MESON_INSTALL_PREFIX': d.prefix, 'MESON_INSTALL_DESTDIR_PREFIX': d.fullprefix, 'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in d.mesonintrospect]), } child_env = os.environ.copy() child_env.update(env) for i in d.install_scripts: script = i['exe'] args = i['args'] name = ' '.join(script + args) print('Running custom install script {!r}'.format(name)) try: rc = subprocess.call(script + args, env=child_env) if rc != 0: sys.exit(rc) except: print('Failed to run install script {!r}'.format(name)) sys.exit(1) def is_elf_platform(): platname = platform.system().lower() if platname == 'darwin' or platname == 'windows' or platname == 'cygwin': return False return True def check_for_stampfile(fname): '''Some languages e.g. Rust have output files whose names are not known at configure time. Check if this is the case and return the real file instead.''' if fname.endswith('.so') or fname.endswith('.dll'): if os.stat(fname).st_size == 0: (base, suffix) = os.path.splitext(fname) files = glob(base + '-*' + suffix) if len(files) > 1: print("Stale dynamic library files in build dir. Can't install.") sys.exit(1) if len(files) == 1: return files[0] elif fname.endswith('.a') or fname.endswith('.lib'): if os.stat(fname).st_size == 0: (base, suffix) = os.path.splitext(fname) files = glob(base + '-*' + '.rlib') if len(files) > 1: print("Stale static library files in build dir. Can't install.") sys.exit(1) if len(files) == 1: return files[0] return fname def install_targets(d): for t in d.targets: fname = check_for_stampfile(t[0]) outdir = get_destdir_path(d, t[1]) outname = os.path.join(outdir, os.path.basename(fname)) aliases = t[2] should_strip = t[3] install_rpath = t[4] print('Installing %s to %s' % (fname, outname)) d.dirmaker.makedirs(outdir, exist_ok=True) if not os.path.exists(fname): raise RuntimeError('File {!r} could not be found'.format(fname)) elif os.path.isfile(fname): do_copyfile(fname, outname) if should_strip and d.strip_bin is not None: if fname.endswith('.jar'): print('Not stripping jar target:', os.path.basename(fname)) continue print('Stripping target {!r}'.format(fname)) ps, stdo, stde = Popen_safe(d.strip_bin + [outname]) if ps.returncode != 0: print('Could not strip file.\n') print('Stdout:\n%s\n' % stdo) print('Stderr:\n%s\n' % stde) sys.exit(1) pdb_filename = os.path.splitext(fname)[0] + '.pdb' if not should_strip and os.path.exists(pdb_filename): pdb_outname = os.path.splitext(outname)[0] + '.pdb' print('Installing pdb file %s to %s' % (pdb_filename, pdb_outname)) do_copyfile(pdb_filename, pdb_outname) elif os.path.isdir(fname): fname = os.path.join(d.build_dir, fname.rstrip('/')) do_copydir(d, fname, os.path.join(outdir, os.path.basename(fname)), None) else: raise RuntimeError('Unknown file type for {!r}'.format(fname)) printed_symlink_error = False for alias, to in aliases.items(): try: symlinkfilename = os.path.join(outdir, alias) try: os.unlink(symlinkfilename) except FileNotFoundError: pass os.symlink(to, symlinkfilename) append_to_log(symlinkfilename) except (NotImplementedError, OSError): if not printed_symlink_error: print("Symlink creation does not work on this platform. " "Skipping all symlinking.") printed_symlink_error = True if is_elf_platform() and os.path.isfile(outname): try: e = depfixer.Elf(outname, False) e.fix_rpath(install_rpath) except SystemExit as e: if isinstance(e.code, int) and e.code == 0: pass else: raise def run(args): global install_log_file if len(args) != 1: print('Installer script for Meson. Do not run on your own, mmm\'kay?') print('meson_install.py [install info file]') datafilename = args[0] private_dir = os.path.dirname(datafilename) log_dir = os.path.join(private_dir, '../meson-logs') with open(os.path.join(log_dir, 'install-log.txt'), 'w') as lf: install_log_file = lf append_to_log('# List of files installed by Meson') append_to_log('# Does not contain files installed by custom scripts.') do_install(datafilename) install_log_file = None return 0 if __name__ == '__main__': sys.exit(run(sys.argv[1:])) meson-0.45.1/mesonbuild/scripts/gtkdochelper.py0000644000175000017500000002246113243342167023203 0ustar jpakkanejpakkane00000000000000# Copyright 2015-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import sys, os import subprocess import shlex import shutil import argparse from ..mesonlib import MesonException, Popen_safe from . import destdir_join parser = argparse.ArgumentParser() parser.add_argument('--sourcedir', dest='sourcedir') parser.add_argument('--builddir', dest='builddir') parser.add_argument('--subdir', dest='subdir') parser.add_argument('--headerdirs', dest='headerdirs') parser.add_argument('--mainfile', dest='mainfile') parser.add_argument('--modulename', dest='modulename') parser.add_argument('--htmlargs', dest='htmlargs', default='') parser.add_argument('--scanargs', dest='scanargs', default='') parser.add_argument('--scanobjsargs', dest='scanobjsargs', default='') parser.add_argument('--gobjects-types-file', dest='gobject_typesfile', default='') parser.add_argument('--fixxrefargs', dest='fixxrefargs', default='') parser.add_argument('--mkdbargs', dest='mkdbargs', default='') parser.add_argument('--ld', dest='ld', default='') parser.add_argument('--cc', dest='cc', default='') parser.add_argument('--ldflags', dest='ldflags', default='') parser.add_argument('--cflags', dest='cflags', default='') parser.add_argument('--content-files', dest='content_files', default='') parser.add_argument('--expand-content-files', dest='expand_content_files', default='') parser.add_argument('--html-assets', dest='html_assets', default='') parser.add_argument('--ignore-headers', dest='ignore_headers', default='') parser.add_argument('--namespace', dest='namespace', default='') parser.add_argument('--mode', dest='mode', default='') parser.add_argument('--installdir', dest='install_dir') def gtkdoc_run_check(cmd, cwd, library_path=None): env = dict(os.environ) if library_path: env['LD_LIBRARY_PATH'] = library_path # Put stderr into stdout since we want to print it out anyway. # This preserves the order of messages. p, out = Popen_safe(cmd, cwd=cwd, env=env, stderr=subprocess.STDOUT)[0:2] if p.returncode != 0: err_msg = ["{!r} failed with status {:d}".format(cmd[0], p.returncode)] if out: err_msg.append(out) raise MesonException('\n'.join(err_msg)) def build_gtkdoc(source_root, build_root, doc_subdir, src_subdirs, main_file, module, html_args, scan_args, fixxref_args, mkdb_args, gobject_typesfile, scanobjs_args, ld, cc, ldflags, cflags, html_assets, content_files, ignore_headers, namespace, expand_content_files, mode): print("Building documentation for %s" % module) src_dir_args = [] for src_dir in src_subdirs: if not os.path.isabs(src_dir): dirs = [os.path.join(source_root, src_dir), os.path.join(build_root, src_dir)] else: dirs = [src_dir] src_dir_args += ['--source-dir=' + d for d in dirs] doc_src = os.path.join(source_root, doc_subdir) abs_out = os.path.join(build_root, doc_subdir) htmldir = os.path.join(abs_out, 'html') content_files += [main_file] sections = os.path.join(doc_src, module + "-sections.txt") if os.path.exists(sections): content_files.append(sections) overrides = os.path.join(doc_src, module + "-overrides.txt") if os.path.exists(overrides): content_files.append(overrides) # Copy files to build directory for f in content_files: f_abs = os.path.join(doc_src, f) shutil.copyfile(f_abs, os.path.join( abs_out, os.path.basename(f_abs))) shutil.rmtree(htmldir, ignore_errors=True) try: os.mkdir(htmldir) except Exception: pass for f in html_assets: f_abs = os.path.join(doc_src, f) shutil.copyfile(f_abs, os.path.join(htmldir, os.path.basename(f_abs))) scan_cmd = ['gtkdoc-scan', '--module=' + module] + src_dir_args if ignore_headers: scan_cmd.append('--ignore-headers=' + ' '.join(ignore_headers)) # Add user-specified arguments scan_cmd += scan_args gtkdoc_run_check(scan_cmd, abs_out) if gobject_typesfile: scanobjs_cmd = ['gtkdoc-scangobj'] + scanobjs_args + ['--types=' + gobject_typesfile, '--module=' + module, '--cflags=' + cflags, '--ldflags=' + ldflags, '--ld=' + ld] library_paths = [] for ldflag in shlex.split(ldflags): if ldflag.startswith('-Wl,-rpath,'): library_paths.append(ldflag[11:]) if 'LD_LIBRARY_PATH' in os.environ: library_paths.append(os.environ['LD_LIBRARY_PATH']) library_path = ':'.join(library_paths) gtkdoc_run_check(scanobjs_cmd, abs_out, library_path) # Make docbook files if mode == 'auto': # Guessing is probably a poor idea but these keeps compat # with previous behavior if main_file.endswith('sgml'): modeflag = '--sgml-mode' else: modeflag = '--xml-mode' elif mode == 'xml': modeflag = '--xml-mode' elif mode == 'sgml': modeflag = '--sgml-mode' else: # none modeflag = None mkdb_cmd = ['gtkdoc-mkdb', '--module=' + module, '--output-format=xml', '--expand-content-files=' + ' '.join(expand_content_files), ] + src_dir_args if namespace: mkdb_cmd.append('--name-space=' + namespace) if modeflag: mkdb_cmd.append(modeflag) if len(main_file) > 0: # Yes, this is the flag even if the file is in xml. mkdb_cmd.append('--main-sgml-file=' + main_file) # Add user-specified arguments mkdb_cmd += mkdb_args gtkdoc_run_check(mkdb_cmd, abs_out) # Make HTML documentation mkhtml_cmd = ['gtkdoc-mkhtml', '--path=' + ':'.join((doc_src, abs_out)), module, ] + html_args if len(main_file) > 0: mkhtml_cmd.append('../' + main_file) else: mkhtml_cmd.append('%s-docs.xml' % module) # html gen must be run in the HTML dir gtkdoc_run_check(mkhtml_cmd, os.path.join(abs_out, 'html')) # Fix cross-references in HTML files fixref_cmd = ['gtkdoc-fixxref', '--module=' + module, '--module-dir=html'] + fixxref_args gtkdoc_run_check(fixref_cmd, abs_out) def install_gtkdoc(build_root, doc_subdir, install_prefix, datadir, module): source = os.path.join(build_root, doc_subdir, 'html') final_destination = os.path.join(install_prefix, datadir, module) shutil.rmtree(final_destination, ignore_errors=True) shutil.copytree(source, final_destination) def run(args): options = parser.parse_args(args) if len(options.htmlargs) > 0: htmlargs = options.htmlargs.split('@@') else: htmlargs = [] if len(options.scanargs) > 0: scanargs = options.scanargs.split('@@') else: scanargs = [] if len(options.scanobjsargs) > 0: scanobjsargs = options.scanobjsargs.split('@@') else: scanobjsargs = [] if len(options.fixxrefargs) > 0: fixxrefargs = options.fixxrefargs.split('@@') else: fixxrefargs = [] if len(options.mkdbargs) > 0: mkdbargs = options.mkdbargs.split('@@') else: mkdbargs = [] build_gtkdoc( options.sourcedir, options.builddir, options.subdir, options.headerdirs.split('@@'), options.mainfile, options.modulename, htmlargs, scanargs, fixxrefargs, mkdbargs, options.gobject_typesfile, scanobjsargs, options.ld, options.cc, options.ldflags, options.cflags, options.html_assets.split('@@') if options.html_assets else [], options.content_files.split('@@') if options.content_files else [], options.ignore_headers.split('@@') if options.ignore_headers else [], options.namespace, options.expand_content_files.split('@@') if options.expand_content_files else [], options.mode) if 'MESON_INSTALL_PREFIX' in os.environ: destdir = os.environ.get('DESTDIR', '') install_prefix = destdir_join(destdir, os.environ['MESON_INSTALL_PREFIX']) install_dir = options.install_dir if options.install_dir else options.modulename if os.path.isabs(install_dir): install_dir = destdir_join(destdir, install_dir) install_gtkdoc(options.builddir, options.subdir, install_prefix, 'share/gtk-doc/html', install_dir) return 0 if __name__ == '__main__': sys.exit(run(sys.argv[1:])) meson-0.45.1/mesonbuild/scripts/symbolextractor.py0000644000175000017500000001010613032764405023761 0ustar jpakkanejpakkane00000000000000# Copyright 2013-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. # This script extracts the symbols of a given shared library # into a file. If the symbols have not changed, the file is not # touched. This information is used to skip link steps if the # ABI has not changed. # This file is basically a reimplementation of # http://cgit.freedesktop.org/libreoffice/core/commit/?id=3213cd54b76bc80a6f0516aac75a48ff3b2ad67c import os, sys from .. import mesonlib from ..mesonlib import Popen_safe import argparse parser = argparse.ArgumentParser() parser.add_argument('--cross-host', default=None, dest='cross_host', help='cross compilation host platform') parser.add_argument('args', nargs='+') def dummy_syms(outfilename): """Just touch it so relinking happens always.""" with open(outfilename, 'w'): pass def write_if_changed(text, outfilename): try: with open(outfilename, 'r') as f: oldtext = f.read() if text == oldtext: return except FileNotFoundError: pass with open(outfilename, 'w') as f: f.write(text) def linux_syms(libfilename, outfilename): evar = 'READELF' if evar in os.environ: readelfbin = os.environ[evar].strip() else: readelfbin = 'readelf' evar = 'NM' if evar in os.environ: nmbin = os.environ[evar].strip() else: nmbin = 'nm' pe, output = Popen_safe([readelfbin, '-d', libfilename])[0:2] if pe.returncode != 0: raise RuntimeError('Readelf does not work') result = [x for x in output.split('\n') if 'SONAME' in x] assert(len(result) <= 1) pnm, output = Popen_safe([nmbin, '--dynamic', '--extern-only', '--defined-only', '--format=posix', libfilename])[0:2] if pnm.returncode != 0: raise RuntimeError('nm does not work.') result += [' '.join(x.split()[0:2]) for x in output.split('\n') if len(x) > 0] write_if_changed('\n'.join(result) + '\n', outfilename) def osx_syms(libfilename, outfilename): pe, output = Popen_safe(['otool', '-l', libfilename])[0:2] if pe.returncode != 0: raise RuntimeError('Otool does not work.') arr = output.split('\n') for (i, val) in enumerate(arr): if 'LC_ID_DYLIB' in val: match = i break result = [arr[match + 2], arr[match + 5]] # Libreoffice stores all 5 lines but the others seem irrelevant. pnm, output = Popen_safe(['nm', '-g', '-P', libfilename])[0:2] if pnm.returncode != 0: raise RuntimeError('nm does not work.') result += [' '.join(x.split()[0:2]) for x in output.split('\n') if len(x) > 0 and not x.endswith('U')] write_if_changed('\n'.join(result) + '\n', outfilename) def gen_symbols(libfilename, outfilename, cross_host): if cross_host is not None: # In case of cross builds just always relink. # In theory we could determine the correct # toolset but there are more important things # to do. dummy_syms(outfilename) elif mesonlib.is_linux(): linux_syms(libfilename, outfilename) elif mesonlib.is_osx(): osx_syms(libfilename, outfilename) else: dummy_syms(outfilename) def run(args): options = parser.parse_args(args) if len(options.args) != 2: print('symbolextractor.py ') sys.exit(1) libfile = options.args[0] outfile = options.args[1] gen_symbols(libfile, outfile, options.cross_host) return 0 if __name__ == '__main__': sys.exit(run(sys.argv[1:])) meson-0.45.1/mesonbuild/scripts/coverage.py0000644000175000017500000000740713254550710022323 0ustar jpakkanejpakkane00000000000000# Copyright 2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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 mesonbuild import environment import sys, os, subprocess, pathlib def coverage(source_root, build_root, log_dir): (gcovr_exe, lcov_exe, genhtml_exe) = environment.find_coverage_tools() if gcovr_exe: subprocess.check_call([gcovr_exe, '-x', '-r', source_root, '-o', os.path.join(log_dir, 'coverage.xml'), ]) subprocess.check_call([gcovr_exe, '-r', source_root, '-o', os.path.join(log_dir, 'coverage.txt'), ]) if lcov_exe and genhtml_exe: htmloutdir = os.path.join(log_dir, 'coveragereport') covinfo = os.path.join(log_dir, 'coverage.info') initial_tracefile = covinfo + '.initial' run_tracefile = covinfo + '.run' raw_tracefile = covinfo + '.raw' subprocess.check_call([lcov_exe, '--directory', build_root, '--capture', '--initial', '--output-file', initial_tracefile]) subprocess.check_call([lcov_exe, '--directory', build_root, '--capture', '--output-file', run_tracefile, '--no-checksum', '--rc', 'lcov_branch_coverage=1', ]) # Join initial and test results. subprocess.check_call([lcov_exe, '-a', initial_tracefile, '-a', run_tracefile, '-o', raw_tracefile]) # Remove all directories outside the source_root from the covinfo subprocess.check_call([lcov_exe, '--extract', raw_tracefile, os.path.join(source_root, '*'), '--output-file', covinfo]) subprocess.check_call([genhtml_exe, '--prefix', build_root, '--output-directory', htmloutdir, '--title', 'Code coverage', '--legend', '--show-details', '--branch-coverage', covinfo]) if gcovr_exe: print('') print('XML coverage report can be found at', pathlib.Path(log_dir, 'coverage.xml').as_uri()) print('Text coverage report can be found at', pathlib.Path(log_dir, 'coverage.txt').as_uri()) if lcov_exe and genhtml_exe: print('Html coverage report can be found at', pathlib.Path(htmloutdir, 'index.html').as_uri()) return 0 def run(args): if not os.path.isfile('build.ninja'): print('Coverage currently only works with the Ninja backend.') return 1 source_root, build_root, log_dir = args[:] return coverage(source_root, build_root, log_dir) if __name__ == '__main__': sys.exit(run(sys.argv[1:])) meson-0.45.1/mesonbuild/scripts/commandrunner.py0000644000175000017500000000530713213234217023371 0ustar jpakkanejpakkane00000000000000# Copyright 2014 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. """This program is a wrapper to run external commands. It determines what to run, sets up the environment and executes the command.""" import sys, os, subprocess, shutil, shlex def run_command(source_dir, build_dir, subdir, meson_command, command, arguments): env = {'MESON_SOURCE_ROOT': source_dir, 'MESON_BUILD_ROOT': build_dir, 'MESON_SUBDIR': subdir, 'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in meson_command + ['introspect']]), } cwd = os.path.join(source_dir, subdir) child_env = os.environ.copy() child_env.update(env) # Is the command an executable in path? exe = shutil.which(command) if exe is not None: command_array = [exe] + arguments else:# No? Maybe it is a script in the source tree. fullpath = os.path.join(source_dir, subdir, command) command_array = [fullpath] + arguments try: return subprocess.Popen(command_array, env=child_env, cwd=cwd) except FileNotFoundError: print('Could not execute command "%s". File not found.' % command) sys.exit(1) except PermissionError: print('Could not execute command "%s". File not executable.' % command) sys.exit(1) except OSError as err: print('Could not execute command "{}": {}'.format(command, err)) sys.exit(1) except subprocess.SubprocessError as err: print('Could not execute command "{}": {}'.format(command, err)) sys.exit(1) def run(args): if len(args) < 4: print('commandrunner.py [arguments]') return 1 src_dir = args[0] build_dir = args[1] subdir = args[2] meson_command = args[3] if 'python' in meson_command: # Hack. meson_command = [meson_command, args[4]] command = args[5] arguments = args[6:] else: meson_command = [meson_command] command = args[4] arguments = args[5:] pc = run_command(src_dir, build_dir, subdir, meson_command, command, arguments) pc.wait() return pc.returncode if __name__ == '__main__': sys.exit(run(sys.argv[1:])) meson-0.45.1/mesonbuild/scripts/uninstall.py0000644000175000017500000000305013140423077022526 0ustar jpakkanejpakkane00000000000000# Copyright 2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os logfile = 'meson-logs/install-log.txt' def do_uninstall(log): failures = 0 successes = 0 for line in open(log): if line.startswith('#'): continue fname = line.strip() try: if os.path.isdir(fname) and not os.path.islink(fname): os.rmdir(fname) else: os.unlink(fname) print('Deleted:', fname) successes += 1 except Exception as e: print('Could not delete %s: %s.' % (fname, e)) failures += 1 print('\nUninstall finished.\n') print('Deleted:', successes) print('Failed:', failures) print('\nRemember that files created by custom scripts have not been removed.') def run(args): if args: print('Weird error.') return 1 if not os.path.exists(logfile): print('Log file does not exist, no installation has been done.') return 0 do_uninstall(logfile) return 0 meson-0.45.1/mesonbuild/scripts/msgfmthelper.py0000644000175000017500000000227413102410222023203 0ustar jpakkanejpakkane00000000000000# Copyright 2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import argparse import subprocess import os parser = argparse.ArgumentParser() parser.add_argument('input') parser.add_argument('output') parser.add_argument('type') parser.add_argument('podir') parser.add_argument('--datadirs', default='') def run(args): options = parser.parse_args(args) env = None if options.datadirs: env = os.environ.copy() env.update({'GETTEXTDATADIRS': options.datadirs}) return subprocess.call(['msgfmt', '--' + options.type, '-d', options.podir, '--template', options.input, '-o', options.output], env=env) meson-0.45.1/mesonbuild/scripts/gettext.py0000644000175000017500000001120713243342167022210 0ustar jpakkanejpakkane00000000000000# Copyright 2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os import shutil import argparse import subprocess from . import destdir_join parser = argparse.ArgumentParser() parser.add_argument('command') parser.add_argument('--pkgname', default='') parser.add_argument('--datadirs', default='') parser.add_argument('--langs', default='') parser.add_argument('--localedir', default='') parser.add_argument('--subdir', default='') parser.add_argument('--extra-args', default='') def read_linguas(src_sub): # Syntax of this file is documented here: # https://www.gnu.org/software/gettext/manual/html_node/po_002fLINGUAS.html linguas = os.path.join(src_sub, 'LINGUAS') try: langs = [] with open(linguas) as f: for line in f: line = line.strip() if line and not line.startswith('#'): langs += line.split() return langs except (FileNotFoundError, PermissionError): print('Could not find file LINGUAS in {}'.format(src_sub)) return [] def run_potgen(src_sub, pkgname, datadirs, args): listfile = os.path.join(src_sub, 'POTFILES') if not os.path.exists(listfile): listfile = os.path.join(src_sub, 'POTFILES.in') if not os.path.exists(listfile): print('Could not find file POTFILES in %s' % src_sub) return 1 child_env = os.environ.copy() if datadirs: child_env['GETTEXTDATADIRS'] = datadirs ofile = os.path.join(src_sub, pkgname + '.pot') return subprocess.call(['xgettext', '--package-name=' + pkgname, '-p', src_sub, '-f', listfile, '-D', os.environ['MESON_SOURCE_ROOT'], '-k_', '-o', ofile] + args, env=child_env) def gen_gmo(src_sub, bld_sub, langs): for l in langs: subprocess.check_call(['msgfmt', os.path.join(src_sub, l + '.po'), '-o', os.path.join(bld_sub, l + '.gmo')]) return 0 def update_po(src_sub, pkgname, langs): potfile = os.path.join(src_sub, pkgname + '.pot') for l in langs: pofile = os.path.join(src_sub, l + '.po') if os.path.exists(pofile): subprocess.check_call(['msgmerge', '-q', '-o', pofile, pofile, potfile]) else: subprocess.check_call(['msginit', '--input', potfile, '--output-file', pofile, '--locale', l, '--no-translator']) return 0 def do_install(src_sub, bld_sub, dest, pkgname, langs): for l in langs: srcfile = os.path.join(bld_sub, l + '.gmo') outfile = os.path.join(dest, l, 'LC_MESSAGES', pkgname + '.mo') os.makedirs(os.path.dirname(outfile), exist_ok=True) shutil.copyfile(srcfile, outfile) shutil.copystat(srcfile, outfile) print('Installing %s to %s' % (srcfile, outfile)) return 0 def run(args): options = parser.parse_args(args) subcmd = options.command langs = options.langs.split('@@') if options.langs else None extra_args = options.extra_args.split('@@') if options.extra_args else [] subdir = os.environ.get('MESON_SUBDIR', '') if options.subdir: subdir = options.subdir src_sub = os.path.join(os.environ['MESON_SOURCE_ROOT'], subdir) bld_sub = os.path.join(os.environ['MESON_BUILD_ROOT'], subdir) if not langs: langs = read_linguas(src_sub) if subcmd == 'pot': return run_potgen(src_sub, options.pkgname, options.datadirs, extra_args) elif subcmd == 'gen_gmo': return gen_gmo(src_sub, bld_sub, langs) elif subcmd == 'update_po': if run_potgen(src_sub, options.pkgname, options.datadirs, extra_args) != 0: return 1 return update_po(src_sub, options.pkgname, langs) elif subcmd == 'install': destdir = os.environ.get('DESTDIR', '') dest = destdir_join(destdir, os.path.join(os.environ['MESON_INSTALL_PREFIX'], options.localedir)) if gen_gmo(src_sub, bld_sub, langs) != 0: return 1 do_install(src_sub, bld_sub, dest, options.pkgname, langs) else: print('Unknown subcommand.') return 1 meson-0.45.1/mesonbuild/scripts/dirchanger.py0000644000175000017500000000160713025554726022641 0ustar jpakkanejpakkane00000000000000# Copyright 2015-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. '''CD into dir given as first argument and execute the command given in the rest of the arguments.''' import os, subprocess, sys def run(args): dirname = args[0] command = args[1:] os.chdir(dirname) return subprocess.call(command) if __name__ == '__main__': sys.exit(run(sys.argv[1:])) meson-0.45.1/mesonbuild/scripts/cleantrees.py0000644000175000017500000000261013026303756022647 0ustar jpakkanejpakkane00000000000000# Copyright 2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os import sys import shutil import pickle def rmtrees(build_dir, trees): for t in trees: # Never delete trees outside of the builddir if os.path.isabs(t): print('Cannot delete dir with absolute path {!r}'.format(t)) continue bt = os.path.join(build_dir, t) # Skip if it doesn't exist, or if it is not a directory if os.path.isdir(bt): shutil.rmtree(bt, ignore_errors=True) def run(args): if len(args) != 1: print('Cleaner script for Meson. Do not run on your own please.') print('cleantrees.py ') return 1 with open(args[0], 'rb') as f: data = pickle.load(f) rmtrees(data.build_dir, data.trees) # Never fail cleaning return 0 if __name__ == '__main__': run(sys.argv[1:]) meson-0.45.1/mesonbuild/scripts/scanbuild.py0000644000175000017500000000442613243342167022475 0ustar jpakkanejpakkane00000000000000# Copyright 2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os import subprocess import shutil import tempfile from ..environment import detect_ninja from ..mesonlib import Popen_safe def scanbuild(exename, srcdir, blddir, privdir, logdir, args): with tempfile.TemporaryDirectory(dir=privdir) as scandir: meson_cmd = [exename] + args build_cmd = [exename, '-o', logdir, detect_ninja(), '-C', scandir] rc = subprocess.call(meson_cmd + [srcdir, scandir]) if rc != 0: return rc return subprocess.call(build_cmd) def run(args): srcdir = args[0] blddir = args[1] meson_cmd = args[2:] privdir = os.path.join(blddir, 'meson-private') logdir = os.path.join(blddir, 'meson-logs/scanbuild') shutil.rmtree(logdir, ignore_errors=True) tools = [ 'scan-build', # base 'scan-build-5.0', 'scan-build50', # latest stable release 'scan-build-4.0', 'scan-build40', # old stable releases 'scan-build-3.9', 'scan-build39', 'scan-build-3.8', 'scan-build38', 'scan-build-3.7', 'scan-build37', 'scan-build-3.6', 'scan-build36', 'scan-build-3.5', 'scan-build35', 'scan-build-6.0', 'scan-build-devel', # development snapshot ] toolname = 'scan-build' for tool in tools: try: p, out = Popen_safe([tool, '--help'])[:2] except (FileNotFoundError, PermissionError): continue if p.returncode != 0: continue else: toolname = tool break exename = os.environ.get('SCANBUILD', toolname) if not shutil.which(exename): print('Scan-build not installed.') return 1 return scanbuild(exename, srcdir, blddir, privdir, logdir, meson_cmd) meson-0.45.1/mesonbuild/scripts/vcstagger.py0000644000175000017500000000302513134457406022512 0ustar jpakkanejpakkane00000000000000# Copyright 2015-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import sys, os, subprocess, re def config_vcs_tag(infile, outfile, fallback, source_dir, replace_string, regex_selector, cmd): try: output = subprocess.check_output(cmd, cwd=source_dir) new_string = re.search(regex_selector, output.decode()).group(1).strip() except Exception: new_string = fallback with open(infile) as f: new_data = f.read().replace(replace_string, new_string) if os.path.exists(outfile): with open(outfile) as f: needs_update = (f.read() != new_data) else: needs_update = True if needs_update: with open(outfile, 'w') as f: f.write(new_data) def run(args): infile, outfile, fallback, source_dir, replace_string, regex_selector = args[0:6] command = args[6:] config_vcs_tag(infile, outfile, fallback, source_dir, replace_string, regex_selector, command) return 0 if __name__ == '__main__': sys.exit(run(sys.argv[1:])) meson-0.45.1/mesonbuild/scripts/delwithsuffix.py0000644000175000017500000000210613110002662023371 0ustar jpakkanejpakkane00000000000000# Copyright 2013 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os, sys def run(args): if len(args) != 2: print('delwithsuffix.py ') sys.exit(1) topdir = args[0] suffix = args[1] if suffix[0] != '.': suffix = '.' + suffix for (root, _, files) in os.walk(topdir): for f in files: if f.endswith(suffix): fullname = os.path.join(root, f) os.unlink(fullname) return 0 if __name__ == '__main__': run(sys.argv[1:]) meson-0.45.1/mesonbuild/scripts/regen_checker.py0000644000175000017500000000444413206650111023303 0ustar jpakkanejpakkane00000000000000# Copyright 2015-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import sys, os import pickle, subprocess from mesonbuild.mesonlib import meson_command # This could also be used for XCode. def need_regen(regeninfo, regen_timestamp): for i in regeninfo.depfiles: curfile = os.path.join(regeninfo.build_dir, i) curtime = os.stat(curfile).st_mtime if curtime > regen_timestamp: return True # The timestamp file gets automatically deleted by MSBuild during a 'Clean' build. # We must make sure to recreate it, even if we do not regenerate the solution. # Otherwise, Visual Studio will always consider the REGEN project out of date. print("Everything is up-to-date, regeneration of build files is not needed.") from ..backend.vs2010backend import Vs2010Backend Vs2010Backend.touch_regen_timestamp(regeninfo.build_dir) return False def regen(regeninfo, mesonscript, backend): cmd = meson_command + ['--internal', 'regenerate', regeninfo.build_dir, regeninfo.source_dir, '--backend=' + backend] subprocess.check_call(cmd) def run(args): private_dir = args[0] dumpfile = os.path.join(private_dir, 'regeninfo.dump') coredata = os.path.join(private_dir, 'coredata.dat') with open(dumpfile, 'rb') as f: regeninfo = pickle.load(f) with open(coredata, 'rb') as f: coredata = pickle.load(f) mesonscript = coredata.meson_script_launcher backend = coredata.get_builtin_option('backend') regen_timestamp = os.stat(dumpfile).st_mtime if need_regen(regeninfo, regen_timestamp): regen(regeninfo, mesonscript, backend) sys.exit(0) if __name__ == '__main__': run(sys.argv[1:]) meson-0.45.1/mesonbuild/scripts/meson_exe.py0000644000175000017500000000515413226722226022511 0ustar jpakkanejpakkane00000000000000# Copyright 2013-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os import sys import argparse import pickle import platform import subprocess options = None parser = argparse.ArgumentParser() parser.add_argument('args', nargs='+') def is_windows(): platname = platform.system().lower() return platname == 'windows' or 'mingw' in platname def is_cygwin(): platname = platform.system().lower() return 'cygwin' in platname def run_with_mono(fname): if fname.endswith('.exe') and not (is_windows() or is_cygwin()): return True return False def run_exe(exe): if exe.fname[0].endswith('.jar'): cmd = ['java', '-jar'] + exe.fname elif not exe.is_cross and run_with_mono(exe.fname[0]): cmd = ['mono'] + exe.fname else: if exe.is_cross: if exe.exe_runner is None: raise AssertionError('BUG: Trying to run cross-compiled exes with no wrapper') else: cmd = [exe.exe_runner] + exe.fname else: cmd = exe.fname child_env = os.environ.copy() child_env.update(exe.env) if len(exe.extra_paths) > 0: child_env['PATH'] = (os.pathsep.join(exe.extra_paths + ['']) + child_env['PATH']) p = subprocess.Popen(cmd + exe.cmd_args, env=child_env, cwd=exe.workdir, close_fds=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() if exe.capture and p.returncode == 0: with open(exe.capture, 'wb') as output: output.write(stdout) if stderr: sys.stderr.buffer.write(stderr) return p.returncode def run(args): global options options = parser.parse_args(args) if len(options.args) != 1: print('Test runner for Meson. Do not run on your own, mmm\'kay?') print(sys.argv[0] + ' [data file]') exe_data_file = options.args[0] with open(exe_data_file, 'rb') as f: exe = pickle.load(f) return run_exe(exe) if __name__ == '__main__': sys.exit(run(sys.argv[1:])) meson-0.45.1/mesonbuild/scripts/depfixer.py0000644000175000017500000003106213134457406022335 0ustar jpakkanejpakkane00000000000000# Copyright 2013-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import sys, struct SHT_STRTAB = 3 DT_NEEDED = 1 DT_RPATH = 15 DT_RUNPATH = 29 DT_STRTAB = 5 DT_SONAME = 14 DT_MIPS_RLD_MAP_REL = 1879048245 class DataSizes: def __init__(self, ptrsize, is_le): if is_le: p = '<' else: p = '>' self.Half = p + 'h' self.HalfSize = 2 self.Word = p + 'I' self.WordSize = 4 self.Sword = p + 'i' self.SwordSize = 4 if ptrsize == 64: self.Addr = p + 'Q' self.AddrSize = 8 self.Off = p + 'Q' self.OffSize = 8 self.XWord = p + 'Q' self.XWordSize = 8 self.Sxword = p + 'q' self.SxwordSize = 8 else: self.Addr = p + 'I' self.AddrSize = 4 self.Off = p + 'I' self.OffSize = 4 class DynamicEntry(DataSizes): def __init__(self, ifile, ptrsize, is_le): super().__init__(ptrsize, is_le) self.ptrsize = ptrsize if ptrsize == 64: self.d_tag = struct.unpack(self.Sxword, ifile.read(self.SxwordSize))[0] self.val = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] else: self.d_tag = struct.unpack(self.Sword, ifile.read(self.SwordSize))[0] self.val = struct.unpack(self.Word, ifile.read(self.WordSize))[0] def write(self, ofile): if self.ptrsize == 64: ofile.write(struct.pack(self.Sxword, self.d_tag)) ofile.write(struct.pack(self.XWord, self.val)) else: ofile.write(struct.pack(self.Sword, self.d_tag)) ofile.write(struct.pack(self.Word, self.val)) class SectionHeader(DataSizes): def __init__(self, ifile, ptrsize, is_le): super().__init__(ptrsize, is_le) if ptrsize == 64: is_64 = True else: is_64 = False # Elf64_Word self.sh_name = struct.unpack(self.Word, ifile.read(self.WordSize))[0] # Elf64_Word self.sh_type = struct.unpack(self.Word, ifile.read(self.WordSize))[0] # Elf64_Xword if is_64: self.sh_flags = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] else: self.sh_flags = struct.unpack(self.Word, ifile.read(self.WordSize))[0] # Elf64_Addr self.sh_addr = struct.unpack(self.Addr, ifile.read(self.AddrSize))[0] # Elf64_Off self.sh_offset = struct.unpack(self.Off, ifile.read(self.OffSize))[0] # Elf64_Xword if is_64: self.sh_size = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] else: self.sh_size = struct.unpack(self.Word, ifile.read(self.WordSize))[0] # Elf64_Word self.sh_link = struct.unpack(self.Word, ifile.read(self.WordSize))[0] # Elf64_Word self.sh_info = struct.unpack(self.Word, ifile.read(self.WordSize))[0] # Elf64_Xword if is_64: self.sh_addralign = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] else: self.sh_addralign = struct.unpack(self.Word, ifile.read(self.WordSize))[0] # Elf64_Xword if is_64: self.sh_entsize = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] else: self.sh_entsize = struct.unpack(self.Word, ifile.read(self.WordSize))[0] class Elf(DataSizes): def __init__(self, bfile, verbose=True): self.bfile = bfile self.verbose = verbose self.bf = open(bfile, 'r+b') try: (self.ptrsize, self.is_le) = self.detect_elf_type() super().__init__(self.ptrsize, self.is_le) self.parse_header() self.parse_sections() self.parse_dynamic() except: self.bf.close() raise def __enter__(self): return self def __del__(self): if self.bf: self.bf.close() def __exit__(self, exc_type, exc_value, traceback): self.bf.close() self.bf = None def detect_elf_type(self): data = self.bf.read(6) if data[1:4] != b'ELF': # This script gets called to non-elf targets too # so just ignore them. if self.verbose: print('File "%s" is not an ELF file.' % self.bfile) sys.exit(0) if data[4] == 1: ptrsize = 32 elif data[4] == 2: ptrsize = 64 else: sys.exit('File "%s" has unknown ELF class.' % self.bfile) if data[5] == 1: is_le = True elif data[5] == 2: is_le = False else: sys.exit('File "%s" has unknown ELF endianness.' % self.bfile) return ptrsize, is_le def parse_header(self): self.bf.seek(0) self.e_ident = struct.unpack('16s', self.bf.read(16))[0] self.e_type = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] self.e_machine = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] self.e_version = struct.unpack(self.Word, self.bf.read(self.WordSize))[0] self.e_entry = struct.unpack(self.Addr, self.bf.read(self.AddrSize))[0] self.e_phoff = struct.unpack(self.Off, self.bf.read(self.OffSize))[0] self.e_shoff = struct.unpack(self.Off, self.bf.read(self.OffSize))[0] self.e_flags = struct.unpack(self.Word, self.bf.read(self.WordSize))[0] self.e_ehsize = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] self.e_phentsize = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] self.e_phnum = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] self.e_shentsize = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] self.e_shnum = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] self.e_shstrndx = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] def parse_sections(self): self.bf.seek(self.e_shoff) self.sections = [] for i in range(self.e_shnum): self.sections.append(SectionHeader(self.bf, self.ptrsize, self.is_le)) def read_str(self): arr = [] x = self.bf.read(1) while x != b'\0': arr.append(x) x = self.bf.read(1) if x == b'': raise RuntimeError('Tried to read past the end of the file') return b''.join(arr) def find_section(self, target_name): section_names = self.sections[self.e_shstrndx] for i in self.sections: self.bf.seek(section_names.sh_offset + i.sh_name) name = self.read_str() if name == target_name: return i def parse_dynamic(self): sec = self.find_section(b'.dynamic') self.dynamic = [] if sec is None: return self.bf.seek(sec.sh_offset) while True: e = DynamicEntry(self.bf, self.ptrsize, self.is_le) self.dynamic.append(e) if e.d_tag == 0: break def print_section_names(self): section_names = self.sections[self.e_shstrndx] for i in self.sections: self.bf.seek(section_names.sh_offset + i.sh_name) name = self.read_str() print(name.decode()) def print_soname(self): soname = None strtab = None for i in self.dynamic: if i.d_tag == DT_SONAME: soname = i if i.d_tag == DT_STRTAB: strtab = i if soname is None or strtab is None: print("This file does not have a soname") return self.bf.seek(strtab.val + soname.val) print(self.read_str()) def get_entry_offset(self, entrynum): sec = self.find_section(b'.dynstr') for i in self.dynamic: if i.d_tag == entrynum: return sec.sh_offset + i.val return None def print_rpath(self): offset = self.get_entry_offset(DT_RPATH) if offset is None: print("This file does not have an rpath.") else: self.bf.seek(offset) print(self.read_str()) def print_runpath(self): offset = self.get_entry_offset(DT_RUNPATH) if offset is None: print("This file does not have a runpath.") else: self.bf.seek(offset) print(self.read_str()) def print_deps(self): sec = self.find_section(b'.dynstr') deps = [] for i in self.dynamic: if i.d_tag == DT_NEEDED: deps.append(i) for i in deps: offset = sec.sh_offset + i.val self.bf.seek(offset) name = self.read_str() print(name) def fix_deps(self, prefix): sec = self.find_section(b'.dynstr') deps = [] for i in self.dynamic: if i.d_tag == DT_NEEDED: deps.append(i) for i in deps: offset = sec.sh_offset + i.val self.bf.seek(offset) name = self.read_str() if name.startswith(prefix): basename = name.split(b'/')[-1] padding = b'\0' * (len(name) - len(basename)) newname = basename + padding assert(len(newname) == len(name)) self.bf.seek(offset) self.bf.write(newname) def fix_rpath(self, new_rpath): # The path to search for can be either rpath or runpath. # Fix both of them to be sure. self.fix_rpathtype_entry(new_rpath, DT_RPATH) self.fix_rpathtype_entry(new_rpath, DT_RUNPATH) def fix_rpathtype_entry(self, new_rpath, entrynum): if isinstance(new_rpath, str): new_rpath = new_rpath.encode('utf8') rp_off = self.get_entry_offset(entrynum) if rp_off is None: if self.verbose: print('File does not have rpath. It should be a fully static executable.') return self.bf.seek(rp_off) old_rpath = self.read_str() if len(old_rpath) < len(new_rpath): sys.exit("New rpath must not be longer than the old one.") # The linker does read-only string deduplication. If there is a # string that shares a suffix with the rpath, they might get # dedupped. This means changing the rpath string might break something # completely unrelated. This has already happened once with X.org. # Thus we want to keep this change as small as possible to minimize # the chance of obliterating other strings. It might still happen # but our behavior is identical to what chrpath does and it has # been in use for ages so based on that this should be rare. if not new_rpath: self.remove_rpath_entry(entrynum) else: self.bf.seek(rp_off) self.bf.write(new_rpath) self.bf.write(b'\0') def remove_rpath_entry(self, entrynum): sec = self.find_section(b'.dynamic') if sec is None: return None for (i, entry) in enumerate(self.dynamic): if entry.d_tag == entrynum: rpentry = self.dynamic[i] rpentry.d_tag = 0 self.dynamic = self.dynamic[:i] + self.dynamic[i + 1:] + [rpentry] break # DT_MIPS_RLD_MAP_REL is relative to the offset of the tag. Adjust it consequently. for entry in self.dynamic[i:]: if entry.d_tag == DT_MIPS_RLD_MAP_REL: entry.val += 2 * (self.ptrsize // 8) break self.bf.seek(sec.sh_offset) for entry in self.dynamic: entry.write(self.bf) return None def run(args): if len(args) < 1 or len(args) > 2: print('This application resets target rpath.') print('Don\'t run this unless you know what you are doing.') print('%s: ' % sys.argv[0]) sys.exit(1) with Elf(args[0]) as e: if len(args) == 1: e.print_rpath() e.print_runpath() else: new_rpath = args[1] e.fix_rpath(new_rpath) return 0 if __name__ == '__main__': run(sys.argv[1:]) meson-0.45.1/mesonbuild/scripts/__init__.py0000644000175000017500000000144413035766234022271 0ustar jpakkanejpakkane00000000000000# Copyright 2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. def destdir_join(d1, d2): # c:\destdir + c:\prefix must produce c:\destdir\prefix if len(d1) > 1 and d1[1] == ':' \ and len(d2) > 1 and d2[1] == ':': return d1 + d2[2:] return d1 + d2 meson-0.45.1/mesonbuild/scripts/yelphelper.py0000644000175000017500000001310513254550710022671 0ustar jpakkanejpakkane00000000000000# Copyright 2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os import subprocess import shutil import argparse from .. import mlog from . import destdir_join from .gettext import read_linguas parser = argparse.ArgumentParser() parser.add_argument('command') parser.add_argument('--id', dest='project_id') parser.add_argument('--subdir', dest='subdir') parser.add_argument('--installdir', dest='install_dir') parser.add_argument('--sources', dest='sources') parser.add_argument('--media', dest='media', default='') parser.add_argument('--langs', dest='langs', default='') parser.add_argument('--symlinks', type=bool, dest='symlinks', default=False) def build_pot(srcdir, project_id, sources): # Must be relative paths sources = [os.path.join('C', source) for source in sources] outfile = os.path.join(srcdir, project_id + '.pot') subprocess.call(['itstool', '-o', outfile] + sources) def update_po(srcdir, project_id, langs): potfile = os.path.join(srcdir, project_id + '.pot') for lang in langs: pofile = os.path.join(srcdir, lang, lang + '.po') subprocess.call(['msgmerge', '-q', '-o', pofile, pofile, potfile]) def build_translations(srcdir, blddir, langs): for lang in langs: outdir = os.path.join(blddir, lang) os.makedirs(outdir, exist_ok=True) subprocess.call([ 'msgfmt', os.path.join(srcdir, lang, lang + '.po'), '-o', os.path.join(outdir, lang + '.gmo') ]) def merge_translations(blddir, sources, langs): for lang in langs: subprocess.call([ 'itstool', '-m', os.path.join(blddir, lang, lang + '.gmo'), '-o', os.path.join(blddir, lang) ] + sources) def install_help(srcdir, blddir, sources, media, langs, install_dir, destdir, project_id, symlinks): c_install_dir = os.path.join(install_dir, 'C', project_id) for lang in langs + ['C']: indir = destdir_join(destdir, os.path.join(install_dir, lang, project_id)) os.makedirs(indir, exist_ok=True) for source in sources: infile = os.path.join(srcdir if lang == 'C' else blddir, lang, source) outfile = os.path.join(indir, source) mlog.log('Installing %s to %s' % (infile, outfile)) shutil.copyfile(infile, outfile) shutil.copystat(infile, outfile) for m in media: infile = os.path.join(srcdir, lang, m) outfile = os.path.join(indir, m) if not os.path.exists(infile): if lang == 'C': mlog.warning('Media file "%s" did not exist in C directory' % m) continue elif symlinks: srcfile = os.path.join(c_install_dir, m) mlog.log('Symlinking %s to %s.' % (outfile, srcfile)) if '/' in m or '\\' in m: os.makedirs(os.path.dirname(outfile), exist_ok=True) try: try: os.symlink(srcfile, outfile) except FileExistsError: os.remove(outfile) os.symlink(srcfile, outfile) continue except (NotImplementedError, OSError): mlog.warning('Symlinking not supported, falling back to copying') else: # Lang doesn't have media file so copy it over 'C' one infile = os.path.join(srcdir, 'C', m) mlog.log('Installing %s to %s' % (infile, outfile)) if '/' in m or '\\' in m: os.makedirs(os.path.dirname(outfile), exist_ok=True) shutil.copyfile(infile, outfile) shutil.copystat(infile, outfile) def run(args): options = parser.parse_args(args) langs = options.langs.split('@@') if options.langs else [] media = options.media.split('@@') if options.media else [] sources = options.sources.split('@@') destdir = os.environ.get('DESTDIR', '') src_subdir = os.path.join(os.environ['MESON_SOURCE_ROOT'], options.subdir) build_subdir = os.path.join(os.environ['MESON_BUILD_ROOT'], options.subdir) abs_sources = [os.path.join(src_subdir, 'C', source) for source in sources] if not langs: langs = read_linguas(src_subdir) if options.command == 'pot': build_pot(src_subdir, options.project_id, sources) elif options.command == 'update-po': build_pot(src_subdir, options.project_id, sources) update_po(src_subdir, options.project_id, langs) elif options.command == 'build': if langs: build_translations(src_subdir, build_subdir, langs) elif options.command == 'install': install_dir = os.path.join(os.environ['MESON_INSTALL_PREFIX'], options.install_dir) if langs: build_translations(src_subdir, build_subdir, langs) merge_translations(build_subdir, abs_sources, langs) install_help(src_subdir, build_subdir, sources, media, langs, install_dir, destdir, options.project_id, options.symlinks) meson-0.45.1/mesonbuild/environment.py0000644000175000017500000012073113254550710021401 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import configparser, os, platform, re, shlex, shutil, subprocess from . import coredata from .linkers import ArLinker, VisualStudioLinker from . import mesonlib from .mesonlib import EnvironmentException, Popen_safe from . import mlog from . import compilers from .compilers import ( CLANG_OSX, CLANG_STANDARD, CLANG_WIN, GCC_CYGWIN, GCC_MINGW, GCC_OSX, GCC_STANDARD, ICC_STANDARD, is_assembly, is_header, is_library, is_llvm_ir, is_object, is_source, ) from .compilers import ( ClangCCompiler, ClangCPPCompiler, ClangObjCCompiler, ClangObjCPPCompiler, G95FortranCompiler, GnuCCompiler, GnuCPPCompiler, GnuFortranCompiler, GnuObjCCompiler, GnuObjCPPCompiler, IntelCCompiler, IntelCPPCompiler, IntelFortranCompiler, JavaCompiler, MonoCompiler, VisualStudioCsCompiler, NAGFortranCompiler, Open64FortranCompiler, PathScaleFortranCompiler, PGIFortranCompiler, RustCompiler, SunFortranCompiler, ValaCompiler, VisualStudioCCompiler, VisualStudioCPPCompiler, ) build_filename = 'meson.build' # Environment variables that each lang uses. cflags_mapping = {'c': 'CFLAGS', 'cpp': 'CXXFLAGS', 'objc': 'OBJCFLAGS', 'objcpp': 'OBJCXXFLAGS', 'fortran': 'FFLAGS', 'd': 'DFLAGS', 'vala': 'VALAFLAGS'} def find_coverage_tools(): gcovr_exe = 'gcovr' lcov_exe = 'lcov' genhtml_exe = 'genhtml' if not mesonlib.exe_exists([gcovr_exe, '--version']): gcovr_exe = None if not mesonlib.exe_exists([lcov_exe, '--version']): lcov_exe = None if not mesonlib.exe_exists([genhtml_exe, '--version']): genhtml_exe = None return gcovr_exe, lcov_exe, genhtml_exe def detect_ninja(version='1.5', log=False): for n in ['ninja', 'ninja-build']: try: p, found = Popen_safe([n, '--version'])[0:2] except (FileNotFoundError, PermissionError): # Doesn't exist in PATH or isn't executable continue found = found.strip() # Perhaps we should add a way for the caller to know the failure mode # (not found or too old) if p.returncode == 0 and mesonlib.version_compare(found, '>=' + version): if log: mlog.log('Found ninja-{} at {}'.format(found, shlex.quote(shutil.which(n)))) return n def detect_native_windows_arch(): """ The architecture of Windows itself: x86 or amd64 """ # These env variables are always available. See: # https://msdn.microsoft.com/en-us/library/aa384274(VS.85).aspx # https://blogs.msdn.microsoft.com/david.wang/2006/03/27/howto-detect-process-bitness/ arch = os.environ.get('PROCESSOR_ARCHITEW6432', '').lower() if not arch: try: # If this doesn't exist, something is messing with the environment arch = os.environ['PROCESSOR_ARCHITECTURE'].lower() except KeyError: raise EnvironmentException('Unable to detect native OS architecture') return arch def detect_windows_arch(compilers): """ Detecting the 'native' architecture of Windows is not a trivial task. We cannot trust that the architecture that Python is built for is the 'native' one because you can run 32-bit apps on 64-bit Windows using WOW64 and people sometimes install 32-bit Python on 64-bit Windows. We also can't rely on the architecture of the OS itself, since it's perfectly normal to compile and run 32-bit applications on Windows as if they were native applications. It's a terrible experience to require the user to supply a cross-info file to compile 32-bit applications on 64-bit Windows. Thankfully, the only way to compile things with Visual Studio on Windows is by entering the 'msvc toolchain' environment, which can be easily detected. In the end, the sanest method is as follows: 1. Check if we're in an MSVC toolchain environment, and if so, return the MSVC toolchain architecture as our 'native' architecture. 2. If not, check environment variables that are set by Windows and WOW64 to find out the architecture that Windows is built for, and use that as our 'native' architecture. """ os_arch = detect_native_windows_arch() if os_arch != 'amd64': return os_arch # If we're on 64-bit Windows, 32-bit apps can be compiled without # cross-compilation. So if we're doing that, just set the native arch as # 32-bit and pretend like we're running under WOW64. Else, return the # actual Windows architecture that we deduced above. for compiler in compilers.values(): # Check if we're using and inside an MSVC toolchain environment if compiler.id == 'msvc' and 'VCINSTALLDIR' in os.environ: # 'Platform' is only set when the target arch is not 'x86'. # It's 'x64' when targeting x86_64 and 'arm' when targeting ARM. platform = os.environ.get('Platform', 'x86').lower() if platform == 'x86': return platform if compiler.id == 'gcc' and compiler.has_builtin_define('__i386__'): return 'x86' return os_arch def detect_cpu_family(compilers): """ Python is inconsistent in its platform module. It returns different values for the same cpu. For x86 it might return 'x86', 'i686' or somesuch. Do some canonicalization. """ if mesonlib.is_windows(): trial = detect_windows_arch(compilers) else: trial = platform.machine().lower() if trial.startswith('i') and trial.endswith('86'): return 'x86' if trial.startswith('arm'): return 'arm' if trial in ('amd64', 'x64'): trial = 'x86_64' if trial == 'x86_64': # On Linux (and maybe others) there can be any mixture of 32/64 bit # code in the kernel, Python, system etc. The only reliable way # to know is to check the compiler defines. for c in compilers.values(): try: if c.has_builtin_define('__i386__'): return 'x86' except mesonlib.MesonException: # Ignore compilers that do not support has_builtin_define. pass return 'x86_64' # Add fixes here as bugs are reported. return trial def detect_cpu(compilers): if mesonlib.is_windows(): trial = detect_windows_arch(compilers) else: trial = platform.machine().lower() if trial in ('amd64', 'x64'): trial = 'x86_64' if trial == 'x86_64': # Same check as above for cpu_family for c in compilers.values(): try: if c.has_builtin_define('__i386__'): return 'i686' # All 64 bit cpus have at least this level of x86 support. except mesonlib.MesonException: pass return 'x86_64' # Add fixes here as bugs are reported. return trial def detect_system(): system = platform.system().lower() if system.startswith('cygwin'): return 'cygwin' return system def search_version(text): # Usually of the type 4.1.4 but compiler output may contain # stuff like this: # (Sourcery CodeBench Lite 2014.05-29) 4.8.3 20140320 (prerelease) # Limiting major version number to two digits seems to work # thus far. When we get to GCC 100, this will break, but # if we are still relevant when that happens, it can be # considered an achievement in itself. # # This regex is reaching magic levels. If it ever needs # to be updated, do not complexify but convert to something # saner instead. version_regex = '(? 1: print('%s ' % args[0]) print('If you omit the build directory, the current directory is substituted.') return 1 if not options.directory: builddir = os.getcwd() else: builddir = options.directory[0] try: c = Conf(builddir) save = False if len(options.sets) > 0: c.set_options(options.sets) save = True elif options.clearcache: c.clear_cache() save = True else: c.print_conf() if save: c.save() except ConfException as e: print('Meson configurator encountered an error:\n') print(e) return 1 return 0 if __name__ == '__main__': sys.exit(run(sys.argv[1:])) meson-0.45.1/mesonbuild/dependencies/0000755000175000017500000000000013254552746021120 5ustar jpakkanejpakkane00000000000000meson-0.45.1/mesonbuild/dependencies/dev.py0000644000175000017500000002572213246615532022252 0ustar jpakkanejpakkane00000000000000# Copyright 2013-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. # This file contains the detection logic for external dependencies useful for # development purposes, such as testing, debugging, etc.. import os import re from .. import mlog from .. import mesonlib from ..mesonlib import version_compare, stringlistify, extract_as_list from .base import ( DependencyException, ExternalDependency, PkgConfigDependency, strip_system_libdirs, ConfigToolDependency, ) class GTestDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('gtest', environment, 'cpp', kwargs) self.main = kwargs.get('main', False) self.src_dirs = ['/usr/src/gtest/src', '/usr/src/googletest/googletest/src'] self.detect() def detect(self): self.version = '1.something_maybe' gtest_detect = self.compiler.find_library("gtest", self.env, []) gtest_main_detect = self.compiler.find_library("gtest_main", self.env, []) if gtest_detect and (not self.main or gtest_main_detect): self.is_found = True self.compile_args = [] self.link_args = gtest_detect if self.main: self.link_args += gtest_main_detect self.sources = [] mlog.log('Dependency GTest found:', mlog.green('YES'), '(prebuilt)') elif self.detect_srcdir(): self.is_found = True self.compile_args = ['-I' + self.src_include_dir] self.link_args = [] if self.main: self.sources = [self.all_src, self.main_src] else: self.sources = [self.all_src] mlog.log('Dependency GTest found:', mlog.green('YES'), '(building self)') else: mlog.log('Dependency GTest found:', mlog.red('NO')) self.is_found = False def detect_srcdir(self): for s in self.src_dirs: if os.path.exists(s): self.src_dir = s self.all_src = mesonlib.File.from_absolute_file( os.path.join(self.src_dir, 'gtest-all.cc')) self.main_src = mesonlib.File.from_absolute_file( os.path.join(self.src_dir, 'gtest_main.cc')) self.src_include_dir = os.path.normpath(os.path.join(self.src_dir, '..')) return True return False def need_threads(self): return True class GMockDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('gmock', environment, 'cpp', kwargs) self.version = '1.something_maybe' # GMock may be a library or just source. # Work with both. gmock_detect = self.compiler.find_library("gmock", self.env, []) if gmock_detect: self.is_found = True self.compile_args = [] self.link_args = gmock_detect self.sources = [] mlog.log('Dependency GMock found:', mlog.green('YES'), '(prebuilt)') return for d in ['/usr/src/googletest/googlemock/src', '/usr/src/gmock/src', '/usr/src/gmock']: if os.path.exists(d): self.is_found = True # Yes, we need both because there are multiple # versions of gmock that do different things. d2 = os.path.normpath(os.path.join(d, '..')) self.compile_args = ['-I' + d, '-I' + d2] self.link_args = [] all_src = mesonlib.File.from_absolute_file(os.path.join(d, 'gmock-all.cc')) main_src = mesonlib.File.from_absolute_file(os.path.join(d, 'gmock_main.cc')) if kwargs.get('main', False): self.sources = [all_src, main_src] else: self.sources = [all_src] mlog.log('Dependency GMock found:', mlog.green('YES'), '(building self)') return mlog.log('Dependency GMock found:', mlog.red('NO')) self.is_found = False class LLVMDependency(ConfigToolDependency): """ LLVM uses a special tool, llvm-config, which has arguments for getting c args, cxx args, and ldargs as well as version. """ # Ordered list of llvm-config binaries to try. Start with base, then try # newest back to oldest (3.5 is arbitrary), and finally the devel version. # Please note that llvm-config-6.0 is a development snapshot and it should # not be moved to the beginning of the list. The only difference between # llvm-config-7 and llvm-config-devel is that the former is used by # Debian and the latter is used by FreeBSD. tools = [ 'llvm-config', # base 'llvm-config-6.0', 'llvm-config60', 'llvm-config-5.0', 'llvm-config50', 'llvm-config-4.0', 'llvm-config40', 'llvm-config-3.9', 'llvm-config39', 'llvm-config-3.8', 'llvm-config38', 'llvm-config-3.7', 'llvm-config37', 'llvm-config-3.6', 'llvm-config36', 'llvm-config-3.5', 'llvm-config35', 'llvm-config-7', 'llvm-config-devel', # development snapshot ] tool_name = 'llvm-config' __cpp_blacklist = {'-DNDEBUG'} def __init__(self, environment, kwargs): # It's necessary for LLVM <= 3.8 to use the C++ linker. For 3.9 and 4.0 # the C linker works fine if only using the C API. super().__init__('LLVM', environment, 'cpp', kwargs) self.provided_modules = [] self.required_modules = set() if not self.is_found: return self.static = kwargs.get('static', False) self.provided_modules = self.get_config_value(['--components'], 'modules') modules = stringlistify(extract_as_list(kwargs, 'modules')) self.check_components(modules) opt_modules = stringlistify(extract_as_list(kwargs, 'optional_modules')) self.check_components(opt_modules, required=False) cargs = set(self.get_config_value(['--cppflags'], 'compile_args')) self.compile_args = list(cargs.difference(self.__cpp_blacklist)) if version_compare(self.version, '>= 3.9'): self._set_new_link_args() else: self._set_old_link_args() self.link_args = strip_system_libdirs(environment, self.link_args) self.link_args = self.__fix_bogus_link_args(self.link_args) @staticmethod def __fix_bogus_link_args(args): """This function attempts to fix bogus link arguments that llvm-config generates. Currently it works around the following: - FreeBSD: when statically linking -l/usr/lib/libexecinfo.so will be generated, strip the -l in cases like this. """ new_args = [] for arg in args: if arg.startswith('-l') and arg.endswith('.so'): new_args.append(arg.lstrip('-l')) else: new_args.append(arg) return new_args def _set_new_link_args(self): """How to set linker args for LLVM versions >= 3.9""" if ((mesonlib.is_dragonflybsd() or mesonlib.is_freebsd()) and not self.static and version_compare(self.version, '>= 4.0')): # llvm-config on DragonFly BSD and FreeBSD for versions 4.0, 5.0, # and 6.0 have an error when generating arguments for shared mode # linking, even though libLLVM.so is installed, because for some # reason the tool expects to find a .so for each static library. # This works around that. self.link_args = self.get_config_value(['--ldflags'], 'link_args') self.link_args.append('-lLLVM') return link_args = ['--link-static', '--system-libs'] if self.static else ['--link-shared'] self.link_args = self.get_config_value( ['--libs', '--ldflags'] + link_args + list(self.required_modules), 'link_args') def _set_old_link_args(self): """Setting linker args for older versions of llvm. Old versions of LLVM bring an extra level of insanity with them. llvm-config will provide the correct arguments for static linking, but not for shared-linnking, we have to figure those out ourselves, because of course we do. """ if self.static: self.link_args = self.get_config_value( ['--libs', '--ldflags', '--system-libs'] + list(self.required_modules), 'link_args') else: # llvm-config will provide arguments for static linking, so we get # to figure out for ourselves what to link with. We'll do that by # checking in the directory provided by --libdir for a library # called libLLVM-.(so|dylib|dll) libdir = self.get_config_value(['--libdir'], 'link_args')[0] expected_name = 'libLLVM-{}'.format(self.version) re_name = re.compile(r'{}.(so|dll|dylib)'.format(expected_name)) for file_ in os.listdir(libdir): if re_name.match(file_): self.link_args = ['-L{}'.format(libdir), '-l{}'.format(os.path.splitext(file_.lstrip('lib'))[0])] break else: raise DependencyException( 'Could not find a dynamically linkable library for LLVM.') def check_components(self, modules, required=True): """Check for llvm components (modules in meson terms). The required option is whether the module is required, not whether LLVM is required. """ for mod in sorted(set(modules)): if mod not in self.provided_modules: mlog.log('LLVM module', mlog.bold(mod), 'found:', mlog.red('NO'), '(optional)' if not required else '') if required: self.is_found = False if self.required: raise DependencyException( 'Could not find required LLVM Component: {}'.format(mod)) else: self.required_modules.add(mod) mlog.log('LLVM module', mlog.bold(mod), 'found:', mlog.green('YES')) def need_threads(self): return True class ValgrindDependency(PkgConfigDependency): ''' Consumers of Valgrind usually only need the compile args and do not want to link to its (static) libraries. ''' def __init__(self, env, kwargs): super().__init__('valgrind', env, kwargs) def get_link_args(self): return [] meson-0.45.1/mesonbuild/dependencies/base.py0000644000175000017500000012077613254550710022406 0ustar jpakkanejpakkane00000000000000# Copyright 2013-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. # This file contains the detection logic for external dependencies. # Custom logic for several other packages are in separate files. import os import re import stat import shlex import shutil import textwrap from enum import Enum from pathlib import PurePath from .. import mlog from .. import mesonlib from ..mesonlib import ( MesonException, Popen_safe, version_compare_many, version_compare, listify ) # These must be defined in this file to avoid cyclical references. packages = {} _packages_accept_language = set() class DependencyException(MesonException): '''Exceptions raised while trying to find dependencies''' class DependencyMethods(Enum): # Auto means to use whatever dependency checking mechanisms in whatever order meson thinks is best. AUTO = 'auto' PKGCONFIG = 'pkg-config' QMAKE = 'qmake' # Just specify the standard link arguments, assuming the operating system provides the library. SYSTEM = 'system' # This is only supported on OSX - search the frameworks directory by name. EXTRAFRAMEWORK = 'extraframework' # Detect using the sysconfig module. SYSCONFIG = 'sysconfig' # Specify using a "program"-config style tool CONFIG_TOOL = 'config-tool' # For backewards compatibility SDLCONFIG = 'sdlconfig' CUPSCONFIG = 'cups-config' PCAPCONFIG = 'pcap-config' LIBWMFCONFIG = 'libwmf-config' class Dependency: @classmethod def _process_method_kw(cls, kwargs): method = kwargs.get('method', 'auto') if method not in [e.value for e in DependencyMethods]: raise DependencyException('method {!r} is invalid'.format(method)) method = DependencyMethods(method) # This sets per-tool config methods which are deprecated to to the new # generic CONFIG_TOOL value. if method in [DependencyMethods.SDLCONFIG, DependencyMethods.CUPSCONFIG, DependencyMethods.PCAPCONFIG, DependencyMethods.LIBWMFCONFIG]: mlog.warning(textwrap.dedent("""\ Configuration method {} has been deprecated in favor of 'config-tool'. This will be removed in a future version of meson.""".format(method))) method = DependencyMethods.CONFIG_TOOL # Set the detection method. If the method is set to auto, use any available method. # If method is set to a specific string, allow only that detection method. if method == DependencyMethods.AUTO: methods = cls.get_methods() elif method in cls.get_methods(): methods = [method] else: raise DependencyException( 'Unsupported detection method: {}, allowed methods are {}'.format( method.value, mlog.format_list([x.value for x in [DependencyMethods.AUTO] + cls.get_methods()]))) return methods def __init__(self, type_name, kwargs): self.name = "null" self.version = 'none' self.language = None # None means C-like self.is_found = False self.type_name = type_name self.compile_args = [] self.link_args = [] self.sources = [] self.methods = self._process_method_kw(kwargs) def __repr__(self): s = '<{0} {1}: {2}>' return s.format(self.__class__.__name__, self.name, self.is_found) def get_compile_args(self): return self.compile_args def get_link_args(self): return self.link_args def found(self): return self.is_found def get_sources(self): """Source files that need to be added to the target. As an example, gtest-all.cc when using GTest.""" return self.sources @staticmethod def get_methods(): return [DependencyMethods.AUTO] def get_name(self): return self.name def get_version(self): return self.version def get_exe_args(self, compiler): return [] def need_threads(self): return False def get_pkgconfig_variable(self, variable_name, kwargs): raise DependencyException('{!r} is not a pkgconfig dependency'.format(self.name)) def get_configtool_variable(self, variable_name): raise DependencyException('{!r} is not a config-tool dependency'.format(self.name)) class InternalDependency(Dependency): def __init__(self, version, incdirs, compile_args, link_args, libraries, sources, ext_deps): super().__init__('internal', {}) self.version = version self.is_found = True self.include_directories = incdirs self.compile_args = compile_args self.link_args = link_args self.libraries = libraries self.sources = sources self.ext_deps = ext_deps def get_pkgconfig_variable(self, variable_name, kwargs): raise DependencyException('Method "get_pkgconfig_variable()" is ' 'invalid for an internal dependency') def get_configtool_variable(self, variable_name): raise DependencyException('Method "get_configtool_variable()" is ' 'invalid for an internal dependency') class ExternalDependency(Dependency): def __init__(self, type_name, environment, language, kwargs): super().__init__(type_name, kwargs) self.env = environment self.name = type_name # default self.is_found = False self.language = language self.version_reqs = kwargs.get('version', None) self.required = kwargs.get('required', True) self.silent = kwargs.get('silent', False) self.static = kwargs.get('static', False) if not isinstance(self.static, bool): raise DependencyException('Static keyword must be boolean') # Is this dependency for cross-compilation? if 'native' in kwargs and self.env.is_cross_build(): self.want_cross = not kwargs['native'] else: self.want_cross = self.env.is_cross_build() # Set the compiler that will be used by this dependency # This is only used for configuration checks if self.want_cross: compilers = self.env.coredata.cross_compilers else: compilers = self.env.coredata.compilers # Set the compiler for this dependency if a language is specified, # else try to pick something that looks usable. if self.language: if self.language not in compilers: m = self.name.capitalize() + ' requires a {} compiler' raise DependencyException(m.format(self.language.capitalize())) self.compiler = compilers[self.language] else: # Try to find a compiler that this dependency can use for compiler # checks. It's ok if we don't find one. for lang in ('c', 'cpp', 'objc', 'objcpp', 'fortran', 'd'): self.compiler = compilers.get(lang, None) if self.compiler: break def get_compiler(self): return self.compiler class ConfigToolDependency(ExternalDependency): """Class representing dependencies found using a config tool.""" tools = None tool_name = None __strip_version = re.compile(r'^[0-9.]*') def __init__(self, name, environment, language, kwargs): super().__init__('config-tool', environment, language, kwargs) self.name = name self.native = kwargs.get('native', False) self.tools = listify(kwargs.get('tools', self.tools)) req_version = kwargs.get('version', None) tool, version = self.find_config(req_version) self.config = tool self.is_found = self.report_config(version, req_version) if not self.is_found: self.config = None return self.version = version def _sanitize_version(self, version): """Remove any non-numeric, non-point version suffixes.""" m = self.__strip_version.match(version) if m: # Ensure that there isn't a trailing '.', such as an input like # `1.2.3.git-1234` return m.group(0).rstrip('.') return version @classmethod def factory(cls, name, environment, language, kwargs, tools, tool_name): """Constructor for use in dependencies that can be found multiple ways. In addition to the standard constructor values, this constructor sets the tool_name and tools values of the instance. """ # This deserves some explanation, because metaprogramming is hard. # This uses type() to create a dynamic subclass of ConfigToolDependency # with the tools and tool_name class attributes set, this class is then # instantiated and returned. The reduce function (method) is also # attached, since python's pickle module won't be able to do anything # with this dynamically generated class otherwise. def reduce(self): return (cls._unpickle, (), self.__dict__) sub = type('{}Dependency'.format(name.capitalize()), (cls, ), {'tools': tools, 'tool_name': tool_name, '__reduce__': reduce}) return sub(name, environment, language, kwargs) @classmethod def _unpickle(cls): return cls.__new__(cls) def find_config(self, versions=None): """Helper method that searchs for config tool binaries in PATH and returns the one that best matches the given version requirements. """ if not isinstance(versions, list) and versions is not None: versions = listify(versions) if self.env.is_cross_build() and not self.native: cross_file = self.env.cross_info.config['binaries'] try: tools = [cross_file[self.tool_name]] except KeyError: mlog.warning('No entry for {0} specified in your cross file. ' 'Falling back to searching PATH. This may find a ' 'native version of {0}!'.format(self.tool_name)) tools = self.tools else: tools = self.tools best_match = (None, None) for tool in tools: try: p, out = Popen_safe([tool, '--version'])[:2] except (FileNotFoundError, PermissionError): continue if p.returncode != 0: continue out = self._sanitize_version(out.strip()) # Some tools, like pcap-config don't supply a version, but also # don't fail with --version, in that case just assume that there is # only one version and return it. if not out: return (tool, 'none') if versions: is_found = version_compare_many(out, versions)[0] # This allows returning a found version without a config tool, # which is useful to inform the user that you found version x, # but y was required. if not is_found: tool = None if best_match[1]: if version_compare(out, '> {}'.format(best_match[1])): best_match = (tool, out) else: best_match = (tool, out) return best_match def report_config(self, version, req_version): """Helper method to print messages about the tool.""" if self.config is None: if version is not None: mlog.log('Found', mlog.bold(self.tool_name), repr(version), mlog.red('NO'), '(needed', req_version, ')') else: mlog.log('Found', mlog.bold(self.tool_name), repr(req_version), mlog.red('NO')) mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.red('NO')) if self.required: raise DependencyException('Dependency {} not found'.format(self.name)) return False mlog.log('Found {}:'.format(self.tool_name), mlog.bold(shutil.which(self.config)), '({})'.format(version)) mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.green('YES')) return True def get_config_value(self, args, stage): p, out, err = Popen_safe([self.config] + args) if p.returncode != 0: if self.required: raise DependencyException( 'Could not generate {} for {}.\n{}'.format( stage, self.name, err)) return [] return shlex.split(out) @staticmethod def get_methods(): return [DependencyMethods.AUTO, DependencyMethods.CONFIG_TOOL] def get_configtool_variable(self, variable_name): p, out, _ = Popen_safe([self.config, '--{}'.format(variable_name)]) if p.returncode != 0: if self.required: raise DependencyException( 'Could not get variable "{}" for dependency {}'.format( variable_name, self.name)) variable = out.strip() mlog.debug('Got config-tool variable {} : {}'.format(variable_name, variable)) return variable class PkgConfigDependency(ExternalDependency): # The class's copy of the pkg-config path. Avoids having to search for it # multiple times in the same Meson invocation. class_pkgbin = None def __init__(self, name, environment, kwargs, language=None): super().__init__('pkgconfig', environment, language, kwargs) self.name = name self.is_libtool = False # Store a copy of the pkg-config path on the object itself so it is # stored in the pickled coredata and recovered. self.pkgbin = None # When finding dependencies for cross-compiling, we don't care about # the 'native' pkg-config if self.want_cross: if 'pkgconfig' not in environment.cross_info.config['binaries']: if self.required: raise DependencyException('Pkg-config binary missing from cross file') else: pkgname = environment.cross_info.config['binaries']['pkgconfig'] potential_pkgbin = ExternalProgram(pkgname, silent=True) if potential_pkgbin.found(): # FIXME, we should store all pkg-configs in ExternalPrograms. # However that is too destabilizing a change to do just before release. self.pkgbin = potential_pkgbin.get_command()[0] PkgConfigDependency.class_pkgbin = self.pkgbin else: mlog.debug('Cross pkg-config %s not found.' % potential_pkgbin.name) # Only search for the native pkg-config the first time and # store the result in the class definition elif PkgConfigDependency.class_pkgbin is None: self.pkgbin = self.check_pkgconfig() PkgConfigDependency.class_pkgbin = self.pkgbin else: self.pkgbin = PkgConfigDependency.class_pkgbin if not self.pkgbin: if self.required: raise DependencyException('Pkg-config not found.') return if self.want_cross: self.type_string = 'Cross' else: self.type_string = 'Native' mlog.debug('Determining dependency {!r} with pkg-config executable ' '{!r}'.format(name, self.pkgbin)) ret, self.version = self._call_pkgbin(['--modversion', name]) if ret != 0: if self.required: raise DependencyException('{} dependency {!r} not found' ''.format(self.type_string, name)) return found_msg = [self.type_string + ' dependency', mlog.bold(name), 'found:'] if self.version_reqs is None: self.is_found = True else: if not isinstance(self.version_reqs, (str, list)): raise DependencyException('Version argument must be string or list.') if isinstance(self.version_reqs, str): self.version_reqs = [self.version_reqs] (self.is_found, not_found, found) = \ version_compare_many(self.version, self.version_reqs) if not self.is_found: found_msg += [mlog.red('NO'), 'found {!r} but need:'.format(self.version), ', '.join(["'{}'".format(e) for e in not_found])] if found: found_msg += ['; matched:', ', '.join(["'{}'".format(e) for e in found])] if not self.silent: mlog.log(*found_msg) if self.required: m = 'Invalid version of dependency, need {!r} {!r} found {!r}.' raise DependencyException(m.format(name, not_found, self.version)) return try: # Fetch cargs to be used while using this dependency self._set_cargs() # Fetch the libraries and library paths needed for using this self._set_libs() found_msg += [mlog.green('YES'), self.version] except DependencyException as e: if self.required: raise else: self.compile_args = [] self.link_args = [] self.is_found = False found_msg += [mlog.red('NO'), '; reason: {}'.format(str(e))] # Print the found message only at the very end because fetching cflags # and libs can also fail if other needed pkg-config files aren't found. if not self.silent: mlog.log(*found_msg) def __repr__(self): s = '<{0} {1}: {2} {3}>' return s.format(self.__class__.__name__, self.name, self.is_found, self.version_reqs) def _call_pkgbin(self, args, env=None): if not env: env = os.environ p, out = Popen_safe([self.pkgbin] + args, env=env)[0:2] return p.returncode, out.strip() def _convert_mingw_paths(self, args): ''' Both MSVC and native Python on Windows cannot handle MinGW-esque /c/foo paths so convert them to C:/foo. We cannot resolve other paths starting with / like /home/foo so leave them as-is so that the user gets an error/warning from the compiler/linker. ''' if not mesonlib.is_windows(): return args converted = [] for arg in args: pargs = [] # Library search path if arg.startswith('-L/'): pargs = PurePath(arg[2:]).parts tmpl = '-L{}:/{}' elif arg.startswith('-I/'): pargs = PurePath(arg[2:]).parts tmpl = '-I{}:/{}' # Full path to library or .la file elif arg.startswith('/'): pargs = PurePath(arg).parts tmpl = '{}:/{}' if len(pargs) > 1 and len(pargs[1]) == 1: arg = tmpl.format(pargs[1], '/'.join(pargs[2:])) converted.append(arg) return converted def _set_cargs(self): env = None if self.language == 'fortran': # gfortran doesn't appear to look in system paths for INCLUDE files, # so don't allow pkg-config to suppress -I flags for system paths env = os.environ.copy() env['PKG_CONFIG_ALLOW_SYSTEM_CFLAGS'] = '1' ret, out = self._call_pkgbin(['--cflags', self.name], env=env) if ret != 0: raise DependencyException('Could not generate cargs for %s:\n\n%s' % (self.name, out)) self.compile_args = self._convert_mingw_paths(shlex.split(out)) def _set_libs(self): env = None libcmd = [self.name, '--libs'] if self.static: libcmd.append('--static') # Force pkg-config to output -L fields even if they are system # paths so we can do manual searching with cc.find_library() later. env = os.environ.copy() env['PKG_CONFIG_ALLOW_SYSTEM_LIBS'] = '1' ret, out = self._call_pkgbin(libcmd, env=env) if ret != 0: raise DependencyException('Could not generate libs for %s:\n\n%s' % (self.name, out)) self.link_args = [] libpaths = [] static_libs_notfound = [] for lib in self._convert_mingw_paths(shlex.split(out)): # If we want to use only static libraries, we have to look for the # file ourselves instead of depending on the compiler to find it # with -lfoo or foo.lib. However, we can only do this if we already # have some library paths gathered. if self.static: if lib.startswith('-L'): libpaths.append(lib[2:]) continue # FIXME: try to handle .la files in static mode too? elif lib.startswith('-l'): args = self.compiler.find_library(lib[2:], self.env, libpaths, libtype='static') if not args or len(args) < 1: if lib in static_libs_notfound: continue mlog.warning('Static library {!r} not found for dependency {!r}, may ' 'not be statically linked'.format(lib[2:], self.name)) static_libs_notfound.append(lib) else: # Replace -l arg with full path to static library lib = args[0] elif lib.endswith(".la"): shared_libname = self.extract_libtool_shlib(lib) shared_lib = os.path.join(os.path.dirname(lib), shared_libname) if not os.path.exists(shared_lib): shared_lib = os.path.join(os.path.dirname(lib), ".libs", shared_libname) if not os.path.exists(shared_lib): raise DependencyException('Got a libtools specific "%s" dependencies' 'but we could not compute the actual shared' 'library path' % lib) lib = shared_lib self.is_libtool = True self.link_args.append(lib) # Add all -Lbar args if we have -lfoo args in link_args if static_libs_notfound: # Order of -L flags doesn't matter with ld, but it might with other # linkers such as MSVC, so prepend them. self.link_args = ['-L' + lp for lp in libpaths] + self.link_args def get_pkgconfig_variable(self, variable_name, kwargs): options = ['--variable=' + variable_name, self.name] if 'define_variable' in kwargs: definition = kwargs.get('define_variable', []) if not isinstance(definition, list): raise MesonException('define_variable takes a list') if len(definition) != 2 or not all(isinstance(i, str) for i in definition): raise MesonException('define_variable must be made up of 2 strings for VARIABLENAME and VARIABLEVALUE') options = ['--define-variable=' + '='.join(definition)] + options ret, out = self._call_pkgbin(options) variable = '' if ret != 0: if self.required: raise DependencyException('%s dependency %s not found.' % (self.type_string, self.name)) else: variable = out.strip() # pkg-config doesn't distinguish between empty and non-existent variables # use the variable list to check for variable existence if not variable: ret, out = self._call_pkgbin(['--print-variables', self.name]) if not re.search(r'^' + variable_name + r'$', out, re.MULTILINE): if 'default' in kwargs: variable = kwargs['default'] else: mlog.warning("pkgconfig variable '%s' not defined for dependency %s." % (variable_name, self.name)) mlog.debug('Got pkgconfig variable %s : %s' % (variable_name, variable)) return variable @staticmethod def get_methods(): return [DependencyMethods.PKGCONFIG] def check_pkgconfig(self): evar = 'PKG_CONFIG' if evar in os.environ: pkgbin = os.environ[evar].strip() else: pkgbin = 'pkg-config' try: p, out = Popen_safe([pkgbin, '--version'])[0:2] if p.returncode != 0: # Set to False instead of None to signify that we've already # searched for it and not found it pkgbin = False except (FileNotFoundError, PermissionError): pkgbin = False if pkgbin and not os.path.isabs(pkgbin) and shutil.which(pkgbin): # Sometimes shutil.which fails where Popen succeeds, so # only find the abs path if it can be found by shutil.which pkgbin = shutil.which(pkgbin) if not self.silent: if pkgbin: mlog.log('Found pkg-config:', mlog.bold(pkgbin), '(%s)' % out.strip()) else: mlog.log('Found Pkg-config:', mlog.red('NO')) return pkgbin def extract_field(self, la_file, fieldname): with open(la_file) as f: for line in f: arr = line.strip().split('=') if arr[0] == fieldname: return arr[1][1:-1] return None def extract_dlname_field(self, la_file): return self.extract_field(la_file, 'dlname') def extract_libdir_field(self, la_file): return self.extract_field(la_file, 'libdir') def extract_libtool_shlib(self, la_file): ''' Returns the path to the shared library corresponding to this .la file ''' dlname = self.extract_dlname_field(la_file) if dlname is None: return None # Darwin uses absolute paths where possible; since the libtool files never # contain absolute paths, use the libdir field if mesonlib.is_osx(): dlbasename = os.path.basename(dlname) libdir = self.extract_libdir_field(la_file) if libdir is None: return dlbasename return os.path.join(libdir, dlbasename) # From the comments in extract_libtool(), older libtools had # a path rather than the raw dlname return os.path.basename(dlname) class ExternalProgram: windows_exts = ('exe', 'msc', 'com', 'bat', 'cmd') def __init__(self, name, command=None, silent=False, search_dir=None): self.name = name if command is not None: self.command = listify(command) else: self.command = self._search(name, search_dir) if not silent: if self.found(): mlog.log('Program', mlog.bold(name), 'found:', mlog.green('YES'), '(%s)' % ' '.join(self.command)) else: mlog.log('Program', mlog.bold(name), 'found:', mlog.red('NO')) def __repr__(self): r = '<{} {!r} -> {!r}>' return r.format(self.__class__.__name__, self.name, self.command) @staticmethod def _shebang_to_cmd(script): """ Check if the file has a shebang and manually parse it to figure out the interpreter to use. This is useful if the script is not executable or if we're on Windows (which does not understand shebangs). """ try: with open(script) as f: first_line = f.readline().strip() if first_line.startswith('#!'): # In a shebang, everything before the first space is assumed to # be the command to run and everything after the first space is # the single argument to pass to that command. So we must split # exactly once. commands = first_line[2:].split('#')[0].strip().split(maxsplit=1) if mesonlib.is_windows(): # Windows does not have UNIX paths so remove them, # but don't remove Windows paths if commands[0].startswith('/'): commands[0] = commands[0].split('/')[-1] if len(commands) > 0 and commands[0] == 'env': commands = commands[1:] # Windows does not ship python3.exe, but we know the path to it if len(commands) > 0 and commands[0] == 'python3': commands = mesonlib.python_command + commands[1:] elif mesonlib.is_haiku(): # Haiku does not have /usr, but a lot of scripts assume that # /usr/bin/env always exists. Detect that case and run the # script with the interpreter after it. if commands[0] == '/usr/bin/env': commands = commands[1:] # We know what python3 is, we're running on it if len(commands) > 0 and commands[0] == 'python3': commands = mesonlib.python_command + commands[1:] return commands + [script] except Exception as e: mlog.debug(e) pass mlog.debug('Unusable script {!r}'.format(script)) return False def _is_executable(self, path): suffix = os.path.splitext(path)[-1].lower()[1:] if mesonlib.is_windows(): if suffix in self.windows_exts: return True elif os.access(path, os.X_OK): return not os.path.isdir(path) return False def _search_dir(self, name, search_dir): if search_dir is None: return False trial = os.path.join(search_dir, name) if os.path.exists(trial): if self._is_executable(trial): return [trial] # Now getting desperate. Maybe it is a script file that is # a) not chmodded executable, or # b) we are on windows so they can't be directly executed. return self._shebang_to_cmd(trial) else: if mesonlib.is_windows(): for ext in self.windows_exts: trial_ext = '{}.{}'.format(trial, ext) if os.path.exists(trial_ext): return [trial_ext] return False def _search_windows_special_cases(self, name, command): ''' Lots of weird Windows quirks: 1. PATH search for @name returns files with extensions from PATHEXT, but only self.windows_exts are executable without an interpreter. 2. @name might be an absolute path to an executable, but without the extension. This works inside MinGW so people use it a lot. 3. The script is specified without an extension, in which case we have to manually search in PATH. 4. More special-casing for the shebang inside the script. ''' if command: # On Windows, even if the PATH search returned a full path, we can't be # sure that it can be run directly if it's not a native executable. # For instance, interpreted scripts sometimes need to be run explicitly # with an interpreter if the file association is not done properly. name_ext = os.path.splitext(command)[1] if name_ext[1:].lower() in self.windows_exts: # Good, it can be directly executed return [command] # Try to extract the interpreter from the shebang commands = self._shebang_to_cmd(command) if commands: return commands return [None] # Maybe the name is an absolute path to a native Windows # executable, but without the extension. This is technically wrong, # but many people do it because it works in the MinGW shell. if os.path.isabs(name): for ext in self.windows_exts: command = '{}.{}'.format(name, ext) if os.path.exists(command): return [command] # On Windows, interpreted scripts must have an extension otherwise they # cannot be found by a standard PATH search. So we do a custom search # where we manually search for a script with a shebang in PATH. search_dirs = os.environ.get('PATH', '').split(';') for search_dir in search_dirs: commands = self._search_dir(name, search_dir) if commands: return commands return [None] def _search(self, name, search_dir): ''' Search in the specified dir for the specified executable by name and if not found search in PATH ''' commands = self._search_dir(name, search_dir) if commands: return commands # Do a standard search in PATH command = shutil.which(name) if mesonlib.is_windows(): return self._search_windows_special_cases(name, command) # On UNIX-like platforms, shutil.which() is enough to find # all executables whether in PATH or with an absolute path return [command] def found(self): return self.command[0] is not None def get_command(self): return self.command[:] def get_path(self): if self.found(): # Assume that the last element is the full path to the script or # binary being run return self.command[-1] return None def get_name(self): return self.name class NonExistingExternalProgram(ExternalProgram): def __init__(self): super().__init__(name = 'nonexistingprogram', silent = True) def __repr__(self): r = '<{} {!r} -> {!r}>' return r.format(self.__class__.__name__, self.name, self.command) def found(self): return False class ExternalLibrary(ExternalDependency): def __init__(self, name, link_args, environment, language, silent=False): super().__init__('external', environment, language, {}) self.name = name self.language = language self.is_found = False if link_args: self.is_found = True self.link_args = link_args if not silent: if self.is_found: mlog.log('Library', mlog.bold(name), 'found:', mlog.green('YES')) else: mlog.log('Library', mlog.bold(name), 'found:', mlog.red('NO')) def get_link_args(self, language=None): ''' External libraries detected using a compiler must only be used with compatible code. For instance, Vala libraries (.vapi files) cannot be used with C code, and not all Rust library types can be linked with C-like code. Note that C++ libraries *can* be linked with C code with a C++ linker (and vice-versa). ''' # Using a vala library in a non-vala target, or a non-vala library in a vala target # XXX: This should be extended to other non-C linkers such as Rust if (self.language == 'vala' and language != 'vala') or \ (language == 'vala' and self.language != 'vala'): return [] return self.link_args class ExtraFrameworkDependency(ExternalDependency): def __init__(self, name, required, path, env, lang, kwargs): super().__init__('extraframeworks', env, lang, kwargs) self.name = None self.required = required self.detect(name, path) if self.found(): mlog.log('Dependency', mlog.bold(name), 'found:', mlog.green('YES'), os.path.join(self.path, self.name)) else: mlog.log('Dependency', name, 'found:', mlog.red('NO')) def detect(self, name, path): lname = name.lower() if path is None: paths = ['/System/Library/Frameworks', '/Library/Frameworks'] else: paths = [path] for p in paths: for d in os.listdir(p): fullpath = os.path.join(p, d) if lname != d.split('.')[0].lower(): continue if not stat.S_ISDIR(os.stat(fullpath).st_mode): continue self.path = p self.name = d self.is_found = True return if not self.found() and self.required: raise DependencyException('Framework dependency %s not found.' % (name, )) def get_compile_args(self): if self.found(): return ['-I' + os.path.join(self.path, self.name, 'Headers')] return [] def get_link_args(self): if self.found(): return ['-F' + self.path, '-framework', self.name.split('.')[0]] return [] def get_version(self): return 'unknown' def get_dep_identifier(name, kwargs, want_cross): # Need immutable objects since the identifier will be used as a dict key version_reqs = listify(kwargs.get('version', [])) if isinstance(version_reqs, list): version_reqs = frozenset(version_reqs) identifier = (name, version_reqs, want_cross) for key, value in kwargs.items(): # 'version' is embedded above as the second element for easy access # 'native' is handled above with `want_cross` # 'required' is irrelevant for caching; the caller handles it separately # 'fallback' subprojects cannot be cached -- they must be initialized if key in ('version', 'native', 'required', 'fallback',): continue # All keyword arguments are strings, ints, or lists (or lists of lists) if isinstance(value, list): value = frozenset(listify(value)) identifier += (key, value) return identifier def find_external_dependency(name, env, kwargs): required = kwargs.get('required', True) if not isinstance(required, bool): raise DependencyException('Keyword "required" must be a boolean.') if not isinstance(kwargs.get('method', ''), str): raise DependencyException('Keyword "method" must be a string.') lname = name.lower() if lname in packages: if lname not in _packages_accept_language and 'language' in kwargs: raise DependencyException('%s dependency does not accept "language" keyword argument' % (lname, )) # Create the dependency object using a factory class method, if one # exists, otherwise it is just constructed directly. if getattr(packages[lname], '_factory', None): dep = packages[lname]._factory(env, kwargs) else: dep = packages[lname](env, kwargs) if required and not dep.found(): raise DependencyException('Dependency "%s" not found' % name) return dep if 'language' in kwargs: # Remove check when PkgConfigDependency supports language. raise DependencyException('%s dependency does not accept "language" keyword argument' % (lname, )) pkg_exc = None pkgdep = None try: pkgdep = PkgConfigDependency(name, env, kwargs) if pkgdep.found(): return pkgdep except Exception as e: pkg_exc = e if mesonlib.is_osx(): fwdep = ExtraFrameworkDependency(name, False, None, env, None, kwargs) if required and not fwdep.found(): m = 'Dependency {!r} not found, tried Extra Frameworks ' \ 'and Pkg-Config:\n\n' + str(pkg_exc) raise DependencyException(m.format(name)) return fwdep if pkg_exc is not None: raise pkg_exc mlog.log('Dependency', mlog.bold(name), 'found:', mlog.red('NO')) return pkgdep def strip_system_libdirs(environment, link_args): """Remove -L arguments. leaving these in will break builds where a user has a version of a library in the system path, and a different version not in the system path if they want to link against the non-system path version. """ exclude = {'-L{}'.format(p) for p in environment.get_compiler_system_dirs()} return [l for l in link_args if l not in exclude] meson-0.45.1/mesonbuild/dependencies/platform.py0000644000175000017500000000270313117556674023322 0ustar jpakkanejpakkane00000000000000# Copyright 2013-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. # This file contains the detection logic for external dependencies that are # platform-specific (generally speaking). from .. import mesonlib from .base import ExternalDependency, DependencyException class AppleFrameworks(ExternalDependency): def __init__(self, env, kwargs): super().__init__('appleframeworks', env, None, kwargs) modules = kwargs.get('modules', []) if isinstance(modules, str): modules = [modules] if not modules: raise DependencyException("AppleFrameworks dependency requires at least one module.") self.frameworks = modules # FIXME: Use self.compiler to check if the frameworks are available for f in self.frameworks: self.link_args += ['-framework', f] def found(self): return mesonlib.is_osx() def get_version(self): return 'unknown' meson-0.45.1/mesonbuild/dependencies/boost.py0000644000175000017500000005637413254550710022624 0ustar jpakkanejpakkane00000000000000# Copyright 2013-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. # This file contains the detection logic for miscellaneous external dependencies. import glob import os from .. import mlog from .. import mesonlib from ..environment import detect_cpu_family from .base import (DependencyException, ExternalDependency) # On windows 3 directory layouts are supported: # * The default layout (versioned) installed: # - $BOOST_ROOT/include/boost-x_x/boost/*.hpp # - $BOOST_ROOT/lib/*.lib # * The non-default layout (system) installed: # - $BOOST_ROOT/include/boost/*.hpp # - $BOOST_ROOT/lib/*.lib # * The pre-built binaries from sf.net: # - $BOOST_ROOT/boost/*.hpp # - $BOOST_ROOT/lib-/*.lib where arch=32/64 and compiler=msvc-14.1 # # Note that we should also try to support: # mingw-w64 / Windows : libboost_-mt.a (location = /mingw64/lib/) # libboost_-mt.dll.a # # Library names supported: # - libboost_--mt-gd-x_x.lib (static) # - boost_--mt-gd-x_x.lib|.dll (shared) # - libboost_.lib (static) # - boost_.lib|.dll (shared) # where compiler is vc141 for example. # # NOTE: -gd means runtime and build time debugging is on # -mt means threading=multi # # The `modules` argument accept library names. This is because every module that # has libraries to link against also has multiple options regarding how to # link. See for example: # * http://www.boost.org/doc/libs/1_65_1/libs/test/doc/html/boost_test/usage_variants.html # * http://www.boost.org/doc/libs/1_65_1/doc/html/stacktrace/configuration_and_build.html # * http://www.boost.org/doc/libs/1_65_1/libs/math/doc/html/math_toolkit/main_tr1.html # **On Unix**, official packaged versions of boost libraries follow the following schemes: # # Linux / Debian: libboost_.so -> libboost_.so.1.66.0 # Linux / Red Hat: libboost_.so -> libboost_.so.1.66.0 # Linux / OpenSuse: libboost_.so -> libboost_.so.1.66.0 # Win / Cygwin: libboost_.dll.a (location = /usr/lib) # libboost_.a # cygboost__1_64.dll (location = /usr/bin) # Mac / homebrew: libboost_.dylib + libboost_-mt.dylib (location = /usr/local/lib) # Mac / macports: libboost_.dylib + libboost_-mt.dylib (location = /opt/local/lib) # # Its not clear that any other abi tags (e.g. -gd) are used in official packages. # # On Linux systems, boost libs have multithreading support enabled, but without the -mt tag. # # Boost documentation recommends using complex abi tags like "-lboost_regex-gcc34-mt-d-1_36". # (See http://www.boost.org/doc/libs/1_66_0/more/getting_started/unix-variants.html#library-naming) # However, its not clear that any Unix distribution follows this scheme. # Furthermore, the boost documentation for unix above uses examples from windows like # "libboost_regex-vc71-mt-d-x86-1_34.lib", so apparently the abi tags may be more aimed at windows. # # Probably we should use the linker search path to decide which libraries to use. This will # make it possible to find the macports boost libraries without setting BOOST_ROOT, and will # also mean that it would be possible to use user-installed boost libraries when official # packages are installed. # # We thus follow the following strategy: # 1. Look for libraries using compiler.find_library( ) # 1.1 On Linux, just look for boost_ # 1.2 On other systems (e.g. Mac) look for boost_-mt if multithreading. # 1.3 Otherwise look for boost_ # 2. Fall back to previous approach # 2.1. Search particular directories. # 2.2. Find boost libraries with unknown suffixes using file-name globbing. # TODO: Unix: Don't assume we know where the boost dir is, rely on -Idir and -Ldir being set. # TODO: Allow user to specify suffix in BOOST_SUFFIX, or add specific options like BOOST_DEBUG for 'd' for debug. class BoostDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('boost', environment, 'cpp', kwargs) self.need_static_link = ['boost_exception', 'boost_test_exec_monitor'] # FIXME: is this the right way to find the build type? self.is_debug = environment.cmd_line_options.buildtype.startswith('debug') threading = kwargs.get("threading", "multi") self.is_multithreading = threading == "multi" self.requested_modules = self.get_requested(kwargs) self.boost_root = None self.boost_roots = [] self.incdir = None self.libdir = None if 'BOOST_ROOT' in os.environ: self.boost_root = os.environ['BOOST_ROOT'] self.boost_roots = [self.boost_root] if not os.path.isabs(self.boost_root): raise DependencyException('BOOST_ROOT must be an absolute path.') if 'BOOST_INCLUDEDIR' in os.environ: self.incdir = os.environ['BOOST_INCLUDEDIR'] if 'BOOST_LIBRARYDIR' in os.environ: self.libdir = os.environ['BOOST_LIBRARYDIR'] if self.boost_root is None: if mesonlib.for_windows(self.want_cross, self.env): self.boost_roots = self.detect_win_roots() else: self.boost_roots = self.detect_nix_roots() if self.incdir is None: if mesonlib.for_windows(self.want_cross, self.env): self.incdir = self.detect_win_incdir() else: self.incdir = self.detect_nix_incdir() if self.check_invalid_modules(): self.log_fail() return mlog.debug('Boost library root dir is', mlog.bold(self.boost_root)) mlog.debug('Boost include directory is', mlog.bold(self.incdir)) # 1. check if we can find BOOST headers. self.detect_headers_and_version() # 2. check if we can find BOOST libraries. if self.is_found: self.detect_lib_modules() mlog.debug('Boost library directory is', mlog.bold(self.libdir)) # 3. Report success or failure if self.is_found: self.log_success() else: self.log_fail() def check_invalid_modules(self): invalid_modules = [c for c in self.requested_modules if 'boost_' + c not in BOOST_LIBS] # previous versions of meson allowed include dirs as modules remove = [] for m in invalid_modules: if m in BOOST_DIRS: mlog.warning('Requested boost library', mlog.bold(m), 'that doesn\'t exist. ' 'This will be an error in the future') remove.append(m) self.requested_modules = [x for x in self.requested_modules if x not in remove] invalid_modules = [x for x in invalid_modules if x not in remove] if invalid_modules: mlog.log(mlog.red('ERROR:'), 'Invalid Boost modules: ' + ', '.join(invalid_modules)) return True else: return False def log_fail(self): module_str = ', '.join(self.requested_modules) mlog.log("Dependency Boost (%s) found:" % module_str, mlog.red('NO')) def log_success(self): module_str = ', '.join(self.requested_modules) if self.boost_root: info = self.version + ', ' + self.boost_root else: info = self.version mlog.log('Dependency Boost (%s) found:' % module_str, mlog.green('YES'), info) def detect_nix_roots(self): return [os.path.abspath(os.path.join(x, '..')) for x in self.compiler.get_default_include_dirs()] def detect_win_roots(self): res = [] # Where boost documentation says it should be globtext = 'C:\\Program Files\\boost\\boost_*' files = glob.glob(globtext) res.extend(files) # Where boost built from source actually installs it if os.path.isdir('C:\\Boost'): res.append('C:\\Boost') # Where boost prebuilt binaries are globtext = 'C:\\local\\boost_*' files = glob.glob(globtext) res.extend(files) return res def detect_nix_incdir(self): if self.boost_root: return os.path.join(self.boost_root, 'include') return None # FIXME: Should pick a version that matches the requested version # Returns the folder that contains the boost folder. def detect_win_incdir(self): for root in self.boost_roots: globtext = os.path.join(root, 'include', 'boost-*') incdirs = glob.glob(globtext) if len(incdirs) > 0: return incdirs[0] incboostdir = os.path.join(root, 'include', 'boost') if os.path.isdir(incboostdir): return os.path.join(root, 'include') incboostdir = os.path.join(root, 'boost') if os.path.isdir(incboostdir): return root return None def get_compile_args(self): args = [] include_dir = self.incdir # Use "-isystem" when including boost headers instead of "-I" # to avoid compiler warnings/failures when "-Werror" is used # Careful not to use "-isystem" on default include dirs as it # breaks some of the headers for certain gcc versions # For example, doing g++ -isystem /usr/include on a simple # "int main()" source results in the error: # "/usr/include/c++/6.3.1/cstdlib:75:25: fatal error: stdlib.h: No such file or directory" # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70129 # and http://stackoverflow.com/questions/37218953/isystem-on-a-system-include-directory-causes-errors # for more details if include_dir and include_dir not in self.compiler.get_default_include_dirs(): args.append("".join(self.compiler.get_include_args(include_dir, True))) return args def get_requested(self, kwargs): candidates = mesonlib.extract_as_list(kwargs, 'modules') for c in candidates: if not isinstance(c, str): raise DependencyException('Boost module argument is not a string.') return candidates def detect_headers_and_version(self): try: version = self.compiler.get_define('BOOST_LIB_VERSION', '#include ', self.env, self.get_compile_args(), []) except mesonlib.EnvironmentException: return except TypeError: return # Remove quotes version = version[1:-1] # Fix version string self.version = version.replace('_', '.') self.is_found = True def detect_lib_modules(self): self.lib_modules = {} # 1. Try to find modules using compiler.find_library( ) if self.find_libraries_with_abi_tags(self.abi_tags()): pass # 2. Fall back to the old method else: if mesonlib.for_windows(self.want_cross, self.env): self.detect_lib_modules_win() else: self.detect_lib_modules_nix() # 3. Check if we can find the modules for m in self.requested_modules: if 'boost_' + m not in self.lib_modules: mlog.debug('Requested Boost library {!r} not found'.format(m)) self.is_found = False def modname_from_filename(self, filename): modname = os.path.basename(filename) modname = modname.split('.', 1)[0] modname = modname.split('-', 1)[0] if modname.startswith('libboost'): modname = modname[3:] return modname def compiler_tag(self): tag = None compiler = self.env.detect_cpp_compiler(self.want_cross) if mesonlib.for_windows(self.want_cross, self.env): if compiler.get_id() == 'msvc': comp_ts_version = compiler.get_toolset_version() compiler_ts = comp_ts_version.split('.') # FIXME - what about other compilers? tag = '-vc{}{}'.format(compiler_ts[0], compiler_ts[1]) else: tag = '' return tag def threading_tag(self): if not self.is_multithreading: return '' if mesonlib.for_darwin(self.want_cross, self.env): # - Mac: requires -mt for multithreading, so should not fall back to non-mt libraries. return '-mt' elif mesonlib.for_windows(self.want_cross, self.env): # - Windows: requires -mt for multithreading, so should not fall back to non-mt libraries. return '-mt' else: # - Linux: leaves off -mt but libraries are multithreading-aware. # - Cygwin: leaves off -mt but libraries are multithreading-aware. return '' def version_tag(self): return '-' + self.version.replace('.', '_') def debug_tag(self): return '-gd' if self.is_debug else '' def versioned_abi_tag(self): return self.compiler_tag() + self.threading_tag() + self.debug_tag() + self.version_tag() # FIXME - how to handle different distributions, e.g. for Mac? Currently we handle homebrew and macports, but not fink. def abi_tags(self): if mesonlib.for_windows(self.want_cross, self.env): return [self.versioned_abi_tag(), self.threading_tag()] else: return [self.threading_tag()] def sourceforge_dir(self): if self.env.detect_cpp_compiler(self.want_cross).get_id() != 'msvc': return None comp_ts_version = self.env.detect_cpp_compiler(self.want_cross).get_toolset_version() arch = detect_cpu_family(self.env.coredata.compilers) if arch == 'x86': return 'lib32-msvc-{}'.format(comp_ts_version) elif arch == 'x86_64': return 'lib64-msvc-{}'.format(comp_ts_version) else: # Does anyone do Boost cross-compiling to other archs on Windows? return None def find_libraries_with_abi_tag(self, tag): # All modules should have the same tag self.lib_modules = {} all_found = True for module in self.requested_modules: libname = 'boost_' + module + tag args = self.compiler.find_library(libname, self.env, self.extra_lib_dirs()) if args is None: mlog.debug("Couldn\'t find library '{}' for boost module '{}' (ABI tag = '{}')".format(libname, module, tag)) all_found = False else: mlog.debug('Link args for boost module "{}" are {}'.format(module, args)) self.lib_modules['boost_' + module] = args return all_found def find_libraries_with_abi_tags(self, tags): for tag in tags: if self.find_libraries_with_abi_tag(tag): return True return False def detect_lib_modules_win(self): if not self.libdir: # The libdirs in the distributed binaries (from sf) lib_sf = self.sourceforge_dir() if self.boost_root: roots = [self.boost_root] else: roots = self.boost_roots for root in roots: # The default libdir when building libdir = os.path.join(root, 'lib') if os.path.isdir(libdir): self.libdir = libdir break if lib_sf: full_path = os.path.join(root, lib_sf) if os.path.isdir(full_path): self.libdir = full_path break if not self.libdir: return for name in self.need_static_link: # FIXME - why are we only looking for *.lib? Mingw provides *.dll.a and *.a libname = 'lib' + name + self.versioned_abi_tag() + '.lib' if os.path.isfile(os.path.join(self.libdir, libname)): self.lib_modules[self.modname_from_filename(libname)] = [libname] else: libname = "lib{}.lib".format(name) if os.path.isfile(os.path.join(self.libdir, libname)): self.lib_modules[name[3:]] = [libname] # globber1 applies to a layout=system installation # globber2 applies to a layout=versioned installation globber1 = 'libboost_*' if self.static else 'boost_*' globber2 = globber1 + self.versioned_abi_tag() # FIXME - why are we only looking for *.lib? Mingw provides *.dll.a and *.a globber2_matches = glob.glob(os.path.join(self.libdir, globber2 + '.lib')) for entry in globber2_matches: fname = os.path.basename(entry) self.lib_modules[self.modname_from_filename(fname)] = [fname] if len(globber2_matches) == 0: # FIXME - why are we only looking for *.lib? Mingw provides *.dll.a and *.a for entry in glob.glob(os.path.join(self.libdir, globber1 + '.lib')): if self.static: fname = os.path.basename(entry) self.lib_modules[self.modname_from_filename(fname)] = [fname] def detect_lib_modules_nix(self): if self.static: libsuffix = 'a' elif mesonlib.for_darwin(self.want_cross, self.env): libsuffix = 'dylib' else: libsuffix = 'so' globber = 'libboost_*.{}'.format(libsuffix) if self.libdir: libdirs = [self.libdir] elif self.boost_root is None: libdirs = mesonlib.get_library_dirs() else: libdirs = [os.path.join(self.boost_root, 'lib')] for libdir in libdirs: for name in self.need_static_link: libname = 'lib{}.a'.format(name) if os.path.isfile(os.path.join(libdir, libname)): self.lib_modules[name] = [libname] for entry in glob.glob(os.path.join(libdir, globber)): # I'm not 100% sure what to do here. Some distros # have modules such as thread only as -mt versions. # On debian all packages are built threading=multi # but not suffixed with -mt. # FIXME: implement detect_lib_modules_{debian, redhat, ...} # FIXME: this wouldn't work with -mt-gd either. -BDR if self.is_multithreading and mesonlib.is_debianlike(): pass elif self.is_multithreading and entry.endswith('-mt.{}'.format(libsuffix)): pass elif not entry.endswith('-mt.{}'.format(libsuffix)): pass else: continue modname = self.modname_from_filename(entry) if modname not in self.lib_modules: self.lib_modules[modname] = [entry] def extra_lib_dirs(self): if self.libdir: return [self.libdir] elif self.boost_root: return [os.path.join(self.boost_root, 'lib')] return [] def get_link_args(self): args = [] for dir in self.extra_lib_dirs(): args += self.compiler.get_linker_search_args(dir) for lib in self.requested_modules: args += self.lib_modules['boost_' + lib] return args def get_sources(self): return [] def need_threads(self): return 'thread' in self.requested_modules # Generated with boost_names.py BOOST_LIBS = [ 'boost_atomic', 'boost_chrono', 'boost_chrono', 'boost_container', 'boost_context', 'boost_coroutine', 'boost_date_time', 'boost_exception', 'boost_fiber', 'boost_filesystem', 'boost_graph', 'boost_iostreams', 'boost_locale', 'boost_log', 'boost_log_setup', 'boost_math_tr1', 'boost_math_tr1f', 'boost_math_tr1l', 'boost_math_c99', 'boost_math_c99f', 'boost_math_c99l', 'boost_math_tr1', 'boost_math_tr1f', 'boost_math_tr1l', 'boost_math_c99', 'boost_math_c99f', 'boost_math_c99l', 'boost_math_tr1', 'boost_math_tr1f', 'boost_math_tr1l', 'boost_math_c99', 'boost_math_c99f', 'boost_math_c99l', 'boost_math_tr1', 'boost_math_tr1f', 'boost_math_tr1l', 'boost_math_c99', 'boost_math_c99f', 'boost_math_c99l', 'boost_math_tr1', 'boost_math_tr1f', 'boost_math_tr1l', 'boost_math_c99', 'boost_math_c99f', 'boost_math_c99l', 'boost_math_tr1', 'boost_math_tr1f', 'boost_math_tr1l', 'boost_math_c99', 'boost_math_c99f', 'boost_math_c99l', 'boost_mpi', 'boost_program_options', 'boost_python', 'boost_python3', 'boost_numpy', 'boost_numpy3', 'boost_random', 'boost_regex', 'boost_serialization', 'boost_wserialization', 'boost_signals', 'boost_stacktrace_noop', 'boost_stacktrace_backtrace', 'boost_stacktrace_addr2line', 'boost_stacktrace_basic', 'boost_stacktrace_windbg', 'boost_stacktrace_windbg_cached', 'boost_system', 'boost_prg_exec_monitor', 'boost_test_exec_monitor', 'boost_unit_test_framework', 'boost_thread', 'boost_timer', 'boost_type_erasure', 'boost_wave' ] BOOST_DIRS = [ 'lambda', 'optional', 'convert', 'system', 'uuid', 'archive', 'align', 'timer', 'chrono', 'gil', 'logic', 'signals', 'predef', 'tr1', 'multi_index', 'property_map', 'multi_array', 'context', 'random', 'endian', 'circular_buffer', 'proto', 'assign', 'format', 'math', 'phoenix', 'graph', 'locale', 'mpl', 'pool', 'unordered', 'core', 'exception', 'ptr_container', 'flyweight', 'range', 'typeof', 'thread', 'move', 'spirit', 'dll', 'compute', 'serialization', 'ratio', 'msm', 'config', 'metaparse', 'coroutine2', 'qvm', 'program_options', 'concept', 'detail', 'hana', 'concept_check', 'compatibility', 'variant', 'type_erasure', 'mpi', 'test', 'fusion', 'log', 'sort', 'local_function', 'units', 'functional', 'preprocessor', 'integer', 'container', 'polygon', 'interprocess', 'numeric', 'iterator', 'wave', 'lexical_cast', 'multiprecision', 'utility', 'tti', 'asio', 'dynamic_bitset', 'algorithm', 'xpressive', 'bimap', 'signals2', 'type_traits', 'regex', 'statechart', 'parameter', 'icl', 'python', 'lockfree', 'intrusive', 'io', 'pending', 'geometry', 'tuple', 'iostreams', 'heap', 'atomic', 'filesystem', 'smart_ptr', 'function', 'fiber', 'type_index', 'accumulators', 'function_types', 'coroutine', 'vmd', 'date_time', 'property_tree', 'bind' ] meson-0.45.1/mesonbuild/dependencies/misc.py0000644000175000017500000004770313243342213022420 0ustar jpakkanejpakkane00000000000000# Copyright 2013-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. # This file contains the detection logic for miscellaneous external dependencies. import os import re import shlex import sysconfig from pathlib import Path from .. import mlog from .. import mesonlib from ..environment import detect_cpu_family from .base import ( DependencyException, DependencyMethods, ExternalDependency, ExternalProgram, ExtraFrameworkDependency, PkgConfigDependency, ConfigToolDependency, ) class MPIDependency(ExternalDependency): def __init__(self, environment, kwargs): language = kwargs.get('language', 'c') super().__init__('mpi', environment, language, kwargs) required = kwargs.pop('required', True) kwargs['required'] = False kwargs['silent'] = True self.is_found = False # NOTE: Only OpenMPI supplies a pkg-config file at the moment. if language == 'c': env_vars = ['MPICC'] pkgconfig_files = ['ompi-c'] default_wrappers = ['mpicc'] elif language == 'cpp': env_vars = ['MPICXX'] pkgconfig_files = ['ompi-cxx'] default_wrappers = ['mpic++', 'mpicxx', 'mpiCC'] elif language == 'fortran': env_vars = ['MPIFC', 'MPIF90', 'MPIF77'] pkgconfig_files = ['ompi-fort'] default_wrappers = ['mpifort', 'mpif90', 'mpif77'] else: raise DependencyException('Language {} is not supported with MPI.'.format(language)) for pkg in pkgconfig_files: try: pkgdep = PkgConfigDependency(pkg, environment, kwargs, language=self.language) if pkgdep.found(): self.compile_args = pkgdep.get_compile_args() self.link_args = pkgdep.get_link_args() self.version = pkgdep.get_version() self.is_found = True self.pcdep = pkgdep break except Exception: pass if not self.is_found: # Prefer environment. for var in env_vars: if var in os.environ: wrappers = [os.environ[var]] break else: # Or search for default wrappers. wrappers = default_wrappers for prog in wrappers: result = self._try_openmpi_wrapper(prog) if result is not None: self.is_found = True self.version = result[0] self.compile_args = self._filter_compile_args(result[1]) self.link_args = self._filter_link_args(result[2]) break result = self._try_other_wrapper(prog) if result is not None: self.is_found = True self.version = result[0] self.compile_args = self._filter_compile_args(result[1]) self.link_args = self._filter_link_args(result[2]) break if not self.is_found and mesonlib.is_windows(): result = self._try_msmpi() if result is not None: self.is_found = True self.version, self.compile_args, self.link_args = result if self.is_found: mlog.log('Dependency', mlog.bold(self.name), 'for', self.language, 'found:', mlog.green('YES'), self.version) else: mlog.log('Dependency', mlog.bold(self.name), 'for', self.language, 'found:', mlog.red('NO')) if required: raise DependencyException('MPI dependency {!r} not found'.format(self.name)) def _filter_compile_args(self, args): """ MPI wrappers return a bunch of garbage args. Drop -O2 and everything that is not needed. """ result = [] multi_args = ('-I', ) if self.language == 'fortran': fc = self.env.coredata.compilers['fortran'] multi_args += fc.get_module_incdir_args() include_next = False for f in args: if f.startswith(('-D', '-f') + multi_args) or f == '-pthread' \ or (f.startswith('-W') and f != '-Wall' and not f.startswith('-Werror')): result.append(f) if f in multi_args: # Path is a separate argument. include_next = True elif include_next: include_next = False result.append(f) return result def _filter_link_args(self, args): """ MPI wrappers return a bunch of garbage args. Drop -O2 and everything that is not needed. """ result = [] include_next = False for f in args: if f.startswith(('-L', '-l', '-Xlinker')) or f == '-pthread' \ or (f.startswith('-W') and f != '-Wall' and not f.startswith('-Werror')): result.append(f) if f in ('-L', '-Xlinker'): include_next = True elif include_next: include_next = False result.append(f) return result def _try_openmpi_wrapper(self, prog): prog = ExternalProgram(prog, silent=True) if prog.found(): cmd = prog.get_command() + ['--showme:compile'] p, o, e = mesonlib.Popen_safe(cmd) p.wait() if p.returncode != 0: mlog.debug('Command', mlog.bold(cmd), 'failed to run:') mlog.debug(mlog.bold('Standard output\n'), o) mlog.debug(mlog.bold('Standard error\n'), e) return cargs = shlex.split(o) cmd = prog.get_command() + ['--showme:link'] p, o, e = mesonlib.Popen_safe(cmd) p.wait() if p.returncode != 0: mlog.debug('Command', mlog.bold(cmd), 'failed to run:') mlog.debug(mlog.bold('Standard output\n'), o) mlog.debug(mlog.bold('Standard error\n'), e) return libs = shlex.split(o) cmd = prog.get_command() + ['--showme:version'] p, o, e = mesonlib.Popen_safe(cmd) p.wait() if p.returncode != 0: mlog.debug('Command', mlog.bold(cmd), 'failed to run:') mlog.debug(mlog.bold('Standard output\n'), o) mlog.debug(mlog.bold('Standard error\n'), e) return version = re.search('\d+.\d+.\d+', o) if version: version = version.group(0) else: version = 'none' return version, cargs, libs def _try_other_wrapper(self, prog): prog = ExternalProgram(prog, silent=True) if prog.found(): cmd = prog.get_command() + ['-show'] p, o, e = mesonlib.Popen_safe(cmd) p.wait() if p.returncode != 0: mlog.debug('Command', mlog.bold(cmd), 'failed to run:') mlog.debug(mlog.bold('Standard output\n'), o) mlog.debug(mlog.bold('Standard error\n'), e) return args = shlex.split(o) version = 'none' return version, args, args def _try_msmpi(self): if self.language == 'cpp': # MS-MPI does not support the C++ version of MPI, only the standard C API. return if 'MSMPI_INC' not in os.environ: return incdir = os.environ['MSMPI_INC'] arch = detect_cpu_family(self.env.coredata.compilers) if arch == 'x86': if 'MSMPI_LIB32' not in os.environ: return libdir = os.environ['MSMPI_LIB32'] post = 'x86' elif arch == 'x86_64': if 'MSMPI_LIB64' not in os.environ: return libdir = os.environ['MSMPI_LIB64'] post = 'x64' else: return if self.language == 'fortran': return ('none', ['-I' + incdir, '-I' + os.path.join(incdir, post)], [os.path.join(libdir, 'msmpi.lib'), os.path.join(libdir, 'msmpifec.lib')]) else: return ('none', ['-I' + incdir, '-I' + os.path.join(incdir, post)], [os.path.join(libdir, 'msmpi.lib')]) class ThreadDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('threads', environment, None, {}) self.name = 'threads' self.is_found = True mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.green('YES')) def need_threads(self): return True def get_version(self): return 'unknown' class Python3Dependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('python3', environment, None, kwargs) self.name = 'python3' self.static = kwargs.get('static', False) # We can only be sure that it is Python 3 at this point self.version = '3' self.pkgdep = None if DependencyMethods.PKGCONFIG in self.methods: try: self.pkgdep = PkgConfigDependency('python3', environment, kwargs) if self.pkgdep.found(): self.compile_args = self.pkgdep.get_compile_args() self.link_args = self.pkgdep.get_link_args() self.version = self.pkgdep.get_version() self.is_found = True self.pcdep = self.pkgdep return else: self.pkgdep = None except Exception: pass if not self.is_found: if mesonlib.is_windows() and DependencyMethods.SYSCONFIG in self.methods: self._find_libpy3_windows(environment) elif mesonlib.is_osx() and DependencyMethods.EXTRAFRAMEWORK in self.methods: # In OSX the Python 3 framework does not have a version # number in its name. # There is a python in /System/Library/Frameworks, but that's # python 2, Python 3 will always bin in /Library fw = ExtraFrameworkDependency( 'python', False, '/Library/Frameworks', self.env, self.language, kwargs) if fw.found(): self.compile_args = fw.get_compile_args() self.link_args = fw.get_link_args() self.is_found = True if self.is_found: mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.green('YES')) else: mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.red('NO')) @staticmethod def get_windows_python_arch(): pyplat = sysconfig.get_platform() if pyplat == 'mingw': pycc = sysconfig.get_config_var('CC') if pycc.startswith('x86_64'): return '64' elif pycc.startswith(('i686', 'i386')): return '32' else: mlog.log('MinGW Python built with unknown CC {!r}, please file' 'a bug'.format(pycc)) return None elif pyplat == 'win32': return '32' elif pyplat in ('win64', 'win-amd64'): return '64' mlog.log('Unknown Windows Python platform {!r}'.format(pyplat)) return None def get_windows_link_args(self): pyplat = sysconfig.get_platform() if pyplat.startswith('win'): vernum = sysconfig.get_config_var('py_version_nodot') if self.static: libname = 'libpython{}.a'.format(vernum) else: libname = 'python{}.lib'.format(vernum) lib = Path(sysconfig.get_config_var('base')) / 'libs' / libname elif pyplat == 'mingw': if self.static: libname = sysconfig.get_config_var('LIBRARY') else: libname = sysconfig.get_config_var('LDLIBRARY') lib = Path(sysconfig.get_config_var('LIBDIR')) / libname if not lib.exists(): mlog.log('Could not find Python3 library {!r}'.format(str(lib))) return None return [str(lib)] def _find_libpy3_windows(self, env): ''' Find python3 libraries on Windows and also verify that the arch matches what we are building for. ''' pyarch = self.get_windows_python_arch() if pyarch is None: self.is_found = False return arch = detect_cpu_family(env.coredata.compilers) if arch == 'x86': arch = '32' elif arch == 'x86_64': arch = '64' else: # We can't cross-compile Python 3 dependencies on Windows yet mlog.log('Unknown architecture {!r} for'.format(arch), mlog.bold(self.name)) self.is_found = False return # Pyarch ends in '32' or '64' if arch != pyarch: mlog.log('Need', mlog.bold(self.name), 'for {}-bit, but ' 'found {}-bit'.format(arch, pyarch)) self.is_found = False return # This can fail if the library is not found largs = self.get_windows_link_args() if largs is None: self.is_found = False return self.link_args = largs # Compile args inc = sysconfig.get_path('include') platinc = sysconfig.get_path('platinclude') self.compile_args = ['-I' + inc] if inc != platinc: self.compile_args.append('-I' + platinc) self.version = sysconfig.get_config_var('py_version') self.is_found = True @staticmethod def get_methods(): if mesonlib.is_windows(): return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSCONFIG] elif mesonlib.is_osx(): return [DependencyMethods.PKGCONFIG, DependencyMethods.EXTRAFRAMEWORK] else: return [DependencyMethods.PKGCONFIG] def get_pkgconfig_variable(self, variable_name, kwargs): if self.pkgdep: return self.pkgdep.get_pkgconfig_variable(variable_name, kwargs) else: return super().get_pkgconfig_variable(variable_name, kwargs) class PcapDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('pcap', environment, None, kwargs) @classmethod def _factory(cls, environment, kwargs): methods = cls._process_method_kw(kwargs) if DependencyMethods.PKGCONFIG in methods: try: pcdep = PkgConfigDependency('pcap', environment, kwargs) if pcdep.found(): return pcdep except Exception as e: mlog.debug('Pcap not found via pkgconfig. Trying next, error was:', str(e)) if DependencyMethods.CONFIG_TOOL in methods: try: ctdep = ConfigToolDependency.factory( 'pcap', environment, None, kwargs, ['pcap-config'], 'pcap-config') if ctdep.found(): ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args') ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args') ctdep.version = cls.get_pcap_lib_version(ctdep) return ctdep except Exception as e: mlog.debug('Pcap not found via pcap-config. Trying next, error was:', str(e)) return PcapDependency(environment, kwargs) @staticmethod def get_methods(): if mesonlib.is_osx(): return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK] else: return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL] @staticmethod def get_pcap_lib_version(ctdep): return ctdep.compiler.get_return_value('pcap_lib_version', 'string', '#include ', ctdep.env, [], [ctdep]) class CupsDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('cups', environment, None, kwargs) @classmethod def _factory(cls, environment, kwargs): methods = cls._process_method_kw(kwargs) if DependencyMethods.PKGCONFIG in methods: try: pcdep = PkgConfigDependency('cups', environment, kwargs) if pcdep.found(): return pcdep except Exception as e: mlog.debug('cups not found via pkgconfig. Trying next, error was:', str(e)) if DependencyMethods.CONFIG_TOOL in methods: try: ctdep = ConfigToolDependency.factory( 'cups', environment, None, kwargs, ['cups-config'], 'cups-config') if ctdep.found(): ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args') ctdep.link_args = ctdep.get_config_value(['--ldflags', '--libs'], 'link_args') return ctdep except Exception as e: mlog.debug('cups not found via cups-config. Trying next, error was:', str(e)) if DependencyMethods.EXTRAFRAMEWORK in methods: if mesonlib.is_osx(): fwdep = ExtraFrameworkDependency('cups', False, None, environment, kwargs.get('language', None), kwargs) if fwdep.found(): return fwdep mlog.log('Dependency', mlog.bold('cups'), 'found:', mlog.red('NO')) return CupsDependency(environment, kwargs) @staticmethod def get_methods(): if mesonlib.is_osx(): return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK] else: return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL] class LibWmfDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('libwmf', environment, None, kwargs) @classmethod def _factory(cls, environment, kwargs): methods = cls._process_method_kw(kwargs) if DependencyMethods.PKGCONFIG in methods: try: kwargs['required'] = False pcdep = PkgConfigDependency('libwmf', environment, kwargs) if pcdep.found(): return pcdep except Exception as e: mlog.debug('LibWmf not found via pkgconfig. Trying next, error was:', str(e)) if DependencyMethods.CONFIG_TOOL in methods: try: ctdep = ConfigToolDependency.factory( 'libwmf', environment, None, kwargs, ['libwmf-config'], 'libwmf-config') if ctdep.found(): ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args') ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args') return ctdep except Exception as e: mlog.debug('cups not found via libwmf-config. Trying next, error was:', str(e)) return LibWmfDependency(environment, kwargs) @staticmethod def get_methods(): if mesonlib.is_osx(): return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK] else: return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL] meson-0.45.1/mesonbuild/dependencies/__init__.py0000644000175000017500000000377413243342213023224 0ustar jpakkanejpakkane00000000000000# Copyright 2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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 .boost import BoostDependency from .base import ( # noqa: F401 Dependency, DependencyException, DependencyMethods, ExternalProgram, NonExistingExternalProgram, ExternalDependency, ExternalLibrary, ExtraFrameworkDependency, InternalDependency, PkgConfigDependency, find_external_dependency, get_dep_identifier, packages, _packages_accept_language) from .dev import GMockDependency, GTestDependency, LLVMDependency, ValgrindDependency from .misc import (MPIDependency, Python3Dependency, ThreadDependency, PcapDependency, CupsDependency, LibWmfDependency) from .platform import AppleFrameworks from .ui import GLDependency, GnuStepDependency, Qt4Dependency, Qt5Dependency, SDL2Dependency, WxDependency, VulkanDependency packages.update({ # From dev: 'gtest': GTestDependency, 'gmock': GMockDependency, 'llvm': LLVMDependency, 'valgrind': ValgrindDependency, # From misc: 'boost': BoostDependency, 'mpi': MPIDependency, 'python3': Python3Dependency, 'threads': ThreadDependency, 'pcap': PcapDependency, 'cups': CupsDependency, 'libwmf': LibWmfDependency, # From platform: 'appleframeworks': AppleFrameworks, # From ui: 'gl': GLDependency, 'gnustep': GnuStepDependency, 'qt4': Qt4Dependency, 'qt5': Qt5Dependency, 'sdl2': SDL2Dependency, 'wxwidgets': WxDependency, 'vulkan': VulkanDependency, }) _packages_accept_language.update({ 'mpi', }) meson-0.45.1/mesonbuild/dependencies/ui.py0000644000175000017500000005274213254550710022106 0ustar jpakkanejpakkane00000000000000# Copyright 2013-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. # This file contains the detection logic for external dependencies that # are UI-related. import os import re import shutil import subprocess from collections import OrderedDict from .. import mlog from .. import mesonlib from ..mesonlib import ( MesonException, Popen_safe, extract_as_list, for_windows, version_compare_many ) from ..environment import detect_cpu from .base import DependencyException, DependencyMethods from .base import ExternalDependency, ExternalProgram from .base import ExtraFrameworkDependency, PkgConfigDependency from .base import ConfigToolDependency class GLDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('gl', environment, None, kwargs) if DependencyMethods.SYSTEM in self.methods: if mesonlib.is_osx(): self.is_found = True # FIXME: Use AppleFrameworks dependency self.link_args = ['-framework', 'OpenGL'] # FIXME: Detect version using self.compiler self.version = '1' return if mesonlib.is_windows(): self.is_found = True # FIXME: Use self.compiler.find_library() self.link_args = ['-lopengl32'] # FIXME: Detect version using self.compiler self.version = '1' return @classmethod def _factory(cls, environment, kwargs): if DependencyMethods.PKGCONFIG in cls._process_method_kw(kwargs): try: pcdep = PkgConfigDependency('gl', environment, kwargs) if pcdep.found(): return pcdep except Exception: pass return GLDependency(environment, kwargs) @staticmethod def get_methods(): if mesonlib.is_osx() or mesonlib.is_windows(): return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM] else: return [DependencyMethods.PKGCONFIG] class GnuStepDependency(ConfigToolDependency): tools = ['gnustep-config'] tool_name = 'gnustep-config' def __init__(self, environment, kwargs): super().__init__('gnustep', environment, 'objc', kwargs) if not self.is_found: return self.modules = kwargs.get('modules', []) self.compile_args = self.filter_args( self.get_config_value(['--objc-flags'], 'compile_args')) self.link_args = self.weird_filter(self.get_config_value( ['--gui-libs' if 'gui' in self.modules else '--base-libs'], 'link_args')) def find_config(self, versions=None): tool = self.tools[0] try: p, out = Popen_safe([tool, '--help'])[:2] except (FileNotFoundError, PermissionError): return (None, None) if p.returncode != 0: return (None, None) self.config = tool found_version = self.detect_version() if versions and not version_compare_many(found_version, versions)[0]: return (None, found_version) return (tool, found_version) def weird_filter(self, elems): """When building packages, the output of the enclosing Make is sometimes mixed among the subprocess output. I have no idea why. As a hack filter out everything that is not a flag. """ return [e for e in elems if e.startswith('-')] def filter_args(self, args): """gnustep-config returns a bunch of garbage args such as -O2 and so on. Drop everything that is not needed. """ result = [] for f in args: if f.startswith('-D') \ or f.startswith('-f') \ or f.startswith('-I') \ or f == '-pthread' \ or (f.startswith('-W') and not f == '-Wall'): result.append(f) return result def detect_version(self): gmake = self.get_config_value(['--variable=GNUMAKE'], 'variable')[0] makefile_dir = self.get_config_value(['--variable=GNUSTEP_MAKEFILES'], 'variable')[0] # This Makefile has the GNUStep version set base_make = os.path.join(makefile_dir, 'Additional', 'base.make') # Print the Makefile variable passed as the argument. For instance, if # you run the make target `print-SOME_VARIABLE`, this will print the # value of the variable `SOME_VARIABLE`. printver = "print-%:\n\t@echo '$($*)'" env = os.environ.copy() # See base.make to understand why this is set env['FOUNDATION_LIB'] = 'gnu' p, o, e = Popen_safe([gmake, '-f', '-', '-f', base_make, 'print-GNUSTEP_BASE_VERSION'], env=env, write=printver, stdin=subprocess.PIPE) version = o.strip() if not version: mlog.debug("Couldn't detect GNUStep version, falling back to '1'") # Fallback to setting some 1.x version version = '1' return version class QtBaseDependency(ExternalDependency): def __init__(self, name, env, kwargs): super().__init__(name, env, 'cpp', kwargs) self.qtname = name.capitalize() self.qtver = name[-1] if self.qtver == "4": self.qtpkgname = 'Qt' else: self.qtpkgname = self.qtname self.root = '/usr' self.bindir = None mods = kwargs.get('modules', []) if isinstance(mods, str): mods = [mods] if not mods: raise DependencyException('No ' + self.qtname + ' modules specified.') type_text = 'cross' if env.is_cross_build() else 'native' found_msg = '{} {} {{}} dependency (modules: {}) found:' \ ''.format(self.qtname, type_text, ', '.join(mods)) from_text = 'pkg-config' # Keep track of the detection methods used, for logging purposes. methods = [] # Prefer pkg-config, then fallback to `qmake -query` if DependencyMethods.PKGCONFIG in self.methods: self._pkgconfig_detect(mods, kwargs) methods.append('pkgconfig') if not self.is_found and DependencyMethods.QMAKE in self.methods: from_text = self._qmake_detect(mods, kwargs) methods.append('qmake-' + self.name) methods.append('qmake') if not self.is_found: # Reset compile args and link args self.compile_args = [] self.link_args = [] from_text = '(checked {})'.format(mlog.format_list(methods)) self.version = 'none' if self.required: err_msg = '{} {} dependency not found {}' \ ''.format(self.qtname, type_text, from_text) raise DependencyException(err_msg) if not self.silent: mlog.log(found_msg.format(from_text), mlog.red('NO')) return from_text = '`{}`'.format(from_text) if not self.silent: mlog.log(found_msg.format(from_text), mlog.green('YES')) def compilers_detect(self): "Detect Qt (4 or 5) moc, uic, rcc in the specified bindir or in PATH" if self.bindir: moc = ExternalProgram(os.path.join(self.bindir, 'moc'), silent=True) uic = ExternalProgram(os.path.join(self.bindir, 'uic'), silent=True) rcc = ExternalProgram(os.path.join(self.bindir, 'rcc'), silent=True) lrelease = ExternalProgram(os.path.join(self.bindir, 'lrelease'), silent=True) else: # We don't accept unsuffixed 'moc', 'uic', and 'rcc' because they # are sometimes older, or newer versions. moc = ExternalProgram('moc-' + self.name, silent=True) uic = ExternalProgram('uic-' + self.name, silent=True) rcc = ExternalProgram('rcc-' + self.name, silent=True) lrelease = ExternalProgram('lrelease-' + self.name, silent=True) return moc, uic, rcc, lrelease def _pkgconfig_detect(self, mods, kwargs): # We set the value of required to False so that we can try the # qmake-based fallback if pkg-config fails. kwargs['required'] = False modules = OrderedDict() for module in mods: modules[module] = PkgConfigDependency(self.qtpkgname + module, self.env, kwargs, language=self.language) for m in modules.values(): if not m.found(): self.is_found = False return self.compile_args += m.get_compile_args() self.link_args += m.get_link_args() self.is_found = True self.version = m.version self.pcdep = list(modules.values()) # Try to detect moc, uic, rcc if 'Core' in modules: core = modules['Core'] else: corekwargs = {'required': 'false', 'silent': 'true'} core = PkgConfigDependency(self.qtpkgname + 'Core', self.env, corekwargs, language=self.language) self.pcdep.append(core) # Used by self.compilers_detect() self.bindir = self.get_pkgconfig_host_bins(core) if not self.bindir: # If exec_prefix is not defined, the pkg-config file is broken prefix = core.get_pkgconfig_variable('exec_prefix', {}) if prefix: self.bindir = os.path.join(prefix, 'bin') def _find_qmake(self, qmake): # Even when cross-compiling, if we don't get a cross-info qmake, we # fallback to using the qmake in PATH because that's what we used to do if self.env.is_cross_build(): qmake = self.env.cross_info.config['binaries'].get('qmake', qmake) return ExternalProgram(qmake, silent=True) def _qmake_detect(self, mods, kwargs): for qmake in ('qmake-' + self.name, 'qmake'): self.qmake = self._find_qmake(qmake) if not self.qmake.found(): continue # Check that the qmake is for qt5 pc, stdo = Popen_safe(self.qmake.get_command() + ['-v'])[0:2] if pc.returncode != 0: continue if not 'Qt version ' + self.qtver in stdo: mlog.log('QMake is not for ' + self.qtname) continue # Found qmake for Qt5! break else: # Didn't find qmake :( self.is_found = False return self.version = re.search(self.qtver + '(\.\d+)+', stdo).group(0) # Query library path, header path, and binary path mlog.log("Found qmake:", mlog.bold(self.qmake.get_name()), '(%s)' % self.version) stdo = Popen_safe(self.qmake.get_command() + ['-query'])[1] qvars = {} for line in stdo.split('\n'): line = line.strip() if line == '': continue (k, v) = tuple(line.split(':', 1)) qvars[k] = v if mesonlib.is_osx(): return self._framework_detect(qvars, mods, kwargs) incdir = qvars['QT_INSTALL_HEADERS'] self.compile_args.append('-I' + incdir) libdir = qvars['QT_INSTALL_LIBS'] # Used by self.compilers_detect() self.bindir = self.get_qmake_host_bins(qvars) self.is_found = True for module in mods: mincdir = os.path.join(incdir, 'Qt' + module) self.compile_args.append('-I' + mincdir) if for_windows(self.env.is_cross_build(), self.env): is_debug = self.env.cmd_line_options.buildtype.startswith('debug') dbg = 'd' if is_debug else '' if self.qtver == '4': base_name = 'Qt' + module + dbg + '4' else: base_name = 'Qt5' + module + dbg libfile = os.path.join(libdir, base_name + '.lib') if not os.path.isfile(libfile): # MinGW can link directly to .dll libfile = os.path.join(self.bindir, base_name + '.dll') if not os.path.isfile(libfile): self.is_found = False break else: libfile = os.path.join(libdir, 'lib{}{}.so'.format(self.qtpkgname, module)) if not os.path.isfile(libfile): self.is_found = False break self.link_args.append(libfile) return qmake def _framework_detect(self, qvars, modules, kwargs): libdir = qvars['QT_INSTALL_LIBS'] for m in modules: fname = 'Qt' + m fwdep = ExtraFrameworkDependency(fname, False, libdir, self.env, self.language, kwargs) self.compile_args.append('-F' + libdir) if fwdep.found(): self.is_found = True self.compile_args += fwdep.get_compile_args() self.link_args += fwdep.get_link_args() # Used by self.compilers_detect() self.bindir = self.get_qmake_host_bins(qvars) def get_qmake_host_bins(self, qvars): # Prefer QT_HOST_BINS (qt5, correct for cross and native compiling) # but fall back to QT_INSTALL_BINS (qt4) if 'QT_HOST_BINS' in qvars: return qvars['QT_HOST_BINS'] else: return qvars['QT_INSTALL_BINS'] @staticmethod def get_methods(): return [DependencyMethods.PKGCONFIG, DependencyMethods.QMAKE] def get_exe_args(self, compiler): # Originally this was -fPIE but nowadays the default # for upstream and distros seems to be -reduce-relocations # which requires -fPIC. This may cause a performance # penalty when using self-built Qt or on platforms # where -fPIC is not required. If this is an issue # for you, patches are welcome. return compiler.get_pic_args() class Qt4Dependency(QtBaseDependency): def __init__(self, env, kwargs): QtBaseDependency.__init__(self, 'qt4', env, kwargs) def get_pkgconfig_host_bins(self, core): # Only return one bins dir, because the tools are generally all in one # directory for Qt4, in Qt5, they must all be in one directory. Return # the first one found among the bin variables, in case one tool is not # configured to be built. applications = ['moc', 'uic', 'rcc', 'lupdate', 'lrelease'] for application in applications: try: return os.path.dirname(core.get_pkgconfig_variable('%s_location' % application, {})) except MesonException: pass class Qt5Dependency(QtBaseDependency): def __init__(self, env, kwargs): QtBaseDependency.__init__(self, 'qt5', env, kwargs) def get_pkgconfig_host_bins(self, core): return core.get_pkgconfig_variable('host_bins', {}) # There are three different ways of depending on SDL2: # sdl2-config, pkg-config and OSX framework class SDL2Dependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('sdl2', environment, None, kwargs) @classmethod def _factory(cls, environment, kwargs): methods = cls._process_method_kw(kwargs) if DependencyMethods.PKGCONFIG in methods: try: pcdep = PkgConfigDependency('sdl2', environment, kwargs) if pcdep.found(): return pcdep except Exception as e: mlog.debug('SDL 2 not found via pkgconfig. Trying next, error was:', str(e)) if DependencyMethods.CONFIG_TOOL in methods: try: ctdep = ConfigToolDependency.factory( 'sdl2', environment, None, kwargs, ['sdl2-config'], 'sdl2-config') if ctdep.found(): ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args') ctdep.links_args = ctdep.get_config_value(['--libs'], 'link_args') return ctdep except Exception as e: mlog.debug('SDL 2 not found via sdl2-config. Trying next, error was:', str(e)) if DependencyMethods.EXTRAFRAMEWORK in methods: if mesonlib.is_osx(): fwdep = ExtraFrameworkDependency('sdl2', False, None, environment, kwargs.get('language', None), kwargs) if fwdep.found(): fwdep.version = '2' # FIXME return fwdep mlog.log('Dependency', mlog.bold('sdl2'), 'found:', mlog.red('NO')) return SDL2Dependency(environment, kwargs) @staticmethod def get_methods(): if mesonlib.is_osx(): return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK] else: return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL] class WxDependency(ConfigToolDependency): tools = ['wx-config-3.0', 'wx-config'] tool_name = 'wx-config' def __init__(self, environment, kwargs): super().__init__('WxWidgets', environment, None, kwargs) if not self.is_found: return self.requested_modules = self.get_requested(kwargs) # wx-config seems to have a cflags as well but since it requires C++, # this should be good, at least for now. self.compile_args = self.get_config_value(['--cxxflags'] + self.requested_modules, 'compile_args') self.link_args = self.get_config_value(['--libs'] + self.requested_modules, 'link_args') def get_requested(self, kwargs): if 'modules' not in kwargs: return [] candidates = extract_as_list(kwargs, 'modules') for c in candidates: if not isinstance(c, str): raise DependencyException('wxwidgets module argument is not a string') return candidates class VulkanDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('vulkan', environment, None, kwargs) if DependencyMethods.SYSTEM in self.methods: try: self.vulkan_sdk = os.environ['VULKAN_SDK'] if not os.path.isabs(self.vulkan_sdk): raise DependencyException('VULKAN_SDK must be an absolute path.') except KeyError: self.vulkan_sdk = None if self.vulkan_sdk: # TODO: this config might not work on some platforms, fix bugs as reported # we should at least detect other 64-bit platforms (e.g. armv8) lib_name = 'vulkan' if mesonlib.is_windows(): lib_name = 'vulkan-1' lib_dir = 'Lib32' inc_dir = 'Include' if detect_cpu({}) == 'x86_64': lib_dir = 'Lib' else: lib_name = 'vulkan' lib_dir = 'lib' inc_dir = 'include' # make sure header and lib are valid inc_path = os.path.join(self.vulkan_sdk, inc_dir) header = os.path.join(inc_path, 'vulkan', 'vulkan.h') lib_path = os.path.join(self.vulkan_sdk, lib_dir) find_lib = self.compiler.find_library(lib_name, environment, lib_path) if not find_lib: raise DependencyException('VULKAN_SDK point to invalid directory (no lib)') if not os.path.isfile(header): raise DependencyException('VULKAN_SDK point to invalid directory (no include)') self.type_name = 'vulkan_sdk' self.is_found = True self.compile_args.append('-I' + inc_path) self.link_args.append('-L' + lib_path) self.link_args.append('-l' + lib_name) # TODO: find a way to retrieve the version from the sdk? # Usually it is a part of the path to it (but does not have to be) self.version = '1' return else: # simply try to guess it, usually works on linux libs = self.compiler.find_library('vulkan', environment, []) if libs is not None and self.compiler.has_header('vulkan/vulkan.h', '', environment): self.type_name = 'system' self.is_found = True self.version = 1 # TODO for lib in libs: self.link_args.append(lib) return @classmethod def _factory(cls, environment, kwargs): if DependencyMethods.PKGCONFIG in cls._process_method_kw(kwargs): try: pcdep = PkgConfigDependency('vulkan', environment, kwargs) if pcdep.found(): return pcdep except Exception: pass return VulkanDependency(environment, kwargs) @staticmethod def get_methods(): return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM] meson-0.45.1/mesonbuild/backend/0000755000175000017500000000000013254552745020060 5ustar jpakkanejpakkane00000000000000meson-0.45.1/mesonbuild/backend/vs2015backend.py0000644000175000017500000000150413113247026022665 0ustar jpakkanejpakkane00000000000000# Copyright 2014-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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 .vs2010backend import Vs2010Backend class Vs2015Backend(Vs2010Backend): def __init__(self, build): super().__init__(build) self.name = 'vs2015' self.platform_toolset = 'v140' self.vs_version = '2015' meson-0.45.1/mesonbuild/backend/vs2017backend.py0000644000175000017500000000244213210623121022661 0ustar jpakkanejpakkane00000000000000# Copyright 2014-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os import xml.etree.ElementTree as ET from .vs2010backend import Vs2010Backend class Vs2017Backend(Vs2010Backend): def __init__(self, build): super().__init__(build) self.name = 'vs2017' self.platform_toolset = 'v141' self.vs_version = '2017' # WindowsSDKVersion should be set by command prompt. sdk_version = os.environ.get('WindowsSDKVersion', None) if sdk_version: self.windows_target_platform_version = sdk_version.rstrip('\\') def generate_debug_information(self, link): # valid values for vs2017 is 'false', 'true', 'DebugFastLink', 'DebugFull' ET.SubElement(link, 'GenerateDebugInformation').text = 'DebugFull' meson-0.45.1/mesonbuild/backend/vs2010backend.py0000644000175000017500000017573213254550710022702 0ustar jpakkanejpakkane00000000000000# Copyright 2014-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os, sys import pickle import xml.dom.minidom import xml.etree.ElementTree as ET from . import backends from .. import build from .. import dependencies from .. import mlog from .. import compilers from ..compilers import CompilerArgs from ..mesonlib import MesonException, File, python_command from ..environment import Environment def autodetect_vs_version(build): vs_version = os.getenv('VisualStudioVersion', None) vs_install_dir = os.getenv('VSINSTALLDIR', None) if not vs_install_dir: raise MesonException('Could not detect Visual Studio: Environment variable VSINSTALLDIR is not set!\n' 'Are you running meson from the Visual Studio Developer Command Prompt?') # VisualStudioVersion is set since Visual Studio 12.0, but sometimes # vcvarsall.bat doesn't set it, so also use VSINSTALLDIR if vs_version == '14.0' or 'Visual Studio 14' in vs_install_dir: from mesonbuild.backend.vs2015backend import Vs2015Backend return Vs2015Backend(build) if vs_version == '15.0' or 'Visual Studio 17' in vs_install_dir or \ 'Visual Studio\\2017' in vs_install_dir: from mesonbuild.backend.vs2017backend import Vs2017Backend return Vs2017Backend(build) if 'Visual Studio 10.0' in vs_install_dir: return Vs2010Backend(build) raise MesonException('Could not detect Visual Studio using VisualStudioVersion: {!r} or VSINSTALLDIR: {!r}!\n' 'Please specify the exact backend to use.'.format(vs_version, vs_install_dir)) def split_o_flags_args(args): """ Splits any /O args and returns them. Does not take care of flags overriding previous ones. Skips non-O flag arguments. ['/Ox', '/Ob1'] returns ['/Ox', '/Ob1'] ['/Oxj', '/MP'] returns ['/Ox', '/Oj'] """ o_flags = [] for arg in args: if not arg.startswith('/O'): continue flags = list(arg[2:]) # Assume that this one can't be clumped with the others since it takes # an argument itself if 'b' in flags: o_flags.append(arg) else: o_flags += ['/O' + f for f in flags] return o_flags class RegenInfo: def __init__(self, source_dir, build_dir, depfiles): self.source_dir = source_dir self.build_dir = build_dir self.depfiles = depfiles class Vs2010Backend(backends.Backend): def __init__(self, build): super().__init__(build) self.name = 'vs2010' self.project_file_version = '10.0.30319.1' self.platform_toolset = None self.vs_version = '2010' self.windows_target_platform_version = None def generate_custom_generator_commands(self, target, parent_node): generator_output_files = [] custom_target_include_dirs = [] custom_target_output_files = [] target_private_dir = self.relpath(self.get_target_private_dir(target), self.get_target_dir(target)) down = self.target_to_build_root(target) for genlist in target.get_generated_sources(): if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)): for i in genlist.get_outputs(): # Path to the generated source from the current vcxproj dir via the build root ipath = os.path.join(down, self.get_target_dir(genlist), i) custom_target_output_files.append(ipath) idir = self.relpath(self.get_target_dir(genlist), self.get_target_dir(target)) if idir not in custom_target_include_dirs: custom_target_include_dirs.append(idir) else: generator = genlist.get_generator() exe = generator.get_exe() infilelist = genlist.get_inputs() outfilelist = genlist.get_outputs() source_dir = os.path.join(self.build_to_src, genlist.subdir) exe_arr = self.exe_object_to_cmd_array(exe) idgroup = ET.SubElement(parent_node, 'ItemGroup') for i in range(len(infilelist)): if len(infilelist) == len(outfilelist): sole_output = os.path.join(target_private_dir, outfilelist[i]) else: sole_output = '' curfile = infilelist[i] infilename = os.path.join(down, curfile.rel_to_builddir(self.build_to_src)) base_args = generator.get_arglist(infilename) outfiles_rel = genlist.get_outputs_for(curfile) outfiles = [os.path.join(target_private_dir, of) for of in outfiles_rel] generator_output_files += outfiles args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output) for x in base_args] args = self.replace_outputs(args, target_private_dir, outfiles_rel) args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()) .replace("@BUILD_DIR@", target_private_dir) for x in args] args = [x.replace("@CURRENT_SOURCE_DIR@", source_dir) for x in args] args = [x.replace("@SOURCE_ROOT@", self.environment.get_source_dir()) .replace("@BUILD_ROOT@", self.environment.get_build_dir()) for x in args] args = [x.replace('\\', '/') for x in args] cmd = exe_arr + self.replace_extra_args(args, genlist) if generator.capture: exe_data = self.serialize_executable( cmd[0], cmd[1:], self.environment.get_build_dir(), capture=outfiles[0] ) cmd = self.environment.get_build_command() + ['--internal', 'exe', exe_data] abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) os.makedirs(abs_pdir, exist_ok=True) cbs = ET.SubElement(idgroup, 'CustomBuild', Include=infilename) ET.SubElement(cbs, 'Command').text = ' '.join(self.quote_arguments(cmd)) ET.SubElement(cbs, 'Outputs').text = ';'.join(outfiles) return generator_output_files, custom_target_output_files, custom_target_include_dirs def generate(self, interp): self.interpreter = interp target_machine = self.interpreter.builtin['target_machine'].cpu_family_method(None, None) if target_machine.endswith('64'): # amd64 or x86_64 self.platform = 'x64' elif target_machine == 'x86': # x86 self.platform = 'Win32' elif 'arm' in target_machine.lower(): self.platform = 'ARM' else: raise MesonException('Unsupported Visual Studio platform: ' + target_machine) self.buildtype = self.environment.coredata.get_builtin_option('buildtype') sln_filename = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.sln') projlist = self.generate_projects() self.gen_testproj('RUN_TESTS', os.path.join(self.environment.get_build_dir(), 'RUN_TESTS.vcxproj')) self.gen_regenproj('REGEN', os.path.join(self.environment.get_build_dir(), 'REGEN.vcxproj')) self.generate_solution(sln_filename, projlist) self.generate_regen_info() Vs2010Backend.touch_regen_timestamp(self.environment.get_build_dir()) @staticmethod def get_regen_stampfile(build_dir): return os.path.join(os.path.join(build_dir, Environment.private_dir), 'regen.stamp') @staticmethod def touch_regen_timestamp(build_dir): with open(Vs2010Backend.get_regen_stampfile(build_dir), 'w'): pass def generate_regen_info(self): deps = self.get_regen_filelist() regeninfo = RegenInfo(self.environment.get_source_dir(), self.environment.get_build_dir(), deps) filename = os.path.join(self.environment.get_scratch_dir(), 'regeninfo.dump') with open(filename, 'wb') as f: pickle.dump(regeninfo, f) def get_obj_target_deps(self, obj_list): result = {} for o in obj_list: if isinstance(o, build.ExtractedObjects): result[o.target.get_id()] = o.target return result.items() def get_target_deps(self, t, recursive=False): all_deps = {} for target in t.values(): if isinstance(target, build.CustomTarget): for d in target.get_target_dependencies(): all_deps[d.get_id()] = d elif isinstance(target, build.RunTarget): for d in [target.command] + target.args: if isinstance(d, (build.BuildTarget, build.CustomTarget)): all_deps[d.get_id()] = d elif isinstance(target, build.BuildTarget): for ldep in target.link_targets: all_deps[ldep.get_id()] = ldep for ldep in target.link_whole_targets: all_deps[ldep.get_id()] = ldep for obj_id, objdep in self.get_obj_target_deps(target.objects): all_deps[obj_id] = objdep for gendep in target.get_generated_sources(): if isinstance(gendep, build.CustomTarget): all_deps[gendep.get_id()] = gendep elif isinstance(gendep, build.CustomTargetIndex): all_deps[gendep.target.get_id()] = gendep.target else: gen_exe = gendep.generator.get_exe() if isinstance(gen_exe, build.Executable): all_deps[gen_exe.get_id()] = gen_exe else: raise MesonException('Unknown target type for target %s' % target) if not t or not recursive: return all_deps ret = self.get_target_deps(all_deps, recursive) ret.update(all_deps) return ret def generate_solution(self, sln_filename, projlist): default_projlist = self.get_build_by_default_targets() with open(sln_filename, 'w') as ofile: ofile.write('Microsoft Visual Studio Solution File, Format ' 'Version 11.00\n') ofile.write('# Visual Studio ' + self.vs_version + '\n') prj_templ = 'Project("{%s}") = "%s", "%s", "{%s}"\n' for p in projlist: prj_line = prj_templ % (self.environment.coredata.guid, p[0], p[1], p[2]) ofile.write(prj_line) target = self.build.targets[p[0]] t = {target.get_id(): target} # Get direct deps all_deps = self.get_target_deps(t) # Get recursive deps recursive_deps = self.get_target_deps(t, 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)) ofile.write('EndProjectSection\n') ofile.write('EndProject\n') for dep, target in recursive_deps.items(): if p[0] in default_projlist: default_projlist[dep] = target test_line = prj_templ % (self.environment.coredata.guid, 'RUN_TESTS', 'RUN_TESTS.vcxproj', self.environment.coredata.test_guid) ofile.write(test_line) ofile.write('EndProject\n') regen_line = prj_templ % (self.environment.coredata.guid, 'REGEN', 'REGEN.vcxproj', self.environment.coredata.regen_guid) ofile.write(regen_line) ofile.write('EndProject\n') ofile.write('Global\n') ofile.write('\tGlobalSection(SolutionConfigurationPlatforms) = ' 'preSolution\n') ofile.write('\t\t%s|%s = %s|%s\n' % (self.buildtype, self.platform, self.buildtype, self.platform)) ofile.write('\tEndGlobalSection\n') ofile.write('\tGlobalSection(ProjectConfigurationPlatforms) = ' 'postSolution\n') ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % (self.environment.coredata.regen_guid, self.buildtype, self.platform, self.buildtype, self.platform)) ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' % (self.environment.coredata.regen_guid, self.buildtype, self.platform, self.buildtype, self.platform)) # Create the solution configuration for p in projlist: # Add to the list of projects in this solution ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % (p[2], self.buildtype, self.platform, self.buildtype, self.platform)) if p[0] in default_projlist and \ not isinstance(self.build.targets[p[0]], build.RunTarget): # Add to the list of projects to be built ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' % (p[2], self.buildtype, self.platform, self.buildtype, self.platform)) ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % (self.environment.coredata.test_guid, self.buildtype, self.platform, self.buildtype, self.platform)) ofile.write('\tEndGlobalSection\n') ofile.write('\tGlobalSection(SolutionProperties) = preSolution\n') ofile.write('\t\tHideSolutionNode = FALSE\n') ofile.write('\tEndGlobalSection\n') ofile.write('EndGlobal\n') def generate_projects(self): projlist = [] for name, target in self.build.targets.items(): outdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) fname = name + '.vcxproj' relname = os.path.join(target.subdir, fname) projfile = os.path.join(outdir, fname) uuid = self.environment.coredata.target_guids[name] self.gen_vcxproj(target, projfile, uuid) projlist.append((name, relname, uuid)) return projlist def split_sources(self, srclist): sources = [] headers = [] objects = [] languages = [] for i in srclist: if self.environment.is_header(i): headers.append(i) elif self.environment.is_object(i): objects.append(i) elif self.environment.is_source(i): sources.append(i) lang = self.lang_from_source_file(i) if lang not in languages: languages.append(lang) elif self.environment.is_library(i): pass else: # Everything that is not an object or source file is considered a header. headers.append(i) return sources, headers, objects, languages def target_to_build_root(self, target): if target.subdir == '': return '' directories = os.path.normpath(target.subdir).split(os.sep) return os.sep.join(['..'] * len(directories)) def quote_arguments(self, arr): return ['"%s"' % i for i in arr] def add_project_reference(self, root, include, projid): ig = ET.SubElement(root, 'ItemGroup') pref = ET.SubElement(ig, 'ProjectReference', Include=include) ET.SubElement(pref, 'Project').text = '{%s}' % projid def create_basic_crap(self, target): project_name = target.name root = ET.Element('Project', {'DefaultTargets': "Build", 'ToolsVersion': '4.0', 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) confitems = ET.SubElement(root, 'ItemGroup', {'Label': 'ProjectConfigurations'}) prjconf = ET.SubElement(confitems, 'ProjectConfiguration', {'Include': self.buildtype + '|' + self.platform}) p = ET.SubElement(prjconf, 'Configuration') p.text = self.buildtype pl = ET.SubElement(prjconf, 'Platform') pl.text = self.platform globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals') guidelem = ET.SubElement(globalgroup, 'ProjectGuid') guidelem.text = '{%s}' % self.environment.coredata.test_guid kw = ET.SubElement(globalgroup, 'Keyword') kw.text = self.platform + 'Proj' p = ET.SubElement(globalgroup, 'Platform') p.text = self.platform pname = ET.SubElement(globalgroup, 'ProjectName') pname.text = project_name if self.windows_target_platform_version: ET.SubElement(globalgroup, 'WindowsTargetPlatformVersion').text = self.windows_target_platform_version ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.Default.props') type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration') ET.SubElement(type_config, 'ConfigurationType') ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte' ET.SubElement(type_config, 'UseOfMfc').text = 'false' if self.platform_toolset: ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.props') direlem = ET.SubElement(root, 'PropertyGroup') fver = ET.SubElement(direlem, '_ProjectFileVersion') fver.text = self.project_file_version outdir = ET.SubElement(direlem, 'OutDir') outdir.text = '.\\' intdir = ET.SubElement(direlem, 'IntDir') intdir.text = target.get_id() + '\\' tname = ET.SubElement(direlem, 'TargetName') tname.text = target.name return root def gen_run_target_vcxproj(self, target, ofname, guid): root = self.create_basic_crap(target) action = ET.SubElement(root, 'ItemDefinitionGroup') customstep = ET.SubElement(action, 'PostBuildEvent') cmd_raw = [target.command] + target.args cmd = python_command + \ [os.path.join(self.environment.get_script_dir(), 'commandrunner.py'), self.environment.get_build_dir(), self.environment.get_source_dir(), self.get_target_dir(target)] + self.environment.get_build_command() for i in cmd_raw: if isinstance(i, build.BuildTarget): cmd.append(os.path.join(self.environment.get_build_dir(), self.get_target_filename(i))) elif isinstance(i, dependencies.ExternalProgram): cmd += i.get_command() elif isinstance(i, File): relfname = i.rel_to_builddir(self.build_to_src) cmd.append(os.path.join(self.environment.get_build_dir(), relfname)) else: cmd.append(i) cmd_templ = '''"%s" ''' * len(cmd) ET.SubElement(customstep, 'Command').text = cmd_templ % tuple(cmd) ET.SubElement(customstep, 'Message').text = 'Running custom command.' ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets') self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) def gen_custom_target_vcxproj(self, target, ofname, guid): root = self.create_basic_crap(target) action = ET.SubElement(root, 'ItemDefinitionGroup') customstep = ET.SubElement(action, 'CustomBuildStep') # We need to always use absolute paths because our invocation is always # from the target dir, not the build root. target.absolute_paths = True (srcs, ofilenames, cmd) = self.eval_custom_target_command(target, True) depend_files = self.get_custom_target_depend_files(target, True) # Always use a wrapper because MSBuild eats random characters when # there are many arguments. tdir_abs = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) extra_bdeps = target.get_transitive_build_target_deps() extra_paths = self.determine_windows_extra_paths(target.command[0], extra_bdeps) exe_data = self.serialize_executable(target.command[0], cmd[1:], # All targets run from the target dir tdir_abs, extra_paths=extra_paths, capture=ofilenames[0] if target.capture else None) wrapper_cmd = self.environment.get_build_command() + ['--internal', 'exe', exe_data] ET.SubElement(customstep, 'Command').text = ' '.join(self.quote_arguments(wrapper_cmd)) ET.SubElement(customstep, 'Outputs').text = ';'.join(ofilenames) ET.SubElement(customstep, 'Inputs').text = ';'.join([exe_data] + srcs + depend_files) ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets') self.generate_custom_generator_commands(target, root) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) @classmethod def lang_from_source_file(cls, src): ext = src.split('.')[-1] if ext in compilers.c_suffixes: return 'c' if ext in compilers.cpp_suffixes: return 'cpp' raise MesonException('Could not guess language from source file %s.' % src) def add_pch(self, inc_cl, proj_to_src_dir, pch_sources, source_file): if len(pch_sources) <= 1: # We only need per file precompiled headers if we have more than 1 language. return lang = Vs2010Backend.lang_from_source_file(source_file) header = os.path.join(proj_to_src_dir, pch_sources[lang][0]) pch_file = ET.SubElement(inc_cl, 'PrecompiledHeaderFile') pch_file.text = header pch_include = ET.SubElement(inc_cl, 'ForcedIncludeFiles') pch_include.text = header + ';%(ForcedIncludeFiles)' pch_out = ET.SubElement(inc_cl, 'PrecompiledHeaderOutputFile') pch_out.text = '$(IntDir)$(TargetName)-%s.pch' % lang def add_additional_options(self, lang, parent_node, file_args): args = [] for arg in file_args[lang].to_native(): if arg == '%(AdditionalOptions)': args.append(arg) else: args.append(self.escape_additional_option(arg)) ET.SubElement(parent_node, "AdditionalOptions").text = ' '.join(args) def add_preprocessor_defines(self, lang, parent_node, file_defines): defines = [] for define in file_defines[lang]: if define == '%(PreprocessorDefinitions)': defines.append(define) else: defines.append(self.escape_preprocessor_define(define)) ET.SubElement(parent_node, "PreprocessorDefinitions").text = ';'.join(defines) def add_include_dirs(self, lang, parent_node, file_inc_dirs): dirs = file_inc_dirs[lang] ET.SubElement(parent_node, "AdditionalIncludeDirectories").text = ';'.join(dirs) @staticmethod def has_objects(objects, additional_objects, generated_objects): # Ignore generated objects, those are automatically used by MSBuild because they are part of # the CustomBuild Outputs. return len(objects) + len(additional_objects) > 0 @staticmethod def add_generated_objects(node, generated_objects): # Do not add generated objects to project file. Those are automatically used by MSBuild, because # they are part of the CustomBuild Outputs. return @staticmethod def escape_preprocessor_define(define): # See: https://msdn.microsoft.com/en-us/library/bb383819.aspx table = str.maketrans({'%': '%25', '$': '%24', '@': '%40', "'": '%27', ';': '%3B', '?': '%3F', '*': '%2A', # We need to escape backslash because it'll be un-escaped by # Windows during process creation when it parses the arguments # Basically, this converts `\` to `\\`. '\\': '\\\\'}) return define.translate(table) @staticmethod def escape_additional_option(option): # See: https://msdn.microsoft.com/en-us/library/bb383819.aspx table = str.maketrans({'%': '%25', '$': '%24', '@': '%40', "'": '%27', ';': '%3B', '?': '%3F', '*': '%2A', ' ': '%20'}) option = option.translate(table) # Since we're surrounding the option with ", if it ends in \ that will # escape the " when the process arguments are parsed and the starting # " will not terminate. So we escape it if that's the case. I'm not # kidding, this is how escaping works for process args on Windows. if option.endswith('\\'): option += '\\' return '"{}"'.format(option) @staticmethod def split_link_args(args): """ Split a list of link arguments into three lists: * library search paths * library filenames (or paths) * other link arguments """ lpaths = [] libs = [] other = [] for arg in args: if arg.startswith('/LIBPATH:'): lpath = arg[9:] # De-dup library search paths by removing older entries when # a new one is found. This is necessary because unlike other # search paths such as the include path, the library is # searched for in the newest (right-most) search path first. if lpath in lpaths: lpaths.remove(lpath) lpaths.append(lpath) elif arg.startswith(('/', '-')): other.append(arg) # It's ok if we miss libraries with non-standard extensions here. # They will go into the general link arguments. elif arg.endswith('.lib') or arg.endswith('.a'): # De-dup if arg not in libs: libs.append(arg) else: other.append(arg) return lpaths, libs, other def _get_cl_compiler(self, target): for lang, c in target.compilers.items(): if lang in ('c', 'cpp'): return c # No source files, only objects, but we still need a compiler, so # return a found compiler if len(target.objects) > 0: for lang, c in self.environment.coredata.compilers.items(): if lang in ('c', 'cpp'): return c raise MesonException('Could not find a C or C++ compiler. MSVC can only build C/C++ projects.') def _prettyprint_vcxproj_xml(self, tree, ofname): tree.write(ofname, encoding='utf-8', xml_declaration=True) # ElementTree can not do prettyprinting so do it manually doc = xml.dom.minidom.parse(ofname) with open(ofname, 'w') as of: of.write(doc.toprettyxml()) def gen_vcxproj(self, target, ofname, guid): mlog.debug('Generating vcxproj %s.' % target.name) entrypoint = 'WinMainCRTStartup' subsystem = 'Windows' if isinstance(target, build.Executable): conftype = 'Application' if not target.gui_app: subsystem = 'Console' entrypoint = 'mainCRTStartup' elif isinstance(target, build.StaticLibrary): conftype = 'StaticLibrary' elif isinstance(target, build.SharedLibrary): conftype = 'DynamicLibrary' entrypoint = '_DllMainCrtStartup' elif isinstance(target, build.CustomTarget): return self.gen_custom_target_vcxproj(target, ofname, guid) elif isinstance(target, build.RunTarget): return self.gen_run_target_vcxproj(target, ofname, guid) else: raise MesonException('Unknown target type for %s' % target.get_basename()) # Prefix to use to access the build root from the vcxproj dir down = self.target_to_build_root(target) # Prefix to use to access the source tree's root from the vcxproj dir proj_to_src_root = os.path.join(down, self.build_to_src) # Prefix to use to access the source tree's subdir from the vcxproj dir proj_to_src_dir = os.path.join(proj_to_src_root, target.subdir) (sources, headers, objects, languages) = self.split_sources(target.sources) if self.is_unity(target): sources = self.generate_unity_files(target, sources) compiler = self._get_cl_compiler(target) buildtype_args = compiler.get_buildtype_args(self.buildtype) buildtype_link_args = compiler.get_buildtype_linker_args(self.buildtype) project_name = target.name target_name = target.name root = ET.Element('Project', {'DefaultTargets': "Build", 'ToolsVersion': '4.0', 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) confitems = ET.SubElement(root, 'ItemGroup', {'Label': 'ProjectConfigurations'}) prjconf = ET.SubElement(confitems, 'ProjectConfiguration', {'Include': self.buildtype + '|' + self.platform}) p = ET.SubElement(prjconf, 'Configuration') p.text = self.buildtype pl = ET.SubElement(prjconf, 'Platform') pl.text = self.platform # Globals globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals') guidelem = ET.SubElement(globalgroup, 'ProjectGuid') guidelem.text = '{%s}' % guid kw = ET.SubElement(globalgroup, 'Keyword') kw.text = self.platform + 'Proj' ns = ET.SubElement(globalgroup, 'RootNamespace') ns.text = target_name p = ET.SubElement(globalgroup, 'Platform') p.text = self.platform pname = ET.SubElement(globalgroup, 'ProjectName') pname.text = project_name if self.windows_target_platform_version: ET.SubElement(globalgroup, 'WindowsTargetPlatformVersion').text = self.windows_target_platform_version ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.Default.props') # Start configuration type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration') ET.SubElement(type_config, 'ConfigurationType').text = conftype ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte' if self.platform_toolset: ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset # FIXME: Meson's LTO support needs to be integrated here ET.SubElement(type_config, 'WholeProgramOptimization').text = 'false' # Let VS auto-set the RTC level ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'Default' o_flags = split_o_flags_args(buildtype_args) if '/Oi' in o_flags: ET.SubElement(type_config, 'IntrinsicFunctions').text = 'true' if '/Ob1' in o_flags: ET.SubElement(type_config, 'InlineFunctionExpansion').text = 'OnlyExplicitInline' elif '/Ob2' in o_flags: ET.SubElement(type_config, 'InlineFunctionExpansion').text = 'AnySuitable' # Size-preserving flags if '/Os' in o_flags: ET.SubElement(type_config, 'FavorSizeOrSpeed').text = 'Size' else: ET.SubElement(type_config, 'FavorSizeOrSpeed').text = 'Speed' # Incremental linking increases code size if '/INCREMENTAL:NO' in buildtype_link_args: ET.SubElement(type_config, 'LinkIncremental').text = 'false' # CRT type; debug or release if '/MDd' in buildtype_args: ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' ET.SubElement(type_config, 'RuntimeLibrary').text = 'MultiThreadedDebugDLL' else: ET.SubElement(type_config, 'UseDebugLibraries').text = 'false' ET.SubElement(type_config, 'RuntimeLibrary').text = 'MultiThreadedDLL' # Debug format if '/ZI' in buildtype_args: ET.SubElement(type_config, 'DebugInformationFormat').text = 'EditAndContinue' elif '/Zi' in buildtype_args: ET.SubElement(type_config, 'DebugInformationFormat').text = 'ProgramDatabase' elif '/Z7' in buildtype_args: ET.SubElement(type_config, 'DebugInformationFormat').text = 'OldStyle' # Runtime checks if '/RTC1' in buildtype_args: ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'EnableFastChecks' elif '/RTCu' in buildtype_args: ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'UninitializedLocalUsageCheck' elif '/RTCs' in buildtype_args: ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'StackFrameRuntimeCheck' # Optimization flags if '/Ox' in o_flags: ET.SubElement(type_config, 'Optimization').text = 'Full' elif '/O2' in o_flags: ET.SubElement(type_config, 'Optimization').text = 'MaxSpeed' elif '/O1' in o_flags: ET.SubElement(type_config, 'Optimization').text = 'MinSpace' elif '/Od' in o_flags: ET.SubElement(type_config, 'Optimization').text = 'Disabled' # End configuration ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.props') generated_files, custom_target_output_files, generated_files_include_dirs = self.generate_custom_generator_commands(target, root) (gen_src, gen_hdrs, gen_objs, gen_langs) = self.split_sources(generated_files) (custom_src, custom_hdrs, custom_objs, custom_langs) = self.split_sources(custom_target_output_files) gen_src += custom_src gen_hdrs += custom_hdrs gen_langs += custom_langs # Project information direlem = ET.SubElement(root, 'PropertyGroup') fver = ET.SubElement(direlem, '_ProjectFileVersion') fver.text = self.project_file_version outdir = ET.SubElement(direlem, 'OutDir') outdir.text = '.\\' intdir = ET.SubElement(direlem, 'IntDir') intdir.text = target.get_id() + '\\' tfilename = os.path.splitext(target.get_filename()) ET.SubElement(direlem, 'TargetName').text = tfilename[0] ET.SubElement(direlem, 'TargetExt').text = tfilename[1] # Build information compiles = ET.SubElement(root, 'ItemDefinitionGroup') clconf = ET.SubElement(compiles, 'ClCompile') # Arguments, include dirs, defines for all files in the current target target_args = [] target_defines = [] target_inc_dirs = [] # Arguments, include dirs, defines passed to individual files in # a target; perhaps because the args are language-specific # # file_args is also later split out into defines and include_dirs in # case someone passed those in there file_args = dict((lang, CompilerArgs(comp)) for lang, comp in target.compilers.items()) file_defines = dict((lang, []) for lang in target.compilers) file_inc_dirs = dict((lang, []) for lang in target.compilers) # The order in which these compile args are added must match # generate_single_compile() and generate_basic_compiler_args() for l, comp in target.compilers.items(): if l in file_args: file_args[l] += compilers.get_base_compile_args(self.environment.coredata.base_options, comp) file_args[l] += comp.get_option_compile_args(self.environment.coredata.compiler_options) # Add compile args added using add_project_arguments() for l, args in self.build.projects_args.get(target.subproject, {}).items(): if l in file_args: file_args[l] += args # Add compile args added using add_global_arguments() # These override per-project arguments for l, args in self.build.global_args.items(): if l in file_args: file_args[l] += args if not target.is_cross: # Compile args added from the env: CFLAGS/CXXFLAGS, etc. We want these # to override all the defaults, but not the per-target compile args. for l, args in self.environment.coredata.external_args.items(): if l in file_args: file_args[l] += args for args in file_args.values(): # This is where Visual Studio will insert target_args, target_defines, # etc, which are added later from external deps (see below). args += ['%(AdditionalOptions)', '%(PreprocessorDefinitions)', '%(AdditionalIncludeDirectories)'] # Add custom target dirs as includes automatically, but before # target-specific include dirs. See _generate_single_compile() in # the ninja backend for caveats. args += ['-I' + arg for arg in generated_files_include_dirs] # Add include dirs from the `include_directories:` kwarg on the target # and from `include_directories:` of internal deps of the target. # # Target include dirs should override internal deps include dirs. # This is handled in BuildTarget.process_kwargs() # # Include dirs from internal deps should override include dirs from # external deps and must maintain the order in which they are # specified. Hence, we must reverse so that the order is preserved. # # These are per-target, but we still add them as per-file because we # need them to be looked in first. for d in reversed(target.get_include_dirs()): for i in d.get_incdirs(): curdir = os.path.join(d.get_curdir(), i) args.append('-I' + self.relpath(curdir, target.subdir)) # build dir args.append('-I' + os.path.join(proj_to_src_root, curdir)) # src dir for i in d.get_extra_build_dirs(): curdir = os.path.join(d.get_curdir(), i) args.append('-I' + self.relpath(curdir, target.subdir)) # build dir # Add per-target compile args, f.ex, `c_args : ['/DFOO']`. We set these # near the end since these are supposed to override everything else. for l, args in target.extra_args.items(): if l in file_args: file_args[l] += args # The highest priority includes. In order of directory search: # target private dir, target build dir, target source dir for args in file_args.values(): t_inc_dirs = [self.relpath(self.get_target_private_dir(target), self.get_target_dir(target))] if target.implicit_include_directories: t_inc_dirs += ['.'] if target.implicit_include_directories: t_inc_dirs += [proj_to_src_dir] args += ['-I' + arg for arg in t_inc_dirs] # Split preprocessor defines and include directories out of the list of # all extra arguments. The rest go into %(AdditionalOptions). for l, args in file_args.items(): for arg in args[:]: if arg.startswith(('-D', '/D')) or arg == '%(PreprocessorDefinitions)': file_args[l].remove(arg) # Don't escape the marker if arg == '%(PreprocessorDefinitions)': define = arg else: define = arg[2:] # De-dup if define in file_defines[l]: file_defines[l].remove(define) file_defines[l].append(define) elif arg.startswith(('-I', '/I')) or arg == '%(AdditionalIncludeDirectories)': file_args[l].remove(arg) # Don't escape the marker if arg == '%(AdditionalIncludeDirectories)': inc_dir = arg else: inc_dir = arg[2:] # De-dup if inc_dir not in file_inc_dirs[l]: file_inc_dirs[l].append(inc_dir) # Split compile args needed to find external dependencies # Link args are added while generating the link command for d in reversed(target.get_external_deps()): # Cflags required by external deps might have UNIX-specific flags, # so filter them out if needed d_compile_args = compiler.unix_args_to_native(d.get_compile_args()) for arg in d_compile_args: if arg.startswith(('-D', '/D')): define = arg[2:] # De-dup if define in target_defines: target_defines.remove(define) target_defines.append(define) elif arg.startswith(('-I', '/I')): inc_dir = arg[2:] # De-dup if inc_dir not in target_inc_dirs: target_inc_dirs.append(inc_dir) else: target_args.append(arg) languages += gen_langs if len(target_args) > 0: target_args.append('%(AdditionalOptions)') ET.SubElement(clconf, "AdditionalOptions").text = ' '.join(target_args) target_inc_dirs.append('%(AdditionalIncludeDirectories)') ET.SubElement(clconf, 'AdditionalIncludeDirectories').text = ';'.join(target_inc_dirs) target_defines.append('%(PreprocessorDefinitions)') ET.SubElement(clconf, 'PreprocessorDefinitions').text = ';'.join(target_defines) ET.SubElement(clconf, 'MinimalRebuild').text = 'true' ET.SubElement(clconf, 'FunctionLevelLinking').text = 'true' pch_node = ET.SubElement(clconf, 'PrecompiledHeader') # Warning level warning_level = self.get_option_for_target('warning_level', target) ET.SubElement(clconf, 'WarningLevel').text = 'Level' + str(1 + int(warning_level)) if self.get_option_for_target('werror', target): ET.SubElement(clconf, 'TreatWarningAsError').text = 'true' # Note: SuppressStartupBanner is /NOLOGO and is 'true' by default pch_sources = {} for lang in ['c', 'cpp']: pch = target.get_pch(lang) if not pch: continue pch_node.text = 'Use' if compiler.id == 'msvc': if len(pch) != 2: raise MesonException('MSVC requires one header and one source to produce precompiled headers.') pch_sources[lang] = [pch[0], pch[1], lang] else: # I don't know whether its relevant but let's handle other compilers # used with a vs backend pch_sources[lang] = [pch[0], None, lang] if len(pch_sources) == 1: # If there is only 1 language with precompiled headers, we can use it for the entire project, which # is cleaner than specifying it for each source file. pch_source = list(pch_sources.values())[0] header = os.path.join(proj_to_src_dir, pch_source[0]) pch_file = ET.SubElement(clconf, 'PrecompiledHeaderFile') pch_file.text = header pch_include = ET.SubElement(clconf, 'ForcedIncludeFiles') pch_include.text = header + ';%(ForcedIncludeFiles)' pch_out = ET.SubElement(clconf, 'PrecompiledHeaderOutputFile') pch_out.text = '$(IntDir)$(TargetName)-%s.pch' % pch_source[2] resourcecompile = ET.SubElement(compiles, 'ResourceCompile') ET.SubElement(resourcecompile, 'PreprocessorDefinitions') # Linker options link = ET.SubElement(compiles, 'Link') extra_link_args = CompilerArgs(compiler) # FIXME: Can these buildtype linker args be added as tags in the # vcxproj file (similar to buildtype compiler args) instead of in # AdditionalOptions? extra_link_args += compiler.get_buildtype_linker_args(self.buildtype) # Generate Debug info if self.buildtype.startswith('debug'): self.generate_debug_information(link) if not isinstance(target, build.StaticLibrary): if isinstance(target, build.SharedModule): extra_link_args += compiler.get_std_shared_module_link_args() # Add link args added using add_project_link_arguments() extra_link_args += self.build.get_project_link_args(compiler, target.subproject) # Add link args added using add_global_link_arguments() # These override per-project link arguments extra_link_args += self.build.get_global_link_args(compiler) if not target.is_cross: # Link args added from the env: LDFLAGS. We want these to # override all the defaults but not the per-target link args. extra_link_args += self.environment.coredata.external_link_args[compiler.get_language()] # Only non-static built targets need link args and link dependencies extra_link_args += target.link_args # External deps must be last because target link libraries may depend on them. for dep in target.get_external_deps(): # Extend without reordering or de-dup to preserve `-L -l` sets # https://github.com/mesonbuild/meson/issues/1718 extra_link_args.extend_direct(dep.get_link_args()) for d in target.get_dependencies(): if isinstance(d, build.StaticLibrary): for dep in d.get_external_deps(): extra_link_args.extend_direct(dep.get_link_args()) # Add link args for c_* or cpp_* build options. Currently this only # adds c_winlibs and cpp_winlibs when building for Windows. This needs # to be after all internal and external libraries so that unresolved # symbols from those can be found here. This is needed when the # *_winlibs that we want to link to are static mingw64 libraries. extra_link_args += compiler.get_option_link_args(self.environment.coredata.compiler_options) (additional_libpaths, additional_links, extra_link_args) = self.split_link_args(extra_link_args.to_native()) # Add more libraries to be linked if needed for t in target.get_dependencies(): lobj = self.build.targets[t.get_id()] linkname = os.path.join(down, self.get_target_filename_for_linking(lobj)) if t in target.link_whole_targets: # /WHOLEARCHIVE:foo must go into AdditionalOptions extra_link_args += compiler.get_link_whole_for(linkname) # To force Visual Studio to build this project even though it # has no sources, we include a reference to the vcxproj file # that builds this target. Technically we should add this only # if the current target has no sources, but it doesn't hurt to # have 'extra' references. trelpath = self.get_target_dir_relative_to(t, target) tvcxproj = os.path.join(trelpath, t.get_id() + '.vcxproj') tid = self.environment.coredata.target_guids[t.get_id()] self.add_project_reference(root, tvcxproj, tid) else: # Other libraries go into AdditionalDependencies additional_links.append(linkname) for lib in self.get_custom_target_provided_libraries(target): additional_links.append(self.relpath(lib, self.get_target_dir(target))) additional_objects = [] for o in self.flatten_object_list(target, down): assert(isinstance(o, str)) additional_objects.append(o) for o in custom_objs: additional_objects.append(o) if len(extra_link_args) > 0: extra_link_args.append('%(AdditionalOptions)') ET.SubElement(link, "AdditionalOptions").text = ' '.join(extra_link_args) if len(additional_libpaths) > 0: additional_libpaths.insert(0, '%(AdditionalLibraryDirectories)') ET.SubElement(link, 'AdditionalLibraryDirectories').text = ';'.join(additional_libpaths) if len(additional_links) > 0: additional_links.append('%(AdditionalDependencies)') ET.SubElement(link, 'AdditionalDependencies').text = ';'.join(additional_links) ofile = ET.SubElement(link, 'OutputFile') ofile.text = '$(OutDir)%s' % target.get_filename() subsys = ET.SubElement(link, 'SubSystem') subsys.text = subsystem if (isinstance(target, build.SharedLibrary) or isinstance(target, build.Executable)) and target.get_import_filename(): # DLLs built with MSVC always have an import library except when # they're data-only DLLs, but we don't support those yet. ET.SubElement(link, 'ImportLibrary').text = target.get_import_filename() if isinstance(target, build.SharedLibrary): # Add module definitions file, if provided if target.vs_module_defs: relpath = os.path.join(down, target.vs_module_defs.rel_to_builddir(self.build_to_src)) ET.SubElement(link, 'ModuleDefinitionFile').text = relpath if '/ZI' in buildtype_args or '/Zi' in buildtype_args: pdb = ET.SubElement(link, 'ProgramDataBaseFileName') pdb.text = '$(OutDir}%s.pdb' % target_name if isinstance(target, build.Executable): ET.SubElement(link, 'EntryPointSymbol').text = entrypoint targetmachine = ET.SubElement(link, 'TargetMachine') targetplatform = self.platform.lower() if targetplatform == 'win32': targetmachine.text = 'MachineX86' elif targetplatform == 'x64': targetmachine.text = 'MachineX64' elif targetplatform == 'arm': targetmachine.text = 'MachineARM' else: raise MesonException('Unsupported Visual Studio target machine: ' + targetmachine) extra_files = target.extra_files if len(headers) + len(gen_hdrs) + len(extra_files) > 0: inc_hdrs = ET.SubElement(root, 'ItemGroup') for h in headers: relpath = os.path.join(down, h.rel_to_builddir(self.build_to_src)) ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath) for h in gen_hdrs: ET.SubElement(inc_hdrs, 'CLInclude', Include=h) for h in target.extra_files: relpath = os.path.join(down, h.rel_to_builddir(self.build_to_src)) ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath) if len(sources) + len(gen_src) + len(pch_sources) > 0: inc_src = ET.SubElement(root, 'ItemGroup') for s in sources: relpath = os.path.join(down, s.rel_to_builddir(self.build_to_src)) inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath) lang = Vs2010Backend.lang_from_source_file(s) self.add_pch(inc_cl, proj_to_src_dir, pch_sources, s) self.add_additional_options(lang, inc_cl, file_args) self.add_preprocessor_defines(lang, inc_cl, file_defines) self.add_include_dirs(lang, inc_cl, file_inc_dirs) ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + self.object_filename_from_source(target, s, False) for s in gen_src: inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=s) lang = Vs2010Backend.lang_from_source_file(s) self.add_pch(inc_cl, proj_to_src_dir, pch_sources, s) self.add_additional_options(lang, inc_cl, file_args) self.add_preprocessor_defines(lang, inc_cl, file_defines) self.add_include_dirs(lang, inc_cl, file_inc_dirs) for lang in pch_sources: header, impl, suffix = pch_sources[lang] if impl: relpath = os.path.join(proj_to_src_dir, impl) inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath) pch = ET.SubElement(inc_cl, 'PrecompiledHeader') pch.text = 'Create' pch_out = ET.SubElement(inc_cl, 'PrecompiledHeaderOutputFile') pch_out.text = '$(IntDir)$(TargetName)-%s.pch' % suffix pch_file = ET.SubElement(inc_cl, 'PrecompiledHeaderFile') # MSBuild searches for the header relative from the implementation, so we have to use # just the file name instead of the relative path to the file. pch_file.text = os.path.basename(header) self.add_additional_options(lang, inc_cl, file_args) self.add_preprocessor_defines(lang, inc_cl, file_defines) self.add_include_dirs(lang, inc_cl, file_inc_dirs) if self.has_objects(objects, additional_objects, gen_objs): inc_objs = ET.SubElement(root, 'ItemGroup') for s in objects: relpath = os.path.join(down, s.rel_to_builddir(self.build_to_src)) ET.SubElement(inc_objs, 'Object', Include=relpath) for s in additional_objects: ET.SubElement(inc_objs, 'Object', Include=s) self.add_generated_objects(inc_objs, gen_objs) ET.SubElement(root, 'Import', Project='$(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._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) def gen_regenproj(self, project_name, ofname): root = ET.Element('Project', {'DefaultTargets': 'Build', 'ToolsVersion': '4.0', 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) confitems = ET.SubElement(root, 'ItemGroup', {'Label': 'ProjectConfigurations'}) prjconf = ET.SubElement(confitems, 'ProjectConfiguration', {'Include': self.buildtype + '|' + self.platform}) p = ET.SubElement(prjconf, 'Configuration') p.text = self.buildtype pl = ET.SubElement(prjconf, 'Platform') pl.text = self.platform globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals') guidelem = ET.SubElement(globalgroup, 'ProjectGuid') guidelem.text = '{%s}' % self.environment.coredata.test_guid kw = ET.SubElement(globalgroup, 'Keyword') kw.text = self.platform + 'Proj' p = ET.SubElement(globalgroup, 'Platform') p.text = self.platform pname = ET.SubElement(globalgroup, 'ProjectName') pname.text = project_name if self.windows_target_platform_version: ET.SubElement(globalgroup, 'WindowsTargetPlatformVersion').text = self.windows_target_platform_version ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.Default.props') type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration') ET.SubElement(type_config, 'ConfigurationType').text = "Utility" ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte' ET.SubElement(type_config, 'UseOfMfc').text = 'false' if self.platform_toolset: ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.props') direlem = ET.SubElement(root, 'PropertyGroup') fver = ET.SubElement(direlem, '_ProjectFileVersion') fver.text = self.project_file_version outdir = ET.SubElement(direlem, 'OutDir') outdir.text = '.\\' intdir = ET.SubElement(direlem, 'IntDir') intdir.text = 'regen-temp\\' tname = ET.SubElement(direlem, 'TargetName') tname.text = project_name action = ET.SubElement(root, 'ItemDefinitionGroup') midl = ET.SubElement(action, 'Midl') ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)' ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)' ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h' ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb' ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c' ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c' regen_command = self.environment.get_build_command() + ['--internal', 'regencheck'] private_dir = self.environment.get_scratch_dir() cmd_templ = '''setlocal "%s" "%s" if %%errorlevel%% neq 0 goto :cmEnd :cmEnd endlocal & call :cmErrorLevel %%errorlevel%% & goto :cmDone :cmErrorLevel exit /b %%1 :cmDone if %%errorlevel%% neq 0 goto :VCEnd''' igroup = ET.SubElement(root, 'ItemGroup') rulefile = os.path.join(self.environment.get_scratch_dir(), 'regen.rule') if not os.path.exists(rulefile): with open(rulefile, 'w') as f: f.write("# Meson regen file.") custombuild = ET.SubElement(igroup, 'CustomBuild', Include=rulefile) message = ET.SubElement(custombuild, 'Message') message.text = 'Checking whether solution needs to be regenerated.' ET.SubElement(custombuild, 'Command').text = cmd_templ % \ ('" "'.join(regen_command), private_dir) ET.SubElement(custombuild, 'Outputs').text = Vs2010Backend.get_regen_stampfile(self.environment.get_build_dir()) deps = self.get_regen_filelist() ET.SubElement(custombuild, 'AdditionalInputs').text = ';'.join(deps) ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets') ET.SubElement(root, 'ImportGroup', Label='ExtensionTargets') self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) def gen_testproj(self, target_name, ofname): project_name = target_name root = ET.Element('Project', {'DefaultTargets': "Build", 'ToolsVersion': '4.0', 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) confitems = ET.SubElement(root, 'ItemGroup', {'Label': 'ProjectConfigurations'}) prjconf = ET.SubElement(confitems, 'ProjectConfiguration', {'Include': self.buildtype + '|' + self.platform}) p = ET.SubElement(prjconf, 'Configuration') p.text = self.buildtype pl = ET.SubElement(prjconf, 'Platform') pl.text = self.platform globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals') guidelem = ET.SubElement(globalgroup, 'ProjectGuid') guidelem.text = '{%s}' % self.environment.coredata.test_guid kw = ET.SubElement(globalgroup, 'Keyword') kw.text = self.platform + 'Proj' p = ET.SubElement(globalgroup, 'Platform') p.text = self.platform pname = ET.SubElement(globalgroup, 'ProjectName') pname.text = project_name if self.windows_target_platform_version: ET.SubElement(globalgroup, 'WindowsTargetPlatformVersion').text = self.windows_target_platform_version ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.Default.props') type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration') ET.SubElement(type_config, 'ConfigurationType') ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte' ET.SubElement(type_config, 'UseOfMfc').text = 'false' if self.platform_toolset: ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.props') direlem = ET.SubElement(root, 'PropertyGroup') fver = ET.SubElement(direlem, '_ProjectFileVersion') fver.text = self.project_file_version outdir = ET.SubElement(direlem, 'OutDir') outdir.text = '.\\' intdir = ET.SubElement(direlem, 'IntDir') intdir.text = 'test-temp\\' tname = ET.SubElement(direlem, 'TargetName') tname.text = target_name action = ET.SubElement(root, 'ItemDefinitionGroup') midl = ET.SubElement(action, 'Midl') ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)' ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)' ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h' ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb' ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c' ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c' postbuild = ET.SubElement(action, 'PostBuildEvent') ET.SubElement(postbuild, 'Message') # FIXME: No benchmarks? test_command = self.environment.get_build_command() + ['test', '--no-rebuild'] if not self.environment.coredata.get_builtin_option('stdsplit'): test_command += ['--no-stdsplit'] if self.environment.coredata.get_builtin_option('errorlogs'): test_command += ['--print-errorlogs'] cmd_templ = '''setlocal "%s" if %%errorlevel%% neq 0 goto :cmEnd :cmEnd endlocal & call :cmErrorLevel %%errorlevel%% & goto :cmDone :cmErrorLevel exit /b %%1 :cmDone if %%errorlevel%% neq 0 goto :VCEnd''' self.serialize_tests() ET.SubElement(postbuild, 'Command').text =\ cmd_templ % ('" "'.join(test_command)) ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets') 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' meson-0.45.1/mesonbuild/backend/backends.py0000644000175000017500000012076313254550710022203 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os, pickle, re from .. import build from .. import dependencies from .. import mesonlib from .. import mlog from .. import compilers import json import subprocess from ..mesonlib import MesonException from ..mesonlib import get_compiler_for_source, classify_unity_sources from ..compilers import CompilerArgs from collections import OrderedDict import shlex class CleanTrees: ''' Directories outputted by custom targets that have to be manually cleaned because on Linux `ninja clean` only deletes empty directories. ''' def __init__(self, build_dir, trees): self.build_dir = build_dir self.trees = trees class InstallData: def __init__(self, source_dir, build_dir, prefix, strip_bin, mesonintrospect): self.source_dir = source_dir self.build_dir = build_dir self.prefix = prefix self.strip_bin = strip_bin self.targets = [] self.headers = [] self.man = [] self.data = [] self.po_package_name = '' self.po = [] self.install_scripts = [] self.install_subdirs = [] self.mesonintrospect = mesonintrospect class ExecutableSerialisation: def __init__(self, name, fname, cmd_args, env, is_cross, exe_wrapper, workdir, extra_paths, capture): self.name = name self.fname = fname self.cmd_args = cmd_args self.env = env self.is_cross = is_cross self.exe_runner = exe_wrapper self.workdir = workdir self.extra_paths = extra_paths self.capture = capture class TestSerialisation: def __init__(self, name, project, suite, fname, is_cross_built, exe_wrapper, is_parallel, cmd_args, env, should_fail, timeout, workdir, extra_paths): self.name = name self.project_name = project self.suite = suite self.fname = fname self.is_cross_built = is_cross_built self.exe_runner = exe_wrapper self.is_parallel = is_parallel self.cmd_args = cmd_args self.env = env self.should_fail = should_fail self.timeout = timeout self.workdir = workdir self.extra_paths = extra_paths class OptionProxy: def __init__(self, name, value): self.name = name self.value = value class OptionOverrideProxy: '''Mimic an option list but transparently override selected option values.''' def __init__(self, overrides, *options): self.overrides = overrides self.options = options def __getitem__(self, option_name): for opts in self.options: if option_name in opts: return self._get_override(option_name, opts[option_name]) raise KeyError('Option not found', option_name) def _get_override(self, option_name, base_opt): if option_name in self.overrides: return OptionProxy(base_opt.name, base_opt.validate_value(self.overrides[option_name])) return base_opt # This class contains the basic functionality that is needed by all backends. # Feel free to move stuff in and out of it as you see fit. class Backend: def __init__(self, build): self.build = build self.environment = build.environment self.processed_targets = {} self.build_to_src = os.path.relpath(self.environment.get_source_dir(), self.environment.get_build_dir()) for t in self.build.targets: priv_dirname = self.get_target_private_dir_abs(t) os.makedirs(priv_dirname, exist_ok=True) def get_target_filename(self, t): if isinstance(t, build.CustomTarget): if len(t.get_outputs()) != 1: mlog.warning('custom_target {!r} has more than one output! ' 'Using the first one.'.format(t.name)) filename = t.get_outputs()[0] else: assert(isinstance(t, build.BuildTarget)) filename = t.get_filename() return os.path.join(self.get_target_dir(t), filename) def get_target_filename_abs(self, target): return os.path.join(self.environment.get_build_dir(), self.get_target_filename(target)) def get_builtin_options_for_target(self, target): return OptionOverrideProxy(target.option_overrides, self.environment.coredata.builtins) def get_base_options_for_target(self, target): return OptionOverrideProxy(target.option_overrides, self.environment.coredata.builtins, self.environment.coredata.base_options) def get_compiler_options_for_target(self, target): return OptionOverrideProxy(target.option_overrides, # no code depends on builtins for now self.environment.coredata.compiler_options) def get_option_for_target(self, option_name, target): if option_name in target.option_overrides: override = target.option_overrides[option_name] return self.environment.coredata.validate_option_value(option_name, override) return self.environment.coredata.get_builtin_option(option_name) def get_target_filename_for_linking(self, target): # On some platforms (msvc for instance), the file that is used for # dynamic linking is not the same as the dynamic library itself. This # file is called an import library, and we want to link against that. # On all other platforms, we link to the library directly. if isinstance(target, build.SharedLibrary): link_lib = target.get_import_filename() or target.get_filename() return os.path.join(self.get_target_dir(target), link_lib) elif isinstance(target, build.StaticLibrary): return os.path.join(self.get_target_dir(target), target.get_filename()) elif isinstance(target, build.Executable): if target.import_filename: return os.path.join(self.get_target_dir(target), target.get_import_filename()) else: return None raise AssertionError('BUG: Tried to link to {!r} which is not linkable'.format(target)) def get_target_dir(self, target): if self.environment.coredata.get_builtin_option('layout') == 'mirror': dirname = target.get_subdir() else: dirname = 'meson-out' return dirname def get_target_dir_relative_to(self, t, o): '''Get a target dir relative to another target's directory''' target_dir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(t)) othert_dir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(o)) return os.path.relpath(target_dir, othert_dir) def get_target_source_dir(self, target): # if target dir is empty, avoid extraneous trailing / from os.path.join() target_dir = self.get_target_dir(target) if target_dir: return os.path.join(self.build_to_src, target_dir) return self.build_to_src def get_target_private_dir(self, target): dirname = os.path.join(self.get_target_dir(target), target.get_basename() + target.type_suffix()) return dirname def get_target_private_dir_abs(self, target): dirname = os.path.join(self.environment.get_build_dir(), self.get_target_private_dir(target)) return dirname def get_target_generated_dir(self, target, gensrc, src): """ Takes a BuildTarget, a generator source (CustomTarget or GeneratedList), and a generated source filename. Returns the full path of the generated source relative to the build root """ # CustomTarget generators output to the build dir of the CustomTarget if isinstance(gensrc, (build.CustomTarget, build.CustomTargetIndex)): return os.path.join(self.get_target_dir(gensrc), src) # GeneratedList generators output to the private build directory of the # target that the GeneratedList is used in return os.path.join(self.get_target_private_dir(target), src) def get_unity_source_file(self, target, suffix): osrc = target.name + '-unity.' + suffix return mesonlib.File.from_built_file(self.get_target_private_dir(target), osrc) def generate_unity_files(self, target, unity_src): abs_files = [] result = [] compsrcs = classify_unity_sources(target.compilers.values(), unity_src) def init_language_file(suffix): unity_src = self.get_unity_source_file(target, suffix) outfileabs = unity_src.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) outfileabs_tmp = outfileabs + '.tmp' abs_files.append(outfileabs) outfileabs_tmp_dir = os.path.dirname(outfileabs_tmp) if not os.path.exists(outfileabs_tmp_dir): os.makedirs(outfileabs_tmp_dir) result.append(unity_src) return open(outfileabs_tmp, 'w') # For each language, generate a unity source file and return the list for comp, srcs in compsrcs.items(): with init_language_file(comp.get_default_suffix()) as ofile: for src in srcs: ofile.write('#include<%s>\n' % src) [mesonlib.replace_if_different(x, x + '.tmp') for x in abs_files] return result def relpath(self, todir, fromdir): return os.path.relpath(os.path.join('dummyprefixdir', todir), os.path.join('dummyprefixdir', fromdir)) def flatten_object_list(self, target, proj_dir_to_build_root=''): obj_list = [] for obj in target.get_objects(): if isinstance(obj, str): o = os.path.join(proj_dir_to_build_root, self.build_to_src, target.get_subdir(), obj) obj_list.append(o) elif isinstance(obj, mesonlib.File): obj_list.append(obj.rel_to_builddir(self.build_to_src)) elif isinstance(obj, build.ExtractedObjects): obj_list += self.determine_ext_objs(target, obj, proj_dir_to_build_root) else: raise MesonException('Unknown data type in object list.') return obj_list def serialize_executable(self, exe, cmd_args, workdir, env={}, extra_paths=None, capture=None): import hashlib if extra_paths is None: # The callee didn't check if we needed extra paths, so check it here if mesonlib.is_windows() or mesonlib.is_cygwin(): extra_paths = self.determine_windows_extra_paths(exe, []) else: extra_paths = [] # Can't just use exe.name here; it will likely be run more than once if isinstance(exe, (dependencies.ExternalProgram, build.BuildTarget, build.CustomTarget)): basename = exe.name else: basename = os.path.basename(exe) # Take a digest of the cmd args, env, workdir, and capture. This avoids # collisions and also makes the name deterministic over regenerations # which avoids a rebuild by Ninja because the cmdline stays the same. data = bytes(str(sorted(env.items())) + str(cmd_args) + str(workdir) + str(capture), encoding='utf-8') digest = hashlib.sha1(data).hexdigest() scratch_file = 'meson_exe_{0}_{1}.dat'.format(basename, digest) exe_data = os.path.join(self.environment.get_scratch_dir(), scratch_file) with open(exe_data, 'wb') as f: if isinstance(exe, dependencies.ExternalProgram): exe_cmd = exe.get_command() exe_needs_wrapper = False elif isinstance(exe, (build.BuildTarget, build.CustomTarget)): exe_cmd = [self.get_target_filename_abs(exe)] exe_needs_wrapper = exe.is_cross else: exe_cmd = [exe] exe_needs_wrapper = False is_cross_built = exe_needs_wrapper and \ self.environment.is_cross_build() and \ self.environment.cross_info.need_cross_compiler() and \ self.environment.cross_info.need_exe_wrapper() if is_cross_built: exe_wrapper = self.environment.cross_info.config['binaries'].get('exe_wrapper', None) else: exe_wrapper = None es = ExecutableSerialisation(basename, exe_cmd, cmd_args, env, is_cross_built, exe_wrapper, workdir, extra_paths, capture) pickle.dump(es, f) return exe_data def serialize_tests(self): test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat') with open(test_data, 'wb') as datafile: self.write_test_file(datafile) benchmark_data = os.path.join(self.environment.get_scratch_dir(), 'meson_benchmark_setup.dat') with open(benchmark_data, 'wb') as datafile: self.write_benchmark_file(datafile) return test_data, benchmark_data def determine_linker(self, target): ''' If we're building a static library, there is only one static linker. Otherwise, we query the target for the dynamic linker. ''' if isinstance(target, build.StaticLibrary): if target.is_cross: return self.build.static_cross_linker else: return self.build.static_linker l = target.get_clike_dynamic_linker() if not l: m = "Couldn't determine linker for target {!r}" raise MesonException(m.format(target.name)) return l def rpaths_for_bundled_shared_libraries(self, target): paths = [] for dep in target.external_deps: if isinstance(dep, (dependencies.ExternalLibrary, dependencies.PkgConfigDependency)): la = dep.link_args if len(la) == 1 and os.path.isabs(la[0]): # The only link argument is an absolute path to a library file. libpath = la[0] if libpath.startswith(('/usr/lib', '/lib')): # No point in adding system paths. continue if os.path.splitext(libpath)[1] not in ['.dll', '.lib', '.so']: continue absdir = os.path.dirname(libpath) if absdir.startswith(self.environment.get_source_dir()): rel_to_src = absdir[len(self.environment.get_source_dir()) + 1:] assert not os.path.isabs(rel_to_src), 'rel_to_src: {} is absolute'.format(rel_to_src) paths.append(os.path.join(self.build_to_src, rel_to_src)) else: paths.append(absdir) return paths def determine_rpath_dirs(self, target): link_deps = target.get_all_link_deps() result = [] for ld in link_deps: if ld is target: continue prospective = self.get_target_dir(ld) if prospective not in result: result.append(prospective) for rp in self.rpaths_for_bundled_shared_libraries(target): if rp not in result: result += [rp] return result def object_filename_from_source(self, target, source, is_unity): assert isinstance(source, mesonlib.File) build_dir = self.environment.get_build_dir() rel_src = source.rel_to_builddir(self.build_to_src) if (not self.environment.is_source(rel_src) or self.environment.is_header(rel_src)) and not is_unity: return None # foo.vala files compile down to foo.c and then foo.c.o, not foo.vala.o if rel_src.endswith(('.vala', '.gs')): # See description in generate_vala_compile for this logic. if source.is_built: if os.path.isabs(rel_src): rel_src = rel_src[len(build_dir) + 1:] rel_src = os.path.relpath(rel_src, self.get_target_private_dir(target)) else: rel_src = os.path.basename(rel_src) if is_unity: return 'meson-generated_' + rel_src[:-5] + '.c.' + self.environment.get_object_suffix() # A meson- prefixed directory is reserved; hopefully no-one creates a file name with such a weird prefix. source = 'meson-generated_' + rel_src[:-5] + '.c' elif source.is_built: if os.path.isabs(rel_src): rel_src = rel_src[len(build_dir) + 1:] targetdir = self.get_target_private_dir(target) # A meson- prefixed directory is reserved; hopefully no-one creates a file name with such a weird prefix. source = 'meson-generated_' + os.path.relpath(rel_src, targetdir) else: if os.path.isabs(rel_src): # Not from the source directory; hopefully this doesn't conflict with user's source files. source = os.path.basename(rel_src) else: source = os.path.relpath(os.path.join(build_dir, rel_src), os.path.join(self.environment.get_source_dir(), target.get_subdir())) return source.replace('/', '_').replace('\\', '_') + '.' + self.environment.get_object_suffix() def determine_ext_objs(self, target, extobj, proj_dir_to_build_root): result = [] targetdir = self.get_target_private_dir(extobj.target) # With unity builds, there's just one object that contains all the # sources, and we only support extracting all the objects in this mode, # so just return that. if self.is_unity(target): comp = get_compiler_for_source(extobj.target.compilers.values(), extobj.srclist[0]) # There is a potential conflict here, but it is unlikely that # anyone both enables unity builds and has a file called foo-unity.cpp. osrc = self.get_unity_source_file(extobj.target, comp.get_default_suffix()) objname = self.object_filename_from_source(extobj.target, osrc, True) objname = objname.replace('/', '_').replace('\\', '_') objpath = os.path.join(proj_dir_to_build_root, targetdir, objname) return [objpath] for osrc in extobj.srclist: objname = self.object_filename_from_source(extobj.target, osrc, False) if objname: objpath = os.path.join(proj_dir_to_build_root, targetdir, objname) result.append(objpath) return result def get_pch_include_args(self, compiler, target): args = [] pchpath = self.get_target_private_dir(target) includeargs = compiler.get_include_args(pchpath, False) p = target.get_pch(compiler.get_language()) if p: args += compiler.get_pch_use_args(pchpath, p[0]) return includeargs + args @staticmethod def escape_extra_args(compiler, args): # No extra escaping/quoting needed when not running on Windows if not mesonlib.is_windows(): return args extra_args = [] # Compiler-specific escaping is needed for -D args but not for any others if compiler.get_id() == 'msvc': # MSVC needs escaping when a -D argument ends in \ or \" for arg in args: if arg.startswith('-D') or arg.startswith('/D'): # Without extra escaping for these two, the next character # gets eaten if arg.endswith('\\'): arg += '\\' elif arg.endswith('\\"'): arg = arg[:-2] + '\\\\"' extra_args.append(arg) else: # MinGW GCC needs all backslashes in defines to be doubly-escaped # FIXME: Not sure about Cygwin or Clang for arg in args: if arg.startswith('-D') or arg.startswith('/D'): arg = arg.replace('\\', '\\\\') extra_args.append(arg) return extra_args def generate_basic_compiler_args(self, target, compiler, no_warn_args=False): # Create an empty commands list, and start adding arguments from # various sources in the order in which they must override each other # starting from hard-coded defaults followed by build options and so on. commands = CompilerArgs(compiler) copt_proxy = self.get_compiler_options_for_target(target) # First, the trivial ones that are impossible to override. # # Add -nostdinc/-nostdinc++ if needed; can't be overridden commands += self.get_cross_stdlib_args(target, compiler) # Add things like /NOLOGO or -pipe; usually can't be overridden commands += compiler.get_always_args() # Only add warning-flags by default if the buildtype enables it, and if # we weren't explicitly asked to not emit warnings (for Vala, f.ex) if no_warn_args: commands += compiler.get_no_warn_args() elif self.get_option_for_target('buildtype', target) != 'plain': commands += compiler.get_warn_args(self.get_option_for_target('warning_level', target)) # Add -Werror if werror=true is set in the build options set on the # command-line or default_options inside project(). This only sets the # action to be done for warnings if/when they are emitted, so it's ok # to set it after get_no_warn_args() or get_warn_args(). if self.get_option_for_target('werror', target): commands += compiler.get_werror_args() # Add compile args for c_* or cpp_* build options set on the # command-line or default_options inside project(). commands += compiler.get_option_compile_args(copt_proxy) # Add buildtype args: optimization level, debugging, etc. commands += compiler.get_buildtype_args(self.get_option_for_target('buildtype', target)) # Add compile args added using add_project_arguments() commands += self.build.get_project_args(compiler, target.subproject) # Add compile args added using add_global_arguments() # These override per-project arguments commands += self.build.get_global_args(compiler) if not target.is_cross: # Compile args added from the env: CFLAGS/CXXFLAGS, etc. We want these # to override all the defaults, but not the per-target compile args. commands += self.environment.coredata.external_args[compiler.get_language()] # Always set -fPIC for shared libraries if isinstance(target, build.SharedLibrary): commands += compiler.get_pic_args() # Set -fPIC for static libraries by default unless explicitly disabled if isinstance(target, build.StaticLibrary) and target.pic: commands += compiler.get_pic_args() # Add compile args needed to find external dependencies. Link args are # added while generating the link command. # NOTE: We must preserve the order in which external deps are # specified, so we reverse the list before iterating over it. for dep in reversed(target.get_external_deps()): if not dep.found(): continue if compiler.language == 'vala': if isinstance(dep, dependencies.PkgConfigDependency): if dep.name == 'glib-2.0' and dep.version_reqs is not None: for req in dep.version_reqs: if req.startswith(('>=', '==')): commands += ['--target-glib', req[2:]] break commands += ['--pkg', dep.name] elif isinstance(dep, dependencies.ExternalLibrary): commands += dep.get_link_args('vala') else: commands += dep.get_compile_args() # Qt needs -fPIC for executables # XXX: We should move to -fPIC for all executables if isinstance(target, build.Executable): commands += dep.get_exe_args(compiler) # For 'automagic' deps: Boost and GTest. Also dependency('threads'). # pkg-config puts the thread flags itself via `Cflags:` if dep.need_threads(): commands += compiler.thread_flags(self.environment) # Fortran requires extra include directives. if compiler.language == 'fortran': for lt in target.link_targets: priv_dir = os.path.join(self.get_target_dir(lt), lt.get_basename() + lt.type_suffix()) incflag = compiler.get_include_args(priv_dir, False) commands += incflag return commands def build_target_link_arguments(self, compiler, deps): args = [] for d in deps: if not (d.is_linkable_target()): raise RuntimeError('Tried to link with a non-library target "%s".' % d.get_basename()) d_arg = self.get_target_filename_for_linking(d) if not d_arg: continue if isinstance(compiler, (compilers.LLVMDCompiler, compilers.DmdDCompiler)): d_arg = '-L' + d_arg args.append(d_arg) return args def determine_windows_extra_paths(self, target, extra_bdeps): '''On Windows there is no such thing as an rpath. We must determine all locations of DLLs that this exe links to and return them so they can be used in unit tests.''' result = [] prospectives = [] if isinstance(target, build.Executable): prospectives = target.get_transitive_link_deps() # External deps for deppath in self.rpaths_for_bundled_shared_libraries(target): result.append(os.path.normpath(os.path.join(self.environment.get_build_dir(), deppath))) for bdep in extra_bdeps: prospectives += bdep.get_transitive_link_deps() # Internal deps for ld in prospectives: if ld == '' or ld == '.': continue dirseg = os.path.join(self.environment.get_build_dir(), self.get_target_dir(ld)) if dirseg not in result: result.append(dirseg) return result def write_benchmark_file(self, datafile): self.write_test_serialisation(self.build.get_benchmarks(), datafile) def write_test_file(self, datafile): self.write_test_serialisation(self.build.get_tests(), datafile) def write_test_serialisation(self, tests, datafile): arr = [] for t in tests: exe = t.get_exe() if isinstance(exe, dependencies.ExternalProgram): cmd = exe.get_command() else: cmd = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(t.get_exe()))] is_cross = self.environment.is_cross_build() and \ self.environment.cross_info.need_cross_compiler() and \ self.environment.cross_info.need_exe_wrapper() if isinstance(exe, build.BuildTarget): is_cross = is_cross and exe.is_cross if isinstance(exe, dependencies.ExternalProgram): # E.g. an external verifier or simulator program run on a generated executable. # Can always be run. is_cross = False if is_cross: exe_wrapper = self.environment.cross_info.config['binaries'].get('exe_wrapper', None) else: exe_wrapper = None if mesonlib.is_windows() or mesonlib.is_cygwin(): extra_paths = self.determine_windows_extra_paths(exe, []) else: extra_paths = [] cmd_args = [] for a in t.cmd_args: if hasattr(a, 'held_object'): a = a.held_object if isinstance(a, mesonlib.File): a = os.path.join(self.environment.get_build_dir(), a.rel_to_builddir(self.build_to_src)) cmd_args.append(a) elif isinstance(a, str): cmd_args.append(a) elif isinstance(a, build.Target): cmd_args.append(self.get_target_filename(a)) else: raise MesonException('Bad object in test command.') ts = TestSerialisation(t.get_name(), t.project_name, t.suite, cmd, is_cross, exe_wrapper, t.is_parallel, cmd_args, t.env, t.should_fail, t.timeout, t.workdir, extra_paths) arr.append(ts) pickle.dump(arr, datafile) def generate_depmf_install(self, d): if self.build.dep_manifest_name is None: return ifilename = os.path.join(self.environment.get_build_dir(), 'depmf.json') ofilename = os.path.join(self.environment.get_prefix(), self.build.dep_manifest_name) mfobj = {'type': 'dependency manifest', 'version': '1.0', 'projects': self.build.dep_manifest} with open(ifilename, 'w') as f: f.write(json.dumps(mfobj)) # Copy file from, to, and with mode unchanged d.data.append([ifilename, ofilename, None]) def get_regen_filelist(self): '''List of all files whose alteration means that the build definition needs to be regenerated.''' deps = [os.path.join(self.build_to_src, df) for df in self.interpreter.get_build_def_files()] if self.environment.is_cross_build(): deps.append(os.path.join(self.build_to_src, self.environment.coredata.cross_file)) deps.append('meson-private/coredata.dat') if os.path.exists(os.path.join(self.environment.get_source_dir(), 'meson_options.txt')): deps.append(os.path.join(self.build_to_src, 'meson_options.txt')) for sp in self.build.subprojects.keys(): fname = os.path.join(self.environment.get_source_dir(), sp, 'meson_options.txt') if os.path.isfile(fname): deps.append(os.path.join(self.build_to_src, sp, 'meson_options.txt')) return deps def exe_object_to_cmd_array(self, exe): if self.environment.is_cross_build() and \ self.environment.cross_info.need_exe_wrapper() and \ isinstance(exe, build.BuildTarget) and exe.is_cross: if 'exe_wrapper' not in self.environment.cross_info.config['binaries']: s = 'Can not use target %s as a generator because it is cross-built\n' s += 'and no exe wrapper is defined. You might want to set it to native instead.' s = s % exe.name raise MesonException(s) if isinstance(exe, build.BuildTarget): exe_arr = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(exe))] else: exe_arr = exe.get_command() return exe_arr def replace_extra_args(self, args, genlist): final_args = [] for a in args: if a == '@EXTRA_ARGS@': final_args += genlist.get_extra_args() else: final_args.append(a) return final_args def replace_outputs(self, args, private_dir, output_list): newargs = [] regex = re.compile('@OUTPUT(\d+)@') for arg in args: m = regex.search(arg) while m is not None: index = int(m.group(1)) src = '@OUTPUT%d@' % index arg = arg.replace(src, os.path.join(private_dir, output_list[index])) m = regex.search(arg) newargs.append(arg) return newargs def get_build_by_default_targets(self): result = OrderedDict() # Get all build and custom targets that must be built by default for name, t in self.build.get_targets().items(): if t.build_by_default or t.install or t.build_always: result[name] = t # Get all targets used as test executables and arguments. These must # also be built by default. XXX: Sometime in the future these should be # built only before running tests. for t in self.build.get_tests(): exe = t.exe if hasattr(exe, 'held_object'): exe = exe.held_object if isinstance(exe, (build.CustomTarget, build.BuildTarget)): result[exe.get_id()] = exe for arg in t.cmd_args: if hasattr(arg, 'held_object'): arg = arg.held_object if not isinstance(arg, (build.CustomTarget, build.BuildTarget)): continue result[arg.get_id()] = arg return result def get_custom_target_provided_libraries(self, target): libs = [] for t in target.get_generated_sources(): if not isinstance(t, build.CustomTarget): continue for f in t.get_outputs(): if self.environment.is_library(f): libs.append(os.path.join(self.get_target_dir(t), f)) return libs def is_unity(self, target): optval = self.get_option_for_target('unity', target) if optval == 'on' or (optval == 'subprojects' and target.subproject != ''): return True return False def get_custom_target_sources(self, target): ''' Custom target sources can be of various object types; strings, File, BuildTarget, even other CustomTargets. Returns the path to them relative to the build root directory. ''' srcs = [] for i in target.get_sources(): if hasattr(i, 'held_object'): i = i.held_object if isinstance(i, str): fname = [os.path.join(self.build_to_src, target.subdir, i)] elif isinstance(i, build.BuildTarget): fname = [self.get_target_filename(i)] elif isinstance(i, build.CustomTarget): fname = [os.path.join(self.get_target_dir(i), p) for p in i.get_outputs()] elif isinstance(i, build.GeneratedList): fname = [os.path.join(self.get_target_private_dir(target), p) for p in i.get_outputs()] else: fname = [i.rel_to_builddir(self.build_to_src)] if target.absolute_paths: fname = [os.path.join(self.environment.get_build_dir(), f) for f in fname] srcs += fname return srcs def get_custom_target_depend_files(self, target, absolute_paths=False): deps = [] for i in target.depend_files: if isinstance(i, mesonlib.File): if absolute_paths: deps.append(i.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir())) else: deps.append(i.rel_to_builddir(self.build_to_src)) else: if absolute_paths: deps.append(os.path.join(self.environment.get_source_dir(), target.subdir, i)) else: deps.append(os.path.join(self.build_to_src, target.subdir, i)) return deps 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? source_root = self.build_to_src build_root = '.' outdir = self.get_target_dir(target) if absolute_outputs: source_root = self.environment.get_source_dir() build_root = self.environment.get_source_dir() outdir = os.path.join(self.environment.get_build_dir(), outdir) outputs = [] for i in target.get_outputs(): outputs.append(os.path.join(outdir, i)) inputs = self.get_custom_target_sources(target) # Evaluate the command list cmd = [] for i in target.command: if isinstance(i, build.Executable): cmd += self.exe_object_to_cmd_array(i) continue elif isinstance(i, build.CustomTarget): # GIR scanner will attempt to execute this binary but # it assumes that it is in path, so always give it a full path. tmp = i.get_outputs()[0] i = os.path.join(self.get_target_dir(i), tmp) elif isinstance(i, mesonlib.File): i = i.rel_to_builddir(self.build_to_src) if target.absolute_paths: i = os.path.join(self.environment.get_build_dir(), i) # FIXME: str types are blindly added ignoring 'target.absolute_paths' # because we can't know if they refer to a file or just a string elif not isinstance(i, str): err_msg = 'Argument {0} is of unknown type {1}' raise RuntimeError(err_msg.format(str(i), str(type(i)))) elif '@SOURCE_ROOT@' in i: i = i.replace('@SOURCE_ROOT@', source_root) elif '@BUILD_ROOT@' in i: i = i.replace('@BUILD_ROOT@', build_root) elif '@DEPFILE@' in i: if target.depfile is None: msg = 'Custom target {!r} has @DEPFILE@ but no depfile ' \ 'keyword argument.'.format(target.name) raise MesonException(msg) dfilename = os.path.join(outdir, target.depfile) i = i.replace('@DEPFILE@', dfilename) elif '@PRIVATE_OUTDIR_' in i: match = re.search('@PRIVATE_OUTDIR_(ABS_)?([^/\s*]*)@', i) if not match: msg = 'Custom target {!r} has an invalid argument {!r}' \ ''.format(target.name, i) raise MesonException(msg) source = match.group(0) if match.group(1) is None and not target.absolute_paths: lead_dir = '' else: lead_dir = self.environment.get_build_dir() i = i.replace(source, os.path.join(lead_dir, outdir)) cmd.append(i) # Substitute the rest of the template strings values = mesonlib.get_filenames_templates_dict(inputs, outputs) cmd = mesonlib.substitute_values(cmd, values) # This should not be necessary but removing it breaks # building GStreamer on Windows. The underlying issue # is problems with quoting backslashes on Windows # which is the seventh circle of hell. The downside is # that this breaks custom targets whose command lines # have backslashes. If you try to fix this be sure to # check that it does not break GST. # # The bug causes file paths such as c:\foo to get escaped # into c:\\foo. # # Unfortunately we have not been able to come up with an # isolated test case for this so unless you manage to come up # with one, the only way is to test the building with Gst's # setup. Note this in your MR or ping us and we will get it # fixed. # # https://github.com/mesonbuild/meson/pull/737 cmd = [i.replace('\\', '/') for i in cmd] return inputs, outputs, cmd def run_postconf_scripts(self): env = {'MESON_SOURCE_ROOT': self.environment.get_source_dir(), 'MESON_BUILD_ROOT': self.environment.get_build_dir(), 'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in self.environment.get_build_command() + ['introspect']]), } child_env = os.environ.copy() child_env.update(env) for s in self.build.postconf_scripts: cmd = s['exe'] + s['args'] subprocess.check_call(cmd, env=child_env) meson-0.45.1/mesonbuild/backend/xcodebackend.py0000644000175000017500000011716413254550710023044 0ustar jpakkanejpakkane00000000000000# Copyright 2014-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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 . import backends from .. import build from .. import dependencies from .. import mesonlib import uuid, os, sys from ..mesonlib import MesonException class XCodeBackend(backends.Backend): def __init__(self, build): super().__init__(build) self.name = 'xcode' self.project_uid = self.environment.coredata.guid.replace('-', '')[:24] self.project_conflist = self.gen_id() self.indent = ' ' self.indent_level = 0 self.xcodetypemap = {'c': 'sourcecode.c.c', 'a': 'archive.ar', 'cc': 'sourcecode.cpp.cpp', 'cxx': 'sourcecode.cpp.cpp', 'cpp': 'sourcecode.cpp.cpp', 'c++': 'sourcecode.cpp.cpp', 'm': 'sourcecode.c.objc', 'mm': 'sourcecode.cpp.objcpp', 'h': 'sourcecode.c.h', 'hpp': 'sourcecode.cpp.h', 'hxx': 'sourcecode.cpp.h', 'hh': 'sourcecode.cpp.hh', 'inc': 'sourcecode.c.h', 'dylib': 'compiled.mach-o.dylib', 'o': 'compiled.mach-o.objfile', } self.maingroup_id = self.gen_id() self.all_id = self.gen_id() self.all_buildconf_id = self.gen_id() self.buildtypes = ['debug'] self.test_id = self.gen_id() self.test_command_id = self.gen_id() self.test_buildconf_id = self.gen_id() def gen_id(self): return str(uuid.uuid4()).upper().replace('-', '')[:24] def get_target_dir(self, target): dirname = os.path.join(target.get_subdir(), self.environment.coredata.get_builtin_option('buildtype')) os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) return dirname def write_line(self, text): self.ofile.write(self.indent * self.indent_level + text) if not text.endswith('\n'): self.ofile.write('\n') def generate(self, interp): self.interpreter = interp test_data = self.serialize_tests()[0] self.generate_filemap() self.generate_buildmap() self.generate_buildstylemap() self.generate_build_phase_map() self.generate_build_configuration_map() self.generate_build_configurationlist_map() self.generate_project_configurations_map() self.generate_buildall_configurations_map() self.generate_test_configurations_map() self.generate_native_target_map() self.generate_native_frameworks_map() self.generate_source_phase_map() self.generate_target_dependency_map() self.generate_pbxdep_map() self.generate_containerproxy_map() self.proj_dir = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.xcodeproj') os.makedirs(self.proj_dir, exist_ok=True) self.proj_file = os.path.join(self.proj_dir, 'project.pbxproj') with open(self.proj_file, 'w') as self.ofile: self.generate_prefix() self.generate_pbx_aggregate_target() self.generate_pbx_build_file() self.generate_pbx_build_style() self.generate_pbx_container_item_proxy() self.generate_pbx_file_reference() self.generate_pbx_frameworks_buildphase() self.generate_pbx_group() self.generate_pbx_native_target() self.generate_pbx_project() self.generate_pbx_shell_build_phase(test_data) self.generate_pbx_sources_build_phase() self.generate_pbx_target_dependency() self.generate_xc_build_configuration() self.generate_xc_configurationList() self.generate_suffix() def get_xcodetype(self, fname): return self.xcodetypemap[fname.split('.')[-1]] def generate_filemap(self): self.filemap = {} # Key is source file relative to src root. self.target_filemap = {} for name, t in self.build.targets.items(): for s in t.sources: if isinstance(s, mesonlib.File): s = os.path.join(s.subdir, s.fname) self.filemap[s] = self.gen_id() for o in t.objects: if isinstance(o, str): o = os.path.join(t.subdir, o) self.filemap[o] = self.gen_id() self.target_filemap[name] = self.gen_id() def generate_buildmap(self): self.buildmap = {} for t in self.build.targets.values(): for s in t.sources: s = os.path.join(s.subdir, s.fname) self.buildmap[s] = self.gen_id() for o in t.objects: o = os.path.join(t.subdir, o) if isinstance(o, str): self.buildmap[o] = self.gen_id() def generate_buildstylemap(self): self.buildstylemap = {'debug': self.gen_id()} def generate_build_phase_map(self): for tname, t in self.build.targets.items(): # generate id for our own target-name t.buildphasemap = {} t.buildphasemap[tname] = self.gen_id() # each target can have it's own Frameworks/Sources/..., generate id's for those t.buildphasemap['Frameworks'] = self.gen_id() t.buildphasemap['Resources'] = self.gen_id() t.buildphasemap['Sources'] = self.gen_id() def generate_build_configuration_map(self): self.buildconfmap = {} for t in self.build.targets: bconfs = {'debug': self.gen_id()} self.buildconfmap[t] = bconfs def generate_project_configurations_map(self): self.project_configurations = {'debug': self.gen_id()} def generate_buildall_configurations_map(self): self.buildall_configurations = {'debug': self.gen_id()} def generate_test_configurations_map(self): self.test_configurations = {'debug': self.gen_id()} def generate_build_configurationlist_map(self): self.buildconflistmap = {} for t in self.build.targets: self.buildconflistmap[t] = self.gen_id() def generate_native_target_map(self): self.native_targets = {} for t in self.build.targets: self.native_targets[t] = self.gen_id() def generate_native_frameworks_map(self): self.native_frameworks = {} self.native_frameworks_fileref = {} for t in self.build.targets.values(): for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: self.native_frameworks[f] = self.gen_id() self.native_frameworks_fileref[f] = self.gen_id() def generate_target_dependency_map(self): self.target_dependency_map = {} for tname, t in self.build.targets.items(): for target in t.link_targets: self.target_dependency_map[(tname, target.get_basename())] = self.gen_id() def generate_pbxdep_map(self): self.pbx_dep_map = {} for t in self.build.targets: self.pbx_dep_map[t] = self.gen_id() def generate_containerproxy_map(self): self.containerproxy_map = {} for t in self.build.targets: self.containerproxy_map[t] = self.gen_id() def generate_source_phase_map(self): self.source_phase = {} for t in self.build.targets: self.source_phase[t] = self.gen_id() def generate_pbx_aggregate_target(self): self.ofile.write('\n/* Begin PBXAggregateTarget section */\n') self.write_line('%s /* ALL_BUILD */ = {' % self.all_id) self.indent_level += 1 self.write_line('isa = PBXAggregateTarget;') self.write_line('buildConfigurationList = %s;' % self.all_buildconf_id) self.write_line('buildPhases = (') self.write_line(');') self.write_line('dependencies = (') self.indent_level += 1 for t in self.build.targets: self.write_line('%s /* PBXTargetDependency */,' % self.pbx_dep_map[t]) self.indent_level -= 1 self.write_line(');') self.write_line('name = ALL_BUILD;') self.write_line('productName = ALL_BUILD;') self.indent_level -= 1 self.write_line('};') self.write_line('%s /* RUN_TESTS */ = {' % self.test_id) self.indent_level += 1 self.write_line('isa = PBXAggregateTarget;') self.write_line('buildConfigurationList = %s;' % self.test_buildconf_id) self.write_line('buildPhases = (') self.indent_level += 1 self.write_line('%s /* test run command */,' % self.test_command_id) self.indent_level -= 1 self.write_line(');') self.write_line('dependencies = (') self.write_line(');') self.write_line('name = RUN_TESTS;') self.write_line('productName = RUN_TESTS;') self.indent_level -= 1 self.write_line('};') self.ofile.write('/* End PBXAggregateTarget section */\n') def generate_pbx_build_file(self): self.ofile.write('\n/* Begin PBXBuildFile section */\n') templ = '%s /* %s */ = { isa = PBXBuildFile; fileRef = %s /* %s */; settings = { COMPILER_FLAGS = "%s"; }; };\n' otempl = '%s /* %s */ = { isa = PBXBuildFile; fileRef = %s /* %s */;};\n' for t in self.build.targets.values(): for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: self.ofile.write('%s /* %s.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = %s /* %s.framework */; };\n' % (self.native_frameworks[f], f, self.native_frameworks_fileref[f], f)) for s in t.sources: if isinstance(s, mesonlib.File): s = s.fname if isinstance(s, str): s = os.path.join(t.subdir, s) idval = self.buildmap[s] fullpath = os.path.join(self.environment.get_source_dir(), s) fileref = self.filemap[s] fullpath2 = fullpath compiler_args = '' self.ofile.write(templ % (idval, fullpath, fileref, fullpath2, compiler_args)) for o in t.objects: o = os.path.join(t.subdir, o) idval = self.buildmap[o] fileref = self.filemap[o] fullpath = os.path.join(self.environment.get_source_dir(), o) fullpath2 = fullpath self.ofile.write(otempl % (idval, fullpath, fileref, fullpath2)) self.ofile.write('/* End PBXBuildFile section */\n') def generate_pbx_build_style(self): self.ofile.write('\n/* Begin PBXBuildStyle section */\n') for name, idval in self.buildstylemap.items(): self.write_line('%s /* %s */ = {\n' % (idval, name)) self.indent_level += 1 self.write_line('isa = PBXBuildStyle;\n') self.write_line('buildSettings = {\n') self.indent_level += 1 self.write_line('COPY_PHASE_STRIP = NO;\n') self.indent_level -= 1 self.write_line('};\n') self.write_line('name = "%s";\n' % name) self.indent_level -= 1 self.write_line('};\n') self.ofile.write('/* End PBXBuildStyle section */\n') def generate_pbx_container_item_proxy(self): self.ofile.write('\n/* Begin PBXContainerItemProxy section */\n') for t in self.build.targets: self.write_line('%s /* PBXContainerItemProxy */ = {' % self.containerproxy_map[t]) self.indent_level += 1 self.write_line('isa = PBXContainerItemProxy;') self.write_line('containerPortal = %s /* Project object */;' % self.project_uid) self.write_line('proxyType = 1;') self.write_line('remoteGlobalIDString = %s;' % self.native_targets[t]) self.write_line('remoteInfo = "%s";' % t) self.indent_level -= 1 self.write_line('};') self.ofile.write('/* End PBXContainerItemProxy section */\n') def generate_pbx_file_reference(self): self.ofile.write('\n/* Begin PBXFileReference section */\n') for t in self.build.targets.values(): for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: self.ofile.write('%s /* %s.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = %s.framework; path = System/Library/Frameworks/%s.framework; sourceTree = SDKROOT; };\n' % (self.native_frameworks_fileref[f], f, f, f)) src_templ = '%s /* %s */ = { isa = PBXFileReference; explicitFileType = "%s"; fileEncoding = 4; name = "%s"; path = "%s"; sourceTree = SOURCE_ROOT; };\n' for fname, idval in self.filemap.items(): fullpath = os.path.join(self.environment.get_source_dir(), fname) xcodetype = self.get_xcodetype(fname) name = os.path.basename(fname) path = fname self.ofile.write(src_templ % (idval, fullpath, xcodetype, name, path)) target_templ = '%s /* %s */ = { isa = PBXFileReference; explicitFileType = "%s"; path = %s; refType = %d; sourceTree = BUILT_PRODUCTS_DIR; };\n' for tname, idval in self.target_filemap.items(): t = self.build.targets[tname] fname = t.get_filename() reftype = 0 if isinstance(t, build.Executable): typestr = 'compiled.mach-o.executable' path = fname elif isinstance(t, build.SharedLibrary): typestr = self.get_xcodetype('dummy.dylib') path = fname else: typestr = self.get_xcodetype(fname) path = '"%s"' % t.get_filename() self.ofile.write(target_templ % (idval, tname, typestr, path, reftype)) self.ofile.write('/* End PBXFileReference section */\n') def generate_pbx_frameworks_buildphase(self): for tname, t in self.build.targets.items(): self.ofile.write('\n/* Begin PBXFrameworksBuildPhase section */\n') self.indent_level += 1 self.write_line('%s /* %s */ = {\n' % (t.buildphasemap['Frameworks'], 'Frameworks')) self.indent_level += 1 self.write_line('isa = PBXFrameworksBuildPhase;\n') self.write_line('buildActionMask = %s;\n' % (2147483647)) self.write_line('files = (\n') self.indent_level += 1 for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: self.write_line('%s /* %s.framework in Frameworks */,\n' % (self.native_frameworks[f], f)) self.indent_level -= 1 self.write_line(');\n') self.write_line('runOnlyForDeploymentPostprocessing = 0;\n') self.indent_level -= 1 self.write_line('};\n') self.ofile.write('/* End PBXFrameworksBuildPhase section */\n') def generate_pbx_group(self): groupmap = {} target_src_map = {} for t in self.build.targets: groupmap[t] = self.gen_id() target_src_map[t] = self.gen_id() self.ofile.write('\n/* Begin PBXGroup section */\n') sources_id = self.gen_id() resources_id = self.gen_id() products_id = self.gen_id() frameworks_id = self.gen_id() self.write_line('%s = {' % self.maingroup_id) self.indent_level += 1 self.write_line('isa = PBXGroup;') self.write_line('children = (') self.indent_level += 1 self.write_line('%s /* Sources */,' % sources_id) self.write_line('%s /* Resources */,' % resources_id) self.write_line('%s /* Products */,' % products_id) self.write_line('%s /* Frameworks */,' % frameworks_id) self.indent_level -= 1 self.write_line(');') self.write_line('sourceTree = "";') self.indent_level -= 1 self.write_line('};') # Sources self.write_line('%s /* Sources */ = {' % sources_id) self.indent_level += 1 self.write_line('isa = PBXGroup;') self.write_line('children = (') self.indent_level += 1 for t in self.build.targets: self.write_line('%s /* %s */,' % (groupmap[t], t)) self.indent_level -= 1 self.write_line(');') self.write_line('name = Sources;') self.write_line('sourcetree = "";') self.indent_level -= 1 self.write_line('};') self.write_line('%s /* Resources */ = {' % resources_id) self.indent_level += 1 self.write_line('isa = PBXGroup;') self.write_line('children = (') self.write_line(');') self.write_line('name = Resources;') self.write_line('sourceTree = "";') self.indent_level -= 1 self.write_line('};') self.write_line('%s /* Frameworks */ = {' % frameworks_id) self.indent_level += 1 self.write_line('isa = PBXGroup;') self.write_line('children = (') # write frameworks self.indent_level += 1 for t in self.build.targets.values(): for dep in t.get_external_deps(): if isinstance(dep, dependencies.AppleFrameworks): for f in dep.frameworks: self.write_line('%s /* %s.framework */,\n' % (self.native_frameworks_fileref[f], f)) self.indent_level -= 1 self.write_line(');') self.write_line('name = Frameworks;') self.write_line('sourceTree = "";') self.indent_level -= 1 self.write_line('};') # Targets for t in self.build.targets: self.write_line('%s /* %s */ = {' % (groupmap[t], t)) self.indent_level += 1 self.write_line('isa = PBXGroup;') self.write_line('children = (') self.indent_level += 1 self.write_line('%s /* Source files */,' % target_src_map[t]) self.indent_level -= 1 self.write_line(');') self.write_line('name = "%s";' % t) self.write_line('sourceTree = "";') self.indent_level -= 1 self.write_line('};') self.write_line('%s /* Source files */ = {' % target_src_map[t]) self.indent_level += 1 self.write_line('isa = PBXGroup;') self.write_line('children = (') self.indent_level += 1 for s in self.build.targets[t].sources: s = os.path.join(s.subdir, s.fname) if isinstance(s, str): self.write_line('%s /* %s */,' % (self.filemap[s], s)) for o in self.build.targets[t].objects: o = os.path.join(self.build.targets[t].subdir, o) self.write_line('%s /* %s */,' % (self.filemap[o], o)) self.indent_level -= 1 self.write_line(');') self.write_line('name = "Source files";') self.write_line('sourceTree = "";') self.indent_level -= 1 self.write_line('};') # And finally products self.write_line('%s /* Products */ = {' % products_id) self.indent_level += 1 self.write_line('isa = PBXGroup;') self.write_line('children = (') self.indent_level += 1 for t in self.build.targets: self.write_line('%s /* %s */,' % (self.target_filemap[t], t)) self.indent_level -= 1 self.write_line(');') self.write_line('name = Products;') self.write_line('sourceTree = "";') self.indent_level -= 1 self.write_line('};') self.ofile.write('/* End PBXGroup section */\n') def generate_pbx_native_target(self): self.ofile.write('\n/* Begin PBXNativeTarget section */\n') for tname, idval in self.native_targets.items(): t = self.build.targets[tname] self.write_line('%s /* %s */ = {' % (idval, tname)) self.indent_level += 1 self.write_line('isa = PBXNativeTarget;') self.write_line('buildConfigurationList = %s /* Build configuration list for PBXNativeTarget "%s" */;' % (self.buildconflistmap[tname], tname)) self.write_line('buildPhases = (') self.indent_level += 1 for bpname, bpval in t.buildphasemap.items(): self.write_line('%s /* %s yyy */,' % (bpval, bpname)) self.indent_level -= 1 self.write_line(');') self.write_line('buildRules = (') self.write_line(');') self.write_line('dependencies = (') self.indent_level += 1 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()] self.write_line('%s /* PBXTargetDependency */,' % idval) self.indent_level -= 1 self.write_line(");") self.write_line('name = "%s";' % tname) self.write_line('productName = "%s";' % tname) self.write_line('productReference = %s /* %s */;' % (self.target_filemap[tname], tname)) if isinstance(t, build.Executable): typestr = 'com.apple.product-type.tool' elif isinstance(t, build.StaticLibrary): typestr = 'com.apple.product-type.library.static' elif isinstance(t, build.SharedLibrary): typestr = 'com.apple.product-type.library.dynamic' else: raise MesonException('Unknown target type for %s' % tname) self.write_line('productType = "%s";' % typestr) self.indent_level -= 1 self.write_line('};') self.ofile.write('/* End PBXNativeTarget section */\n') def generate_pbx_project(self): self.ofile.write('\n/* Begin PBXProject section */\n') self.write_line('%s /* Project object */ = {' % self.project_uid) self.indent_level += 1 self.write_line('isa = PBXProject;') self.write_line('attributes = {') self.indent_level += 1 self.write_line('BuildIndependentTargetsInParallel = YES;') self.indent_level -= 1 self.write_line('};') conftempl = 'buildConfigurationList = %s /* build configuration list for PBXProject "%s"*/;' self.write_line(conftempl % (self.project_conflist, self.build.project_name)) self.write_line('buildSettings = {') self.write_line('};') self.write_line('buildStyles = (') self.indent_level += 1 for name, idval in self.buildstylemap.items(): self.write_line('%s /* %s */,' % (idval, name)) self.indent_level -= 1 self.write_line(');') self.write_line('compatibilityVersion = "Xcode 3.2";') self.write_line('hasScannedForEncodings = 0;') self.write_line('mainGroup = %s;' % self.maingroup_id) self.write_line('projectDirPath = "%s";' % self.build_to_src) self.write_line('projectRoot = "";') self.write_line('targets = (') self.indent_level += 1 self.write_line('%s /* ALL_BUILD */,' % self.all_id) self.write_line('%s /* RUN_TESTS */,' % self.test_id) for t in self.build.targets: self.write_line('%s /* %s */,' % (self.native_targets[t], t)) self.indent_level -= 1 self.write_line(');') self.indent_level -= 1 self.write_line('};') self.ofile.write('/* End PBXProject section */\n') def generate_pbx_shell_build_phase(self, test_data): self.ofile.write('\n/* Begin PBXShellScriptBuildPhase section */\n') self.write_line('%s = {' % self.test_command_id) self.indent_level += 1 self.write_line('isa = PBXShellScriptBuildPhase;') self.write_line('buildActionMask = 2147483647;') self.write_line('files = (') self.write_line(');') self.write_line('inputPaths = (') self.write_line(');') self.write_line('outputPaths = (') self.write_line(');') self.write_line('runOnlyForDeploymentPostprocessing = 0;') self.write_line('shellPath = /bin/sh;') script_root = self.environment.get_script_dir() test_script = os.path.join(script_root, 'meson_test.py') cmd = mesonlib.python_command + [test_script, test_data, '--wd', self.environment.get_build_dir()] cmdstr = ' '.join(["'%s'" % i for i in cmd]) self.write_line('shellScript = "%s";' % cmdstr) self.write_line('showEnvVarsInLog = 0;') self.indent_level -= 1 self.write_line('};') self.ofile.write('/* End PBXShellScriptBuildPhase section */\n') def generate_pbx_sources_build_phase(self): self.ofile.write('\n/* Begin PBXSourcesBuildPhase section */\n') for name, phase_id in self.source_phase.items(): t = self.build.targets[name] self.write_line('%s /* Sources */ = {' % (t.buildphasemap[name])) self.indent_level += 1 self.write_line('isa = PBXSourcesBuildPhase;') self.write_line('buildActionMask = 2147483647;') self.write_line('files = (') self.indent_level += 1 for s in self.build.targets[name].sources: s = os.path.join(s.subdir, s.fname) if not self.environment.is_header(s): self.write_line('%s /* %s */,' % (self.buildmap[s], os.path.join(self.environment.get_source_dir(), s))) self.indent_level -= 1 self.write_line(');') self.write_line('runOnlyForDeploymentPostprocessing = 0;') self.indent_level -= 1 self.write_line('};') self.ofile.write('/* End PBXSourcesBuildPhase section */\n') def generate_pbx_target_dependency(self): self.ofile.write('\n/* Begin PBXTargetDependency section */\n') for t in self.build.targets: idval = self.pbx_dep_map[t] # VERIFY: is this correct? self.write_line('%s /* PBXTargetDependency */ = {' % idval) self.indent_level += 1 self.write_line('isa = PBXTargetDependency;') self.write_line('target = %s /* %s */;' % (self.native_targets[t], t)) self.write_line('targetProxy = %s /* PBXContainerItemProxy */;' % self.containerproxy_map[t]) self.indent_level -= 1 self.write_line('};') self.ofile.write('/* End PBXTargetDependency section */\n') def generate_xc_build_configuration(self): self.ofile.write('\n/* Begin XCBuildConfiguration section */\n') # First the setup for the toplevel project. for buildtype in self.buildtypes: self.write_line('%s /* %s */ = {' % (self.project_configurations[buildtype], buildtype)) self.indent_level += 1 self.write_line('isa = XCBuildConfiguration;') self.write_line('buildSettings = {') self.indent_level += 1 self.write_line('ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";') self.write_line('ONLY_ACTIVE_ARCH = YES;') self.write_line('SDKROOT = "macosx";') self.write_line('SYMROOT = "%s/build";' % self.environment.get_build_dir()) self.indent_level -= 1 self.write_line('};') self.write_line('name = "%s";' % buildtype) self.indent_level -= 1 self.write_line('};') # Then the all target. for buildtype in self.buildtypes: self.write_line('%s /* %s */ = {' % (self.buildall_configurations[buildtype], buildtype)) self.indent_level += 1 self.write_line('isa = XCBuildConfiguration;') self.write_line('buildSettings = {') self.indent_level += 1 self.write_line('COMBINE_HIDPI_IMAGES = YES;') self.write_line('GCC_GENERATE_DEBUGGING_SYMBOLS = NO;') self.write_line('GCC_INLINES_ARE_PRIVATE_EXTERN = NO;') self.write_line('GCC_OPTIMIZATION_LEVEL = 0;') self.write_line('GCC_PREPROCESSOR_DEFINITIONS = ("");') self.write_line('GCC_SYMBOLS_PRIVATE_EXTERN = NO;') self.write_line('INSTALL_PATH = "";') self.write_line('OTHER_CFLAGS = " ";') self.write_line('OTHER_LDFLAGS = " ";') self.write_line('OTHER_REZFLAGS = "";') self.write_line('PRODUCT_NAME = ALL_BUILD;') self.write_line('SECTORDER_FLAGS = "";') self.write_line('SYMROOT = "%s";' % self.environment.get_build_dir()) self.write_line('USE_HEADERMAP = NO;') self.write_line('WARNING_CFLAGS = ("-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", );') self.indent_level -= 1 self.write_line('};') self.write_line('name = "%s";' % buildtype) self.indent_level -= 1 self.write_line('};') # Then the test target. for buildtype in self.buildtypes: self.write_line('%s /* %s */ = {' % (self.test_configurations[buildtype], buildtype)) self.indent_level += 1 self.write_line('isa = XCBuildConfiguration;') self.write_line('buildSettings = {') self.indent_level += 1 self.write_line('COMBINE_HIDPI_IMAGES = YES;') self.write_line('GCC_GENERATE_DEBUGGING_SYMBOLS = NO;') self.write_line('GCC_INLINES_ARE_PRIVATE_EXTERN = NO;') self.write_line('GCC_OPTIMIZATION_LEVEL = 0;') self.write_line('GCC_PREPROCESSOR_DEFINITIONS = ("");') self.write_line('GCC_SYMBOLS_PRIVATE_EXTERN = NO;') self.write_line('INSTALL_PATH = "";') self.write_line('OTHER_CFLAGS = " ";') self.write_line('OTHER_LDFLAGS = " ";') self.write_line('OTHER_REZFLAGS = "";') self.write_line('PRODUCT_NAME = RUN_TESTS;') self.write_line('SECTORDER_FLAGS = "";') self.write_line('SYMROOT = "%s";' % self.environment.get_build_dir()) self.write_line('USE_HEADERMAP = NO;') self.write_line('WARNING_CFLAGS = ("-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", );') self.indent_level -= 1 self.write_line('};') self.write_line('name = "%s";' % buildtype) self.indent_level -= 1 self.write_line('};') # Now finally targets. langnamemap = {'c': 'C', 'cpp': 'CPLUSPLUS', 'objc': 'OBJC', 'objcpp': 'OBJCPLUSPLUS'} for target_name, target in self.build.targets.items(): for buildtype in self.buildtypes: dep_libs = [] links_dylib = False headerdirs = [] for d in target.include_dirs: for sd in d.incdirs: cd = os.path.join(d.curdir, sd) headerdirs.append(os.path.join(self.environment.get_source_dir(), cd)) headerdirs.append(os.path.join(self.environment.get_build_dir(), cd)) for l in target.link_targets: abs_path = os.path.join(self.environment.get_build_dir(), l.subdir, buildtype, l.get_filename()) dep_libs.append("'%s'" % abs_path) if isinstance(l, build.SharedLibrary): links_dylib = True if links_dylib: dep_libs = ['-Wl,-search_paths_first', '-Wl,-headerpad_max_install_names'] + dep_libs dylib_version = None if isinstance(target, build.SharedLibrary): ldargs = ['-dynamiclib', '-Wl,-headerpad_max_install_names'] + dep_libs install_path = os.path.join(self.environment.get_build_dir(), target.subdir, buildtype) dylib_version = target.version else: ldargs = dep_libs install_path = '' if dylib_version is not None: product_name = target.get_basename() + '.' + dylib_version else: product_name = target.get_basename() ldargs += target.link_args ldstr = ' '.join(ldargs) valid = self.buildconfmap[target_name][buildtype] langargs = {} for lang in self.environment.coredata.compilers: if lang not in langnamemap: continue gargs = self.build.global_args.get(lang, []) targs = target.get_extra_args(lang) args = gargs + targs if len(args) > 0: langargs[langnamemap[lang]] = args symroot = os.path.join(self.environment.get_build_dir(), target.subdir) self.write_line('%s /* %s */ = {' % (valid, buildtype)) self.indent_level += 1 self.write_line('isa = XCBuildConfiguration;') self.write_line('buildSettings = {') self.indent_level += 1 self.write_line('COMBINE_HIDPI_IMAGES = YES;') if dylib_version is not None: self.write_line('DYLIB_CURRENT_VERSION = "%s";' % dylib_version) self.write_line('EXECUTABLE_PREFIX = "%s";' % target.prefix) if target.suffix == '': suffix = '' else: suffix = '.' + target.suffix self.write_line('EXECUTABLE_SUFFIX = "%s";' % suffix) self.write_line('GCC_GENERATE_DEBUGGING_SYMBOLS = YES;') self.write_line('GCC_INLINES_ARE_PRIVATE_EXTERN = NO;') self.write_line('GCC_OPTIMIZATION_LEVEL = 0;') self.write_line('GCC_PREPROCESSOR_DEFINITIONS = ("");') self.write_line('GCC_SYMBOLS_PRIVATE_EXTERN = NO;') if len(headerdirs) > 0: quotedh = ','.join(['"\\"%s\\""' % i for i in headerdirs]) self.write_line('HEADER_SEARCH_PATHS=(%s);' % quotedh) self.write_line('INSTALL_PATH = "%s";' % install_path) self.write_line('LIBRARY_SEARCH_PATHS = "";') if isinstance(target, build.SharedLibrary): self.write_line('LIBRARY_STYLE = DYNAMIC;') for langname, args in langargs.items(): argstr = ' '.join(args) self.write_line('OTHER_%sFLAGS = "%s";' % (langname, argstr)) self.write_line('OTHER_LDFLAGS = "%s";' % ldstr) self.write_line('OTHER_REZFLAGS = "";') self.write_line('PRODUCT_NAME = %s;' % product_name) self.write_line('SECTORDER_FLAGS = "";') self.write_line('SYMROOT = "%s";' % symroot) self.write_line('USE_HEADERMAP = NO;') self.write_line('WARNING_CFLAGS = ("-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", );') self.indent_level -= 1 self.write_line('};') self.write_line('name = "%s";' % buildtype) self.indent_level -= 1 self.write_line('};') self.ofile.write('/* End XCBuildConfiguration section */\n') def generate_xc_configurationList(self): self.ofile.write('\n/* Begin XCConfigurationList section */\n') self.write_line('%s /* Build configuration list for PBXProject "%s" */ = {' % (self.project_conflist, self.build.project_name)) self.indent_level += 1 self.write_line('isa = XCConfigurationList;') self.write_line('buildConfigurations = (') self.indent_level += 1 for buildtype in self.buildtypes: self.write_line('%s /* %s */,' % (self.project_configurations[buildtype], buildtype)) self.indent_level -= 1 self.write_line(');') self.write_line('defaultConfigurationIsVisible = 0;') self.write_line('defaultConfigurationName = debug;') self.indent_level -= 1 self.write_line('};') # Now the all target self.write_line('%s /* Build configuration list for PBXAggregateTarget "ALL_BUILD" */ = {' % self.all_buildconf_id) self.indent_level += 1 self.write_line('isa = XCConfigurationList;') self.write_line('buildConfigurations = (') self.indent_level += 1 for buildtype in self.buildtypes: self.write_line('%s /* %s */,' % (self.buildall_configurations[buildtype], buildtype)) self.indent_level -= 1 self.write_line(');') self.write_line('defaultConfigurationIsVisible = 0;') self.write_line('defaultConfigurationName = debug;') self.indent_level -= 1 self.write_line('};') # Test target self.write_line('%s /* Build configuration list for PBXAggregateTarget "ALL_BUILD" */ = {' % self.test_buildconf_id) self.indent_level += 1 self.write_line('isa = XCConfigurationList;') self.write_line('buildConfigurations = (') self.indent_level += 1 for buildtype in self.buildtypes: self.write_line('%s /* %s */,' % (self.test_configurations[buildtype], buildtype)) self.indent_level -= 1 self.write_line(');') self.write_line('defaultConfigurationIsVisible = 0;') self.write_line('defaultConfigurationName = debug;') self.indent_level -= 1 self.write_line('};') for target_name in self.build.targets: listid = self.buildconflistmap[target_name] self.write_line('%s /* Build configuration list for PBXNativeTarget "%s" */ = {' % (listid, target_name)) self.indent_level += 1 self.write_line('isa = XCConfigurationList;') self.write_line('buildConfigurations = (') self.indent_level += 1 typestr = 'debug' idval = self.buildconfmap[target_name][typestr] self.write_line('%s /* %s */,' % (idval, typestr)) self.indent_level -= 1 self.write_line(');') self.write_line('defaultConfigurationIsVisible = 0;') self.write_line('defaultConfigurationName = "%s";' % typestr) self.indent_level -= 1 self.write_line('};') self.ofile.write('/* End XCConfigurationList section */\n') def generate_prefix(self): self.ofile.write('// !$*UTF8*$!\n{\n') self.indent_level += 1 self.write_line('archiveVersion = 1;\n') self.write_line('classes = {\n') self.write_line('};\n') self.write_line('objectVersion = 46;\n') self.write_line('objects = {\n') self.indent_level += 1 def generate_suffix(self): self.indent_level -= 1 self.write_line('};\n') self.write_line('rootObject = ' + self.project_uid + ';') self.indent_level -= 1 self.write_line('}\n') meson-0.45.1/mesonbuild/backend/__init__.py0000644000175000017500000000000012650745767022166 0ustar jpakkanejpakkane00000000000000meson-0.45.1/mesonbuild/backend/ninjabackend.py0000644000175000017500000040533413254550710023040 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os, pickle, re, shlex, subprocess from collections import OrderedDict from pathlib import PurePath from . import backends from .. import modules from .. import environment, mesonlib from .. import build from .. import mlog from .. import dependencies from .. import compilers from ..compilers import CompilerArgs from ..linkers import ArLinker from ..mesonlib import File, MesonException, OrderedSet from ..mesonlib import get_compiler_for_source from .backends import CleanTrees, InstallData from ..build import InvalidArguments if mesonlib.is_windows(): quote_func = lambda s: '"{}"'.format(s) execute_wrapper = 'cmd /c' rmfile_prefix = 'del /f /s /q {} &&' else: quote_func = shlex.quote execute_wrapper = '' rmfile_prefix = 'rm -f {} &&' def ninja_quote(text, is_build_line=False): if is_build_line: qcs = ('$', ' ', ':') else: qcs = ('$', ' ') for char in qcs: text = text.replace(char, '$' + char) if '\n' in text: errmsg = '''Ninja does not support newlines in rules. The content was: %s Please report this error with a test case to the Meson bug tracker.''' % text raise MesonException(errmsg) return text class NinjaBuildElement: def __init__(self, all_outputs, outfilenames, rule, infilenames): if isinstance(outfilenames, str): self.outfilenames = [outfilenames] else: self.outfilenames = outfilenames assert(isinstance(rule, str)) self.rule = rule if isinstance(infilenames, str): self.infilenames = [infilenames] else: self.infilenames = infilenames self.deps = set() self.orderdeps = set() self.elems = [] self.all_outputs = all_outputs def add_dep(self, dep): if isinstance(dep, list): self.deps.update(dep) else: self.deps.add(dep) def add_orderdep(self, dep): if isinstance(dep, list): self.orderdeps.update(dep) else: self.orderdeps.add(dep) def add_item(self, name, elems): if isinstance(elems, str): elems = [elems] self.elems.append((name, elems)) def write(self, outfile): self.check_outputs() line = 'build %s: %s %s' % (' '.join([ninja_quote(i, True) for i in self.outfilenames]), self.rule, ' '.join([ninja_quote(i, True) for i in self.infilenames])) if len(self.deps) > 0: line += ' | ' + ' '.join([ninja_quote(x, True) for x in self.deps]) if len(self.orderdeps) > 0: line += ' || ' + ' '.join([ninja_quote(x, True) for x in self.orderdeps]) line += '\n' # This is the only way I could find to make this work on all # platforms including Windows command shell. Slash is a dir separator # on Windows, too, so all characters are unambiguous and, more importantly, # do not require quoting, unless explicitely specified, which is necessary for # the csc compiler. line = line.replace('\\', '/') outfile.write(line) # All the entries that should remain unquoted raw_names = {'DEPFILE', 'DESC', 'pool', 'description'} for e in self.elems: (name, elems) = e should_quote = name not in raw_names line = ' %s = ' % name newelems = [] for i in elems: if not should_quote or i == '&&': # Hackety hack hack quoter = ninja_quote else: quoter = lambda x: ninja_quote(quote_func(x)) i = i.replace('\\', '\\\\') if quote_func('') == '""': i = i.replace('"', '\\"') newelems.append(quoter(i)) line += ' '.join(newelems) line += '\n' outfile.write(line) outfile.write('\n') def check_outputs(self): for n in self.outfilenames: if n in self.all_outputs: raise MesonException('Multiple producers for Ninja target "%s". Please rename your targets.' % n) self.all_outputs[n] = True class NinjaBackend(backends.Backend): def __init__(self, build): super().__init__(build) self.name = 'ninja' self.ninja_filename = 'build.ninja' self.target_arg_cache = {} self.fortran_deps = {} self.all_outputs = {} def create_target_alias(self, to_target, outfile): # We need to use aliases for targets that might be used as directory # names to workaround a Ninja bug that breaks `ninja -t clean`. # This is used for 'reserved' targets such as 'test', 'install', # 'benchmark', etc, and also for RunTargets. # https://github.com/mesonbuild/meson/issues/1644 if not to_target.startswith('meson-'): m = 'Invalid usage of create_target_alias with {!r}' raise AssertionError(m.format(to_target)) from_target = to_target[len('meson-'):] elem = NinjaBuildElement(self.all_outputs, from_target, 'phony', to_target) elem.write(outfile) def detect_vs_dep_prefix(self, tempfilename): '''VS writes its dependency in a locale dependent format. Detect the search prefix to use.''' for compiler in self.build.compilers.values(): # Have to detect the dependency format if compiler.id == 'msvc': break else: # None of our compilers are MSVC, we're done. return open(tempfilename, 'a') filename = os.path.join(self.environment.get_scratch_dir(), 'incdetect.c') with open(filename, 'w') as f: f.write('''#include int dummy; ''') # The output of cl dependency information is language # and locale dependent. Any attempt at converting it to # Python strings leads to failure. We _must_ do this detection # in raw byte mode and write the result in raw bytes. pc = subprocess.Popen(['cl', '/showIncludes', '/c', 'incdetect.c'], cwd=self.environment.get_scratch_dir(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdo, _) = pc.communicate() # We want to match 'Note: including file: ' in the line # 'Note: including file: d:\MyDir\include\stdio.h', however # different locales have different messages with a different # number of colons. Match up to the the drive name 'd:\'. matchre = re.compile(rb"^(.*\s)[a-zA-Z]:\\.*stdio.h$") for line in stdo.split(b'\r\n'): match = matchre.match(line) if match: with open(tempfilename, 'ab') as binfile: binfile.write(b'msvc_deps_prefix = ' + match.group(1) + b'\n') return open(tempfilename, 'a') raise MesonException('Could not determine vs dep dependency prefix string.') def generate(self, interp): self.interpreter = interp self.ninja_command = environment.detect_ninja(log=True) if self.ninja_command is None: raise MesonException('Could not detect Ninja v1.5 or newer') outfilename = os.path.join(self.environment.get_build_dir(), self.ninja_filename) tempfilename = outfilename + '~' with open(tempfilename, 'w') as outfile: outfile.write('# This is the build file for project "%s"\n' % self.build.get_project()) outfile.write('# It is autogenerated by the Meson build system.\n') outfile.write('# Do not edit by hand.\n\n') outfile.write('ninja_required_version = 1.5.1\n\n') with self.detect_vs_dep_prefix(tempfilename) as outfile: self.generate_rules(outfile) self.generate_phony(outfile) outfile.write('# Build rules for targets\n\n') for t in self.build.get_targets().values(): self.generate_target(t, outfile) outfile.write('# Test rules\n\n') self.generate_tests(outfile) outfile.write('# Install rules\n\n') self.generate_install(outfile) self.generate_dist(outfile) if 'b_coverage' in self.environment.coredata.base_options and \ self.environment.coredata.base_options['b_coverage'].value: outfile.write('# Coverage rules\n\n') self.generate_coverage_rules(outfile) outfile.write('# Suffix\n\n') self.generate_utils(outfile) self.generate_ending(outfile) # Only overwrite the old build file after the new one has been # fully created. os.replace(tempfilename, outfilename) self.generate_compdb() # http://clang.llvm.org/docs/JSONCompilationDatabase.html def generate_compdb(self): pch_compilers = ['%s_PCH' % i for i in self.build.compilers] native_compilers = ['%s_COMPILER' % i for i in self.build.compilers] cross_compilers = ['%s_CROSS_COMPILER' % i for i in self.build.cross_compilers] ninja_compdb = [self.ninja_command, '-t', 'compdb'] + pch_compilers + native_compilers + cross_compilers builddir = self.environment.get_build_dir() try: jsondb = subprocess.check_output(ninja_compdb, cwd=builddir) with open(os.path.join(builddir, 'compile_commands.json'), 'wb') as f: f.write(jsondb) except Exception: mlog.warning('Could not create compilation database.') # Get all generated headers. Any source file might need them so # we need to add an order dependency to them. def get_generated_headers(self, target): header_deps = [] # XXX: Why don't we add deps to CustomTarget headers here? for genlist in target.get_generated_sources(): if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)): continue for src in genlist.get_outputs(): if self.environment.is_header(src): header_deps.append(self.get_target_generated_dir(target, genlist, src)) if 'vala' in target.compilers and not isinstance(target, build.Executable): vala_header = File.from_built_file(self.get_target_dir(target), target.vala_header) header_deps.append(vala_header) # Recurse and find generated headers for dep in target.link_targets: if isinstance(dep, (build.StaticLibrary, build.SharedLibrary)): header_deps += self.get_generated_headers(dep) return header_deps def get_target_generated_sources(self, target): """ Returns a dictionary with the keys being the path to the file (relative to the build directory) of that type and the value being the GeneratorList or CustomTarget that generated it. """ srcs = OrderedDict() for gensrc in target.get_generated_sources(): for s in gensrc.get_outputs(): f = self.get_target_generated_dir(target, gensrc, s) srcs[f] = s return srcs def get_target_sources(self, target): srcs = OrderedDict() for s in target.get_sources(): # BuildTarget sources are always mesonlib.File files which are # either in the source root, or generated with configure_file and # in the build root if not isinstance(s, File): raise InvalidArguments('All sources in target {!r} must be of type mesonlib.File'.format(s)) f = s.rel_to_builddir(self.build_to_src) srcs[f] = s return srcs # Languages that can mix with C or C++ but don't support unity builds yet # because the syntax we use for unity builds is specific to C/++/ObjC/++. # Assembly files cannot be unitified and neither can LLVM IR files langs_cant_unity = ('d', 'fortran') def get_target_source_can_unity(self, target, source): if isinstance(source, File): source = source.fname if self.environment.is_llvm_ir(source) or \ self.environment.is_assembly(source): return False suffix = os.path.splitext(source)[1][1:] for lang in self.langs_cant_unity: if lang not in target.compilers: continue if suffix in target.compilers[lang].file_suffixes: return False return True def generate_target(self, target, outfile): if isinstance(target, build.CustomTarget): self.generate_custom_target(target, outfile) if isinstance(target, build.RunTarget): self.generate_run_target(target, outfile) name = target.get_id() if name in self.processed_targets: return self.processed_targets[name] = True # Generate rules for all dependency targets self.process_target_dependencies(target, outfile) # If target uses a language that cannot link to C objects, # just generate for that language and return. if isinstance(target, build.Jar): self.generate_jar_target(target, outfile) return if 'rust' in target.compilers: self.generate_rust_target(target, outfile) return if 'cs' in target.compilers: self.generate_cs_target(target, outfile) return if 'swift' in target.compilers: self.generate_swift_target(target, outfile) return # Now we handle the following languages: # ObjC++, ObjC, C++, C, D, Fortran, Vala # target_sources: # Pre-existing target C/C++ sources to be built; dict of full path to # source relative to build root and the original File object. # generated_sources: # GeneratedList and CustomTarget sources to be built; dict of the full # path to source relative to build root and the generating target/list # vala_generated_sources: # Array of sources generated by valac that have to be compiled if 'vala' in target.compilers: # Sources consumed by valac are filtered out. These only contain # C/C++ sources, objects, generated libs, and unknown sources now. target_sources, generated_sources, \ vala_generated_sources = self.generate_vala_compile(target, outfile) else: target_sources = self.get_target_sources(target) generated_sources = self.get_target_generated_sources(target) vala_generated_sources = [] self.scan_fortran_module_outputs(target) # Generate rules for GeneratedLists self.generate_generator_list_rules(target, outfile) # 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. header_deps += self.get_generated_headers(target) if is_unity: # Warn about incompatible sources if a unity build is enabled langs = set(target.compilers.keys()) langs_cant = langs.intersection(self.langs_cant_unity) if langs_cant: langs_are = langs = ', '.join(langs_cant).upper() langs_are += ' are' if len(langs_cant) > 1 else ' is' msg = '{} not supported in Unity builds yet, so {} ' \ 'sources in the {!r} target will be compiled normally' \ ''.format(langs_are, langs, target.name) mlog.log(mlog.red('FIXME'), msg) # Get a list of all generated headers that will be needed while building # this target's sources (generated sources and pre-existing sources). # This will be set as dependencies of all the target's sources. At the # same time, also deal with generated sources that need to be compiled. generated_source_files = [] for rel_src, gensrc in generated_sources.items(): dirpart, fnamepart = os.path.split(rel_src) raw_src = File(True, dirpart, fnamepart) if self.environment.is_source(rel_src) and not self.environment.is_header(rel_src): if is_unity and self.get_target_source_can_unity(target, rel_src): unity_deps.append(raw_src) abs_src = os.path.join(self.environment.get_build_dir(), rel_src) unity_src.append(abs_src) else: generated_source_files.append(raw_src) elif self.environment.is_object(rel_src): obj_list.append(rel_src) elif self.environment.is_library(rel_src): pass else: # Assume anything not specifically a source file is a header. This is because # people generate files with weird suffixes (.inc, .fh) that they then include # in their source files. header_deps.append(raw_src) # These are the generated source files that need to be built for use by # this target. We create the Ninja build file elements for this here # because we need `header_deps` to be fully generated in the above loop. for src in generated_source_files: if self.environment.is_llvm_ir(src): o = self.generate_llvm_ir_compile(target, outfile, src) else: o = self.generate_single_compile(target, outfile, src, True, header_deps=header_deps) obj_list.append(o) # 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 vala_generated_source_files = [] for src in vala_generated_sources: dirpart, fnamepart = os.path.split(src) raw_src = File(True, dirpart, fnamepart) if is_unity: unity_src.append(os.path.join(self.environment.get_build_dir(), src)) header_deps.append(raw_src) else: # Generated targets are ordered deps because the must exist # before the sources compiling them are used. After the first # compile we get precise dependency info from dep files. # This should work in all cases. If it does not, then just # move them from orderdeps to proper deps. if self.environment.is_header(src): header_deps.append(raw_src) else: # We gather all these and generate compile rules below # after `header_deps` (above) is fully generated vala_generated_source_files.append(raw_src) for src in vala_generated_source_files: # Passing 'vala' here signifies that we want the compile # arguments to be specialized for C code generated by # valac. For instance, no warnings should be emitted. obj_list.append(self.generate_single_compile(target, outfile, src, 'vala', [], header_deps)) # Generate compile targets for all the pre-existing sources for this target for f, src in target_sources.items(): if not self.environment.is_header(src): if self.environment.is_llvm_ir(src): obj_list.append(self.generate_llvm_ir_compile(target, outfile, src)) elif is_unity and self.get_target_source_can_unity(target, src): abs_src = os.path.join(self.environment.get_build_dir(), src.rel_to_builddir(self.build_to_src)) unity_src.append(abs_src) else: obj_list.append(self.generate_single_compile(target, outfile, src, False, [], header_deps)) obj_list += self.flatten_object_list(target) if is_unity: for src in self.generate_unity_files(target, unity_src): obj_list.append(self.generate_single_compile(target, outfile, src, True, unity_deps + header_deps)) linker = self.determine_linker(target) elem = self.generate_link(target, outfile, outname, obj_list, linker, pch_objects) self.generate_shlib_aliases(target, self.get_target_dir(target)) elem.write(outfile) def process_target_dependencies(self, target, outfile): for t in target.get_dependencies(): tname = t.get_basename() + t.type_suffix() if tname not in self.processed_targets: self.generate_target(t, outfile) def custom_target_generator_inputs(self, target, outfile): for s in target.sources: if hasattr(s, 'held_object'): s = s.held_object if isinstance(s, build.GeneratedList): self.generate_genlist_for_target(s, target, outfile) def unwrap_dep_list(self, target): deps = [] for i in target.get_dependencies(): # FIXME, should not grab element at zero but rather expand all. if isinstance(i, list): i = i[0] # Add a dependency on all the outputs of this target for output in i.get_outputs(): deps.append(os.path.join(self.get_target_dir(i), output)) return deps def generate_custom_target(self, target, outfile): self.custom_target_generator_inputs(target, outfile) (srcs, ofilenames, cmd) = self.eval_custom_target_command(target) deps = self.unwrap_dep_list(target) deps += self.get_custom_target_depend_files(target) desc = 'Generating {0} with a {1} command.' if target.build_always: deps.append('PHONY') if target.depfile is None: rulename = 'CUSTOM_COMMAND' else: rulename = 'CUSTOM_COMMAND_DEP' elem = NinjaBuildElement(self.all_outputs, ofilenames, rulename, srcs) elem.add_dep(deps) for d in target.extra_depends: # Add a dependency on all the outputs of this target for output in d.get_outputs(): elem.add_dep(os.path.join(self.get_target_dir(d), output)) serialize = False extra_paths = [] # If the target requires capturing stdout, then use the serialized # executable wrapper to capture that output and save it to a file. if target.capture: serialize = True # If the command line requires a newline, also use the wrapper, as # ninja does not support them in its build rule syntax. if any('\n' in c for c in cmd): serialize = True # Windows doesn't have -rpath, so for EXEs that need DLLs built within # the project, we need to set PATH so the DLLs are found. We use # a serialized executable wrapper for that and check if the # CustomTarget command needs extra paths first. if mesonlib.is_windows() or mesonlib.is_cygwin(): extra_bdeps = target.get_transitive_build_target_deps() extra_paths = self.determine_windows_extra_paths(target.command[0], extra_bdeps) if extra_paths: serialize = True if serialize: exe_data = self.serialize_executable(target.command[0], cmd[1:], # All targets are built from the build dir self.environment.get_build_dir(), extra_paths=extra_paths, capture=ofilenames[0] if target.capture else None) cmd = self.environment.get_build_command() + ['--internal', 'exe', exe_data] cmd_type = 'meson_exe.py custom' else: cmd_type = 'custom' if target.depfile is not None: rel_dfile = os.path.join(self.get_target_dir(target), target.depfile) abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) os.makedirs(abs_pdir, exist_ok=True) elem.add_item('DEPFILE', rel_dfile) cmd = self.replace_paths(target, cmd) elem.add_item('COMMAND', cmd) elem.add_item('description', desc.format(target.name, cmd_type)) elem.write(outfile) self.processed_targets[target.get_id()] = True def generate_run_target(self, target, outfile): cmd = self.environment.get_build_command() + ['--internal', 'commandrunner'] deps = self.unwrap_dep_list(target) arg_strings = [] for i in target.args: if isinstance(i, str): arg_strings.append(i) elif isinstance(i, (build.BuildTarget, build.CustomTarget)): relfname = self.get_target_filename(i) arg_strings.append(os.path.join(self.environment.get_build_dir(), relfname)) deps.append(relfname) elif isinstance(i, mesonlib.File): relfname = i.rel_to_builddir(self.build_to_src) arg_strings.append(os.path.join(self.environment.get_build_dir(), relfname)) else: raise AssertionError('Unreachable code in generate_run_target: ' + str(i)) if target.subproject != '': subproject_prefix = '{}@@'.format(target.subproject) else: subproject_prefix = '' target_name = 'meson-{}{}'.format(subproject_prefix, target.name) elem = NinjaBuildElement(self.all_outputs, target_name, 'CUSTOM_COMMAND', []) cmd += [self.environment.get_source_dir(), self.environment.get_build_dir(), target.subdir] + self.environment.get_build_command() texe = target.command try: texe = texe.held_object except AttributeError: pass if isinstance(texe, build.Executable): abs_exe = os.path.join(self.environment.get_build_dir(), self.get_target_filename(texe)) deps.append(self.get_target_filename(texe)) if self.environment.is_cross_build() and \ self.environment.cross_info.need_exe_wrapper(): exe_wrap = self.environment.cross_info.config['binaries'].get('exe_wrapper', None) if exe_wrap is not None: cmd += [exe_wrap] cmd.append(abs_exe) elif isinstance(texe, dependencies.ExternalProgram): cmd += texe.get_command() elif isinstance(texe, build.CustomTarget): deps.append(self.get_target_filename(texe)) cmd += [os.path.join(self.environment.get_build_dir(), self.get_target_filename(texe))] elif isinstance(texe, mesonlib.File): cmd.append(texe.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir())) else: cmd.append(target.command) cmd += arg_strings elem.add_dep(deps) cmd = self.replace_paths(target, cmd) elem.add_item('COMMAND', cmd) elem.add_item('description', 'Running external command %s.' % target.name) elem.add_item('pool', 'console') elem.write(outfile) # Alias that runs the target defined above with the name the user specified self.create_target_alias(target_name, outfile) self.processed_targets[target.get_id()] = True def generate_coverage_rules(self, outfile): e = NinjaBuildElement(self.all_outputs, 'meson-coverage', 'CUSTOM_COMMAND', 'PHONY') e.add_item('COMMAND', self.environment.get_build_command() + ['--internal', 'coverage', self.environment.get_source_dir(), self.environment.get_build_dir(), self.environment.get_log_dir()]) e.add_item('description', 'Generates coverage reports.') e.write(outfile) # Alias that runs the target defined above self.create_target_alias('meson-coverage', outfile) self.generate_coverage_legacy_rules(outfile) def generate_coverage_legacy_rules(self, outfile): (gcovr_exe, lcov_exe, genhtml_exe) = environment.find_coverage_tools() added_rule = False if gcovr_exe: added_rule = True elem = NinjaBuildElement(self.all_outputs, 'meson-coverage-xml', 'CUSTOM_COMMAND', '') elem.add_item('COMMAND', [gcovr_exe, '-x', '-r', self.environment.get_source_dir(), '-o', os.path.join(self.environment.get_log_dir(), 'coverage.xml')]) elem.add_item('DESC', 'Generating XML coverage report.') elem.write(outfile) # Alias that runs the target defined above self.create_target_alias('meson-coverage-xml', outfile) elem = NinjaBuildElement(self.all_outputs, 'meson-coverage-text', 'CUSTOM_COMMAND', '') elem.add_item('COMMAND', [gcovr_exe, '-r', self.environment.get_source_dir(), '-o', os.path.join(self.environment.get_log_dir(), 'coverage.txt')]) elem.add_item('DESC', 'Generating text coverage report.') elem.write(outfile) # Alias that runs the target defined above self.create_target_alias('meson-coverage-text', outfile) if lcov_exe and genhtml_exe: added_rule = True htmloutdir = os.path.join(self.environment.get_log_dir(), 'coveragereport') covinfo = os.path.join(self.environment.get_log_dir(), 'coverage.info') phony_elem = NinjaBuildElement(self.all_outputs, 'meson-coverage-html', 'phony', os.path.join(htmloutdir, 'index.html')) phony_elem.write(outfile) # Alias that runs the target defined above self.create_target_alias('meson-coverage-html', outfile) elem = NinjaBuildElement(self.all_outputs, os.path.join(htmloutdir, 'index.html'), 'CUSTOM_COMMAND', '') command = [lcov_exe, '--directory', self.environment.get_build_dir(), '--capture', '--output-file', covinfo, '--no-checksum', '&&', genhtml_exe, '--prefix', self.environment.get_build_dir(), '--output-directory', htmloutdir, '--title', 'Code coverage', '--legend', '--show-details', covinfo] elem.add_item('COMMAND', command) elem.add_item('DESC', 'Generating HTML coverage report.') elem.write(outfile) if not added_rule: mlog.warning('coverage requested but neither gcovr nor lcov/genhtml found.') def generate_install(self, outfile): install_data_file = os.path.join(self.environment.get_scratch_dir(), 'install.dat') if self.environment.is_cross_build(): bins = self.environment.cross_info.config['binaries'] if 'strip' not in bins: mlog.warning('Cross file does not specify strip binary, result will not be stripped.') strip_bin = None else: strip_bin = mesonlib.stringlistify(bins['strip']) else: strip_bin = self.environment.native_strip_bin d = InstallData(self.environment.get_source_dir(), self.environment.get_build_dir(), self.environment.get_prefix(), strip_bin, self.environment.get_build_command() + ['introspect']) elem = NinjaBuildElement(self.all_outputs, 'meson-install', 'CUSTOM_COMMAND', 'PHONY') elem.add_dep('all') elem.add_item('DESC', 'Installing files.') elem.add_item('COMMAND', self.environment.get_build_command() + ['--internal', 'install', install_data_file]) elem.add_item('pool', 'console') self.generate_depmf_install(d) self.generate_target_install(d) self.generate_header_install(d) self.generate_man_install(d) self.generate_data_install(d) self.generate_custom_install_script(d) self.generate_subdir_install(d) elem.write(outfile) # Alias that runs the target defined above self.create_target_alias('meson-install', outfile) with open(install_data_file, 'wb') as ofile: pickle.dump(d, ofile) def generate_target_install(self, d): for t in self.build.get_targets().values(): if not t.should_install(): continue # Find the installation directory. outdirs = t.get_custom_install_dir() custom_install_dir = False if outdirs[0] is not None and outdirs[0] is not True: # Either the value is set, or is set to False which means # we want this specific output out of many outputs to not # be installed. custom_install_dir = True elif isinstance(t, build.SharedModule): outdirs[0] = self.environment.get_shared_module_dir() elif isinstance(t, build.SharedLibrary): outdirs[0] = self.environment.get_shared_lib_dir() elif isinstance(t, build.StaticLibrary): outdirs[0] = self.environment.get_static_lib_dir() elif isinstance(t, build.Executable): outdirs[0] = self.environment.get_bindir() else: assert(isinstance(t, build.BuildTarget)) # XXX: Add BuildTarget-specific install dir cases here outdirs[0] = self.environment.get_libdir() # Sanity-check the outputs and install_dirs num_outdirs, num_out = len(outdirs), len(t.get_outputs()) if num_outdirs != 1 and num_outdirs != num_out: m = 'Target {!r} has {} outputs: {!r}, but only {} "install_dir"s were found.\n' \ "Pass 'false' for outputs that should not be installed and 'true' for\n" \ 'using the default installation directory for an output.' raise MesonException(m.format(t.name, num_out, t.get_outputs(), num_outdirs)) # Install the target output(s) if isinstance(t, build.BuildTarget): should_strip = self.get_option_for_target('strip', t) # Install primary build output (library/executable/jar, etc) # Done separately because of strip/aliases/rpath if outdirs[0] is not False: i = [self.get_target_filename(t), outdirs[0], t.get_aliases(), should_strip, t.install_rpath] d.targets.append(i) # On toolchains/platforms that use an import library for # linking (separate from the shared library with all the # code), we need to install that too (dll.a/.lib). if (isinstance(t, build.SharedLibrary) or isinstance(t, build.Executable)) and t.get_import_filename(): if custom_install_dir: # If the DLL is installed into a custom directory, # install the import library into the same place so # it doesn't go into a surprising place implib_install_dir = outdirs[0] else: implib_install_dir = self.environment.get_import_lib_dir() # Install the import library. i = [self.get_target_filename_for_linking(t), implib_install_dir, # It has no aliases, should not be stripped, and # doesn't have an install_rpath {}, False, ''] d.targets.append(i) # Install secondary outputs. Only used for Vala right now. if num_outdirs > 1: for output, outdir in zip(t.get_outputs()[1:], outdirs[1:]): # User requested that we not install this output if outdir is False: continue f = os.path.join(self.get_target_dir(t), output) d.targets.append([f, outdir, {}, False, None]) elif isinstance(t, build.CustomTarget): # If only one install_dir is specified, assume that all # outputs will be installed into it. This is for # backwards-compatibility and because it makes sense to # avoid repetition since this is a common use-case. # # To selectively install only some outputs, pass `false` as # the install_dir for the corresponding output by index if num_outdirs == 1 and num_out > 1: for output in t.get_outputs(): f = os.path.join(self.get_target_dir(t), output) d.targets.append([f, outdirs[0], {}, False, None]) else: for output, outdir in zip(t.get_outputs(), outdirs): # User requested that we not install this output if outdir is False: continue f = os.path.join(self.get_target_dir(t), output) d.targets.append([f, outdir, {}, False, None]) def generate_custom_install_script(self, d): result = [] srcdir = self.environment.get_source_dir() builddir = self.environment.get_build_dir() for i in self.build.install_scripts: exe = i['exe'] args = i['args'] fixed_args = [] for a in args: a = a.replace('@SOURCE_ROOT@', srcdir) a = a.replace('@BUILD_ROOT@', builddir) fixed_args.append(a) result.append(build.RunScript(exe, fixed_args)) d.install_scripts = result def generate_header_install(self, d): incroot = self.environment.get_includedir() headers = self.build.get_headers() srcdir = self.environment.get_source_dir() builddir = self.environment.get_build_dir() for h in headers: outdir = h.get_custom_install_dir() if outdir is None: outdir = os.path.join(incroot, h.get_install_subdir()) for f in h.get_sources(): if not isinstance(f, File): msg = 'Invalid header type {!r} can\'t be installed' raise MesonException(msg.format(f)) abspath = f.absolute_path(srcdir, builddir) i = [abspath, outdir] d.headers.append(i) def generate_man_install(self, d): manroot = self.environment.get_mandir() man = self.build.get_man() for m in man: for f in m.get_sources(): num = f.split('.')[-1] subdir = m.get_custom_install_dir() if subdir is None: subdir = os.path.join(manroot, 'man' + num) srcabs = f.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) dstabs = os.path.join(subdir, os.path.basename(f.fname) + '.gz') i = [srcabs, dstabs] d.man.append(i) def generate_data_install(self, d): data = self.build.get_data() srcdir = self.environment.get_source_dir() builddir = self.environment.get_build_dir() for de in data: assert(isinstance(de, build.Data)) subdir = de.install_dir if not subdir: subdir = os.path.join(self.environment.get_datadir(), self.interpreter.build.project_name) for f in de.sources: assert(isinstance(f, mesonlib.File)) plain_f = os.path.basename(f.fname) dstabs = os.path.join(subdir, plain_f) i = [f.absolute_path(srcdir, builddir), dstabs, de.install_mode] d.data.append(i) def generate_subdir_install(self, d): for sd in self.build.get_install_subdirs(): src_dir = os.path.join(self.environment.get_source_dir(), sd.source_subdir, sd.installable_subdir).rstrip('/') dst_dir = os.path.join(self.environment.get_prefix(), sd.install_dir) if not sd.strip_directory: dst_dir = os.path.join(dst_dir, os.path.basename(src_dir)) d.install_subdirs.append([src_dir, dst_dir, sd.install_mode, sd.exclude]) def generate_tests(self, outfile): self.serialize_tests() cmd = self.environment.get_build_command(True) + ['test', '--no-rebuild'] if not self.environment.coredata.get_builtin_option('stdsplit'): cmd += ['--no-stdsplit'] if self.environment.coredata.get_builtin_option('errorlogs'): cmd += ['--print-errorlogs'] elem = NinjaBuildElement(self.all_outputs, 'meson-test', 'CUSTOM_COMMAND', ['all', 'PHONY']) elem.add_item('COMMAND', cmd) elem.add_item('DESC', 'Running all tests.') elem.add_item('pool', 'console') elem.write(outfile) # Alias that runs the above-defined meson-test target self.create_target_alias('meson-test', outfile) # And then benchmarks. cmd = self.environment.get_build_command(True) + [ 'test', '--benchmark', '--logbase', 'benchmarklog', '--num-processes=1', '--no-rebuild'] elem = NinjaBuildElement(self.all_outputs, 'meson-benchmark', 'CUSTOM_COMMAND', ['all', 'PHONY']) elem.add_item('COMMAND', cmd) elem.add_item('DESC', 'Running benchmark suite.') elem.add_item('pool', 'console') elem.write(outfile) # Alias that runs the above-defined meson-benchmark target self.create_target_alias('meson-benchmark', outfile) def generate_rules(self, outfile): outfile.write('# Rules for compiling.\n\n') self.generate_compile_rules(outfile) outfile.write('# Rules for linking.\n\n') num_pools = self.environment.coredata.backend_options['backend_max_links'].value if num_pools > 0: outfile.write('''pool link_pool depth = %d ''' % num_pools) if self.environment.is_cross_build(): self.generate_static_link_rules(True, outfile) self.generate_static_link_rules(False, outfile) self.generate_dynamic_link_rules(outfile) outfile.write('# Other rules\n\n') outfile.write('rule CUSTOM_COMMAND\n') outfile.write(' command = $COMMAND\n') outfile.write(' description = $DESC\n') outfile.write(' restat = 1\n\n') # Ninja errors out if you have deps = gcc but no depfile, so we must # have two rules for custom commands. outfile.write('rule CUSTOM_COMMAND_DEP\n') outfile.write(' command = $COMMAND\n') outfile.write(' description = $DESC\n') outfile.write(' deps = gcc\n') outfile.write(' depfile = $DEPFILE\n') outfile.write(' restat = 1\n\n') outfile.write('rule REGENERATE_BUILD\n') c = [ninja_quote(quote_func(x)) for x in self.environment.get_build_command()] + \ ['--internal', 'regenerate', ninja_quote(quote_func(self.environment.get_source_dir())), ninja_quote(quote_func(self.environment.get_build_dir()))] outfile.write(" command = " + ' '.join(c) + ' --backend ninja\n') outfile.write(' description = Regenerating build files.\n') outfile.write(' generator = 1\n\n') outfile.write('\n') def generate_phony(self, outfile): outfile.write('# Phony build target, always out of date\n') outfile.write('build PHONY: phony\n') outfile.write('\n') def generate_jar_target(self, target, outfile): fname = target.get_filename() outname_rel = os.path.join(self.get_target_dir(target), fname) src_list = target.get_sources() class_list = [] compiler = target.compilers['java'] c = 'c' m = '' e = '' f = 'f' main_class = target.get_main_class() if main_class != '': e = 'e' for src in src_list: plain_class_path = self.generate_single_java_compile(src, target, compiler, outfile) class_list.append(plain_class_path) class_dep_list = [os.path.join(self.get_target_private_dir(target), i) for i in class_list] jar_rule = 'java_LINKER' commands = [c + m + e + f] if e != '': commands.append(main_class) commands.append(self.get_target_filename(target)) # Java compilation can produce an arbitrary number of output # class files for a single source file. Thus tell jar to just # grab everything in the final package. commands += ['-C', self.get_target_private_dir(target), '.'] elem = NinjaBuildElement(self.all_outputs, outname_rel, jar_rule, []) elem.add_dep(class_dep_list) elem.add_item('ARGS', commands) elem.write(outfile) def generate_cs_resource_tasks(self, target, outfile): args = [] deps = [] for r in target.resources: rel_sourcefile = os.path.join(self.build_to_src, target.subdir, r) if r.endswith('.resources'): a = '-resource:' + rel_sourcefile elif r.endswith('.txt') or r.endswith('.resx'): ofilebase = os.path.splitext(os.path.basename(r))[0] + '.resources' ofilename = os.path.join(self.get_target_private_dir(target), ofilebase) elem = NinjaBuildElement(self.all_outputs, ofilename, "CUSTOM_COMMAND", rel_sourcefile) elem.add_item('COMMAND', ['resgen', rel_sourcefile, ofilename]) elem.add_item('DESC', 'Compiling resource %s.' % rel_sourcefile) elem.write(outfile) deps.append(ofilename) a = '-resource:' + ofilename else: raise InvalidArguments('Unknown resource file %s.' % r) args.append(a) return args, deps def generate_cs_target(self, target, outfile): buildtype = self.get_option_for_target('buildtype', target) fname = target.get_filename() outname_rel = os.path.join(self.get_target_dir(target), fname) src_list = target.get_sources() compiler = target.compilers['cs'] rel_srcs = [os.path.normpath(s.rel_to_builddir(self.build_to_src)) for s in src_list] deps = [] commands = CompilerArgs(compiler, target.extra_args.get('cs', [])) commands += compiler.get_buildtype_args(buildtype) if isinstance(target, build.Executable): commands.append('-target:exe') elif isinstance(target, build.SharedLibrary): commands.append('-target:library') else: raise MesonException('Unknown C# target type.') (resource_args, resource_deps) = self.generate_cs_resource_tasks(target, outfile) commands += resource_args deps += resource_deps commands += compiler.get_output_args(outname_rel) for l in target.link_targets: lname = os.path.join(self.get_target_dir(l), l.get_filename()) commands += compiler.get_link_args(lname) deps.append(lname) if '-g' in commands: outputs = [outname_rel, outname_rel + '.mdb'] else: outputs = [outname_rel] generated_sources = self.get_target_generated_sources(target) for rel_src in generated_sources.keys(): dirpart, fnamepart = os.path.split(rel_src) if rel_src.lower().endswith('.cs'): rel_srcs.append(os.path.normpath(rel_src)) deps.append(os.path.normpath(rel_src)) for dep in target.get_external_deps(): commands.extend_direct(dep.get_link_args()) commands += self.build.get_project_args(compiler, target.subproject) commands += self.build.get_global_args(compiler) elem = NinjaBuildElement(self.all_outputs, outputs, 'cs_COMPILER', rel_srcs) elem.add_dep(deps) elem.add_item('ARGS', commands) elem.write(outfile) self.generate_generator_list_rules(target, outfile) def generate_single_java_compile(self, src, target, compiler, outfile): args = [] args += compiler.get_buildtype_args(self.get_option_for_target('buildtype', target)) args += self.build.get_global_args(compiler) args += self.build.get_project_args(compiler, target.subproject) args += target.get_java_args() args += compiler.get_output_args(self.get_target_private_dir(target)) for i in target.include_dirs: for idir in i.get_incdirs(): args += ['-sourcepath', os.path.join(self.build_to_src, i.curdir, idir)] rel_src = src.rel_to_builddir(self.build_to_src) plain_class_path = src.fname[:-4] + 'class' rel_obj = os.path.join(self.get_target_private_dir(target), plain_class_path) element = NinjaBuildElement(self.all_outputs, rel_obj, compiler.get_language() + '_COMPILER', rel_src) element.add_item('ARGS', args) element.write(outfile) return plain_class_path def generate_java_link(self, outfile): rule = 'rule java_LINKER\n' command = ' command = jar $ARGS\n' description = ' description = Creating JAR $out.\n' outfile.write(rule) outfile.write(command) outfile.write(description) outfile.write('\n') def determine_dep_vapis(self, target): """ Peek into the sources of BuildTargets we're linking with, and if any of them was built with Vala, assume that it also generated a .vapi file of the same name as the BuildTarget and return the path to it relative to the build directory. """ result = OrderedSet() for dep in target.link_targets + target.link_whole_targets: for i in dep.sources: if hasattr(i, 'fname'): i = i.fname if i.endswith('vala'): vapiname = dep.vala_vapi fullname = os.path.join(self.get_target_dir(dep), vapiname) result.add(fullname) break return list(result) def split_vala_sources(self, t): """ Splits the target's sources into .vala, .gs, .vapi, and other sources. Handles both pre-existing and generated sources. Returns a tuple (vala, vapi, others) each of which is a dictionary with the keys being the path to the file (relative to the build directory) and the value being the object that generated or represents the file. """ vala = OrderedDict() vapi = OrderedDict() others = OrderedDict() othersgen = OrderedDict() # Split pre-existing sources for s in t.get_sources(): # BuildTarget sources are always mesonlib.File files which are # either in the source root, or generated with configure_file and # in the build root if not isinstance(s, File): msg = 'All sources in target {!r} must be of type ' \ 'mesonlib.File, not {!r}'.format(t, s) raise InvalidArguments(msg) f = s.rel_to_builddir(self.build_to_src) if s.endswith(('.vala', '.gs')): srctype = vala elif s.endswith('.vapi'): srctype = vapi else: srctype = others srctype[f] = s # Split generated sources for gensrc in t.get_generated_sources(): for s in gensrc.get_outputs(): f = self.get_target_generated_dir(t, gensrc, s) if s.endswith(('.vala', '.gs')): srctype = vala elif s.endswith('.vapi'): srctype = vapi # Generated non-Vala (C/C++) sources. Won't be used for # generating the Vala compile rule below. else: srctype = othersgen # Duplicate outputs are disastrous if f in srctype and srctype[f] is not gensrc: msg = 'Duplicate output {0!r} from {1!r} {2!r}; ' \ 'conflicts with {0!r} from {4!r} {3!r}' \ ''.format(f, type(gensrc).__name__, gensrc.name, srctype[f].name, type(srctype[f]).__name__) raise InvalidArguments(msg) # Store 'somefile.vala': GeneratedList (or CustomTarget) srctype[f] = gensrc return vala, vapi, (others, othersgen) def generate_vala_compile(self, target, outfile): """Vala is compiled into C. Set up all necessary build steps here.""" (vala_src, vapi_src, other_src) = self.split_vala_sources(target) extra_dep_files = [] if not vala_src: msg = 'Vala library {!r} has no Vala or Genie source files.' raise InvalidArguments(msg.format(target.name)) valac = target.compilers['vala'] c_out_dir = self.get_target_private_dir(target) # C files generated by valac vala_c_src = [] # Files generated by valac valac_outputs = [] # All sources that are passed to valac on the commandline all_files = list(vapi_src.keys()) # Passed as --basedir srcbasedir = os.path.join(self.build_to_src, target.get_subdir()) for (vala_file, gensrc) in vala_src.items(): all_files.append(vala_file) # Figure out where the Vala compiler will write the compiled C file # # If the Vala file is in a subdir of the build dir (in our case # because it was generated/built by something else), and is also # a subdir of --basedir (because the builddir is in the source # tree, and the target subdir is the source root), the subdir # components from the source root till the private builddir will be # duplicated inside the private builddir. Otherwise, just the # basename will be used. # # If the Vala file is outside the build directory, the paths from # the --basedir till the subdir will be duplicated inside the # private builddir. if isinstance(gensrc, (build.CustomTarget, build.GeneratedList)) or gensrc.is_built: vala_c_file = os.path.splitext(os.path.basename(vala_file))[0] + '.c' # Check if the vala file is in a subdir of --basedir abs_srcbasedir = os.path.join(self.environment.get_source_dir(), target.get_subdir()) abs_vala_file = os.path.join(self.environment.get_build_dir(), vala_file) if PurePath(os.path.commonpath((abs_srcbasedir, abs_vala_file))) == PurePath(abs_srcbasedir): vala_c_subdir = PurePath(abs_vala_file).parent.relative_to(abs_srcbasedir) vala_c_file = os.path.join(vala_c_subdir, vala_c_file) else: path_to_target = os.path.join(self.build_to_src, target.get_subdir()) if vala_file.startswith(path_to_target): vala_c_file = os.path.splitext(os.path.relpath(vala_file, path_to_target))[0] + '.c' else: vala_c_file = os.path.splitext(os.path.basename(vala_file))[0] + '.c' # All this will be placed inside the c_out_dir vala_c_file = os.path.join(c_out_dir, vala_c_file) vala_c_src.append(vala_c_file) valac_outputs.append(vala_c_file) args = self.generate_basic_compiler_args(target, valac) args += valac.get_colorout_args(self.environment.coredata.base_options.get('b_colorout').value) # Tell Valac to output everything in our private directory. Sadly this # means it will also preserve the directory components of Vala sources # found inside the build tree (generated sources). args += ['--directory', c_out_dir] args += ['--basedir', srcbasedir] if not isinstance(target, build.Executable): # Library name args += ['--library', target.name] # Outputted header hname = os.path.join(self.get_target_dir(target), target.vala_header) args += ['--header', hname] if self.is_unity(target): # Without this the declarations will get duplicated in the .c # files and cause a build failure when all of them are # #include-d in one .c file. # https://github.com/mesonbuild/meson/issues/1969 args += ['--use-header'] valac_outputs.append(hname) # Outputted vapi file vapiname = os.path.join(self.get_target_dir(target), target.vala_vapi) # Force valac to write the vapi and gir files in the target build dir. # Without this, it will write it inside c_out_dir args += ['--vapi', os.path.join('..', target.vala_vapi)] valac_outputs.append(vapiname) target.outputs += [target.vala_header, target.vala_vapi] # Install header and vapi to default locations if user requests this if len(target.install_dir) > 1 and target.install_dir[1] is True: target.install_dir[1] = self.environment.get_includedir() if len(target.install_dir) > 2 and target.install_dir[2] is True: target.install_dir[2] = os.path.join(self.environment.get_datadir(), 'vala', 'vapi') # Generate GIR if requested if isinstance(target.vala_gir, str): girname = os.path.join(self.get_target_dir(target), target.vala_gir) args += ['--gir', os.path.join('..', target.vala_gir)] valac_outputs.append(girname) target.outputs.append(target.vala_gir) # Install GIR to default location if requested by user if len(target.install_dir) > 3 and target.install_dir[3] is True: target.install_dir[3] = os.path.join(self.environment.get_datadir(), 'gir-1.0') # Detect gresources and add --gresources arguments for each for (gres, gensrc) in other_src[1].items(): if isinstance(gensrc, modules.GResourceTarget): gres_xml, = self.get_custom_target_sources(gensrc) args += ['--gresources=' + gres_xml] extra_args = [] for a in target.extra_args.get('vala', []): if isinstance(a, File): relname = a.rel_to_builddir(self.build_to_src) extra_dep_files.append(relname) extra_args.append(relname) else: extra_args.append(a) dependency_vapis = self.determine_dep_vapis(target) extra_dep_files += dependency_vapis args += extra_args element = NinjaBuildElement(self.all_outputs, valac_outputs, valac.get_language() + '_COMPILER', all_files + dependency_vapis) element.add_item('ARGS', args) element.add_dep(extra_dep_files) element.write(outfile) return other_src[0], other_src[1], vala_c_src def generate_rust_target(self, target, outfile): rustc = target.compilers['rust'] relsrc = [] for i in target.get_sources(): if not rustc.can_compile(i): raise InvalidArguments('Rust target %s contains a non-rust source file.' % target.get_basename()) relsrc.append(i.rel_to_builddir(self.build_to_src)) target_name = os.path.join(target.subdir, target.get_filename()) args = ['--crate-type'] if isinstance(target, build.Executable): cratetype = 'bin' elif hasattr(target, 'rust_crate_type'): cratetype = target.rust_crate_type elif isinstance(target, build.SharedLibrary): cratetype = 'dylib' elif isinstance(target, build.StaticLibrary): cratetype = 'rlib' else: raise InvalidArguments('Unknown target type for rustc.') args.append(cratetype) args += ['--crate-name', target.name] args += rustc.get_buildtype_args(self.get_option_for_target('buildtype', target)) depfile = os.path.join(target.subdir, target.name + '.d') args += ['--emit', 'dep-info={}'.format(depfile), '--emit', 'link'] args += target.get_extra_args('rust') args += ['-o', os.path.join(target.subdir, target.get_filename())] 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 # specify `extern CRATE_NAME=OUTPUT_FILE` for each Rust # dependency, so that collisions with libraries in rustc's # sysroot don't cause ambiguity args += ['--extern', '{}={}'.format(d.name, os.path.join(d.subdir, d.filename))] for d in linkdirs.keys(): if d == '': d = '.' args += ['-L', d] has_shared_deps = False for dep in target.get_dependencies(): if isinstance(dep, build.SharedLibrary): has_shared_deps = True if isinstance(target, build.SharedLibrary) or has_shared_deps: # add prefer-dynamic if any of the Rust libraries we link # against are dynamic, otherwise we'll end up with # multiple implementations of crates args += ['-C', 'prefer-dynamic'] # build the usual rpath arguments as well... # 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 '/' in target.name or '\\' in 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 = rustc.build_rpath_args(self.environment.get_build_dir(), target_slashname_workaround_dir, self.determine_rpath_dirs(target), target.build_rpath, target.install_rpath) # ... but then add rustc's sysroot to account for rustup # installations for rpath_arg in rpath_args: args += ['-C', 'link-arg=' + rpath_arg + ':' + os.path.join(rustc.get_sysroot(), 'lib')] crstr = '' if target.is_cross: crstr = '_CROSS' compiler_name = 'rust%s_COMPILER' % crstr element = NinjaBuildElement(self.all_outputs, target_name, compiler_name, relsrc) if len(orderdeps) > 0: element.add_orderdep(orderdeps) element.add_item('ARGS', args) element.add_item('targetdep', depfile) element.add_item('cratetype', cratetype) element.write(outfile) if isinstance(target, build.SharedLibrary): self.generate_shsym(outfile, target) def swift_module_file_name(self, target): return os.path.join(self.get_target_private_dir(target), self.target_swift_modulename(target) + '.swiftmodule') 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: if self.is_swift_target(l): result.append(self.swift_module_file_name(l)) return result def determine_swift_dep_dirs(self, target): result = [] for l in target.link_targets: result.append(self.get_target_private_dir_abs(l)) return result def get_swift_link_deps(self, target): result = [] for l in target.link_targets: result.append(self.get_target_filename(l)) return result def split_swift_generated_sources(self, target): all_srcs = self.get_target_generated_sources(target) srcs = [] others = [] for i in all_srcs: if i.endswith('.swift'): srcs.append(i) else: others.append(i) return srcs, others def generate_swift_target(self, target, outfile): module_name = self.target_swift_modulename(target) swiftc = target.compilers['swift'] abssrc = [] abs_headers = [] header_imports = [] for i in target.get_sources(): if swiftc.can_compile(i): relsrc = i.rel_to_builddir(self.build_to_src) abss = os.path.normpath(os.path.join(self.environment.get_build_dir(), relsrc)) abssrc.append(abss) elif self.environment.is_header(i): relh = i.rel_to_builddir(self.build_to_src) absh = os.path.normpath(os.path.join(self.environment.get_build_dir(), relh)) abs_headers.append(absh) header_imports += swiftc.get_header_import_args(absh) else: raise InvalidArguments('Swift target %s contains a non-swift source file.' % target.get_basename()) os.makedirs(self.get_target_private_dir_abs(target), exist_ok=True) compile_args = swiftc.get_compile_only_args() compile_args += swiftc.get_module_args(module_name) compile_args += self.build.get_project_args(swiftc, target.subproject) compile_args += self.build.get_global_args(swiftc) for i in reversed(target.get_include_dirs()): basedir = i.get_curdir() for d in i.get_incdirs(): if d not in ('', '.'): expdir = os.path.join(basedir, d) else: expdir = basedir srctreedir = os.path.normpath(os.path.join(self.environment.get_build_dir(), self.build_to_src, expdir)) sargs = swiftc.get_include_args(srctreedir) compile_args += sargs link_args = swiftc.get_output_args(os.path.join(self.environment.get_build_dir(), self.get_target_filename(target))) link_args += self.build.get_project_link_args(swiftc, target.subproject) link_args += self.build.get_global_link_args(swiftc) rundir = self.get_target_private_dir(target) out_module_name = self.swift_module_file_name(target) in_module_files = self.determine_swift_dep_modules(target) abs_module_dirs = self.determine_swift_dep_dirs(target) module_includes = [] for x in abs_module_dirs: module_includes += swiftc.get_include_args(x) link_deps = self.get_swift_link_deps(target) abs_link_deps = [os.path.join(self.environment.get_build_dir(), x) for x in link_deps] for d in target.link_targets: reldir = self.get_target_dir(d) if reldir == '': reldir = '.' link_args += ['-L', os.path.normpath(os.path.join(self.environment.get_build_dir(), reldir))] (rel_generated, _) = self.split_swift_generated_sources(target) abs_generated = [os.path.join(self.environment.get_build_dir(), x) for x in rel_generated] # We need absolute paths because swiftc needs to be invoked in a subdir # and this is the easiest way about it. objects = [] # Relative to swift invocation dir rel_objects = [] # Relative to build.ninja for i in abssrc + abs_generated: base = os.path.basename(i) oname = os.path.splitext(base)[0] + '.o' objects.append(oname) rel_objects.append(os.path.join(self.get_target_private_dir(target), oname)) # Swiftc does not seem to be able to emit objects and module files in one go. elem = NinjaBuildElement(self.all_outputs, rel_objects, 'swift_COMPILER', abssrc) elem.add_dep(in_module_files + rel_generated) elem.add_dep(abs_headers) elem.add_item('ARGS', compile_args + header_imports + abs_generated + module_includes) elem.add_item('RUNDIR', rundir) elem.write(outfile) elem = NinjaBuildElement(self.all_outputs, out_module_name, 'swift_COMPILER', abssrc) elem.add_dep(in_module_files + rel_generated) elem.add_item('ARGS', compile_args + abs_generated + module_includes + swiftc.get_mod_gen_args()) elem.add_item('RUNDIR', rundir) elem.write(outfile) if isinstance(target, build.StaticLibrary): elem = self.generate_link(target, outfile, self.get_target_filename(target), rel_objects, self.build.static_linker) elem.write(outfile) elif isinstance(target, build.Executable): elem = NinjaBuildElement(self.all_outputs, self.get_target_filename(target), 'swift_COMPILER', []) elem.add_dep(rel_objects) elem.add_dep(link_deps) elem.add_item('ARGS', link_args + swiftc.get_std_exe_link_args() + objects + abs_link_deps) elem.add_item('RUNDIR', rundir) elem.write(outfile) else: raise MesonException('Swift supports only executable and static library targets.') def generate_static_link_rules(self, is_cross, outfile): num_pools = self.environment.coredata.backend_options['backend_max_links'].value if 'java' in self.build.compilers: if not is_cross: self.generate_java_link(outfile) if is_cross: if self.environment.cross_info.need_cross_compiler(): static_linker = self.build.static_cross_linker else: static_linker = self.build.static_linker crstr = '_CROSS' else: static_linker = self.build.static_linker crstr = '' if static_linker is None: return rule = 'rule STATIC%s_LINKER\n' % crstr # We don't use @file.rsp on Windows with ArLinker because llvm-ar and # gcc-ar blindly pass the --plugin argument to `ar` and you cannot pass # options as arguments while using the @file.rsp syntax. # See: https://github.com/mesonbuild/meson/issues/1646 if mesonlib.is_windows() and not isinstance(static_linker, ArLinker): command_template = ''' command = {executable} @$out.rsp rspfile = $out.rsp rspfile_content = $LINK_ARGS {output_args} $in ''' else: command_template = ' command = {executable} $LINK_ARGS {output_args} $in\n' cmdlist = [] # FIXME: Must normalize file names with pathlib.Path before writing # them out to fix this properly on Windows. See: # https://github.com/mesonbuild/meson/issues/1517 # https://github.com/mesonbuild/meson/issues/1526 if isinstance(static_linker, ArLinker) and not mesonlib.is_windows(): # `ar` has no options to overwrite archives. It always appends, # which is never what we want. Delete an existing library first if # it exists. https://github.com/mesonbuild/meson/issues/1355 cmdlist = [execute_wrapper, rmfile_prefix.format('$out')] cmdlist += static_linker.get_exelist() command = command_template.format( executable=' '.join(cmdlist), output_args=' '.join(static_linker.get_output_args('$out'))) description = ' description = Linking static target $out.\n\n' outfile.write(rule) outfile.write(command) if num_pools > 0: outfile.write(' pool = link_pool\n') outfile.write(description) def generate_dynamic_link_rules(self, outfile): num_pools = self.environment.coredata.backend_options['backend_max_links'].value ctypes = [(self.build.compilers, False)] if self.environment.is_cross_build(): if self.environment.cross_info.need_cross_compiler(): ctypes.append((self.build.cross_compilers, True)) else: # Native compiler masquerades as the cross compiler. ctypes.append((self.build.compilers, True)) else: ctypes.append((self.build.cross_compilers, True)) for (complist, is_cross) in ctypes: for langname, compiler in complist.items(): if langname == 'java' \ or langname == 'vala' \ or langname == 'rust' \ or langname == 'cs': continue crstr = '' cross_args = [] if is_cross: crstr = '_CROSS' try: cross_args = self.environment.cross_info.config['properties'][langname + '_link_args'] except KeyError: pass rule = 'rule %s%s_LINKER\n' % (langname, crstr) if mesonlib.is_windows(): command_template = ''' command = {executable} @$out.rsp rspfile = $out.rsp rspfile_content = $ARGS {output_args} $in $LINK_ARGS {cross_args} $aliasing ''' else: command_template = ' command = {executable} $ARGS {output_args} $in $LINK_ARGS {cross_args} $aliasing\n' command = command_template.format( executable=' '.join(compiler.get_linker_exelist()), cross_args=' '.join(cross_args), output_args=' '.join(compiler.get_linker_output_args('$out')) ) description = ' description = Linking target $out.\n' outfile.write(rule) outfile.write(command) if num_pools > 0: outfile.write(' pool = link_pool\n') outfile.write(description) outfile.write('\n') outfile.write('\n') args = [ninja_quote(quote_func(x)) for x in self.environment.get_build_command()] + \ ['--internal', 'symbolextractor', '$in', '$out'] symrule = 'rule SHSYM\n' symcmd = ' command = ' + ' '.join(args) + ' $CROSS\n' synstat = ' restat = 1\n' syndesc = ' description = Generating symbol file $out.\n' outfile.write(symrule) outfile.write(symcmd) outfile.write(synstat) outfile.write(syndesc) outfile.write('\n') def generate_java_compile_rule(self, compiler, outfile): rule = 'rule %s_COMPILER\n' % compiler.get_language() invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) command = ' command = %s $ARGS $in\n' % invoc description = ' description = Compiling Java object $in.\n' outfile.write(rule) outfile.write(command) outfile.write(description) outfile.write('\n') def generate_cs_compile_rule(self, compiler, outfile): rule = 'rule %s_COMPILER\n' % compiler.get_language() invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) if mesonlib.is_windows(): command = ''' command = {executable} @$out.rsp rspfile = $out.rsp rspfile_content = $ARGS $in '''.format(executable=invoc) else: command = ' command = %s $ARGS $in\n' % invoc description = ' description = Compiling C Sharp target $out.\n' outfile.write(rule) outfile.write(command) outfile.write(description) outfile.write('\n') def generate_vala_compile_rules(self, compiler, outfile): rule = 'rule %s_COMPILER\n' % compiler.get_language() invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) command = ' command = %s $ARGS $in\n' % invoc description = ' description = Compiling Vala source $in.\n' restat = ' restat = 1\n' # ValaC does this always to take advantage of it. outfile.write(rule) outfile.write(command) outfile.write(description) outfile.write(restat) outfile.write('\n') def generate_rust_compile_rules(self, compiler, outfile, is_cross): crstr = '' if is_cross: crstr = '_CROSS' rule = 'rule %s%s_COMPILER\n' % (compiler.get_language(), crstr) invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) command = ' command = %s $ARGS $in\n' % invoc description = ' description = Compiling Rust source $in.\n' depfile = ' depfile = $targetdep\n' depstyle = ' deps = gcc\n' outfile.write(rule) outfile.write(command) outfile.write(description) outfile.write(depfile) outfile.write(depstyle) outfile.write('\n') def generate_swift_compile_rules(self, compiler, outfile): rule = 'rule %s_COMPILER\n' % compiler.get_language() full_exe = [ninja_quote(x) for x in self.environment.get_build_command()] + [ '--internal', 'dirchanger', '$RUNDIR', ] invoc = (' '.join(full_exe) + ' ' + ' '.join(ninja_quote(i) for i in compiler.get_exelist())) command = ' command = %s $ARGS $in\n' % invoc description = ' description = Compiling Swift source $in.\n' outfile.write(rule) outfile.write(command) outfile.write(description) outfile.write('\n') def generate_fortran_dep_hack(self, outfile): if mesonlib.is_windows(): cmd = 'cmd /C ""' else: cmd = 'true' template = '''# Workaround for these issues: # https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485 rule FORTRAN_DEP_HACK command = %s description = Dep hack restat = 1 ''' outfile.write(template % cmd) def generate_llvm_ir_compile_rule(self, compiler, is_cross, outfile): if getattr(self, 'created_llvm_ir_rule', False): return rule = 'rule llvm_ir{}_COMPILER\n'.format('_CROSS' if is_cross else '') if mesonlib.is_windows(): command_template = ' command = {executable} @$out.rsp\n' \ ' rspfile = $out.rsp\n' \ ' rspfile_content = {cross_args} $ARGS {output_args} {compile_only_args} $in\n' else: command_template = ' command = {executable} {cross_args} $ARGS {output_args} {compile_only_args} $in\n' command = command_template.format( executable=' '.join([ninja_quote(i) for i in compiler.get_exelist()]), cross_args=' '.join(self.get_cross_info_lang_args(compiler.language, is_cross)), output_args=' '.join(compiler.get_output_args('$out')), compile_only_args=' '.join(compiler.get_compile_only_args()) ) description = ' description = Compiling LLVM IR object $in.\n' outfile.write(rule) outfile.write(command) outfile.write(description) outfile.write('\n') self.created_llvm_ir_rule = True def get_cross_info_lang_args(self, lang, is_cross): if is_cross: try: return self.environment.cross_info.config['properties'][lang + '_args'] except KeyError: pass return [] def generate_compile_rule_for(self, langname, compiler, is_cross, outfile): if langname == 'java': if not is_cross: self.generate_java_compile_rule(compiler, outfile) return if langname == 'cs': if not is_cross: self.generate_cs_compile_rule(compiler, outfile) return if langname == 'vala': if not is_cross: self.generate_vala_compile_rules(compiler, outfile) return if langname == 'rust': self.generate_rust_compile_rules(compiler, outfile, is_cross) return if langname == 'swift': if not is_cross: self.generate_swift_compile_rules(compiler, outfile) return if langname == 'fortran': self.generate_fortran_dep_hack(outfile) if is_cross: crstr = '_CROSS' else: crstr = '' rule = 'rule %s%s_COMPILER\n' % (langname, crstr) depargs = compiler.get_dependency_gen_args('$out', '$DEPFILE') quoted_depargs = [] for d in depargs: if d != '$out' and d != '$in': d = quote_func(d) quoted_depargs.append(d) cross_args = self.get_cross_info_lang_args(langname, is_cross) if mesonlib.is_windows(): command_template = ''' command = {executable} @$out.rsp rspfile = $out.rsp rspfile_content = {cross_args} $ARGS {dep_args} {output_args} {compile_only_args} $in ''' else: command_template = ' command = {executable} {cross_args} $ARGS {dep_args} {output_args} {compile_only_args} $in\n' command = command_template.format( executable=' '.join([ninja_quote(i) for i in compiler.get_exelist()]), cross_args=' '.join(cross_args), dep_args=' '.join(quoted_depargs), output_args=' '.join(compiler.get_output_args('$out')), compile_only_args=' '.join(compiler.get_compile_only_args()) ) description = ' description = Compiling %s object $out.\n' % compiler.get_display_language() if compiler.get_id() == 'msvc': deps = ' deps = msvc\n' else: deps = ' deps = gcc\n' deps += ' depfile = $DEPFILE\n' outfile.write(rule) outfile.write(command) outfile.write(deps) outfile.write(description) outfile.write('\n') def generate_pch_rule_for(self, langname, compiler, is_cross, outfile): if langname != 'c' and langname != 'cpp': return if is_cross: crstr = '_CROSS' else: crstr = '' rule = 'rule %s%s_PCH\n' % (langname, crstr) depargs = compiler.get_dependency_gen_args('$out', '$DEPFILE') cross_args = [] if is_cross: try: cross_args = self.environment.cross_info.config['properties'][langname + '_args'] except KeyError: pass quoted_depargs = [] for d in depargs: if d != '$out' and d != '$in': d = quote_func(d) quoted_depargs.append(d) if compiler.get_id() == 'msvc': output = '' else: output = ' '.join(compiler.get_output_args('$out')) command = " command = {executable} {cross_args} $ARGS {dep_args} {output_args} {compile_only_args} $in\n".format( executable=' '.join(compiler.get_exelist()), cross_args=' '.join(cross_args), dep_args=' '.join(quoted_depargs), output_args=output, compile_only_args=' '.join(compiler.get_compile_only_args()) ) description = ' description = Precompiling header %s.\n' % '$in' if compiler.get_id() == 'msvc': deps = ' deps = msvc\n' else: deps = ' deps = gcc\n' deps += ' depfile = $DEPFILE\n' outfile.write(rule) outfile.write(command) outfile.write(deps) outfile.write(description) outfile.write('\n') def generate_compile_rules(self, outfile): for langname, compiler in self.build.compilers.items(): if compiler.get_id() == 'clang': self.generate_llvm_ir_compile_rule(compiler, False, outfile) self.generate_compile_rule_for(langname, compiler, False, outfile) self.generate_pch_rule_for(langname, compiler, False, outfile) if self.environment.is_cross_build(): # In case we are going a target-only build, make the native compilers # masquerade as cross compilers. if self.environment.cross_info.need_cross_compiler(): cclist = self.build.cross_compilers else: cclist = self.build.compilers for langname, compiler in cclist.items(): if compiler.get_id() == 'clang': self.generate_llvm_ir_compile_rule(compiler, True, outfile) self.generate_compile_rule_for(langname, compiler, True, outfile) self.generate_pch_rule_for(langname, compiler, True, outfile) outfile.write('\n') def generate_generator_list_rules(self, target, outfile): # CustomTargets have already written their rules and # CustomTargetIndexes don't actually get generated, so write rules for # GeneratedLists here for genlist in target.get_generated_sources(): if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)): continue self.generate_genlist_for_target(genlist, target, outfile) def replace_paths(self, target, args, override_subdir=None): if override_subdir: source_target_dir = os.path.join(self.build_to_src, override_subdir) else: source_target_dir = self.get_target_source_dir(target) relout = self.get_target_private_dir(target) args = [x.replace("@SOURCE_DIR@", self.build_to_src).replace("@BUILD_DIR@", relout) for x in args] args = [x.replace("@CURRENT_SOURCE_DIR@", source_target_dir) for x in args] args = [x.replace("@SOURCE_ROOT@", self.build_to_src).replace("@BUILD_ROOT@", '.') for x in args] args = [x.replace('\\', '/') for x in args] return args def generate_genlist_for_target(self, genlist, target, outfile): generator = genlist.get_generator() subdir = genlist.subdir exe = generator.get_exe() exe_arr = self.exe_object_to_cmd_array(exe) infilelist = genlist.get_inputs() outfilelist = genlist.get_outputs() extra_dependencies = [os.path.join(self.build_to_src, i) for i in genlist.extra_depends] for i in range(len(infilelist)): if len(generator.outputs) == 1: sole_output = os.path.join(self.get_target_private_dir(target), outfilelist[i]) else: sole_output = '' curfile = infilelist[i] infilename = curfile.rel_to_builddir(self.build_to_src) base_args = generator.get_arglist(infilename) outfiles = genlist.get_outputs_for(curfile) outfiles = [os.path.join(self.get_target_private_dir(target), of) for of in outfiles] if generator.depfile is None: rulename = 'CUSTOM_COMMAND' args = base_args else: rulename = 'CUSTOM_COMMAND_DEP' depfilename = generator.get_dep_outname(infilename) depfile = os.path.join(self.get_target_private_dir(target), depfilename) args = [x.replace('@DEPFILE@', depfile) for x in base_args] args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output) for x in args] args = self.replace_outputs(args, self.get_target_private_dir(target), outfilelist) # We have consumed output files, so drop them from the list of remaining outputs. if sole_output == '': outfilelist = outfilelist[len(generator.outputs):] args = self.replace_paths(target, args, override_subdir=subdir) cmdlist = exe_arr + self.replace_extra_args(args, genlist) if generator.capture: exe_data = self.serialize_executable( cmdlist[0], cmdlist[1:], self.environment.get_build_dir(), capture=outfiles[0] ) cmd = self.environment.get_build_command() + ['--internal', 'exe', exe_data] abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) os.makedirs(abs_pdir, exist_ok=True) else: cmd = cmdlist elem = NinjaBuildElement(self.all_outputs, outfiles, rulename, infilename) if generator.depfile is not None: elem.add_item('DEPFILE', depfile) if len(extra_dependencies) > 0: elem.add_dep(extra_dependencies) elem.add_item('DESC', 'Generating {!r}.'.format(sole_output)) if isinstance(exe, build.BuildTarget): elem.add_dep(self.get_target_filename(exe)) elem.add_item('COMMAND', cmd) elem.write(outfile) def scan_fortran_module_outputs(self, target): compiler = None for lang, c in self.build.compilers.items(): if lang == 'fortran': compiler = c break if compiler is None: self.fortran_deps[target.get_basename()] = {} return modre = re.compile(r"\s*module\s+(\w+)", re.IGNORECASE) module_files = {} for s in target.get_sources(): # FIXME, does not work for Fortran sources generated by # custom_target() and generator() as those are run after # the configuration (configure_file() is OK) if not compiler.can_compile(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: for line in f: modmatch = modre.match(line) if modmatch is not None: modname = modmatch.group(1).lower() if modname == 'procedure': # MODULE PROCEDURE construct continue if modname in module_files: raise InvalidArguments( 'Namespace collision: module %s defined in ' 'two files %s and %s.' % (modname, module_files[modname], s)) module_files[modname] = s self.fortran_deps[target.get_basename()] = module_files def get_fortran_deps(self, compiler, src, target): mod_files = [] usere = re.compile(r"\s*use\s+(\w+)", re.IGNORECASE) dirname = self.get_target_private_dir(target) tdeps = self.fortran_deps[target.get_basename()] with open(src) as f: for line in f: usematch = usere.match(line) if usematch is not None: usename = usematch.group(1).lower() if usename not in tdeps: # The module is not provided by any source file. This # is due to: # a) missing file/typo/etc # b) using a module provided by the compiler, such as # OpenMP # There's no easy way to tell which is which (that I # know of) so just ignore this and go on. Ideally we # would print a warning message to the user but this is # a common occurrence, which would lead to lots of # distracting noise. continue mod_source_file = tdeps[usename] # Check if a source uses a module it exports itself. # Potential bug if multiple targets have a file with # the same name. if mod_source_file.fname == os.path.basename(src): continue mod_name = compiler.module_name_to_filename( usematch.group(1)) mod_files.append(os.path.join(dirname, mod_name)) return mod_files def get_cross_stdlib_args(self, target, compiler): if not target.is_cross: return [] if not self.environment.cross_info.has_stdlib(compiler.language): return [] return compiler.get_no_stdinc_args() def get_compile_debugfile_args(self, compiler, target, objfile): if compiler.id != 'msvc': return [] # The way MSVC uses PDB files is documented exactly nowhere so # the following is what we have been able to decipher via # reverse engineering. # # Each object file gets the path of its PDB file written # inside it. This can be either the final PDB (for, say, # foo.exe) or an object pdb (for foo.obj). If the former, then # each compilation step locks the pdb file for writing, which # is a bottleneck and object files from one target can not be # used in a different target. The latter seems to be the # sensible one (and what Unix does) but there is a catch. If # you try to use precompiled headers MSVC will error out # because both source and pch pdbs go in the same file and # they must be the same. # # This means: # # - pch files must be compiled anew for every object file (negating # the entire point of having them in the first place) # - when using pch, output must go to the target pdb # # Since both of these are broken in some way, use the one that # works for each target. This unfortunately means that you # can't combine pch and object extraction in a single target. # # PDB files also lead to filename collisions. A target foo.exe # has a corresponding foo.pdb. A shared library foo.dll _also_ # has pdb file called foo.pdb. So will a static library # foo.lib, which clobbers both foo.pdb _and_ the dll file's # export library called foo.lib (by default, currently we name # them libfoo.a to avoidt this issue). You can give the files # unique names such as foo_exe.pdb but VC also generates a # bunch of other files which take their names from the target # basename (i.e. "foo") and stomp on each other. # # CMake solves this problem by doing two things. First of all # static libraries do not generate pdb files at # all. Presumably you don't need them and VC is smart enough # to look up the original data when linking (speculation, not # tested). The second solution is that you can only have # target named "foo" as an exe, shared lib _or_ static # lib. This makes filename collisions not happen. The downside # is that you can't have an executable foo that uses a shared # library libfoo.so, which is a common idiom on Unix. # # If you feel that the above is completely wrong and all of # this is actually doable, please send patches. if target.has_pch(): tfilename = self.get_target_filename_abs(target) return compiler.get_compile_debugfile_args(tfilename, pch=True) else: return compiler.get_compile_debugfile_args(objfile, pch=False) def get_link_debugfile_args(self, linker, target, outname): return linker.get_link_debugfile_args(outname) def generate_llvm_ir_compile(self, target, outfile, src): compiler = get_compiler_for_source(target.compilers.values(), src) commands = CompilerArgs(compiler) # Compiler args for compiling this target commands += compilers.get_base_compile_args(self.environment.coredata.base_options, compiler) if isinstance(src, File): if src.is_built: src_filename = os.path.join(src.subdir, src.fname) else: src_filename = src.fname elif os.path.isabs(src): src_filename = os.path.basename(src) else: src_filename = src obj_basename = src_filename.replace('/', '_').replace('\\', '_') rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename) rel_obj += '.' + self.environment.get_object_suffix() commands += self.get_compile_debugfile_args(compiler, target, rel_obj) if isinstance(src, File) and src.is_built: rel_src = src.fname elif isinstance(src, File): rel_src = src.rel_to_builddir(self.build_to_src) else: raise InvalidArguments('Invalid source type: {!r}'.format(src)) # Write the Ninja build command compiler_name = 'llvm_ir{}_COMPILER'.format('_CROSS' if target.is_cross else '') element = NinjaBuildElement(self.all_outputs, rel_obj, compiler_name, rel_src) # Convert from GCC-style link argument naming to the naming used by the # current compiler. commands = commands.to_native() element.add_item('ARGS', commands) element.write(outfile) return rel_obj def get_source_dir_include_args(self, target, compiler): curdir = target.get_subdir() tmppath = os.path.normpath(os.path.join(self.build_to_src, curdir)) return compiler.get_include_args(tmppath, False) def get_build_dir_include_args(self, target, compiler): curdir = target.get_subdir() if curdir == '': curdir = '.' return compiler.get_include_args(curdir, False) def get_custom_target_dir_include_args(self, target, compiler): custom_target_include_dirs = [] for i in target.get_generated_sources(): # Generator output goes into the target private dir which is # already in the include paths list. Only custom targets have their # own target build dir. if not isinstance(i, (build.CustomTarget, build.CustomTargetIndex)): continue idir = self.get_target_dir(i) if idir not in custom_target_include_dirs: custom_target_include_dirs.append(idir) incs = [] for i in custom_target_include_dirs: incs += compiler.get_include_args(i, False) return incs def _generate_single_compile(self, target, compiler, is_generated=False): base_proxy = self.get_base_options_for_target(target) # Create an empty commands list, and start adding arguments from # various sources in the order in which they must override each other commands = CompilerArgs(compiler) # Add compiler args for compiling this target derived from 'base' build # options passed on the command-line, in default_options, etc. # These have the lowest priority. commands += compilers.get_base_compile_args(base_proxy, compiler) # The code generated by valac is usually crap and has tons of unused # variables and such, so disable warnings for Vala C sources. no_warn_args = (is_generated == 'vala') # Add compiler args and include paths from several sources; defaults, # build options, external dependencies, etc. commands += self.generate_basic_compiler_args(target, compiler, no_warn_args) # Add custom target dirs as includes automatically, but before # target-specific include directories. # XXX: Not sure if anyone actually uses this? It can cause problems in # situations which increase the likelihood for a header name collision, # such as in subprojects. commands += self.get_custom_target_dir_include_args(target, compiler) # Add include dirs from the `include_directories:` kwarg on the target # and from `include_directories:` of internal deps of the target. # # Target include dirs should override internal deps include dirs. # This is handled in BuildTarget.process_kwargs() # # Include dirs from internal deps should override include dirs from # external deps and must maintain the order in which they are specified. # Hence, we must reverse the list so that the order is preserved. for i in reversed(target.get_include_dirs()): basedir = i.get_curdir() for d in i.get_incdirs(): # Avoid superfluous '/.' at the end of paths when d is '.' if d not in ('', '.'): expdir = os.path.join(basedir, d) else: expdir = basedir srctreedir = os.path.join(self.build_to_src, expdir) # Add source subdir first so that the build subdir overrides it sargs = compiler.get_include_args(srctreedir, i.is_system) commands += sargs # There may be include dirs where a build directory has not been # created for some source dir. For example if someone does this: # # inc = include_directories('foo/bar/baz') # # But never subdir()s into the actual dir. if os.path.isdir(os.path.join(self.environment.get_build_dir(), expdir)): bargs = compiler.get_include_args(expdir, i.is_system) else: bargs = [] commands += bargs for d in i.get_extra_build_dirs(): commands += compiler.get_include_args(d, i.is_system) # Add per-target compile args, f.ex, `c_args : ['-DFOO']`. We set these # near the end since these are supposed to override everything else. commands += self.escape_extra_args(compiler, target.get_extra_args(compiler.get_language())) # Add source dir and build dir. Project-specific and target-specific # include paths must override per-target compile args, include paths # from external dependencies, internal dependencies, and from # per-target `include_directories:` # # We prefer headers in the build dir over the source dir since, for # instance, the user might have an srcdir == builddir Autotools build # in their source tree. Many projects that are moving to Meson have # both Meson and Autotools in parallel as part of the transition. if target.implicit_include_directories: commands += self.get_source_dir_include_args(target, compiler) if target.implicit_include_directories: commands += self.get_build_dir_include_args(target, compiler) # Finally add the private dir for the target to the include path. This # must override everything else and must be the final path added. commands += compiler.get_include_args(self.get_target_private_dir(target), False) return commands def generate_single_compile(self, target, outfile, src, is_generated=False, header_deps=[], order_deps=[]): """ Compiles C/C++, ObjC/ObjC++, Fortran, and D sources """ if isinstance(src, str) and src.endswith('.h'): raise AssertionError('BUG: sources should not contain headers {!r}'.format(src)) compiler = get_compiler_for_source(target.compilers.values(), src) key = (target, compiler, is_generated) if key in self.target_arg_cache: commands = self.target_arg_cache[key] else: commands = self._generate_single_compile(target, compiler, is_generated) self.target_arg_cache[key] = commands commands = CompilerArgs(commands.compiler, commands) build_dir = self.environment.get_build_dir() if isinstance(src, File): rel_src = src.rel_to_builddir(self.build_to_src) if os.path.isabs(rel_src): # Source files may not be from the source directory if they originate in source-only libraries, # so we can't assert that the absolute path is anywhere in particular. if src.is_built: assert rel_src.startswith(build_dir) rel_src = rel_src[len(build_dir) + 1:] elif is_generated: raise AssertionError('BUG: broken generated source file handling for {!r}'.format(src)) else: raise InvalidArguments('Invalid source type: {!r}'.format(src)) obj_basename = self.object_filename_from_source(target, src, self.is_unity(target)) rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename) dep_file = compiler.depfile_for_object(rel_obj) # Add MSVC debug file generation compile flags: /Fd /FS commands += self.get_compile_debugfile_args(compiler, target, rel_obj) # PCH handling if self.environment.coredata.base_options.get('b_pch', False): commands += self.get_pch_include_args(compiler, target) pchlist = target.get_pch(compiler.language) else: pchlist = [] if not pchlist: pch_dep = [] elif compiler.id == 'intel': pch_dep = [] else: arr = [] i = os.path.join(self.get_target_private_dir(target), compiler.get_pch_name(pchlist[0])) arr.append(i) pch_dep = arr crstr = '' if target.is_cross: crstr = '_CROSS' compiler_name = '%s%s_COMPILER' % (compiler.get_language(), crstr) extra_deps = [] if compiler.get_language() == 'fortran': # Can't read source file to scan for deps if it's generated later # at build-time. Skip scanning for deps, and just set the module # outdir argument instead. # https://github.com/mesonbuild/meson/issues/1348 if not is_generated: abs_src = os.path.join(build_dir, rel_src) extra_deps += self.get_fortran_deps(compiler, abs_src, target) # Dependency hack. Remove once multiple outputs in Ninja is fixed: # https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8 for modname, srcfile in self.fortran_deps[target.get_basename()].items(): modfile = os.path.join(self.get_target_private_dir(target), compiler.module_name_to_filename(modname)) if srcfile == src: depelem = NinjaBuildElement(self.all_outputs, modfile, 'FORTRAN_DEP_HACK', rel_obj) depelem.write(outfile) commands += compiler.get_module_outdir_args(self.get_target_private_dir(target)) if compiler.language == 'd': commands += compiler.get_feature_args(target.d_features, self.build_to_src) 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) for d in extra_deps: element.add_dep(d) for d in order_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_orderdep(d) element.add_orderdep(pch_dep) # Convert from GCC-style link argument naming to the naming used by the # current compiler. commands = commands.to_native() for i in self.get_fortran_orderdeps(target, compiler): element.add_orderdep(i) element.add_item('DEPFILE', dep_file) element.add_item('ARGS', commands) element.write(outfile) return rel_obj def has_dir_part(self, fname): # FIXME FIXME: The usage of this is a terrible and unreliable hack if isinstance(fname, File): return fname.subdir != '' return '/' in fname or '\\' in fname # Fortran is a bit weird (again). When you link against a library, just compiling a source file # requires the mod files that are output when single files are built. To do this right we would need to # scan all inputs and write out explicit deps for each file. That is stoo slow and too much effort so # instead just have an ordered dependency on the library. This ensures all required mod files are created. # The real deps are then detected via dep file generation from the compiler. This breaks on compilers that # produce incorrect dep files but such is life. def get_fortran_orderdeps(self, target, compiler): if compiler.language != 'fortran': return [] return [os.path.join(self.get_target_dir(lt), lt.get_filename()) for lt in target.link_targets] def generate_msvc_pch_command(self, target, compiler, pch): if len(pch) != 2: raise MesonException('MSVC requires one header and one source to produce precompiled headers.') header = pch[0] source = pch[1] pchname = compiler.get_pch_name(header) dst = os.path.join(self.get_target_private_dir(target), pchname) commands = [] commands += self.generate_basic_compiler_args(target, compiler) just_name = os.path.basename(header) (objname, pch_args) = compiler.gen_pch_args(just_name, source, dst) commands += pch_args commands += self.get_compile_debugfile_args(compiler, target, objname) dep = dst + '.' + compiler.get_depfile_suffix() return commands, dep, dst, [objname] def generate_gcc_pch_command(self, target, compiler, pch): commands = self._generate_single_compile(target, compiler) dst = os.path.join(self.get_target_private_dir(target), os.path.basename(pch) + '.' + compiler.get_pch_suffix()) 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): cstr = '' pch_objects = [] if target.is_cross: cstr = '_CROSS' for lang in ['c', 'cpp']: pch = target.get_pch(lang) if not pch: continue if '/' not in pch[0] or '/' not in pch[-1]: msg = 'Precompiled header of {!r} must not be in the same ' \ 'directory as source, please put it in a subdirectory.' \ ''.format(target.get_basename()) raise InvalidArguments(msg) compiler = target.compilers[lang] if compiler.id == 'msvc': src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[-1]) (commands, dep, dst, objs) = self.generate_msvc_pch_command(target, compiler, pch) extradep = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0]) elif compiler.id == 'intel': # Intel generates on target generation continue else: src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0]) (commands, dep, dst, objs) = self.generate_gcc_pch_command(target, compiler, pch[0]) extradep = None pch_objects += objs rulename = compiler.get_language() + cstr + '_PCH' elem = NinjaBuildElement(self.all_outputs, dst, rulename, src) if extradep is not None: elem.add_dep(extradep) elem.add_item('ARGS', commands) elem.add_item('DEPFILE', dep) elem.write(outfile) return pch_objects def generate_shsym(self, outfile, target): target_name = self.get_target_filename(target) targetdir = self.get_target_private_dir(target) symname = os.path.join(targetdir, target_name + '.symbols') elem = NinjaBuildElement(self.all_outputs, symname, 'SHSYM', target_name) if self.environment.is_cross_build() and self.environment.cross_info.need_cross_compiler(): elem.add_item('CROSS', '--cross-host=' + self.environment.cross_info.config['host_machine']['system']) elem.write(outfile) def get_cross_stdlib_link_args(self, target, linker): if isinstance(target, build.StaticLibrary) or not target.is_cross: return [] if not self.environment.cross_info.has_stdlib(linker.language): return [] return linker.get_no_stdlib_link_args() def get_target_type_link_args(self, target, linker): abspath = os.path.join(self.environment.get_build_dir(), target.subdir) commands = [] if isinstance(target, build.Executable): # Currently only used with the Swift compiler to add '-emit-executable' commands += linker.get_std_exe_link_args() # If gui_app, and that's significant on this platform if target.gui_app and hasattr(linker, 'get_gui_app_args'): commands += linker.get_gui_app_args() # If export_dynamic, add the appropriate linker arguments if target.export_dynamic: commands += linker.gen_export_dynamic_link_args(self.environment) # If implib, and that's significant on this platform (i.e. Windows using either GCC or Visual Studio) if target.import_filename: commands += linker.gen_import_library_args(os.path.join(self.get_target_dir(target), target.import_filename)) elif isinstance(target, build.SharedLibrary): if isinstance(target, build.SharedModule): commands += linker.get_std_shared_module_link_args() else: commands += linker.get_std_shared_lib_link_args() # All shared libraries are PIC commands += linker.get_pic_args() # Add -Wl,-soname arguments on Linux, -install_name on OS X commands += linker.get_soname_args(target.prefix, target.name, target.suffix, abspath, target.soversion, isinstance(target, build.SharedModule)) # This is only visited when building for Windows using either GCC or Visual Studio if target.vs_module_defs and hasattr(linker, 'gen_vs_module_defs_args'): commands += linker.gen_vs_module_defs_args(target.vs_module_defs.rel_to_builddir(self.build_to_src)) # This is only visited when building for Windows using either GCC or Visual Studio if target.import_filename: commands += linker.gen_import_library_args(os.path.join(self.get_target_dir(target), target.import_filename)) elif isinstance(target, build.StaticLibrary): commands += linker.get_std_link_args() else: raise RuntimeError('Unknown build target type.') return commands def get_link_whole_args(self, linker, target): target_args = self.build_target_link_arguments(linker, target.link_whole_targets) return linker.get_link_whole_for(target_args) if len(target_args) else [] def generate_link(self, target, outfile, outname, obj_list, linker, extra_args=[]): if isinstance(target, build.StaticLibrary): linker_base = 'STATIC' else: linker_base = linker.get_language() # Fixme. if isinstance(target, build.SharedLibrary): self.generate_shsym(outfile, target) crstr = '' if target.is_cross: crstr = '_CROSS' linker_rule = linker_base + crstr + '_LINKER' # Create an empty commands list, and start adding link arguments from # various sources in the order in which they must override each other # starting from hard-coded defaults followed by build options and so on. # # Once all the linker options have been passed, we will start passing # libraries and library paths from internal and external sources. commands = CompilerArgs(linker) # First, the trivial ones that are impossible to override. # # Add linker args for linking this target derived from 'base' build # options passed on the command-line, in default_options, etc. # These have the lowest priority. if not isinstance(target, build.StaticLibrary): commands += compilers.get_base_link_args(self.environment.coredata.base_options, linker, isinstance(target, build.SharedModule)) # Add -nostdlib if needed; can't be overridden commands += self.get_cross_stdlib_link_args(target, linker) # Add things like /NOLOGO; usually can't be overridden commands += linker.get_linker_always_args() # Add buildtype linker args: optimization level, etc. commands += linker.get_buildtype_linker_args(self.get_option_for_target('buildtype', target)) # Add /DEBUG and the pdb filename when using MSVC commands += self.get_link_debugfile_args(linker, target, outname) # Add link args specific to this BuildTarget type, such as soname args, # PIC, import library generation, etc. commands += self.get_target_type_link_args(target, linker) # Archives that are copied wholesale in the result. Must be before any # other link targets so missing symbols from whole archives are found in those. if not isinstance(target, build.StaticLibrary): commands += self.get_link_whole_args(linker, target) if not isinstance(target, build.StaticLibrary): # Add link args added using add_project_link_arguments() commands += self.build.get_project_link_args(linker, target.subproject) # Add link args added using add_global_link_arguments() # These override per-project link arguments commands += self.build.get_global_link_args(linker) if not target.is_cross: # Link args added from the env: LDFLAGS. We want these to # override all the defaults but not the per-target link args. commands += self.environment.coredata.external_link_args[linker.get_language()] # Now we will add libraries and library paths from various sources # Add link args to link to all internal libraries (link_with:) and # internal dependencies needed by this target. if linker_base == 'STATIC': # Link arguments of static libraries are not put in the command # line of the library. They are instead appended to the command # line where the static library is used. dependencies = [] else: dependencies = target.get_dependencies() commands += self.build_target_link_arguments(linker, dependencies) # For 'automagic' deps: Boost and GTest. Also dependency('threads'). # pkg-config puts the thread flags itself via `Cflags:` for d in target.external_deps: if d.need_threads(): commands += linker.thread_link_flags(self.environment) # Only non-static built targets need link args and link dependencies if not isinstance(target, build.StaticLibrary): commands += target.link_args # External deps must be last because target link libraries may depend on them. for dep in target.get_external_deps(): # Extend without reordering or de-dup to preserve `-L -l` sets # https://github.com/mesonbuild/meson/issues/1718 commands.extend_direct(dep.get_link_args()) for d in target.get_dependencies(): if isinstance(d, build.StaticLibrary): for dep in d.get_external_deps(): commands.extend_direct(dep.get_link_args()) # Add link args for c_* or cpp_* build options. Currently this only # adds c_winlibs and cpp_winlibs when building for Windows. This needs # to be after all internal and external libraries so that unresolved # symbols from those can be found here. This is needed when the # *_winlibs that we want to link to are static mingw64 libraries. commands += linker.get_option_link_args(self.environment.coredata.compiler_options) # 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 '/' in target.name or '\\' in 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) commands += linker.build_rpath_args(self.environment.get_build_dir(), target_slashname_workaround_dir, self.determine_rpath_dirs(target), target.build_rpath, target.install_rpath) # Add libraries generated by custom targets custom_target_libraries = self.get_custom_target_provided_libraries(target) commands += extra_args commands += custom_target_libraries # Convert from GCC-style link argument naming to the naming used by the # current compiler. commands = commands.to_native() dep_targets = [self.get_dependency_filename(t) for t in dependencies] dep_targets.extend([self.get_dependency_filename(t) for t in target.link_depends]) elem = NinjaBuildElement(self.all_outputs, outname, linker_rule, obj_list) elem.add_dep(dep_targets + custom_target_libraries) elem.add_item('LINK_ARGS', commands) return elem def get_dependency_filename(self, t): if isinstance(t, build.SharedLibrary): return os.path.join(self.get_target_private_dir(t), self.get_target_filename(t) + '.symbols') elif isinstance(t, mesonlib.File): if t.is_built: return t.relative_name() else: return t.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) return self.get_target_filename(t) def generate_shlib_aliases(self, target, outdir): aliases = target.get_aliases() for alias, to in aliases.items(): aliasfile = os.path.join(self.environment.get_build_dir(), outdir, alias) try: os.remove(aliasfile) except Exception: pass try: os.symlink(to, aliasfile) except NotImplementedError: mlog.debug("Library versioning disabled because symlinks are not supported.") except OSError: mlog.debug("Library versioning disabled because we do not have symlink creation privileges.") def generate_custom_target_clean(self, outfile, trees): e = NinjaBuildElement(self.all_outputs, 'meson-clean-ctlist', 'CUSTOM_COMMAND', 'PHONY') d = CleanTrees(self.environment.get_build_dir(), trees) d_file = os.path.join(self.environment.get_scratch_dir(), 'cleantrees.dat') e.add_item('COMMAND', self.environment.get_build_command() + ['--internal', 'cleantrees', d_file]) e.add_item('description', 'Cleaning custom target directories.') e.write(outfile) # Alias that runs the target defined above self.create_target_alias('meson-clean-ctlist', outfile) # Write out the data file passed to the script with open(d_file, 'wb') as ofile: pickle.dump(d, ofile) return 'clean-ctlist' def generate_gcov_clean(self, outfile): gcno_elem = NinjaBuildElement(self.all_outputs, 'meson-clean-gcno', 'CUSTOM_COMMAND', 'PHONY') script_root = self.environment.get_script_dir() clean_script = os.path.join(script_root, 'delwithsuffix.py') gcno_elem.add_item('COMMAND', mesonlib.python_command + [clean_script, '.', 'gcno']) gcno_elem.add_item('description', 'Deleting gcno files.') gcno_elem.write(outfile) # Alias that runs the target defined above self.create_target_alias('meson-clean-gcno', outfile) gcda_elem = NinjaBuildElement(self.all_outputs, 'meson-clean-gcda', 'CUSTOM_COMMAND', 'PHONY') script_root = self.environment.get_script_dir() clean_script = os.path.join(script_root, 'delwithsuffix.py') gcda_elem.add_item('COMMAND', mesonlib.python_command + [clean_script, '.', 'gcda']) gcda_elem.add_item('description', 'Deleting gcda files.') gcda_elem.write(outfile) # Alias that runs the target defined above self.create_target_alias('meson-clean-gcda', outfile) def get_user_option_args(self): cmds = [] for (k, v) in self.environment.coredata.user_options.items(): cmds.append('-D' + k + '=' + (v.value if isinstance(v.value, str) else str(v.value).lower())) # The order of these arguments must be the same between runs of Meson # to ensure reproducible output. The order we pass them shouldn't # affect behavior in any other way. return sorted(cmds) def generate_dist(self, outfile): elem = NinjaBuildElement(self.all_outputs, 'meson-dist', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('DESC', 'Creating source packages') elem.add_item('COMMAND', self.environment.get_build_command() + [ '--internal', 'dist', self.environment.source_dir, self.environment.build_dir, ] + self.environment.get_build_command()) elem.add_item('pool', 'console') elem.write(outfile) # Alias that runs the target defined above self.create_target_alias('meson-dist', outfile) # For things like scan-build and other helper tools we might have. def generate_utils(self, outfile): cmd = self.environment.get_build_command() + \ ['--internal', 'scanbuild', self.environment.source_dir, self.environment.build_dir] + \ self.environment.get_build_command() + self.get_user_option_args() elem = NinjaBuildElement(self.all_outputs, 'meson-scan-build', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', cmd) elem.add_item('pool', 'console') elem.write(outfile) # Alias that runs the target defined above self.create_target_alias('meson-scan-build', outfile) cmd = self.environment.get_build_command() + ['--internal', 'uninstall'] elem = NinjaBuildElement(self.all_outputs, 'meson-uninstall', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', cmd) elem.add_item('pool', 'console') elem.write(outfile) # Alias that runs the target defined above self.create_target_alias('meson-uninstall', outfile) def generate_ending(self, outfile): targetlist = [] for t in self.get_build_by_default_targets().values(): # Add the first output of each target to the 'all' target so that # they are all built targetlist.append(os.path.join(self.get_target_dir(t), t.get_outputs()[0])) elem = NinjaBuildElement(self.all_outputs, 'all', 'phony', targetlist) elem.write(outfile) default = 'default all\n\n' outfile.write(default) elem = NinjaBuildElement(self.all_outputs, 'meson-clean', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', [self.ninja_command, '-t', 'clean']) elem.add_item('description', 'Cleaning.') # Alias that runs the above-defined meson-clean target self.create_target_alias('meson-clean', outfile) # If we have custom targets in this project, add all their outputs to # the list that is passed to the `cleantrees.py` script. The script # will manually delete all custom_target outputs that are directories # instead of files. This is needed because on platforms other than # Windows, Ninja only deletes directories while cleaning if they are # empty. https://github.com/mesonbuild/meson/issues/1220 ctlist = [] for t in self.build.get_targets().values(): if isinstance(t, build.CustomTarget): # Create a list of all custom target outputs for o in t.get_outputs(): ctlist.append(os.path.join(self.get_target_dir(t), o)) if ctlist: elem.add_dep(self.generate_custom_target_clean(outfile, ctlist)) if 'b_coverage' in self.environment.coredata.base_options and \ self.environment.coredata.base_options['b_coverage'].value: self.generate_gcov_clean(outfile) elem.add_dep('clean-gcda') elem.add_dep('clean-gcno') elem.write(outfile) deps = self.get_regen_filelist() elem = NinjaBuildElement(self.all_outputs, 'build.ninja', 'REGENERATE_BUILD', deps) elem.add_item('pool', 'console') elem.write(outfile) elem = NinjaBuildElement(self.all_outputs, 'reconfigure', 'REGENERATE_BUILD', 'PHONY') elem.add_item('pool', 'console') elem.write(outfile) elem = NinjaBuildElement(self.all_outputs, deps, 'phony', '') elem.write(outfile) def load(build_dir): filename = os.path.join(build_dir, 'meson-private', 'install.dat') with open(filename, 'rb') as f: obj = pickle.load(f) return obj meson-0.45.1/mesonbuild/rewriter.py0000644000175000017500000000476013254550710020703 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 # Copyright 2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool. # This tool is used to manipulate an existing Meson build definition. # # - add a file to a target # - remove files from a target # - move targets # - reindent? import mesonbuild.astinterpreter from mesonbuild.mesonlib import MesonException from mesonbuild import mlog import sys, traceback import argparse parser = argparse.ArgumentParser(prog='meson rewrite') parser.add_argument('--sourcedir', default='.', help='Path to source directory.') parser.add_argument('--target', default=None, help='Name of target to edit.') parser.add_argument('--filename', default=None, help='Name of source file to add or remove to target.') parser.add_argument('commands', nargs='+') def run(args): options = parser.parse_args(args) if options.target is None or options.filename is None: sys.exit("Must specify both target and filename.") print('This tool is highly experimental, use with care.') rewriter = mesonbuild.astinterpreter.AstInterpreter(options.sourcedir, '') try: if options.commands[0] == 'add': rewriter.add_source(options.target, options.filename) elif options.commands[0] == 'remove': rewriter.remove_source(options.target, options.filename) else: sys.exit('Unknown command: ' + options.commands[0]) except Exception as e: if isinstance(e, MesonException): if hasattr(e, 'file') and hasattr(e, 'lineno') and hasattr(e, 'colno'): mlog.log(mlog.red('\nMeson encountered an error in file %s, line %d, column %d:' % (e.file, e.lineno, e.colno))) else: mlog.log(mlog.red('\nMeson encountered an error:')) mlog.log(e) else: traceback.print_exc() return 1 return 0 meson-0.45.1/mesonbuild/mesonlib.py0000644000175000017500000010255013254550710020644 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2015 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. """A library of random helper functionality.""" import sys import stat import time import platform, subprocess, operator, os, shutil, re import collections from mesonbuild import mlog from glob import glob def detect_meson_py_location(): c = sys.argv[0] c_dir, c_fname = os.path.split(c) # get the absolute path to the folder m_dir = None if os.path.isabs(c): # $ /foo/.py m_dir = c_dir elif c_dir == '': # $ (gets run from /usr/bin/) in_path_exe = shutil.which(c_fname) if in_path_exe: if not os.path.isabs(in_path_exe): m_dir = os.getcwd() c_fname = in_path_exe else: m_dir, c_fname = os.path.split(in_path_exe) else: m_dir = os.path.abspath(c_dir) # find meson in m_dir if m_dir is not None: for fname in ['meson', 'meson.py']: m_path = os.path.join(m_dir, fname) if os.path.exists(m_path): return m_path # No meson found, which means that either: # a) meson is not installed # b) meson is installed to a non-standard location # c) the script that invoked mesonlib is not the one of meson tools (e.g. run_unittests.py) fname = os.path.normpath(os.path.join(os.path.dirname(__file__), '..', 'meson.py')) if os.path.exists(fname): return fname # If meson is still not found, we might be imported by out-of-source tests # https://github.com/mesonbuild/meson/issues/3015 exe = shutil.which('meson') if exe is None: exe = shutil.which('meson.py') if exe is not None: return exe # Give up. raise RuntimeError('Could not determine how to run Meson. Please file a bug with details.') if os.path.basename(sys.executable) == 'meson.exe': # In Windows and using the MSI installed executable. meson_command = [sys.executable] python_command = [sys.executable, 'runpython'] else: python_command = [sys.executable] meson_command = python_command + [detect_meson_py_location()] def is_ascii_string(astring): try: if isinstance(astring, str): astring.encode('ascii') if isinstance(astring, bytes): astring.decode('ascii') except UnicodeDecodeError: return False return True def check_direntry_issues(direntry_array): import locale # Warn if the locale is not UTF-8. This can cause various unfixable issues # such as os.stat not being able to decode filenames with unicode in them. # There is no way to reset both the preferred encoding and the filesystem # encoding, so we can just warn about it. e = locale.getpreferredencoding() if e.upper() != 'UTF-8' and not is_windows(): if not isinstance(direntry_array, list): direntry_array = [direntry_array] for de in direntry_array: if is_ascii_string(de): continue mlog.warning('''You are using {!r} which is not a Unicode-compatible ' locale but you are trying to access a file system entry called {!r} which is not pure ASCII. This may cause problems. '''.format(e, de), file=sys.stderr) # Put this in objects that should not get dumped to pickle files # by accident. import threading an_unpicklable_object = threading.Lock() class MesonException(Exception): '''Exceptions thrown by Meson''' class EnvironmentException(MesonException): '''Exceptions thrown while processing and creating the build environment''' class FileMode: # The first triad is for owner permissions, the second for group permissions, # and the third for others (everyone else). # For the 1st character: # 'r' means can read # '-' means not allowed # For the 2nd character: # 'w' means can write # '-' means not allowed # For the 3rd character: # 'x' means can execute # 's' means can execute and setuid/setgid is set (owner/group triads only) # 'S' means cannot execute and setuid/setgid is set (owner/group triads only) # 't' means can execute and sticky bit is set ("others" triads only) # 'T' means cannot execute and sticky bit is set ("others" triads only) # '-' means none of these are allowed # # The meanings of 'rwx' perms is not obvious for directories; see: # https://www.hackinglinuxexposed.com/articles/20030424.html # # For information on this notation such as setuid/setgid/sticky bits, see: # https://en.wikipedia.org/wiki/File_system_permissions#Symbolic_notation symbolic_perms_regex = re.compile('[r-][w-][xsS-]' # Owner perms '[r-][w-][xsS-]' # Group perms '[r-][w-][xtT-]') # Others perms def __init__(self, perms=None, owner=None, group=None): self.perms_s = perms self.perms = self.perms_s_to_bits(perms) self.owner = owner self.group = group def __repr__(self): ret = '='): cmpop = operator.ge vstr2 = vstr2[2:] elif vstr2.startswith('<='): cmpop = operator.le vstr2 = vstr2[2:] elif vstr2.startswith('!='): cmpop = operator.ne vstr2 = vstr2[2:] elif vstr2.startswith('=='): cmpop = operator.eq vstr2 = vstr2[2:] elif vstr2.startswith('='): cmpop = operator.eq vstr2 = vstr2[1:] elif vstr2.startswith('>'): cmpop = operator.gt vstr2 = vstr2[1:] elif vstr2.startswith('<'): cmpop = operator.lt vstr2 = vstr2[1:] else: cmpop = operator.eq varr1 = grab_leading_numbers(vstr1, strict) varr2 = grab_leading_numbers(vstr2, strict) return cmpop(varr1, varr2) def version_compare_many(vstr1, conditions): if not isinstance(conditions, (list, tuple, frozenset)): conditions = [conditions] found = [] not_found = [] for req in conditions: if not version_compare(vstr1, req, strict=True): not_found.append(req) else: found.append(req) return not_found == [], not_found, found def default_libdir(): if is_debianlike(): try: pc = subprocess.Popen(['dpkg-architecture', '-qDEB_HOST_MULTIARCH'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) (stdo, _) = pc.communicate() if pc.returncode == 0: archpath = stdo.decode().strip() return 'lib/' + archpath except Exception: pass if os.path.isdir('/usr/lib64') and not os.path.islink('/usr/lib64'): return 'lib64' return 'lib' def default_libexecdir(): # There is no way to auto-detect this, so it must be set at build time return 'libexec' def default_prefix(): return 'c:/' if is_windows() else '/usr/local' def get_library_dirs(): if is_windows(): return ['C:/mingw/lib'] # Fixme if is_osx(): return ['/usr/lib'] # Fix me as well. # The following is probably Debian/Ubuntu specific. # /usr/local/lib is first because it contains stuff # installed by the sysadmin and is probably more up-to-date # than /usr/lib. If you feel that this search order is # problematic, please raise the issue on the mailing list. unixdirs = ['/usr/local/lib', '/usr/lib', '/lib'] plat = subprocess.check_output(['uname', '-m']).decode().strip() # This is a terrible hack. I admit it and I'm really sorry. # I just don't know what the correct solution is. if plat == 'i686': plat = 'i386' if plat.startswith('arm'): plat = 'arm' unixdirs += glob('/usr/lib/' + plat + '*') if os.path.exists('/usr/lib64'): unixdirs.append('/usr/lib64') unixdirs += glob('/lib/' + plat + '*') if os.path.exists('/lib64'): unixdirs.append('/lib64') unixdirs += glob('/lib/' + plat + '*') return unixdirs def do_replacement(regex, line, confdata): missing_variables = set() def variable_replace(match): # Pairs of escape characters before '@' or '\@' if match.group(0).endswith('\\'): num_escapes = match.end(0) - match.start(0) return '\\' * (num_escapes // 2) # Single escape character and '@' elif match.group(0) == '\\@': return '@' # Template variable to be replaced else: varname = match.group(1) if varname in confdata: (var, desc) = confdata.get(varname) if isinstance(var, str): pass elif isinstance(var, int): var = str(var) else: raise RuntimeError('Tried to replace a variable with something other than a string or int.') else: missing_variables.add(varname) var = '' return var return re.sub(regex, variable_replace, line), missing_variables def do_mesondefine(line, confdata): arr = line.split() if len(arr) != 2: raise MesonException('#mesondefine does not contain exactly two tokens: %s', line.strip()) varname = arr[1] try: (v, desc) = confdata.get(varname) except KeyError: return '/* #undef %s */\n' % varname if isinstance(v, bool): if v: return '#define %s\n' % varname else: return '#undef %s\n' % varname elif isinstance(v, int): return '#define %s %d\n' % (varname, v) elif isinstance(v, str): return '#define %s %s\n' % (varname, v) else: raise MesonException('#mesondefine argument "%s" is of unknown type.' % varname) def do_conf_file(src, dst, confdata): try: with open(src, encoding='utf-8') as f: data = f.readlines() except Exception as e: raise MesonException('Could not read input file %s: %s' % (src, str(e))) # Only allow (a-z, A-Z, 0-9, _, -) as valid characters for a define # Also allow escaping '@' with '\@' regex = re.compile(r'(?:\\\\)+(?=\\?@)|\\@|@([-a-zA-Z0-9_]+)@') result = [] missing_variables = set() for line in data: if line.startswith('#mesondefine'): line = do_mesondefine(line, confdata) else: line, missing = do_replacement(regex, line, confdata) missing_variables.update(missing) result.append(line) dst_tmp = dst + '~' with open(dst_tmp, 'w', encoding='utf-8') as f: f.writelines(result) shutil.copymode(src, dst_tmp) replace_if_different(dst, dst_tmp) return missing_variables def dump_conf_header(ofilename, cdata): ofilename_tmp = ofilename + '~' with open(ofilename_tmp, 'w', encoding='utf-8') as ofile: ofile.write('''/* * Autogenerated by the Meson build system. * Do not edit, your changes will be lost. */ #pragma once ''') for k in sorted(cdata.keys()): (v, desc) = cdata.get(k) if desc: ofile.write('/* %s */\n' % desc) if isinstance(v, bool): if v: ofile.write('#define %s\n\n' % k) else: ofile.write('#undef %s\n\n' % k) elif isinstance(v, (int, str)): ofile.write('#define %s %s\n\n' % (k, v)) else: raise MesonException('Unknown data type in configuration file entry: ' + k) replace_if_different(ofilename, ofilename_tmp) def replace_if_different(dst, dst_tmp): # If contents are identical, don't touch the file to prevent # unnecessary rebuilds. different = True try: with open(dst, 'rb') as f1, open(dst_tmp, 'rb') as f2: if f1.read() == f2.read(): different = False except FileNotFoundError: pass if different: os.replace(dst_tmp, dst) else: os.unlink(dst_tmp) def listify(item, flatten=True, unholder=False): ''' Returns a list with all args embedded in a list if they are not a list. This function preserves order. @flatten: Convert lists of lists to a flat list @unholder: Replace each item with the object it holds, if required Note: unholding only works recursively when flattening ''' if not isinstance(item, list): if unholder and hasattr(item, 'held_object'): item = item.held_object return [item] result = [] for i in item: if unholder and hasattr(i, 'held_object'): i = i.held_object if flatten and isinstance(i, list): result += listify(i, flatten=True, unholder=unholder) else: result.append(i) return result def extract_as_list(dict_object, *keys, pop=False, **kwargs): ''' Extracts all values from given dict_object and listifies them. ''' result = [] fetch = dict_object.get if pop: fetch = dict_object.pop # If there's only one key, we don't return a list with one element if len(keys) == 1: return listify(fetch(keys[0], []), **kwargs) # Return a list of values corresponding to *keys for key in keys: result.append(listify(fetch(key, []), **kwargs)) return result def typeslistify(item, types): ''' Ensure that type(@item) is one of @types or a list of items all of which are of type @types ''' if isinstance(item, types): item = [item] if not isinstance(item, list): raise MesonException('Item must be a list or one of {!r}'.format(types)) for i in item: if i is not None and not isinstance(i, types): raise MesonException('List item must be one of {!r}'.format(types)) return item def stringlistify(item): return typeslistify(item, str) def expand_arguments(args): expended_args = [] for arg in args: if not arg.startswith('@'): expended_args.append(arg) continue args_file = arg[1:] try: with open(args_file) as f: extended_args = f.read().split() expended_args += extended_args except Exception as e: print('Error expanding command line arguments, %s not found' % args_file) print(e) return None return expended_args def Popen_safe(args, write=None, stderr=subprocess.PIPE, **kwargs): if sys.version_info < (3, 6) or not sys.stdout.encoding: return Popen_safe_legacy(args, write=write, stderr=stderr, **kwargs) p = subprocess.Popen(args, universal_newlines=True, close_fds=False, stdout=subprocess.PIPE, stderr=stderr, **kwargs) o, e = p.communicate(write) return p, o, e def Popen_safe_legacy(args, write=None, stderr=subprocess.PIPE, **kwargs): p = subprocess.Popen(args, universal_newlines=False, stdout=subprocess.PIPE, stderr=stderr, **kwargs) if write is not None: write = write.encode('utf-8') o, e = p.communicate(write) if o is not None: if sys.stdout.encoding: o = o.decode(encoding=sys.stdout.encoding, errors='replace').replace('\r\n', '\n') else: o = o.decode(errors='replace').replace('\r\n', '\n') if e is not None: if sys.stderr.encoding: e = e.decode(encoding=sys.stderr.encoding, errors='replace').replace('\r\n', '\n') else: e = e.decode(errors='replace').replace('\r\n', '\n') return p, o, e def iter_regexin_iter(regexiter, initer): ''' Takes each regular expression in @regexiter and tries to search for it in every item in @initer. If there is a match, returns that match. Else returns False. ''' for regex in regexiter: for ii in initer: if not isinstance(ii, str): continue match = re.search(regex, ii) if match: return match.group() return False def _substitute_values_check_errors(command, values): # Error checking inregex = ('@INPUT([0-9]+)?@', '@PLAINNAME@', '@BASENAME@') outregex = ('@OUTPUT([0-9]+)?@', '@OUTDIR@') if '@INPUT@' not in values: # Error out if any input-derived templates are present in the command match = iter_regexin_iter(inregex, command) if match: m = 'Command cannot have {!r}, since no input files were specified' raise MesonException(m.format(match)) else: if len(values['@INPUT@']) > 1: # Error out if @PLAINNAME@ or @BASENAME@ is present in the command match = iter_regexin_iter(inregex[1:], command) if match: raise MesonException('Command cannot have {!r} when there is ' 'more than one input file'.format(match)) # Error out if an invalid @INPUTnn@ template was specified for each in command: if not isinstance(each, str): continue match = re.search(inregex[0], each) if match and match.group() not in values: m = 'Command cannot have {!r} since there are only {!r} inputs' raise MesonException(m.format(match.group(), len(values['@INPUT@']))) if '@OUTPUT@' not in values: # Error out if any output-derived templates are present in the command match = iter_regexin_iter(outregex, command) if match: m = 'Command cannot have {!r} since there are no outputs' raise MesonException(m.format(match)) else: # Error out if an invalid @OUTPUTnn@ template was specified for each in command: if not isinstance(each, str): continue match = re.search(outregex[0], each) if match and match.group() not in values: m = 'Command cannot have {!r} since there are only {!r} outputs' raise MesonException(m.format(match.group(), len(values['@OUTPUT@']))) def substitute_values(command, values): ''' Substitute the template strings in the @values dict into the list of strings @command and return a new list. For a full list of the templates, see get_filenames_templates_dict() If multiple inputs/outputs are given in the @values dictionary, we substitute @INPUT@ and @OUTPUT@ only if they are the entire string, not just a part of it, and in that case we substitute *all* of them. ''' # Error checking _substitute_values_check_errors(command, values) # Substitution outcmd = [] rx_keys = [re.escape(key) for key in values if key not in ('@INPUT@', '@OUTPUT@')] value_rx = re.compile('|'.join(rx_keys)) if rx_keys else None for vv in command: if not isinstance(vv, str): outcmd.append(vv) elif '@INPUT@' in vv: inputs = values['@INPUT@'] if vv == '@INPUT@': outcmd += inputs elif len(inputs) == 1: outcmd.append(vv.replace('@INPUT@', inputs[0])) else: raise MesonException("Command has '@INPUT@' as part of a " "string and more than one input file") elif '@OUTPUT@' in vv: outputs = values['@OUTPUT@'] if vv == '@OUTPUT@': outcmd += outputs elif len(outputs) == 1: outcmd.append(vv.replace('@OUTPUT@', outputs[0])) else: raise MesonException("Command has '@OUTPUT@' as part of a " "string and more than one output file") # Append values that are exactly a template string. # This is faster than a string replace. elif vv in values: outcmd.append(values[vv]) # Substitute everything else with replacement elif value_rx: outcmd.append(value_rx.sub(lambda m: values[m.group(0)], vv)) else: outcmd.append(vv) return outcmd def get_filenames_templates_dict(inputs, outputs): ''' Create a dictionary with template strings as keys and values as values for the following templates: @INPUT@ - the full path to one or more input files, from @inputs @OUTPUT@ - the full path to one or more output files, from @outputs @OUTDIR@ - the full path to the directory containing the output files If there is only one input file, the following keys are also created: @PLAINNAME@ - the filename of the input file @BASENAME@ - the filename of the input file with the extension removed If there is more than one input file, the following keys are also created: @INPUT0@, @INPUT1@, ... one for each input file If there is more than one output file, the following keys are also created: @OUTPUT0@, @OUTPUT1@, ... one for each output file ''' values = {} # Gather values derived from the input if inputs: # We want to substitute all the inputs. values['@INPUT@'] = inputs for (ii, vv) in enumerate(inputs): # Write out @INPUT0@, @INPUT1@, ... values['@INPUT{}@'.format(ii)] = vv if len(inputs) == 1: # Just one value, substitute @PLAINNAME@ and @BASENAME@ values['@PLAINNAME@'] = plain = os.path.basename(inputs[0]) values['@BASENAME@'] = os.path.splitext(plain)[0] if outputs: # Gather values derived from the outputs, similar to above. values['@OUTPUT@'] = outputs for (ii, vv) in enumerate(outputs): values['@OUTPUT{}@'.format(ii)] = vv # Outdir should be the same for all outputs values['@OUTDIR@'] = os.path.dirname(outputs[0]) # Many external programs fail on empty arguments. if values['@OUTDIR@'] == '': values['@OUTDIR@'] = '.' return values def windows_proof_rmtree(f): # On Windows if anyone is holding a file open you can't # delete it. As an example an anti virus scanner might # be scanning files you are trying to delete. The only # way to fix this is to try again and again. delays = [0.1, 0.1, 0.2, 0.2, 0.2, 0.5, 0.5, 1, 1, 1, 1, 2] for d in delays: try: shutil.rmtree(f) return except FileNotFoundError: return except (OSError, PermissionError): time.sleep(d) # Try one last time and throw if it fails. shutil.rmtree(f) def detect_subprojects(spdir_name, current_dir='', result=None): if result is None: result = {} spdir = os.path.join(current_dir, spdir_name) if not os.path.exists(spdir): return result for trial in glob(os.path.join(spdir, '*')): basename = os.path.basename(trial) if trial == 'packagecache': continue append_this = True if os.path.isdir(trial): detect_subprojects(spdir_name, trial, result) elif trial.endswith('.wrap') and os.path.isfile(trial): basename = os.path.splitext(basename)[0] else: append_this = False if append_this: if basename in result: result[basename].append(trial) else: result[basename] = [trial] return result class OrderedSet(collections.MutableSet): """A set that preserves the order in which items are added, by first insertion. """ def __init__(self, iterable=None): self.__container = collections.OrderedDict() if iterable: self.update(iterable) def __contains__(self, value): return value in self.__container def __iter__(self): return iter(self.__container.keys()) def __len__(self): return len(self.__container) def __repr__(self): # Don't print 'OrderedSet("")' for an empty set. if self.__container: return 'OrderedSet("{}")'.format( '", "'.join(repr(e) for e in self.__container.keys())) return 'OrderedSet()' def add(self, value): self.__container[value] = None def discard(self, value): if value in self.__container: del self.__container[value] def update(self, iterable): for item in iterable: self.__container[item] = None def difference(self, set_): return type(self)(e for e in self if e not in set_) meson-0.45.1/mesonbuild/compilers/0000755000175000017500000000000013254552746020467 5ustar jpakkanejpakkane00000000000000meson-0.45.1/mesonbuild/compilers/d.py0000644000175000017500000003350013246615532021257 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os.path, subprocess from ..mesonlib import EnvironmentException, version_compare from .compilers import ( GCC_STANDARD, d_dmd_buildtype_args, d_gdc_buildtype_args, d_ldc_buildtype_args, get_gcc_soname_args, gnu_color_args, Compiler, CompilerArgs, ) d_feature_args = {'gcc': {'unittest': '-funittest', 'version': '-fversion', 'import_dir': '-J' }, 'llvm': {'unittest': '-unittest', 'version': '-d-version', 'import_dir': '-J' }, 'dmd': {'unittest': '-unittest', 'version': '-version', 'import_dir': '-J' } } class DCompiler(Compiler): def __init__(self, exelist, version, is_cross, **kwargs): self.language = 'd' super().__init__(exelist, version, **kwargs) self.id = 'unknown' self.is_cross = is_cross def sanity_check(self, work_dir, environment): source_name = os.path.join(work_dir, 'sanity.d') output_name = os.path.join(work_dir, 'dtest') with open(source_name, 'w') as ofile: ofile.write('''void main() { } ''') pc = subprocess.Popen(self.exelist + self.get_output_args(output_name) + [source_name], cwd=work_dir) pc.wait() if pc.returncode != 0: raise EnvironmentException('D compiler %s can not compile programs.' % self.name_string()) if subprocess.call(output_name) != 0: raise EnvironmentException('Executables created by D compiler %s are not runnable.' % self.name_string()) def needs_static_linker(self): return True def name_string(self): return ' '.join(self.exelist) def get_linker_exelist(self): return self.exelist[:] def get_preprocess_only_args(self): return ['-E'] def get_compile_only_args(self): return ['-c'] def depfile_for_object(self, objfile): return objfile + '.' + self.get_depfile_suffix() def get_depfile_suffix(self): return 'deps' def get_pic_args(self): return ['-fPIC'] def get_std_shared_lib_link_args(self): return ['-shared'] def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): # FIXME: Make this work for Windows, MacOS and cross-compiling return get_gcc_soname_args(GCC_STANDARD, prefix, shlib_name, suffix, path, soversion, is_shared_module) def get_feature_args(self, kwargs, build_to_src): res = [] if 'unittest' in kwargs: unittest = kwargs.pop('unittest') unittest_arg = d_feature_args[self.id]['unittest'] if not unittest_arg: raise EnvironmentException('D compiler %s does not support the "unittest" feature.' % self.name_string()) if unittest: res.append(unittest_arg) if 'versions' in kwargs: versions = kwargs.pop('versions') if not isinstance(versions, list): versions = [versions] version_arg = d_feature_args[self.id]['version'] if not version_arg: raise EnvironmentException('D compiler %s does not support the "feature versions" feature.' % self.name_string()) for v in versions: res.append('{0}={1}'.format(version_arg, v)) if 'import_dirs' in kwargs: import_dirs = kwargs.pop('import_dirs') if not isinstance(import_dirs, list): import_dirs = [import_dirs] import_dir_arg = d_feature_args[self.id]['import_dir'] if not import_dir_arg: raise EnvironmentException('D compiler %s does not support the "string import directories" feature.' % self.name_string()) for idir_obj in import_dirs: basedir = idir_obj.get_curdir() for idir in idir_obj.get_incdirs(): # Avoid superfluous '/.' at the end of paths when d is '.' if idir not in ('', '.'): expdir = os.path.join(basedir, idir) else: expdir = basedir srctreedir = os.path.join(build_to_src, expdir) res.append('{0}{1}'.format(import_dir_arg, srctreedir)) if kwargs: raise EnvironmentException('Unknown D compiler feature(s) selected: %s' % ', '.join(kwargs.keys())) return res def get_buildtype_linker_args(self, buildtype): return [] def get_std_exe_link_args(self): return [] def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): # This method is to be used by LDC and DMD. # GDC can deal with the verbatim flags. if not rpath_paths and not install_rpath: return [] paths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths]) if build_rpath != '': paths += ':' + build_rpath if len(paths) < len(install_rpath): padding = 'X' * (len(install_rpath) - len(paths)) if not paths: paths = padding else: paths = paths + ':' + padding return ['-L-rpath={}'.format(paths)] def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'): if extra_args is None: extra_args = [] elif isinstance(extra_args, str): extra_args = [extra_args] if dependencies is None: dependencies = [] elif not isinstance(dependencies, list): dependencies = [dependencies] # Collect compiler arguments args = CompilerArgs(self) for d in dependencies: # Add compile flags needed by dependencies args += d.get_compile_args() if mode == 'link': # Add link flags needed to find dependencies args += d.get_link_args() if mode == 'compile': # Add DFLAGS from the env args += env.coredata.external_args[self.language] elif mode == 'link': # Add LDFLAGS from the env args += env.coredata.external_link_args[self.language] # extra_args must override all other arguments, so we add them last args += extra_args return args def compiles(self, code, env, extra_args=None, dependencies=None, mode='compile'): args = self._get_compiler_check_args(env, extra_args, dependencies, mode) with self.compile(code, args, mode) as p: return p.returncode == 0 def has_multi_arguments(self, args, env): return self.compiles('int i;\n', env, extra_args=args) @classmethod def translate_args_to_nongnu(cls, args): dcargs = [] # Translate common arguments to flags the LDC/DMD compilers # can understand. # The flags might have been added by pkg-config files, # and are therefore out of the user's control. for arg in args: if arg == '-pthread': continue if arg.startswith('-Wl,'): linkargs = arg[arg.index(',') + 1:].split(',') for la in linkargs: dcargs.append('-L' + la.strip()) continue elif arg.startswith('-l'): # translate library link flag dcargs.append('-L' + arg) continue 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 # have set this flag too to do what it is intended to for this # compiler (pass flag through to the linker) # Hence, we guess here whether the flag was intended to pass # a linker search path. dcargs.append('-L' + arg) continue dcargs.append(arg) return dcargs class GnuDCompiler(DCompiler): def __init__(self, exelist, version, is_cross, **kwargs): DCompiler.__init__(self, exelist, version, is_cross, **kwargs) self.id = 'gcc' default_warn_args = ['-Wall', '-Wdeprecated'] self.warn_args = {'1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} self.base_options = ['b_colorout', 'b_sanitize', 'b_staticpic'] self._has_color_support = version_compare(self.version, '>=4.9') # dependencies were implemented before, but broken - support was fixed in GCC 7.1+ # (and some backported versions) self._has_deps_support = version_compare(self.version, '>=7.1') def get_colorout_args(self, colortype): if self._has_color_support: return gnu_color_args[colortype][:] return [] def get_dependency_gen_args(self, outtarget, outfile): if not self._has_deps_support: return [] return ['-MD', '-MQ', outtarget, '-MF', outfile] def get_output_args(self, target): return ['-o', target] def get_linker_output_args(self, target): return ['-o', target] def get_include_args(self, path, is_system): return ['-I' + path] def get_warn_args(self, level): return self.warn_args[level] def get_werror_args(self): return ['-Werror'] def get_linker_search_args(self, dirname): return ['-L' + dirname] def get_buildtype_args(self, buildtype): return d_gdc_buildtype_args[buildtype] def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath) class LLVMDCompiler(DCompiler): def __init__(self, exelist, version, is_cross, **kwargs): DCompiler.__init__(self, exelist, version, is_cross, **kwargs) self.id = 'llvm' self.base_options = ['b_coverage', 'b_colorout'] def get_colorout_args(self, colortype): if colortype == 'always': return ['-enable-color'] return [] def get_dependency_gen_args(self, outtarget, outfile): # LDC using the -deps flag returns a non-Makefile dependency-info file, which # the backends can not use. So we disable this feature for now. return [] def get_output_args(self, target): return ['-of', target] def get_linker_output_args(self, target): return ['-of', target] def get_include_args(self, path, is_system): return ['-I' + path] def get_warn_args(self, level): if level == '2' or level == '3': return ['-wi', '-dw'] else: return ['-wi'] def get_werror_args(self): return ['-w'] def get_coverage_args(self): return ['-cov'] def get_buildtype_args(self, buildtype): return d_ldc_buildtype_args[buildtype] def get_pic_args(self): return ['-relocation-model=pic'] def get_linker_search_args(self, dirname): # -L is recognized as "add this to the search path" by the linker, # while the compiler recognizes it as "pass to linker". So, the first # -L is for the compiler, telling it to pass the second -L to the linker. return ['-L-L' + dirname] @classmethod def unix_args_to_native(cls, args): return cls.translate_args_to_nongnu(args) class DmdDCompiler(DCompiler): def __init__(self, exelist, version, is_cross, **kwargs): DCompiler.__init__(self, exelist, version, is_cross, **kwargs) self.id = 'dmd' self.base_options = ['b_coverage', 'b_colorout'] def get_colorout_args(self, colortype): if colortype == 'always': return ['-color=on'] return [] def get_dependency_gen_args(self, outtarget, outfile): # LDC using the -deps flag returns a non-Makefile dependency-info file, which # the backends can not use. So we disable this feature for now. return [] def get_output_args(self, target): return ['-of' + target] def get_werror_args(self): return ['-w'] def get_linker_output_args(self, target): return ['-of' + target] def get_include_args(self, path, is_system): return ['-I' + path] def get_warn_args(self, level): return ['-wi'] def get_coverage_args(self): return ['-cov'] def get_linker_search_args(self, dirname): # -L is recognized as "add this to the search path" by the linker, # while the compiler recognizes it as "pass to linker". So, the first # -L is for the compiler, telling it to pass the second -L to the linker. return ['-L-L' + dirname] def get_buildtype_args(self, buildtype): return d_dmd_buildtype_args[buildtype] def get_std_shared_lib_link_args(self): return ['-shared', '-defaultlib=libphobos2.so'] @classmethod def unix_args_to_native(cls, args): return cls.translate_args_to_nongnu(args) meson-0.45.1/mesonbuild/compilers/objcpp.py0000644000175000017500000000607713134457406022322 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os.path, subprocess from ..mesonlib import EnvironmentException from .cpp import CPPCompiler from .compilers import ClangCompiler, GnuCompiler class ObjCPPCompiler(CPPCompiler): def __init__(self, exelist, version, is_cross, exe_wrap): self.language = 'objcpp' CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap) def get_display_language(self): return 'Objective-C++' def sanity_check(self, work_dir, environment): # TODO try to use sanity_check_impl instead of duplicated code source_name = os.path.join(work_dir, 'sanitycheckobjcpp.mm') binary_name = os.path.join(work_dir, 'sanitycheckobjcpp') extra_flags = self.get_cross_extra_flags(environment, link=False) if self.is_cross: extra_flags += self.get_compile_only_args() with open(source_name, 'w') as ofile: ofile.write('#import\n' 'class MyClass;' 'int main(int argc, char **argv) { return 0; }\n') pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name]) pc.wait() if pc.returncode != 0: raise EnvironmentException('ObjC++ compiler %s can not compile programs.' % self.name_string()) if self.is_cross: # Can't check if the binaries run so we have to assume they do return pe = subprocess.Popen(binary_name) pe.wait() if pe.returncode != 0: raise EnvironmentException('Executables created by ObjC++ compiler %s are not runnable.' % self.name_string()) class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler): def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None): ObjCPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) GnuCompiler.__init__(self, gcc_type, defines) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} class ClangObjCPPCompiler(ClangCompiler, GnuObjCPPCompiler): def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None): GnuObjCPPCompiler.__init__(self, exelist, version, cltype, is_cross, exe_wrapper) ClangCompiler.__init__(self, cltype) self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage'] meson-0.45.1/mesonbuild/compilers/cs.py0000644000175000017500000000772213246615532021450 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os.path, subprocess from ..mesonlib import EnvironmentException from ..mesonlib import is_windows from .compilers import Compiler, mono_buildtype_args class CsCompiler(Compiler): def __init__(self, exelist, version, id, runner=None): self.language = 'cs' super().__init__(exelist, version) self.id = id self.runner = runner def get_display_language(self): return 'C sharp' def get_always_args(self): return ['/nologo'] def get_linker_always_args(self): return ['/nologo'] def get_output_args(self, fname): return ['-out:' + fname] def get_link_args(self, fname): return ['-r:' + fname] def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): return [] def get_werror_args(self): return ['-warnaserror'] def split_shlib_to_parts(self, fname): return None, fname def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return [] def get_dependency_gen_args(self, outtarget, outfile): return [] def get_linker_exelist(self): return self.exelist[:] def get_compile_only_args(self): return [] def get_linker_output_args(self, outputname): return [] def get_coverage_args(self): return [] def get_coverage_link_args(self): return [] def get_std_exe_link_args(self): return [] def get_include_args(self, path): return [] def get_pic_args(self): return [] def name_string(self): return ' '.join(self.exelist) def get_pch_use_args(self, pch_dir, header): return [] def get_pch_name(self, header_name): return '' def sanity_check(self, work_dir, environment): src = 'sanity.cs' obj = 'sanity.exe' source_name = os.path.join(work_dir, src) with open(source_name, 'w') as ofile: ofile.write('''public class Sanity { static public void Main () { } } ''') pc = subprocess.Popen(self.exelist + self.get_always_args() + [src], cwd=work_dir) pc.wait() if pc.returncode != 0: raise EnvironmentException('Mono compiler %s can not compile programs.' % self.name_string()) if self.runner: cmdlist = [self.runner, obj] else: cmdlist = [os.path.join(work_dir, obj)] pe = subprocess.Popen(cmdlist, cwd=work_dir) pe.wait() if pe.returncode != 0: raise EnvironmentException('Executables created by Mono compiler %s are not runnable.' % self.name_string()) def needs_static_linker(self): return False def get_buildtype_args(self, buildtype): return mono_buildtype_args[buildtype] class MonoCompiler(CsCompiler): def __init__(self, exelist, version): super().__init__(exelist, version, 'mono', 'mono') class VisualStudioCsCompiler(CsCompiler): def __init__(self, exelist, version): super().__init__(exelist, version, 'csc') def get_buildtype_args(self, buildtype): res = mono_buildtype_args[buildtype] if not is_windows(): tmp = [] for flag in res: if flag == '-debug': flag = '-debug:portable' tmp.append(flag) res = tmp return res meson-0.45.1/mesonbuild/compilers/rust.py0000644000175000017500000000522113243342167022026 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import subprocess, os.path from ..mesonlib import EnvironmentException, Popen_safe from .compilers import Compiler, rust_buildtype_args class RustCompiler(Compiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None): self.language = 'rust' super().__init__(exelist, version) self.is_cross = is_cross self.exe_wrapper = exe_wrapper self.id = 'rustc' def needs_static_linker(self): return False def name_string(self): return ' '.join(self.exelist) def sanity_check(self, work_dir, environment): source_name = os.path.join(work_dir, 'sanity.rs') output_name = os.path.join(work_dir, 'rusttest') with open(source_name, 'w') as ofile: ofile.write('''fn main() { } ''') pc = subprocess.Popen(self.exelist + ['-o', output_name, source_name], cwd=work_dir) pc.wait() if pc.returncode != 0: raise EnvironmentException('Rust compiler %s can not compile programs.' % self.name_string()) if self.is_cross: if self.exe_wrapper is None: # Can't check if the binaries run so we have to assume they do return cmdlist = self.exe_wrapper + [output_name] else: cmdlist = [output_name] pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) pe.wait() if pe.returncode != 0: raise EnvironmentException('Executables created by Rust compiler %s are not runnable.' % self.name_string()) def get_dependency_gen_args(self, outfile): return ['--dep-info', outfile] def get_buildtype_args(self, buildtype): return rust_buildtype_args[buildtype] def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath) def get_sysroot(self): cmd = self.exelist + ['--print', 'sysroot'] p, stdo, stde = Popen_safe(cmd) return stdo.split('\n')[0] meson-0.45.1/mesonbuild/compilers/cpp.py0000644000175000017500000002234213254550710021613 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os.path from .. import mlog from .. import coredata from ..mesonlib import version_compare from .c import CCompiler, VisualStudioCCompiler from .compilers import ( GCC_MINGW, gnu_winlibs, msvc_winlibs, ClangCompiler, GnuCompiler, IntelCompiler, ) class CPPCompiler(CCompiler): def __init__(self, exelist, version, is_cross, exe_wrap, **kwargs): # If a child ObjCPP class has already set it, don't set it ourselves if not hasattr(self, 'language'): self.language = 'cpp' CCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs) def get_display_language(self): return 'C++' def get_no_stdinc_args(self): return ['-nostdinc++'] def sanity_check(self, work_dir, environment): code = 'class breakCCompiler;int main(int argc, char **argv) { return 0; }\n' return self.sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code) def get_compiler_check_args(self): # -fpermissive allows non-conforming code to compile which is necessary # for many C++ checks. Particularly, the has_header_symbol check is # too strict without this and always fails. return super().get_compiler_check_args() + ['-fpermissive'] def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None): # Check if it's a C-like symbol if super().has_header_symbol(hname, symbol, prefix, env, extra_args, dependencies): return True # Check if it's a class or a template if extra_args is None: extra_args = [] fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol} t = '''{prefix} #include <{header}> using {symbol}; int main () {{ return 0; }}''' return self.compiles(t.format(**fargs), env, extra_args, dependencies) class ClangCPPCompiler(ClangCompiler, CPPCompiler): def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None, **kwargs): CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) ClangCompiler.__init__(self, cltype) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} def get_options(self): return {'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use', ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z'], 'none')} def get_option_compile_args(self, options): args = [] std = options['cpp_std'] if std.value != 'none': args.append('-std=' + std.value) return args def get_option_link_args(self, options): return [] class GnuCPPCompiler(GnuCompiler, CPPCompiler): def __init__(self, exelist, version, gcc_type, is_cross, exe_wrap, defines, **kwargs): CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs) GnuCompiler.__init__(self, gcc_type, defines) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} def get_options(self): opts = {'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use', ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z'], 'none'), 'cpp_debugstl': coredata.UserBooleanOption('cpp_debugstl', 'STL debug mode', False)} if self.gcc_type == GCC_MINGW: opts.update({ 'cpp_winlibs': coredata.UserArrayOption('cpp_winlibs', 'Standard Win libraries to link against', gnu_winlibs), }) return opts def get_option_compile_args(self, options): args = [] std = options['cpp_std'] if std.value != 'none': args.append('-std=' + std.value) if options['cpp_debugstl'].value: args.append('-D_GLIBCXX_DEBUG=1') return args def get_option_link_args(self, options): if self.gcc_type == GCC_MINGW: return options['cpp_winlibs'].value[:] return [] def get_pch_use_args(self, pch_dir, header): return ['-fpch-preprocess', '-include', os.path.basename(header)] class IntelCPPCompiler(IntelCompiler, CPPCompiler): def __init__(self, exelist, version, icc_type, is_cross, exe_wrap, **kwargs): CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs) IntelCompiler.__init__(self, icc_type) self.lang_header = 'c++-header' default_warn_args = ['-Wall', '-w3', '-diag-disable:remark', '-Wpch-messages', '-Wnon-virtual-dtor'] self.warn_args = {'1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} def get_options(self): c_stds = [] g_stds = ['gnu++98'] if version_compare(self.version, '>=15.0.0'): c_stds += ['c++11', 'c++14'] g_stds += ['gnu++11'] if version_compare(self.version, '>=16.0.0'): c_stds += ['c++17'] if version_compare(self.version, '>=17.0.0'): g_stds += ['gnu++14'] opts = {'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use', ['none'] + c_stds + g_stds, 'none'), 'cpp_debugstl': coredata.UserBooleanOption('cpp_debugstl', 'STL debug mode', False)} return opts def get_option_compile_args(self, options): args = [] std = options['cpp_std'] if std.value != 'none': args.append('-std=' + std.value) if options['cpp_debugstl'].value: args.append('-D_GLIBCXX_DEBUG=1') return args def get_option_link_args(self, options): return [] def has_multi_arguments(self, args, env): for arg in args: if arg.startswith('-Wl,'): mlog.warning('''{} looks like a linker argument, but has_argument and other similar methods only support checking compiler arguments. Using them to check linker arguments are never supported, and results are likely to be wrong regardless of the compiler you are using. '''.format(arg)) return super().has_multi_arguments(args + ['-diag-error', '10006'], env) class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler): def __init__(self, exelist, version, is_cross, exe_wrap, is_64): self.language = 'cpp' VisualStudioCCompiler.__init__(self, exelist, version, is_cross, exe_wrap, is_64) self.base_options = ['b_pch'] # FIXME add lto, pgo and the like def get_options(self): return {'cpp_eh': coredata.UserComboOption('cpp_eh', 'C++ exception handling type.', ['none', 'a', 's', 'sc'], 'sc'), 'cpp_winlibs': coredata.UserArrayOption('cpp_winlibs', 'Windows libs to link against.', msvc_winlibs) } def get_option_compile_args(self, options): args = [] std = options['cpp_eh'] if std.value != 'none': args.append('/EH' + std.value) return args def get_option_link_args(self, options): return options['cpp_winlibs'].value[:] def get_compiler_check_args(self): # Visual Studio C++ compiler doesn't support -fpermissive, # so just use the plain C args. return super(VisualStudioCCompiler, self).get_compiler_check_args() meson-0.45.1/mesonbuild/compilers/c.py0000644000175000017500000013165513254550710021263 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import subprocess, os.path, tempfile from .. import mlog from .. import coredata from . import compilers from ..mesonlib import ( EnvironmentException, version_compare, Popen_safe, listify, for_windows, for_darwin, for_cygwin, for_haiku, ) from .compilers import ( GCC_MINGW, get_largefile_args, gnu_winlibs, msvc_buildtype_args, msvc_buildtype_linker_args, msvc_winlibs, vs32_instruction_set_args, vs64_instruction_set_args, ClangCompiler, Compiler, CompilerArgs, CrossNoRunException, GnuCompiler, IntelCompiler, RunResult, ) class CCompiler(Compiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs): # If a child ObjC or CPP class has already set it, don't set it ourselves if not hasattr(self, 'language'): self.language = 'c' super().__init__(exelist, version, **kwargs) self.id = 'unknown' self.is_cross = is_cross self.can_compile_suffixes.add('h') if isinstance(exe_wrapper, str): self.exe_wrapper = [exe_wrapper] else: self.exe_wrapper = exe_wrapper def needs_static_linker(self): return True # When compiling static libraries, so yes. def get_always_args(self): ''' Args that are always-on for all C compilers other than MSVC ''' return ['-pipe'] + get_largefile_args(self) def get_linker_debug_crt_args(self): """ Arguments needed to select a debug crt for the linker This is only needed for MSVC """ return [] def get_no_stdinc_args(self): return ['-nostdinc'] def get_no_stdlib_link_args(self): return ['-nostdlib'] def get_warn_args(self, level): return self.warn_args[level] def get_no_warn_args(self): # Almost every compiler uses this for disabling warnings return ['-w'] def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): return [] def split_shlib_to_parts(self, fname): return None, fname # The default behavior is this, override in MSVC def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): if self.id == 'clang' and self.clang_type == compilers.CLANG_OSX: return self.build_osx_rpath_args(build_dir, rpath_paths, build_rpath) return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath) def get_dependency_gen_args(self, outtarget, outfile): return ['-MD', '-MQ', outtarget, '-MF', outfile] def depfile_for_object(self, objfile): return objfile + '.' + self.get_depfile_suffix() def get_depfile_suffix(self): return 'd' def get_exelist(self): return self.exelist[:] def get_linker_exelist(self): return self.exelist[:] def get_preprocess_only_args(self): return ['-E', '-P'] def get_compile_only_args(self): return ['-c'] def get_no_optimization_args(self): return ['-O0'] def get_compiler_check_args(self): ''' Get arguments useful for compiler checks such as being permissive in the code quality and not doing any optimization. ''' return self.get_no_optimization_args() def get_output_args(self, target): return ['-o', target] def get_linker_output_args(self, outputname): return ['-o', outputname] def get_coverage_args(self): return ['--coverage'] def get_coverage_link_args(self): return ['--coverage'] def get_werror_args(self): return ['-Werror'] def get_std_exe_link_args(self): return [] def get_include_args(self, path, is_system): if path == '': path = '.' if is_system: return ['-isystem', path] return ['-I' + path] def get_std_shared_lib_link_args(self): return ['-shared'] def get_library_dirs(self): env = os.environ.copy() env['LC_ALL'] = 'C' stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=env)[1] for line in stdo.split('\n'): if line.startswith('libraries:'): libstr = line.split('=', 1)[1] return libstr.split(':') return [] def get_pic_args(self): return ['-fPIC'] def name_string(self): return ' '.join(self.exelist) def get_pch_use_args(self, pch_dir, header): return ['-include', os.path.basename(header)] def get_pch_name(self, header_name): return os.path.basename(header_name) + '.' + self.get_pch_suffix() def get_linker_search_args(self, dirname): return ['-L' + dirname] def get_default_include_dirs(self): return [] def gen_export_dynamic_link_args(self, env): if for_windows(env.is_cross_build(), env) or for_cygwin(env.is_cross_build(), env): return ['-Wl,--export-all-symbols'] elif for_darwin(env.is_cross_build(), env): return [] else: return ['-Wl,-export-dynamic'] def gen_import_library_args(self, implibname): """ The name of the outputted import library This implementation is used only on Windows by compilers that use GNU ld """ return ['-Wl,--out-implib=' + implibname] def sanity_check_impl(self, work_dir, environment, sname, code): mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', ' '.join(self.exelist)) mlog.debug('Is cross compiler: %s.' % str(self.is_cross)) extra_flags = [] source_name = os.path.join(work_dir, sname) binname = sname.rsplit('.', 1)[0] if self.is_cross: binname += '_cross' if self.exe_wrapper is None: # Linking cross built apps is painful. You can't really # tell if you should use -nostdlib or not and for example # on OSX the compiler binary is the same but you need # a ton of compiler flags to differentiate between # arm and x86_64. So just compile. extra_flags += self.get_cross_extra_flags(environment, link=False) extra_flags += self.get_compile_only_args() else: extra_flags += self.get_cross_extra_flags(environment, link=True) # Is a valid executable output for all toolchains and platforms binname += '.exe' # Write binary check source binary_name = os.path.join(work_dir, binname) with open(source_name, 'w') as ofile: ofile.write(code) # Compile sanity check cmdlist = self.exelist + extra_flags + [source_name] + self.get_output_args(binary_name) pc, stdo, stde = Popen_safe(cmdlist, cwd=work_dir) mlog.debug('Sanity check compiler command line:', ' '.join(cmdlist)) mlog.debug('Sanity check compile stdout:') mlog.debug(stdo) mlog.debug('-----\nSanity check compile stderr:') mlog.debug(stde) mlog.debug('-----') if pc.returncode != 0: raise EnvironmentException('Compiler {0} can not compile programs.'.format(self.name_string())) # Run sanity check if self.is_cross: if self.exe_wrapper is None: # Can't check if the binaries run so we have to assume they do return cmdlist = self.exe_wrapper + [binary_name] else: cmdlist = [binary_name] mlog.debug('Running test binary command: ' + ' '.join(cmdlist)) pe = subprocess.Popen(cmdlist) pe.wait() if pe.returncode != 0: raise EnvironmentException('Executables created by {0} compiler {1} are not runnable.'.format(self.language, self.name_string())) def sanity_check(self, work_dir, environment): code = 'int main(int argc, char **argv) { int class=0; return class; }\n' return self.sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code) def has_header(self, hname, prefix, env, extra_args=None, dependencies=None): fargs = {'prefix': prefix, 'header': hname} code = '''{prefix} #ifdef __has_include #if !__has_include("{header}") #error "Header '{header}' could not be found" #endif #else #include <{header}> #endif''' return self.compiles(code.format(**fargs), env, extra_args, dependencies, 'preprocess') def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None): fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol} t = '''{prefix} #include <{header}> int main () {{ /* If it's not defined as a macro, try to use as a symbol */ #ifndef {symbol} {symbol}; #endif }}''' return self.compiles(t.format(**fargs), env, extra_args, dependencies) def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'): if extra_args is None: extra_args = [] elif isinstance(extra_args, str): extra_args = [extra_args] if dependencies is None: dependencies = [] elif not isinstance(dependencies, list): dependencies = [dependencies] # Collect compiler arguments args = CompilerArgs(self) for d in dependencies: # Add compile flags needed by dependencies args += d.get_compile_args() if d.need_threads(): args += self.thread_flags(env) if mode == 'link': # Add link flags needed to find dependencies args += d.get_link_args() if d.need_threads(): args += self.thread_link_flags(env) # Select a CRT if needed since we're linking if mode == 'link': args += self.get_linker_debug_crt_args() # Read c_args/cpp_args/etc from the cross-info file (if needed) args += self.get_cross_extra_flags(env, link=(mode == 'link')) if not self.is_cross: if mode == 'preprocess': # Add CPPFLAGS from the env. args += env.coredata.external_preprocess_args[self.language] elif mode == 'compile': # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS from the env args += env.coredata.external_args[self.language] elif mode == 'link': # Add LDFLAGS from the env args += env.coredata.external_link_args[self.language] args += self.get_compiler_check_args() # extra_args must override all other arguments, so we add them last args += extra_args return args def compiles(self, code, env, extra_args=None, dependencies=None, mode='compile'): args = self._get_compiler_check_args(env, extra_args, dependencies, mode) # We only want to compile; not link with self.compile(code, args.to_native(), mode) as p: return p.returncode == 0 def _links_wrapper(self, code, env, extra_args, dependencies): "Shares common code between self.links and self.run" args = self._get_compiler_check_args(env, extra_args, dependencies, mode='link') return self.compile(code, args) def links(self, code, env, extra_args=None, dependencies=None): with self._links_wrapper(code, env, extra_args, dependencies) as p: return p.returncode == 0 def run(self, code, env, extra_args=None, dependencies=None): if self.is_cross and self.exe_wrapper is None: raise CrossNoRunException('Can not run test applications in this cross environment.') with self._links_wrapper(code, env, extra_args, dependencies) as p: if p.returncode != 0: mlog.debug('Could not compile test file %s: %d\n' % ( p.input_name, p.returncode)) return RunResult(False) if self.is_cross: cmdlist = self.exe_wrapper + [p.output_name] else: cmdlist = p.output_name try: pe, so, se = Popen_safe(cmdlist) except Exception as e: mlog.debug('Could not run: %s (error: %s)\n' % (cmdlist, e)) return RunResult(False) mlog.debug('Program stdout:\n') mlog.debug(so) mlog.debug('Program stderr:\n') mlog.debug(se) return RunResult(True, pe.returncode, so, se) def _compile_int(self, expression, prefix, env, extra_args, dependencies): fargs = {'prefix': prefix, 'expression': expression} t = '''#include {prefix} int main() {{ static int a[1-2*!({expression})]; a[0]=0; return 0; }}''' return self.compiles(t.format(**fargs), env, extra_args, dependencies) def cross_compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies): if isinstance(guess, int): if self._compile_int('%s == %d' % (expression, guess), prefix, env, extra_args, dependencies): return guess cur = low while low < high: cur = int((low + high) / 2) if cur == low: break if self._compile_int('%s >= %d' % (expression, cur), prefix, env, extra_args, dependencies): low = cur else: high = cur if self._compile_int('%s == %d' % (expression, cur), prefix, env, extra_args, dependencies): return cur raise EnvironmentException('Cross-compile check overflowed') def compute_int(self, expression, low, high, guess, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] if self.is_cross: return self.cross_compute_int(expression, low, high, guess, prefix, env, extra_args, dependencies) fargs = {'prefix': prefix, 'expression': expression} t = '''#include {prefix} int main(int argc, char **argv) {{ printf("%ld\\n", (long)({expression})); return 0; }};''' res = self.run(t.format(**fargs), env, extra_args, dependencies) if not res.compiled: return -1 if res.returncode != 0: raise EnvironmentException('Could not run compute_int test binary.') return int(res.stdout) def cross_sizeof(self, typename, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] fargs = {'prefix': prefix, 'type': typename} t = '''#include {prefix} int main(int argc, char **argv) {{ {type} something; }}''' if not self.compiles(t.format(**fargs), env, extra_args, dependencies): return -1 return self.cross_compute_int('sizeof(%s)' % typename, 1, 128, None, prefix, env, extra_args, dependencies) def sizeof(self, typename, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] fargs = {'prefix': prefix, 'type': typename} if self.is_cross: return self.cross_sizeof(typename, prefix, env, extra_args, dependencies) t = '''#include {prefix} int main(int argc, char **argv) {{ printf("%ld\\n", (long)(sizeof({type}))); return 0; }};''' res = self.run(t.format(**fargs), env, extra_args, dependencies) if not res.compiled: return -1 if res.returncode != 0: raise EnvironmentException('Could not run sizeof test binary.') return int(res.stdout) def cross_alignment(self, typename, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] fargs = {'prefix': prefix, 'type': typename} t = '''#include {prefix} int main(int argc, char **argv) {{ {type} something; }}''' if not self.compiles(t.format(**fargs), env, extra_args, dependencies): return -1 t = '''#include {prefix} struct tmp {{ char c; {type} target; }};''' return self.cross_compute_int('offsetof(struct tmp, target)', 1, 1024, None, t.format(**fargs), env, extra_args, dependencies) def alignment(self, typename, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] if self.is_cross: return self.cross_alignment(typename, prefix, env, extra_args, dependencies) fargs = {'prefix': prefix, 'type': typename} t = '''#include #include {prefix} struct tmp {{ char c; {type} target; }}; int main(int argc, char **argv) {{ printf("%d", (int)offsetof(struct tmp, target)); return 0; }}''' res = self.run(t.format(**fargs), env, extra_args, dependencies) if not res.compiled: raise EnvironmentException('Could not compile alignment test.') if res.returncode != 0: raise EnvironmentException('Could not run alignment test binary.') align = int(res.stdout) if align == 0: raise EnvironmentException('Could not determine alignment of %s. Sorry. You might want to file a bug.' % typename) return align def get_define(self, dname, prefix, env, extra_args, dependencies): delim = '"MESON_GET_DEFINE_DELIMITER"' fargs = {'prefix': prefix, 'define': dname, 'delim': delim} code = ''' {prefix} #ifndef {define} # define {define} #endif {delim}\n{define}''' args = self._get_compiler_check_args(env, extra_args, dependencies, mode='preprocess').to_native() with self.compile(code.format(**fargs), args, 'preprocess') as p: if p.returncode != 0: raise EnvironmentException('Could not get define {!r}'.format(dname)) # Get the preprocessed value after the delimiter, # minus the extra newline at the end return p.stdo.split(delim + '\n')[-1][:-1] def get_return_value(self, fname, rtype, prefix, env, extra_args, dependencies): if rtype == 'string': fmt = '%s' cast = '(char*)' elif rtype == 'int': fmt = '%lli' cast = '(long long int)' else: raise AssertionError('BUG: Unknown return type {!r}'.format(rtype)) fargs = {'prefix': prefix, 'f': fname, 'cast': cast, 'fmt': fmt} code = '''{prefix} #include int main(int argc, char *argv[]) {{ printf ("{fmt}", {cast} {f}()); }}'''.format(**fargs) res = self.run(code, env, extra_args, dependencies) if not res.compiled: m = 'Could not get return value of {}()' raise EnvironmentException(m.format(fname)) if rtype == 'string': return res.stdout elif rtype == 'int': try: return int(res.stdout.strip()) except: m = 'Return value of {}() is not an int' raise EnvironmentException(m.format(fname)) @staticmethod def _no_prototype_templ(): """ Try to find the function without a prototype from a header by defining our own dummy prototype and trying to link with the C library (and whatever else the compiler links in by default). This is very similar to the check performed by Autoconf for AC_CHECK_FUNCS. """ # Define the symbol to something else since it is defined by the # includes or defines listed by the user or by the compiler. This may # include, for instance _GNU_SOURCE which must be defined before # limits.h, which includes features.h # Then, undef the symbol to get rid of it completely. head = ''' #define {func} meson_disable_define_of_{func} {prefix} #include #undef {func} ''' # Override any GCC internal prototype and declare our own definition for # the symbol. Use char because that's unlikely to be an actual return # value for a function which ensures that we override the definition. head += ''' #ifdef __cplusplus extern "C" #endif char {func} (); ''' # The actual function call main = ''' int main () {{ return {func} (); }}''' return head, main @staticmethod def _have_prototype_templ(): """ Returns a head-er and main() call that uses the headers listed by the user for the function prototype while checking if a function exists. """ # Add the 'prefix', aka defines, includes, etc that the user provides # This may include, for instance _GNU_SOURCE which must be defined # before limits.h, which includes features.h head = '{prefix}\n#include \n' # We don't know what the function takes or returns, so return it as an int. # Just taking the address or comparing it to void is not enough because # compilers are smart enough to optimize it away. The resulting binary # is not run so we don't care what the return value is. main = '''\nint main() {{ void *a = (void*) &{func}; long b = (long) a; return (int) b; }}''' return head, main def has_function(self, funcname, prefix, env, extra_args=None, dependencies=None): """ First, this function looks for the symbol in the default libraries provided by the compiler (stdlib + a few others usually). If that fails, it checks if any of the headers specified in the prefix provide an implementation of the function, and if that fails, it checks if it's implemented as a compiler-builtin. """ if extra_args is None: extra_args = [] # Short-circuit if the check is already provided by the cross-info file varname = 'has function ' + funcname varname = varname.replace(' ', '_') if self.is_cross: val = env.cross_info.config['properties'].get(varname, None) if val is not None: if isinstance(val, bool): return val raise EnvironmentException('Cross variable {0} is not a boolean.'.format(varname)) fargs = {'prefix': prefix, 'func': funcname} # glibc defines functions that are not available on Linux as stubs that # fail with ENOSYS (such as e.g. lchmod). In this case we want to fail # instead of detecting the stub as a valid symbol. # We already included limits.h earlier to ensure that these are defined # for stub functions. stubs_fail = ''' #if defined __stub_{func} || defined __stub___{func} fail fail fail this function is not going to work #endif ''' # If we have any includes in the prefix supplied by the user, assume # that the user wants us to use the symbol prototype defined in those # includes. If not, then try to do the Autoconf-style check with # a dummy prototype definition of our own. # This is needed when the linker determines symbol availability from an # SDK based on the prototype in the header provided by the SDK. # Ignoring this prototype would result in the symbol always being # marked as available. if '#include' in prefix: head, main = self._have_prototype_templ() else: head, main = self._no_prototype_templ() templ = head + stubs_fail + main if self.links(templ.format(**fargs), env, extra_args, dependencies): return True # MSVC does not have compiler __builtin_-s. if self.get_id() == 'msvc': return False # Detect function as a built-in # # Some functions like alloca() are defined as compiler built-ins which # are inlined by the compiler and you can't take their address, so we # need to look for them differently. On nice compilers like clang, we # can just directly use the __has_builtin() macro. fargs['no_includes'] = '#include' not in prefix t = '''{prefix} int main() {{ #ifdef __has_builtin #if !__has_builtin(__builtin_{func}) #error "__builtin_{func} not found" #endif #elif ! defined({func}) /* Check for __builtin_{func} only if no includes were added to the * prefix above, which means no definition of {func} can be found. * We would always check for this, but we get false positives on * MSYS2 if we do. Their toolchain is broken, but we can at least * give them a workaround. */ #if {no_includes:d} __builtin_{func}; #else #error "No definition for __builtin_{func} found in the prefix" #endif #endif }}''' return self.links(t.format(**fargs), env, extra_args, dependencies) def has_members(self, typename, membernames, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] fargs = {'prefix': prefix, 'type': typename, 'name': 'foo'} # Create code that accesses all members members = '' for member in membernames: members += '{}.{};\n'.format(fargs['name'], member) fargs['members'] = members t = '''{prefix} void bar() {{ {type} {name}; {members} }};''' return self.compiles(t.format(**fargs), env, extra_args, dependencies) def has_type(self, typename, prefix, env, extra_args, dependencies=None): fargs = {'prefix': prefix, 'type': typename} t = '''{prefix} void bar() {{ sizeof({type}); }};''' return self.compiles(t.format(**fargs), env, extra_args, dependencies) def symbols_have_underscore_prefix(self, env): ''' Check if the compiler prefixes an underscore to global C symbols ''' symbol_name = b'meson_uscore_prefix' code = '''#ifdef __cplusplus extern "C" { #endif void ''' + symbol_name.decode() + ''' () {} #ifdef __cplusplus } #endif ''' args = self.get_cross_extra_flags(env, link=False) args += self.get_compiler_check_args() n = 'symbols_have_underscore_prefix' with self.compile(code, args, 'compile') as p: if p.returncode != 0: m = 'BUG: Unable to compile {!r} check: {}' raise RuntimeError(m.format(n, p.stdo)) if not os.path.isfile(p.output_name): m = 'BUG: Can\'t find compiled test code for {!r} check' raise RuntimeError(m.format(n)) with open(p.output_name, 'rb') as o: for line in o: # Check if the underscore form of the symbol is somewhere # in the output file. if b'_' + symbol_name in line: return True # Else, check if the non-underscored form is present elif symbol_name in line: return False raise RuntimeError('BUG: {!r} check failed unexpectedly'.format(n)) def get_library_naming(self, env, libtype): ''' Get library prefixes and suffixes for the target platform ordered by priority ''' stlibext = ['a'] # We've always allowed libname to be both `foo` and `libfoo`, # and now people depend on it prefixes = ['lib', ''] # Library suffixes and prefixes if for_darwin(env.is_cross_build(), env): shlibext = ['dylib'] elif for_windows(env.is_cross_build(), env): # FIXME: .lib files can be import or static so we should read the # file, figure out which one it is, and reject the wrong kind. if self.id == 'msvc': shlibext = ['lib'] else: shlibext = ['dll.a', 'lib', 'dll'] # Yep, static libraries can also be foo.lib stlibext += ['lib'] elif for_cygwin(env.is_cross_build(), env): shlibext = ['dll', 'dll.a'] prefixes = ['cyg'] + prefixes else: # Linux/BSDs shlibext = ['so'] # Search priority if libtype in ('default', 'shared-static'): suffixes = shlibext + stlibext elif libtype == 'static-shared': suffixes = stlibext + shlibext elif libtype == 'shared': suffixes = shlibext elif libtype == 'static': suffixes = stlibext else: raise AssertionError('BUG: unknown libtype {!r}'.format(libtype)) return prefixes, suffixes def find_library(self, libname, env, extra_dirs, libtype='default'): # These libraries are either built-in or invalid if libname in self.ignore_libs: return [] # First try if we can just add the library as -l. code = 'int main(int argc, char **argv) { return 0; }' if extra_dirs and isinstance(extra_dirs, str): extra_dirs = [extra_dirs] # Gcc + co seem to prefer builtin lib dirs to -L dirs. # Only try to find std libs if no extra dirs specified. if not extra_dirs and libtype == 'default': args = ['-l' + libname] if self.links(code, env, extra_args=args): return args # Ensure that we won't modify the list that was passed to us extra_dirs = extra_dirs[:] # Search in the system libraries too extra_dirs += self.get_library_dirs() # Not found or we want to use a specific libtype? Try to find the # library file itself. prefixes, suffixes = self.get_library_naming(env, libtype) # Triply-nested loop! for d in extra_dirs: for suffix in suffixes: for prefix in prefixes: trial = os.path.join(d, prefix + libname + '.' + suffix) if os.path.isfile(trial): return [trial] return None def thread_flags(self, env): if for_haiku(self.is_cross, env): return [] return ['-pthread'] def thread_link_flags(self, env): if for_haiku(self.is_cross, env): return [] return ['-pthread'] def has_multi_arguments(self, args, env): for arg in args: if arg.startswith('-Wl,'): mlog.warning('''{} looks like a linker argument, but has_argument and other similar methods only support checking compiler arguments. Using them to check linker arguments are never supported, and results are likely to be wrong regardless of the compiler you are using. '''.format(arg)) return self.compiles('int i;\n', env, extra_args=args) class ClangCCompiler(ClangCompiler, CCompiler): def __init__(self, exelist, version, clang_type, is_cross, exe_wrapper=None, **kwargs): CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) ClangCompiler.__init__(self, clang_type) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} def get_options(self): return {'c_std': coredata.UserComboOption('c_std', 'C language standard to use', ['none', 'c89', 'c99', 'c11', 'gnu89', 'gnu99', 'gnu11'], 'none')} def get_option_compile_args(self, options): args = [] std = options['c_std'] if std.value != 'none': args.append('-std=' + std.value) return args def get_option_link_args(self, options): return [] def get_linker_always_args(self): basic = super().get_linker_always_args() if self.clang_type == compilers.CLANG_OSX: return basic + ['-Wl,-headerpad_max_install_names'] return basic class GnuCCompiler(GnuCompiler, CCompiler): def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None, **kwargs): CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) GnuCompiler.__init__(self, gcc_type, defines) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} def get_options(self): opts = {'c_std': coredata.UserComboOption('c_std', 'C language standard to use', ['none', 'c89', 'c99', 'c11', 'gnu89', 'gnu99', 'gnu11'], 'none')} if self.gcc_type == GCC_MINGW: opts.update({ 'c_winlibs': coredata.UserArrayOption('c_winlibs', 'Standard Win libraries to link against', gnu_winlibs), }) return opts def get_option_compile_args(self, options): args = [] std = options['c_std'] if std.value != 'none': args.append('-std=' + std.value) return args def get_option_link_args(self, options): if self.gcc_type == GCC_MINGW: return options['c_winlibs'].value[:] return [] def get_std_shared_lib_link_args(self): return ['-shared'] def get_pch_use_args(self, pch_dir, header): return ['-fpch-preprocess', '-include', os.path.basename(header)] class IntelCCompiler(IntelCompiler, CCompiler): def __init__(self, exelist, version, icc_type, is_cross, exe_wrapper=None, **kwargs): CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) IntelCompiler.__init__(self, icc_type) self.lang_header = 'c-header' default_warn_args = ['-Wall', '-w3', '-diag-disable:remark', '-Wpch-messages'] self.warn_args = {'1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} def get_options(self): c_stds = ['c89', 'c99'] g_stds = ['gnu89', 'gnu99'] if version_compare(self.version, '>=16.0.0'): c_stds += ['c11'] opts = {'c_std': coredata.UserComboOption('c_std', 'C language standard to use', ['none'] + c_stds + g_stds, 'none')} return opts def get_option_compile_args(self, options): args = [] std = options['c_std'] if std.value != 'none': args.append('-std=' + std.value) return args def get_std_shared_lib_link_args(self): return ['-shared'] def has_multi_arguments(self, args, env): return super().has_multi_arguments(args + ['-diag-error', '10006'], env) class VisualStudioCCompiler(CCompiler): std_warn_args = ['/W3'] std_opt_args = ['/O2'] ignore_libs = ('m', 'c', 'pthread') def __init__(self, exelist, version, is_cross, exe_wrap, is_64): CCompiler.__init__(self, exelist, version, is_cross, exe_wrap) self.id = 'msvc' # /showIncludes is needed for build dependency tracking in Ninja # See: https://ninja-build.org/manual.html#_deps self.always_args = ['/nologo', '/showIncludes'] self.warn_args = {'1': ['/W2'], '2': ['/W3'], '3': ['/W4']} self.base_options = ['b_pch'] # FIXME add lto, pgo and the like self.is_64 = is_64 # Override CCompiler.get_always_args def get_always_args(self): return self.always_args def get_linker_debug_crt_args(self): """ Arguments needed to select a debug crt for the linker Sometimes we need to manually select the CRT (C runtime) to use with MSVC. One example is when trying to link with static libraries since MSVC won't auto-select a CRT for us in that case and will error out asking us to select one. """ return ['/MDd'] def get_buildtype_args(self, buildtype): return msvc_buildtype_args[buildtype] def get_buildtype_linker_args(self, buildtype): return msvc_buildtype_linker_args[buildtype] def get_pch_suffix(self): return 'pch' def get_pch_name(self, header): chopped = os.path.basename(header).split('.')[:-1] chopped.append(self.get_pch_suffix()) pchname = '.'.join(chopped) return pchname def get_pch_use_args(self, pch_dir, header): base = os.path.basename(header) pchname = self.get_pch_name(header) return ['/FI' + base, '/Yu' + base, '/Fp' + os.path.join(pch_dir, pchname)] def get_preprocess_only_args(self): return ['/EP'] def get_compile_only_args(self): return ['/c'] def get_no_optimization_args(self): return ['/Od'] def get_output_args(self, target): if target.endswith('.exe'): return ['/Fe' + target] return ['/Fo' + target] def get_dependency_gen_args(self, outtarget, outfile): return [] def get_linker_exelist(self): return ['link'] # FIXME, should have same path as compiler. def get_linker_always_args(self): return ['/nologo'] def get_linker_output_args(self, outputname): return ['/OUT:' + outputname] def get_linker_search_args(self, dirname): return ['/LIBPATH:' + dirname] def get_gui_app_args(self): return ['/SUBSYSTEM:WINDOWS'] def get_pic_args(self): return [] # PIC is handled by the loader on Windows def get_std_shared_lib_link_args(self): return ['/DLL'] def gen_vs_module_defs_args(self, defsfile): if not isinstance(defsfile, str): raise RuntimeError('Module definitions file should be str') # With MSVC, DLLs only export symbols that are explicitly exported, # so if a module defs file is specified, we use that to export symbols return ['/DEF:' + defsfile] def gen_pch_args(self, header, source, pchname): objname = os.path.splitext(pchname)[0] + '.obj' return objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname] def gen_import_library_args(self, implibname): "The name of the outputted import library" return ['/IMPLIB:' + implibname] def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return [] # FIXME, no idea what these should be. def thread_flags(self, env): return [] def thread_link_flags(self, env): return [] def get_options(self): return {'c_winlibs': coredata.UserArrayOption('c_winlibs', 'Windows libs to link against.', msvc_winlibs) } def get_option_link_args(self, options): return options['c_winlibs'].value[:] @classmethod def unix_args_to_native(cls, args): result = [] for i in args: # -mms-bitfields is specific to MinGW-GCC # -pthread is only valid for GCC if i in ('-mms-bitfields', '-pthread'): continue if i.startswith('-L'): i = '/LIBPATH:' + i[2:] # Translate GNU-style -lfoo library name to the import library elif i.startswith('-l'): name = i[2:] if name in cls.ignore_libs: # With MSVC, these are provided by the C runtime which is # linked in by default continue else: i = name + '.lib' # -pthread in link flags is only used on Linux elif i == '-pthread': continue result.append(i) return result def get_werror_args(self): return ['/WX'] def get_include_args(self, path, is_system): if path == '': path = '.' # msvc does not have a concept of system header dirs. return ['-I' + path] # Visual Studio is special. It ignores some arguments it does not # understand and you can't tell it to error out on those. # http://stackoverflow.com/questions/15259720/how-can-i-make-the-microsoft-c-compiler-treat-unknown-flags-as-errors-rather-t def has_multi_arguments(self, args, env): warning_text = '9002' code = 'int i;\n' (fd, srcname) = tempfile.mkstemp(suffix='.' + self.default_suffix) os.close(fd) with open(srcname, 'w') as ofile: ofile.write(code) # Read c_args/cpp_args/etc from the cross-info file (if needed) extra_args = self.get_cross_extra_flags(env, link=False) extra_args += self.get_compile_only_args() commands = self.exelist + args + extra_args + [srcname] mlog.debug('Running VS compile:') mlog.debug('Command line: ', ' '.join(commands)) mlog.debug('Code:\n', code) p, stdo, stde = Popen_safe(commands, cwd=os.path.dirname(srcname)) if p.returncode != 0: return False return not(warning_text in stde or warning_text in stdo) def get_compile_debugfile_args(self, rel_obj, pch=False): pdbarr = rel_obj.split('.')[:-1] pdbarr += ['pdb'] args = ['/Fd' + '.'.join(pdbarr)] # When generating a PDB file with PCH, all compile commands write # to the same PDB file. Hence, we need to serialize the PDB # writes using /FS since we do parallel builds. This slows down the # build obviously, which is why we only do this when PCH is on. # This was added in Visual Studio 2013 (MSVC 18.0). Before that it was # always on: https://msdn.microsoft.com/en-us/library/dn502518.aspx if pch and version_compare(self.version, '>=18.0'): args = ['/FS'] + args return args def get_link_debugfile_args(self, targetfile): pdbarr = targetfile.split('.')[:-1] pdbarr += ['pdb'] return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)] def get_link_whole_for(self, args): # Only since VS2015 args = listify(args) return ['/WHOLEARCHIVE:' + x for x in args] def get_instruction_set_args(self, instruction_set): if self.is_64: return vs64_instruction_set_args.get(instruction_set, None) if self.version.split('.')[0] == '16' and instruction_set == 'avx': # VS documentation says that this exists and should work, but # it does not. The headers do not contain AVX intrinsics # and the can not be called. return None return vs32_instruction_set_args.get(instruction_set, None) def get_toolset_version(self): # See boost/config/compiler/visualc.cpp for up to date mapping try: version = int(''.join(self.version.split('.')[0:2])) except: return None if version < 1310: return '7.0' elif version < 1400: return '7.1' # (Visual Studio 2003) elif version < 1500: return '8.0' # (Visual Studio 2005) elif version < 1600: return '9.0' # (Visual Studio 2008) elif version < 1700: return '10.0' # (Visual Studio 2010) elif version < 1800: return '11.0' # (Visual Studio 2012) elif version < 1900: return '12.0' # (Visual Studio 2013) elif version < 1910: return '14.0' # (Visual Studio 2015) elif version < 1920: return '14.1' # (Visual Studio 2017) return None def get_default_include_dirs(self): if 'INCLUDE' not in os.environ: return [] return os.environ['INCLUDE'].split(os.pathsep) meson-0.45.1/mesonbuild/compilers/vala.py0000644000175000017500000000651213214041151021743 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os.path from .. import mlog from ..mesonlib import EnvironmentException, version_compare from .compilers import Compiler class ValaCompiler(Compiler): def __init__(self, exelist, version): self.language = 'vala' super().__init__(exelist, version) self.version = version self.id = 'valac' self.is_cross = False self.base_options = ['b_colorout'] def name_string(self): return ' '.join(self.exelist) def needs_static_linker(self): return False # Because compiles into C. def get_output_args(self, target): return ['-o', target] def get_compile_only_args(self): return ['-C'] def get_pic_args(self): return [] def get_always_args(self): return ['-C'] def get_warn_args(self, warning_level): return [] def get_no_warn_args(self): return ['--disable-warnings'] def get_werror_args(self): return ['--fatal-warnings'] def get_colorout_args(self, colortype): if version_compare(self.version, '>=0.37.1'): return ['--color=' + colortype] return [] def sanity_check(self, work_dir, environment): code = 'class MesonSanityCheck : Object { }' args = self.get_cross_extra_flags(environment, link=False) with self.compile(code, args, 'compile') as p: if p.returncode != 0: msg = 'Vala compiler {!r} can not compile programs' \ ''.format(self.name_string()) raise EnvironmentException(msg) def get_buildtype_args(self, buildtype): if buildtype == 'debug' or buildtype == 'debugoptimized' or buildtype == 'minsize': return ['--debug'] return [] def find_library(self, libname, env, extra_dirs): if extra_dirs and isinstance(extra_dirs, str): extra_dirs = [extra_dirs] # Valac always looks in the default vapi dir, so only search there if # no extra dirs are specified. if not extra_dirs: code = 'class MesonFindLibrary : Object { }' vapi_args = ['--pkg', libname] args = self.get_cross_extra_flags(env, link=False) args += vapi_args with self.compile(code, args, 'compile') as p: if p.returncode == 0: return vapi_args # Not found? Try to find the vapi file itself. for d in extra_dirs: vapi = os.path.join(d, libname + '.vapi') if os.path.isfile(vapi): return [vapi] mlog.debug('Searched {!r} and {!r} wasn\'t found'.format(extra_dirs, libname)) return None def thread_flags(self, env): return [] def thread_link_flags(self, env): return [] meson-0.45.1/mesonbuild/compilers/fortran.py0000644000175000017500000002304113243342167022504 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os.path, subprocess from ..mesonlib import EnvironmentException, is_osx from .compilers import ( GCC_CYGWIN, GCC_MINGW, GCC_OSX, GCC_STANDARD, ICC_STANDARD, apple_buildtype_linker_args, get_gcc_soname_args, gnulike_buildtype_args, gnulike_buildtype_linker_args, Compiler, IntelCompiler, ) class FortranCompiler(Compiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs): self.language = 'fortran' super().__init__(exelist, version, **kwargs) self.is_cross = is_cross self.exe_wrapper = exe_wrapper # Not really correct but I don't have Fortran compilers to test with. Sorry. self.gcc_type = GCC_STANDARD self.id = "IMPLEMENTATION CLASSES MUST SET THIS" def name_string(self): return ' '.join(self.exelist) def get_pic_args(self): if self.gcc_type in (GCC_CYGWIN, GCC_MINGW, GCC_OSX): return [] # On Window and OS X, pic is always on. return ['-fPIC'] def get_std_shared_lib_link_args(self): return ['-shared'] def needs_static_linker(self): return True def sanity_check(self, work_dir, environment): source_name = os.path.join(work_dir, 'sanitycheckf.f90') binary_name = os.path.join(work_dir, 'sanitycheckf') with open(source_name, 'w') as ofile: ofile.write('''program prog print *, "Fortran compilation is working." end program prog ''') extra_flags = self.get_cross_extra_flags(environment, link=True) pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name]) pc.wait() if pc.returncode != 0: raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string()) if self.is_cross: if self.exe_wrapper is None: # Can't check if the binaries run so we have to assume they do return cmdlist = self.exe_wrapper + [binary_name] else: cmdlist = [binary_name] pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) pe.wait() if pe.returncode != 0: raise EnvironmentException('Executables created by Fortran compiler %s are not runnable.' % self.name_string()) def get_std_warn_args(self, level): return FortranCompiler.std_warn_args def get_buildtype_args(self, buildtype): return gnulike_buildtype_args[buildtype] def get_buildtype_linker_args(self, buildtype): if is_osx(): return apple_buildtype_linker_args[buildtype] return gnulike_buildtype_linker_args[buildtype] def split_shlib_to_parts(self, fname): return os.path.dirname(fname), fname def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module) def get_dependency_gen_args(self, outtarget, outfile): # Disabled until this is fixed: # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62162 # return ['-cpp', '-MD', '-MQ', outtarget] return [] def get_output_args(self, target): return ['-o', target] def get_preprocess_only_args(self): return ['-E'] def get_compile_only_args(self): return ['-c'] def get_linker_exelist(self): return self.exelist[:] def get_linker_output_args(self, outputname): return ['-o', outputname] def get_include_args(self, path, is_system): return ['-I' + path] def get_module_incdir_args(self): return ('-I', ) def get_module_outdir_args(self, path): return ['-J' + path] def depfile_for_object(self, objfile): return objfile + '.' + self.get_depfile_suffix() def get_depfile_suffix(self): return 'd' def get_std_exe_link_args(self): return [] def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath) def module_name_to_filename(self, module_name): return module_name.lower() + '.mod' def get_warn_args(self, level): return ['-Wall'] def get_no_warn_args(self): return ['-w'] class GnuFortranCompiler(FortranCompiler): def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None, **kwargs): super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwargs) self.gcc_type = gcc_type self.defines = defines or {} self.id = 'gcc' def has_builtin_define(self, define): return define in self.defines def get_builtin_define(self, define): if define in self.defines: return self.defines[define] def get_always_args(self): return ['-pipe'] def get_coverage_args(self): return ['--coverage'] def get_coverage_link_args(self): return ['--coverage'] def gen_import_library_args(self, implibname): """ The name of the outputted import library Used only on Windows """ return ['-Wl,--out-implib=' + implibname] class G95FortranCompiler(FortranCompiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags) self.id = 'g95' def get_module_outdir_args(self, path): return ['-fmod=' + path] def get_always_args(self): return ['-pipe'] def get_no_warn_args(self): # FIXME: Confirm that there's no compiler option to disable all warnings return [] def gen_import_library_args(self, implibname): """ The name of the outputted import library Used only on Windows """ return ['-Wl,--out-implib=' + implibname] class SunFortranCompiler(FortranCompiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags) self.id = 'sun' def get_dependency_gen_args(self, outtarget, outfile): return ['-fpp'] def get_always_args(self): return [] def get_warn_args(self, level): return [] def get_module_incdir_args(self): return ('-M', ) def get_module_outdir_args(self, path): return ['-moddir=' + path] class IntelFortranCompiler(IntelCompiler, FortranCompiler): std_warn_args = ['-warn', 'all'] def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): self.file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp') FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags) # FIXME: Add support for OS X and Windows in detect_fortran_compiler so # we are sent the type of compiler IntelCompiler.__init__(self, ICC_STANDARD) self.id = 'intel' def get_module_outdir_args(self, path): return ['-module', path] def get_warn_args(self, level): return IntelFortranCompiler.std_warn_args class PathScaleFortranCompiler(FortranCompiler): std_warn_args = ['-fullwarn'] def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags) self.id = 'pathscale' def get_module_outdir_args(self, path): return ['-module', path] def get_std_warn_args(self, level): return PathScaleFortranCompiler.std_warn_args class PGIFortranCompiler(FortranCompiler): std_warn_args = ['-Minform=inform'] def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags) self.id = 'pgi' def get_module_incdir_args(self): return ('-module', ) def get_module_outdir_args(self, path): return ['-module', path] def get_warn_args(self, level): return PGIFortranCompiler.std_warn_args def get_no_warn_args(self): return ['-silent'] class Open64FortranCompiler(FortranCompiler): std_warn_args = ['-fullwarn'] def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags) self.id = 'open64' def get_module_outdir_args(self, path): return ['-module', path] def get_warn_args(self, level): return Open64FortranCompiler.std_warn_args class NAGFortranCompiler(FortranCompiler): std_warn_args = [] def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags) self.id = 'nagfor' def get_module_outdir_args(self, path): return ['-mdir', path] def get_warn_args(self, level): return NAGFortranCompiler.std_warn_args meson-0.45.1/mesonbuild/compilers/java.py0000644000175000017500000000701413134457413021754 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os.path, shutil, subprocess from ..mesonlib import EnvironmentException from .compilers import Compiler, java_buildtype_args class JavaCompiler(Compiler): def __init__(self, exelist, version): self.language = 'java' super().__init__(exelist, version) self.id = 'unknown' self.javarunner = 'java' def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): return [] def get_werror_args(self): return ['-Werror'] def split_shlib_to_parts(self, fname): return None, fname def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return [] def get_dependency_gen_args(self, outtarget, outfile): return [] def get_linker_exelist(self): return self.exelist[:] def get_compile_only_args(self): return [] def get_output_args(self, subdir): if subdir == '': subdir = './' return ['-d', subdir, '-s', subdir] def get_linker_output_args(self, outputname): return [] def get_coverage_args(self): return [] def get_coverage_link_args(self): return [] def get_std_exe_link_args(self): return [] def get_include_args(self, path): return [] def get_pic_args(self): return [] def name_string(self): return ' '.join(self.exelist) def get_pch_use_args(self, pch_dir, header): return [] def get_pch_name(self, header_name): return '' def get_buildtype_args(self, buildtype): return java_buildtype_args[buildtype] def sanity_check(self, work_dir, environment): src = 'SanityCheck.java' obj = 'SanityCheck' source_name = os.path.join(work_dir, src) with open(source_name, 'w') as ofile: ofile.write('''class SanityCheck { public static void main(String[] args) { int i; } } ''') pc = subprocess.Popen(self.exelist + [src], cwd=work_dir) pc.wait() if pc.returncode != 0: raise EnvironmentException('Java compiler %s can not compile programs.' % self.name_string()) runner = shutil.which(self.javarunner) if runner: cmdlist = [runner, obj] pe = subprocess.Popen(cmdlist, cwd=work_dir) pe.wait() if pe.returncode != 0: raise EnvironmentException('Executables created by Java compiler %s are not runnable.' % self.name_string()) else: m = "Java Virtual Machine wasn't found, but it's needed by Meson. " \ "Please install a JRE.\nIf you have specific needs where this " \ "requirement doesn't make sense, please open a bug at " \ "https://github.com/mesonbuild/meson/issues/new and tell us " \ "all about it." raise EnvironmentException(m) def needs_static_linker(self): return False meson-0.45.1/mesonbuild/compilers/compilers.py0000644000175000017500000013577613254550710023046 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import contextlib, os.path, re, tempfile import subprocess from ..linkers import StaticLinker from .. import coredata from .. import mlog from .. import mesonlib from ..mesonlib import EnvironmentException, MesonException, version_compare, Popen_safe """This file contains the data files of all compilers Meson knows about. To support a new compiler, add its information below. Also add corresponding autodetection code in environment.py.""" header_suffixes = ('h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di') obj_suffixes = ('o', 'obj', 'res') lib_suffixes = ('a', 'lib', 'dll', 'dylib', 'so') # Mapping of language to suffixes of files that should always be in that language # This means we can't include .h headers here since they could be C, C++, ObjC, etc. lang_suffixes = { 'c': ('c',), 'cpp': ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx'), # f90, f95, f03, f08 are for free-form fortran ('f90' recommended) # f, for, ftn, fpp are for fixed-form fortran ('f' or 'for' recommended) 'fortran': ('f90', 'f95', 'f03', 'f08', 'f', 'for', 'ftn', 'fpp'), 'd': ('d', 'di'), 'objc': ('m',), 'objcpp': ('mm',), 'rust': ('rs',), 'vala': ('vala', 'vapi', 'gs'), 'cs': ('cs',), 'swift': ('swift',), 'java': ('java',), } cpp_suffixes = lang_suffixes['cpp'] + ('h',) c_suffixes = lang_suffixes['c'] + ('h',) # List of languages that can be linked with C code directly by the linker # used in build.py:process_compilers() and build.py:get_dynamic_linker() clike_langs = ('d', 'objcpp', 'cpp', 'objc', 'c', 'fortran',) clike_suffixes = () for _l in clike_langs: clike_suffixes += lang_suffixes[_l] clike_suffixes += ('h', 'll', 's') # XXX: Use this in is_library()? soregex = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$') # All these are only for C-like languages; see `clike_langs` above. def sort_clike(lang): ''' Sorting function to sort the list of languages according to reversed(compilers.clike_langs) and append the unknown langs in the end. The purpose is to prefer C over C++ for files that can be compiled by both such as assembly, C, etc. Also applies to ObjC, ObjC++, etc. ''' if lang not in clike_langs: return 1 return -clike_langs.index(lang) def is_header(fname): if hasattr(fname, 'fname'): fname = fname.fname suffix = fname.split('.')[-1] return suffix in header_suffixes def is_source(fname): if hasattr(fname, 'fname'): fname = fname.fname suffix = fname.split('.')[-1].lower() return suffix in clike_suffixes def is_assembly(fname): if hasattr(fname, 'fname'): fname = fname.fname return fname.split('.')[-1].lower() == 's' def is_llvm_ir(fname): if hasattr(fname, 'fname'): fname = fname.fname return fname.split('.')[-1] == 'll' def is_object(fname): if hasattr(fname, 'fname'): fname = fname.fname suffix = fname.split('.')[-1] return suffix in obj_suffixes def is_library(fname): if hasattr(fname, 'fname'): fname = fname.fname suffix = fname.split('.')[-1] return suffix in lib_suffixes gnulike_buildtype_args = {'plain': [], # -O0 is passed for improved debugging information with gcc # See https://github.com/mesonbuild/meson/pull/509 'debug': ['-O0', '-g'], 'debugoptimized': ['-O2', '-g'], 'release': ['-O3'], 'minsize': ['-Os', '-g']} msvc_buildtype_args = {'plain': [], 'debug': ["/MDd", "/ZI", "/Ob0", "/Od", "/RTC1"], 'debugoptimized': ["/MD", "/Zi", "/O2", "/Ob1"], 'release': ["/MD", "/O2", "/Ob2"], 'minsize': ["/MD", "/Zi", "/Os", "/Ob1"], } apple_buildtype_linker_args = {'plain': [], 'debug': [], 'debugoptimized': [], 'release': [], 'minsize': [], } gnulike_buildtype_linker_args = {'plain': [], 'debug': [], 'debugoptimized': [], 'release': ['-Wl,-O1'], 'minsize': [], } msvc_buildtype_linker_args = {'plain': [], 'debug': [], 'debugoptimized': [], # The otherwise implicit REF and ICF linker # optimisations are disabled by /DEBUG. # REF implies ICF. 'release': ['/OPT:REF'], 'minsize': ['/INCREMENTAL:NO', '/OPT:REF'], } java_buildtype_args = {'plain': [], 'debug': ['-g'], 'debugoptimized': ['-g'], 'release': [], 'minsize': [], } rust_buildtype_args = {'plain': [], 'debug': ['-C', 'debuginfo=2'], 'debugoptimized': ['-C', 'debuginfo=2', '-C', 'opt-level=2'], 'release': ['-C', 'opt-level=3'], 'minsize': [], # In a future release: ['-C', 'opt-level=s'], } d_gdc_buildtype_args = {'plain': [], 'debug': ['-g', '-O0'], 'debugoptimized': ['-g', '-O'], 'release': ['-O3', '-frelease'], 'minsize': [], } d_ldc_buildtype_args = {'plain': [], 'debug': ['-g', '-O0'], 'debugoptimized': ['-g', '-O'], 'release': ['-O3', '-release'], 'minsize': [], } d_dmd_buildtype_args = {'plain': [], 'debug': ['-g'], 'debugoptimized': ['-g', '-O'], 'release': ['-O', '-release'], 'minsize': [], } mono_buildtype_args = {'plain': [], 'debug': ['-debug'], 'debugoptimized': ['-debug', '-optimize+'], 'release': ['-optimize+'], 'minsize': [], } swift_buildtype_args = {'plain': [], 'debug': ['-g'], 'debugoptimized': ['-g', '-O'], 'release': ['-O'], 'minsize': [], } gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32', '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32'] msvc_winlibs = ['kernel32.lib', 'user32.lib', 'gdi32.lib', 'winspool.lib', 'shell32.lib', 'ole32.lib', 'oleaut32.lib', 'uuid.lib', 'comdlg32.lib', 'advapi32.lib'] gnu_color_args = {'auto': ['-fdiagnostics-color=auto'], 'always': ['-fdiagnostics-color=always'], 'never': ['-fdiagnostics-color=never'], } clang_color_args = {'auto': ['-Xclang', '-fcolor-diagnostics'], 'always': ['-Xclang', '-fcolor-diagnostics'], 'never': ['-Xclang', '-fno-color-diagnostics'], } base_options = {'b_pch': coredata.UserBooleanOption('b_pch', 'Use precompiled headers', True), 'b_lto': coredata.UserBooleanOption('b_lto', 'Use link time optimization', False), 'b_sanitize': coredata.UserComboOption('b_sanitize', 'Code sanitizer to use', ['none', 'address', 'thread', 'undefined', 'memory', 'address,undefined'], 'none'), 'b_lundef': coredata.UserBooleanOption('b_lundef', 'Use -Wl,--no-undefined when linking', True), 'b_asneeded': coredata.UserBooleanOption('b_asneeded', 'Use -Wl,--as-needed when linking', True), 'b_pgo': coredata.UserComboOption('b_pgo', 'Use profile guided optimization', ['off', 'generate', 'use'], 'off'), 'b_coverage': coredata.UserBooleanOption('b_coverage', 'Enable coverage tracking.', False), 'b_colorout': coredata.UserComboOption('b_colorout', 'Use colored output', ['auto', 'always', 'never'], 'always'), 'b_ndebug': coredata.UserComboOption('b_ndebug', 'Disable asserts', ['true', 'false', 'if-release'], 'false'), 'b_staticpic': coredata.UserBooleanOption('b_staticpic', 'Build static libraries as position independent', True), } gnulike_instruction_set_args = {'mmx': ['-mmmx'], 'sse': ['-msse'], 'sse2': ['-msse2'], 'sse3': ['-msse3'], 'ssse3': ['-mssse3'], 'sse41': ['-msse4.1'], 'sse42': ['-msse4.2'], 'avx': ['-mavx'], 'avx2': ['-mavx2'], 'neon': ['-mfpu=neon'], } vs32_instruction_set_args = {'mmx': ['/arch:SSE'], # There does not seem to be a flag just for MMX 'sse': ['/arch:SSE'], 'sse2': ['/arch:SSE2'], 'sse3': ['/arch:AVX'], # VS leaped from SSE2 directly to AVX. 'sse41': ['/arch:AVX'], 'sse42': ['/arch:AVX'], 'avx': ['/arch:AVX'], 'avx2': ['/arch:AVX2'], 'neon': None, } # The 64 bit compiler defaults to /arch:avx. vs64_instruction_set_args = {'mmx': ['/arch:AVX'], 'sse': ['/arch:AVX'], 'sse2': ['/arch:AVX'], 'sse3': ['/arch:AVX'], 'ssse3': ['/arch:AVX'], 'sse41': ['/arch:AVX'], 'sse42': ['/arch:AVX'], 'avx': ['/arch:AVX'], 'avx2': ['/arch:AVX2'], 'neon': None, } def sanitizer_compile_args(value): if value == 'none': return [] args = ['-fsanitize=' + value] if 'address' in value: # For -fsanitize=address,undefined args.append('-fno-omit-frame-pointer') return args def sanitizer_link_args(value): if value == 'none': return [] args = ['-fsanitize=' + value] return args def get_base_compile_args(options, compiler): args = [] # FIXME, gcc/clang specific. try: if options['b_lto'].value: args.append('-flto') except KeyError: pass try: args += compiler.get_colorout_args(options['b_colorout'].value) except KeyError: pass try: args += sanitizer_compile_args(options['b_sanitize'].value) except KeyError: pass try: pgo_val = options['b_pgo'].value if pgo_val == 'generate': args.append('-fprofile-generate') elif pgo_val == 'use': args.append('-fprofile-use') except KeyError: pass try: if options['b_coverage'].value: args += compiler.get_coverage_args() except KeyError: pass try: if (options['b_ndebug'].value == 'true' or (options['b_ndebug'].value == 'if-release' and options['buildtype'].value == 'release')): args += ['-DNDEBUG'] except KeyError: pass return args def get_base_link_args(options, linker, is_shared_module): args = [] # FIXME, gcc/clang specific. try: if options['b_lto'].value: args.append('-flto') except KeyError: pass try: args += sanitizer_link_args(options['b_sanitize'].value) except KeyError: pass try: pgo_val = options['b_pgo'].value if pgo_val == 'generate': args.append('-fprofile-generate') elif pgo_val == 'use': args.append('-fprofile-use') except KeyError: pass try: if not is_shared_module and 'b_lundef' in linker.base_options and options['b_lundef'].value: args.append('-Wl,--no-undefined') except KeyError: pass try: if 'b_asneeded' in linker.base_options and options['b_asneeded'].value: args.append('-Wl,--as-needed') except KeyError: pass try: if options['b_coverage'].value: args += linker.get_coverage_link_args() except KeyError: pass return args class CrossNoRunException(MesonException): pass class RunResult: def __init__(self, compiled, returncode=999, stdout='UNDEFINED', stderr='UNDEFINED'): self.compiled = compiled self.returncode = returncode self.stdout = stdout self.stderr = stderr class CompilerArgs(list): ''' Class derived from list() that manages a list of compiler arguments. Should be used while constructing compiler arguments from various sources. Can be operated with ordinary lists, so this does not need to be used everywhere. All arguments must be inserted and stored in GCC-style (-lfoo, -Idir, etc) and can converted to the native type of each compiler by using the .to_native() method to which you must pass an instance of the compiler or the compiler class. New arguments added to this class (either with .append(), .extend(), or +=) are added in a way that ensures that they override previous arguments. For example: >>> a = ['-Lfoo', '-lbar'] >>> a += ['-Lpho', '-lbaz'] >>> print(a) ['-Lpho', '-Lfoo', '-lbar', '-lbaz'] Arguments will also be de-duped if they can be de-duped safely. Note that because of all this, this class is not commutative and does not preserve the order of arguments if it is safe to not. For example: >>> ['-Ifoo', '-Ibar'] + ['-Ifez', '-Ibaz', '-Werror'] ['-Ifez', '-Ibaz', '-Ifoo', '-Ibar', '-Werror'] >>> ['-Ifez', '-Ibaz', '-Werror'] + ['-Ifoo', '-Ibar'] ['-Ifoo', '-Ibar', '-Ifez', '-Ibaz', '-Werror'] ''' # NOTE: currently this class is only for C-like compilers, but it can be # extended to other languages easily. Just move the following to the # compiler class and initialize when self.compiler is set. # Arg prefixes that override by prepending instead of appending prepend_prefixes = ('-I', '-L') # Arg prefixes and args that must be de-duped by returning 2 dedup2_prefixes = ('-I', '-L', '-D', '-U') dedup2_suffixes = () dedup2_args = () # Arg prefixes and args that must be de-duped by returning 1 dedup1_prefixes = ('-l',) dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a') # Match a .so of the form path/to/libfoo.so.0.1.0 # Only UNIX shared libraries require this. Others have a fixed extension. dedup1_regex = re.compile(r'([\/\\]|\A)lib.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$') dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread') compiler = None def _check_args(self, args): cargs = [] if len(args) > 2: raise TypeError("CompilerArgs() only accepts at most 2 arguments: " "The compiler, and optionally an initial list") elif not args: return cargs elif len(args) == 1: if isinstance(args[0], (Compiler, StaticLinker)): self.compiler = args[0] else: raise TypeError("you must pass a Compiler instance as one of " "the arguments") elif len(args) == 2: if isinstance(args[0], (Compiler, StaticLinker)): self.compiler = args[0] cargs = args[1] elif isinstance(args[1], (Compiler, StaticLinker)): cargs = args[0] self.compiler = args[1] else: raise TypeError("you must pass a Compiler instance as one of " "the two arguments") else: raise AssertionError('Not reached') return cargs def __init__(self, *args): super().__init__(self._check_args(args)) @classmethod def _can_dedup(cls, arg): ''' Returns whether the argument can be safely de-duped. This is dependent on three things: a) Whether an argument can be 'overridden' by a later argument. For example, -DFOO defines FOO and -UFOO undefines FOO. In this case, we can safely remove the previous occurrence and add a new one. The same is true for include paths and library paths with -I and -L. For these we return `2`. See `dedup2_prefixes` and `dedup2_args`. b) Arguments that once specified cannot be undone, such as `-c` or `-pipe`. New instances of these can be completely skipped. For these we return `1`. See `dedup1_prefixes` and `dedup1_args`. c) Whether it matters where or how many times on the command-line a particular argument is present. This can matter for symbol resolution in static or shared libraries, so we cannot de-dup or reorder them. For these we return `0`. This is the default. In addition to these, we handle library arguments specially. With GNU ld, we surround library arguments with -Wl,--start/end-group to recursively search for symbols in the libraries. This is not needed with other linkers. ''' # A standalone argument must never be deduplicated because it is # defined by what comes _after_ it. Thus dedupping this: # -D FOO -D BAR # would yield either # -D FOO BAR # or # FOO -D BAR # both of which are invalid. if arg in cls.dedup2_prefixes: return 0 if arg in cls.dedup2_args or \ arg.startswith(cls.dedup2_prefixes) or \ arg.endswith(cls.dedup2_suffixes): return 2 if arg in cls.dedup1_args or \ arg.startswith(cls.dedup1_prefixes) or \ arg.endswith(cls.dedup1_suffixes) or \ re.search(cls.dedup1_regex, arg): return 1 return 0 @classmethod def _should_prepend(cls, arg): if arg.startswith(cls.prepend_prefixes): return True return False def to_native(self): # Check if we need to add --start/end-group for circular dependencies # between static libraries, and for recursively searching for symbols # needed by static libraries that are provided by object files or # shared libraries. if get_compiler_uses_gnuld(self.compiler): global soregex group_start = -1 for each in self: if not each.startswith('-l') and not each.endswith('.a') and \ not soregex.match(each): continue i = self.index(each) if group_start < 0: # First occurrence of a library group_start = i if group_start >= 0: # Last occurrence of a library self.insert(i + 1, '-Wl,--end-group') self.insert(group_start, '-Wl,--start-group') return self.compiler.unix_args_to_native(self) def append_direct(self, arg): ''' Append the specified argument without any reordering or de-dup ''' super().append(arg) def extend_direct(self, iterable): ''' Extend using the elements in the specified iterable without any reordering or de-dup ''' super().extend(iterable) def __add__(self, args): new = CompilerArgs(self, self.compiler) new += args return new def __iadd__(self, args): ''' Add two CompilerArgs while taking into account overriding of arguments and while preserving the order of arguments as much as possible ''' pre = [] post = [] if not isinstance(args, list): raise TypeError('can only concatenate list (not "{}") to list'.format(args)) for arg in args: # If the argument can be de-duped, do it either by removing the # previous occurrence of it and adding a new one, or not adding the # new occurrence. dedup = self._can_dedup(arg) if dedup == 1: # Argument already exists and adding a new instance is useless if arg in self or arg in pre or arg in post: continue if dedup == 2: # Remove all previous occurrences of the arg and add it anew if arg in self: self.remove(arg) if arg in pre: pre.remove(arg) if arg in post: post.remove(arg) if self._should_prepend(arg): pre.append(arg) else: post.append(arg) # Insert at the beginning self[:0] = pre # Append to the end super().__iadd__(post) return self def __radd__(self, args): new = CompilerArgs(args, self.compiler) new += self return new def __mul__(self, args): raise TypeError("can't multiply compiler arguments") def __imul__(self, args): raise TypeError("can't multiply compiler arguments") def __rmul__(self, args): raise TypeError("can't multiply compiler arguments") def append(self, arg): self.__iadd__([arg]) def extend(self, args): self.__iadd__(args) class Compiler: # Libraries to ignore in find_library() since they are provided by the # compiler or the C library. Currently only used for MSVC. ignore_libs = () def __init__(self, exelist, version, **kwargs): if isinstance(exelist, str): self.exelist = [exelist] elif isinstance(exelist, list): self.exelist = exelist else: raise TypeError('Unknown argument to Compiler') # In case it's been overridden by a child class already if not hasattr(self, 'file_suffixes'): self.file_suffixes = lang_suffixes[self.language] if not hasattr(self, 'can_compile_suffixes'): self.can_compile_suffixes = set(self.file_suffixes) self.default_suffix = self.file_suffixes[0] self.version = version if 'full_version' in kwargs: self.full_version = kwargs['full_version'] else: self.full_version = None self.base_options = [] def __repr__(self): repr_str = "<{0}: v{1} `{2}`>" return repr_str.format(self.__class__.__name__, self.version, ' '.join(self.exelist)) def can_compile(self, src): if hasattr(src, 'fname'): src = src.fname suffix = os.path.splitext(src)[1].lower() if suffix and suffix[1:] in self.can_compile_suffixes: return True return False def get_id(self): return self.id def get_language(self): return self.language def get_display_language(self): return self.language.capitalize() def get_default_suffix(self): return self.default_suffix def get_exelist(self): return self.exelist[:] def get_builtin_define(self, *args, **kwargs): raise EnvironmentException('%s does not support get_builtin_define.' % self.id) def has_builtin_define(self, *args, **kwargs): raise EnvironmentException('%s does not support has_builtin_define.' % self.id) def get_always_args(self): return [] def get_linker_always_args(self): return [] def gen_import_library_args(self, implibname): """ Used only on Windows for libraries that need an import library. This currently means C, C++, Fortran. """ return [] def get_options(self): return {} # build afresh every time def get_option_compile_args(self, options): return [] def get_option_link_args(self, options): return [] def has_header(self, *args, **kwargs): raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) def has_header_symbol(self, *args, **kwargs): raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language()) def compiles(self, *args, **kwargs): raise EnvironmentException('Language %s does not support compile checks.' % self.get_display_language()) def links(self, *args, **kwargs): raise EnvironmentException('Language %s does not support link checks.' % self.get_display_language()) def run(self, *args, **kwargs): raise EnvironmentException('Language %s does not support run checks.' % self.get_display_language()) def sizeof(self, *args, **kwargs): raise EnvironmentException('Language %s does not support sizeof checks.' % self.get_display_language()) def alignment(self, *args, **kwargs): raise EnvironmentException('Language %s does not support alignment checks.' % self.get_display_language()) def has_function(self, *args, **kwargs): raise EnvironmentException('Language %s does not support function checks.' % self.get_display_language()) @classmethod def unix_args_to_native(cls, args): "Always returns a copy that can be independently mutated" return args[:] def find_library(self, *args, **kwargs): raise EnvironmentException('Language {} does not support library finding.'.format(self.get_display_language())) def get_library_dirs(self): return [] def has_argument(self, arg, env): return self.has_multi_arguments([arg], env) def has_multi_arguments(self, args, env): raise EnvironmentException( 'Language {} does not support has_multi_arguments.'.format( self.get_display_language())) def get_supported_arguments(self, args, env): supported_args = [] for arg in args: if self.has_argument(arg, env): supported_args.append(arg) return supported_args def get_cross_extra_flags(self, environment, link): extra_flags = [] if self.is_cross and environment: if 'properties' in environment.cross_info.config: props = environment.cross_info.config['properties'] lang_args_key = self.language + '_args' extra_flags += props.get(lang_args_key, []) lang_link_args_key = self.language + '_link_args' if link: extra_flags += props.get(lang_link_args_key, []) return extra_flags def _get_compile_output(self, dirname, mode): # In pre-processor mode, the output is sent to stdout and discarded if mode == 'preprocess': return None # Extension only matters if running results; '.exe' is # guaranteed to be executable on every platform. if mode == 'link': suffix = 'exe' else: suffix = 'obj' return os.path.join(dirname, 'output.' + suffix) @contextlib.contextmanager def compile(self, code, extra_args=None, mode='link'): if extra_args is None: extra_args = [] try: with tempfile.TemporaryDirectory() as tmpdirname: if isinstance(code, str): srcname = os.path.join(tmpdirname, 'testfile.' + self.default_suffix) with open(srcname, 'w') as ofile: ofile.write(code) elif isinstance(code, mesonlib.File): srcname = code.fname output = self._get_compile_output(tmpdirname, mode) # Construct the compiler command-line commands = CompilerArgs(self) commands.append(srcname) commands += extra_args commands += self.get_always_args() if mode == 'compile': commands += self.get_compile_only_args() # Preprocess mode outputs to stdout, so no output args if mode == 'preprocess': commands += self.get_preprocess_only_args() else: commands += self.get_output_args(output) # Generate full command-line with the exelist commands = self.get_exelist() + commands.to_native() mlog.debug('Running compile:') mlog.debug('Working directory: ', tmpdirname) mlog.debug('Command line: ', ' '.join(commands), '\n') mlog.debug('Code:\n', code) p, p.stdo, p.stde = Popen_safe(commands, cwd=tmpdirname) mlog.debug('Compiler stdout:\n', p.stdo) mlog.debug('Compiler stderr:\n', p.stde) p.input_name = srcname p.output_name = output yield p except (PermissionError, OSError): # On Windows antivirus programs and the like hold on to files so # they can't be deleted. There's not much to do in this case. Also, # catch OSError because the directory is then no longer empty. pass def get_colorout_args(self, colortype): return [] # Some compilers (msvc) write debug info to a separate file. # These args specify where it should be written. def get_compile_debugfile_args(self, rel_obj, **kwargs): return [] def get_link_debugfile_args(self, rel_obj): return [] def get_std_shared_lib_link_args(self): return [] def get_std_shared_module_link_args(self): return self.get_std_shared_lib_link_args() def get_link_whole_for(self, args): if isinstance(args, list) and not args: return [] raise EnvironmentException('Language %s does not support linking whole archives.' % self.get_display_language()) # Compiler arguments needed to enable the given instruction set. # May be [] meaning nothing needed or None meaning the given set # is not supported. def get_instruction_set_args(self, instruction_set): return None def build_osx_rpath_args(self, build_dir, rpath_paths, build_rpath): if not rpath_paths and not build_rpath: return [] # On OSX, rpaths must be absolute. abs_rpaths = [os.path.join(build_dir, p) for p in rpath_paths] if build_rpath != '': abs_rpaths.append(build_rpath) args = ['-Wl,-rpath,' + rp for rp in abs_rpaths] return args def build_unix_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): if not rpath_paths and not install_rpath and not build_rpath: return [] # The rpaths we write must be relative, because otherwise # they have different length depending on the build # directory. This breaks reproducible builds. rel_rpaths = [] for p in rpath_paths: if p == from_dir: relative = '' # relpath errors out in this case else: relative = os.path.relpath(os.path.join(build_dir, p), os.path.join(build_dir, from_dir)) rel_rpaths.append(relative) paths = ':'.join([os.path.join('$ORIGIN', p) for p in rel_rpaths]) # Build_rpath is used as-is (it is usually absolute). if build_rpath != '': if paths != '': paths += ':' paths += build_rpath if len(paths) < len(install_rpath): padding = 'X' * (len(install_rpath) - len(paths)) if not paths: paths = padding else: paths = paths + ':' + padding args = [] if mesonlib.is_dragonflybsd(): # This argument instructs the compiler to record the value of # ORIGIN in the .dynamic section of the elf. On Linux this is done # by default, but is not on dragonfly for some reason. Without this # $ORIGIN in the runtime path will be undefined and any binaries # linked against local libraries will fail to resolve them. args.append('-Wl,-z,origin') args.append('-Wl,-rpath,' + paths) if get_compiler_is_linuxlike(self): # Rpaths to use while linking must be absolute. These are not # written to the binary. Needed only with GNU ld: # https://sourceware.org/bugzilla/show_bug.cgi?id=16936 # Not needed on Windows or other platforms that don't use RPATH # https://github.com/mesonbuild/meson/issues/1897 lpaths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths]) # clang expands '-Wl,rpath-link,' to ['-rpath-link'] instead of ['-rpath-link',''] # This eats the next argument, which happens to be 'ldstdc++', causing link failures. # We can dodge this problem by not adding any rpath_paths if the argument is empty. if lpaths.strip() != '': args += ['-Wl,-rpath-link,' + lpaths] return args def thread_flags(self, env): return [] GCC_STANDARD = 0 GCC_OSX = 1 GCC_MINGW = 2 GCC_CYGWIN = 3 CLANG_STANDARD = 0 CLANG_OSX = 1 CLANG_WIN = 2 # Possibly clang-cl? ICC_STANDARD = 0 ICC_OSX = 1 ICC_WIN = 2 def get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module): if soversion is None: sostr = '' else: sostr = '.' + soversion if gcc_type in (GCC_STANDARD, GCC_MINGW, GCC_CYGWIN): # Might not be correct for mingw but seems to work. return ['-Wl,-soname,%s%s.%s%s' % (prefix, shlib_name, suffix, sostr)] elif gcc_type == GCC_OSX: if is_shared_module: return [] install_name = prefix + shlib_name if soversion is not None: install_name += '.' + soversion install_name += '.dylib' return ['-install_name', os.path.join('@rpath', install_name)] else: raise RuntimeError('Not implemented yet.') def get_compiler_is_linuxlike(compiler): if (getattr(compiler, 'gcc_type', None) == GCC_STANDARD) or \ (getattr(compiler, 'clang_type', None) == CLANG_STANDARD) or \ (getattr(compiler, 'icc_type', None) == ICC_STANDARD): return True return False def get_compiler_uses_gnuld(c): # FIXME: Perhaps we should detect the linker in the environment? # FIXME: Assumes that *BSD use GNU ld, but they might start using lld soon if (getattr(c, 'gcc_type', None) in (GCC_STANDARD, GCC_MINGW, GCC_CYGWIN)) or \ (getattr(c, 'clang_type', None) in (CLANG_STANDARD, CLANG_WIN)) or \ (getattr(c, 'icc_type', None) in (ICC_STANDARD, ICC_WIN)): return True return False def get_largefile_args(compiler): ''' Enable transparent large-file-support for 32-bit UNIX systems ''' if get_compiler_is_linuxlike(compiler): # Enable large-file support unconditionally on all platforms other # than macOS and Windows. macOS is now 64-bit-only so it doesn't # need anything special, and Windows doesn't have automatic LFS. # You must use the 64-bit counterparts explicitly. # glibc, musl, and uclibc, and all BSD libcs support this. On Android, # support for transparent LFS is available depending on the version of # Bionic: https://github.com/android/platform_bionic#32-bit-abi-bugs # https://code.google.com/p/android/issues/detail?id=64613 # # If this breaks your code, fix it! It's been 20+ years! return ['-D_FILE_OFFSET_BITS=64'] # We don't enable -D_LARGEFILE64_SOURCE since that enables # transitionary features and must be enabled by programs that use # those features explicitly. return [] # TODO: The result from calling compiler should be cached. So that calling this # function multiple times don't add latency. def gnulike_default_include_dirs(compiler, lang): if lang == 'cpp': lang = 'c++' env = os.environ.copy() env["LC_ALL"] = 'C' cmd = compiler + ['-x{}'.format(lang), '-E', '-v', '-'] p = subprocess.Popen( cmd, stdin=subprocess.DEVNULL, stderr=subprocess.PIPE, stdout=subprocess.PIPE, env=env ) stderr = p.stderr.read().decode('utf-8') parse_state = 0 paths = [] for line in stderr.split('\n'): if parse_state == 0: if line == '#include "..." search starts here:': parse_state = 1 elif parse_state == 1: if line == '#include <...> search starts here:': parse_state = 2 else: paths.append(line[1:]) elif parse_state == 2: if line == 'End of search list.': break else: paths.append(line[1:]) if len(paths) == 0: mlog.warning('No include directory found parsing "{cmd}" output'.format(cmd=" ".join(cmd))) return paths class GnuCompiler: # Functionality that is common to all GNU family compilers. def __init__(self, gcc_type, defines): self.id = 'gcc' self.gcc_type = gcc_type self.defines = defines or {} self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage', 'b_colorout', 'b_ndebug', 'b_staticpic'] if self.gcc_type != GCC_OSX: self.base_options.append('b_lundef') self.base_options.append('b_asneeded') # All GCC backends can do assembly self.can_compile_suffixes.add('s') def get_colorout_args(self, colortype): if mesonlib.version_compare(self.version, '>=4.9.0'): return gnu_color_args[colortype][:] return [] def get_warn_args(self, level): args = super().get_warn_args(level) if mesonlib.version_compare(self.version, '<4.8.0') and '-Wpedantic' in args: # -Wpedantic was added in 4.8.0 # https://gcc.gnu.org/gcc-4.8/changes.html args[args.index('-Wpedantic')] = '-pedantic' return args def has_builtin_define(self, define): return define in self.defines def get_builtin_define(self, define): if define in self.defines: return self.defines[define] def get_pic_args(self): if self.gcc_type in (GCC_CYGWIN, GCC_MINGW, GCC_OSX): return [] # On Window and OS X, pic is always on. return ['-fPIC'] def get_buildtype_args(self, buildtype): return gnulike_buildtype_args[buildtype] def get_buildtype_linker_args(self, buildtype): if self.gcc_type == GCC_OSX: return apple_buildtype_linker_args[buildtype] return gnulike_buildtype_linker_args[buildtype] def get_pch_suffix(self): return 'gch' def split_shlib_to_parts(self, fname): return os.path.dirname(fname), fname def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module) def get_std_shared_lib_link_args(self): return ['-shared'] def get_link_whole_for(self, args): return ['-Wl,--whole-archive'] + args + ['-Wl,--no-whole-archive'] def gen_vs_module_defs_args(self, defsfile): if not isinstance(defsfile, str): raise RuntimeError('Module definitions file should be str') # On Windows targets, .def files may be specified on the linker command # line like an object file. if self.gcc_type in (GCC_CYGWIN, GCC_MINGW): return [defsfile] # For other targets, discard the .def file. return [] def get_gui_app_args(self): if self.gcc_type in (GCC_CYGWIN, GCC_MINGW): return ['-mwindows'] return [] def get_instruction_set_args(self, instruction_set): return gnulike_instruction_set_args.get(instruction_set, None) def get_default_include_dirs(self): return gnulike_default_include_dirs(self.exelist, self.language) class ClangCompiler: def __init__(self, clang_type): self.id = 'clang' self.clang_type = clang_type self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage', 'b_ndebug', 'b_staticpic', 'b_colorout'] if self.clang_type != CLANG_OSX: self.base_options.append('b_lundef') self.base_options.append('b_asneeded') # All Clang backends can do assembly and LLVM IR self.can_compile_suffixes.update(['ll', 's']) def get_pic_args(self): if self.clang_type in (CLANG_WIN, CLANG_OSX): return [] # On Window and OS X, pic is always on. return ['-fPIC'] def get_colorout_args(self, colortype): return clang_color_args[colortype][:] def get_buildtype_args(self, buildtype): return gnulike_buildtype_args[buildtype] def get_buildtype_linker_args(self, buildtype): if self.clang_type == CLANG_OSX: return apple_buildtype_linker_args[buildtype] return gnulike_buildtype_linker_args[buildtype] def get_pch_suffix(self): return 'pch' def get_pch_use_args(self, pch_dir, header): # Workaround for Clang bug http://llvm.org/bugs/show_bug.cgi?id=15136 # This flag is internal to Clang (or at least not documented on the man page) # so it might change semantics at any time. return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))] def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): if self.clang_type == CLANG_STANDARD: gcc_type = GCC_STANDARD elif self.clang_type == CLANG_OSX: gcc_type = GCC_OSX elif self.clang_type == CLANG_WIN: gcc_type = GCC_MINGW else: raise MesonException('Unreachable code when converting clang type to gcc type.') return get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module) def has_multi_arguments(self, args, env): myargs = ['-Werror=unknown-warning-option', '-Werror=unused-command-line-argument'] if mesonlib.version_compare(self.version, '>=3.6.0'): myargs.append('-Werror=ignored-optimization-argument') return super().has_multi_arguments( myargs + args, env) def has_function(self, funcname, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] # Starting with XCode 8, we need to pass this to force linker # visibility to obey OS X and iOS minimum version targets with # -mmacosx-version-min, -miphoneos-version-min, etc. # https://github.com/Homebrew/homebrew-core/issues/3727 if self.clang_type == CLANG_OSX and version_compare(self.version, '>=8.0'): extra_args.append('-Wl,-no_weak_imports') return super().has_function(funcname, prefix, env, extra_args, dependencies) def get_std_shared_module_link_args(self): if self.clang_type == CLANG_OSX: return ['-bundle', '-Wl,-undefined,dynamic_lookup'] return ['-shared'] def get_link_whole_for(self, args): if self.clang_type == CLANG_OSX: result = [] for a in args: result += ['-Wl,-force_load', a] return result return ['-Wl,--whole-archive'] + args + ['-Wl,--no-whole-archive'] def get_instruction_set_args(self, instruction_set): return gnulike_instruction_set_args.get(instruction_set, None) def get_default_include_dirs(self): return gnulike_default_include_dirs(self.exelist, self.language) # Tested on linux for ICC 14.0.3, 15.0.6, 16.0.4, 17.0.1 class IntelCompiler: def __init__(self, icc_type): self.id = 'intel' self.icc_type = icc_type self.lang_header = 'none' self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage', 'b_colorout', 'b_ndebug', 'b_staticpic', 'b_lundef', 'b_asneeded'] # Assembly self.can_compile_suffixes.add('s') def get_pic_args(self): return ['-fPIC'] def get_buildtype_args(self, buildtype): return gnulike_buildtype_args[buildtype] def get_buildtype_linker_args(self, buildtype): return gnulike_buildtype_linker_args[buildtype] def get_pch_suffix(self): return 'pchi' def get_pch_use_args(self, pch_dir, header): return ['-pch', '-pch_dir', os.path.join(pch_dir), '-x', self.lang_header, '-include', header, '-x', 'none'] def get_pch_name(self, header_name): return os.path.basename(header_name) + '.' + self.get_pch_suffix() def split_shlib_to_parts(self, fname): return os.path.dirname(fname), fname def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): if self.icc_type == ICC_STANDARD: gcc_type = GCC_STANDARD elif self.icc_type == ICC_OSX: gcc_type = GCC_OSX elif self.icc_type == ICC_WIN: gcc_type = GCC_MINGW else: raise MesonException('Unreachable code when converting icc type to gcc type.') return get_gcc_soname_args(gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module) def get_std_shared_lib_link_args(self): # FIXME: Don't know how icc works on OSX # if self.icc_type == ICC_OSX: # return ['-bundle'] return ['-shared'] def get_default_include_dirs(self): return gnulike_default_include_dirs(self.exelist, self.language) meson-0.45.1/mesonbuild/compilers/objc.py0000644000175000017500000000573513134457406021762 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os.path, subprocess from ..mesonlib import EnvironmentException from .c import CCompiler from .compilers import ClangCompiler, GnuCompiler class ObjCCompiler(CCompiler): def __init__(self, exelist, version, is_cross, exe_wrap): self.language = 'objc' CCompiler.__init__(self, exelist, version, is_cross, exe_wrap) def get_display_language(self): return 'Objective-C' def sanity_check(self, work_dir, environment): # TODO try to use sanity_check_impl instead of duplicated code source_name = os.path.join(work_dir, 'sanitycheckobjc.m') binary_name = os.path.join(work_dir, 'sanitycheckobjc') extra_flags = self.get_cross_extra_flags(environment, link=False) if self.is_cross: extra_flags += self.get_compile_only_args() with open(source_name, 'w') as ofile: ofile.write('#import\n' 'int main(int argc, char **argv) { return 0; }\n') pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name]) pc.wait() if pc.returncode != 0: raise EnvironmentException('ObjC compiler %s can not compile programs.' % self.name_string()) if self.is_cross: # Can't check if the binaries run so we have to assume they do return pe = subprocess.Popen(binary_name) pe.wait() if pe.returncode != 0: raise EnvironmentException('Executables created by ObjC compiler %s are not runnable.' % self.name_string()) class GnuObjCCompiler(GnuCompiler, ObjCCompiler): def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None): ObjCCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) GnuCompiler.__init__(self, gcc_type, defines) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} class ClangObjCCompiler(ClangCompiler, GnuObjCCompiler): def __init__(self, exelist, version, cltype, is_cross, exe_wrapper=None): GnuObjCCompiler.__init__(self, exelist, version, cltype, is_cross, exe_wrapper) ClangCompiler.__init__(self, cltype) self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage'] meson-0.45.1/mesonbuild/compilers/swift.py0000644000175000017500000000617713134457406022202 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import subprocess, os.path from ..mesonlib import EnvironmentException from .compilers import Compiler, swift_buildtype_args class SwiftCompiler(Compiler): def __init__(self, exelist, version): self.language = 'swift' super().__init__(exelist, version) self.version = version self.id = 'llvm' self.is_cross = False def get_linker_exelist(self): return self.exelist[:] def name_string(self): return ' '.join(self.exelist) def needs_static_linker(self): return True def get_werror_args(self): return ['--fatal-warnings'] def get_dependency_gen_args(self, outtarget, outfile): return ['-emit-dependencies'] def depfile_for_object(self, objfile): return os.path.splitext(objfile)[0] + '.' + self.get_depfile_suffix() def get_depfile_suffix(self): return 'd' def get_output_args(self, target): return ['-o', target] def get_linker_output_args(self, target): return ['-o', target] def get_header_import_args(self, headername): return ['-import-objc-header', headername] def get_warn_args(self, level): return [] def get_buildtype_args(self, buildtype): return swift_buildtype_args[buildtype] def get_buildtype_linker_args(self, buildtype): return [] def get_std_exe_link_args(self): return ['-emit-executable'] def get_module_args(self, modname): return ['-module-name', modname] def get_mod_gen_args(self): return ['-emit-module'] def build_rpath_args(self, *args): return [] # FIXME def get_include_args(self, dirname): return ['-I' + dirname] def get_compile_only_args(self): return ['-c'] def sanity_check(self, work_dir, environment): src = 'swifttest.swift' source_name = os.path.join(work_dir, src) output_name = os.path.join(work_dir, 'swifttest') with open(source_name, 'w') as ofile: ofile.write('''print("Swift compilation is working.") ''') extra_flags = self.get_cross_extra_flags(environment, link=True) pc = subprocess.Popen(self.exelist + extra_flags + ['-emit-executable', '-o', output_name, src], cwd=work_dir) pc.wait() if pc.returncode != 0: raise EnvironmentException('Swift compiler %s can not compile programs.' % self.name_string()) if subprocess.call(output_name) != 0: raise EnvironmentException('Executables created by Swift compiler %s are not runnable.' % self.name_string()) meson-0.45.1/mesonbuild/compilers/__init__.py0000644000175000017500000000704213246615532022575 0ustar jpakkanejpakkane00000000000000# Copyright 2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. # Public symbols for compilers sub-package when using 'from . import compilers' __all__ = [ 'CLANG_OSX', 'CLANG_STANDARD', 'CLANG_WIN', 'GCC_CYGWIN', 'GCC_MINGW', 'GCC_OSX', 'GCC_STANDARD', 'ICC_OSX', 'ICC_STANDARD', 'ICC_WIN', 'base_options', 'clike_langs', 'c_suffixes', 'cpp_suffixes', 'get_base_compile_args', 'get_base_link_args', 'is_assembly', 'is_header', 'is_library', 'is_llvm_ir', 'is_object', 'is_source', 'lang_suffixes', 'sanitizer_compile_args', 'sort_clike', 'CCompiler', 'ClangCCompiler', 'ClangCompiler', 'ClangCPPCompiler', 'ClangObjCCompiler', 'ClangObjCPPCompiler', 'CompilerArgs', 'CPPCompiler', 'DCompiler', 'DmdDCompiler', 'FortranCompiler', 'G95FortranCompiler', 'GnuCCompiler', 'GnuCompiler', 'GnuCPPCompiler', 'GnuDCompiler', 'GnuFortranCompiler', 'GnuObjCCompiler', 'GnuObjCPPCompiler', 'IntelCompiler', 'IntelCCompiler', 'IntelCPPCompiler', 'IntelFortranCompiler', 'JavaCompiler', 'LLVMDCompiler', 'MonoCompiler', 'VisualStudioCsCompiler', 'NAGFortranCompiler', 'ObjCCompiler', 'ObjCPPCompiler', 'Open64FortranCompiler', 'PathScaleFortranCompiler', 'PGIFortranCompiler', 'RustCompiler', 'SunFortranCompiler', 'SwiftCompiler', 'ValaCompiler', 'VisualStudioCCompiler', 'VisualStudioCPPCompiler', ] # Bring symbols from each module into compilers sub-package namespace from .compilers import ( GCC_OSX, GCC_MINGW, GCC_CYGWIN, GCC_STANDARD, CLANG_OSX, CLANG_WIN, CLANG_STANDARD, ICC_OSX, ICC_WIN, ICC_STANDARD, base_options, clike_langs, c_suffixes, cpp_suffixes, get_base_compile_args, get_base_link_args, is_header, is_source, is_assembly, is_llvm_ir, is_object, is_library, lang_suffixes, sanitizer_compile_args, sort_clike, ClangCompiler, CompilerArgs, GnuCompiler, IntelCompiler, ) from .c import ( CCompiler, ClangCCompiler, GnuCCompiler, IntelCCompiler, VisualStudioCCompiler, ) from .cpp import ( CPPCompiler, ClangCPPCompiler, GnuCPPCompiler, IntelCPPCompiler, VisualStudioCPPCompiler, ) from .cs import MonoCompiler, VisualStudioCsCompiler from .d import ( DCompiler, DmdDCompiler, GnuDCompiler, LLVMDCompiler, ) from .fortran import ( FortranCompiler, G95FortranCompiler, GnuFortranCompiler, IntelFortranCompiler, NAGFortranCompiler, Open64FortranCompiler, PathScaleFortranCompiler, PGIFortranCompiler, SunFortranCompiler, ) from .java import JavaCompiler from .objc import ( ObjCCompiler, ClangObjCCompiler, GnuObjCCompiler, ) from .objcpp import ( ObjCPPCompiler, ClangObjCPPCompiler, GnuObjCPPCompiler, ) from .rust import RustCompiler from .swift import SwiftCompiler from .vala import ValaCompiler meson-0.45.1/mesonbuild/mesonmain.py0000644000175000017500000004022213254550710021017 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import sys, stat, traceback, argparse import datetime import os.path from . import environment, interpreter, mesonlib from . import build from . import mconf, mintro, mtest, rewriter, minit import platform from . import mlog, coredata from .mesonlib import MesonException from .wrap import WrapMode, wraptool default_warning = '1' def add_builtin_argument(p, name, **kwargs): k = kwargs.get('dest', name.replace('-', '_')) c = coredata.get_builtin_option_choices(k) b = kwargs.get('action', None) in ['store_true', 'store_false'] h = coredata.get_builtin_option_description(k) if not b: h = h.rstrip('.') + ' (default: %s).' % coredata.get_builtin_option_default(k) if c and not b: kwargs['choices'] = c default = coredata.get_builtin_option_default(k, noneIfSuppress=True) if default is not None: kwargs['default'] = default else: kwargs['default'] = argparse.SUPPRESS p.add_argument('--' + name, help=h, **kwargs) def create_parser(): p = argparse.ArgumentParser(prog='meson') add_builtin_argument(p, 'prefix') add_builtin_argument(p, 'libdir') add_builtin_argument(p, 'libexecdir') add_builtin_argument(p, 'bindir') add_builtin_argument(p, 'sbindir') add_builtin_argument(p, 'includedir') add_builtin_argument(p, 'datadir') add_builtin_argument(p, 'mandir') add_builtin_argument(p, 'infodir') add_builtin_argument(p, 'localedir') add_builtin_argument(p, 'sysconfdir') add_builtin_argument(p, 'localstatedir') add_builtin_argument(p, 'sharedstatedir') add_builtin_argument(p, 'backend') add_builtin_argument(p, 'buildtype') add_builtin_argument(p, 'strip', action='store_true') add_builtin_argument(p, 'unity') add_builtin_argument(p, 'werror', action='store_true') add_builtin_argument(p, 'layout') add_builtin_argument(p, 'default-library') add_builtin_argument(p, 'warnlevel', dest='warning_level') add_builtin_argument(p, 'stdsplit', action='store_false') add_builtin_argument(p, 'errorlogs', action='store_false') p.add_argument('--cross-file', default=None, help='File describing cross compilation environment.') p.add_argument('-D', action='append', dest='projectoptions', default=[], metavar="option", help='Set the value of an option, can be used several times to set multiple options.') p.add_argument('-v', '--version', action='version', version=coredata.version) # See the mesonlib.WrapMode enum for documentation p.add_argument('--wrap-mode', default=WrapMode.default, type=wrapmodetype, choices=WrapMode, help='Special wrap mode to use') p.add_argument('directories', nargs='*') return p def wrapmodetype(string): try: return getattr(WrapMode, string) except AttributeError: msg = ', '.join([t.name.lower() for t in WrapMode]) msg = 'invalid argument {!r}, use one of {}'.format(string, msg) raise argparse.ArgumentTypeError(msg) class MesonApp: def __init__(self, dir1, dir2, script_launcher, handshake, options, original_cmd_line_args): (self.source_dir, self.build_dir) = self.validate_dirs(dir1, dir2, handshake) self.meson_script_launcher = script_launcher self.options = options self.original_cmd_line_args = original_cmd_line_args def has_build_file(self, dirname): fname = os.path.join(dirname, environment.build_filename) return os.path.exists(fname) def validate_core_dirs(self, dir1, dir2): ndir1 = os.path.abspath(os.path.realpath(dir1)) ndir2 = os.path.abspath(os.path.realpath(dir2)) if not os.path.exists(ndir1): os.makedirs(ndir1) if not os.path.exists(ndir2): os.makedirs(ndir2) if not stat.S_ISDIR(os.stat(ndir1).st_mode): raise RuntimeError('%s is not a directory' % dir1) if not stat.S_ISDIR(os.stat(ndir2).st_mode): raise RuntimeError('%s is not a directory' % dir2) if os.path.samefile(dir1, dir2): raise RuntimeError('Source and build directories must not be the same. Create a pristine build directory.') if self.has_build_file(ndir1): if self.has_build_file(ndir2): raise RuntimeError('Both directories contain a build file %s.' % environment.build_filename) return ndir1, ndir2 if self.has_build_file(ndir2): return ndir2, ndir1 raise RuntimeError('Neither directory contains a build file %s.' % environment.build_filename) def validate_dirs(self, dir1, dir2, handshake): (src_dir, build_dir) = self.validate_core_dirs(dir1, dir2) priv_dir = os.path.join(build_dir, 'meson-private/coredata.dat') if os.path.exists(priv_dir): if not handshake: print('Directory already configured, exiting Meson. Just run your build command\n' '(e.g. ninja) and Meson will regenerate as necessary. If ninja fails, run ninja\n' 'reconfigure to force Meson to regenerate.\n' '\nIf build failures persist, manually wipe your build directory to clear any\n' 'stored system data.\n' '\nTo change option values, run meson configure instead.') sys.exit(0) else: if handshake: raise RuntimeError('Something went terribly wrong. Please file a bug.') return src_dir, build_dir def check_pkgconfig_envvar(self, env): curvar = os.environ.get('PKG_CONFIG_PATH', '') if curvar != env.coredata.pkgconf_envvar: mlog.warning('PKG_CONFIG_PATH has changed between invocations from "%s" to "%s".' % (env.coredata.pkgconf_envvar, curvar)) env.coredata.pkgconf_envvar = curvar def generate(self): env = environment.Environment(self.source_dir, self.build_dir, self.meson_script_launcher, self.options, self.original_cmd_line_args) mlog.initialize(env.get_log_dir()) self._generate(env) def _generate(self, env): mlog.debug('Build started at', datetime.datetime.now().isoformat()) mlog.debug('Main binary:', sys.executable) mlog.debug('Python system:', platform.system()) mlog.log(mlog.bold('The Meson build system')) self.check_pkgconfig_envvar(env) mlog.log('Version:', coredata.version) mlog.log('Source dir:', mlog.bold(self.source_dir)) mlog.log('Build dir:', mlog.bold(self.build_dir)) if env.is_cross_build(): mlog.log('Build type:', mlog.bold('cross build')) else: mlog.log('Build type:', mlog.bold('native build')) b = build.Build(env) if self.options.backend == 'ninja': from .backend import ninjabackend g = ninjabackend.NinjaBackend(b) elif self.options.backend == 'vs': from .backend import vs2010backend g = vs2010backend.autodetect_vs_version(b) env.coredata.set_builtin_option('backend', g.name) mlog.log('Auto detected Visual Studio backend:', mlog.bold(g.name)) elif self.options.backend == 'vs2010': from .backend import vs2010backend g = vs2010backend.Vs2010Backend(b) elif self.options.backend == 'vs2015': from .backend import vs2015backend g = vs2015backend.Vs2015Backend(b) elif self.options.backend == 'vs2017': from .backend import vs2017backend g = vs2017backend.Vs2017Backend(b) elif self.options.backend == 'xcode': from .backend import xcodebackend g = xcodebackend.XCodeBackend(b) else: raise RuntimeError('Unknown backend "%s".' % self.options.backend) intr = interpreter.Interpreter(b, g) if env.is_cross_build(): mlog.log('Host machine cpu family:', mlog.bold(intr.builtin['host_machine'].cpu_family_method([], {}))) mlog.log('Host machine cpu:', mlog.bold(intr.builtin['host_machine'].cpu_method([], {}))) mlog.log('Target machine cpu family:', mlog.bold(intr.builtin['target_machine'].cpu_family_method([], {}))) mlog.log('Target machine cpu:', mlog.bold(intr.builtin['target_machine'].cpu_method([], {}))) mlog.log('Build machine cpu family:', mlog.bold(intr.builtin['build_machine'].cpu_family_method([], {}))) mlog.log('Build machine cpu:', mlog.bold(intr.builtin['build_machine'].cpu_method([], {}))) intr.run() try: dumpfile = os.path.join(env.get_scratch_dir(), 'build.dat') # We would like to write coredata as late as possible since we use the existence of # this file to check if we generated the build file successfully. Since coredata # includes settings, the build files must depend on it and appear newer. However, due # to various kernel caches, we cannot guarantee that any time in Python is exactly in # sync with the time that gets applied to any files. Thus, we dump this file as late as # possible, but before build files, and if any error occurs, delete it. cdf = env.dump_coredata() g.generate(intr) build.save(b, dumpfile) # Post-conf scripts must be run after writing coredata or else introspection fails. g.run_postconf_scripts() except: os.unlink(cdf) raise def run_script_command(args): cmdname = args[0] cmdargs = args[1:] if cmdname == 'exe': import mesonbuild.scripts.meson_exe as abc cmdfunc = abc.run elif cmdname == 'cleantrees': import mesonbuild.scripts.cleantrees as abc cmdfunc = abc.run elif cmdname == 'install': import mesonbuild.scripts.meson_install as abc cmdfunc = abc.run elif cmdname == 'commandrunner': import mesonbuild.scripts.commandrunner as abc cmdfunc = abc.run elif cmdname == 'delsuffix': import mesonbuild.scripts.delwithsuffix as abc cmdfunc = abc.run elif cmdname == 'depfixer': import mesonbuild.scripts.depfixer as abc cmdfunc = abc.run elif cmdname == 'dirchanger': import mesonbuild.scripts.dirchanger as abc cmdfunc = abc.run elif cmdname == 'gtkdoc': import mesonbuild.scripts.gtkdochelper as abc cmdfunc = abc.run elif cmdname == 'msgfmthelper': import mesonbuild.scripts.msgfmthelper as abc cmdfunc = abc.run elif cmdname == 'regencheck': import mesonbuild.scripts.regen_checker as abc cmdfunc = abc.run elif cmdname == 'symbolextractor': import mesonbuild.scripts.symbolextractor as abc cmdfunc = abc.run elif cmdname == 'scanbuild': import mesonbuild.scripts.scanbuild as abc cmdfunc = abc.run elif cmdname == 'vcstagger': import mesonbuild.scripts.vcstagger as abc cmdfunc = abc.run elif cmdname == 'gettext': import mesonbuild.scripts.gettext as abc cmdfunc = abc.run elif cmdname == 'yelphelper': import mesonbuild.scripts.yelphelper as abc cmdfunc = abc.run elif cmdname == 'uninstall': import mesonbuild.scripts.uninstall as abc cmdfunc = abc.run elif cmdname == 'dist': import mesonbuild.scripts.dist as abc cmdfunc = abc.run elif cmdname == 'coverage': import mesonbuild.scripts.coverage as abc cmdfunc = abc.run else: raise MesonException('Unknown internal command {}.'.format(cmdname)) return cmdfunc(cmdargs) def run(original_args, mainfile=None): if sys.version_info < (3, 5): print('Meson works correctly only with python 3.5+.') print('You have python %s.' % sys.version) print('Please update your environment') return 1 args = original_args[:] if len(args) > 0: # First check if we want to run a subcommand. cmd_name = args[0] remaining_args = args[1:] if cmd_name == 'test': return mtest.run(remaining_args) elif cmd_name == 'setup': args = remaining_args # FALLTHROUGH like it's 1972. elif cmd_name == 'introspect': return mintro.run(remaining_args) elif cmd_name == 'rewrite': return rewriter.run(remaining_args) elif cmd_name == 'configure': try: return mconf.run(remaining_args) except MesonException as e: mlog.log(mlog.red('\nError configuring project:'), e) sys.exit(1) elif cmd_name == 'wrap': return wraptool.run(remaining_args) elif cmd_name == 'init': return minit.run(remaining_args) elif cmd_name == 'runpython': import runpy script_file = remaining_args[0] sys.argv[1:] = remaining_args[1:] runpy.run_path(script_file, run_name='__main__') sys.exit(0) # No special command? Do the basic setup/reconf. if len(args) >= 2 and args[0] == '--internal': if args[1] != 'regenerate': script = args[1] try: sys.exit(run_script_command(args[1:])) except MesonException as e: mlog.log(mlog.red('\nError in {} helper script:'.format(script))) mlog.log(e) sys.exit(1) args = args[2:] handshake = True else: handshake = False parser = create_parser() args = mesonlib.expand_arguments(args) options = parser.parse_args(args) args = options.directories if not args or len(args) > 2: # if there's a meson.build in the dir above, and not in the current # directory, assume we're in the build directory if not args and not os.path.exists('meson.build') and os.path.exists('../meson.build'): dir1 = '..' dir2 = '.' else: print('{} '.format(sys.argv[0])) print('If you omit either directory, the current directory is substituted.') print('Run {} --help for more information.'.format(sys.argv[0])) return 1 else: dir1 = args[0] if len(args) > 1: dir2 = args[1] else: dir2 = '.' try: if mainfile is None: raise AssertionError('I iz broken. Sorry.') app = MesonApp(dir1, dir2, mainfile, handshake, options, original_args) except Exception as e: # Log directory does not exist, so just print # to stdout. print('Error during basic setup:\n') print(e) return 1 try: app.generate() except Exception as e: if isinstance(e, MesonException): mlog.log() if hasattr(e, 'file') and hasattr(e, 'lineno') and hasattr(e, 'colno'): mlog.log('%s:%d:%d:' % (e.file, e.lineno, e.colno), mlog.red('ERROR: '), end='') else: mlog.log(mlog.red('ERROR: '), end='') # Error message mlog.log(e) # Path to log file mlog.shutdown() logfile = os.path.join(app.build_dir, environment.Environment.log_dir, mlog.log_fname) mlog.log("\nA full log can be found at", mlog.bold(logfile)) if os.environ.get('MESON_FORCE_BACKTRACE'): raise return 1 else: if os.environ.get('MESON_FORCE_BACKTRACE'): raise traceback.print_exc() return 2 finally: mlog.shutdown() return 0 meson-0.45.1/mesonbuild/astinterpreter.py0000644000175000017500000002411313040633773022111 0ustar jpakkanejpakkane00000000000000# Copyright 2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool. from . import interpreterbase, mlog, mparser, mesonlib from . import environment from .interpreterbase import InterpreterException, InvalidArguments import os, sys class DontCareObject(interpreterbase.InterpreterObject): pass class MockExecutable(interpreterbase.InterpreterObject): pass class MockStaticLibrary(interpreterbase.InterpreterObject): pass class MockSharedLibrary(interpreterbase.InterpreterObject): pass class MockCustomTarget(interpreterbase.InterpreterObject): pass class MockRunTarget(interpreterbase.InterpreterObject): pass ADD_SOURCE = 0 REMOVE_SOURCE = 1 class AstInterpreter(interpreterbase.InterpreterBase): def __init__(self, source_root, subdir): super().__init__(source_root, subdir) self.asts = {} self.funcs.update({'project': self.func_do_nothing, 'test': self.func_do_nothing, 'benchmark': self.func_do_nothing, 'install_headers': self.func_do_nothing, 'install_man': self.func_do_nothing, 'install_data': self.func_do_nothing, 'install_subdir': self.func_do_nothing, 'configuration_data': self.func_do_nothing, 'configure_file': self.func_do_nothing, 'find_program': self.func_do_nothing, 'include_directories': self.func_do_nothing, 'add_global_arguments': self.func_do_nothing, 'add_global_link_arguments': self.func_do_nothing, 'add_project_arguments': self.func_do_nothing, 'add_project_link_arguments': self.func_do_nothing, 'message': self.func_do_nothing, 'generator': self.func_do_nothing, 'error': self.func_do_nothing, 'run_command': self.func_do_nothing, 'assert': self.func_do_nothing, 'subproject': self.func_do_nothing, 'dependency': self.func_do_nothing, 'get_option': self.func_do_nothing, 'join_paths': self.func_do_nothing, 'environment': self.func_do_nothing, 'import': self.func_do_nothing, 'vcs_tag': self.func_do_nothing, 'add_languages': self.func_do_nothing, 'declare_dependency': self.func_do_nothing, 'files': self.func_files, 'executable': self.func_executable, 'static_library': self.func_static_lib, 'shared_library': self.func_shared_lib, 'library': self.func_library, 'build_target': self.func_build_target, 'custom_target': self.func_custom_target, 'run_target': self.func_run_target, 'subdir': self.func_subdir, 'set_variable': self.func_set_variable, 'get_variable': self.func_get_variable, 'is_variable': self.func_is_variable, }) def func_do_nothing(self, node, args, kwargs): return True def method_call(self, node): return True def func_executable(self, node, args, kwargs): if args[0] == self.targetname: if self.operation == ADD_SOURCE: self.add_source_to_target(node, args, kwargs) elif self.operation == REMOVE_SOURCE: self.remove_source_from_target(node, args, kwargs) else: raise NotImplementedError('Bleep bloop') return MockExecutable() def func_static_lib(self, node, args, kwargs): return MockStaticLibrary() def func_shared_lib(self, node, args, kwargs): return MockSharedLibrary() def func_library(self, node, args, kwargs): return self.func_shared_lib(node, args, kwargs) def func_custom_target(self, node, args, kwargs): return MockCustomTarget() def func_run_target(self, node, args, kwargs): return MockRunTarget() def func_subdir(self, node, args, kwargs): prev_subdir = self.subdir subdir = os.path.join(prev_subdir, args[0]) self.subdir = subdir buildfilename = os.path.join(self.subdir, environment.build_filename) absname = os.path.join(self.source_root, buildfilename) if not os.path.isfile(absname): self.subdir = prev_subdir raise InterpreterException('Nonexistent build def file %s.' % buildfilename) with open(absname, encoding='utf8') as f: code = f.read() assert(isinstance(code, str)) try: codeblock = mparser.Parser(code, self.subdir).parse() self.asts[subdir] = codeblock except mesonlib.MesonException as me: me.file = buildfilename raise me self.evaluate_codeblock(codeblock) self.subdir = prev_subdir def func_files(self, node, args, kwargs): if not isinstance(args, list): return [args] return args def evaluate_arithmeticstatement(self, cur): return 0 def evaluate_plusassign(self, node): return 0 def evaluate_indexing(self, node): return 0 def reduce_arguments(self, args): assert(isinstance(args, mparser.ArgumentNode)) if args.incorrect_order(): raise InvalidArguments('All keyword arguments must be after positional arguments.') return args.arguments, args.kwargs def transform(self): self.load_root_meson_file() self.asts[''] = self.ast self.sanity_check_ast() self.parse_project() self.run() def add_source(self, targetname, filename): self.operation = ADD_SOURCE self.targetname = targetname self.filename = filename self.transform() def remove_source(self, targetname, filename): self.operation = REMOVE_SOURCE self.targetname = targetname self.filename = filename self.transform() def unknown_function_called(self, func_name): mlog.warning('Unknown function called: ' + func_name) def add_source_to_target(self, node, args, kwargs): namespan = node.args.arguments[0].bytespan buildfilename = os.path.join(self.source_root, self.subdir, environment.build_filename) raw_data = open(buildfilename, 'r').read() updated = raw_data[0:namespan[1]] + (", '%s'" % self.filename) + raw_data[namespan[1]:] open(buildfilename, 'w').write(updated) sys.exit(0) def remove_argument_item(self, args, i): assert(isinstance(args, mparser.ArgumentNode)) namespan = args.arguments[i].bytespan # Usually remove the comma after this item but if it is # the last argument, we need to remove the one before. if i >= len(args.commas): i -= 1 if i < 0: commaspan = (0, 0) # Removed every entry in the list. else: commaspan = args.commas[i].bytespan if commaspan[0] < namespan[0]: commaspan, namespan = namespan, commaspan buildfilename = os.path.join(self.source_root, args.subdir, environment.build_filename) raw_data = open(buildfilename, 'r').read() intermediary = raw_data[0:commaspan[0]] + raw_data[commaspan[1]:] updated = intermediary[0:namespan[0]] + intermediary[namespan[1]:] open(buildfilename, 'w').write(updated) sys.exit(0) def hacky_find_and_remove(self, node_to_remove): for a in self.asts[node_to_remove.subdir].lines: if a.lineno == node_to_remove.lineno: if isinstance(a, mparser.AssignmentNode): v = a.value if not isinstance(v, mparser.ArrayNode): raise NotImplementedError('Not supported yet, bro.') args = v.args for i in range(len(args.arguments)): if isinstance(args.arguments[i], mparser.StringNode) and self.filename == args.arguments[i].value: self.remove_argument_item(args, i) raise NotImplementedError('Sukkess') def remove_source_from_target(self, node, args, kwargs): for i in range(1, len(node.args)): # Is file name directly in function call as a string. if isinstance(node.args.arguments[i], mparser.StringNode) and self.filename == node.args.arguments[i].value: self.remove_argument_item(node.args, i) # Is file name in a variable that gets expanded here. if isinstance(node.args.arguments[i], mparser.IdNode): avar = self.get_variable(node.args.arguments[i].value) if not isinstance(avar, list): raise NotImplementedError('Non-arrays not supported yet, sorry.') for entry in avar: if isinstance(entry, mparser.StringNode) and entry.value == self.filename: self.hacky_find_and_remove(entry) sys.exit('Could not find source %s in target %s.' % (self.filename, args[0])) meson-0.45.1/mesonbuild/minit.py0000644000175000017500000002576513254550710020170 0ustar jpakkanejpakkane00000000000000# Copyright 2017 The Meson development team from pyclbr import Function # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. """Code that creates simple startup projects.""" import os, sys, argparse, re from glob import glob lib_h_template = '''#pragma once #if defined _WIN32 || defined __CYGWIN__ #ifdef BUILDING_{utoken} #define {utoken}_PUBLIC __declspec(dllexport) #else #define {utoken}_PUBLIC __declspec(dllimport) #endif #else #ifdef BUILDING_{utoken} #define {utoken}_PUBLIC __attribute__ ((visibility ("default"))) #else #define {utoken}_PUBLIC #endif #endif int {utoken}_PUBLIC {function_name}(); ''' lib_c_template = '''#include <{header_file}> /* This function will not be exported and is not * directly callable by users of this library. */ int internal_function() {{ return 0; }} int {function_name}() {{ return internal_function(); }} ''' lib_c_test_template = '''#include <{header_file}> #include int main(int argc, char **argv) {{ if(argc != 1) {{ printf("%s takes no arguments.\\n", argv[0]); return 1; }} return {function_name}(); }} ''' lib_c_meson_template = '''project('{project_name}', 'c', version : '{version}', default_options : ['warning_level=3']) # These arguments are only used to build the shared library # not the executables that use the library. lib_args = ['-DBUILDING_{utoken}'] # Hiding symbols that are not explicitly marked as exported # requires a compiler flag on all compilers except VS. cc = meson.get_compiler('c') if cc.get_id() != 'msvc' lib_args += ['-fvisibility=hidden'] endif shlib = shared_library('{lib_name}', '{source_file}', install : true, c_args : lib_args, ) test_exe = executable('{test_exe_name}', '{test_source_file}', link_with : shlib) test('{test_name}', test_exe) # Make this library usable as a Meson subproject. {ltoken}_dep = declare_dependency( include_directories: include_directories('.'), link_with : shlib) # Make this library usable from the system's # package manager. install_headers('{header_file}', subdir : '{header_dir}') pkg_mod = import('pkgconfig') pkg_mod.generate( name : '{project_name}', filebase : '{ltoken}', description : 'Meson sample project.', subdirs : '{header_dir}', libraries : shlib, version : '{version}', ) ''' hello_c_template = '''#include #define PROJECT_NAME "{project_name}" int main(int argc, char **argv) {{ if(argc != 1) {{ printf("%s takes no arguments.\\n", argv[0]); return 1; }} printf("This is project %s.\\n", PROJECT_NAME); return 0; }} ''' hello_c_meson_template = '''project('{project_name}', 'c', version : '{version}', default_options : ['warning_level=3', 'cpp_std=c++14']) exe = executable('{exe_name}', '{source_name}', install : true) test('basic', exe) ''' hello_cpp_template = '''#include #define PROJECT_NAME "{project_name}" int main(int argc, char **argv) {{ if(argc != 1) {{ std::cout << argv[0] << "takes no arguments.\\n"; return 1; }} std::cout << "This is project " << PROJECT_NAME << ".\\n"; return 0; }} ''' hello_cpp_meson_template = '''project('{project_name}', 'cpp', version : '{version}', default_options : ['warning_level=3']) exe = executable('{exe_name}', '{source_name}', install : true) test('basic', exe) ''' lib_hpp_template = '''#pragma once #if defined _WIN32 || defined __CYGWIN__ #ifdef BUILDING_{utoken} #define {utoken}_PUBLIC __declspec(dllexport) #else #define {utoken}_PUBLIC __declspec(dllimport) #endif #else #ifdef BUILDING_{utoken} #define {utoken}_PUBLIC __attribute__ ((visibility ("default"))) #else #define {utoken}_PUBLIC #endif #endif namespace {namespace} {{ class {utoken}_PUBLIC {class_name} {{ public: {class_name}(); int get_number() const; private: int number; }}; }} ''' lib_cpp_template = '''#include <{header_file}> namespace {namespace} {{ {class_name}::{class_name}() {{ number = 6; }} int {class_name}::get_number() const {{ return number; }} }} ''' lib_cpp_test_template = '''#include <{header_file}> #include int main(int argc, char **argv) {{ if(argc != 1) {{ std::cout << argv[0] << " takes no arguments.\\n"; return 1; }} {namespace}::{class_name} c; return c.get_number() != 6; }} ''' lib_cpp_meson_template = '''project('{project_name}', 'cpp', version : '{version}', default_options : ['warning_level=3', 'cpp_std=c++14']) # These arguments are only used to build the shared library # not the executables that use the library. lib_args = ['-DBUILDING_{utoken}'] # Hiding symbols that are not explicitly marked as exported # requires a compiler flag on all compilers except VS. cpp = meson.get_compiler('cpp') if cpp.get_id() != 'msvc' lib_args += ['-fvisibility=hidden'] endif shlib = shared_library('{lib_name}', '{source_file}', install : true, cpp_args : lib_args, ) test_exe = executable('{test_exe_name}', '{test_source_file}', link_with : shlib) test('{test_name}', test_exe) # Make this library usable as a Meson subproject. {ltoken}_dep = declare_dependency( include_directories: include_directories('.'), link_with : shlib) # Make this library usable from the system's # package manager. install_headers('{header_file}', subdir : '{header_dir}') pkg_mod = import('pkgconfig') pkg_mod.generate( name : '{project_name}', filebase : '{ltoken}', description : 'Meson sample project.', subdirs : '{header_dir}', libraries : shlib, version : '{version}', ) ''' info_message = '''Sample project created. To build it run the following commands: meson builddir ninja -C builddir ''' def create_exe_c_sample(project_name, project_version): lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower()) uppercase_token = lowercase_token.upper() source_name = lowercase_token + '.c' open(source_name, 'w').write(hello_c_template.format(project_name=project_name)) open('meson.build', 'w').write(hello_c_meson_template.format(project_name=project_name, exe_name=lowercase_token, source_name=source_name, version=project_version)) def create_lib_c_sample(project_name, version): lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower()) uppercase_token = lowercase_token.upper() function_name = lowercase_token[0:3] + '_func' lib_h_name = lowercase_token + '.h' lib_c_name = lowercase_token + '.c' test_c_name = lowercase_token + '_test.c' kwargs = {'utoken': uppercase_token, 'ltoken': lowercase_token, 'header_dir': lowercase_token, 'function_name': function_name, 'header_file': lib_h_name, 'source_file': lib_c_name, 'test_source_file': test_c_name, 'test_exe_name': lowercase_token, 'project_name': project_name, 'lib_name': lowercase_token, 'test_name': lowercase_token, 'version': version, } open(lib_h_name, 'w').write(lib_h_template.format(**kwargs)) open(lib_c_name, 'w').write(lib_c_template.format(**kwargs)) open(test_c_name, 'w').write(lib_c_test_template.format(**kwargs)) open('meson.build', 'w').write(lib_c_meson_template.format(**kwargs)) def create_exe_cpp_sample(project_name, project_version): lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower()) uppercase_token = lowercase_token.upper() source_name = lowercase_token + '.cpp' open(source_name, 'w').write(hello_cpp_template.format(project_name=project_name)) open('meson.build', 'w').write(hello_cpp_meson_template.format(project_name=project_name, exe_name=lowercase_token, source_name=source_name, version=project_version)) def create_lib_cpp_sample(project_name, version): lowercase_token = re.sub(r'[^a-z0-9]', '_', project_name.lower()) uppercase_token = lowercase_token.upper() class_name = uppercase_token[0] + lowercase_token[1:] namespace = lowercase_token lib_h_name = lowercase_token + '.hpp' lib_c_name = lowercase_token + '.cpp' test_c_name = lowercase_token + '_test.cpp' kwargs = {'utoken': uppercase_token, 'ltoken': lowercase_token, 'header_dir': lowercase_token, 'class_name': class_name, 'namespace': namespace, 'header_file': lib_h_name, 'source_file': lib_c_name, 'test_source_file': test_c_name, 'test_exe_name': lowercase_token, 'project_name': project_name, 'lib_name': lowercase_token, 'test_name': lowercase_token, 'version': version, } open(lib_h_name, 'w').write(lib_hpp_template.format(**kwargs)) open(lib_c_name, 'w').write(lib_cpp_template.format(**kwargs)) open(test_c_name, 'w').write(lib_cpp_test_template.format(**kwargs)) open('meson.build', 'w').write(lib_cpp_meson_template.format(**kwargs)) def create_sample(options): if options.language == 'c': if options.type == 'executable': create_exe_c_sample(options.name, options.version) elif options.type == 'library': create_lib_c_sample(options.name, options.version) else: raise RuntimeError('Unreachable code') elif options.language == 'cpp': if options.type == 'executable': create_exe_cpp_sample(options.name, options.version) elif options.type == 'library': create_lib_cpp_sample(options.name, options.version) else: raise RuntimeError('Unreachable code') else: raise RuntimeError('Unreachable code') print(info_message) def run(args): parser = argparse.ArgumentParser(prog='meson') parser.add_argument('--name', default = 'mesonsample') parser.add_argument('--type', default='executable', choices=['executable', 'library']) parser.add_argument('--language', default='c', choices=['c', 'cpp']) parser.add_argument('--version', default='1.0') options = parser.parse_args(args) if len(glob('*')) != 0: sys.exit('This command must be run in an empty directory.') create_sample(options) return 0 meson-0.45.1/mesonbuild/interpreterbase.py0000644000175000017500000007041013254550710022231 0ustar jpakkanejpakkane00000000000000# Copyright 2016-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool. from . import mparser, mesonlib, mlog from . import environment, dependencies import os, copy, re, types from functools import wraps # Decorators for method calls. def check_stringlist(a, msg='Arguments must be strings.'): if not isinstance(a, list): mlog.debug('Not a list:', str(a)) raise InvalidArguments('Argument not a list.') if not all(isinstance(s, str) for s in a): mlog.debug('Element not a string:', str(a)) raise InvalidArguments(msg) def noPosargs(f): @wraps(f) def wrapped(self, node, args, kwargs): if args: raise InvalidArguments('Function does not take positional arguments.') return f(self, node, args, kwargs) return wrapped def noKwargs(f): @wraps(f) def wrapped(self, node, args, kwargs): if kwargs: raise InvalidArguments('Function does not take keyword arguments.') return f(self, node, args, kwargs) return wrapped def stringArgs(f): @wraps(f) def wrapped(self, node, args, kwargs): assert(isinstance(args, list)) check_stringlist(args) return f(self, node, args, kwargs) return wrapped class permittedKwargs: def __init__(self, permitted): self.permitted = permitted def __call__(self, f): @wraps(f) def wrapped(s, node_or_state, args, kwargs): loc = types.SimpleNamespace() if hasattr(s, 'subdir'): loc.subdir = s.subdir loc.lineno = s.current_lineno elif hasattr(node_or_state, 'subdir'): loc.subdir = node_or_state.subdir loc.lineno = node_or_state.current_lineno else: loc = None for k in kwargs: if k not in self.permitted: mlog.warning('''Passed invalid keyword argument "{}".'''.format(k), location=loc) mlog.warning('This will become a hard error in the future.') return f(s, node_or_state, args, kwargs) return wrapped class InterpreterException(mesonlib.MesonException): pass class InvalidCode(InterpreterException): pass class InvalidArguments(InterpreterException): pass class InterpreterObject: def __init__(self): self.methods = {} def method_call(self, method_name, args, kwargs): if method_name in self.methods: return self.methods[method_name](args, kwargs) raise InvalidCode('Unknown method "%s" in object.' % method_name) class MutableInterpreterObject(InterpreterObject): def __init__(self): super().__init__() class Disabler(InterpreterObject): def __init__(self): super().__init__() self.methods.update({'found': self.found_method}) def found_method(self, args, kwargs): return False def is_disabler(i): return isinstance(i, Disabler) def is_disabled(args, kwargs): for i in args: if isinstance(i, Disabler): return True for i in kwargs.values(): if isinstance(i, Disabler): return True if isinstance(i, list): for j in i: if isinstance(j, Disabler): return True return False class InterpreterBase: def __init__(self, source_root, subdir): self.source_root = source_root self.funcs = {} self.builtin = {} self.subdir = subdir self.variables = {} self.argument_depth = 0 self.current_lineno = -1 def load_root_meson_file(self): mesonfile = os.path.join(self.source_root, self.subdir, environment.build_filename) if not os.path.isfile(mesonfile): raise InvalidArguments('Missing Meson file in %s' % mesonfile) with open(mesonfile, encoding='utf8') as mf: code = mf.read() if code.isspace(): raise InvalidCode('Builder file is empty.') assert(isinstance(code, str)) try: self.ast = mparser.Parser(code, self.subdir).parse() except mesonlib.MesonException as me: me.file = environment.build_filename raise me def parse_project(self): """ Parses project() and initializes languages, compilers etc. Do this early because we need this before we parse the rest of the AST. """ self.evaluate_codeblock(self.ast, end=1) def sanity_check_ast(self): if not isinstance(self.ast, mparser.CodeBlockNode): raise InvalidCode('AST is of invalid type. Possibly a bug in the parser.') if not self.ast.lines: raise InvalidCode('No statements in code.') first = self.ast.lines[0] if not isinstance(first, mparser.FunctionNode) or first.func_name != 'project': raise InvalidCode('First statement must be a call to project') def run(self): # Evaluate everything after the first line, which is project() because # we already parsed that in self.parse_project() self.evaluate_codeblock(self.ast, start=1) def evaluate_codeblock(self, node, start=0, end=None): if node is None: return if not isinstance(node, mparser.CodeBlockNode): e = InvalidCode('Tried to execute a non-codeblock. Possibly a bug in the parser.') e.lineno = node.lineno e.colno = node.colno raise e statements = node.lines[start:end] i = 0 while i < len(statements): cur = statements[i] try: self.current_lineno = cur.lineno self.evaluate_statement(cur) except Exception as e: if not(hasattr(e, 'lineno')): e.lineno = cur.lineno e.colno = cur.colno e.file = os.path.join(self.subdir, 'meson.build') raise e i += 1 # In THE FUTURE jump over blocks and stuff. def evaluate_statement(self, cur): if isinstance(cur, mparser.FunctionNode): return self.function_call(cur) elif isinstance(cur, mparser.AssignmentNode): return self.assignment(cur) elif isinstance(cur, mparser.MethodNode): return self.method_call(cur) elif isinstance(cur, mparser.StringNode): return cur.value elif isinstance(cur, mparser.BooleanNode): return cur.value elif isinstance(cur, mparser.IfClauseNode): return self.evaluate_if(cur) elif isinstance(cur, mparser.IdNode): return self.get_variable(cur.value) elif isinstance(cur, mparser.ComparisonNode): return self.evaluate_comparison(cur) elif isinstance(cur, mparser.ArrayNode): return self.evaluate_arraystatement(cur) elif isinstance(cur, mparser.NumberNode): return cur.value elif isinstance(cur, mparser.AndNode): return self.evaluate_andstatement(cur) elif isinstance(cur, mparser.OrNode): return self.evaluate_orstatement(cur) elif isinstance(cur, mparser.NotNode): return self.evaluate_notstatement(cur) elif isinstance(cur, mparser.UMinusNode): return self.evaluate_uminusstatement(cur) elif isinstance(cur, mparser.ArithmeticNode): return self.evaluate_arithmeticstatement(cur) elif isinstance(cur, mparser.ForeachClauseNode): return self.evaluate_foreach(cur) elif isinstance(cur, mparser.PlusAssignmentNode): return self.evaluate_plusassign(cur) elif isinstance(cur, mparser.IndexNode): return self.evaluate_indexing(cur) elif isinstance(cur, mparser.TernaryNode): return self.evaluate_ternary(cur) elif self.is_elementary_type(cur): return cur else: raise InvalidCode("Unknown statement.") def evaluate_arraystatement(self, cur): (arguments, kwargs) = self.reduce_arguments(cur.args) if len(kwargs) > 0: raise InvalidCode('Keyword arguments are invalid in array construction.') return arguments def evaluate_notstatement(self, cur): v = self.evaluate_statement(cur.value) if not isinstance(v, bool): raise InterpreterException('Argument to "not" is not a boolean.') return not v def evaluate_if(self, node): assert(isinstance(node, mparser.IfClauseNode)) for i in node.ifs: result = self.evaluate_statement(i.condition) if is_disabler(result): return result if not(isinstance(result, bool)): raise InvalidCode('If clause {!r} does not evaluate to true or false.'.format(result)) if result: self.evaluate_codeblock(i.block) return if not isinstance(node.elseblock, mparser.EmptyNode): self.evaluate_codeblock(node.elseblock) def validate_comparison_types(self, val1, val2): if type(val1) != type(val2): return False return True def evaluate_comparison(self, node): val1 = self.evaluate_statement(node.left) if is_disabler(val1): return val1 val2 = self.evaluate_statement(node.right) if is_disabler(val2): return val2 valid = self.validate_comparison_types(val1, val2) # Ordering comparisons of different types isn't allowed since PR #1810 # (0.41.0). Since PR #2884 we also warn about equality comparisons of # different types, which will one day become an error. if not valid and (node.ctype == '==' or node.ctype == '!='): mlog.warning('''Trying to compare values of different types ({}, {}) using {}. The result of this is undefined and will become a hard error in a future Meson release.''' .format(type(val1).__name__, type(val2).__name__, node.ctype), location=node) if node.ctype == '==': return val1 == val2 elif node.ctype == '!=': return val1 != val2 elif not valid: raise InterpreterException( 'Values of different types ({}, {}) cannot be compared using {}.'.format(type(val1).__name__, type(val2).__name__, node.ctype)) elif not self.is_elementary_type(val1): raise InterpreterException('{} can only be compared for equality.'.format(node.left.value)) elif not self.is_elementary_type(val2): raise InterpreterException('{} can only be compared for equality.'.format(node.right.value)) elif node.ctype == '<': return val1 < val2 elif node.ctype == '<=': return val1 <= val2 elif node.ctype == '>': return val1 > val2 elif node.ctype == '>=': return val1 >= val2 else: raise InvalidCode('You broke my compare eval.') def evaluate_andstatement(self, cur): l = self.evaluate_statement(cur.left) if is_disabler(l): return l if not isinstance(l, bool): raise InterpreterException('First argument to "and" is not a boolean.') if not l: return False r = self.evaluate_statement(cur.right) if is_disabler(r): return r if not isinstance(r, bool): raise InterpreterException('Second argument to "and" is not a boolean.') return r def evaluate_orstatement(self, cur): l = self.evaluate_statement(cur.left) if is_disabler(l): return l if not isinstance(l, bool): raise InterpreterException('First argument to "or" is not a boolean.') if l: return True r = self.evaluate_statement(cur.right) if is_disabler(r): return r if not isinstance(r, bool): raise InterpreterException('Second argument to "or" is not a boolean.') return r def evaluate_uminusstatement(self, cur): v = self.evaluate_statement(cur.value) if is_disabler(v): return v if not isinstance(v, int): raise InterpreterException('Argument to negation is not an integer.') return -v def evaluate_arithmeticstatement(self, cur): l = self.evaluate_statement(cur.left) if is_disabler(l): return l r = self.evaluate_statement(cur.right) if is_disabler(r): return r if cur.operation == 'add': try: return l + r except Exception as e: raise InvalidCode('Invalid use of addition: ' + str(e)) elif cur.operation == 'sub': if not isinstance(l, int) or not isinstance(r, int): raise InvalidCode('Subtraction works only with integers.') return l - r elif cur.operation == 'mul': if not isinstance(l, int) or not isinstance(r, int): raise InvalidCode('Multiplication works only with integers.') return l * r elif cur.operation == 'div': if not isinstance(l, int) or not isinstance(r, int): raise InvalidCode('Division works only with integers.') return l // r elif cur.operation == 'mod': if not isinstance(l, int) or not isinstance(r, int): raise InvalidCode('Modulo works only with integers.') return l % r else: raise InvalidCode('You broke me.') def evaluate_ternary(self, node): assert(isinstance(node, mparser.TernaryNode)) result = self.evaluate_statement(node.condition) if is_disabler(result): return result if not isinstance(result, bool): raise InterpreterException('Ternary condition is not boolean.') if result: return self.evaluate_statement(node.trueblock) else: return self.evaluate_statement(node.falseblock) def evaluate_foreach(self, node): assert(isinstance(node, mparser.ForeachClauseNode)) varname = node.varname.value items = self.evaluate_statement(node.items) if is_disabler(items): return items if not isinstance(items, list): raise InvalidArguments('Items of foreach loop is not an array') for item in items: self.set_variable(varname, item) self.evaluate_codeblock(node.block) def evaluate_plusassign(self, node): assert(isinstance(node, mparser.PlusAssignmentNode)) varname = node.var_name addition = self.evaluate_statement(node.value) if is_disabler(addition): set_variable(varname, addition) return # Remember that all variables are immutable. We must always create a # full new variable and then assign it. old_variable = self.get_variable(varname) if isinstance(old_variable, str): if not isinstance(addition, str): raise InvalidArguments('The += operator requires a string on the right hand side if the variable on the left is a string') new_value = old_variable + addition elif isinstance(old_variable, int): if not isinstance(addition, int): raise InvalidArguments('The += operator requires an int on the right hand side if the variable on the left is an int') new_value = old_variable + addition elif not isinstance(old_variable, list): raise InvalidArguments('The += operator currently only works with arrays, strings or ints ') # Add other data types here. else: if isinstance(addition, list): new_value = old_variable + addition else: new_value = old_variable + [addition] self.set_variable(varname, new_value) def evaluate_indexing(self, node): assert(isinstance(node, mparser.IndexNode)) iobject = self.evaluate_statement(node.iobject) if is_disabler(iobject): return iobject if not hasattr(iobject, '__getitem__'): raise InterpreterException( 'Tried to index an object that doesn\'t support indexing.') index = self.evaluate_statement(node.index) if not isinstance(index, int): raise InterpreterException('Index value is not an integer.') try: return iobject[index] except IndexError: raise InterpreterException('Index %d out of bounds of array of size %d.' % (index, len(iobject))) def function_call(self, node): func_name = node.func_name (posargs, kwargs) = self.reduce_arguments(node.args) if is_disabled(posargs, kwargs): return Disabler() if func_name in self.funcs: return self.funcs[func_name](node, self.flatten(posargs), kwargs) else: self.unknown_function_called(func_name) def method_call(self, node): invokable = node.source_object if isinstance(invokable, mparser.IdNode): object_name = invokable.value obj = self.get_variable(object_name) else: obj = self.evaluate_statement(invokable) method_name = node.name args = node.args if isinstance(obj, str): return self.string_method_call(obj, method_name, args) if isinstance(obj, bool): return self.bool_method_call(obj, method_name, args) if isinstance(obj, int): return self.int_method_call(obj, method_name, args) if isinstance(obj, list): return self.array_method_call(obj, method_name, args) if isinstance(obj, mesonlib.File): raise InvalidArguments('File object "%s" is not callable.' % obj) if not isinstance(obj, InterpreterObject): raise InvalidArguments('Variable "%s" is not callable.' % object_name) (args, kwargs) = self.reduce_arguments(args) # Special case. This is the only thing you can do with a disabler # object. Every other use immediately returns the disabler object. if isinstance(obj, Disabler) and method_name == 'found': return False if is_disabled(args, kwargs): return Disabler() if method_name == 'extract_objects': self.validate_extraction(obj.held_object) return obj.method_call(method_name, self.flatten(args), kwargs) def bool_method_call(self, obj, method_name, args): (posargs, kwargs) = self.reduce_arguments(args) if is_disabled(posargs, kwargs): return Disabler() if method_name == 'to_string': if not posargs: if obj: return 'true' else: return 'false' elif len(posargs) == 2 and isinstance(posargs[0], str) and isinstance(posargs[1], str): if obj: return posargs[0] else: return posargs[1] else: raise InterpreterException('bool.to_string() must have either no arguments or exactly two string arguments that signify what values to return for true and false.') elif method_name == 'to_int': if obj: return 1 else: return 0 else: raise InterpreterException('Unknown method "%s" for a boolean.' % method_name) def int_method_call(self, obj, method_name, args): (posargs, kwargs) = self.reduce_arguments(args) if is_disabled(posargs, kwargs): return Disabler() if method_name == 'is_even': if not posargs: return obj % 2 == 0 else: raise InterpreterException('int.is_even() must have no arguments.') elif method_name == 'is_odd': if not posargs: return obj % 2 != 0 else: raise InterpreterException('int.is_odd() must have no arguments.') elif method_name == 'to_string': if not posargs: return str(obj) else: raise InterpreterException('int.to_string() must have no arguments.') else: raise InterpreterException('Unknown method "%s" for an integer.' % method_name) @staticmethod def _get_one_string_posarg(posargs, method_name): if len(posargs) > 1: m = '{}() must have zero or one arguments' raise InterpreterException(m.format(method_name)) elif len(posargs) == 1: s = posargs[0] if not isinstance(s, str): m = '{}() argument must be a string' raise InterpreterException(m.format(method_name)) return s return None def string_method_call(self, obj, method_name, args): (posargs, kwargs) = self.reduce_arguments(args) if is_disabled(posargs, kwargs): return Disabler() if method_name == 'strip': s = self._get_one_string_posarg(posargs, 'strip') if s is not None: return obj.strip(s) return obj.strip() elif method_name == 'format': return self.format_string(obj, args) elif method_name == 'to_upper': return obj.upper() elif method_name == 'to_lower': return obj.lower() elif method_name == 'underscorify': return re.sub(r'[^a-zA-Z0-9]', '_', obj) elif method_name == 'split': s = self._get_one_string_posarg(posargs, 'split') if s is not None: return obj.split(s) return obj.split() elif method_name == 'startswith' or method_name == 'contains' or method_name == 'endswith': s = posargs[0] if not isinstance(s, str): raise InterpreterException('Argument must be a string.') if method_name == 'startswith': return obj.startswith(s) elif method_name == 'contains': return obj.find(s) >= 0 return obj.endswith(s) elif method_name == 'to_int': try: return int(obj) except Exception: raise InterpreterException('String {!r} cannot be converted to int'.format(obj)) elif method_name == 'join': if len(posargs) != 1: raise InterpreterException('Join() takes exactly one argument.') strlist = posargs[0] check_stringlist(strlist) return obj.join(strlist) elif method_name == 'version_compare': if len(posargs) != 1: raise InterpreterException('Version_compare() takes exactly one argument.') cmpr = posargs[0] if not isinstance(cmpr, str): raise InterpreterException('Version_compare() argument must be a string.') return mesonlib.version_compare(obj, cmpr) raise InterpreterException('Unknown method "%s" for a string.' % method_name) def unknown_function_called(self, func_name): raise InvalidCode('Unknown function "%s".' % func_name) def array_method_call(self, obj, method_name, args): (posargs, kwargs) = self.reduce_arguments(args) if is_disabled(posargs, kwargs): return Disabler() if method_name == 'contains': return self.check_contains(obj, posargs) elif method_name == 'length': return len(obj) elif method_name == 'get': index = posargs[0] fallback = None if len(posargs) == 2: fallback = posargs[1] elif len(posargs) > 2: m = 'Array method \'get()\' only takes two arguments: the ' \ 'index and an optional fallback value if the index is ' \ 'out of range.' raise InvalidArguments(m) if not isinstance(index, int): raise InvalidArguments('Array index must be a number.') if index < -len(obj) or index >= len(obj): if fallback is None: m = 'Array index {!r} is out of bounds for array of size {!r}.' raise InvalidArguments(m.format(index, len(obj))) return fallback return obj[index] m = 'Arrays do not have a method called {!r}.' raise InterpreterException(m.format(method_name)) def reduce_arguments(self, args): assert(isinstance(args, mparser.ArgumentNode)) if args.incorrect_order(): raise InvalidArguments('All keyword arguments must be after positional arguments.') self.argument_depth += 1 reduced_pos = [self.evaluate_statement(arg) for arg in args.arguments] reduced_kw = {} for key in args.kwargs.keys(): if not isinstance(key, str): raise InvalidArguments('Keyword argument name is not a string.') a = args.kwargs[key] reduced_kw[key] = self.evaluate_statement(a) self.argument_depth -= 1 return reduced_pos, reduced_kw def flatten(self, args): if isinstance(args, mparser.StringNode): return args.value if isinstance(args, (int, str, mesonlib.File, InterpreterObject)): return args result = [] for a in args: if isinstance(a, list): rest = self.flatten(a) result = result + rest elif isinstance(a, mparser.StringNode): result.append(a.value) else: result.append(a) return result def assignment(self, node): assert(isinstance(node, mparser.AssignmentNode)) if self.argument_depth != 0: raise InvalidArguments('''Tried to assign values inside an argument list. To specify a keyword argument, use : instead of =.''') var_name = node.var_name if not isinstance(var_name, str): raise InvalidArguments('Tried to assign value to a non-variable.') value = self.evaluate_statement(node.value) if not self.is_assignable(value): raise InvalidCode('Tried to assign an invalid value to variable.') # For mutable objects we need to make a copy on assignment if isinstance(value, MutableInterpreterObject): value = copy.deepcopy(value) self.set_variable(var_name, value) return None def set_variable(self, varname, variable): if variable is None: raise InvalidCode('Can not assign None to variable.') if not isinstance(varname, str): raise InvalidCode('First argument to set_variable must be a string.') if not self.is_assignable(variable): raise InvalidCode('Assigned value not of assignable type.') if re.match('[_a-zA-Z][_0-9a-zA-Z]*$', varname) is None: raise InvalidCode('Invalid variable name: ' + varname) if varname in self.builtin: raise InvalidCode('Tried to overwrite internal variable "%s"' % varname) self.variables[varname] = variable def get_variable(self, varname): if varname in self.builtin: return self.builtin[varname] if varname in self.variables: return self.variables[varname] raise InvalidCode('Unknown variable "%s".' % varname) def is_assignable(self, value): return isinstance(value, (InterpreterObject, dependencies.Dependency, str, int, list, mesonlib.File)) def is_elementary_type(self, v): return isinstance(v, (int, float, str, bool, list)) meson-0.45.1/mesonbuild/wrap/0000755000175000017500000000000013254552746017443 5ustar jpakkanejpakkane00000000000000meson-0.45.1/mesonbuild/wrap/wrap.py0000644000175000017500000004003213243104135020744 0ustar jpakkanejpakkane00000000000000# Copyright 2015 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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 .. import mlog import contextlib import urllib.request, os, hashlib, shutil, tempfile, stat import subprocess import sys from pathlib import Path from . import WrapMode from ..mesonlib import Popen_safe try: import ssl has_ssl = True API_ROOT = 'https://wrapdb.mesonbuild.com/v1/' except ImportError: has_ssl = False API_ROOT = 'http://wrapdb.mesonbuild.com/v1/' ssl_warning_printed = False def build_ssl_context(): ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) ctx.options |= ssl.OP_NO_SSLv2 ctx.options |= ssl.OP_NO_SSLv3 ctx.verify_mode = ssl.CERT_REQUIRED ctx.load_default_certs() return ctx def quiet_git(cmd, workingdir): pc = subprocess.Popen(['git', '-C', workingdir] + cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = pc.communicate() if pc.returncode != 0: return False, err return True, out def open_wrapdburl(urlstring): global ssl_warning_printed if has_ssl: try: return urllib.request.urlopen(urlstring)# , context=build_ssl_context()) except urllib.error.URLError: if not ssl_warning_printed: print('SSL connection failed. Falling back to unencrypted connections.') ssl_warning_printed = True if not ssl_warning_printed: print('Warning: SSL not available, traffic not authenticated.', file=sys.stderr) ssl_warning_printed = True # Trying to open SSL connection to wrapdb fails because the # certificate is not known. if urlstring.startswith('https'): urlstring = 'http' + urlstring[5:] return urllib.request.urlopen(urlstring) class PackageDefinition: def __init__(self, fname): self.values = {} with open(fname) as ifile: first = ifile.readline().strip() if first == '[wrap-file]': self.type = 'file' elif first == '[wrap-git]': self.type = 'git' elif first == '[wrap-hg]': self.type = 'hg' elif first == '[wrap-svn]': self.type = 'svn' else: raise RuntimeError('Invalid format of package file') for line in ifile: line = line.strip() if line == '': continue (k, v) = line.split('=', 1) k = k.strip() v = v.strip() self.values[k] = v def get(self, key): return self.values[key] def has_patch(self): return 'patch_url' in self.values class Resolver: def __init__(self, subdir_root, wrap_mode=WrapMode(1)): self.wrap_mode = wrap_mode self.subdir_root = subdir_root self.cachedir = os.path.join(self.subdir_root, 'packagecache') def resolve(self, packagename): # Check if the directory is already resolved dirname = Path(os.path.join(self.subdir_root, packagename)) subprojdir = os.path.join(*dirname.parts[-2:]) if dirname.is_dir(): if (dirname / 'meson.build').is_file(): # The directory is there and has meson.build? Great, use it. return packagename # Is the dir not empty and also not a git submodule dir that is # not checkout properly? Can't do anything, exception! elif next(dirname.iterdir(), None) and not (dirname / '.git').is_file(): m = '{!r} is not empty and has no meson.build files' raise RuntimeError(m.format(subprojdir)) elif dirname.exists(): m = '{!r} already exists and is not a dir; cannot use as subproject' raise RuntimeError(m.format(subprojdir)) dirname = str(dirname) # Check if the subproject is a git submodule if self.resolve_git_submodule(dirname): return packagename # Don't download subproject data based on wrap file if requested. # Git submodules are ok (see above)! if self.wrap_mode is WrapMode.nodownload: m = 'Automatic wrap-based subproject downloading is disabled' raise RuntimeError(m) # Check if there's a .wrap file for this subproject fname = os.path.join(self.subdir_root, packagename + '.wrap') if not os.path.isfile(fname): # No wrap file with this name? Give up. m = 'No {}.wrap found for {!r}' raise RuntimeError(m.format(packagename, subprojdir)) p = PackageDefinition(fname) if p.type == 'file': if not os.path.isdir(self.cachedir): os.mkdir(self.cachedir) self.download(p, packagename) self.extract_package(p) elif p.type == 'git': self.get_git(p) elif p.type == "hg": self.get_hg(p) elif p.type == "svn": self.get_svn(p) else: raise AssertionError('Unreachable code.') return p.get('directory') def resolve_git_submodule(self, dirname): # Are we in a git repository? ret, out = quiet_git(['rev-parse'], self.subdir_root) if not ret: return False # Is `dirname` a submodule? ret, out = quiet_git(['submodule', 'status', dirname], self.subdir_root) if not ret: return False # Submodule has not been added, add it if out.startswith(b'+'): mlog.warning('git submodule {} might be out of date'.format(dirname)) return True elif out.startswith(b'U'): raise RuntimeError('submodule {} has merge conflicts'.format(dirname)) # Submodule exists, but is deinitialized or wasn't initialized elif out.startswith(b'-'): if subprocess.call(['git', '-C', self.subdir_root, 'submodule', 'update', '--init', dirname]) == 0: return True raise RuntimeError('Failed to git submodule init {!r}'.format(dirname)) # Submodule looks fine, but maybe it wasn't populated properly. Do a checkout. elif out.startswith(b' '): subprocess.call(['git', 'checkout', '.'], cwd=dirname) # Even if checkout failed, try building it anyway and let the user # handle any problems manually. return True m = 'Unknown git submodule output: {!r}' raise RuntimeError(m.format(out)) def get_git(self, p): checkoutdir = os.path.join(self.subdir_root, p.get('directory')) revno = p.get('revision') is_there = os.path.isdir(checkoutdir) if is_there: try: subprocess.check_call(['git', 'rev-parse'], cwd=checkoutdir) except subprocess.CalledProcessError: raise RuntimeError('%s is not empty but is not a valid ' 'git repository, we can not work with it' ' as a subproject directory.' % ( checkoutdir)) if revno.lower() == 'head': # Failure to do pull is not a fatal error, # because otherwise you can't develop without # a working net connection. subprocess.call(['git', 'pull'], cwd=checkoutdir) else: if subprocess.call(['git', 'checkout', revno], cwd=checkoutdir) != 0: subprocess.check_call(['git', 'fetch'], cwd=checkoutdir) subprocess.check_call(['git', 'checkout', revno], cwd=checkoutdir) else: subprocess.check_call(['git', 'clone', p.get('url'), p.get('directory')], cwd=self.subdir_root) if revno.lower() != 'head': subprocess.check_call(['git', 'checkout', revno], cwd=checkoutdir) push_url = p.values.get('push-url') if push_url: subprocess.check_call(['git', 'remote', 'set-url', '--push', 'origin', push_url], cwd=checkoutdir) def get_hg(self, p): checkoutdir = os.path.join(self.subdir_root, p.get('directory')) revno = p.get('revision') is_there = os.path.isdir(checkoutdir) if is_there: if revno.lower() == 'tip': # Failure to do pull is not a fatal error, # because otherwise you can't develop without # a working net connection. subprocess.call(['hg', 'pull'], cwd=checkoutdir) else: if subprocess.call(['hg', 'checkout', revno], cwd=checkoutdir) != 0: subprocess.check_call(['hg', 'pull'], cwd=checkoutdir) subprocess.check_call(['hg', 'checkout', revno], cwd=checkoutdir) else: subprocess.check_call(['hg', 'clone', p.get('url'), p.get('directory')], cwd=self.subdir_root) if revno.lower() != 'tip': subprocess.check_call(['hg', 'checkout', revno], cwd=checkoutdir) def get_svn(self, p): checkoutdir = os.path.join(self.subdir_root, p.get('directory')) revno = p.get('revision') is_there = os.path.isdir(checkoutdir) if is_there: p, out = Popen_safe(['svn', 'info', '--show-item', 'revision', checkoutdir]) current_revno = out if current_revno == revno: return if revno.lower() == 'head': # Failure to do pull is not a fatal error, # because otherwise you can't develop without # a working net connection. subprocess.call(['svn', 'update'], cwd=checkoutdir) else: subprocess.check_call(['svn', 'update', '-r', revno], cwd=checkoutdir) else: subprocess.check_call(['svn', 'checkout', '-r', revno, p.get('url'), p.get('directory')], cwd=self.subdir_root) def get_data(self, url): blocksize = 10 * 1024 h = hashlib.sha256() tmpfile = tempfile.NamedTemporaryFile(mode='wb', dir=self.cachedir, delete=False) if url.startswith('https://wrapdb.mesonbuild.com'): resp = open_wrapdburl(url) else: resp = urllib.request.urlopen(url) with contextlib.closing(resp) as resp: try: dlsize = int(resp.info()['Content-Length']) except TypeError: dlsize = None if dlsize is None: print('Downloading file of unknown size.') while True: block = resp.read(blocksize) if block == b'': break h.update(block) tmpfile.write(block) hashvalue = h.hexdigest() return hashvalue, tmpfile.name print('Download size:', dlsize) print('Downloading: ', end='') sys.stdout.flush() printed_dots = 0 downloaded = 0 while True: block = resp.read(blocksize) if block == b'': break downloaded += len(block) h.update(block) tmpfile.write(block) ratio = int(downloaded / dlsize * 10) while printed_dots < ratio: print('.', end='') sys.stdout.flush() printed_dots += 1 print('') hashvalue = h.hexdigest() return hashvalue, tmpfile.name def get_hash(self, data): h = hashlib.sha256() h.update(data) hashvalue = h.hexdigest() return hashvalue def download(self, p, packagename): ofname = os.path.join(self.cachedir, p.get('source_filename')) if os.path.exists(ofname): mlog.log('Using', mlog.bold(packagename), 'from cache.') else: srcurl = p.get('source_url') mlog.log('Downloading', mlog.bold(packagename), 'from', mlog.bold(srcurl)) dhash, tmpfile = self.get_data(srcurl) expected = p.get('source_hash') if dhash != expected: os.remove(tmpfile) raise RuntimeError('Incorrect hash for source %s:\n %s expected\n %s actual.' % (packagename, expected, dhash)) os.rename(tmpfile, ofname) if p.has_patch(): patch_filename = p.get('patch_filename') filename = os.path.join(self.cachedir, patch_filename) if os.path.exists(filename): mlog.log('Using', mlog.bold(patch_filename), 'from cache.') else: purl = p.get('patch_url') mlog.log('Downloading patch from', mlog.bold(purl)) phash, tmpfile = self.get_data(purl) expected = p.get('patch_hash') if phash != expected: os.remove(tmpfile) raise RuntimeError('Incorrect hash for patch %s:\n %s expected\n %s actual' % (packagename, expected, phash)) os.rename(tmpfile, filename) else: mlog.log('Package does not require patch.') def copy_tree(self, root_src_dir, root_dst_dir): """ Copy directory tree. Overwrites also read only files. """ for src_dir, dirs, files in os.walk(root_src_dir): dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1) if not os.path.exists(dst_dir): os.makedirs(dst_dir) for file_ in files: src_file = os.path.join(src_dir, file_) dst_file = os.path.join(dst_dir, file_) if os.path.exists(dst_file): try: os.remove(dst_file) except PermissionError as exc: os.chmod(dst_file, stat.S_IWUSR) os.remove(dst_file) shutil.copy2(src_file, dst_dir) def extract_package(self, package): if sys.version_info < (3, 5): try: import lzma # noqa: F401 del lzma except ImportError: pass else: try: shutil.register_unpack_format('xztar', ['.tar.xz', '.txz'], shutil._unpack_tarfile, [], "xz'ed tar-file") except shutil.RegistryError: pass target_dir = os.path.join(self.subdir_root, package.get('directory')) if os.path.isdir(target_dir): return extract_dir = self.subdir_root # Some upstreams ship packages that do not have a leading directory. # Create one for them. try: package.get('lead_directory_missing') os.mkdir(target_dir) extract_dir = target_dir except KeyError: pass shutil.unpack_archive(os.path.join(self.cachedir, package.get('source_filename')), extract_dir) if package.has_patch(): try: shutil.unpack_archive(os.path.join(self.cachedir, package.get('patch_filename')), self.subdir_root) except Exception: with tempfile.TemporaryDirectory() as workdir: shutil.unpack_archive(os.path.join(self.cachedir, package.get('patch_filename')), workdir) self.copy_tree(workdir, self.subdir_root) meson-0.45.1/mesonbuild/wrap/__init__.py0000644000175000017500000000234613066536047021556 0ustar jpakkanejpakkane00000000000000from enum import Enum # Used for the --wrap-mode command-line argument # # Special wrap modes: # nofallback: Don't download wraps for dependency() fallbacks # nodownload: Don't download wraps for all subproject() calls # # subprojects are used for two purposes: # 1. To download and build dependencies by using .wrap # files if they are not provided by the system. This is # usually expressed via dependency(..., fallback: ...). # 2. To download and build 'copylibs' which are meant to be # used by copying into your project. This is always done # with an explicit subproject() call. # # --wrap-mode=nofallback will never do (1) # --wrap-mode=nodownload will do neither (1) nor (2) # # If you are building from a release tarball, you should be # able to safely use 'nodownload' since upstream is # expected to ship all required sources with the tarball. # # If you are building from a git repository, you will want # to use 'nofallback' so that any 'copylib' wraps will be # download as subprojects. # # Note that these options do not affect subprojects that # are git submodules since those are only usable in git # repositories, and you almost always want to download them. WrapMode = Enum('WrapMode', 'default nofallback nodownload') meson-0.45.1/mesonbuild/wrap/wraptool.py0000644000175000017500000001760013243342167021660 0ustar jpakkanejpakkane00000000000000# Copyright 2015-2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import json import sys, os import configparser import shutil from glob import glob from .wrap import API_ROOT, open_wrapdburl from .. import mesonlib help_templ = '''This program allows you to manage your Wrap dependencies using the online wrap database http://wrapdb.mesonbuild.com. Run this command in your top level source directory. Usage: %s [options] Commands: list - show all available projects search - search the db by name install - install the specified project update - update the project to its newest available release info - show available versions of a project status - show installed and available versions of your projects promote - bring a subsubproject up to the master project ''' def print_help(): print(help_templ % sys.argv[0]) def get_result(urlstring): u = open_wrapdburl(urlstring) data = u.read().decode('utf-8') jd = json.loads(data) if jd['output'] != 'ok': print('Got bad output from server.') print(data) sys.exit(1) return jd def get_projectlist(): jd = get_result(API_ROOT + 'projects') projects = jd['projects'] return projects def list_projects(): projects = get_projectlist() for p in projects: print(p) def search(name): jd = get_result(API_ROOT + 'query/byname/' + name) for p in jd['projects']: print(p) def get_latest_version(name): jd = get_result(API_ROOT + 'query/get_latest/' + name) branch = jd['branch'] revision = jd['revision'] return branch, revision def install(name): if not os.path.isdir('subprojects'): print('Subprojects dir not found. Run this script in your source root directory.') sys.exit(1) if os.path.isdir(os.path.join('subprojects', name)): print('Subproject directory for this project already exists.') sys.exit(1) wrapfile = os.path.join('subprojects', name + '.wrap') if os.path.exists(wrapfile): print('Wrap file already exists.') sys.exit(1) (branch, revision) = get_latest_version(name) u = open_wrapdburl(API_ROOT + 'projects/%s/%s/%s/get_wrap' % (name, branch, revision)) data = u.read() with open(wrapfile, 'wb') as f: f.write(data) print('Installed', name, 'branch', branch, 'revision', revision) def get_current_version(wrapfile): cp = configparser.ConfigParser() cp.read(wrapfile) cp = cp['wrap-file'] patch_url = cp['patch_url'] arr = patch_url.split('/') branch = arr[-3] revision = int(arr[-2]) return branch, revision, cp['directory'], cp['source_filename'], cp['patch_filename'] def update(name): if not os.path.isdir('subprojects'): print('Subprojects dir not found. Run this command in your source root directory.') sys.exit(1) wrapfile = os.path.join('subprojects', name + '.wrap') if not os.path.exists(wrapfile): print('Project', name, 'is not in use.') sys.exit(1) (branch, revision, subdir, src_file, patch_file) = get_current_version(wrapfile) (new_branch, new_revision) = get_latest_version(name) if new_branch == branch and new_revision == revision: print('Project', name, 'is already up to date.') sys.exit(0) u = open_wrapdburl(API_ROOT + 'projects/%s/%s/%d/get_wrap' % (name, new_branch, new_revision)) data = u.read() shutil.rmtree(os.path.join('subprojects', subdir), ignore_errors=True) try: os.unlink(os.path.join('subprojects/packagecache', src_file)) except FileNotFoundError: pass try: os.unlink(os.path.join('subprojects/packagecache', patch_file)) except FileNotFoundError: pass with open(wrapfile, 'wb') as f: f.write(data) print('Updated', name, 'to branch', new_branch, 'revision', new_revision) def info(name): jd = get_result(API_ROOT + 'projects/' + name) versions = jd['versions'] if not versions: print('No available versions of', name) sys.exit(0) print('Available versions of %s:' % name) for v in versions: print(' ', v['branch'], v['revision']) def do_promotion(from_path, spdir_name): if os.path.isfile(from_path): assert(from_path.endswith('.wrap')) shutil.copy(from_path, spdir_name) elif os.path.isdir(from_path): sproj_name = os.path.basename(from_path) outputdir = os.path.join(spdir_name, sproj_name) if os.path.exists(outputdir): sys.exit('Output dir %s already exists. Will not overwrite.' % outputdir) shutil.copytree(from_path, outputdir, ignore=shutil.ignore_patterns('subprojects')) def promote(argument): path_segment, subproject_name = os.path.split(argument) spdir_name = 'subprojects' sprojs = mesonlib.detect_subprojects(spdir_name) if subproject_name not in sprojs: sys.exit('Subproject %s not found in directory tree.' % subproject_name) matches = sprojs[subproject_name] if len(matches) == 1: do_promotion(matches[0], spdir_name) return if path_segment == '': print('There are many versions of %s in tree. Please specify which one to promote:\n' % subproject_name) for s in matches: print(s) sys.exit(1) system_native_path_argument = argument.replace('/', os.sep) if system_native_path_argument in matches: do_promotion(argument, spdir_name) def status(): print('Subproject status') for w in glob('subprojects/*.wrap'): name = os.path.basename(w)[:-5] try: (latest_branch, latest_revision) = get_latest_version(name) except Exception: print('', name, 'not available in wrapdb.') continue try: (current_branch, current_revision, _, _, _) = get_current_version(w) except Exception: print('Wrap file not from wrapdb.') continue if current_branch == latest_branch and current_revision == latest_revision: print('', name, 'up to date. Branch %s, revision %d.' % (current_branch, current_revision)) else: print('', name, 'not up to date. Have %s %d, but %s %d is available.' % (current_branch, current_revision, latest_branch, latest_revision)) def run(args): if not args or args[0] == '-h' or args[0] == '--help': print_help() return 0 command = args[0] args = args[1:] if command == 'list': list_projects() elif command == 'search': if len(args) != 1: print('Search requires exactly one argument.') return 1 search(args[0]) elif command == 'install': if len(args) != 1: print('Install requires exactly one argument.') return 1 install(args[0]) elif command == 'update': if len(args) != 1: print('update requires exactly one argument.') return 1 update(args[0]) elif command == 'info': if len(args) != 1: print('info requires exactly one argument.') return 1 info(args[0]) elif command == 'promote': if len(args) != 1: print('promote requires exactly one argument.') return 1 promote(args[0]) elif command == 'status': status() else: print('Unknown command', command) return 1 return 0 if __name__ == '__main__': sys.exit(run(sys.argv[1:])) meson-0.45.1/mesonbuild/optinterpreter.py0000644000175000017500000002437013254550710022125 0ustar jpakkanejpakkane00000000000000# Copyright 2013-2014 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os, re import functools from . import mlog from . import mparser from . import coredata from . import mesonlib forbidden_option_names = coredata.get_builtin_options() forbidden_prefixes = {'c_', 'cpp_', 'd_', 'rust_', 'fortran_', 'objc_', 'objcpp_', 'vala_', 'csharp_', 'swift_', 'b_', 'backend_', } def is_invalid_name(name): if name in forbidden_option_names: return True pref = name.split('_')[0] + '_' if pref in forbidden_prefixes: return True return False class OptionException(mesonlib.MesonException): pass def permitted_kwargs(permitted): """Function that validates kwargs for options.""" def _wraps(func): @functools.wraps(func) def _inner(name, description, kwargs): bad = [a for a in kwargs.keys() if a not in permitted] if bad: raise OptionException('Invalid kwargs for option "{}": "{}"'.format( name, ' '.join(bad))) return func(name, description, kwargs) return _inner return _wraps optname_regex = re.compile('[^a-zA-Z0-9_-]') @permitted_kwargs({'value', 'yield'}) def StringParser(name, description, kwargs): return coredata.UserStringOption(name, description, kwargs.get('value', ''), kwargs.get('choices', []), kwargs.get('yield', coredata.default_yielding)) @permitted_kwargs({'value', 'yield'}) def BooleanParser(name, description, kwargs): return coredata.UserBooleanOption(name, description, kwargs.get('value', True), kwargs.get('yield', coredata.default_yielding)) @permitted_kwargs({'value', 'yiel', 'choices'}) def ComboParser(name, description, kwargs): if 'choices' not in kwargs: raise OptionException('Combo option missing "choices" keyword.') choices = kwargs['choices'] if not isinstance(choices, list): raise OptionException('Combo choices must be an array.') for i in choices: if not isinstance(i, str): raise OptionException('Combo choice elements must be strings.') return coredata.UserComboOption(name, description, choices, kwargs.get('value', choices[0]), kwargs.get('yield', coredata.default_yielding),) @permitted_kwargs({'value', 'min', 'max', 'yield'}) def IntegerParser(name, description, kwargs): if 'value' not in kwargs: raise OptionException('Integer option must contain value argument.') return coredata.UserIntegerOption(name, description, kwargs.get('min', None), kwargs.get('max', None), kwargs['value'], kwargs.get('yield', coredata.default_yielding)) @permitted_kwargs({'value', 'yield', 'choices'}) def string_array_parser(name, description, kwargs): if 'choices' in kwargs: choices = kwargs['choices'] if not isinstance(choices, list): raise OptionException('Array choices must be an array.') for i in choices: if not isinstance(i, str): raise OptionException('Array choice elements must be strings.') value = kwargs.get('value', choices) else: choices = None value = kwargs.get('value', []) if not isinstance(value, list): raise OptionException('Array choices must be passed as an array.') return coredata.UserArrayOption(name, description, value, choices=choices, yielding=kwargs.get('yield', coredata.default_yielding)) option_types = {'string': StringParser, 'boolean': BooleanParser, 'combo': ComboParser, 'integer': IntegerParser, 'array': string_array_parser, } class OptionInterpreter: def __init__(self, subproject, command_line_options): self.options = {} self.subproject = subproject self.sbprefix = subproject + ':' self.cmd_line_options = {} for o in command_line_options: if self.subproject != '': # Strip the beginning. # Ignore options that aren't for this subproject if not o.startswith(self.sbprefix): continue try: (key, value) = o.split('=', 1) except ValueError: raise OptionException('Option {!r} must have a value separated by equals sign.'.format(o)) # Ignore subproject options if not fetching subproject options if self.subproject == '' and ':' in key: continue self.cmd_line_options[key] = value def get_bad_options(self): subproj_len = len(self.subproject) if subproj_len > 0: subproj_len += 1 retval = [] # The options need to be sorted (e.g. here) to get consistent # error messages (on all platforms) which is required by some test # cases that check (also) the order of these options. for option in sorted(self.cmd_line_options): if option in list(self.options) + forbidden_option_names: continue if any(option[subproj_len:].startswith(p) for p in forbidden_prefixes): continue retval += [option] return retval def check_for_bad_options(self): bad = self.get_bad_options() if bad: sub = 'In subproject {}: '.format(self.subproject) if self.subproject else '' mlog.warning( '{}Unknown command line options: "{}"\n' 'This will become a hard error in a future Meson release.'.format(sub, ', '.join(bad))) def process(self, option_file): try: with open(option_file, 'r', encoding='utf8') as f: ast = mparser.Parser(f.read(), '').parse() except mesonlib.MesonException as me: me.file = option_file raise me if not isinstance(ast, mparser.CodeBlockNode): e = OptionException('Option file is malformed.') e.lineno = ast.lineno() raise e for cur in ast.lines: try: self.evaluate_statement(cur) except Exception as e: e.lineno = cur.lineno e.colno = cur.colno e.file = os.path.join('meson_options.txt') raise e self.check_for_bad_options() def reduce_single(self, arg): if isinstance(arg, str): return arg elif isinstance(arg, (mparser.StringNode, mparser.BooleanNode, mparser.NumberNode)): return arg.value elif isinstance(arg, mparser.ArrayNode): return [self.reduce_single(curarg) for curarg in arg.args.arguments] else: raise OptionException('Arguments may only be string, int, bool, or array of those.') def reduce_arguments(self, args): assert(isinstance(args, mparser.ArgumentNode)) if args.incorrect_order(): raise OptionException('All keyword arguments must be after positional arguments.') reduced_pos = [self.reduce_single(arg) for arg in args.arguments] reduced_kw = {} for key in args.kwargs.keys(): if not isinstance(key, str): raise OptionException('Keyword argument name is not a string.') a = args.kwargs[key] reduced_kw[key] = self.reduce_single(a) return reduced_pos, reduced_kw def evaluate_statement(self, node): if not isinstance(node, mparser.FunctionNode): raise OptionException('Option file may only contain option definitions') func_name = node.func_name if func_name != 'option': raise OptionException('Only calls to option() are allowed in option files.') (posargs, kwargs) = self.reduce_arguments(node.args) if 'type' not in kwargs: raise OptionException('Option call missing mandatory "type" keyword argument') opt_type = kwargs.pop('type') if opt_type not in option_types: raise OptionException('Unknown type %s.' % opt_type) if len(posargs) != 1: raise OptionException('Option() must have one (and only one) positional argument') opt_name = posargs[0] if not isinstance(opt_name, str): raise OptionException('Positional argument must be a string.') if optname_regex.search(opt_name) is not None: raise OptionException('Option names can only contain letters, numbers or dashes.') if is_invalid_name(opt_name): raise OptionException('Option name %s is reserved.' % opt_name) if self.subproject != '': opt_name = self.subproject + ':' + opt_name opt = option_types[opt_type](opt_name, kwargs.pop('description', ''), kwargs) if opt.description == '': opt.description = opt_name if opt_name in self.cmd_line_options: opt.set_value(self.cmd_line_options[opt_name]) self.options[opt_name] = opt meson-0.45.1/mesonbuild/build.py0000644000175000017500000024222013254550710020132 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2017 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import copy, os, re from collections import OrderedDict import itertools, pathlib import pickle from . import environment from . import dependencies from . import mlog from .mesonlib import File, MesonException, listify, extract_as_list from .mesonlib import typeslistify, stringlistify, classify_unity_sources from .mesonlib import get_filenames_templates_dict, substitute_values from .mesonlib import for_windows, for_darwin, for_cygwin, for_android from .compilers import is_object, clike_langs, sort_clike, lang_suffixes known_basic_kwargs = {'install': True, 'c_pch': True, 'cpp_pch': True, 'c_args': True, 'objc_args': True, 'objcpp_args': True, 'cpp_args': True, 'cs_args': True, 'vala_args': True, 'fortran_args': True, 'd_args': True, 'd_import_dirs': True, 'd_unittest': True, 'd_module_versions': True, 'java_args': True, 'rust_args': True, 'link_args': True, 'link_depends': True, 'link_with': True, 'link_whole': True, 'implicit_include_directories': True, 'include_directories': True, 'dependencies': True, 'install_dir': True, 'main_class': True, 'name_suffix': True, 'gui_app': True, 'extra_files': True, 'install_rpath': True, 'build_rpath': True, 'resources': True, 'sources': True, 'objects': True, 'native': True, 'build_by_default': True, 'override_options': True, } # These contain kwargs supported by both static and shared libraries. These are # combined here because a library() call might be shared_library() or # static_library() at runtime based on the configuration. # FIXME: Find a way to pass that info down here so we can have proper target # kwargs checking when specifically using shared_library() or static_library(). known_lib_kwargs = known_basic_kwargs.copy() known_lib_kwargs.update({'version': True, # Only for shared libs 'soversion': True, # Only for shared libs 'name_prefix': True, 'vs_module_defs': True, # Only for shared libs 'vala_header': True, 'vala_vapi': True, 'vala_gir': True, 'pic': True, # Only for static libs 'rust_crate_type': True, # Only for Rust libs }) known_exe_kwargs = known_basic_kwargs.copy() known_exe_kwargs.update({'implib': True, 'export_dynamic': True }) class InvalidArguments(MesonException): pass class Build: """A class that holds the status of one build including all dependencies and so on. """ def __init__(self, environment): self.project_name = 'name of master project' self.project_version = None self.environment = environment self.projects = {} self.targets = OrderedDict() self.compilers = OrderedDict() self.cross_compilers = OrderedDict() self.global_args = {} self.projects_args = {} self.global_link_args = {} self.projects_link_args = {} self.tests = [] self.benchmarks = [] self.headers = [] self.man = [] self.data = [] self.static_linker = None self.static_cross_linker = None self.subprojects = {} self.install_scripts = [] self.postconf_scripts = [] self.install_dirs = [] self.dep_manifest_name = None self.dep_manifest = {} self.cross_stdlibs = {} self.test_setups = {} def add_compiler(self, compiler): if self.static_linker is None and compiler.needs_static_linker(): self.static_linker = self.environment.detect_static_linker(compiler) lang = compiler.get_language() if lang not in self.compilers: self.compilers[lang] = compiler def add_cross_compiler(self, compiler): if not self.cross_compilers: self.static_cross_linker = self.environment.detect_static_linker(compiler) lang = compiler.get_language() if lang not in self.cross_compilers: self.cross_compilers[lang] = compiler def get_project(self): return self.projects[''] def get_targets(self): return self.targets def get_tests(self): return self.tests def get_benchmarks(self): return self.benchmarks def get_headers(self): return self.headers def get_man(self): return self.man def get_data(self): return self.data def get_install_subdirs(self): return self.install_dirs def get_global_args(self, compiler): return self.global_args.get(compiler.get_language(), []) def get_project_args(self, compiler, project): args = self.projects_args.get(project) if not args: return [] return args.get(compiler.get_language(), []) def get_global_link_args(self, compiler): return self.global_link_args.get(compiler.get_language(), []) def get_project_link_args(self, compiler, project): link_args = self.projects_link_args.get(project) if not link_args: return [] return link_args.get(compiler.get_language(), []) class IncludeDirs: def __init__(self, curdir, dirs, is_system, extra_build_dirs=None): self.curdir = curdir self.incdirs = dirs self.is_system = is_system # Interpreter has validated that all given directories # actually exist. if extra_build_dirs is None: self.extra_build_dirs = [] else: self.extra_build_dirs = extra_build_dirs def __repr__(self): r = '<{} {}/{}>' return r.format(self.__class__.__name__, self.curdir, self.incdirs) def get_curdir(self): return self.curdir def get_incdirs(self): return self.incdirs def get_extra_build_dirs(self): return self.extra_build_dirs class ExtractedObjects: ''' Holds a list of sources for which the objects must be extracted ''' def __init__(self, target, srclist, is_unity): self.target = target self.srclist = srclist if is_unity: self.check_unity_compatible() def __repr__(self): r = '<{0} {1!r}: {2}>' return r.format(self.__class__.__name__, self.target.name, self.srclist) def check_unity_compatible(self): # Figure out if the extracted object list is compatible with a Unity # build. When we're doing a Unified build, we go through the sources, # and create a single source file from each subset of the sources that # can be compiled with a specific compiler. Then we create one object # from each unified source file. # If the list of sources for which we want objects is the same as the # list of sources that go into each unified build, we're good. srclist_set = set(self.srclist) # Objects for all the sources are required, so we're compatible if srclist_set == set(self.target.sources): return # Check if the srclist is a subset (of the target's sources) that is # going to form a unified source file and a single object compsrcs = classify_unity_sources(self.target.compilers.values(), self.target.sources) for srcs in compsrcs.values(): if srclist_set == set(srcs): return msg = 'Single object files can not be extracted in Unity builds. ' \ 'You can only extract all the object files at once.' raise MesonException(msg) class EnvironmentVariables: def __init__(self): self.envvars = [] def __repr__(self): repr_str = "<{0}: {1}>" return repr_str.format(self.__class__.__name__, self.envvars) def get_value(self, values, kwargs): separator = kwargs.get('separator', os.pathsep) value = '' for var in values: value += separator + var return separator, value.strip(separator) def set(self, env, name, values, kwargs): return self.get_value(values, kwargs)[1] def append(self, env, name, values, kwargs): sep, value = self.get_value(values, kwargs) if name in env: return env[name] + sep + value return value def prepend(self, env, name, values, kwargs): sep, value = self.get_value(values, kwargs) if name in env: return value + sep + env[name] return value def get_env(self, full_env): env = {} for method, name, values, kwargs in self.envvars: env[name] = method(full_env, name, values, kwargs) return env class Target: def __init__(self, name, subdir, subproject, build_by_default): if '/' in name or '\\' in name: # Fix failing test 53 when this becomes an error. mlog.warning('''Target "%s" has a path separator in its name. This is not supported, it can cause unexpected failures and will become a hard error in the future.''' % name) self.name = name self.subdir = subdir self.subproject = subproject self.build_by_default = build_by_default self.install = False self.build_always = False self.option_overrides = {} def get_basename(self): return self.name def get_subdir(self): return self.subdir def get_id(self): # This ID must also be a valid file name on all OSs. # It should also avoid shell metacharacters for obvious # reasons. base = self.name + self.type_suffix() if self.subproject == '': return base return self.subproject + '@@' + base def process_kwargs(self, kwargs): if 'build_by_default' in kwargs: self.build_by_default = kwargs['build_by_default'] if not isinstance(self.build_by_default, bool): raise InvalidArguments('build_by_default must be a boolean value.') self.option_overrides = self.parse_overrides(kwargs) def parse_overrides(self, kwargs): result = {} overrides = stringlistify(kwargs.get('override_options', [])) for o in overrides: if '=' not in o: raise InvalidArguments('Overrides must be of form "key=value"') k, v = o.split('=', 1) k = k.strip() v = v.strip() result[k] = v return result class BuildTarget(Target): def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): super().__init__(name, subdir, subproject, True) self.is_cross = is_cross unity_opt = environment.coredata.get_builtin_option('unity') self.is_unity = unity_opt == 'on' or (unity_opt == 'subprojects' and subproject != '') self.environment = environment self.sources = [] self.compilers = OrderedDict() self.objects = [] self.external_deps = [] self.include_dirs = [] self.link_targets = [] self.link_whole_targets = [] self.link_depends = [] self.name_prefix_set = False self.name_suffix_set = False self.filename = 'no_name' # The list of all files outputted by this target. Useful in cases such # as Vala which generates .vapi and .h besides the compiled output. self.outputs = [self.filename] self.need_install = False self.pch = {} self.extra_args = {} self.generated = [] self.extra_files = [] self.d_features = {} # Sources can be: # 1. Pre-existing source files in the source tree # 2. Pre-existing sources generated by configure_file in the build tree # 3. Sources files generated by another target or a Generator self.process_sourcelist(sources) # Objects can be: # 1. Pre-existing objects provided by the user with the `objects:` kwarg # 2. Compiled objects created by and extracted from another target self.process_objectlist(objects) self.process_kwargs(kwargs, environment) self.check_unknown_kwargs(kwargs) self.process_compilers() if not any([self.sources, self.generated, self.objects, self.link_whole]): raise InvalidArguments('Build target %s has no sources.' % name) self.process_compilers_late() self.validate_sources() self.validate_cross_install(environment) def __lt__(self, other): return self.get_id() < other.get_id() def __repr__(self): repr_str = "<{0} {1}: {2}>" return repr_str.format(self.__class__.__name__, self.get_id(), self.filename) def validate_cross_install(self, environment): if environment.is_cross_build() and not self.is_cross and self.install: raise InvalidArguments('Tried to install a natively built target in a cross build.') def check_unknown_kwargs(self, kwargs): # Override this method in derived classes that have more # keywords. self.check_unknown_kwargs_int(kwargs, known_basic_kwargs) def check_unknown_kwargs_int(self, kwargs, known_kwargs): unknowns = [] for k in kwargs: if k not in known_kwargs: unknowns.append(k) if len(unknowns) > 0: mlog.warning('Unknown keyword argument(s) in target %s: %s.' % (self.name, ', '.join(unknowns))) def process_objectlist(self, objects): assert(isinstance(objects, list)) for s in objects: if hasattr(s, 'held_object'): s = s.held_object if isinstance(s, (str, File, ExtractedObjects)): self.objects.append(s) elif isinstance(s, (GeneratedList, CustomTarget)): msg = 'Generated files are not allowed in the \'objects\' kwarg ' + \ 'for target {!r}.\nIt is meant only for '.format(self.name) + \ 'pre-built object files that are shipped with the\nsource ' + \ 'tree. Try adding it in the list of sources.' raise InvalidArguments(msg) else: msg = 'Bad object of type {!r} in target {!r}.'.format(type(s).__name__, self.name) raise InvalidArguments(msg) def process_sourcelist(self, sources): sources = listify(sources) added_sources = {} # If the same source is defined multiple times, use it only once. for s in sources: # Holder unpacking. Ugly. if hasattr(s, 'held_object'): s = s.held_object if isinstance(s, File): if s not in added_sources: self.sources.append(s) added_sources[s] = True elif isinstance(s, (GeneratedList, CustomTarget, CustomTargetIndex)): self.generated.append(s) else: msg = 'Bad source of type {!r} in target {!r}.'.format(type(s).__name__, self.name) raise InvalidArguments(msg) @staticmethod def can_compile_remove_sources(compiler, sources): removed = False for s in sources[:]: if compiler.can_compile(s): sources.remove(s) removed = True return removed def process_compilers_late(self): """Processes additional compilers after kwargs have been evaluated. This can add extra compilers that might be required by keyword arguments, such as link_with or dependencies. It will also try to guess which compiler to use if one hasn't been selected already. """ # Populate list of compilers if self.is_cross: compilers = self.environment.coredata.cross_compilers else: compilers = self.environment.coredata.compilers # If this library is linked against another library we need to consider # the languages of those libraries as well. if self.link_targets or self.link_whole_targets: extra = set() for t in itertools.chain(self.link_targets, self.link_whole_targets): for name, compiler in t.compilers.items(): if name in clike_langs: extra.add((name, compiler)) for name, compiler in sorted(extra, key=lambda p: sort_clike(p[0])): self.compilers[name] = compiler if not self.compilers: # No source files or parent targets, target consists of only object # files of unknown origin. Just add the first clike compiler # that we have and hope that it can link these objects for lang in clike_langs: if lang in compilers: self.compilers[lang] = compilers[lang] break def process_compilers(self): ''' Populate self.compilers, which is the list of compilers that this target will use for compiling all its sources. We also add compilers that were used by extracted objects to simplify dynamic linker determination. ''' if not self.sources and not self.generated and not self.objects: return # Populate list of compilers if self.is_cross: compilers = self.environment.coredata.cross_compilers else: compilers = self.environment.coredata.compilers # Pre-existing sources sources = list(self.sources) # All generated sources for gensrc in self.generated: for s in gensrc.get_outputs(): # Generated objects can't be compiled, so don't use them for # compiler detection. If our target only has generated objects, # we will fall back to using the first c-like compiler we find, # which is what we need. if not is_object(s): sources.append(s) for d in self.external_deps: if hasattr(d, 'held_object'): d = d.held_object for s in d.sources: if isinstance(s, (str, File)): sources.append(s) # Sources that were used to create our extracted objects for o in self.objects: if not isinstance(o, ExtractedObjects): continue for s in o.srclist: # Don't add Vala sources since that will pull in the Vala # compiler even though we will never use it since we are # dealing with compiled C code. if not s.endswith(lang_suffixes['vala']): sources.append(s) if sources: # For each source, try to add one compiler that can compile it. # It's ok if no compilers can do so, because users are expected to # be able to add arbitrary non-source files to the sources list. for s in sources: for lang, compiler in compilers.items(): if compiler.can_compile(s): if lang not in self.compilers: self.compilers[lang] = compiler break # Re-sort according to clike_langs self.compilers = OrderedDict(sorted(self.compilers.items(), key=lambda t: sort_clike(t[0]))) # If all our sources are Vala, our target also needs the C compiler but # it won't get added above. if 'vala' in self.compilers and 'c' not in self.compilers: self.compilers['c'] = compilers['c'] def validate_sources(self): if not self.sources: return for lang in ('cs', 'java'): if lang in self.compilers: check_sources = list(self.sources) compiler = self.compilers[lang] if not self.can_compile_remove_sources(compiler, check_sources): m = 'No {} sources found in target {!r}'.format(lang, self.name) raise InvalidArguments(m) if check_sources: m = '{0} targets can only contain {0} files:\n'.format(lang.capitalize()) m += '\n'.join([repr(c) for c in check_sources]) raise InvalidArguments(m) # CSharp and Java targets can't contain any other file types assert(len(self.compilers) == 1) return def process_link_depends(self, sources, environment): """Process the link_depends keyword argument. This is designed to handle strings, Files, and the output of Custom Targets. Notably it doesn't handle generator() returned objects, since adding them as a link depends would inherently cause them to be generated twice, since the output needs to be passed to the ld_args and link_depends. """ sources = listify(sources) for s in sources: if hasattr(s, 'held_object'): s = s.held_object if isinstance(s, File): self.link_depends.append(s) elif isinstance(s, str): self.link_depends.append( File.from_source_file(environment.source_dir, self.subdir, s)) elif hasattr(s, 'get_outputs'): self.link_depends.extend( [File.from_built_file(s.subdir, p) for p in s.get_outputs()]) else: raise InvalidArguments( 'Link_depends arguments must be strings, Files, ' 'or a Custom Target, or lists thereof.') def get_original_kwargs(self): return self.kwargs def unpack_holder(self, d): d = listify(d) newd = [] for i in d: if isinstance(i, list): i = self.unpack_holder(i) elif hasattr(i, 'held_object'): i = i.held_object for t in ['dependencies', 'link_with', 'include_directories', 'sources']: if hasattr(i, t): setattr(i, t, self.unpack_holder(getattr(i, t))) newd.append(i) return newd def copy_kwargs(self, kwargs): self.kwargs = copy.copy(kwargs) # This sucks quite badly. Arguments # are holders but they can't be pickled # so unpack those known. for k, v in self.kwargs.items(): if isinstance(v, list): self.kwargs[k] = self.unpack_holder(v) if hasattr(v, 'held_object'): self.kwargs[k] = v.held_object for t in ['dependencies', 'link_with', 'include_directories', 'sources']: if t in self.kwargs: self.kwargs[t] = self.unpack_holder(self.kwargs[t]) def extract_objects(self, srclist): obj_src = [] for src in srclist: if not isinstance(src, str): raise MesonException('Object extraction arguments must be strings.') src = File(False, self.subdir, src) if src not in self.sources: raise MesonException('Tried to extract unknown source %s.' % src) obj_src.append(src) return ExtractedObjects(self, obj_src, self.is_unity) def extract_all_objects(self): return ExtractedObjects(self, self.sources, self.is_unity) def get_all_link_deps(self): return self.get_transitive_link_deps() def get_transitive_link_deps(self): result = [] for i in self.link_targets: result += i.get_all_link_deps() return result def get_custom_install_dir(self): return self.install_dir def process_kwargs(self, kwargs, environment): super().process_kwargs(kwargs) self.copy_kwargs(kwargs) kwargs.get('modules', []) self.need_install = kwargs.get('install', self.need_install) llist = extract_as_list(kwargs, 'link_with') for linktarget in llist: # Sorry for this hack. Keyword targets are kept in holders # in kwargs. Unpack here without looking at the exact type. if hasattr(linktarget, "held_object"): linktarget = linktarget.held_object if isinstance(linktarget, dependencies.ExternalLibrary): raise MesonException('''An external library was used in link_with keyword argument, which is reserved for libraries built as part of this project. External libraries must be passed using the dependencies keyword argument instead, because they are conceptually "external dependencies", just like those detected with the dependency() function.''') self.link(linktarget) lwhole = extract_as_list(kwargs, 'link_whole') for linktarget in lwhole: self.link_whole(linktarget) c_pchlist, cpp_pchlist, clist, cpplist, cslist, valalist, objclist, objcpplist, fortranlist, rustlist \ = extract_as_list(kwargs, 'c_pch', 'cpp_pch', 'c_args', 'cpp_args', 'cs_args', 'vala_args', 'objc_args', 'objcpp_args', 'fortran_args', 'rust_args') self.add_pch('c', c_pchlist) self.add_pch('cpp', cpp_pchlist) compiler_args = {'c': clist, 'cpp': cpplist, 'cs': cslist, 'vala': valalist, 'objc': objclist, 'objcpp': objcpplist, 'fortran': fortranlist, 'rust': rustlist } for key, value in compiler_args.items(): self.add_compiler_args(key, value) if not isinstance(self, Executable): self.vala_header = kwargs.get('vala_header', self.name + '.h') self.vala_vapi = kwargs.get('vala_vapi', self.name + '.vapi') self.vala_gir = kwargs.get('vala_gir', None) dlist = stringlistify(kwargs.get('d_args', [])) self.add_compiler_args('d', dlist) dfeatures = dict() dfeature_unittest = kwargs.get('d_unittest', False) if dfeature_unittest: dfeatures['unittest'] = dfeature_unittest dfeature_versions = kwargs.get('d_module_versions', None) if dfeature_versions: dfeatures['versions'] = dfeature_versions if 'd_import_dirs' in kwargs: dfeature_import_dirs = extract_as_list(kwargs, 'd_import_dirs', unholder=True) for d in dfeature_import_dirs: if not isinstance(d, IncludeDirs): raise InvalidArguments('Arguments to d_import_dirs must be include_directories.') dfeatures['import_dirs'] = dfeature_import_dirs if dfeatures: self.d_features = dfeatures self.link_args = extract_as_list(kwargs, 'link_args') for i in self.link_args: if not isinstance(i, str): raise InvalidArguments('Link_args arguments must be strings.') for l in self.link_args: if '-Wl,-rpath' in l or l.startswith('-rpath'): mlog.warning('''Please do not define rpath with a linker argument, use install_rpath or build_rpath properties instead. This will become a hard error in a future Meson release.''') self.process_link_depends(kwargs.get('link_depends', []), environment) # Target-specific include dirs must be added BEFORE include dirs from # internal deps (added inside self.add_deps()) to override them. inclist = extract_as_list(kwargs, 'include_directories') self.add_include_dirs(inclist) # Add dependencies (which also have include_directories) deplist = extract_as_list(kwargs, 'dependencies') self.add_deps(deplist) # If an item in this list is False, the output corresponding to # the list index of that item will not be installed self.install_dir = typeslistify(kwargs.get('install_dir', [None]), (str, bool)) main_class = kwargs.get('main_class', '') if not isinstance(main_class, str): raise InvalidArguments('Main class must be a string') self.main_class = main_class if isinstance(self, Executable): self.gui_app = kwargs.get('gui_app', False) if not isinstance(self.gui_app, bool): raise InvalidArguments('Argument gui_app must be boolean.') elif 'gui_app' in kwargs: raise InvalidArguments('Argument gui_app can only be used on executables.') extra_files = extract_as_list(kwargs, 'extra_files') for i in extra_files: assert(isinstance(i, File)) trial = os.path.join(environment.get_source_dir(), i.subdir, i.fname) if not(os.path.isfile(trial)): raise InvalidArguments('Tried to add non-existing extra file %s.' % i) self.extra_files = extra_files self.install_rpath = kwargs.get('install_rpath', '') if not isinstance(self.install_rpath, str): raise InvalidArguments('Install_rpath is not a string.') self.build_rpath = kwargs.get('build_rpath', '') if not isinstance(self.build_rpath, str): raise InvalidArguments('Build_rpath is not a string.') resources = extract_as_list(kwargs, 'resources') for r in resources: if not isinstance(r, str): raise InvalidArguments('Resource argument is not a string.') trial = os.path.join(environment.get_source_dir(), self.subdir, r) if not os.path.isfile(trial): raise InvalidArguments('Tried to add non-existing resource %s.' % r) self.resources = resources if 'name_prefix' in kwargs: name_prefix = kwargs['name_prefix'] if isinstance(name_prefix, list): if name_prefix: raise InvalidArguments('name_prefix array must be empty to signify null.') elif not isinstance(name_prefix, str): raise InvalidArguments('name_prefix must be a string.') self.prefix = name_prefix self.name_prefix_set = True if 'name_suffix' in kwargs: name_suffix = kwargs['name_suffix'] if isinstance(name_suffix, list): if name_suffix: raise InvalidArguments('name_suffix array must be empty to signify null.') else: if not isinstance(name_suffix, str): raise InvalidArguments('name_suffix must be a string.') self.suffix = name_suffix self.name_suffix_set = True if isinstance(self, StaticLibrary): # You can't disable PIC on OS X. The compiler ignores -fno-PIC. # PIC is always on for Windows (all code is position-independent # since library loading is done differently) if for_darwin(self.is_cross, self.environment) or for_windows(self.is_cross, self.environment): self.pic = True elif '-fPIC' in clist + cpplist: mlog.warning("Use the 'pic' kwarg instead of passing -fPIC manually to static library {!r}".format(self.name)) self.pic = True else: self.pic = kwargs.get('pic', False) if not isinstance(self.pic, bool): raise InvalidArguments('Argument pic to static library {!r} must be boolean'.format(self.name)) self.implicit_include_directories = kwargs.get('implicit_include_directories', True) if not isinstance(self.implicit_include_directories, bool): raise InvalidArguments('Implicit_include_directories must be a boolean.') def get_filename(self): return self.filename def get_outputs(self): return self.outputs def get_extra_args(self, language): return self.extra_args.get(language, []) def get_dependencies(self): transitive_deps = [] for t in self.link_targets + self.link_whole_targets: transitive_deps.append(t) if isinstance(t, StaticLibrary): transitive_deps += t.get_dependencies() return transitive_deps def get_source_subdir(self): return self.subdir def get_sources(self): return self.sources def get_objects(self): return self.objects def get_generated_sources(self): return self.generated def should_install(self): return self.need_install def has_pch(self): return len(self.pch) > 0 def get_pch(self, language): try: return self.pch[language] except KeyError: return[] def get_include_dirs(self): return self.include_dirs def add_deps(self, deps): deps = listify(deps) for dep in deps: if hasattr(dep, 'held_object'): dep = dep.held_object if isinstance(dep, dependencies.InternalDependency): # Those parts that are internal. self.process_sourcelist(dep.sources) self.add_include_dirs(dep.include_directories) for l in dep.libraries: self.link(l) # Those parts that are external. extpart = dependencies.InternalDependency('undefined', [], dep.compile_args, dep.link_args, [], [], []) self.external_deps.append(extpart) # Deps of deps. self.add_deps(dep.ext_deps) elif isinstance(dep, dependencies.Dependency): self.external_deps.append(dep) self.process_sourcelist(dep.get_sources()) elif isinstance(dep, BuildTarget): raise InvalidArguments('''Tried to use a build target as a dependency. You probably should put it in link_with instead.''') else: # This is a bit of a hack. We do not want Build to know anything # about the interpreter so we can't import it and use isinstance. # This should be reliable enough. if hasattr(dep, 'project_args_frozen') or hasattr(dep, 'global_args_frozen'): raise InvalidArguments('Tried to use subproject object as a dependency.\n' 'You probably wanted to use a dependency declared in it instead.\n' 'Access it by calling get_variable() on the subproject object.') raise InvalidArguments('Argument is of an unacceptable type {!r}.\nMust be ' 'either an external dependency (returned by find_library() or ' 'dependency()) or an internal dependency (returned by ' 'declare_dependency()).'.format(type(dep).__name__)) def get_external_deps(self): return self.external_deps def link(self, target): for t in listify(target, unholder=True): if not isinstance(t, Target): raise InvalidArguments('{!r} is not a target.'.format(t)) if not t.is_linkable_target(): raise InvalidArguments('Link target {!r} is not linkable.'.format(t)) if isinstance(self, SharedLibrary) and isinstance(t, StaticLibrary) and not t.pic: msg = "Can't link non-PIC static library {!r} into shared library {!r}. ".format(t.name, self.name) msg += "Use the 'pic' option to static_library to build with PIC." raise InvalidArguments(msg) if self.is_cross != t.is_cross: raise InvalidArguments('Tried to mix cross built and native libraries in target {!r}'.format(self.name)) self.link_targets.append(t) def link_whole(self, target): for t in listify(target, unholder=True): if not isinstance(t, StaticLibrary): raise InvalidArguments('{!r} is not a static library.'.format(t)) if isinstance(self, SharedLibrary) and not t.pic: msg = "Can't link non-PIC static library {!r} into shared library {!r}. ".format(t.name, self.name) msg += "Use the 'pic' option to static_library to build with PIC." raise InvalidArguments(msg) if self.is_cross != t.is_cross: raise InvalidArguments('Tried to mix cross built and native libraries in target {!r}'.format(self.name)) self.link_whole_targets.append(t) def add_pch(self, language, pchlist): if not pchlist: return elif len(pchlist) == 1: if not environment.is_header(pchlist[0]): raise InvalidArguments('PCH argument %s is not a header.' % pchlist[0]) elif len(pchlist) == 2: if environment.is_header(pchlist[0]): if not environment.is_source(pchlist[1]): raise InvalidArguments('PCH definition must contain one header and at most one source.') elif environment.is_source(pchlist[0]): if not environment.is_header(pchlist[1]): raise InvalidArguments('PCH definition must contain one header and at most one source.') pchlist = [pchlist[1], pchlist[0]] else: raise InvalidArguments('PCH argument %s is of unknown type.' % pchlist[0]) elif len(pchlist) > 2: raise InvalidArguments('PCH definition may have a maximum of 2 files.') self.pch[language] = pchlist def add_include_dirs(self, args): ids = [] for a in args: # FIXME same hack, forcibly unpack from holder. if hasattr(a, 'held_object'): a = a.held_object if not isinstance(a, IncludeDirs): raise InvalidArguments('Include directory to be added is not an include directory object.') ids.append(a) self.include_dirs += ids def add_compiler_args(self, language, args): args = listify(args) for a in args: if not isinstance(a, (str, File)): raise InvalidArguments('A non-string passed to compiler args.') if language in self.extra_args: self.extra_args[language] += args else: self.extra_args[language] = args def get_aliases(self): return {} def get_langs_used_by_deps(self): ''' Sometimes you want to link to a C++ library that exports C API, which means the linker must link in the C++ stdlib, and we must use a C++ compiler for linking. The same is also applicable for objc/objc++, etc, so we can keep using clike_langs for the priority order. See: https://github.com/mesonbuild/meson/issues/1653 ''' langs = [] # Check if any of the external libraries were written in this language for dep in self.external_deps: if dep.language not in langs: langs.append(dep.language) # Check if any of the internal libraries this target links to were # written in this language for link_target in itertools.chain(self.link_targets, self.link_whole_targets): for language in link_target.compilers: if language not in langs: langs.append(language) return langs def get_clike_dynamic_linker(self): ''' We use the order of languages in `clike_langs` to determine which linker to use in case the target has sources compiled with multiple compilers. All languages other than those in this list have their own linker. Note that Vala outputs C code, so Vala sources can use any linker that can link compiled C. We don't actually need to add an exception for Vala here because of that. ''' # Populate list of all compilers, not just those being used to compile # sources in this target if self.is_cross: all_compilers = self.environment.coredata.cross_compilers else: all_compilers = self.environment.coredata.compilers # Languages used by dependencies dep_langs = self.get_langs_used_by_deps() # Pick a compiler based on the language priority-order for l in clike_langs: if l in self.compilers or l in dep_langs: try: return all_compilers[l] except KeyError: raise MesonException( 'Could not get a dynamic linker for build target {!r}. ' 'Requires a linker for language "{}", but that is not ' 'a project language.'.format(self.name, l)) m = 'Could not get a dynamic linker for build target {!r}' raise AssertionError(m.format(self.name)) def get_using_msvc(self): ''' Check if the dynamic linker is MSVC. Used by Executable, StaticLibrary, and SharedLibrary for deciding when to use MSVC-specific file naming and debug filenames. If at least some code is built with MSVC and the final library is linked with MSVC, we can be sure that some debug info will be generated. We only check the dynamic linker here because the static linker is guaranteed to be of the same type. Interesting cases: 1. The Vala compiler outputs C code to be compiled by whatever C compiler we're using, so all objects will still be created by the MSVC compiler. 2. If the target contains only objects, process_compilers guesses and picks the first compiler that smells right. ''' linker = self.get_clike_dynamic_linker() if linker and linker.get_id() == 'msvc': return True return False def is_linkable_target(self): return False class Generator: def __init__(self, args, kwargs): if len(args) != 1: raise InvalidArguments('Generator requires exactly one positional argument: the executable') exe = args[0] if hasattr(exe, 'held_object'): exe = exe.held_object if not isinstance(exe, (Executable, dependencies.ExternalProgram)): raise InvalidArguments('First generator argument must be an executable.') self.exe = exe self.depfile = None self.capture = False self.process_kwargs(kwargs) def __repr__(self): repr_str = "<{0}: {1}>" return repr_str.format(self.__class__.__name__, self.exe) def get_exe(self): return self.exe def process_kwargs(self, kwargs): if 'arguments' not in kwargs: raise InvalidArguments('Generator must have "arguments" keyword argument.') args = kwargs['arguments'] if isinstance(args, str): args = [args] if not isinstance(args, list): raise InvalidArguments('"Arguments" keyword argument must be a string or a list of strings.') for a in args: if not isinstance(a, str): raise InvalidArguments('A non-string object in "arguments" keyword argument.') self.arglist = args if 'output' not in kwargs: raise InvalidArguments('Generator must have "output" keyword argument.') outputs = listify(kwargs['output']) for rule in outputs: if not isinstance(rule, str): raise InvalidArguments('"output" may only contain strings.') if '@BASENAME@' not in rule and '@PLAINNAME@' not in rule: raise InvalidArguments('Every element of "output" must contain @BASENAME@ or @PLAINNAME@.') if '/' in rule or '\\' in rule: raise InvalidArguments('"outputs" must not contain a directory separator.') if len(outputs) > 1: for o in outputs: if '@OUTPUT@' in o: raise InvalidArguments('Tried to use @OUTPUT@ in a rule with more than one output.') self.outputs = outputs if 'depfile' in kwargs: depfile = kwargs['depfile'] if not isinstance(depfile, str): raise InvalidArguments('Depfile must be a string.') if os.path.basename(depfile) != depfile: raise InvalidArguments('Depfile must be a plain filename without a subdirectory.') self.depfile = depfile if 'capture' in kwargs: capture = kwargs['capture'] if not isinstance(capture, bool): raise InvalidArguments('Capture must be boolean.') self.capture = capture def get_base_outnames(self, inname): plainname = os.path.basename(inname) basename = os.path.splitext(plainname)[0] bases = [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.outputs] return bases def get_dep_outname(self, inname): if self.depfile is None: raise InvalidArguments('Tried to get dep name for rule that does not have dependency file defined.') plainname = os.path.basename(inname) basename = os.path.splitext(plainname)[0] return self.depfile.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) def get_arglist(self, inname): plainname = os.path.basename(inname) basename = os.path.splitext(plainname)[0] return [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.arglist] def is_parent_path(self, parent, trial): relpath = pathlib.PurePath(trial).relative_to(parent) return relpath.parts[0] != '..' # For subdirs we can only go "down". def process_files(self, name, files, state, preserve_path_from=None, extra_args=[]): output = GeneratedList(self, state.subdir, preserve_path_from, extra_args=extra_args) for f in files: if isinstance(f, str): f = File.from_source_file(state.environment.source_dir, state.subdir, f) elif not isinstance(f, File): raise InvalidArguments('{} arguments must be strings or files not {!r}.'.format(name, f)) if preserve_path_from: abs_f = f.absolute_path(state.environment.source_dir, state.environment.build_dir) if not self.is_parent_path(preserve_path_from, abs_f): raise InvalidArguments('When using preserve_path_from, all input files must be in a subdirectory of the given dir.') output.add_file(f, state) return output class GeneratedList: def __init__(self, generator, subdir, preserve_path_from=None, extra_args=[]): if hasattr(generator, 'held_object'): generator = generator.held_object self.generator = generator self.name = self.generator.exe self.subdir = subdir self.infilelist = [] self.outfilelist = [] self.outmap = {} self.extra_depends = [] self.preserve_path_from = preserve_path_from self.extra_args = extra_args def add_preserved_path_segment(self, infile, outfiles, state): result = [] in_abs = infile.absolute_path(state.environment.source_dir, state.environment.build_dir) assert(os.path.isabs(self.preserve_path_from)) rel = os.path.relpath(in_abs, self.preserve_path_from) path_segment = os.path.dirname(rel) for of in outfiles: result.append(os.path.join(path_segment, of)) return result def add_file(self, newfile, state): self.infilelist.append(newfile) outfiles = self.generator.get_base_outnames(newfile.fname) if self.preserve_path_from: outfiles = self.add_preserved_path_segment(newfile, outfiles, state) self.outfilelist += outfiles self.outmap[newfile] = outfiles def get_inputs(self): return self.infilelist def get_outputs(self): return self.outfilelist def get_outputs_for(self, filename): return self.outmap[filename] def get_generator(self): return self.generator def get_extra_args(self): return self.extra_args class Executable(BuildTarget): def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs) # Unless overridden, executables have no suffix or prefix. Except on # Windows and with C#/Mono executables where the suffix is 'exe' if not hasattr(self, 'prefix'): self.prefix = '' if not hasattr(self, 'suffix'): # Executable for Windows or C#/Mono if (for_windows(is_cross, environment) or for_cygwin(is_cross, environment) or 'cs' in self.compilers): self.suffix = 'exe' else: self.suffix = '' self.filename = self.name if self.suffix: self.filename += '.' + self.suffix self.outputs = [self.filename] # The import library this target will generate self.import_filename = None # The import library that Visual Studio would generate (and accept) self.vs_import_filename = None # The import library that GCC would generate (and prefer) self.gcc_import_filename = None # Check for export_dynamic self.export_dynamic = False if kwargs.get('export_dynamic'): if not isinstance(kwargs['export_dynamic'], bool): raise InvalidArguments('"export_dynamic" keyword argument must be a boolean') self.export_dynamic = True if kwargs.get('implib'): self.export_dynamic = True if self.export_dynamic and kwargs.get('implib') is False: raise InvalidArguments('"implib" keyword argument must not be false for if "export_dynamic" is true') # If using export_dynamic, set the import library name if self.export_dynamic: implib_basename = self.name + '.exe' if not isinstance(kwargs.get('implib', False), bool): implib_basename = kwargs['implib'] if for_windows(is_cross, environment) or for_cygwin(is_cross, environment): self.vs_import_filename = '{0}.lib'.format(implib_basename) self.gcc_import_filename = 'lib{0}.a'.format(implib_basename) if self.get_using_msvc(): self.import_filename = self.vs_import_filename else: self.import_filename = self.gcc_import_filename # Only linkwithable if using export_dynamic self.is_linkwithable = self.export_dynamic def type_suffix(self): return "@exe" def check_unknown_kwargs(self, kwargs): self.check_unknown_kwargs_int(kwargs, known_exe_kwargs) def get_import_filename(self): """ The name of the import library that will be outputted by the compiler Returns None if there is no import library required for this platform """ return self.import_filename def get_import_filenameslist(self): if self.import_filename: return [self.vs_import_filename, self.gcc_import_filename] return [] def is_linkable_target(self): return self.is_linkwithable class StaticLibrary(BuildTarget): def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): if 'pic' not in kwargs and 'b_staticpic' in environment.coredata.base_options: kwargs['pic'] = environment.coredata.base_options['b_staticpic'].value super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs) if 'cs' in self.compilers: raise InvalidArguments('Static libraries not supported for C#.') if 'rust' in self.compilers: # If no crate type is specified, or it's the generic lib type, use rlib if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'lib': mlog.debug('Defaulting Rust static library target crate type to rlib') self.rust_crate_type = 'rlib' # Don't let configuration proceed with a non-static crate type elif self.rust_crate_type not in ['rlib', 'staticlib']: raise InvalidArguments('Crate type "{0}" invalid for static libraries; must be "rlib" or "staticlib"'.format(self.rust_crate_type)) # By default a static library is named libfoo.a even on Windows because # MSVC does not have a consistent convention for what static libraries # are called. The MSVC CRT uses libfoo.lib syntax but nothing else uses # it and GCC only looks for static libraries called foo.lib and # libfoo.a. However, we cannot use foo.lib because that's the same as # the import library. Using libfoo.a is ok because people using MSVC # always pass the library filename while linking anyway. if not hasattr(self, 'prefix'): self.prefix = 'lib' if not hasattr(self, 'suffix'): if 'rust' in self.compilers: if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'rlib': # default Rust static library suffix self.suffix = 'rlib' elif self.rust_crate_type == 'staticlib': self.suffix = 'a' else: self.suffix = 'a' self.filename = self.prefix + self.name + '.' + self.suffix self.outputs = [self.filename] def type_suffix(self): return "@sta" def check_unknown_kwargs(self, kwargs): self.check_unknown_kwargs_int(kwargs, known_lib_kwargs) def process_kwargs(self, kwargs, environment): super().process_kwargs(kwargs, environment) if 'rust_crate_type' in kwargs: rust_crate_type = kwargs['rust_crate_type'] if isinstance(rust_crate_type, str): self.rust_crate_type = rust_crate_type else: raise InvalidArguments('Invalid rust_crate_type "{0}": must be a string.'.format(rust_crate_type)) def is_linkable_target(self): return True class SharedLibrary(BuildTarget): def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): self.soversion = None self.ltversion = None self.vs_module_defs = None # The import library this target will generate self.import_filename = None # The import library that Visual Studio would generate (and accept) self.vs_import_filename = None # The import library that GCC would generate (and prefer) self.gcc_import_filename = None super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs) if 'rust' in self.compilers: # If no crate type is specified, or it's the generic lib type, use dylib if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'lib': mlog.debug('Defaulting Rust dynamic library target crate type to "dylib"') self.rust_crate_type = 'dylib' # Don't let configuration proceed with a non-dynamic crate type elif self.rust_crate_type not in ['dylib', 'cdylib']: raise InvalidArguments('Crate type "{0}" invalid for dynamic libraries; must be "dylib" or "cdylib"'.format(self.rust_crate_type)) if not hasattr(self, 'prefix'): self.prefix = None if not hasattr(self, 'suffix'): self.suffix = None self.basic_filename_tpl = '{0.prefix}{0.name}.{0.suffix}' self.determine_filenames(is_cross, environment) def determine_filenames(self, is_cross, env): """ See https://github.com/mesonbuild/meson/pull/417 for details. First we determine the filename template (self.filename_tpl), then we set the output filename (self.filename). The template is needed while creating aliases (self.get_aliases), which are needed while generating .so shared libraries for Linux. Besides this, there's also the import library name, which is only used on Windows since on that platform the linker uses a separate library called the "import library" during linking instead of the shared library (DLL). The toolchain will output an import library in one of two formats: GCC or Visual Studio. When we're building with Visual Studio, the import library that will be generated by the toolchain is self.vs_import_filename, and with MinGW/GCC, it's self.gcc_import_filename. self.import_filename will always contain the import library name this target will generate. """ prefix = '' suffix = '' self.filename_tpl = self.basic_filename_tpl # If the user already provided the prefix and suffix to us, we don't # need to do any filename suffix/prefix detection. # NOTE: manual prefix/suffix override is currently only tested for C/C++ if self.prefix is not None and self.suffix is not None: pass # C# and Mono elif 'cs' in self.compilers: prefix = '' suffix = 'dll' self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' # C, C++, Swift, Vala # Only Windows uses a separate import library for linking # For all other targets/platforms import_filename stays None elif for_windows(is_cross, env): suffix = 'dll' self.vs_import_filename = '{0}.lib'.format(self.name) self.gcc_import_filename = 'lib{0}.dll.a'.format(self.name) if self.get_using_msvc(): # Shared library is of the form foo.dll prefix = '' # Import library is called foo.lib self.import_filename = self.vs_import_filename # Assume GCC-compatible naming else: # Shared library is of the form libfoo.dll prefix = 'lib' # Import library is called libfoo.dll.a self.import_filename = self.gcc_import_filename # Shared library has the soversion if it is defined if self.soversion: self.filename_tpl = '{0.prefix}{0.name}-{0.soversion}.{0.suffix}' else: self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' elif for_cygwin(is_cross, env): suffix = 'dll' self.gcc_import_filename = 'lib{0}.dll.a'.format(self.name) # Shared library is of the form cygfoo.dll # (ld --dll-search-prefix=cyg is the default) prefix = 'cyg' # Import library is called libfoo.dll.a self.import_filename = self.gcc_import_filename if self.soversion: self.filename_tpl = '{0.prefix}{0.name}-{0.soversion}.{0.suffix}' else: self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' elif for_darwin(is_cross, env): prefix = 'lib' suffix = 'dylib' # On macOS, the filename can only contain the major version if self.soversion: # libfoo.X.dylib self.filename_tpl = '{0.prefix}{0.name}.{0.soversion}.{0.suffix}' else: # libfoo.dylib self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' elif for_android(is_cross, env): prefix = 'lib' suffix = 'so' # Android doesn't support shared_library versioning self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' else: prefix = 'lib' suffix = 'so' if self.ltversion: # libfoo.so.X[.Y[.Z]] (.Y and .Z are optional) self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}.{0.ltversion}' elif self.soversion: # libfoo.so.X self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}.{0.soversion}' else: # No versioning, libfoo.so self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' if self.prefix is None: self.prefix = prefix if self.suffix is None: self.suffix = suffix self.filename = self.filename_tpl.format(self) self.outputs = [self.filename] def process_kwargs(self, kwargs, environment): super().process_kwargs(kwargs, environment) if not for_android(self.is_cross, self.environment): supports_versioning = True else: supports_versioning = False if supports_versioning: # Shared library version if 'version' in kwargs: self.ltversion = kwargs['version'] if not isinstance(self.ltversion, str): raise InvalidArguments('Shared library version needs to be a string, not ' + type(self.ltversion).__name__) if not re.fullmatch(r'[0-9]+(\.[0-9]+){0,2}', self.ltversion): raise InvalidArguments('Invalid Shared library version "{0}". Must be of the form X.Y.Z where all three are numbers. Y and Z are optional.'.format(self.ltversion)) # Try to extract/deduce the soversion if 'soversion' in kwargs: self.soversion = kwargs['soversion'] if isinstance(self.soversion, int): self.soversion = str(self.soversion) if not isinstance(self.soversion, str): raise InvalidArguments('Shared library soversion is not a string or integer.') elif self.ltversion: # library version is defined, get the soversion from that # We replicate what Autotools does here and take the first # number of the version by default. self.soversion = self.ltversion.split('.')[0] # Visual Studio module-definitions file if 'vs_module_defs' in kwargs: path = kwargs['vs_module_defs'] if hasattr(path, 'held_object'): path = path.held_object if isinstance(path, str): if os.path.isabs(path): self.vs_module_defs = File.from_absolute_file(path) else: self.vs_module_defs = File.from_source_file(environment.source_dir, self.subdir, path) self.link_depends.append(self.vs_module_defs) elif isinstance(path, File): # When passing a generated file. self.vs_module_defs = path self.link_depends.append(path) elif hasattr(path, 'get_filename'): # When passing output of a Custom Target path = File.from_built_file(path.subdir, path.get_filename()) self.vs_module_defs = path self.link_depends.append(path) else: raise InvalidArguments( 'Shared library vs_module_defs must be either a string, ' 'a file object or a Custom Target') if 'rust_crate_type' in kwargs: rust_crate_type = kwargs['rust_crate_type'] if isinstance(rust_crate_type, str): self.rust_crate_type = rust_crate_type else: raise InvalidArguments('Invalid rust_crate_type "{0}": must be a string.'.format(rust_crate_type)) def check_unknown_kwargs(self, kwargs): self.check_unknown_kwargs_int(kwargs, known_lib_kwargs) def get_import_filename(self): """ The name of the import library that will be outputted by the compiler Returns None if there is no import library required for this platform """ return self.import_filename def get_import_filenameslist(self): if self.import_filename: return [self.vs_import_filename, self.gcc_import_filename] return [] def get_all_link_deps(self): return [self] + self.get_transitive_link_deps() def get_aliases(self): """ If the versioned library name is libfoo.so.0.100.0, aliases are: * libfoo.so.0 (soversion) -> libfoo.so.0.100.0 * libfoo.so (unversioned; for linking) -> libfoo.so.0 Same for dylib: * libfoo.dylib (unversioned; for linking) -> libfoo.0.dylib """ aliases = {} # Aliases are only useful with .so and .dylib libraries. Also if # there's no self.soversion (no versioning), we don't need aliases. if self.suffix not in ('so', 'dylib') or not self.soversion: return {} # With .so libraries, the minor and micro versions are also in the # filename. If ltversion != soversion we create an soversion alias: # libfoo.so.0 -> libfoo.so.0.100.0 # Where libfoo.so.0.100.0 is the actual library if self.suffix == 'so' and self.ltversion and self.ltversion != self.soversion: alias_tpl = self.filename_tpl.replace('ltversion', 'soversion') ltversion_filename = alias_tpl.format(self) aliases[ltversion_filename] = self.filename # libfoo.so.0/libfoo.0.dylib is the actual library else: ltversion_filename = self.filename # Unversioned alias: # libfoo.so -> libfoo.so.0 # libfoo.dylib -> libfoo.0.dylib aliases[self.basic_filename_tpl.format(self)] = ltversion_filename return aliases def type_suffix(self): return "@sha" def is_linkable_target(self): return True # A shared library that is meant to be used with dlopen rather than linking # into something else. class SharedModule(SharedLibrary): def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): if 'version' in kwargs: raise MesonException('Shared modules must not specify the version kwarg.') if 'soversion' in kwargs: raise MesonException('Shared modules must not specify the soversion kwarg.') super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs) self.import_filename = None class CustomTarget(Target): known_kwargs = {'input': True, 'output': True, 'command': True, 'capture': False, 'install': True, 'install_dir': True, 'build_always': True, 'depends': True, 'depend_files': True, 'depfile': True, 'build_by_default': True, 'override_options': True, } def __init__(self, name, subdir, subproject, kwargs, absolute_paths=False): super().__init__(name, subdir, subproject, False) self.dependencies = [] self.extra_depends = [] self.depend_files = [] # Files that this target depends on but are not on the command line. self.depfile = None self.process_kwargs(kwargs) self.extra_files = [] # Whether to use absolute paths for all files on the commandline self.absolute_paths = absolute_paths unknowns = [] for k in kwargs: if k not in CustomTarget.known_kwargs: unknowns.append(k) if len(unknowns) > 0: mlog.warning('Unknown keyword arguments in target %s: %s' % (self.name, ', '.join(unknowns))) def __lt__(self, other): return self.get_id() < other.get_id() def __repr__(self): repr_str = "<{0} {1}: {2}>" return repr_str.format(self.__class__.__name__, self.get_id(), self.command) def get_id(self): return self.name + self.type_suffix() def get_target_dependencies(self): deps = self.dependencies[:] deps += self.extra_depends for c in self.sources: if hasattr(c, 'held_object'): c = c.held_object if isinstance(c, (BuildTarget, CustomTarget)): deps.append(c) return deps def get_transitive_build_target_deps(self): ''' Recursively fetch the build targets that this custom target depends on, whether through `command:`, `depends:`, or `sources:` The recursion is only performed on custom targets. This is useful for setting PATH on Windows for finding required DLLs. F.ex, if you have a python script that loads a C module that links to other DLLs in your project. ''' bdeps = set() deps = self.get_target_dependencies() for d in deps: if isinstance(d, BuildTarget): bdeps.add(d) elif isinstance(d, CustomTarget): bdeps.update(d.get_transitive_build_target_deps()) return bdeps def flatten_command(self, cmd): cmd = listify(cmd, unholder=True) final_cmd = [] for c in cmd: if isinstance(c, str): final_cmd.append(c) elif isinstance(c, File): self.depend_files.append(c) final_cmd.append(c) elif isinstance(c, dependencies.ExternalProgram): if not c.found(): m = 'Tried to use not-found external program {!r} in "command"' raise InvalidArguments(m.format(c.name)) self.depend_files.append(File.from_absolute_file(c.get_path())) final_cmd += c.get_command() elif isinstance(c, (BuildTarget, CustomTarget)): self.dependencies.append(c) final_cmd.append(c) elif isinstance(c, list): final_cmd += self.flatten_command(c) else: raise InvalidArguments('Argument {!r} in "command" is invalid'.format(c)) return final_cmd def process_kwargs(self, kwargs): super().process_kwargs(kwargs) self.sources = extract_as_list(kwargs, 'input', unholder=True) if 'output' not in kwargs: raise InvalidArguments('Missing keyword argument "output".') self.outputs = listify(kwargs['output']) # This will substitute values from the input into output and return it. inputs = get_sources_string_names(self.sources) values = get_filenames_templates_dict(inputs, []) for i in self.outputs: if not(isinstance(i, str)): raise InvalidArguments('Output argument not a string.') if i == '': raise InvalidArguments('Output must not be empty.') if i.strip() == '': raise InvalidArguments('Output must not consist only of whitespace.') if '/' in i: raise InvalidArguments('Output must not contain a path segment.') if '@INPUT@' in i or '@INPUT0@' in i: m = 'Output cannot contain @INPUT@ or @INPUT0@, did you ' \ 'mean @PLAINNAME@ or @BASENAME@?' raise InvalidArguments(m) # We already check this during substitution, but the error message # will be unclear/confusing, so check it here. if len(inputs) != 1 and ('@PLAINNAME@' in i or '@BASENAME@' in i): m = "Output cannot contain @PLAINNAME@ or @BASENAME@ when " \ "there is more than one input (we can't know which to use)" raise InvalidArguments(m) self.outputs = substitute_values(self.outputs, values) self.capture = kwargs.get('capture', False) if self.capture and len(self.outputs) != 1: raise InvalidArguments('Capturing can only output to a single file.') if 'command' not in kwargs: raise InvalidArguments('Missing keyword argument "command".') if 'depfile' in kwargs: depfile = kwargs['depfile'] if not isinstance(depfile, str): raise InvalidArguments('Depfile must be a string.') if os.path.basename(depfile) != depfile: raise InvalidArguments('Depfile must be a plain filename without a subdirectory.') self.depfile = depfile self.command = self.flatten_command(kwargs['command']) if self.capture: for c in self.command: if isinstance(c, str) and '@OUTPUT@' in c: raise InvalidArguments('@OUTPUT@ is not allowed when capturing output.') if 'install' in kwargs: self.install = kwargs['install'] if not isinstance(self.install, bool): raise InvalidArguments('"install" must be boolean.') if self.install: if 'install_dir' not in kwargs: raise InvalidArguments('"install_dir" must be specified ' 'when installing a target') # If an item in this list is False, the output corresponding to # the list index of that item will not be installed self.install_dir = typeslistify(kwargs['install_dir'], (str, bool)) else: self.install = False self.install_dir = [None] self.build_always = kwargs.get('build_always', False) if not isinstance(self.build_always, bool): raise InvalidArguments('Argument build_always must be a boolean.') extra_deps, depend_files = extract_as_list(kwargs, 'depends', 'depend_files', pop = False) for ed in extra_deps: while hasattr(ed, 'held_object'): ed = ed.held_object if not isinstance(ed, (CustomTarget, BuildTarget)): raise InvalidArguments('Can only depend on toplevel targets: custom_target or build_target (executable or a library)') self.extra_depends.append(ed) for i in depend_files: if isinstance(i, (File, str)): self.depend_files.append(i) else: mlog.debug(i) raise InvalidArguments('Unknown type {!r} in depend_files.'.format(type(i).__name__)) def get_dependencies(self): return self.dependencies def should_install(self): return self.install def get_custom_install_dir(self): return self.install_dir def get_outputs(self): return self.outputs def get_filename(self): return self.outputs[0] def get_sources(self): return self.sources def get_generated_lists(self): genlists = [] for c in self.sources: if hasattr(c, 'held_object'): c = c.held_object if isinstance(c, GeneratedList): genlists.append(c) return genlists def get_generated_sources(self): return self.get_generated_lists() def type_suffix(self): return "@cus" def __getitem__(self, index): return CustomTargetIndex(self, self.outputs[index]) def __setitem__(self, index, value): raise NotImplementedError def __delitem__(self, index): raise NotImplementedError class RunTarget(Target): def __init__(self, name, command, args, dependencies, subdir, subproject): super().__init__(name, subdir, subproject, False) self.command = command self.args = args self.dependencies = dependencies def __lt__(self, other): return self.get_id() < other.get_id() def __repr__(self): repr_str = "<{0} {1}: {2}>" return repr_str.format(self.__class__.__name__, self.get_id(), self.command) def get_dependencies(self): return self.dependencies def get_generated_sources(self): return [] def get_sources(self): return [] def should_install(self): return False def get_filename(self): return self.name def type_suffix(self): return "@run" class Jar(BuildTarget): def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs) for s in self.sources: if not s.endswith('.java'): raise InvalidArguments('Jar source %s is not a java file.' % s) self.filename = self.name + '.jar' self.outputs = [self.filename] self.java_args = kwargs.get('java_args', []) def get_main_class(self): return self.main_class def type_suffix(self): return "@jar" def get_java_args(self): return self.java_args def validate_cross_install(self, environment): # All jar targets are installable. pass class CustomTargetIndex: """A special opaque object returned by indexing a CustomTarget. This object exists in meson, but acts as a proxy in the backends, making targets depend on the CustomTarget it's derived from, but only adding one source file to the sources. """ def __init__(self, target, output): self.target = target self.output = output def __repr__(self): return ''.format( self.target, self.target.get_outputs().index(self.output)) def get_outputs(self): return [self.output] def get_subdir(self): return self.target.get_subdir() class ConfigureFile: def __init__(self, subdir, sourcename, targetname, configuration_data): self.subdir = subdir self.sourcename = sourcename self.targetname = targetname self.configuration_data = configuration_data def __repr__(self): repr_str = "<{0}: {1} -> {2}>" src = os.path.join(self.subdir, self.sourcename) dst = os.path.join(self.subdir, self.targetname) return repr_str.format(self.__class__.__name__, src, dst) def get_configuration_data(self): return self.configuration_data def get_subdir(self): return self.subdir def get_source_name(self): return self.sourcename def get_target_name(self): return self.targetname class ConfigurationData: def __init__(self): super().__init__() self.values = {} def __repr__(self): return repr(self.values) def __contains__(self, value): return value in self.values def get(self, name): return self.values[name] # (val, desc) def keys(self): return self.values.keys() # A bit poorly named, but this represents plain data files to copy # during install. class Data: def __init__(self, sources, install_dir, install_mode=None): self.sources = sources self.install_dir = install_dir self.install_mode = install_mode self.sources = listify(self.sources) for s in self.sources: assert(isinstance(s, File)) class RunScript(dict): def __init__(self, script, args): super().__init__() assert(isinstance(script, list)) assert(isinstance(args, list)) self['exe'] = script self['args'] = args class TestSetup: def __init__(self, *, exe_wrapper=None, gdb=None, timeout_multiplier=None, env=None): self.exe_wrapper = exe_wrapper self.gdb = gdb self.timeout_multiplier = timeout_multiplier self.env = env def get_sources_string_names(sources): ''' For the specified list of @sources which can be strings, Files, or targets, get all the output basenames. ''' names = [] for s in sources: if hasattr(s, 'held_object'): s = s.held_object if isinstance(s, str): names.append(s) elif isinstance(s, (BuildTarget, CustomTarget, GeneratedList)): names += s.get_outputs() elif isinstance(s, File): names.append(s.fname) else: raise AssertionError('Unknown source type: {!r}'.format(s)) return names def load(build_dir): filename = os.path.join(build_dir, 'meson-private', 'build.dat') load_fail_msg = 'Build data file {!r} is corrupted. Try with a fresh build tree.'.format(filename) nonexisting_fail_msg = 'No such build data file as "{!r}".'.format(filename) try: with open(filename, 'rb') as f: obj = pickle.load(f) except FileNotFoundError: raise MesonException(nonexisting_fail_msg) except pickle.UnpicklingError: raise MesonException(load_fail_msg) if not isinstance(obj, Build): raise MesonException(load_fail_msg) return obj def save(obj, filename): with open(filename, 'wb') as f: pickle.dump(obj, f) meson-0.45.1/mesonbuild/mlog.py0000644000175000017500000000740013254550710017770 0ustar jpakkanejpakkane00000000000000# Copyright 2013-2014 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import sys, os, platform, io """This is (mostly) a standalone module used to write logging information about Meson runs. Some output goes to screen, some to logging dir and some goes to both.""" if platform.system().lower() == 'windows': colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('ANSICON') else: colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM') != 'dumb' log_dir = None log_file = None log_fname = 'meson-log.txt' def initialize(logdir): global log_dir, log_file log_dir = logdir log_file = open(os.path.join(logdir, log_fname), 'w', encoding='utf8') def shutdown(): global log_file if log_file is not None: exception_around_goer = log_file log_file = None exception_around_goer.close() class AnsiDecorator: plain_code = "\033[0m" def __init__(self, text, code): self.text = text self.code = code def get_text(self, with_codes): if with_codes: return self.code + self.text + AnsiDecorator.plain_code return self.text def bold(text): return AnsiDecorator(text, "\033[1m") def red(text): return AnsiDecorator(text, "\033[1;31m") def green(text): return AnsiDecorator(text, "\033[1;32m") def yellow(text): return AnsiDecorator(text, "\033[1;33m") def cyan(text): return AnsiDecorator(text, "\033[1;36m") def process_markup(args, keep): arr = [] for arg in args: if isinstance(arg, str): arr.append(arg) elif isinstance(arg, AnsiDecorator): arr.append(arg.get_text(keep)) else: arr.append(str(arg)) return arr def force_print(*args, **kwargs): # _Something_ is going to get printed. try: print(*args, **kwargs) except UnicodeEncodeError: iostr = io.StringIO() kwargs['file'] = iostr print(*args, **kwargs) cleaned = iostr.getvalue().encode('ascii', 'replace').decode('ascii') print(cleaned) def debug(*args, **kwargs): arr = process_markup(args, False) if log_file is not None: print(*arr, file=log_file, **kwargs) # Log file never gets ANSI codes. log_file.flush() def log(*args, **kwargs): arr = process_markup(args, False) if log_file is not None: print(*arr, file=log_file, **kwargs) # Log file never gets ANSI codes. log_file.flush() if colorize_console: arr = process_markup(args, True) force_print(*arr, **kwargs) def warning(*args, **kwargs): from . import environment args = (yellow('WARNING:'),) + args if 'location' in kwargs: location = kwargs['location'] del kwargs['location'] location = '{}:{}:'.format(os.path.join(location.subdir, environment.build_filename), location.lineno) args = (location,) + args log(*args, **kwargs) # Format a list for logging purposes as a string. It separates # all but the last item with commas, and the last with 'and'. def format_list(list): l = len(list) if l > 2: return ' and '.join([', '.join(list[:-1]), list[-1]]) elif l == 2: return ' and '.join(list) elif l == 1: return list[0] else: return '' meson-0.45.1/mesonbuild/__init__.py0000644000175000017500000000000012650745767020577 0ustar jpakkanejpakkane00000000000000meson-0.45.1/mesonbuild/coredata.py0000644000175000017500000005004713254550710020621 0ustar jpakkanejpakkane00000000000000# Copyright 2012-2018 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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 . import mlog import pickle, os, uuid import sys from pathlib import PurePath from collections import OrderedDict from .mesonlib import MesonException from .mesonlib import default_libdir, default_libexecdir, default_prefix import ast version = '0.45.1' backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'xcode'] default_yielding = False class UserOption: def __init__(self, name, description, choices, yielding): super().__init__() self.name = name self.choices = choices self.description = description if yielding is None: yielding = default_yielding if not isinstance(yielding, bool): raise MesonException('Value of "yielding" must be a boolean.') self.yielding = yielding # Check that the input is a valid value and return the # "cleaned" or "native" version. For example the Boolean # option could take the string "true" and return True. def validate_value(self, value): raise RuntimeError('Derived option class did not override validate_value.') class UserStringOption(UserOption): def __init__(self, name, description, value, choices=None, yielding=None): super().__init__(name, description, choices, yielding) self.set_value(value) def validate(self, value): if not isinstance(value, str): raise MesonException('Value "%s" for string option "%s" is not a string.' % (str(value), self.name)) def set_value(self, newvalue): self.validate(newvalue) self.value = newvalue def validate_value(self, value): self.validate(value) return value class UserBooleanOption(UserOption): def __init__(self, name, description, value, yielding=None): super().__init__(name, description, [True, False], yielding) self.set_value(value) def tobool(self, thing): if isinstance(thing, bool): return thing if thing.lower() == 'true': return True if thing.lower() == 'false': return False raise MesonException('Value %s is not boolean (true or false).' % thing) def set_value(self, newvalue): self.value = self.tobool(newvalue) def __bool__(self): return self.value def validate_value(self, value): return self.tobool(value) class UserIntegerOption(UserOption): def __init__(self, name, description, min_value, max_value, value, yielding=None): super().__init__(name, description, [True, False], yielding) self.min_value = min_value self.max_value = max_value self.set_value(value) c = [] if min_value is not None: c.append('>=' + str(min_value)) if max_value is not None: c.append('<=' + str(max_value)) self.choices = ', '.join(c) def set_value(self, newvalue): if isinstance(newvalue, str): newvalue = self.toint(newvalue) if not isinstance(newvalue, int): raise MesonException('New value for integer option is not an integer.') if self.min_value is not None and newvalue < self.min_value: raise MesonException('New value %d is less than minimum value %d.' % (newvalue, self.min_value)) if self.max_value is not None and newvalue > self.max_value: raise MesonException('New value %d is more than maximum value %d.' % (newvalue, self.max_value)) self.value = newvalue def toint(self, valuestring): try: return int(valuestring) except: raise MesonException('Value string "%s" is not convertable to an integer.' % valuestring) def validate_value(self, value): return self.toint(value) class UserComboOption(UserOption): def __init__(self, name, description, choices, value, yielding=None): super().__init__(name, description, choices, yielding) if not isinstance(self.choices, list): raise MesonException('Combo choices must be an array.') for i in self.choices: if not isinstance(i, str): raise MesonException('Combo choice elements must be strings.') self.set_value(value) def set_value(self, newvalue): if newvalue not in self.choices: optionsstring = ', '.join(['"%s"' % (item,) for item in self.choices]) raise MesonException('Value "%s" for combo option "%s" is not one of the choices. Possible choices are: %s.' % (newvalue, self.name, optionsstring)) self.value = newvalue def validate_value(self, value): if value not in self.choices: raise MesonException('Value %s not one of accepted values.' % value) return value class UserArrayOption(UserOption): def __init__(self, name, description, value, **kwargs): super().__init__(name, description, kwargs.get('choices', []), yielding=kwargs.get('yielding', None)) self.set_value(value, user_input=False) def validate(self, value, user_input): # User input is for options defined on the command line (via -D # options). Users can put their input in as a comma separated # string, but for defining options in meson_options.txt the format # should match that of a combo if not user_input: if isinstance(value, str): if not value.startswith('['): raise MesonException('Valuestring does not define an array: ' + value) newvalue = ast.literal_eval(value) else: newvalue = value else: assert isinstance(value, str) if value.startswith('['): newvalue = ast.literal_eval(value) else: newvalue = [v.strip() for v in value.split(',')] if len(set(newvalue)) != len(newvalue): mlog.log(mlog.red('DEPRECATION:'), '''Duplicated values in an array type is deprecated. This will become a hard error in the future.''') if not isinstance(newvalue, list): raise MesonException('"{0}" should be a string array, but it is not'.format(str(newvalue))) for i in newvalue: if not isinstance(i, str): raise MesonException('String array element "{0}" is not a string.'.format(str(newvalue))) if self.choices: bad = [x for x in newvalue if x not in self.choices] if bad: raise MesonException('Options "{}" are not in allowed choices: "{}"'.format( ', '.join(bad), ', '.join(self.choices))) return newvalue def set_value(self, newvalue, user_input=True): self.value = self.validate(newvalue, user_input) def validate_value(self, value): self.validate(value) return value # This class contains all data that must persist over multiple # invocations of Meson. It is roughly the same thing as # cmakecache. class CoreData: def __init__(self, options): self.guid = str(uuid.uuid4()).upper() self.test_guid = str(uuid.uuid4()).upper() self.regen_guid = str(uuid.uuid4()).upper() self.target_guids = {} self.version = version self.init_builtins(options) self.init_backend_options(self.builtins['backend'].value) self.user_options = {} self.compiler_options = {} self.base_options = {} # These external_*args, are set via env vars CFLAGS, LDFLAGS, etc # but only when not cross-compiling. self.external_preprocess_args = {} # CPPFLAGS only self.external_args = {} # CPPFLAGS + CFLAGS self.external_link_args = {} # CFLAGS + LDFLAGS (with MSVC: only LDFLAGS) self.cross_file = self.__load_cross_file(options.cross_file) self.wrap_mode = options.wrap_mode self.compilers = OrderedDict() self.cross_compilers = OrderedDict() self.deps = OrderedDict() self.modules = {} # Only to print a warning if it changes between Meson invocations. self.pkgconf_envvar = os.environ.get('PKG_CONFIG_PATH', '') @staticmethod def __load_cross_file(filename): """Try to load the cross file. If the filename is None return None. If the filename is an absolute (after resolving variables and ~), return that absolute path. Next, check if the file is relative to the current source dir. If the path still isn't resolved do the following: Windows: - Error *: - $XDG_DATA_HOME/meson/cross (or ~/.local/share/meson/cross if undefined) - $XDG_DATA_DIRS/meson/cross (or /usr/local/share/meson/cross:/usr/share/meson/cross if undefined) - Error Non-Windows follows the Linux path and will honor XDG_* if set. This simplifies the implementation somewhat. """ if filename is None: return None filename = os.path.expanduser(os.path.expandvars(filename)) if os.path.isabs(filename): return filename path_to_try = os.path.abspath(filename) if os.path.exists(path_to_try): return path_to_try if sys.platform != 'win32': paths = [ os.environ.get('XDG_DATA_HOME', os.path.expanduser('~/.local/share')), ] + os.environ.get('XDG_DATA_DIRS', '/usr/local/share:/usr/share').split(':') for path in paths: path_to_try = os.path.join(path, 'meson', 'cross', filename) if os.path.exists(path_to_try): return path_to_try raise MesonException('Cannot find specified cross file: ' + filename) raise MesonException('Cannot find specified cross file: ' + filename) def sanitize_prefix(self, prefix): if not os.path.isabs(prefix): raise MesonException('prefix value {!r} must be an absolute path' ''.format(prefix)) if prefix.endswith('/') or prefix.endswith('\\'): # On Windows we need to preserve the trailing slash if the # string is of type 'C:\' because 'C:' is not an absolute path. if len(prefix) == 3 and prefix[1] == ':': pass # If prefix is a single character, preserve it since it is # the root directory. elif len(prefix) == 1: pass else: prefix = prefix[:-1] return prefix def sanitize_dir_option_value(self, prefix, option, value): ''' If the option is an installation directory option and the value is an absolute path, check that it resides within prefix and return the value as a path relative to the prefix. This way everyone can do f.ex, get_option('libdir') and be sure to get the library directory relative to prefix. ''' if option.endswith('dir') and os.path.isabs(value) and \ option not in builtin_dir_noprefix_options: # Value must be a subdir of the prefix # commonpath will always return a path in the native format, so we # must use pathlib.PurePath to do the same conversion before # comparing. if os.path.commonpath([value, prefix]) != str(PurePath(prefix)): m = 'The value of the {!r} option is {!r} which must be a ' \ 'subdir of the prefix {!r}.\nNote that if you pass a ' \ 'relative path, it is assumed to be a subdir of prefix.' raise MesonException(m.format(option, value, prefix)) # Convert path to be relative to prefix skip = len(prefix) + 1 value = value[skip:] return value def init_builtins(self, options): self.builtins = {} # Sanitize prefix options.prefix = self.sanitize_prefix(options.prefix) # Initialize other builtin options for key in get_builtin_options(): if hasattr(options, key): value = getattr(options, key) value = self.sanitize_dir_option_value(options.prefix, key, value) setattr(options, key, value) else: value = get_builtin_option_default(key, prefix=options.prefix) args = [key] + builtin_options[key][1:-1] + [value] self.builtins[key] = builtin_options[key][0](*args) def init_backend_options(self, backend_name): self.backend_options = {} if backend_name == 'ninja': self.backend_options['backend_max_links'] = UserIntegerOption('backend_max_links', 'Maximum number of linker processes to run or 0 for no limit', 0, None, 0) def get_builtin_option(self, optname): if optname in self.builtins: return self.builtins[optname].value raise RuntimeError('Tried to get unknown builtin option %s.' % optname) def set_builtin_option(self, optname, value): if optname == 'prefix': value = self.sanitize_prefix(value) elif optname in self.builtins: prefix = self.builtins['prefix'].value value = self.sanitize_dir_option_value(prefix, optname, value) else: raise RuntimeError('Tried to set unknown builtin option %s.' % optname) self.builtins[optname].set_value(value) def validate_option_value(self, option_name, override_value): for opts in (self.builtins, self.base_options, self.compiler_options, self.user_options): if option_name in opts: opt = opts[option_name] return opt.validate_value(override_value) raise MesonException('Tried to validate unknown option %s.' % option_name) def load(build_dir): filename = os.path.join(build_dir, 'meson-private', 'coredata.dat') load_fail_msg = 'Coredata file {!r} is corrupted. Try with a fresh build tree.'.format(filename) try: with open(filename, 'rb') as f: obj = pickle.load(f) except pickle.UnpicklingError: raise MesonException(load_fail_msg) if not isinstance(obj, CoreData): raise MesonException(load_fail_msg) if obj.version != version: raise MesonException('Build directory has been generated with Meson version %s, which is incompatible with current version %s.\nPlease delete this build directory AND create a new one.' % (obj.version, version)) return obj def save(obj, build_dir): filename = os.path.join(build_dir, 'meson-private', 'coredata.dat') if obj.version != version: raise MesonException('Fatal version mismatch corruption.') with open(filename, 'wb') as f: pickle.dump(obj, f) def get_builtin_options(): return list(builtin_options.keys()) def is_builtin_option(optname): return optname in get_builtin_options() def get_builtin_option_choices(optname): if is_builtin_option(optname): if builtin_options[optname][0] == UserStringOption: return None elif builtin_options[optname][0] == UserBooleanOption: return [True, False] else: return builtin_options[optname][2] else: raise RuntimeError('Tried to get the supported values for an unknown builtin option \'%s\'.' % optname) def get_builtin_option_description(optname): if is_builtin_option(optname): return builtin_options[optname][1] else: raise RuntimeError('Tried to get the description for an unknown builtin option \'%s\'.' % optname) def get_builtin_option_default(optname, prefix='', noneIfSuppress=False): if is_builtin_option(optname): o = builtin_options[optname] if o[0] == UserComboOption: return o[3] if optname in builtin_dir_noprefix_options: if noneIfSuppress: # Return None if argparse defaulting should be suppressed for # this option (so we can determine the default later based on # prefix) return None elif prefix in builtin_dir_noprefix_options[optname]: return builtin_dir_noprefix_options[optname][prefix] return o[2] else: raise RuntimeError('Tried to get the default value for an unknown builtin option \'%s\'.' % optname) builtin_options = { 'buildtype': [UserComboOption, 'Build type to use.', ['plain', 'debug', 'debugoptimized', 'release', 'minsize'], 'debug'], 'strip': [UserBooleanOption, 'Strip targets on install.', False], 'unity': [UserComboOption, 'Unity build.', ['on', 'off', 'subprojects'], 'off'], 'prefix': [UserStringOption, 'Installation prefix.', default_prefix()], 'libdir': [UserStringOption, 'Library directory.', default_libdir()], 'libexecdir': [UserStringOption, 'Library executable directory.', default_libexecdir()], 'bindir': [UserStringOption, 'Executable directory.', 'bin'], 'sbindir': [UserStringOption, 'System executable directory.', 'sbin'], 'includedir': [UserStringOption, 'Header file directory.', 'include'], 'datadir': [UserStringOption, 'Data file directory.', 'share'], 'mandir': [UserStringOption, 'Manual page directory.', 'share/man'], 'infodir': [UserStringOption, 'Info page directory.', 'share/info'], 'localedir': [UserStringOption, 'Locale data directory.', 'share/locale'], 'sysconfdir': [UserStringOption, 'Sysconf data directory.', 'etc'], 'localstatedir': [UserStringOption, 'Localstate data directory.', 'var'], 'sharedstatedir': [UserStringOption, 'Architecture-independent data directory.', 'com'], 'werror': [UserBooleanOption, 'Treat warnings as errors.', False], 'warning_level': [UserComboOption, 'Compiler warning level to use.', ['1', '2', '3'], '1'], 'layout': [UserComboOption, 'Build directory layout.', ['mirror', 'flat'], 'mirror'], 'default_library': [UserComboOption, 'Default library type.', ['shared', 'static'], 'shared'], 'backend': [UserComboOption, 'Backend to use.', backendlist, 'ninja'], 'stdsplit': [UserBooleanOption, 'Split stdout and stderr in test logs.', True], 'errorlogs': [UserBooleanOption, "Whether to print the logs from failing tests.", True], } # Special prefix-dependent defaults for installation directories that reside in # a path outside of the prefix in FHS and common usage. builtin_dir_noprefix_options = { 'sysconfdir': {'/usr': '/etc'}, 'localstatedir': {'/usr': '/var', '/usr/local': '/var/local'}, 'sharedstatedir': {'/usr': '/var/lib', '/usr/local': '/var/local/lib'}, } forbidden_target_names = {'clean': None, 'clean-ctlist': None, 'clean-gcno': None, 'clean-gcda': None, 'coverage': None, 'coverage-text': None, 'coverage-xml': None, 'coverage-html': None, 'phony': None, 'PHONY': None, 'all': None, 'test': None, 'benchmark': None, 'install': None, 'uninstall': None, 'build.ninja': None, 'scan-build': None, 'reconfigure': None, 'dist': None, 'distcheck': None, } meson-0.45.1/graphics/0000755000175000017500000000000013254552745016130 5ustar jpakkanejpakkane00000000000000meson-0.45.1/graphics/meson_logo_big.png0000644000175000017500000010463012650745767021633 0ustar jpakkanejpakkane00000000000000‰PNG  IHDRl„8°q®sBIT|dˆ pHYs.#.#x„?vtEXtSoftwarewww.inkscape.org›ī< IDATxœģŻyų¦ē|÷ń÷93ÉL&#ĖdO$™,²H‚„$N‘„ČJ‚Č"„øÖ®ÕG©¶Ŗ<¤ŌÖŚ¢Øh«URMmW‹¢O5m“ŌZA"’ĢõüqßIf&³ü–ū¾æ×ņ~LJ¼Iųż~Ÿū<Æ+5Mƒ$MK.i°3°Ėų÷»Ū+Ēæoī·ōÆ% ֎-ęo~±ĮƟ/šŸūY]5?Č’$µH.i``ĒMü¾Xl½‘_›śē7öÆ5ĄÆ€›7ų}¾üKąGĄĒæ’hŻ\WĶ/'ü_‘$MLr°‘4¹¤•ŒĘ—Ū˜]6ųµį?·=£aehn~\7žõƒužx£’Ųo%I³’KŚŲŲŲ•Ńą²©fŻß—GōNэl0ālę’ųf]5?ŽI•446’n7cö’Ś_{rdz2,°’~Ī<FŸ Ž“*Ij›\Rbōõś¶!fsæß%(³n¾9žõüń·żś,il¤É%-a4¾¬;ʬ;ĪģW§h}ś7ׁē:ÆjIR7å’VūūŽķĆh|YwˆŁXÕØŪŻ |›ĶŒ:uÕÜ—'©+l¤žÉ%-ażafFßąõķ(³ęēWŒ®jż£oæ¶ĮÆÆ×Usc\ž$ S.i;īcÖżµfüū® óŠq_]üpÕæ®­«fmd˜¤öp°‘:,—“ øp/ąžćߏ`ō@^i!ą»ŒĘ›k¹ó óŻŗņ ‡$ĶW.ią@6=Źģ§6ł%p5wrž«®š["Ć$ĶžƒŌ¹¤= 2ėž:?mÓlż’;9’|¾®šė#Ć$©MĘŖœ<8‰Ń+~ĶÖBŻ |ųwÖr¾ZWĶM‘a’¦ĒĮFj™ńk°ęĪćĢĪ‘]Ņ4ĄŸ[ēחż&RŅP䒖÷c4ΜƒĻ“ŃōŻ \ĆCĪ—ĻÕUóõČ(I“į`#æ™é$ątąXąp`Eh”47’Ńxó)ącuÕü 6I’&'—tp.p p~żV{ü€õ?Dł\]5?ŠM’4_6R€\Ņ!Ąć_'ąƒ€5 £Ož®> |Ś8’ŗ&—“p>š(ąčąi>ž‹õGœ®«ęW±I’6ĒĮFš\ŅVŒ>}{£‘fæŲ"©ndtņę£ĄuÕüæąIŚØ\Ņ.ŒNŅ\Ļ¢Q?üø’Ń×įŌUsulޤ 9ŲHS’KJŒī²?8Ų)¶Hj½kĖ€÷ÖUó„čIƖKŚ8›ŃHó |śļ›ŒĘ›2ŗĘüćąišl¤ Ė%Żøx4£×tJšæ’ŽĖh¼łJtŒ¤į_[ž ą"`epŽe-šyFćĶ‡źŖł§ąil¤ Č%ķ<žŃiš#ƒs¤¾¹ŠŃɛ?÷ø¶¤iÉ% ü&£—xåIZß7øćģ?GĒHCį`#-B.épąŒ†?…“¦ļJąO€÷×UsKp‹¤ŽĖ%mĆčkųowĪ‘ŗāF§`/««ę_¢c¤>s°‘ę)—“8 x&£×qKš½ļoŽTWĶw¢c$uK.iOą©Ą“€ƒs¤.»š;®0_#õƒ4G¹¤€'OĆ·Qź¦\R~x¾@꺟3z8ńĖėŖłAtŒŌ6œ\Ņ#€WūD·H ÷9ą)uÕ|1:DŅÜå’ŽÜ/ŗEŅDż„Ń›_WWĶĶŃ1R4 F.iWąMĄĆ¢[$µŹ­ŒŽc?殚ŸFĒHŚ“ń۟žĻčMŽ[ēHšž«=wīļ¢C¤H6„\Ņ9Œ^%øst‹¤ÖśoąQuÕ|&:DŅå’Nž_ É匆›ÆF‡HlŌk¹¤€×F·Hź„[}z‰Æ—Śa|ŖęUĄ“¢[$…ø™Ń«Ą_äIX ƒz+—tšV`ÆčIóą±>ųPŠ•Kŗ'šąŠčIįžųŗjž<:DšõĪų PƞŻ"©Ó¾\XWĶ•Ń!ŅŠŒßõŒŽåŪ%­ė2ą©uÕü0:Dš6õJ.énĄ_GD·Hź…[/öõßŅlä’v pzpФöś.škuÕ|(:Dš&õF.élFßąmœ"©®Ī©«ę†č©ĻrIŽģŻ"©ŽĀč”Ä?‹‘¦ĮĮF—KZüą·£[$õŚ—€3źŖł~tˆŌ7¹¤åĄόn‘Ō9×U]5ŸŒ‘&ĶĮF–KŚųsąÄčIƒp pj]5_‹‘ś"—“š×Ą=¢[$uÖZąåĄļÕUsktŒ4)6ź¬\Ņż=tlčIƒņ=F'm¾"uŻųkłū£[$õĀߏō-ź‹%ŃŅBä’.>Žc¤ŁŪų‡\Ņ¢C¤.Ė%UŒ¾–;ÖHš”_Ģ%"M‚'lŌ9¹¤ē/Rt‹¤A» xt]5"uI.i šRą9Ń-’zė&ą™uÕ¼):DZ uF.i)šząIŃ-’4¶øØ®šwE‡H]KZ¼ xht‹¤Ax+š“ŗjnŠ‘ĀĮFKŚ–ŃĆ…ĻŒn‘¤ Ü <¤®š+¢C¤6Ė%ķü->\XŅl}xD]5’"Ķ—ƒZ/—“+šAąččIŚ„Ÿ'ÖUóÅč©rI÷eō&ØŻ¢[$ Ņ·ÓėŖłJtˆ4>tX­–KZŌ8ÖHj·UĄå¹¤ż£C¤¶É%\‰c¤8{ŸĢ%Ż/:DšµÖx¬¹š I]°š‘\Ņ.Ń!R[Œßõ`ypŠ$ķ|,—ä#Ō6j„\Ņ~Ą?ūF·HŅ<|hüÜ-iŠrIOŽ,n‘¤±m€÷ē’"Ķ…ƒZg|„ąJ`ŸąIZˆ£÷咖E‡HQrIĻ^¤čIŚĄ2ąķ¹¤gG‡H[ā`£VÉ%€c¤ī;ųĆč)B.éEĄĖ¢;$i3šņ\Ņ%Ń!Ņęų–(µĘ:cĶ]ƒS$iÖ§ŌUó‰čiVrIÆžŻ!IópI]5æ!mŒƒZ!—“7šYk$õĖw€{ŌUóĆčišrIK€7æŻ"I šĀŗjž :BڐW¢.—“#šak$õĻžĄ[£#¤i?ÆéRk$u× sIωސ6ä`£P¹¤Ąßwn‘¤)yX.é)ŃŅ4ä’šąĀčIZ¤KrIψސÖå`£0ććÓŻ"ISöŠ\ŅaŃҼxtt„$MČ«sIžTk8Ų(ŅēDGHŅ l¼g|ŖPź…\Ņó?–Ō' xC.é±Ń!8Ų(ČųŽØßäI’#€FGH“0¾ę÷¢čIš‚%ĄŪrI§D‡H¾%J3—Kŗx7£[’†ä&ąŠŗj®‘*—t>šüąORæżČuÕü{tˆ†Ė/“š©\Ņ!Ą[p¬‘4LˁK¢#¤…Ź% ¼懔ŌŪŹ%ķ¢įņ„f&—“ š9ąščI v\]5ŸŽę#—t,šq`ŪčIš”Ļ'ÕUsStˆ†ĒOG4KÆĮ±F’^9~²Ō ¹¤CįX#ixī¼-:BĆä`£™Č%]\Ż!I-q,pAt„4¹¤];E·HRGē’^”įńJ”¦.—tšĻĄŖčIj‘o×UóĖčiSrI[1ŗu|t‹$µĄuÕ¼7:BĆį MU.iš>k$iCūϊސ¶ąU8ÖHŅmŽ2~‰Š46š¶?ī!I-õ¼\ŅŽŃŅĘä’<-ŗC’Zd𹤕Ń!MM.éąIŃ’Ōbwž!m(—t š§Ń’ŌB‡”aš6šŠ\ŅŻ=·ę.Ń-’Ōr_¬«ęÖč —“£Æį{E·HR‹]\WĶ[£#Ōož°ŃÄ咖ļűF’ęb pVt„·?dų/q¬‘¤-ym.ÉG?hŖl4 ÆŽŒŽ¤yft€4öąøčIź€m=ĻĘ©556šØ\ŅyĄS£;$©c˜K:":BƖKŗxrt‡$uČŻ€7FGØæl41¹¤€·DwHRG=#:@ƕK:xmt‡$uŠ£rI‹ŽP?9Ųh’Žl!Iõ˜\Ņźč Ļų¹5¬ˆn‘¤Žz}.ɟƒ4q6šˆ\Ņ…xē]’cąāč Ņ €£¢#$©Ćö.‰ŽP’ųZo-Z.i[ą«ĄžŃ-’Ōq×ŌUs`t„†#—t_ąÓĄŅčIźø8±®šOE‡Ø?äŗjnQ·yĀF ’KZ¼:ŗC’z(gEGØ×ވc$MÓŃĄ3£#Ō}6Zا‡FGHROy-JS‘K:8'ŗC’ąsIk‚Ōq6š·\Ņ.Ą ¢;$©Ē4~ƒ41ćæ§^Ż!I±-£Ņ‚9Ųh!^ģ!I=¶8-:B½óūĄŽŃ’4 §ę’.ŠŽPw9Ųh^rIGOŒī¤šõޚ˜\ŅĮĄoEwHҽr|CAš7Ķ×kšļIš…DØW^ l!I“£Ÿ”¤yóoĶY.éŃĄqŃ’4ūę’VGGØūrIē§DwHŅ€]K:#:BŻć`£9?Øš¢;$i`ŽŒP·æ~æ2ŗC’ÄĖsIžü­yńoĶÕS½¢#$i`l“XĻī!Iā0ą1ŃźmQ.išĢčI £¢Ō]¹¤CšAƒŌ&Kņybš3ĶÅyųéœ$Eš„浥VŃ’¤Ū­ž”īp°Ń\<+:@’ź ń3H¤yÉ%=89ŗC’t'æē×vĶ•ƒ6+—tąččIØ%Ą=£#ŌI IŚØŻšqĶ‘ƒ¶Ä’3‘¤X^‹Ņ¼ä’NŽī$mҳsI«£#Ō~6ڤ\ŅžĄĆ£;$ią|š°ęėEŃ’¤ĶŚx^t„ŚĻĮF›óų÷ˆ$EóJ”ę,—t£;$I[ōō\Ņ^Ńj7×F咶žŻ!IāĄčuЧk$©V/ˆŽP»9ŲhS~ X!Ibū\ŅŽŃjæ\ŅC€c¢;$Isöų\ŅŻ¢#Ō^6ŗ“\Ņ2ąŃ’¤Ūķ Nxat€$i^–/ŽŽP{9ŲhcĪö‰Ž$Żn’čµ[.锥}¢;$Ióv^.É7Bj£l“1¾Ź[’ŚÅ6ŚŸƒ IŻ”€—FG؝l“ž\Ņż€c£;$Iėq°Ń&咎Ć׿KR—–K:1:Bķć`£ yŗF’ŚĒ+Qڜ§EH’ĶS6ŗŻ.—“8;¶B’“ž°ŃFå’vcōģ9IR·å\ŅéŃj­ėiĄŅčIŅģ›KJŃj„‹­£#$Ińœčµ‹ƒČ%­Ż!IŚØåĄ^Ńj—\ŅRąIŃ’¤‰y`.É7žév6ŗĶłĄNŃ’¤MņZ”6t°wt„$i¢Ėf€l&—“ščIŅ‚xĀfø¼%IĆvN.É[ć`3<æŽŻ%©«vĪ%-ŽPˆ³£$I”–āM‰Įń÷É%m\Ż!IZ”=¢āŃ’¤pOČ%­ˆŽŠģ8Ų ĖŁĄnŃ’¤Eń96“Kŗ;°Kt‡$)ÜNĄ#£#4;6Ćā:Iź>Ÿc3<ˆ$µĘS£4;6‘K:æį“¤>p°ž£$I­qŒÆų›įxrt€$i"¼5<6’¤uyŹf l —“x\t‡$i":BÓē`3 >lX’śĆ6Ćāu(IŅĘ<%—”¢#4]6=—K:øwt‡$ib.Č%m”Ér°éŸÓ€½£#$ISå ›žs°‘$ĶĒjąĢčM–ƒM’\ Iš:›Ė%%ą°čIRē<.:@“å`Ó#¹¤ķ€‡FwH’¦nõų‡zõÓ~ĄŖčIRēœ1~Ė zĀĮ¦_ζ‰Ž$MŻR`‡čMĶŻ£$I“šččMŽƒMæ<6:@’43^‹źÆ5Ń’¤Īņ=ā`Ó¹¤}€£;$I3㛢śkMt€$©³ŽŹ%”Ép°éĒ>Ļ@’†Ć6żµ&:@’Ōi>|ø'lśĆėP’4,6żµ&:@’Ōi꒖FGhńlz —tąčIŅLy%ŖæÖDH’:mąŌč-žƒM?ų`)IOŲōP.iŽq’¤ÅógÄp°éø\Ņ2ą‚čIŅĢłC}?ķ Iꅇ璶ŽŠā8ŲtßéĄ.Ń’¤™ó„M?­‰$õĀ ąüč-ŽƒM÷ł°aI&›~Z Iź ßÕq66>āöŠčIRÆDõӚčIRo—K: :B ē`Ómē1:ź&IOŲō“ϰ‘$M’ī0›nó:”$ ן\RŠŽŠÄķ Iź•‹ü~”»l:*—“8>¶B’hąŪśĒ«n’¤IZœ”…q°é® —RI6ÆEõƒ$iŅ|ųpG9Ųt—×”$I6ż³::@’Ō;ēę’VFGhžl:(—t ppt‡$)œ§1z$—“ XŻ!Iź»gGGhžlŗÉÓ5’$š„Mß8ĄI’¦ÅkQä`Ó1¹¤­€ ¢;$I­ą`Ó/6’¤iyP.iÆčĶƒM÷œß K’Füæ_üė)Iš–%xS£slŗĒ’‘I’nć€ß/6’¤iŗ(:@óć`Ó!¹¤€³¢;$I­įųżā_OIŅ4šK:::Bsē`Ó-ēįŪ#$Iwš„Mæ8ŲH’¦Ķ‡wˆƒM·xJ’“.›~q°‘$MŪ¹¤­£#476‘KŚøt‡$©Uüæ_üė)Iš¶€‡DGhnlŗć1@ŠŽ$µŹN¹$æ6ō‡ƒ$i¼Õ6Żįu(I҆–ŪGGhbl$I³šą\’×Ŗ;ĄĮ¦rIĒw‹ī$µ’?ä÷‡-%I³°šččm™ƒM7\ Ij-?!ėIҬx-ŖlZ.—“šČčIRk9Ųō@.Éėm’¤Y:*—tXt„6ĻĮ¦żŒŸøI’6ĶÆż°::@’48>'µålŚĻ’I’6ĒōūĮįM’4kŽäh9›Ė%ķœŻ!Ijµ£46’¤Y[“Kŗot„6ĶĮ¦ŻĪ–GGH’ZĶĮ¦l$I.ˆЦ9Ų“ŪyŃ’¤ÖŪ!:@į`#IŠp^.É] „ü ÓR¹¤€DwH’ZĻ6ż°]t€$iöŽŽŠĘ9Ų“×ƀeŃ’¤Ös°é‡m£$IƒåµØ–r°iÆs¢$Ią•Ø~X I¬ssIh!›Ź%mœŻ!IźOŲōƒƒ$)ŹĪĄƒ¢#tg6ķt°ut„$©ēFH’:Ē6Żē`#IŠöŠ\ŅŹčŻĮĮ¦ErIŪ0:a#IŅ|8ŲtŸW¢$IѶΌŽŠlŚå4ü†M’4^‰ź>OŲH’ŚĄkQ-ā`Ó.^‡’$-„'lŗĻl$ImpF.i»č8Ų“Äųj?“$-„ƒM÷yĀF’Ō+€‡GGhÄĮ¦=Nfō*5I’ęĖ+Q–KZ,‹ī$iģ‘Ńq°iÆCI’Ź6Żęu(IR›œ’KZ!›VČ%-Ż!Iź,›nó:”$©M¶ΉŽƒM[<pĮ”$-”W¢ŗĶ6’¤¶ńmQ-ą`Ó®—’¤Åš„M·yĀF’Ō6Č%ķ1t6ĮrIK€³£;$Ię ›nó„$©m–ēEG ƒM¼ć]£#$Ię ›nó„$©|[T0›x^‡’$-Öö曟&IRŻ/—“OtĐłĶ] \RŻ!Iź¼l”óJ”$©p~tĐ9ŲÄŗ/°Wt„$©¼Õ]ž°‘$µ•o‹ ä`ĖėP’¤Iq°é.IR[Ż;—t`tÄP9ŲÄr°‘$MŠoŠź®ķ£$IŚ OŁq° ’Kŗ7°&ŗC’Ōž°é.IR›ł¶Ø 6q<]#Iš$›īr°‘$µŁį¹¤Ć¢#†ČĮ&ιŃ’¤^ńJTw9ŲH’ŚĪkQl䒎īŻ!IźOŲt—ƒ$©ķl8ŲÄšt$iŅlŗĖĮF’ŌvŽŸĆŖr°‰įók$I“敨īr°‘$u§lfĢĮfĘrI>°I’4iž°é.IR<2—”¢#†ÄĮfö¼%IšOŲtP.i)°*ŗC’¤9Ų8>:bHlfĻėP’¤iš„M7m IŅ<\0$63”KŚ82ŗC’ŌK6Żäu(IR—œ—KŚ::b(lfėŃ’¤ŽZķ½ņNr°‘$uɎĄƒ£#†ĀĮf¶ĪŒ$õÖ2|ŽM9ŲH’ŗĘkQ3ā`3#¹¤€ć¢;$I½¶Kt€ęĶĮF’Ō5gę’üś56³s*£O?%Iš›īń^IR׬Ą—éĢ„ƒĶģxJ’4m6Żć`#Iź"ÆEĶ€ƒĶ 䒖§GwH’zĻĮ¦{l$I]ō€\Ņ^Ń}ē`3Ēą7ђ¤éókM÷8ŲH’ŗh šØčˆ¾s°™‡DH’ĮĮ¦{l$I]嵨)s°™ IŅ,8Ųtƒ$©«ī•Kŗ{tDŸ9ŲLY.iOąČčIŅ 8Ųtƒ$©Ėr°™.IҬ9Ų$h\O IDATtĒīŃ’$Mˆ×¢¦ĄĮfJrIDwH’ĒĮ¦;öˆ$iBĪņZöä9ŲL§k$IlŗĆĮF’ŌŪˆŽč›éq°‘$Eš!¶Żį`#Iź“ĒDōƒĶ䒶Žī$ ’'lŗĆĮF’Ō''å’üŚ6A6Óq ąkĶ$IlŗĆ‡K’śd pAtDŸ8ŲL‡×”$IQlŗĆO!%I}ćŪ¢&ČĮfĀrI xpt‡$i°lŗĆĮF’Ō7÷Ī%Ń6“w`·čIŅ`9Ųt@.i ^‰’$õ“§l&ÄĮfņ¼%IŠä`Ó {ćóī$Iżōč耾p°™<IR¤U¹¤ŃŚ¢ż£$Iš’żsI9:¢l&(—“pļčIŅąyʦżˆ$iŠŠ6“õ` EGH’ĻĮ¦żl$I}v~.iYtD×9ŲL–×”$Imą`Ó~6’¤>Ū8-:¢ėl&$—“pJt‡$I8Ųtƒ$©ļ¼µH6“s<°]t„$I8Ųt–$õŻCsI«¢#ŗĢĮfr¼%Ij ›Ė%­vˆī$iŹVgGGt™ƒĶäœ IҘƒM»yJ’4Ft™ƒĶä’Šī$iĢĮ¦Żl$ICqr.i·čˆ®r°™ ÆCI’ŚÄĮ¦Żl$IC±xTtDW9ŲL†ƒ$©MlŚķ°čI’fČ·E-ƒĶ"Ÿz}bt‡$Iėp°i·#£$Iš”{ē’Žč"›Å;Ų::B’¤uģKŚ*:Bw–KZ‰Ļ½“$ §lĄĮfńN$i#vŽŠFŻæ’’$ Ļ…¹¤Ń5~ưx'GH’“ŪFh£¼%I¢}ć£#ŗĘĮfrI{w‹ī$i#–Gh£l$ICõŲ耮q°YO×H’ŚjEt€6ŹĮF’4Tēę’ü@ilĒĮF’ŌV~CŌ2¹¤eĄįŃ’$Ł8+:¢KlēAŃ’$m‚ƒMū‚'Ÿ$IĆęŪ¢ęĮĮfrI‡»EwH’“ 6ķću(IŅŠ=8—“StDW8Ų,œ×”$Imę`Ó>6’¤”Ū 8?:¢+lĪėP’¤6óźMū IR ų¶Ø9r°Y€ńCOŒī$i3vŠrIŪā`#I@Ī%Ń6 s,p—čI’6cŸč­ēžŒŽK’$><'6 ću(IRŪ9Ų“ĖIŃ’$µˆƒĶ8Ų,Œ–$µƒM»8ŲH’t‡sI÷Žh;›yßA÷o,IRŪ9Ų“D.i{|C”$Iņ”Ķ8ŲĢß x]’Ō~»å’|µw;œ,Ž$©e™KņgėĶp°™?ÆCI’ŗ wŽŒ$©…vNŽh3›łs°‘$u…×¢ŚĮē×H’“qh3›yČ%ķ Ż!IŅŻ=:`črI;ć÷’$mŹYćg½i#lęē$FGĢ%Iź‚ūDˆą÷’$mŹ ąÜ舶r°™ÆCI’ŗÄĮ&ŽiŃ’$µœo‹Ś›łyPt€$Ióph.ietÄP咖gGwH’Ōr'ę’öŽŽh#›9Ź%¬‰ī$i–GFG ŲÉĄNŃ’$µ\.ŒŽh#›¹ó:”$©‹¼ēüčI’:ĀkQį`3w^‡’$u‘ƒM€\ŅÖxJ’¤¹:,—䩹 8ŲĢA.i £7DI’Ō561NvˆŽ$©CŠ66ss/¼ƒ.IꦃrI³÷ČčI’:ęQ¹¤„Ńmā`37^‡’$uÕF§=4#¹¤åĄĆ¢;$Iź˜Żńٱėq°™’¦‘$uŁŃs:°]t„$IäƇ×į`³ćOɎī$iNĻ%„čˆń:”$I sv.ietD[8ŲlY¶‰Ž$iöī1¹¤m€³¢;$IźØmT6sįu(IRx-j6ĪVEGH’ŌaēD“…ƒĶ–9ŲH’śĄĮf6ž IRĒ9~4Éą9ŲlF.i{ą>Ń’$M@]Ӕä’NŽŒī$©ć¶Ćƒ€ƒĶ–<š=š’¤>X†Æ÷ž6O×H’4^‹ĀĮfK\õ$I}rAt@_å’Ą‡ K’4)Ė%-‹Žˆę`³y6’¤>9+—“StDO=æÆ’$iRV3ŗń2h~c± ¹¤½€C¢;$I𠭁GGGōĶųŁ@Oˆī$©g-ŹĮfÓNА$i ŠC㫼%Iš“‡ē’½Y ś?üœ IŅ™KŗgtD_䒖ψī$©‡vŽ‹Žˆä`³i6’¤¾ņ”Ķäœ ģ!IRO śZ”ƒĶFä’vŠī$iJ.Ģ%mŃ’+:@’¤{Dt@$›;>:@’¤)Ś83:¢ėrIg÷ī$©ĒöĪ%ÅĮfćNŒ$iŹžŠećJ—DwH’4ƒ½å`³q>æF’Ōw'咎Žč°§w‹Ž$il4’KŚ8<ŗC’¤ų½č€.Æšæ£;$IˆsI÷ˆŽˆą`sgĒ):B’¤83—tDtDż>°::B’¤ä)›;ó:”$i(š¼čˆ.É%€Ļ’‘$iÖl8ŲH’†åü\ҁŃņ2`ėčI’ę°\ŅĮѳę`³Ž\Ņ*ąČčI’fh)šÜčˆ.Č%œŻ!IŅ@ ī”ƒĶśī,‹Ž$iĘ.Ź%Ż5:¢ĶrI xEt‡$Ię`3p^‡’$ Ń֌®śhÓųtI’ā•KZÜ0S6ės°‘$ Յ¹¤£#Ś(—“šščI’4¬S66c¹¤åĄ1Ń’$z].É«Įė_…*ĄNĮ)’$ 0K6w8X!IR ĆgDG“Ģ3S£#$I9—“gtĬ8ŲÜĮėP’$Į ĒW€/—t8pIt‡$Iŗ]ĪŽŽ˜›;8ŲH’Ū/Žˆ6¾*żn<}+IRŪ ę966Ąų¾žż¢;$Ij @ /ŽˆŽ$IwrB.i—čˆYp°9 Ų6:B’¤yk.i‡čˆ¹¤S€ßŒī$IµxXtÄ,8،xJ’¤õ¼cü–¤ĮČ%ķÄč­PƒśĻ-IRĒ āZ”ƒĶˆƒ$IwöPą¹Ń3öf`0oŸ$©£4„“Ą©išč†P¹¤%ĄuĄŽŃ-’$µŠ­Ą©uÕ|":dŚrIĻĘ.K³r#p-p šµńļßnaō”ņŅ ~ß 88hükĶų_“4\ÕUóĪčˆiZЇćX# Įæ¾Üülß׿ć›}#x$£ē[ Ü O$jø–ļÉ%UWĶ·£c¦a|ķė„ ļ4‘4Kæ>ü5šQą[uµšOŽsI[ūwNĪ`4āHŽG½lÄh¤łp]5?ŸęŸ,—tp:£ńęD`ł4’|’ĀŻģŌ·ļMÖå`SŅeĄyŃ’&ā_}zwšÉi}c8ž†š·Ē[OćĻ!µŌ[€__̧ām’Kŗ š—Ą)Ń-RĻüøx]]57Fä’Vž Ü+¢AŅLœPWͧ¢#¦ÅĮ¦¤ļ»EwHZ°µĄ_XWĶWfł'Ī%ķ üšd`»Yž¹„@oe4Ś,čÄZ[ä’v.gtrNŅdܼ xE]5?Ž¹M.éFĆĶĆń¹7Rß¼ø®šēGGLĖ ›\ŅAĄÕŃ’d-š^F’'}UdH.i;ąIĄļ«#[¤¹xB]5·F‡,Äųė’‡ż¢[¤žø™Ń#^ZWĶuŃ1›’KŚx~Š"õÉēźŖ96:bZ†>Ųüš¦čIór+šną%uÕ“jp#xŠŪ/Ņ:ŽĆčķ ·D‡ĢG.é¾Ąß;G·H=ń}ąÜŗj>2Wćv—0zv•Ϥ“ŗm-°K]5?Š™†”æõä„čIóņwĄ!uÕ\Ō¶± ®šoĒŻ"ĶĄ£½=j«č¹Ź%=ų8Ž5Ҥ|øO—Ę€ŗj¾WWĶć€ū_Œī‘“(K€EGL‹ƒ¤.øx6šŗjž+:fsźŖ¹¹®šg1zĶąõŃ=Ņ” ¼/—“mtČęä’vĢ%½™Ń›jVF÷H=q)p|]5ߊYØŗj> ĶčŠŌƒs$-Ü©ŃÓ2Ų+Q¹¤}ÆGwHŚ¢k źŖł\tČ|å’öŽÜ;ŗEš²k€ĒÕUó™č å’.^ ģŻ"õČoÕUóŖčˆIŹ%­f4B=$ŗEҼ}³®š}£#¦aČ'l<]#µßū€#»8ÖŌUs-p?F’9¤>;ųd.ée¹¤V¼ź>—t`.é ąĻp¬‘&éÅ}kĘĻæ8 x0ĢO“„īŚ'—tHtÄ48ŲHj£_O®«ęüŗj~³uÕü øųHt‹4eK€ē_Č%Ż3*"—“u.é÷NŽźzꯀ’1-uÕ4uÕ¼xŠéļ?¤źåµ(Imó ×UóĘčI©«ęfFĻ“łlt‹4GŸĖ%żn.iÅ,’Ť€/ĢōĻ- Ą—½®÷§OźŖł[F϶¹*ŗEҜõr°ä3lrI»ߋīt'?NŖ«ę+Ń!ӐKŚųF?ŠJCš#ąķĄ¦õĄšń×ōG1z=ļQÓųsHāūĄ1ć·!F.iš~<­'uĮρÕćÓķ½1ŌĮę<ą²čIėłFcĶæE‡LS.iąÓĄžŃ-Ņ 5ĄĄŸ¬«ęÖÅü›å’Vg4Ҝ,]t”¤MYĖčmPƒ<%:~ ŽG=“NR»=°®š+£#&iØƒĶ«gFwHŗŻ÷5ƒ8zœKڟŃh³Gt‹࿁÷2ŗjšĄÕć‡}nR.i`/F7>‡ŃĆUSī”4ņĪŗj.ŠŽˆ”KŚøøWpФĶ{i]5æ1ICl>Ü'ŗC0°±ę6¹¤#ZńF)ŲuŒĒą‡ĄžŒšŪ~m—& ŚĶĄ!uÕ|-:$Z.iąSĄĮŃ-’6éŸėŖéÕĻłƒlrIŪ0zźūVŃ-’ų£±ęߣC"ä’~xit‡$I›š†ŗjžŃ¹¤»2:!»ot‹¤j€]ėŖ¹.:dR†ų–ØūąX#µĮõ x¬ū#ą3Ń’$m茮ø¦±ŗj¾œĘčᦒŚ'ѳ‡„q°ńaR¼xĢĄĒźŖY \ü,ŗE’¤ ¼¾®šļDG“M]5WĻŽī“I½z½÷› ‰ŌUó”čˆ6?ąYŃ’$­ć§ĄĖ¢#ŚŖ®š7Ż!i£l:ĪĮFŠõąÅŃmRWĶ[€FwH’4ö’ŗj~ŃrO6ū†;I!öŹ%1)ƒlrI»FwHv5šŲŗŲÓĪēębFoŹ‘$)ҵĄ«£#Ś®®šļOŽī“Q½9e3ØĮO×H‘nĪ®«ę§Ń!mTWĶ÷ßŒī$ ŽsėŖ¹):¢ źŖyšīčIwā`ÓQ>pXŠŃśC†ēąŻĄ£#$Iƒõ™ń”¹{pKt„¤õœKZ1 Cl üct‡¤Ū%ą”čˆÅÄ`“KJ8ŲH³“–ŃUØ_E‡tÕų!†Æī$õŽļÕUóó舞xGt€¤õtžZŌ ą `ut„4 ÆŖ«ęŸ¢#ząeĄ/¢#$I½õ%&éŠčIėń„MGÜ/:@’žŃuÕüø4ŗC’Ō[æ_W¹Ÿŗj®¾Ż!év{ä’:ż¦č” 6^‡’f£žXWĶŃ!=ņj|UØ$iņ¾TWĶåŃ=ō±čIėéōµ(I“ti]5ŸŠŽč“ŗjžųpt‡$©w^ŠS6R»œ°½lrIŪwīąFFo6Ņä½*:@’Ō+WŃSŸĄ“±R›Ü?—“UtÄBõ~°Že’9„hÆØ«ę[Ń}TWĶĄæEwH’zć„uÕ8*LH.éē’ī[WĶ€/G7IŗŻ6Ą½¢#jC†×”¤éū>pItDĻżqt€$©®ŽŃ'uÕ\l \žK:ß¼%µMg_B4„Į¦³q¤yA]5?‹Žč¹?®‹Ž$uŽ%uÕÜŃCš#ąķĄ ”5’ÖÕŁM`YtĄ4咖0ŗ%iz®ŽŃwuÕü2—ō|N$iį¾…§?¦¢®šoß¾ķē’Ž<=®HŅ::;Ųōż„Ķ”ĄöŃRĻż¶ŸŌĶĢŪšA†’¤…ū£ŗj~1ÆÅÆŁR[Ü5—“wtÄBō}°éģ’&uÄĒźŖ¹<:b(źŖ¹ųLt‡$©“¾'bg¦®šÆŽīt»Nn}l|ą°4=kgGG Š;£$IōŹŗjnŒŽ˜×DHŗƒM 9ŲHÓóēuÕüKtÄ]Ü!Iź”ė?Ž WGGHlŚ%—“88ŗCź©xItÄÕUs=šĮčIR§¼µ®ßZ4cuÕ4Œže#)޽rI+£#ę«·ƒ p_ EGH=õWuÕ\1`^‹’$ĶÕZąO¢#ģĄO£#$± 8::b¾ś<ŲtņȓŌž®‰u9šĆčIR'\^WĶ×¢#†Ŗ®šŸ1zĖ£¤xŪś<Ųųüi:>XWĶ—¢#†¬®š›÷FwH’:Į+9ń^Ē褓¤X6mKZ Ż!õŌ‹£x-J’“eWWDG ]]5׊īDĪ%uź±)½l€#€UŃR}¬®šŠŽŌUóĄw¢;$I­öśńƒoĻW|KńvŠŽ˜¾6^‡’¦ć£“žĖ£$I­u£ŽŖźŖłą ¤xŗå`#i®>UWĶ'£#“IҦ\ZWo'jŸ'$Ås°iNżE:ĀgדĻĄÆ¢#$I­ōŗčŻÉ„ĄõŃŅĄ0½lrI;DwH=ó/uÕ|4:Bėæ*ōSŃ’¤ÖłX]5’”õÕUó ą-ŃŅĄšKZ1W½lšķPŅ4¼::@›ä['$IņźM{½_ń-EZĘč%EŠĒĮęčč©g~¼;:B›äsl$IėśšĮčm\]5_>Ż! ܑŃsÕĒĮĘ6Ņd½±®š›¢#“quÕ\ \Ż!IjKėŖńG»ł|!)–ƒM irnž$:B[ä)IŅm.Š}?l‘"9ŲDČ%ķģŻ!õČeuÕ|7:B[äsl$IŸ©«ęæ¢#“yuÕ4Ą›£;¤»G.iitÄ\ōj°ĮÓ5Ҥł°įnųąŃ’¤pļˆМ½ŃIfI³·8(:b.l$mJ]WĶē£#“euÕüųxt‡$)Ō/Ė¢#47uÕüš7ŃŅ€uāZ”ƒ¤MńtM·ųI¶æ©«ę'Ńš—7EHę`3Kć;hGEwH=ń-ą/£#4/6’4l^‡źž_‹ŽŹĮfĘgtMŅā½”®š[¢#4wuÕ|ųJt‡$)Ä÷€FGh~Ę~Kt‡4P63ęu(i2Öā§t]å)I¦?««ęÖč-ČŪ?$“fou.iŸčˆ-éÓ`stt€ŌŸØ«ę[ŃZ_ļ-IĆtit€¦®šļˆīŖõTéÓ`ć i2Jt€ģ³ĄõŃ’¤™śR]5’”EńįĆRŒÖ_‹źÅ`“KZÉč6’ē§Ąū£#“0ćēł IO×tßĄ×£#¤r°™‘£€„ŃR¼Æ®š_DGhQ®Œ$ĶLüEt„§®šµųša)‚ƒĶŒxJš 6Ü}Ÿ‰$ĶĢē}ī\o¼ >,ĶŚ]sI»DGlŽƒ¤Ū\SWͧ¢#“h_~!Iš Æ1÷D]5ß>Ż! н£6ĒĮFŅm¼ßćcÕut‡$i&ž*:@åƇ„Łs°™¦\ŅĪĄ~ŃRĒ58Ųō‰×¢$©’®Ŗ«ę«ŃšØßˆŽĘĮfŹ<]#-Ž?ŌUóõčMŒƒ$õŸ×”zf|Jö­ŃŅĄÜ':`sś0Ų õ@‰ŠDż>øP’śĪėPżōVąÖči@önóƒ‡ū0ŲxĀFZœŸć+A{eüjö/GwH’¦ęuÕ|1:B“WWĶw€EwHÓŚS66’ž¢®šŸGGhā¼%Iżõ×ŃšŖ7GHÓŚēŲtz°É%ķģŻ!uÜ;¢4ŸŽ$M×”śķĆĄ÷£#¤q°™O×H‹óuąŹąM‡'l$©Ÿ~€£|ÆÕUs šīči@¼5%6Ņā¼³®š&:B“WWĶwk£;$I÷7ć· ©ß.䮹¤]£#6ĘĮF6ÆCõ›§l$©|÷ŌUóeą_£;¤i嵨Ī6¹¤„ĄQŃR‡}ŗ®šk¢#4U6’Ō/7ŽŠĢxŹFšV^‹źģ`¬ŒŽ:¬Dhźl$©_>TWĶMŃš™w·FGHį › ó:”“p掔©ū7ąśčIŅÄxj@ĘĻ£ūXt‡46vtt€Ōaﯫę§Ńš®ńC)ėčIŅDÜ\”™óZ”4wĶ%ķ±”.6ž°‘Ī/žĆįµ(Iź‡+źŖłYt„fīżŒž]$iśZwʦ“ƒM.i%£gŲHšæŸˆŽŠĢ|6:@’4^‡ ŗjnÄkģҬ“īĮƝl½jit„ŌQØ«ę–čĶĢ€µŃ’¤E¹ų@t„Āx2Zš OŲLˆ×”¤…ūĖčĶN]57WGwH’åSuÕ\”0Ÿ¾! Ą‘Ńr°‘†å§ĄŃš¹ĻEH’ÅėPVWM¼3ŗC€½sI;DG¬ĖĮF–ÖUsSt„fīóŃ’¤Eq°‘ƒ4‡E¬«sƒM.i`æč©£¼5Lž°‘¤īśB]5’”XuÕ|ųĒčiŽˆXWēąģč©£~|8:B!žųUt„$iA<]£ŪųšaiśZõ6ź.6:źļźŖłEt„fÆ®š_1m$IŻsyt€Zć½ųŒ4mž°YØ\ŅĪĄńŃRGyjŲ|Ž$uĻ÷pp×X]5?>Ż!õœ'lį,`it„ŌA7įų”ó96’Ō=æ!Hŗ×¢¤éZKŚ#:ā6]l|~“0WŌUsCt„ByĀF’ŗĒgĻiC—×EGH=ךkQlrIŪ§DwHåu(żąh'IŻq+šŃčµK]57Ż!õ\k®Euf°NVDGHt ščÅŖ«f-šĻŃ’¤9ū\]5?ŽŽP+] õœ'lĄėPŅĀüżų!u’ϱ‘¤īų»čµÖg€ļDGH=ę ›’ĻŽĒŻv×õ”’¬“ ČCdF@j\¢ γUƶ½­Že-z-ÖŚZķÕ«µŠ­·j[-Zl]jµ*0ŒaLHp%LaB „) ĢgŻ?žēsNΰ‡µ÷oķµßļ×kæNĪyžgķ/ {ŸĻž~ku[—ä[Kē€ õāŅ ēŲlē×pH»S³ÖŻaužP·Õ(ŗ’Q„˜Įs’œV:l ½I^V:£aĀ`3\—äķ„C0j/*&ģ~IY:D²9…Ķß+6Ō…]Ó_[:ćŠ5żG“\S:GužŪysÖ¢`µF±5śĀ¦n«* X”qYvié•u(ŽČZ¬Ü(}a“äéIT:l >ÉKJ‡`tŽ[:G“7nēĶl¬EĮ꘰™‘»CĮb.难ć„C0:ļ)€#zG×ōוĮF°«cĀfFÖ”`1Ęd9… Ąø¹73±+õ˜ŗ­Ž/bŌ…MŻVOHņŲŅ9`CyēPž6ɝ„CpXĪÆaÖ¢`5ŽMņÅ„CŒŗ°‰u(XŌ»»¦’péŒO×ōw$¹¬té†$o-‚b- V§ųšˆĀ¦é„0jÖ¢Ęéu]Óß]:›ĆZ¬”Āępź¶:'Éß-6ŌĖK`Ō6ćäüa- Vć1„Œ¶°‰Ć†aQ×&y[錚[{ŒOŸä¼Ņ!ŲHÖ¢`5L؁u(XĢ+wĒcįpL،ϻŗ¦’TélkQ°2&l„n«Ó“<³tŲPίሺ¦’X’KēąīÅ2¬EĮšĪŖŪźŌ’FYŲ$łö$Ē”čŽ$Æ-‚`Ź`\œ_Ć2¬EĮj]‹kaćüXĢł]ÓßR:Į96ćqS’®t63r IDAT—µ(X™¢kQ£+lź¶:!É7”ĪŹŻ”˜• €ńx}×ōw•ĮƳĆ3asÆLrßŅ!`C9æ†Y)lĘĆł5 ĮZ OasÆ)6Ōūŗ¦’HélŒĖKą ^W:›ĻZ¬„•؃|mé°”L×0³®éoLņ™Ņ9Č»¦æŖt&ć„„ĄÄ˜°Ł§n«““<µtŲPĪÆa^W–@^_:“ra| C:„n«³J=łØ ›$ĻLrl鰁®Orqélœ—€Ā†įģ^ķL$V±)›±6Ö”`1ÆŚŻ[†y˜°(ko’7•Į䘺†a)lv9p慙E(lŹzĒī™b0¤W'¹»t˜b¦°©ŪźŒ$O*6ŠI^[:IaP–»C1øŻš¢Ņ9`BLŲ$yN’ŖtŲ@tMsél$… @YĪÆaUL_ĆpLŲÄł5°(·ófQWeēüÖļÖ$]:“„°į<ŗn«"Ć% Ų|^YH×ōw&¹ŗt€-ua×ō·—Į4uMy’ĖK瀉øo’sJ<ń( ›ŗ­ĪIņčŅ9`} kzk-,Ć’~ʰÅŖłP†Sd-j…MLץ¢¼³¬—°„6¬šµyN‘ƒ‡ĒRŲø7,Ę 1Ė2a°~×'yWéLŽEIÜ6†±Õ… ˜ß qX!ĖSجߺ¦ļK‡`Śŗ¦æ+ÉkJ瀉ŲĪ•Øŗ­—äĮ„sĄzu×ōw—ĮĘSŲ¬Ÿu(ÖÅś< ck'l¬CĮb¼3„O”°…6¬Ė«“ÜU:LĄ#ź¶:vŻO:†ĀĘ:Ģψ+C¹¦t€-ó”®é?R:Ū”kśĻdē,`9Ē&yÄŗŸ“haS·Õž$Ļ.™6Ō…]ÓßT:›Ækś;ā@B€u2]Ćŗ™Ź†a¬}-Ŗō„ĶS’< pŲD^xҧJŲ"Æ+€­ć}# cķ—.lœ_‹q;o†d- `=ö&ySél—®é?˜ä²Ņ9`¶nĀĘł50æĖv_xa(&lÖć]ÓßP:[ɔ ,o{&lź¶:.ÉW—z~Ų`¦kšĀ`=œ_C) XŽVMŲ<=ɉŸ6•\†f% `=6”ņ–øÉ,뜺­ī»Ī',YŲX‡‚łŻ˜\’ €Õ»-^Ć)¤kś»ćü$XV•äQė|Ā’…ĶW|nŲTÆéšž®Ņ!˜6«wa×ō·•ĮV{Cé0k]‹*RŲŌmU%yZ‰ē† ēüVĮ„ ĄźY‡¢“7–0żĀ&É撜Vč¹aSŻäÕ„C0I €ÕSŲPT×ō›ä„sĄ†[ė¢J6_Qčya“½„kz‡Å± ×%éK‡˜°O'¹“tˆµ(XÖVLŲ<½ŠóĀ&sw(Vb÷\¤ėK瘰7vMÆg ¬EĮr½Ī'3a›CaĆ*Y‹XėPŒ… XĪŁu[“®'[{aS·Õ‰Ižøīē… wE×ō—•Į¤¹SĄź¼®tH’®éÆNņĮŅ9`Ć­ķ›6OMrLē…Mfŗ†U3a°WvM’įŅ!`?Ö¢`9k[‹*QŲ8æę÷ŖŅ˜<6«aб±Ė™ō„ók`>{“\\:“gĀ`5^[:äMqwHXʤ'l60Ÿ÷wMKéLžĀ`xwń #Ó5żõIŽS:l°iNŲŌmõ°$gÆó9aL×°V¢†wq×ō7•‡`- 7Ł ēץü.)€­`Ā`xÆ)Ca‹[Ū­½×]ŲX‡‚ł™°aLŲ OaĆX½9;+{ĄbÖ2e£°q»9ÉJ‡`+\ŸäīŅ!&äŗ$ļ,e÷|Ä·–Īl-ēŲ¬­°©Ūźų$_¶®ēƒ‰x[×ō{K‡`śv’wvmér^×ōīÄƘY‹‚ÅMnĀęÉINXćóĮX‡b¬E ē¼Ņą(6°øiMŲÄ:,BaĆ:9x`}6ŒßÅIn-6”Āp‡(ÖJa0ŒwvM]ép$]Óߞä¢Ņ9`CMn%Jaó¹Ņ›=ÖĢJĄ0ÜŠMa- ³–[{Æ„°©ŪźĢ$\ĒsĮ„X‡bŻLŲ CaƦø tŲ`+Ÿ²YׄĶÓ×ō<0%Ö”X·—07Ň.lŽK“ÜQ:lؕŸc³®ĀĘ:ĢĻ›=Öķc„LĄŗ¦æ«t˜Åī96—–ĪŹ„ l©Ū“¼«t¶ŽĀ`yÖ”Ų4>$„Ålž„MŻV{’³²µØ•6u[Ÿäq«ŗ>L”;D1¦lfwa×ōŠn¦ąo“|¦tŲ@›WŲ$yB’ćVx}˜"Ÿl0 €ŁY‡bŗ¦ļ“¼µtŲ@+;Ēf•…u(˜ĻĶI>P:ÄĮĆóPŲ0%><„łm䄍Āęó¶®é÷–1a0«÷wMeé0 … ĢĻ„ l/Œ…Ā`6¦k˜ē)ĀüLŲĄšÉXX‰˜Ā†I难†$——ĪęA«ŗµ÷J ›ŗ­’äōU\&Ģ„ caĀąč®‰[˜&ĆüV2e³Ŗ Ó50Ÿ+»¦æ®tŲ„°8ŗWģŽU¦ę½„ĄśāU\Taćą:F£kśĻ$ł|é#gŠ©z_鰁¾dUŲĄ8X‡blLŁŽ­I^W:¬ČūK€ ō„U\Tać °al< pxÆļšžÖŅ!`E>šä–Ņ!`ĆlʄMŻV÷MņŲ”Æ v{’w•1apxÖ”˜¬Ż³™ž¦tŲ0®Ūźų”/ŗŠ ›/]ŃuaŖ.ķšžŽŅ!ą €C듼¼tX1ēŲĄ|ŽMņ˜”/ŗŠbÅ:ĢĒ:cd% ąŠ.难šŅ!`Ŝcó|-Jaå¹CcdĀąŠ^V:¬Āę7ųĮĆ (Ļ„ cteé#„°a(l`~QŲę7čĮĆC6ųz0eÖ”»ĖćNQIņ™$ē—ėŌ5ż§’ÜP:l˜qNŲģž†üČ”®[ĄĆŒš;E|Į+»¦æ³t(Ą” Ģē±u[;Ōņœ°yd’Į‚Įxké0oŌ¬C±½œcó9>É£‡ŗŲ…ók`v·%ł@é0… °ķnKņšŅ! ļ`~ƒ­E)l Œ÷vMļl67jĄ¶{}×ō·”…xó{ŅPRŲ@—–3ś›Ņ ³Å6ó>ę÷””.¤°2ŽY:Ģȝ¢€m¶7ɹ„C@)]Ó_›»¤³SŲĄ†3aĆFŲ½SŌå„sņ–®éÆ+ ó>ęó°ŗ­ī?ą)lvÜ9ĵ` ܝä=„CĄ܂ŲVÖ” ¹¬tŲ@ƒLŁ 5acŗf÷®éo+ępaé…(lĄ„ ,bT…ĶcŗlėPlš‹J(ą]]Ó_Y:Œ€ ˜ßßā"&l`ż8ĢF难Š$Ÿ*`Ķž¢t 60æQMŲ(l`v&lŲDo)`Ķž²t‰&éK‡€ óųŗ­NXö" XÆ>É»J‡€8ĒŲ&o·;ŗ¦’|’«Kē€ sl’'.{‘„ ›ŗ­ö$yׁ̲-qe×ō7• pŽ °M¬CĮ¬EĮü–^‹bĀęaI–õ-aŠMõ®$·”°}’•#ćąa˜ß( ėP0;³‘ŗ¦æ;ÉÅ„s¬Į%]Ó_U:ŒŒ ˜ßŅwŠRŲĄz™°a“9ĒŲÖ”ąŽLŲĄüžT·UµĢ6°^ 6™sl€©³‡fĀęwr’G-s… ¬Ļ'ŗ¦æ¦tXĀÅIī*`…ŽŅ5żĒK‡€ŗ*Éķ„CĄZj-jˆĀę±\¶é6Śīm=ĆL™u(8„®é÷&¹¢tŲ@K<¼TaS·Õ‰IŗĢ5`‹ų‹.S`- ˜Ŗ½I^\:Œ˜sl`~å ›˜®y˜°a Ü) ˜Ŗ7wM’©Ņ!`Ĝcó+ŗåü˜Ā†)xGé+b ŽĢ„ ĢļAu[°č+l`=nģšž#„CĄ²ŗ¦æ2ɍ„s ģī$’»t9… ,ę“EPaėaŗ†)q05oźšžŗŅ!`ä¬DĮbN]ō6°ž‚Ė”X‹¦Ę:E×ōŸNņéŅ9`›°qč0Ģʄ S¢°¦äĪ$/)6„)˜ßś ›ŗ­’ä¤E¶ĢūJ€™¦äe]ÓßP:lēŲĄüЬD™®ŁģO#˜–%¹©t€ü^é°A¼§…łY‰r~ Ģę#]ÓßV: „kś>ÉŪKēĄIŽX:l60?… ŒŲߖ+š¦Ņšū»%4060æ"+Q ˜Ā†)zCéKŗ#I[:l˜fgŻ˜ ±”+šö$7—°„—tM]é°Iŗ¦æ=ÉU„sĄ†YoaS·Õ I¾č“Ā–1aĆätMW’7—ΰ‡ Ćb¬EĮ|Ö¾õč%~¶Ā†©²lŖĖ»¦?ætŲP†ł¬}%Ź:Ģęś®éÆ/VDal*Ó5°860… Œ”é¦ģ}I®-`N·'ł£Ņ!`ƒ™°ł(l`¤8ĢdķŽ ÷„sĢéÅ]ÓŗtŲ`&l`>k?Ć걋>!l6LŻKJ˜“u(XĪÕIn-6ČÉu[³Čš°ÕRŲ0uÆLņłŅ!fō®é/,6Łī„ķKē€ ³Š”Ķ܅MŻVg$yĄ"O[ČJ“Ö5żē³SŚlÓ50 ēŲĄ|ÖSŲÄt Ģź¶$W•kš¢Ņfp[’?.&Ā960Ÿ…VŲĄź\Ö5żŽŅ!` ¬E›ąE]ÓßX:L„ ˜ĀFĘł5lkQĄ†xAé0! ˜Ļé‹üĀVGaĆ6±ŒŁk»¦[é0!V¢`>g.ņC‹6né ³qą0Ūä•In)ą0ž}é0%]Ó&ɵ„sĄ9k‘š«°©ŪjO’G.ņD°…LŲ°5v×¢ž¬t€CøØkś7—dŹf·śĀ&É9INXä‰`Ėģ1¶Ļļ–pæ\:L”sl`vkY‰zō"O[čŖ®éo-Ö©kśK“¼µt€ż¼£kśóJ‡€‰ņį$Ģn-6 ˜u(¶•)`Lœ]«cĀfgĀFāĆl«?Oņ™Ņ!’¼?ÉĖJ‡€ »²tŲ k™°yĢ"O[Ȅ [iwšKēHņó]Ó÷„CĄ„}“tŲ ØŪź˜yȄ ¬†Ā†mf- (ķ¢®é_Z:LY×ō7%¹¹tŲ{’œ¾Čͤn«*né ³ņ‰[«kś$y}éĄVūׄĄ–øŖtŲ sÆEĶ3aó$÷÷ ` ķMņ‰Ņ! 0·ŃJłĖ®é/)¶„)avs<ÉÅ„s[ćĘXĒ„u3a³³# °{˜²Öå—ŗ¦æ”tŲ2&l`v&l`®.Ę¢kśW%yGéĄä½-É J‡€-dĀf§°0aś„Ņ€I»3É?ķšžīŅA` }"É]„CĄ†XĶJTŻVNræ¹ćĄvRŲĄ~ŗ¦?7É„s“õ«]Óæ§tŲF]Óļ÷¾0«•Mؘ®Łyт{ū‰${K‡&ē²8+ J³³Yٔà ˜MŸäć„CĄŲtM’®$’£t`Rś$ĻķšžöŅA`Ė9xfs’ŗ­Ž›ē60¬k»¦æ£t©ŸKrséĄdün×ō–˜°9šä’)H¢°ya£°Ł)l`F]Ó’U’?.ŲĪ­qsš0Ģʄ ¤°łü‹ų’ pd/Šsk`ģLŲĄlLŲ@!×uM{é°Iŗ¦’L’*­ “|æsk`ō>Y:lˆSė¶:qÖovč0 Ē”, kś×&łķŅ9€Ńł@’ļōal7€ŁĶV¢`ŗ¦æ"É7dē/xĄęūd’ētMļœ*˜60»™Ö¢606°"]Óæ7É·$ł\é,ĄRŗ$·kśw— Na³›éąa… ć®®éo+¦¬kś‹“ü½ģR lžßMņģ®é?Y:°V¢`vKOŲ8ĆfgŗÖ kś×gg=ź3„³3»=É?ķšžG»¦æ£t`eLŲĄģLŲĄ)l`Mŗ¦æ(ɳ²s0nKņĢ®é’{é ĄŹ)l`v‹OŲŌmuZ’ӍÓęĄaX£®éߓäI®(8¬ ²s^Ķ[KÖĀJĢn© Ó506°f]Ó8ÉW%¹“tąw&ł„$_×5½æĄĮ–čšžę$Īt„Ł,u†Ā棰ŗ¦æ&ɳ³óI>PŽ„IžŚ5ż/tMWé0ĄŚY‹‚Ł,5aćĄa˜•((d÷½oLņĀŅY`‹Ż‘äē’<Ķ-»a«™ŖƒŁœU·ÕqGū¦cóē&l`>&l  ®éoOņĆu[]”äw’ÜÆp$Ų&oMņOŗ¦é @q&l`6U’³“\}¤o²Ć0a#Š5ż'yz’ĖKg-p[’ŸNņ•Ź`— ˜ŻQϱQŲĄ0LŲĄHtM’¾$_žäE„³Ą„½"ɓ»¦’µ®éļ. 60»£žcsÆ•Øŗ­NIrÖJāĄt)l`Dŗ¦’l’ļ«ŪźĒ“üz’£ī3¹$ÉOwM’ęŅA€Qŗ©tŲ MŲ¤€ƒ]“ä·“üN×ōחl… Ģn”3l¼y…łyq‚ ²{ūļĒ'ya’» ǁ1xo’Lņ°®éŸÆ¬ä=1Ģn”3lLŲĄü¼8Į†éšžŗ®é8;ÅĶ’JŅŽėÖ'yu’ÆļšžI]Ó·]Óß^:°ŃLĆģN©Ūź¤#}ƒĀ†įÅ 6T×ōWtM’&yJ’——Īkpk’ßĻĪAĀßŅ5żėK&Ƈ˜0Ÿ#®E9t†qkéĄrŗ¦O’ļØŪź+’ü‡$Ļ) †vevÖ’ĄŹ°" ˜Ļƒ“\vø/:t†qØi5`uMq’Æ©ŪźYIžy’ļĢ”_/aܙ䯲3Qóś®é­ž«¤°ł˜°5PŲĄÄtMA’ ź¶zH’IņÜ$g—M3Ū7Mó‡]Ó_S: °ŗ¦æµn«»“S: lˆ#ް’ן¶:.É#sč2ēˆć³ŒÖ-IŽ–)š‹“\bĶ ˜ … ĢēĮIŽwØ/˜°a˜°µ{ńĖvØŪźÄÜSŽ<&Nåœ%ņōI>żŹ™$ļ³āl… Ģē°Ä)l` `mŗ¦’\’KwØŪź„ģ¬Y“ä‹óė)k ;m}’'¹āPŻ’ž¶Āę3sac% s\éIŅ5żķŁ9åC‡ūžŗ­NĶį˜/ŹNįćßk;öfge탹w)se×ō·Ģ0F†ł˜°;¹t€YuMS’÷ī>īe÷0䳓œ™sNĻĪ{„Cżó¾ß? ›wHņŽģüÅāęŻĒĒrčRęŽb 6éB˜ X1… 0»‡!r÷1³ŻÉC•9ū~½ovŽ{ õø=÷”-‹(Մ ,FaĄ¼ĪŽ]Gæ—/6»ßp’µE‚iQŲ0Æc“œuØ/ģ?asZܚ„°`‡\‹Śæ q~ ,NaĄ"ŽZŲ8æ§°`&l`…6,Ā„ ¬Ā€E˜°RŲ°… ¬Ā€EX‰‚ŗél$6°BgÖmuLélœ³ź¶:öą?4aĆŲ“äĢŅ!Ų8{’<šPø XĪŁ„°‘īµe†ó ŅŲHG,lLŲĄrLŲ°ˆC6u[ķIrŚŚćĄ“(lXÄa'lZo˜… ‹8laćüXžĀ€EqĀXŽĀ€E¶°9uĶA`ŠÜ% €E(l`…LŲ°ˆ3ź¶:~’?ŲW؜R LĶÉu[ŻÆt(č¤Ņ`ƒ°µ”°a}QéPķ XÜkQV¢`X) 2 ‹{Čžæ1aĆRŲ°Ķ Ąā9a£°a(lŲf Xœ•(X!… ŪĢ0,Ī„ ¬Ā€mf÷Ąż£°aS·Õ}J‡€B6°ø3ö’•(V•äQ„C@!†`qµ}±É IDATgī’60¼Ē–…€ÅrĀFaĆqŽ [§n«’œP:l°ūÖmuæ}æŁS·Õž$' S£°`€å}aŹfO’“³sī0 … ŪČ:,ļ ēŲ쉒SĮŠ6l#·„å0acl †õąż÷`K(l`y X1·ö`Ūų»%,ĻJ¬Ų£K€5ówKXž X16l… ,Oa+fĀ€mćļ–°¼V¢ī[0L• ¶ XŽ6' SeĀ€m£°å)l`ÅĪ©ŪźųŅ!`¬DĮņ6°bĒ$yxé°F÷/&ąōŗ­ŖDa«ōŲŅ`Ī)&ą˜ģ–Ÿ XÆ.Öča„ĄDœ‘ģ6÷)¦źėJ€uØŪźŒ$÷+&āĢĄ ¬Ņߣ}ဩ3]Ć9=QŲĄ*UI¾¦tXƒ‡—rj¢°U³Ą60aĆ99QŲĄŖ}}é° Ī)‰ĀVķįu[=ŖtX1… ē 6ī«e- €©SŲĄpLŲĄšX‹`ź^:Lˆ3l`M¾¹n«SK‡€UØŪź”$§•ĪbĀÖä~I¾ætXėP0,6°F?\:¬ˆĀ†õ… ‡Ćź}iŻVué° – X³)Vąį„ĄÄ8ĆÖģūź¶ŗé0060,… ¬Ł}ćša¦GaĆ:©n«jOé°e¬E05 V•ä¤=Iī*¶Čź¶zfé0„ŗ­ī“䁄sĄ¼'ɝ„SĄ–łw„Ą@LץjœbĀÖļ9u[}cé0… ¬ĘÉ (ćWź¶ŖJ‡€%)l`5LŲ@!'É?(–ōˆŅ`¢LŲ@AĻÆŪźøŅ!` .&Ja=*ÉsK‡€%(l`5īć.QPÖĻ×mubé° … ¬Ęń&l ¬³“üDé0Æŗ­˜ääŅ9`¢60?S·Õ#K‡€9=¦t˜0… ŒĄ‰IžŠm¾Ų0O)&ģ… ŒĆ3“üxé0‡g–fĀFäWź¶zlé0£Æ.&La#rß$mŻV{J€#Łż ńģŅ9`ĀŽw[o—:ÉO–GaŗVĖ„ ŒŠóė¶zBép_W:LœĀFč„$T·Õ±„ƒĄĮź¶:1É·—Īē.Q0R_žä7J‡€CųŽ$'–gĀFģyu[żHépX:l… ŒÜ ź¶zvé$u[= É7•Ī[ąų=In)8¬ć’¼øn«G–Ł™®9®tŲĒļIņéŅ)€#:=ɹu[\:Ū«n«=Ižeé°%6°!¾$ɟķ¾H@ ߕäQ„CĄ–8Aa›ćŪ’üJél­Ÿ*¶ˆ Ų0?]·Õ’]:Ū„n«ÆNņōŅ9`‹(l`ż·ŗ­ž[:Ūaw-’×Jē€-£° T%ł½ŗ­~°t¶ĀOÄt ¬›Ā6T•äź¶śŅA˜®ŗ­•äł„sĄRŲĄŪ“äė¶śG„ƒ0=u[UI^˜ä~„³Ą:aO×ōw$¹„t`!{’üQŻV’°t&ē¹IžS:l©ć÷ģžƒ)Ų\Ē$ł“ŗ­¾Æt¦”n«‡ĘAĆPŅ1ū ›ė‹Ę–uL’?­ŪźŸ”Ą$ün’SJ‡€-v· ˜Žc“ü÷ŗ­ ĄĀvĻHüÖŅ9`ĖŻ„°éł¹ŗ­ž¤n«ćK`³ŌmõČ$æY:`¦ź'9Æn«ū—ĄfØŪź!I^ŸäōŅY60eĻNņ–ŗ­^4£W·Õ™Ł)kQ: Da“÷ų$×mõŌŅA§ŗ­NKņŚ$+ų+Q°˜äüŗ­¾»tĘ„n«“¼*ÉSJg`Ā¶Äż’üļŗ­~ĆaÄ$IŻV÷Irn’ŗtą^6°ežEvε±› °Åź¶:.ɋ’|Mé,Ą!Y‰‚-ōåI.­Ūź{J`żv˚?Iņm„³‡õ… ›O$Ł[2 °V§&yqŻV/ØŪź„ŅaXŗ­ĪIņę$ætąˆv ›®éoOņŃĀa€õū±$]·Õ£J`µź¶śĘ$—&łŠŅY€£śĀJT’|°X  ¤/KņĪŗ­žqé Æn«=u[żbvīuzé<ĄLīRŲIrJ’?©ŪźUu[}Qé0 £n«3“œ—äß&Łs”oĘć€Āęņb1€±ųę$ļÆŪźĒź¶ŖJ‡`qu[}evV ¾®t`nV¢€{9)É ’\X·ÕćJ‡`~u[żĖ$$yHé,ĄBī:væß(l€ż=#É»ź¶śå$’±kś;KąČź¶zz’’’¤.XŹ+QNrW©$Ą(äłIŽ^·ÕSK‡ąŠź¶zhŻV’3Ie LĮŻUß÷_ų]ŻV—'yL¹<ĄˆķMņGIžß®é?Y: IŻV'&łé$?•ä¾…ćĆ9÷ąĀę•I¾„\`|.ÉÆ&łõ®é?_: Ą6ڽAÄ÷'ł•$.ŽK¾­›;EGsb’_LryŻV?ąnRėU·ÕW%ykv¦Ÿ•50Mw\Ų8x˜ÕC²ó&įmu[=³t€)«ŪŖŖŪźź¶zU’ “|yéLĄJp—ØDaĢļļ&¹ n«—&ł7]Óū÷Ą@vĻØł$?žäq…ćės×ĮgŲ<,ÉGŠÅ6ŻŻIž<É蚾oJ‡ŲTu[="Éó’üP’Ó ĒÖļ.lö$ł|vnå °Ø>ÉK’üū®é/-`SŌmõœģLÓ|G’ƒ°¶ĒÆPŲ$IŻVļOņ„2y€ ze’_īšžāŅAĘØn«³“|O’Iņ„…ććšsŸa“ģÜ)Ja å[“|kŻVoČNqs~į<ÅÕmõ$ߝä{“<#¦i€}ęP…CUųŚ$_[·Õ%I~+É_vMGįLkS·Õ9Ł™¤łŽ$u’Ŗl"`Ä6ĄŚ=}÷ńŸė¶za’ßėšž£…3¬DŻVĻ=%ĶÓ¢¤fó™Caó¬$ē‰l£»“¼<Éo'yC×ō/%€ ²{ͳ’<{÷×Ē lŖÆ:Taóą$/“Ųr—%łoIžØkś›J‡8šŻ³hž•{JšĒ LÅļUŲ$IŻVŸJņĄõēH’ÜšäÜ$šä5]ÓßY8@ź¶Ŗ’<";‡ļ+hU20Y=\asn’o_€{łt’e§¼y‹•)`ź¶ŗO’/Iņ”żOJrJÉ\ĄÖ8ép…ĶĻ%yžśóŃUIžW’?ķšž}„ĆÓP·Õ™Ł)džœ{Ź™/Nr؛“¬Ś]]ÓwøĀę’œ·žL3{O’—%yE’·›¼§n«=I’õ„żÜżõžåŅÜĖõ]ӟyøĀę“$7Ä-ē€ĶpM’Wī>^Ū5ż-…ókT·Õ©IĪŽļń ģœ5³Æ˜yD’Š˜Ļ{ŗ¦ņ! ›$©Ūź²8įŲžU’›ė¶z]’W$yu×ō×Mpu[=#É÷'ł¾$÷/Žäņ}’0Kaó†`³’ä{v}ŻVoĻĪäĶ’ģšžCE“[­n«S“ÉO'9”pĀßģ’›=³üD×ō—g擊`Iē$łļIŽ[·••[`.u[=%ÉŪ³SŲ(k˜Šł ›]/8<>ÉKź¶ŗøn«g—Œ[ŻVĒķNē½5ɓ Ē€”-\؜;pŲēéIŽT·Õ«w?98@ŻVOĪNQó IŽ+Vį€Āf¦C‡“¤n«c’\›ä+ūōIž ÉOtM’łŅa€²ź¶:6ÉĻdgżIQĄ”=ØkśOķūĶĢ6»‡B¾z%‘ąU’ē&y{ŻVV`‹Õmur’W%ł„(k˜¶k÷/k’łV¢kQ¬Ļć“\R·Õ?+Xæŗ­˜äü$__8 ¬ĆE’Į¼…ĶyIī& Õ}’üvŻV/©Ūźž„ĆėQ·Õ£“üu’/+Öd¹Ā¦kś›’¼y°80›ļJņīŗ­¾Ŗt`µź¶śņģ”5,Öčƒ’`Ž ›ÄZeœ“äüŗ­žW:°u[}SvÖ Ī,Öé–$—ü‡‹6/_> ,ä˜$æU·Õ– «n«”÷™'–ĪkÖķŽčés6]Ó8Éū‰‹łķŗ­~Øt`u[=+I›äŲĀQ „{_“,6a“X‹ ¬*Éļ×mõż„ƒĖ©ŪźaI^e Ūė^ē×$‹6Ö¢(mO’?¬Ūź”,¦n«ū%yY’3Jg€BīLrÉ”¾°hasI’kŽĆ8&ɟŌmõŻ„ƒ łĆ$O) zG×ōŸ?Ō*lŗ¦ß›ä•KE€a›äĻė¶śŚŅA€ŁÕmõ³I¾Æt(ģėPÉā6‰µ(Ęćø$mŻV§–]ŻVß–äł„sĄœø/,SŲ¼6ÉķKü< é”IžK饑ÕmõØ$šåއĄܝĆÜ!*Yā…²kśĻ%yć¢?+šƒu[}K饿ē$§”#pi×ō7ī‹Ė~²a- €±yaŻV§•ÜŪīYSßQ:ŒÄGś¢Ā€©yp’ß,8PŻVĒÄŚ"ģļü#}q©Ā¦kś%¹t™kĄ üĄī”¦ĄxüÓ$_Z:ŒÄŽįQÉ0‡½;Ą5`hæ_·•s2`vļąę®PpwuMӑ¾aˆĀĘZcō $Mé@’äē“œY:ŒČĻÆI†)lŽ™ä\†ö£„Ą¶«ŪźŃIžyé02ēķ–.lŗ¦ļcŹ€qzÜī]i€r~5Éń„CĄˆõüšd˜ ›DaĄxż³Ņ`[ÕmuN’ļ,Fę=]Óßx“oŖ°yC’Ļt-ŅwÖmõŠŅ!`K5īż&LÅł³|Ó / ]Óߖä¼!®;&É—Ū¦n«*É–Ī#tŌ‡“a?ńųóÆCznŻVĒ•[ęk’<¢t™>ɛgłĘ! ›—'¹eĄėĄPĪNņŻ„CĄ–ł'„Ą½·kśfłĘĮ ›®éoMņ²”®ū®Ņ`[ŌmuZ”¤p(ošõ‡>ī |=ŹÓJ€-ņ’ܧt”™ļ²=taóŚ$×|MĀ#ź¶:½tŲÖ”ąŽnȌ'6]ÓߕäÅC^ōŌŅ`źź¶zJ’/+FčÜŻŽd&COŲ$ɟ­ąš0… ¬ž³kąŠ^:Ļ7Æ¢°¹(ÉÕ+ø.,Ka«÷U„Ą}.;ĒČĢlšĀ¦kś>ɟ}]€ƒ‡a…ź¶:6ÉÓKē€zu×ō·Ķ󫘰IÜ- €qz`ŻVē”öeIīW:ŒŠK꿁•6]Ó_šä²U\–d- Vē„ĄŻ‘ä•óžŠŖ&l‡0N_^:L˜ókąŽŽŠ5żĶóžŠ* kQŒŃ£J€ SŲĄ½Ķ½•¬°°éšžƒI޾ŖėĄ‚V:LQŻVIrVé02{“œ»Č®rĀ&1eĄų(l`5Lץ½]Ō5żµ‹üąŖ ›æČN›cńĄŗ­N(&Ha÷öŅEp„…M×ōOņęU>Ģ©JāÖŽ0<… ÜŪ8 ›]Ö¢kQ0 ŗ­Ž‰½ą`ļ蚾ŖEx…Ķ‹“ܹ†ē€Y)l`Xg'9¦t™æ\ę‡W^ŲtMC’óVż<0‡/*&ęĮ„ĄČܙ¤]ę똰I¬E0.&l`X)Fęe‹ŽjŸu6•äskz.8… Ė„ č÷—½ĄZ ›®é?—ä×ń\0+Q0,6p%yòYׄM’¼`ĻGrNŻVUé0! øĒļwMß/{‘µ6]Ó ÉėÖõ|pĒ'yPé0!V¢`Ē҇ ļ³Ī ›$łÆk~>8kQ06°ć„Ė6¼Ļŗ ›Weg— Jsš0 Ē„ ģXś°į}ÖZŲtMæ7Éo­ó9ą060€ŗ­ī—ä“Ņ9`®HņĘ”.¶ī ›$łIn)š¼°?… Ćt ģä°į}Ö^ŲtMs:€–ą Ę„Ąܑ»Ž6ÉĪZŌ`­,Ą„ ćųŅ`^Ś5żuC^°HaÓ5żeIĪ+ńܰKaĆ8®tßś‚„&l·ų ¬Sź¶:µt˜… ŪīƒIĪś¢% ›×$¹¼ąó€)XžĀ€m÷›C6¼O±Āf÷?Œ[|P’Ā–§°`›}<ɬāĀ%'l’”o.œ€ķåNQ°<… Ūģ’ėšžöU\øhaÓ5żgćߔcĀ–§°`[}<É WuńŅ6Iņ‚øÅ7e(l`y ¶Õʦk’6]Ó_‘äU„s°•Z:L€Ā€m“Ņéšd…Ķ®_+€­t’Ņ`n+ XétM2’¦kś ’œ[:[ē”Ņ`>[:¬ŁŹ§k’‘6»~*ɝ„C°UN-&@aĄ¶YłtM2¢Ā¦kśĖ“üNél•ė¶Ķk!l(… Ūd-Ó5Ɉ ›]æ˜äĘŅ!ŲU’“K‡€ wsé°Fk™®IFVŲtMC’_.€­b- –cĀ€m±¶éšdd…Ķ®ßJrEél Ćr6l‹µM×$#,lŗ¦æ#Éæ)€­aĀ–sKé°k®IFXŲ$I×ō/IņęŅ9Ų &l` ]Óߝäó„sĄŠżĢ:§k’‘6»~2I_:“§°å]S:¬Š›ŗ¦’“u?éh ›®éߞä–ĪĄäY‰‚å]U:¬ČI~“ď¶°Łõ³In-€I3aĖSŲ0U’±kśĖJ<ńØ ›®é?–ä×Kē`Ņ6°<… StE’’PźÉG]ŲģśÕ$Ÿ,€É²ĖSŲ0E’¬kśŪJ=łč ›®éoÉĪj椰`jž¼kś×• 0śĀ&Iŗ¦o“¼“t&és„Ą(l˜’›’üĖŅ!6¢°ŁõCI>Z:“sKé0W'éK‡€ül×ōŸ*bc ›®éoLņ“ÜU: “bĀ–Ō5żķqę ÓšÖ$æ[:D²A…M’tM’×I~”tų’Ū»óXĶŹś€ć߃"•ŗZ‘¦­šj 5•†ō(85Z0ÕŅő6HįėRŃJ憖`*‹ ©µcA”S—Ö%AY†Ķ²“O[”%`7†mFd˜żéē½ĢåĪpēŽ™÷½æ÷¼ēūINŽ÷ŽÜ/!™ūęwžó<’&Š+l¤įųat€$IŪh=šīœŹ†ččŲĄfą$ąŅčIŅÄp…4ߏ$i}6§ņƒčˆ)Ų &]Ė£[$IĮ6Ņp\ IŅ6X1]ē6ƒĶĮĶķ$IŪĪ6ŅpøĀF’ŌU끃s*cu#Ɠ€œŹÅĄ§£;$I7V昄®Ź©ÜÜŻ!IŅVųxNå?£#fźģĄfąhą¢#$Ię ix\e#IźšsOEGlN§69•µ“G}?Ż"Iź,WŲHĆć>6’¤.ł1phNe,·[éōĄ §ņą]Ń’¤Īr`# +l$I]± XœSy0:ä©t~`Sł&pFt‡$©“|$Jž ¬Ž$iޟS¹>:b61°ų0v›I’ĘŚŗœŹźčiRäT®Šī$i šœŹ™Ń[21›œŹ*ą`¬'d’¤±ņpt€4–FH’4‹€÷FGĢÅÄ lą‰»:onn‘$u‚æ/¤įs`#IWÓī[óxtČ\LŌĄ §²Ųø;ŗE’4ön‰&MNåą§Ń’$mĘa9•Ū¢#ęjā6šÄÉQūD·H’ĘŚ­ŃŅ„r•$iܜšS9;:b>&r`S¹ x šXt‹$il9°‘Fć‚čI’¦¹ųhtÄ|MģĄ §r5°—”$mži4.:±?€$iāż8 §².:d¾&z`S¹8 (Ń-’¤±²7–Fb°™ćyŃ’¤Ž»Ų/§ņ`tČ֘ų @NåkĄ‘Ń’¤±r{ļ“HņÅčIRÆŻ¼1§²":dkõb`Sł,š‰čIŅŲø::@šp’ü,:B’ŌKwoČ©tśōčŽ lr*Ē’Ż!I WDH“,§²8+ŗC’Ō;÷Ņk:Ó W›#€ÆGGH’Ā] õĄYĄ†čIRoÜOūŌmŃ!ĆŠ»ĶąnĻĮĄæF·H’ĀܑSY!MŗœŹĻi’$iŌ¢Ż`ųęča鯥 §²žöäØĻE·H’B\ õˆ›K’Fm%šĒ9•ė¢C†©—€œJÉ©¼ųdt‹$iĮ] õČw€åŃ’¤‰µ 8 §2qJōv`3%§r4šŃčIŅ‚ŗ<:@ź‹œŹąSŃ’¤‰“xkNå²čQ迥 §r š^ D·H’FŹ]ŃRĻ,ĮU6’¤įz80§rAtČØ8°Č©|8XŻ"I©ÆDH}“Sy WŁH’†ē`QNå;Ń!£äĄfšœŹW·«£[$I#±ųft„ŌS®²‘$ ĆõĄŽ9•k¢CFĶĶ ƒ ݟŠī2-Iš,Ks*DGH}ä*IŅœ ģ“SY²ŲlFNå»Ą~“ēøK’&‡CI±\e#IŚZŸnō‚›§08ģõĄŠčIŅP<,Žślš!ū¤čIR§¬Ī©SéÕAAlf‘S¹xąi"’Ō}_/,)Ö?7FGH’:į>ąõ9•ÆE‡Dp`³9•[}€;¢[$I[m pJt„$Č©¬Ž ōź.©$iŽn Ż\8G‡Dq`39•ŸÆ® N‘$m/ęTīŒŽŌ|ų>=ŗC’4¶Ī^›SłytH$6s”S¹X\Ż"Iš—5Ą‰Ń’6ń1ąŽčIŅŲłšē9•G£C¢U„_{öl³ŗ©¶Ī‰n‘$ĶɒœŹŃ’6U7Õ_’Ż!I ?Ž—Sńˆ6[©nŖ£¢;$I³Z ¼,§²,:DŅęÕMu°t‡$)ĢZąTą„>Ł=>µ•r*Žlˆn‘$=„3ÖHcļ]ĄżŃ’¤WÆĪ©å°fSl¶ANåsĄĄŖčIŅ&–ĒGGHšŻ`CɃń&˜$õÉ/wūęTnŠŽW>5uSķ œ˜SY2īŲ IŻTæ \ģŻ"IāĖ9•C£#$Ķ]ŻTŪK7E·H’F⿁äT®Œé 6CT7ÕnĄ…ĄžŃ-’Ōcw{ęTŠ‘4?uS½øųµčIŅŠüųxNåģ萮q›!Ź©Üģ \œ"I}U€w8¬‘ŗ)§r?°˜ö„7IR·Ż ¼ŲĆaĶÖq…ĶŌMµšeŚ ‰%I gINåˆčIŪ¦nŖƒi?KUŃ-’¤y{88-§²2:¦Ė،HŻTpščIź‰ļ‹<Rš uSż-°$ŗC’4gk€ÓOø”šp8°±ŗ©>D;]ō‘$ĪĄkr*Ė£C$ OŻT¦ż%I_g§ęTīŽŽ™$l@ŻTgψn‘¤ “‚vXs{tˆ¤į«›źą˜čIŅ&V’üsNåĮč˜IäĄfŌMUßv‹n‘¤ ²x}NåščI£S7ÕiĄ‘Ń’$~|ųRNåńč˜IęĄfÕMµ+š ąƒS$i¬ž4§rAtˆ¤Ńģ x:šĪčIź±€“oäTÖGĒō›V7ÕӁ“€F·HRĒžS9+:BŅĀ©›źxąøčIź‘õĄyĄēs*—DĒō› uS½ ųšģčI꘵Ą»ÖHżT7Õ_gāŽ€’4JwÓž]ū…œŹ²č˜¾r`ØnŖWgƈn‘¤ŽxxkNåņčIqź¦Z|x^t‹$M\ |87§².ø§÷Ų«›ź9@üEpŠ$»oĪ©Ü")^ŻTæ,^Ż"I÷KŚSOϩܣ،‰ŗ©>|xZt‹$”«i7žEtˆ¤ńQ7ÕĪ“+mö‰n‘¤ŽYI;ōž&°4§²*øG›įĄfŒŌMµ°Ų;ŗE’ĘČׁ”SY"iüŌMõ4ąhąąéĮ9’4Ī.`ćę±ąm›1S7ÕvĄß'ĻĪ‘¤Hk€ć“rņ—•¤ŁÕMµ7šUąåŃ-’4F.¤ҜŸSYÜ£yp`3¦K|OŖąIZh’K{l÷ĶŃ!’ŗ£nŖg§ļŠn‘¤@«h‡4ßĪĖ©<Ü£­äĄfĢÕMõŚĒ¤^Ż"I ąqąXą“œŹśčIŻT7Õ[€/»F·HŅY \D»’ę¼œŹ#Į=60x6ū}Ą ĄNĮ9’4*WļštIĆP7Õ.Ą?‡ć”’&ÓąbŚ!͹9•‡ƒ{4dl:¤nŖŸŠn‘¤!z8 Xā^5’†­nŖ=€OūG·HҬ¾K;¤9'§ņPpFȁMÕMõ{ĄGÅxĒHRw­ž 8&§ņ³čI“­nŖżi7{D·HŅ<¬®.\ßĖ©<›¤…āĄ¦Ćź¦zšaąP`‡ąIš«B{WčųœŹ­Ń1’ścš˜łį“™æ(8G’6§7Ńg.žĖU4żåĄfŌMõ«Ąßļžœ#I³ł6p\NåĘčIż58Mź0ąļšpIńnc㠚Ės*+‚{4&ŲLŗ©ž |Ų%8G’¦¬£ԜœS¹6:F’¦ŌMUoŽŽœ#©?–±q@sYNåĪą)6ØnŖi—ū~ųõŲI=vpš…œŹ=Ń1’4›ĮęÄGožœ#i²üøœĮcNžˆ©¹r`3ĮwŃ~šX <7¶HRO\ ,”=^r]tŒ$ĶGŻT; ųKą÷ck$uŠ:ąfŚ‚ƾÜčI˜Ślz¢nŖh—ü¾}šź&Œ†ep p>š­œŹ‚{$i(ź¦ś ąmĄĄ^Į9’ĘĻŚ ‚Æcć€ę†œŹźŠ*M 6=4Ųėf1ķšfPÅIź ‡Kh‡4ęT–÷HŅHÕMõ›l޼:8GŅĀ[ ÜČĘĮĢu“+gքVi¢9°é¹ŗ©^4ø^œ#i¼ŻN; 9ŸöˆÉµĮ=’bšłišŗĮõŠŲ"IC¶ ų!3×7ūŁG ́žP7ՋiOHxćązql‘¤`ė€+i4K}ŌI’6ÆnŖ]€}Ł8Ąy°]h”¤¹Ųü ų?ąGĄõ“ƙ[܇O楁žRŻTÆžˆvx³Ų)¶H҈­n”½“tpqNå”Ų$Iźžŗ©v^¼dpķ>ķżŌå~‚ҹv(3óŗĆżf4ĪŲhNź¦z:°7Wßü°}h”¤mq/ķRߦ½ŽźR_IZƒU9O5ŠŁŲ Ų1,PźžGŲüPę6o@©«Ųh« Nś]Śö¢Ż|oą‘]’61µję‡LŠäTV„VI’¶ØnŖ°é@g7``ēiÆ®‚Vl ])s°Œvo½'39•{Ū¤‘p`£”©›źĄž“ƛ©AĪžøäWµ•ĄŻÓ®ŸÓžbąŖIꁺ©¶§Ü̼vyŠļw4^„Ä̼īžöž^÷•Qß8°ŃH >@üķę{/qķ˜&uĮjąž<ŒŁär™Æ$i¾ź¦z›q~xķŠ-½>7VÖģ ššKąŲ™zæ#ķŠėgN»v˜ć{··x€vš2uĶåėr*"‚„IįĄFci°2g×ĮõĀiļg~żBŚå¾ž2Ÿ›õĄ*Ś_¼kim^;ćż¶~oź/•jŚæwsļēś½Qü­3’[ęó:żż*f br*!I’¶É`04s3õõv“æŪ·ō:—ŸõŸ©h?#m˜qĶüް~f’쵓C—•[ž?%iŲh"ŌMõ\ął“wp¦®gĪųz¶ļĻē{…vš±nš:óŚÜ÷ēó³ėi…Y5ø¦æŸķŚāĻłÜÆ$I’$uĆ’ĘK}8EģålIEND®B`‚meson-0.45.1/graphics/meson_logo.svg0000644000175000017500000004564012650745767021032 0ustar jpakkanejpakkane00000000000000 image/svg+xml meson-0.45.1/graphics/wrap_logo.svg0000644000175000017500000001056212650745767020655 0ustar jpakkanejpakkane00000000000000 image/svg+xml meson-0.45.1/setup.py0000644000175000017500000000777413251072277016053 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 # Copyright 2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import os import sys from mesonbuild.coredata import version if sys.version_info < (3, 5, 0): print('Tried to install with an unsupported version of Python. ' 'Meson requires Python 3.5.0 or greater') sys.exit(1) # We need to support Python installations that have nothing but the basic # Python installation. Use setuptools when possible and fall back to # plain distutils when setuptools is not available. try: from setuptools import setup from setuptools.command.install_scripts import install_scripts as orig except ImportError: from distutils.core import setup from distutils.command.install_scripts import install_scripts as orig class install_scripts(orig): def run(self): if sys.platform == 'win32': super().run() return if not self.skip_build: self.run_command('build_scripts') self.outfiles = [] if not self.dry_run: self.mkpath(self.install_dir) # We want the files to be installed without a suffix on Unix for infile in self.get_inputs(): infile = os.path.basename(infile) in_built = os.path.join(self.build_dir, infile) in_stripped = infile[:-3] if infile.endswith('.py') else infile outfile = os.path.join(self.install_dir, in_stripped) # NOTE: Mode is preserved by default self.copy_file(in_built, outfile) self.outfiles.append(outfile) setup(name='meson', version=version, description='A high performance build system', author='Jussi Pakkanen', author_email='jpakkane@gmail.com', url='http://mesonbuild.com', license=' Apache License, Version 2.0', python_requires='>=3.5', packages=['mesonbuild', 'mesonbuild.backend', 'mesonbuild.compilers', 'mesonbuild.dependencies', 'mesonbuild.modules', 'mesonbuild.scripts', 'mesonbuild.wrap'], scripts=['meson.py', 'mesonconf.py', 'mesontest.py', 'mesonintrospect.py', 'wraptool.py'], cmdclass={'install_scripts': install_scripts}, data_files=[('share/man/man1', ['man/meson.1', 'man/mesonconf.1', 'man/mesonintrospect.1', 'man/mesontest.1', 'man/wraptool.1'])], classifiers=['Development Status :: 5 - Production/Stable', 'Environment :: Console', 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Natural Language :: English', 'Operating System :: MacOS :: MacOS X', 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX :: BSD', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python :: 3 :: Only', 'Topic :: Software Development :: Build Tools', ], long_description='''Meson is a cross-platform build system designed to be both as fast and as user friendly as possible. It supports many languages and compilers, including GCC, Clang and Visual Studio. Its build definitions are written in a simple non-turing complete DSL.''') meson-0.45.1/test cases/0000755000175000017500000000000013254552745016366 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/0000755000175000017500000000000013254552745020060 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/11 vs module defs generated custom target/0000755000175000017500000000000013254552751027540 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/11 vs module defs generated custom target/meson.build0000644000175000017500000000044613111335362031673 0ustar jpakkanejpakkane00000000000000project('generated_dll_module_defs', 'c') if meson.backend().startswith('vs') # FIXME: Broken on the VS backends error('MESON_SKIP_TEST see https://github.com/mesonbuild/meson/issues/1799') endif subdir('subdir') exe = executable('prog', 'prog.c', link_with : shlib) test('runtest', exe) meson-0.45.1/test cases/windows/11 vs module defs generated custom target/subdir/0000755000175000017500000000000013254552751031030 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/11 vs module defs generated custom target/subdir/meson.build0000644000175000017500000000033613111335362033161 0ustar jpakkanejpakkane00000000000000make_def = find_program('make_def.py') def_file = custom_target('gen_def', command: [make_def, '@OUTPUT@'], output: 'somedll.def') shlib = shared_library('somedll', 'somedll.c', vs_module_defs: def_file) meson-0.45.1/test cases/windows/11 vs module defs generated custom target/subdir/make_def.py0000755000175000017500000000021313111335362033121 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys with open(sys.argv[1], 'w') as f: print('EXPORTS', file=f) print(' somedllfunc', file=f) meson-0.45.1/test cases/windows/11 vs module defs generated custom target/subdir/somedll.c0000644000175000017500000000004513111335362032617 0ustar jpakkanejpakkane00000000000000int somedllfunc() { return 42; } meson-0.45.1/test cases/windows/11 vs module defs generated custom target/prog.c0000644000175000017500000000014013111335362030633 0ustar jpakkanejpakkane00000000000000int somedllfunc(); int main(int argc, char **argv) { return somedllfunc() == 42 ? 0 : 1; } meson-0.45.1/test cases/windows/8 dll versioning/0000755000175000017500000000000013254552752023125 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/8 dll versioning/installed_files.txt0000644000175000017500000000133513134457413027024 0ustar jpakkanejpakkane00000000000000?msvc:usr/bin/some-0.dll ?msvc:usr/bin/some-0.pdb ?msvc:usr/lib/some.lib ?msvc:usr/bin/noversion.dll ?msvc:usr/bin/noversion.pdb ?msvc:usr/lib/noversion.lib ?msvc:usr/bin/onlyversion-1.dll ?msvc:usr/lib/onlyversion.lib ?msvc:usr/bin/onlysoversion-5.dll ?msvc:usr/lib/onlysoversion.lib ?msvc:usr/libexec/customdir.dll ?msvc:usr/libexec/customdir.lib ?msvc:usr/lib/module.dll ?gcc:usr/bin/?libsome-0.dll ?gcc:usr/lib/libsome.dll.a ?gcc:usr/bin/?libnoversion.dll ?gcc:usr/lib/libnoversion.dll.a ?gcc:usr/bin/?libonlyversion-1.dll ?gcc:usr/lib/libonlyversion.dll.a ?gcc:usr/bin/?libonlysoversion-5.dll ?gcc:usr/lib/libonlysoversion.dll.a ?gcc:usr/libexec/?libcustomdir.dll ?gcc:usr/libexec/libcustomdir.dll.a ?gcc:usr/lib/?libmodule.dll meson-0.45.1/test cases/windows/8 dll versioning/lib.c0000644000175000017500000000011313134457413024025 0ustar jpakkanejpakkane00000000000000#ifdef _WIN32 __declspec(dllexport) #endif int myFunc() { return 55; } meson-0.45.1/test cases/windows/8 dll versioning/meson.build0000644000175000017500000000317313134457413025266 0ustar jpakkanejpakkane00000000000000project('msvc dll versioning', 'c') cc = meson.get_compiler('c') # Test that we create correctly-named dll and import lib files, # and also install them in the right place some = shared_library('some', 'lib.c', version : '1.2.3', soversion : '0', install : true) noversion = shared_library('noversion', 'lib.c', install : true) onlyversion = shared_library('onlyversion', 'lib.c', version : '1.4.5', install : true) onlysoversion = shared_library('onlysoversion', 'lib.c', # Also test that int soversion is acceptable soversion : 5, install : true) # Hack to make the executables below depend on the shared libraries above # without actually adding them as `link_with` dependencies since we want to try # linking to them with -lfoo linker arguments. cp = find_program('copyfile.py') out = custom_target('library-dependency-hack', input : 'exe.orig.c', output : 'exe.c', depends : [some, noversion, onlyversion, onlysoversion], command : [cp, '@INPUT@', '@OUTPUT@']) # Manually test if the linker can find the above libraries # i.e., whether they were generated with the right naming scheme test('manually linked 1', executable('manuallink1', out, link_args : ['-L.', '-lsome'])) test('manually linked 2', executable('manuallink2', out, link_args : ['-L.', '-lnoversion'])) test('manually linked 3', executable('manuallink3', out, link_args : ['-L.', '-lonlyversion'])) test('manually linked 4', executable('manuallink4', out, link_args : ['-L.', '-lonlysoversion'])) shared_library('customdir', 'lib.c', install : true, install_dir : get_option('libexecdir')) shared_module('module', 'lib.c', install : true) meson-0.45.1/test cases/windows/8 dll versioning/copyfile.py0000644000175000017500000000013413134457413025302 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys import shutil shutil.copyfile(sys.argv[1], sys.argv[2]) meson-0.45.1/test cases/windows/8 dll versioning/exe.orig.c0000644000175000017500000000015213134457413025002 0ustar jpakkanejpakkane00000000000000int myFunc (void); int main (int argc, char *argv[]) { if (myFunc() == 55) return 0; return 1; } meson-0.45.1/test cases/windows/10 vs module defs generated/0000755000175000017500000000000013254552751024775 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/10 vs module defs generated/meson.build0000644000175000017500000000020713105362433027125 0ustar jpakkanejpakkane00000000000000project('generated_dll_module_defs', 'c') subdir('subdir') exe = executable('prog', 'prog.c', link_with : shlib) test('runtest', exe) meson-0.45.1/test cases/windows/10 vs module defs generated/subdir/0000755000175000017500000000000013254552751026265 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/10 vs module defs generated/subdir/somedll.def.in0000644000175000017500000000002313074426732031003 0ustar jpakkanejpakkane00000000000000EXPORTS @func@ meson-0.45.1/test cases/windows/10 vs module defs generated/subdir/meson.build0000644000175000017500000000036013074426732030425 0ustar jpakkanejpakkane00000000000000conf = configuration_data() conf.set('func', 'somedllfunc') def_file = configure_file( input: 'somedll.def.in', output: 'somedll.def', configuration : conf, ) shlib = shared_library('somedll', 'somedll.c', vs_module_defs : def_file) meson-0.45.1/test cases/windows/10 vs module defs generated/subdir/somedll.c0000644000175000017500000000004513105362433030056 0ustar jpakkanejpakkane00000000000000int somedllfunc() { return 42; } meson-0.45.1/test cases/windows/10 vs module defs generated/prog.c0000644000175000017500000000014013074426732026102 0ustar jpakkanejpakkane00000000000000int somedllfunc(); int main(int argc, char **argv) { return somedllfunc() == 42 ? 0 : 1; } meson-0.45.1/test cases/windows/1 basic/0000755000175000017500000000000013254552751021257 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/1 basic/installed_files.txt0000644000175000017500000000004213057037357025156 0ustar jpakkanejpakkane00000000000000usr/bin/prog.exe usr/bin/prog.pdb meson-0.45.1/test cases/windows/1 basic/meson.build0000644000175000017500000000014313057037357023420 0ustar jpakkanejpakkane00000000000000project('wintest', 'c') prog = executable('prog', 'prog.c', install : true) test('wintest', prog) meson-0.45.1/test cases/windows/1 basic/prog.c0000644000175000017500000000011013134457406022360 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/windows/12 exe implib/0000755000175000017500000000000013254552751022276 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/12 exe implib/installed_files.txt0000644000175000017500000000025613134457413026177 0ustar jpakkanejpakkane00000000000000usr/bin/prog.exe usr/bin/prog.pdb usr/bin/prog2.exe usr/bin/prog2.pdb ?gcc:usr/lib/libprog.exe.a ?gcc:usr/lib/libburble.a ?msvc:usr/lib/prog.exe.lib ?msvc:usr/lib/burble.lib meson-0.45.1/test cases/windows/12 exe implib/meson.build0000644000175000017500000000045213134457413024435 0ustar jpakkanejpakkane00000000000000project('wintest', 'c') # Test that we can produce an implib for an executable on Windows, and that it's # name can be set, and that it is installed along with the executable executable('prog', 'prog.c', install: true, implib: true) executable('prog2', 'prog.c', install: true, implib: 'burble') meson-0.45.1/test cases/windows/12 exe implib/prog.c0000644000175000017500000000013713134457413023406 0ustar jpakkanejpakkane00000000000000#include int __declspec(dllexport) main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/windows/2 winmain/0000755000175000017500000000000013254552752021642 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/2 winmain/meson.build0000644000175000017500000000014112650745767024011 0ustar jpakkanejpakkane00000000000000project('winmain', 'c') exe = executable('prog', 'prog.c', gui_app : true) test('winmain', exe) meson-0.45.1/test cases/windows/2 winmain/prog.c0000644000175000017500000000023412650745767022765 0ustar jpakkanejpakkane00000000000000#include int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { return 0; } meson-0.45.1/test cases/windows/4 winmaincpp/0000755000175000017500000000000013254552752022347 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/4 winmaincpp/meson.build0000644000175000017500000000015312650745767024521 0ustar jpakkanejpakkane00000000000000project('winmaincpp', 'cpp') exe = executable('prog', 'prog.cpp', gui_app : true) test('winmaincpp', exe) meson-0.45.1/test cases/windows/4 winmaincpp/prog.cpp0000644000175000017500000000025012650745767024030 0ustar jpakkanejpakkane00000000000000#include class Foo; int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { return 0; } meson-0.45.1/test cases/windows/3 cpp/0000755000175000017500000000000013254552752020763 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/3 cpp/meson.build0000644000175000017500000000012312650745767023132 0ustar jpakkanejpakkane00000000000000project('wincpp', 'cpp') exe = executable('prog', 'prog.cpp') test('wincpp', exe) meson-0.45.1/test cases/windows/3 cpp/prog.cpp0000644000175000017500000000012312650745767022443 0ustar jpakkanejpakkane00000000000000#include class Foo; int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/windows/13 resources with custom targets/0000755000175000017500000000000013254552751026154 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/13 resources with custom targets/meson.build0000644000175000017500000000351613243342167030317 0ustar jpakkanejpakkane00000000000000project('winmain', 'c') # MinGW windres has a bug due to which it doesn't parse args with space properly: # https://github.com/mesonbuild/meson/pull/1346 # https://sourceware.org/bugzilla/show_bug.cgi?id=4933 if meson.get_compiler('c').get_id() == 'gcc' and host_machine.system() == 'windows' # Construct build_to_src and skip this test if it has spaces # because then the -I flag to windres will also have spaces # and we know the test will fail src_parts = meson.source_root().split('/') build_parts = meson.build_root().split('/') # Get the common path (which might just be '/' or 'C:/') common = [] done = false count = 0 if src_parts.length() > build_parts.length() parts = build_parts other = src_parts else parts = src_parts other = build_parts endif foreach part : parts if not done and part == other.get(count) common += [part] else done = true endif count += 1 endforeach # Create path components to go down from the build root to the common path count = 0 rel = build_parts foreach build : build_parts if count < build_parts.length() - common.length() rel += ['..'] endif count += 1 endforeach # Create path components to go up from the common path to the build root count = 0 foreach src : src_parts if count >= common.length() rel += [src] endif count += 1 endforeach build_to_src = '/'.join(rel) if build_to_src.contains(' ') message('build_to_src is: ' + build_to_src) error('MESON_SKIP_TEST build_to_src has spaces') endif # Welcome to the end of this conditional. # We hope you never have to implement something like this. endif subdir('res') foreach id : [0, 1, 2] exe = executable('prog_@0@'.format(id), 'prog.c', res[id], gui_app : true) test('winmain_@0@'.format(id), exe) endforeach meson-0.45.1/test cases/windows/13 resources with custom targets/res/0000755000175000017500000000000013254552751026745 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/13 resources with custom targets/res/myres.rc.in0000644000175000017500000000004513243342167031032 0ustar jpakkanejpakkane00000000000000#include 1 ICON "{icon}" meson-0.45.1/test cases/windows/13 resources with custom targets/res/myres_static.rc0000644000175000017500000000005113243342167031771 0ustar jpakkanejpakkane00000000000000#include 1 ICON "sample.ico" meson-0.45.1/test cases/windows/13 resources with custom targets/res/sample.ico0000644000175000017500000002267613243342167030733 0ustar jpakkanejpakkane0000000000000000 Ø%(0` ’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåóåóåóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåóåóåóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåóåóåóåóåóåó åó åóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåóåó åóåóåóåóåóåóåó åó åóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åóåó#åó+åó/åó1åó-åó%åóåóåóåó åóåó’’’’’’’’’’’’’’’’’’’’’åóåóåó åóåóåóåóåó"åó&åó(åó)åó&åó!åóåóåóåó åóåó’’’’’’’’’’’’’’’’’’åóåó åóåó*åó<åóIåóQåóQåóKåóCåó:åó.åó&åóåóåó åóåó’’’’’’’’’’’’åóåóåóåóåó&åó.åó0åó7åó<åóCåóFåóEåóBåó;åó3åó*åó!åóåóåóåó’’’’’’’’’’’’åóåóåóåó*åó@åóVåófåókåógåóaåóXåóOåóFåó<åó3åó(åóåóåóåó’’’’’’’’’åóåóåó#åó4åóDåóLåóQåóVåóXåó[åó^åó]åóZåóRåóMåóCåó8åó-åó åóåó åó’’’’’’’’’åóåóåó$åó<åóVåójåóxåóyåóvåómåóbåó\åóWåóQåóHåó?åó0åó"åóåóåó’’’’’’åóåó"åó9åóNåóbåójåólåójåóiåógåóhåógåódåóaåóZåóWåóMåóBåó4åó'åóåó åó’’’åóåóåóåó0åóIåóbåóuåó|åóxåóråóeåó^åó[åó[åó^åó^åóXåóKåó6åó#åóåó’’’’’’åóåó.åóKåóhåó{åó€åóåósåónåógåóeåódåóaåó_åócåóaåó_åóYåóJåó:åó(åóåó åóåóåó åóåó7åóUåójåóuåózåónåócåóWåóPåóPåóVåóbåójåójåó`åóMåó4åóåó åó’’’åóåó7åóYåówåó‰åóˆåó‚åóqåóaåóWåóUåóSåóTåóUåóZåó`åófåóeåó^åóPåó>åó*åóåóåóåóåó åó?åóXåójåóråómåó]åóJåó>åó8åó;åóJåó_åómåótåóqåó_åóCåó(åóåó’’’åóåó:åó_åó~åóŒåó‰åó~åófåóQåó?åó7åó7åó:åó?åóJåóVåóbåójåókåóbåóQåó8åó"åóåó åóåó"åó>åóVåógåólåócåóNåó7åó(åóåó(åó:åóRåóiåóyåóxåóiåóOåó1åóåó ’’’åóåó<åóaåózåó†åóƒåóqåóXåó;åó(åóåóåóåó'åó2åóCåóSåódåónåójåó]åóFåó,åóåó åó åóåó9åóQåódåófåó[åóGåó-åóåó åóåó(åóDåóaåóuåó|åóqåó[åó>åó"åó åóåóåó9åó]åóuåóåóyåófåóDåó+åóåó åó åó åóåó åó-åóDåóYåóhåókåócåóMåó5åóåó åó åóåó2åóJåó]åódåó]åóHåó+åóåóåó åóåó5åóTåómåóxåósåóaåóGåó)åóåóåóåó3åóSåólåóuåónåóWåó7åóåó åó’’’’’’åóåó åó åó1åóJåó]åógåódåóRåó9åóåó åó åóåó,åóEåó\åóeåócåóOåó7åóåó åóåóåó+åóDåó]åómåónåóbåóJåó.åóåó åóåó-åóHåó^åóhåó_åóHåó,åóåó’’’’’’’’’’’’åóåóåó%åó<åóTåóbåóbåóRåó;åó!åóåóåóåó$åóBåóYåóeåóhåóYåóCåó&åóåóåó åóåó5åóMåó_åódåó[åóFåó-åóåó åóåó#åó8åóJåóQåóKåó8åó$åóåó’’’’’’’’’’’’åóåóåó"åó:åóOåó^åó\åóPåó9åó åóåóåó åóåó;åóWåógåóoåófåóPåó3åóåóåóåóåó&åó8åóKåóRåóMåó=åó'åóåó åó åóåó'åó3åó7åó3åó'åóåó åó’’’’’’’’’åóåóåóåó(åó>åóRåó\åó\åóNåó8åó åóåóåóåóåó5åóRåójåóvåósåócåóGåó*åóåóåóåóåó'åó4åó;åó7åó-åóåóåóåóåó åóåóåó!åóåóåó åó’’’’’’’’’åóåó åóåó'åó8åóKåóYåó_åóYåóIåó2åóåó åóåóåóåó/åóPåólåó}åóåóuåó\åóAåó)åóåó åóåóåóåó"åó!åóåóåóåóåóåóåó åóåóåóåó åó’’’’’’’’’åóåóåóåó.åó?åóPåó\åódåócåóXåóEåó,åóåó åóåóåóåó(åóLåókåó‚åóŠåó„åótåóZåóAåó,åóåóåóåóåóåóåó åóåó’’’’’’’’’åóåóåóåóåó’’’’’’’’’åóåóåó%åó5åóHåóZåófåólåójåóaåóMåó;åó#åóåó’’’’’’åó åó#åó@åócåó€åóŽåó’åó†åóråó[åóDåó5åó#åóåó åóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åóåó+åó8åóNåócåónåótåósåóiåóVåóEåó/åóåó åó’’’’’’åóåóåó6åóYåówåóŠåóåóåó€åónåó`åóOåó;åó)åóåó åó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåó!åó-åóAåóTåógåóråó~åóyåónåó_åóJåó4åó"åóåóåó’’’’’’åóåóåó'åóFåódåó}åó…åó„åó€åóyåótåódåóUåó>åó*åóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåó%åó:åóJåóaåónåóyåó}åó{åóqåó`åóKåó6åó%åóåóåó’’’’’’’’’’’’åóåóåó3åóJåó`åólåósåóvåóxåówåóqåóeåóSåó:åó#åóåó’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó!åó9åóTåógåóxåó€åóåózåópåóaåóIåó6åó%åóåóåó’’’’’’’’’’’’’’’åóåó åóåó,åó>åóKåóSåó^åóhåósåótåópåó_åóHåó-åóåó’’’’’’’’’’’’’’’’’’’’’åóåó åóåó3åóMåókåó|åó‡åó†åóåóqåó^åóEåó1åó!åóåóåó’’’’’’’’’’’’’’’’’’’’’åóåóåóåó åó*åó3åóAåóRåóaåóoåósåójåóTåó8åóåó åó’’’’’’’’’’’’’’’’’’åóåóåó$åóBåó]åóvåóƒåó‡åóƒåóuåó_åóEåó-åóåó åó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó åóåóåó'åó7åóQåóeåóoåólåó]åóCåó'åóåó’’’’’’’’’’’’’’’åóåó åóåó2åóMåóeåóxåó‚åóåóråó_åóEåó.åóåó åó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåóåó)åóBåó]åónåópåófåóNåó/åóåó’’’’’’’’’’’’’’’åóåóåó åó8åóTåókåóuåóvåójåóWåóCåó/åóåó åó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó>åóYåóoåótåólåóUåó9åóåó ’’’’’’’’’’’’’’’åóåóåó$åó?åó[åójåóråóiåóXåó?åó,åóåó åó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó6åóYåóoåó{åótåó_åó:åó åó åó’’’’’’’’’’’’åóåóåó&åóCåó]åómåómåócåóJåó1åóåó åóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó9åó\åótåó~åóuåóaåóAåó!åó åó’’’’’’’’’’’’åóåóåó(åóHåó_åónåóoåóaåóFåó*åóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åóåó:åóZåósåó|åóråó\åó:åóåó åó’’’’’’’’’’’’åóåóåó%åóCåó`åópåópåófåóIåó*åóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åó"åó?åó\åóråóxåókåóRåó4åóåó’’’’’’’’’’’’’’’åóåó åó$åó>åó[åónåótåójåóRåó3åóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åó åó<åóXåómåólåó^åóEåó)åóåó’’’’’’’’’’’’’’’åóåó åóåó5åóWåókåótåómåóZåó<åóåó åó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åó"åó?åóVåógåóeåóVåó;åó#åó åó’’’’’’’’’’’’’’’’’’åóåóåó-åóIåófåóråópåó_åóEåó(åóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó#åó@åóUåódåóaåóNåó4åóåóåó’’’’’’’’’’’’’’’’’’åóåóåó$åó@åó]åópåóråóhåóQåó2åóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó*åóGåó[åófåó_åóMåó2åóåó’’’’’’’’’’’’’’’’’’’’’åóåó åóåó;åóZåómåóvåópåó^åóAåó(åóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåó åóåó2åóOåócåókåócåóNåó0åóåó’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó2åóQåókåóxåówåójåóPåó:åó&åóåó åóåóåó’’’’’’åóåóåóåóåóåóåóåó åóåóåóåóåó.åóBåó[åókåópåógåóQåó3åóåó’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó)åóGåócåóuåóyåópåó`åóNåó<åó-åó"åóåóåó åó åó åó åó åó åó åóåóåóåóåó"åó*åó/åó8åóBåóSåógåósåósåóhåóRåó/åóåóåó’’’’’’’’’’’’’’’’’’’’’åóåó åó åó:åóTåóiåóuåótåómåóaåóTåóHåó<åó2åó*åó%åó#åó$åó!åó"åó"åó!åó!åó'åó-åó6åó?åóDåóLåóOåóVåóaåónåósåóråóaåóIåó-åóåóåó’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó*åóBåóYåógåólåóoåójåóeåó\åóSåóMåóHåóFåóCåóAåóAåó@åó>åó>åó>åóBåóGåóPåóWåóZåó^åóaåóbåófåómåómåóeåóUåó>åó"åóåóåó’’’’’’’’’’’’’’’’’’’’’’’’åóåó åóåó,åó?åóOåó^åóeåóhåójåóiåógåódåóbåóeåóeåóeåóbåó]åóZåóVåóTåóUåóYåó^åócåóhåófåócåó`åóbåóaåó]åóSåóDåó.åóåó åó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åóåó*åó7åóCåóQåó\åócåófåókåónåóråótåówåóvåótåópåóiåócåóbåóaåó^åóaåóbåócåó_åóXåóSåóNåóMåóDåó;åó-åóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åóåó!åó+åó8åóDåóPåóXåóbåókåópåóxåó{åó|åóyåóråójåóaåó]åó[åóXåóVåóTåóRåóJåóCåó=åó7åó/åó*åó!åóåó åóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó åóåó åó*åó6åó@åóMåóWåó`åóhåónåónåóhåóaåóZåóQåóKåóGåóDåó@åó:åó5åó-åó)åó!åóåóåóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó åóåóåó%åó/åó:åóFåóNåóSåóTåóQåóIåó@åó:åó0åó,åó)åó&åó!åóåóåóåóåó åóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó åóåóåó åó%åó*åó/åó0åó.åó(åó"åóåóåóåóåóåóåó åóåóåóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåó åóåóåóåóåóåóåóåó åó åóåóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåóåóåóåóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ü’ž’šą?ą?€Ą€€<<8pąĮĄ`’`ü`ųšųššųšüą’ą?’ąą’ąą’ąą’’Ąą’’Ąą’’Ąą’’Ąš’’Ąš’’Ąš?žųųųüüž’’€?’ą’ų’’ž’’’Ą’’meson-0.45.1/test cases/windows/13 resources with custom targets/res/meson.build0000644000175000017500000000072113243342167031103 0ustar jpakkanejpakkane00000000000000win = import('windows') rc_writer = find_program('./gen-res.py') rc_sources = [] foreach id : [1, 2] rc_sources += custom_target('RC source file @0@'.format(id), input : 'myres.rc.in', output : 'myres_@0@.rc'.format(id), command : [rc_writer, '@INPUT@', '@OUTPUT@', files('sample.ico')], install : false, build_always : true) endforeach rc_sources += files('myres_static.rc') res = win.compile_resources(rc_sources) meson-0.45.1/test cases/windows/13 resources with custom targets/res/gen-res.py0000755000175000017500000000025013243342167030653 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys with open(sys.argv[1], 'r') as infile, open(sys.argv[2], 'w') as outfile: outfile.write(infile.read().format(icon=sys.argv[3])) meson-0.45.1/test cases/windows/13 resources with custom targets/prog.c0000644000175000017500000000042313243342167027262 0ustar jpakkanejpakkane00000000000000#include #define MY_ICON 1 int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { HICON hIcon; hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(MY_ICON)); return hIcon ? 0 : 1; } meson-0.45.1/test cases/windows/6 vs module defs/0000755000175000017500000000000013254552752023004 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/6 vs module defs/meson.build0000644000175000017500000000017513105362433025137 0ustar jpakkanejpakkane00000000000000project('dll_module_defs', 'c') subdir('subdir') exe = executable('prog', 'prog.c', link_with : shlib) test('runtest', exe) meson-0.45.1/test cases/windows/6 vs module defs/subdir/0000755000175000017500000000000013254552752024274 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/6 vs module defs/subdir/somedll.def0000644000175000017500000000002612700546566026412 0ustar jpakkanejpakkane00000000000000EXPORTS somedllfunc meson-0.45.1/test cases/windows/6 vs module defs/subdir/meson.build0000644000175000017500000000011712700546566026436 0ustar jpakkanejpakkane00000000000000shlib = shared_library('somedll', 'somedll.c', vs_module_defs : 'somedll.def') meson-0.45.1/test cases/windows/6 vs module defs/subdir/somedll.c0000644000175000017500000000004513105362433026064 0ustar jpakkanejpakkane00000000000000int somedllfunc() { return 42; } meson-0.45.1/test cases/windows/6 vs module defs/prog.c0000644000175000017500000000014012700546566024113 0ustar jpakkanejpakkane00000000000000int somedllfunc(); int main(int argc, char **argv) { return somedllfunc() == 42 ? 0 : 1; } meson-0.45.1/test cases/windows/5 resources/0000755000175000017500000000000013254552752022215 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/5 resources/meson.build0000644000175000017500000000342013074426732024354 0ustar jpakkanejpakkane00000000000000project('winmain', 'c') # MinGW windres has a bug due to which it doesn't parse args with space properly: # https://github.com/mesonbuild/meson/pull/1346 # https://sourceware.org/bugzilla/show_bug.cgi?id=4933 if meson.get_compiler('c').get_id() == 'gcc' and host_machine.system() == 'windows' # Construct build_to_src and skip this test if it has spaces # because then the -I flag to windres will also have spaces # and we know the test will fail src_parts = meson.source_root().split('/') build_parts = meson.build_root().split('/') # Get the common path (which might just be '/' or 'C:/') common = [] done = false count = 0 if src_parts.length() > build_parts.length() parts = build_parts other = src_parts else parts = src_parts other = build_parts endif foreach part : parts if not done and part == other.get(count) common += [part] else done = true endif count += 1 endforeach # Create path components to go down from the build root to the common path count = 0 rel = build_parts foreach build : build_parts if count < build_parts.length() - common.length() rel += ['..'] endif count += 1 endforeach # Create path components to go up from the common path to the build root count = 0 foreach src : src_parts if count >= common.length() rel += [src] endif count += 1 endforeach build_to_src = '/'.join(rel) if build_to_src.contains(' ') message('build_to_src is: ' + build_to_src) error('MESON_SKIP_TEST build_to_src has spaces') endif # Welcome to the end of this conditional. # We hope you never have to implement something like this. endif subdir('inc') subdir('res') exe = executable('prog', 'prog.c', res, gui_app : true) test('winmain', exe) meson-0.45.1/test cases/windows/5 resources/res/0000755000175000017500000000000013254552752023006 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/5 resources/res/sample.ico0000644000175000017500000002267613070746245024776 0ustar jpakkanejpakkane0000000000000000 Ø%(0` ’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåóåóåóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåóåóåóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåóåóåóåóåóåó åó åóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåóåó åóåóåóåóåóåóåó åó åóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åóåó#åó+åó/åó1åó-åó%åóåóåóåó åóåó’’’’’’’’’’’’’’’’’’’’’åóåóåó åóåóåóåóåó"åó&åó(åó)åó&åó!åóåóåóåó åóåó’’’’’’’’’’’’’’’’’’åóåó åóåó*åó<åóIåóQåóQåóKåóCåó:åó.åó&åóåóåó åóåó’’’’’’’’’’’’åóåóåóåóåó&åó.åó0åó7åó<åóCåóFåóEåóBåó;åó3åó*åó!åóåóåóåó’’’’’’’’’’’’åóåóåóåó*åó@åóVåófåókåógåóaåóXåóOåóFåó<åó3åó(åóåóåóåó’’’’’’’’’åóåóåó#åó4åóDåóLåóQåóVåóXåó[åó^åó]åóZåóRåóMåóCåó8åó-åó åóåó åó’’’’’’’’’åóåóåó$åó<åóVåójåóxåóyåóvåómåóbåó\åóWåóQåóHåó?åó0åó"åóåóåó’’’’’’åóåó"åó9åóNåóbåójåólåójåóiåógåóhåógåódåóaåóZåóWåóMåóBåó4åó'åóåó åó’’’åóåóåóåó0åóIåóbåóuåó|åóxåóråóeåó^åó[åó[åó^åó^åóXåóKåó6åó#åóåó’’’’’’åóåó.åóKåóhåó{åó€åóåósåónåógåóeåódåóaåó_åócåóaåó_åóYåóJåó:åó(åóåó åóåóåó åóåó7åóUåójåóuåózåónåócåóWåóPåóPåóVåóbåójåójåó`åóMåó4åóåó åó’’’åóåó7åóYåówåó‰åóˆåó‚åóqåóaåóWåóUåóSåóTåóUåóZåó`åófåóeåó^åóPåó>åó*åóåóåóåóåó åó?åóXåójåóråómåó]åóJåó>åó8åó;åóJåó_åómåótåóqåó_åóCåó(åóåó’’’åóåó:åó_åó~åóŒåó‰åó~åófåóQåó?åó7åó7åó:åó?åóJåóVåóbåójåókåóbåóQåó8åó"åóåó åóåó"åó>åóVåógåólåócåóNåó7åó(åóåó(åó:åóRåóiåóyåóxåóiåóOåó1åóåó ’’’åóåó<åóaåózåó†åóƒåóqåóXåó;åó(åóåóåóåó'åó2åóCåóSåódåónåójåó]åóFåó,åóåó åó åóåó9åóQåódåófåó[åóGåó-åóåó åóåó(åóDåóaåóuåó|åóqåó[åó>åó"åó åóåóåó9åó]åóuåóåóyåófåóDåó+åóåó åó åó åóåó åó-åóDåóYåóhåókåócåóMåó5åóåó åó åóåó2åóJåó]åódåó]åóHåó+åóåóåó åóåó5åóTåómåóxåósåóaåóGåó)åóåóåóåó3åóSåólåóuåónåóWåó7åóåó åó’’’’’’åóåó åó åó1åóJåó]åógåódåóRåó9åóåó åó åóåó,åóEåó\åóeåócåóOåó7åóåó åóåóåó+åóDåó]åómåónåóbåóJåó.åóåó åóåó-åóHåó^åóhåó_åóHåó,åóåó’’’’’’’’’’’’åóåóåó%åó<åóTåóbåóbåóRåó;åó!åóåóåóåó$åóBåóYåóeåóhåóYåóCåó&åóåóåó åóåó5åóMåó_åódåó[åóFåó-åóåó åóåó#åó8åóJåóQåóKåó8åó$åóåó’’’’’’’’’’’’åóåóåó"åó:åóOåó^åó\åóPåó9åó åóåóåó åóåó;åóWåógåóoåófåóPåó3åóåóåóåóåó&åó8åóKåóRåóMåó=åó'åóåó åó åóåó'åó3åó7åó3åó'åóåó åó’’’’’’’’’åóåóåóåó(åó>åóRåó\åó\åóNåó8åó åóåóåóåóåó5åóRåójåóvåósåócåóGåó*åóåóåóåóåó'åó4åó;åó7åó-åóåóåóåóåó åóåóåó!åóåóåó åó’’’’’’’’’åóåó åóåó'åó8åóKåóYåó_åóYåóIåó2åóåó åóåóåóåó/åóPåólåó}åóåóuåó\åóAåó)åóåó åóåóåóåó"åó!åóåóåóåóåóåóåó åóåóåóåó åó’’’’’’’’’åóåóåóåó.åó?åóPåó\åódåócåóXåóEåó,åóåó åóåóåóåó(åóLåókåó‚åóŠåó„åótåóZåóAåó,åóåóåóåóåóåóåó åóåó’’’’’’’’’åóåóåóåóåó’’’’’’’’’åóåóåó%åó5åóHåóZåófåólåójåóaåóMåó;åó#åóåó’’’’’’åó åó#åó@åócåó€åóŽåó’åó†åóråó[åóDåó5åó#åóåó åóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åóåó+åó8åóNåócåónåótåósåóiåóVåóEåó/åóåó åó’’’’’’åóåóåó6åóYåówåóŠåóåóåó€åónåó`åóOåó;åó)åóåó åó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåó!åó-åóAåóTåógåóråó~åóyåónåó_åóJåó4åó"åóåóåó’’’’’’åóåóåó'åóFåódåó}åó…åó„åó€åóyåótåódåóUåó>åó*åóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåó%åó:åóJåóaåónåóyåó}åó{åóqåó`åóKåó6åó%åóåóåó’’’’’’’’’’’’åóåóåó3åóJåó`åólåósåóvåóxåówåóqåóeåóSåó:åó#åóåó’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó!åó9åóTåógåóxåó€åóåózåópåóaåóIåó6åó%åóåóåó’’’’’’’’’’’’’’’åóåó åóåó,åó>åóKåóSåó^åóhåósåótåópåó_åóHåó-åóåó’’’’’’’’’’’’’’’’’’’’’åóåó åóåó3åóMåókåó|åó‡åó†åóåóqåó^åóEåó1åó!åóåóåó’’’’’’’’’’’’’’’’’’’’’åóåóåóåó åó*åó3åóAåóRåóaåóoåósåójåóTåó8åóåó åó’’’’’’’’’’’’’’’’’’åóåóåó$åóBåó]åóvåóƒåó‡åóƒåóuåó_åóEåó-åóåó åó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó åóåóåó'åó7åóQåóeåóoåólåó]åóCåó'åóåó’’’’’’’’’’’’’’’åóåó åóåó2åóMåóeåóxåó‚åóåóråó_åóEåó.åóåó åó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåóåó)åóBåó]åónåópåófåóNåó/åóåó’’’’’’’’’’’’’’’åóåóåó åó8åóTåókåóuåóvåójåóWåóCåó/åóåó åó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó>åóYåóoåótåólåóUåó9åóåó ’’’’’’’’’’’’’’’åóåóåó$åó?åó[åójåóråóiåóXåó?åó,åóåó åó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó6åóYåóoåó{åótåó_åó:åó åó åó’’’’’’’’’’’’åóåóåó&åóCåó]åómåómåócåóJåó1åóåó åóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó9åó\åótåó~åóuåóaåóAåó!åó åó’’’’’’’’’’’’åóåóåó(åóHåó_åónåóoåóaåóFåó*åóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åóåó:åóZåósåó|åóråó\åó:åóåó åó’’’’’’’’’’’’åóåóåó%åóCåó`åópåópåófåóIåó*åóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åó"åó?åó\åóråóxåókåóRåó4åóåó’’’’’’’’’’’’’’’åóåó åó$åó>åó[åónåótåójåóRåó3åóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åó åó<åóXåómåólåó^åóEåó)åóåó’’’’’’’’’’’’’’’åóåó åóåó5åóWåókåótåómåóZåó<åóåó åó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åó"åó?åóVåógåóeåóVåó;åó#åó åó’’’’’’’’’’’’’’’’’’åóåóåó-åóIåófåóråópåó_åóEåó(åóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó#åó@åóUåódåóaåóNåó4åóåóåó’’’’’’’’’’’’’’’’’’åóåóåó$åó@åó]åópåóråóhåóQåó2åóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó*åóGåó[åófåó_åóMåó2åóåó’’’’’’’’’’’’’’’’’’’’’åóåó åóåó;åóZåómåóvåópåó^åóAåó(åóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåó åóåó2åóOåócåókåócåóNåó0åóåó’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó2åóQåókåóxåówåójåóPåó:åó&åóåó åóåóåó’’’’’’åóåóåóåóåóåóåóåó åóåóåóåóåó.åóBåó[åókåópåógåóQåó3åóåó’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó)åóGåócåóuåóyåópåó`åóNåó<åó-åó"åóåóåó åó åó åó åó åó åó åóåóåóåóåó"åó*åó/åó8åóBåóSåógåósåósåóhåóRåó/åóåóåó’’’’’’’’’’’’’’’’’’’’’åóåó åó åó:åóTåóiåóuåótåómåóaåóTåóHåó<åó2åó*åó%åó#åó$åó!åó"åó"åó!åó!åó'åó-åó6åó?åóDåóLåóOåóVåóaåónåósåóråóaåóIåó-åóåóåó’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó*åóBåóYåógåólåóoåójåóeåó\åóSåóMåóHåóFåóCåóAåóAåó@åó>åó>åó>åóBåóGåóPåóWåóZåó^åóaåóbåófåómåómåóeåóUåó>åó"åóåóåó’’’’’’’’’’’’’’’’’’’’’’’’åóåó åóåó,åó?åóOåó^åóeåóhåójåóiåógåódåóbåóeåóeåóeåóbåó]åóZåóVåóTåóUåóYåó^åócåóhåófåócåó`åóbåóaåó]åóSåóDåó.åóåó åó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åóåó*åó7åóCåóQåó\åócåófåókåónåóråótåówåóvåótåópåóiåócåóbåóaåó^åóaåóbåócåó_åóXåóSåóNåóMåóDåó;åó-åóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåó åóåó!åó+åó8åóDåóPåóXåóbåókåópåóxåó{åó|åóyåóråójåóaåó]åó[åóXåóVåóTåóRåóJåóCåó=åó7åó/åó*åó!åóåó åóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó åóåó åó*åó6åó@åóMåóWåó`åóhåónåónåóhåóaåóZåóQåóKåóGåóDåó@åó:åó5åó-åó)åó!åóåóåóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó åóåóåó%åó/åó:åóFåóNåóSåóTåóQåóIåó@åó:åó0åó,åó)åó&åó!åóåóåóåóåó åóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåó åóåóåó åó%åó*åó/åó0åó.åó(åó"åóåóåóåóåóåóåó åóåóåóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåó åóåóåóåóåóåóåóåó åó åóåóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’åóåóåóåóåóåóåóåóåóåó’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ü’ž’šą?ą?€Ą€€<<8pąĮĄ`’`ü`ųšųššųšüą’ą?’ąą’ąą’ąą’’Ąą’’Ąą’’Ąą’’Ąš’’Ąš’’Ąš?žųųųüüž’’€?’ą’ų’’ž’’’Ą’’meson-0.45.1/test cases/windows/5 resources/res/meson.build0000644000175000017500000000013613070746245025146 0ustar jpakkanejpakkane00000000000000win = import('windows') res = win.compile_resources('myres.rc', include_directories : inc) meson-0.45.1/test cases/windows/5 resources/res/myres.rc0000644000175000017500000000010413070746245024464 0ustar jpakkanejpakkane00000000000000#include #include"resource.h" ICON_ID ICON "sample.ico" meson-0.45.1/test cases/windows/5 resources/prog.c0000644000175000017500000000042313243342167023322 0ustar jpakkanejpakkane00000000000000#include #define MY_ICON 1 int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { HICON hIcon; hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(MY_ICON)); return hIcon ? 0 : 1; } meson-0.45.1/test cases/windows/5 resources/inc/0000755000175000017500000000000013254552752022766 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/5 resources/inc/meson.build0000644000175000017500000000004613070746245025126 0ustar jpakkanejpakkane00000000000000inc = include_directories('resource') meson-0.45.1/test cases/windows/5 resources/inc/resource/0000755000175000017500000000000013254552752024615 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/5 resources/inc/resource/resource.h0000644000175000017500000000002213070746245026605 0ustar jpakkanejpakkane00000000000000#define ICON_ID 1 meson-0.45.1/test cases/windows/9 find program/0000755000175000017500000000000013254552752022557 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/windows/9 find program/meson.build0000644000175000017500000000054513055371450024716 0ustar jpakkanejpakkane00000000000000project('find program', 'c') # Test that we can find native windows executables find_program('cmd') find_program('cmd.exe') # Test that a script file with an extension can be found ext = find_program('test-script-ext.py') test('ext', ext) # Test that a script file without an extension can be found prog = find_program('test-script') test('script', prog) meson-0.45.1/test cases/windows/9 find program/test-script-ext.py0000644000175000017500000000005313055371450026177 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 print('ext/noext') meson-0.45.1/test cases/windows/9 find program/test-script0000644000175000017500000000004212747162664024764 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python print('1') meson-0.45.1/test cases/failing build/0000755000175000017500000000000013254552745021057 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing build/1 vala c werror/0000755000175000017500000000000013254552750023623 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing build/1 vala c werror/meson.build0000644000175000017500000000060513254552153025763 0ustar jpakkanejpakkane00000000000000project('valatest', 'c', default_options : 'werror=true') if find_program('valac', required : false).found() add_languages('vala') valadeps = [dependency('glib-2.0'), dependency('gobject-2.0')] # Must fail due to -Werror and unused variable in C file executable('valaprog', 'prog.vala', 'unused-var.c', dependencies : valadeps) else executable('failprog', 'unused-var.c') endif meson-0.45.1/test cases/failing build/1 vala c werror/unused-var.c0000644000175000017500000000011313033265323026043 0ustar jpakkanejpakkane00000000000000#warning "something" int somelib(void) { int unused_var; return 33; } meson-0.45.1/test cases/failing build/1 vala c werror/prog.vala0000644000175000017500000000022313003456157025430 0ustar jpakkanejpakkane00000000000000class MainProg : GLib.Object { public static int main(string[] args) { stdout.printf("Vala is working.\n"); return 0; } } meson-0.45.1/test cases/common/0000755000175000017500000000000013254552745017656 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/172 subdir if_found/0000755000175000017500000000000013254552747023214 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/172 subdir if_found/meson.build0000644000175000017500000000044313254552133025344 0ustar jpakkanejpakkane00000000000000project('subdir if found', 'c') found_dep = declare_dependency() not_found_dep = dependency('nonexisting', required : false) subdir('nonexisting_dir', if_found : not_found_dep) variable = 3 subdir('subdir', if_found : found_dep) assert(variable == 5, 'Subdir was not properly entered.') meson-0.45.1/test cases/common/172 subdir if_found/subdir/0000755000175000017500000000000013254552747024504 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/172 subdir if_found/subdir/meson.build0000644000175000017500000000001513211772701026625 0ustar jpakkanejpakkane00000000000000variable = 5 meson-0.45.1/test cases/common/61 custom target source output/0000755000175000017500000000000013254552747025452 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/61 custom target source output/main.c0000644000175000017500000000011212650745767026541 0ustar jpakkanejpakkane00000000000000#include"mylib.h" int main(int argc, char **argv) { return func(); } meson-0.45.1/test cases/common/61 custom target source output/meson.build0000644000175000017500000000031713254551751027607 0ustar jpakkanejpakkane00000000000000project('source generation', 'c') ct = custom_target('gen', output : ['mylib.h', 'mylib.c'], command : [find_program('generator.py'), '@OUTDIR@'], ) e = executable('prog', 'main.c', ct) test('gentest', e) meson-0.45.1/test cases/common/61 custom target source output/generator.py0000755000175000017500000000046113057037314030003 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys, os if len(sys.argv) != 2: print(sys.argv[0], '') odir = sys.argv[1] with open(os.path.join(odir, 'mylib.h'), 'w') as f: f.write('int func();\n') with open(os.path.join(odir, 'mylib.c'), 'w') as f: f.write('''int func() { return 0; } ''') meson-0.45.1/test cases/common/74 modules/0000755000175000017500000000000013254552747021543 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/74 modules/meson.build0000644000175000017500000000011713254551767023705 0ustar jpakkanejpakkane00000000000000project('module test', 'c') modtest = import('modtest') modtest.print_hello() meson-0.45.1/test cases/common/6 linkshared/0000755000175000017500000000000013254552747022132 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/6 linkshared/main.c0000644000175000017500000000030512650745767023225 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_IMPORT __declspec(dllimport) #else #define DLL_IMPORT #endif int DLL_IMPORT func(); int main(int argc, char **arg) { return func(); } meson-0.45.1/test cases/common/6 linkshared/cpplib.cpp0000644000175000017500000000027212650745767024115 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 #define DLL_PUBLIC __declspec(dllexport) #else #define DLL_PUBLIC __attribute__ ((visibility ("default"))) #endif int DLL_PUBLIC cppfunc() { return 42; } meson-0.45.1/test cases/common/6 linkshared/installed_files.txt0000644000175000017500000000002112742140120026000 0ustar jpakkanejpakkane00000000000000usr/bin/prog?exe meson-0.45.1/test cases/common/6 linkshared/meson.build0000644000175000017500000000075113254551636024273 0ustar jpakkanejpakkane00000000000000project('shared library linking test', 'c', 'cpp') lib = shared_library('mylib', 'libfile.c' # Split to different lines before and after the comma to test parser. , install : false) # Don't install libraries in common tests; the path is platform-specific exe = executable('prog', 'main.c', link_with : lib, install : true) test('runtest', exe) cpplib = shared_library('mycpplib', 'cpplib.cpp') cppexe = executable('cppprog', 'cppmain.cpp', link_with : cpplib) test('cpptest', cppexe) meson-0.45.1/test cases/common/6 linkshared/libfile.c0000644000175000017500000000051512650745767023712 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif int DLL_PUBLIC func() { return 0; } meson-0.45.1/test cases/common/6 linkshared/cppmain.cpp0000644000175000017500000000012012650745767024263 0ustar jpakkanejpakkane00000000000000int cppfunc(); int main(int argc, char **argv) { return cppfunc() != 42; } meson-0.45.1/test cases/common/111 has header symbol/0000755000175000017500000000000013254552746023414 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/111 has header symbol/meson.build0000644000175000017500000000375713254552052025560 0ustar jpakkanejpakkane00000000000000project('has header symbol', 'c', 'cpp') cc = meson.get_compiler('c') cpp = meson.get_compiler('cpp') foreach comp : [cc, cpp] assert (comp.has_header_symbol('stdio.h', 'int'), 'base types should always be available') assert (comp.has_header_symbol('stdio.h', 'printf'), 'printf function not found') assert (comp.has_header_symbol('stdio.h', 'FILE'), 'FILE structure not found') assert (comp.has_header_symbol('limits.h', 'INT_MAX'), 'INT_MAX define not found') assert (not comp.has_header_symbol('limits.h', 'guint64'), 'guint64 is not defined in limits.h') assert (not comp.has_header_symbol('stdlib.h', 'FILE'), 'FILE structure is defined in stdio.h, not stdlib.h') assert (not comp.has_header_symbol('stdlol.h', 'printf'), 'stdlol.h shouldn\'t exist') assert (not comp.has_header_symbol('stdlol.h', 'int'), 'shouldn\'t be able to find "int" with invalid header') endforeach # This is available on Glibc, Solaris & the BSD's, so just test for _GNU_SOURCE # on Linux if cc.has_function('ppoll') and host_machine.system() == 'linux' assert (not cc.has_header_symbol('poll.h', 'ppoll'), 'ppoll should not be accessible without _GNU_SOURCE') assert (cc.has_header_symbol('poll.h', 'ppoll', prefix : '#define _GNU_SOURCE'), 'ppoll should be accessible with _GNU_SOURCE') endif assert (cpp.has_header_symbol('iostream', 'std::iostream'), 'iostream not found in iostream.h') assert (cpp.has_header_symbol('vector', 'std::vector'), 'vector not found in vector.h') assert (not cpp.has_header_symbol('limits.h', 'std::iostream'), 'iostream should not be defined in limits.h') # Cross compilation and boost do not mix. if not meson.is_cross_build() boost = dependency('boost', required : false) if boost.found() assert (cpp.has_header_symbol('boost/math/quaternion.hpp', 'boost::math::quaternion', dependencies : boost), 'quaternion not found') else assert (not cpp.has_header_symbol('boost/math/quaternion.hpp', 'boost::math::quaternion', dependencies : boost), 'quaternion found?!') endif endif meson-0.45.1/test cases/common/128 extract all shared library/0000755000175000017500000000000013254552746025231 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/128 extract all shared library/extractor.h0000644000175000017500000000010213024065327027373 0ustar jpakkanejpakkane00000000000000#pragma once int func1(); int func2(); int func3(); int func4(); meson-0.45.1/test cases/common/128 extract all shared library/func1234.def0000644000175000017500000000004413024065327027141 0ustar jpakkanejpakkane00000000000000EXPORTS func1 func2 func3 func4 meson-0.45.1/test cases/common/128 extract all shared library/meson.build0000644000175000017500000000047413254552063027370 0ustar jpakkanejpakkane00000000000000project('extract all', 'c', 'cpp') a = static_library('a', 'one.c', 'two.c') b = static_library('b', 'three.c', 'four.c') c = shared_library('c', objects : [a.extract_all_objects(), b.extract_all_objects()], vs_module_defs : 'func1234.def') e = executable('proggie', 'prog.c', link_with : c) test('extall', e) meson-0.45.1/test cases/common/128 extract all shared library/one.c0000644000175000017500000000006513024065327026144 0ustar jpakkanejpakkane00000000000000#include"extractor.h" int func1() { return 1; } meson-0.45.1/test cases/common/128 extract all shared library/four.c0000644000175000017500000000006513024065327026336 0ustar jpakkanejpakkane00000000000000#include"extractor.h" int func4() { return 4; } meson-0.45.1/test cases/common/128 extract all shared library/two.c0000644000175000017500000000006513024065327026174 0ustar jpakkanejpakkane00000000000000#include"extractor.h" int func2() { return 2; } meson-0.45.1/test cases/common/128 extract all shared library/prog.c0000644000175000017500000000033313024065327026330 0ustar jpakkanejpakkane00000000000000#include"extractor.h" #include int main(int argc, char **argv) { if((1+2+3+4) != (func1() + func2() + func3() + func4())) { printf("Arithmetic is fail.\n"); return 1; } return 0; } meson-0.45.1/test cases/common/128 extract all shared library/three.c0000644000175000017500000000006513024065327026472 0ustar jpakkanejpakkane00000000000000#include"extractor.h" int func3() { return 3; } meson-0.45.1/test cases/common/107 postconf/0000755000175000017500000000000013254552746022002 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/107 postconf/postconf.py0000644000175000017500000000055413057037314024201 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import os template = '''#pragma once #define THE_NUMBER {} ''' input_file = os.path.join(os.environ['MESON_SOURCE_ROOT'], 'raw.dat') output_file = os.path.join(os.environ['MESON_BUILD_ROOT'], 'generated.h') with open(input_file) as f: data = f.readline().strip() with open(output_file, 'w') as f: f.write(template.format(data)) meson-0.45.1/test cases/common/107 postconf/meson.build0000644000175000017500000000016613254552030024131 0ustar jpakkanejpakkane00000000000000project('postconf script', 'c') meson.add_postconf_script('postconf.py') test('post', executable('prog', 'prog.c')) meson-0.45.1/test cases/common/107 postconf/prog.c0000644000175000017500000000012712665647635023124 0ustar jpakkanejpakkane00000000000000#include"generated.h" int main(int argc, char **argv) { return THE_NUMBER != 9; } meson-0.45.1/test cases/common/107 postconf/raw.dat0000644000175000017500000000000212665647635023264 0ustar jpakkanejpakkane000000000000009 meson-0.45.1/test cases/common/81 file object/0000755000175000017500000000000013254552747022237 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/81 file object/lib.c0000644000175000017500000000003512650745767023154 0ustar jpakkanejpakkane00000000000000int func() { return 0; } meson-0.45.1/test cases/common/81 file object/meson.build0000644000175000017500000000023713254552000024361 0ustar jpakkanejpakkane00000000000000project('file object', 'c') prog0 = files('prog.c') lib0 = files('lib.c') test('fobj', executable('fobj', prog0, lib0)) subdir('subdir1') subdir('subdir2') meson-0.45.1/test cases/common/81 file object/subdir1/0000755000175000017500000000000013254552747023610 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/81 file object/subdir1/lib.c0000644000175000017500000000003512650745767024525 0ustar jpakkanejpakkane00000000000000int func() { return 1; } meson-0.45.1/test cases/common/81 file object/subdir1/meson.build0000644000175000017500000000036312650745767025761 0ustar jpakkanejpakkane00000000000000prog1 = files('prog.c') lib1 = files('lib.c') test('subdir0', executable('subdir0', prog0, lib1), should_fail : true) test('subdir1', executable('subdir1', prog1, lib0), should_fail : true) test('subdir2', executable('subdir2', prog1, lib1))meson-0.45.1/test cases/common/81 file object/subdir1/prog.c0000644000175000017500000000031412650745767024726 0ustar jpakkanejpakkane00000000000000#include int func(); int main(int argc, char **argv) { if(func() == 1) { printf("Iz success.\n"); } else { printf("Iz fail.\n"); return 1; } return 0; } meson-0.45.1/test cases/common/81 file object/prog.c0000644000175000017500000000040612650745767023357 0ustar jpakkanejpakkane00000000000000#include int func(); /* Files in different subdirs return different values. */ int main(int argc, char **argv) { if(func() == 0) { printf("Iz success.\n"); } else { printf("Iz fail.\n"); return 1; } return 0; } meson-0.45.1/test cases/common/81 file object/subdir2/0000755000175000017500000000000013254552747023611 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/81 file object/subdir2/lib.c0000644000175000017500000000003512650745767024526 0ustar jpakkanejpakkane00000000000000int func() { return 2; } meson-0.45.1/test cases/common/81 file object/subdir2/meson.build0000644000175000017500000000036312650745767025762 0ustar jpakkanejpakkane00000000000000prog2 = files('prog.c') lib2 = files('lib.c') test('subdir3', executable('subdir3', prog1, lib2), should_fail : true) test('subdir4', executable('subdir4', prog2, lib1), should_fail : true) test('subdir4', executable('subdir5', prog2, lib2))meson-0.45.1/test cases/common/81 file object/subdir2/prog.c0000644000175000017500000000031412650745767024727 0ustar jpakkanejpakkane00000000000000#include int func(); int main(int argc, char **argv) { if(func() == 2) { printf("Iz success.\n"); } else { printf("Iz fail.\n"); return 1; } return 0; } meson-0.45.1/test cases/common/92 skip subdir/0000755000175000017500000000000013254552750022304 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/92 skip subdir/meson.build0000644000175000017500000000005713254552011024436 0ustar jpakkanejpakkane00000000000000project('foo', 'c') subdir('subdir1/subdir2') meson-0.45.1/test cases/common/92 skip subdir/subdir1/0000755000175000017500000000000013254552750023655 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/92 skip subdir/subdir1/meson.build0000644000175000017500000000004412650745767026030 0ustar jpakkanejpakkane00000000000000error('This should not be called.') meson-0.45.1/test cases/common/92 skip subdir/subdir1/subdir2/0000755000175000017500000000000013254552750025227 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/92 skip subdir/subdir1/subdir2/meson.build0000644000175000017500000000004212650745767027400 0ustar jpakkanejpakkane00000000000000message('I\'m in subdir subdir.') meson-0.45.1/test cases/common/21 includedir/0000755000175000017500000000000013254552747022205 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/21 includedir/meson.build0000644000175000017500000000012513254551657024344 0ustar jpakkanejpakkane00000000000000project('include dir test', 'c') inc = include_directories('include') subdir('src') meson-0.45.1/test cases/common/21 includedir/include/0000755000175000017500000000000013254552747023630 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/21 includedir/include/func.h0000644000175000017500000000006712650745767024744 0ustar jpakkanejpakkane00000000000000#ifndef FUNC_H__ #define FUNC_H__ int func(); #endif meson-0.45.1/test cases/common/21 includedir/src/0000755000175000017500000000000013254552747022774 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/21 includedir/src/func.c0000644000175000017500000000006012650745767024074 0ustar jpakkanejpakkane00000000000000#include "func.h" int func() { return 0; } meson-0.45.1/test cases/common/21 includedir/src/meson.build0000644000175000017500000000013612650745767025143 0ustar jpakkanejpakkane00000000000000exe = executable('prog', 'prog.c', 'func.c', include_directories : inc) test('inc test', exe) meson-0.45.1/test cases/common/21 includedir/src/prog.c0000644000175000017500000000011212650745767024106 0ustar jpakkanejpakkane00000000000000#include "func.h" int main(int argc, char **argv) { return func(); } meson-0.45.1/test cases/common/28 config subdir/0000755000175000017500000000000013254552747022610 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/28 config subdir/meson.build0000644000175000017500000000014413254551666024750 0ustar jpakkanejpakkane00000000000000project('subdirconfig', 'c') inc = include_directories('include') subdir('include') subdir('src') meson-0.45.1/test cases/common/28 config subdir/include/0000755000175000017500000000000013254552747024233 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/28 config subdir/include/config.h.in0000644000175000017500000000011312650745767026256 0ustar jpakkanejpakkane00000000000000#ifndef CONFIG_H_ #define CONFIG_H_ #define RETURN_VALUE @number@ #endif meson-0.45.1/test cases/common/28 config subdir/include/meson.build0000644000175000017500000000021712650745767026402 0ustar jpakkanejpakkane00000000000000conf_data = configuration_data() conf_data.set('number', '0') configure_file(input:'config.h.in', output:'config.h', configuration:conf_data) meson-0.45.1/test cases/common/28 config subdir/src/0000755000175000017500000000000013254552747023377 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/28 config subdir/src/meson.build0000644000175000017500000000013112650745767025541 0ustar jpakkanejpakkane00000000000000exe = executable('prog', 'prog.c', include_directories : inc) test('subdir config', exe) meson-0.45.1/test cases/common/28 config subdir/src/prog.c0000644000175000017500000000012212650745767024512 0ustar jpakkanejpakkane00000000000000#include "config.h" int main(int argc, char **argv) { return RETURN_VALUE; } meson-0.45.1/test cases/common/71 arithmetic bidmas/0000755000175000017500000000000013254552747023441 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/71 arithmetic bidmas/meson.build0000644000175000017500000000057513254551763025607 0ustar jpakkanejpakkane00000000000000project('arithmetic bidmas', 'c') if 5 * 3 - 6 / 2 + 1 != 13 error('Arithmetic bidmas broken') endif if 5 * (3 - 6 / 2) + 1 != 1 error('Arithmetic bidmas with brackets broken') endif if 5 * 12 / 2 * 3 != 90 error('Sequential multiplication and division broken') endif if 5 * (12 / (2 * 3)) != 10 error('Sequential multiplication and division with brackets broken') endif meson-0.45.1/test cases/common/113 generatorcustom/0000755000175000017500000000000013254552746023365 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/113 generatorcustom/gen.py0000755000175000017500000000036513057037314024505 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys ifile = sys.argv[1] ofile = sys.argv[2] with open(ifile, 'r') as f: resname = f.readline().strip() templ = 'const char %s[] = "%s";\n' with open(ofile, 'w') as f: f.write(templ % (resname, resname)) meson-0.45.1/test cases/common/113 generatorcustom/main.c0000644000175000017500000000013612732535546024454 0ustar jpakkanejpakkane00000000000000#include #include"alltogether.h" int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/113 generatorcustom/catter.py0000755000175000017500000000045113057037314025212 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys output = sys.argv[-1] inputs = sys.argv[1:-1] with open(output, 'w') as ofile: ofile.write('#pragma once\n') for i in inputs: with open(i, 'r') as ifile: content = ifile.read() ofile.write(content) ofile.write('\n') meson-0.45.1/test cases/common/113 generatorcustom/meson.build0000644000175000017500000000063413254552036025522 0ustar jpakkanejpakkane00000000000000project('generatorcustom', 'c') creator = find_program('gen.py') catter = find_program('catter.py') gen = generator(creator, output: '@BASENAME@.h', arguments : ['@INPUT@', '@OUTPUT@']) hs = gen.process('res1.txt', 'res2.txt') allinone = custom_target('alltogether', input : hs, output : 'alltogether.h', command : [catter, '@INPUT@', '@OUTPUT@']) executable('proggie', 'main.c', allinone) meson-0.45.1/test cases/common/113 generatorcustom/res2.txt0000644000175000017500000000000512732535546024773 0ustar jpakkanejpakkane00000000000000res2 meson-0.45.1/test cases/common/113 generatorcustom/res1.txt0000644000175000017500000000000512732535546024772 0ustar jpakkanejpakkane00000000000000res1 meson-0.45.1/test cases/common/145 whole archive/0000755000175000017500000000000013254552746022671 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/145 whole archive/sh_func2_linked_func1/0000755000175000017500000000000013254552746027022 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/145 whole archive/sh_func2_linked_func1/meson.build0000644000175000017500000000031713246615532031157 0ustar jpakkanejpakkane00000000000000# Nothing in func2.c uses func1, so the linker would throw it # away and thus linking the exe would fail. sh_func2_linked_func1 = shared_library('sh_func2_linked_func1', '../func2.c', link_whole : st_func1) meson-0.45.1/test cases/common/145 whole archive/mylib.h0000644000175000017500000000073313076164167024157 0ustar jpakkanejpakkane00000000000000#pragma once /* Both funcs here for simplicity. */ #if defined _WIN32 || defined __CYGWIN__ #if defined BUILDING_DLL #define DLL_PUBLIC __declspec(dllexport) #else #define DLL_PUBLIC __declspec(dllimport) #endif #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif int DLL_PUBLIC func1(); int DLL_PUBLIC func2(); meson-0.45.1/test cases/common/145 whole archive/st_func1/0000755000175000017500000000000013254552746024413 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/145 whole archive/st_func1/meson.build0000644000175000017500000000006413246615532026547 0ustar jpakkanejpakkane00000000000000st_func1 = static_library('st_func1', '../func1.c') meson-0.45.1/test cases/common/145 whole archive/meson.build0000644000175000017500000000170713254552103025023 0ustar jpakkanejpakkane00000000000000project('whole archive', 'c') add_project_arguments('-I' + meson.source_root(), language : 'c') cc = meson.get_compiler('c') if cc.get_id() == 'msvc' if cc.version().version_compare('<19') error('MESON_SKIP_TEST link_whole only works on VS2015 or newer.') endif endif # Test 1: link_whole keeps all symbols # Make static func1 subdir('st_func1') # Make shared func2 linking whole func1 archive subdir('sh_func2_linked_func1') # Link exe with shared library only subdir('exe') # Test that both func1 and func2 are accessible from shared library test('prog', exe) # Test 2: link_whole can be used instead of source list, see #2180 # Make static func2 subdir('st_func2') # Link both func1 and func2 into same shared library # which does not have any sources other than 2 static libraries subdir('sh_only_link_whole') # Link exe2 with shared library only subdir('exe2') # Test that both func1 and func2 are accessible from shared library test('prog2', exe2) meson-0.45.1/test cases/common/145 whole archive/sh_only_link_whole/0000755000175000017500000000000013254552746026557 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/145 whole archive/sh_only_link_whole/meson.build0000644000175000017500000000013513246615532030712 0ustar jpakkanejpakkane00000000000000sh_only_link_whole = shared_library('sh_only_link_whole', link_whole : [st_func1, st_func2]) meson-0.45.1/test cases/common/145 whole archive/func1.c0000644000175000017500000000011013246615532024033 0ustar jpakkanejpakkane00000000000000#define BUILDING_DLL #include int func1() { return 42; } meson-0.45.1/test cases/common/145 whole archive/st_func2/0000755000175000017500000000000013254552746024414 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/145 whole archive/st_func2/meson.build0000644000175000017500000000006413246615532026550 0ustar jpakkanejpakkane00000000000000st_func2 = static_library('st_func2', '../func2.c') meson-0.45.1/test cases/common/145 whole archive/prog.c0000644000175000017500000000012513076164167024000 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { return func1() - func2(); } meson-0.45.1/test cases/common/145 whole archive/exe/0000755000175000017500000000000013254552746023452 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/145 whole archive/exe/meson.build0000644000175000017500000000011113246615532025577 0ustar jpakkanejpakkane00000000000000exe = executable('prog', '../prog.c', link_with : sh_func2_linked_func1) meson-0.45.1/test cases/common/145 whole archive/func2.c0000644000175000017500000000011013246615532024034 0ustar jpakkanejpakkane00000000000000#define BUILDING_DLL #include int func2() { return 42; } meson-0.45.1/test cases/common/145 whole archive/exe2/0000755000175000017500000000000013254552746023534 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/145 whole archive/exe2/meson.build0000644000175000017500000000011013246615532025660 0ustar jpakkanejpakkane00000000000000exe2 = executable('prog2', '../prog.c', link_with : sh_only_link_whole) meson-0.45.1/test cases/common/154 library at root/0000755000175000017500000000000013254552746023146 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/154 library at root/main/0000755000175000017500000000000013254552746024072 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/154 library at root/main/main.c0000644000175000017500000000007213125214444025144 0ustar jpakkanejpakkane00000000000000extern int fn(void); int main() { return 1 + fn(); } meson-0.45.1/test cases/common/154 library at root/main/meson.build0000644000175000017500000000011513125214444026214 0ustar jpakkanejpakkane00000000000000exe = executable('main', 'main.c', link_with : lib) test('stuff works', exe) meson-0.45.1/test cases/common/154 library at root/lib.c0000644000175000017500000000014613125214444024044 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ __declspec(dllexport) #endif int fn(void) { return -1; } meson-0.45.1/test cases/common/154 library at root/meson.build0000644000175000017500000000011513254552114025272 0ustar jpakkanejpakkane00000000000000project('lib@root', 'c') lib = shared_library('lib', 'lib.c') subdir('main') meson-0.45.1/test cases/common/137 build by default/0000755000175000017500000000000013254552746023251 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/137 build by default/mygen.py0000644000175000017500000000017013043224360024720 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys ifile = open(sys.argv[1]) ofile = open(sys.argv[2], 'w') ofile.write(ifile.read()) meson-0.45.1/test cases/common/137 build by default/foo.c0000644000175000017500000000014613043224360024161 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("Existentialism.\n"); return 0; } meson-0.45.1/test cases/common/137 build by default/meson.build0000644000175000017500000000135113254552071025402 0ustar jpakkanejpakkane00000000000000project('build on all', 'c') py3_mod = import('python3') py3 = py3_mod.find_python() executable('fooprog', 'foo.c', build_by_default : false) comp = files('mygen.py') mytarget = custom_target('gendat', output : 'generated.dat', input : 'source.txt', command : [py3] + comp + ['@INPUT@', '@OUTPUT@'], build_by_default : true, ) ct_output = join_paths(meson.build_root(), 'generated.dat') exe_output = join_paths(meson.build_root(), 'fooprog') if host_machine.system() == 'windows' exe_output += '.exe' endif ct_exists_exe_nexists = 'import os.path, sys; sys.exit(not os.path.exists(sys.argv[1]) and os.path.exists(sys.argv[2]))' test('check-build-by-default', py3, args : ['-c', ct_exists_exe_nexists, ct_output, exe_output]) meson-0.45.1/test cases/common/137 build by default/source.txt0000644000175000017500000000002613043224360025270 0ustar jpakkanejpakkane00000000000000I am a bunch of text. meson-0.45.1/test cases/common/46 library chain/0000755000175000017500000000000013254552747022601 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/46 library chain/main.c0000644000175000017500000000006112650745767023673 0ustar jpakkanejpakkane00000000000000int libfun(); int main() { return libfun(); } meson-0.45.1/test cases/common/46 library chain/installed_files.txt0000644000175000017500000000002112742140120026447 0ustar jpakkanejpakkane00000000000000usr/bin/prog?exe meson-0.45.1/test cases/common/46 library chain/meson.build0000644000175000017500000000017513254551716024741 0ustar jpakkanejpakkane00000000000000project('libchain', 'c') subdir('subdir') e = executable('prog', 'main.c', link_with : lib1, install : true) test('tst', e) meson-0.45.1/test cases/common/46 library chain/subdir/0000755000175000017500000000000013254552747024071 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/46 library chain/subdir/subdir3/0000755000175000017500000000000013254552747025444 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/46 library chain/subdir/subdir3/lib3.c0000644000175000017500000000051712650745767026451 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif int DLL_PUBLIC lib3fun() { return 0; } meson-0.45.1/test cases/common/46 library chain/subdir/subdir3/meson.build0000644000175000017500000000007112742140120027557 0ustar jpakkanejpakkane00000000000000lib3 = shared_library('lib3', 'lib3.c', install : false) meson-0.45.1/test cases/common/46 library chain/subdir/meson.build0000644000175000017500000000017012742140120026204 0ustar jpakkanejpakkane00000000000000subdir('subdir2') subdir('subdir3') lib1 = shared_library('lib1', 'lib1.c', install : false, link_with : [lib2, lib3]) meson-0.45.1/test cases/common/46 library chain/subdir/lib1.c0000644000175000017500000000060012650745767025065 0ustar jpakkanejpakkane00000000000000int lib2fun(); int lib3fun(); #if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif int DLL_PUBLIC libfun() { return lib2fun() + lib3fun(); } meson-0.45.1/test cases/common/46 library chain/subdir/subdir2/0000755000175000017500000000000013254552747025443 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/46 library chain/subdir/subdir2/meson.build0000644000175000017500000000007112742140120027556 0ustar jpakkanejpakkane00000000000000lib2 = shared_library('lib2', 'lib2.c', install : false) meson-0.45.1/test cases/common/46 library chain/subdir/subdir2/lib2.c0000644000175000017500000000051612650745767026446 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif int DLL_PUBLIC lib2fun() { return 0; } meson-0.45.1/test cases/common/69 string arithmetic/0000755000175000017500000000000013254552747023517 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/69 string arithmetic/meson.build0000644000175000017500000000046113254551760025654 0ustar jpakkanejpakkane00000000000000project('string arithmetic', 'c') if 'foo' + 'bar' != 'foobar' error('String concatenation is broken') endif if 'foo' + 'bar' + 'baz' != 'foobarbaz' error('Many-string concatenation is broken') endif a = 'a' b = 'b' if a + b + 'c' != 'abc' error('String concat with variables is broken.') endif meson-0.45.1/test cases/common/129 object only target/0000755000175000017500000000000013254552746023632 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/129 object only target/installed_files.txt0000644000175000017500000000002113024065327027512 0ustar jpakkanejpakkane00000000000000usr/bin/prog?exe meson-0.45.1/test cases/common/129 object only target/source2.c0000644000175000017500000000004513024065327025344 0ustar jpakkanejpakkane00000000000000int func2_in_obj() { return 0; } meson-0.45.1/test cases/common/129 object only target/source.c0000644000175000017500000000004513024065327025262 0ustar jpakkanejpakkane00000000000000int func1_in_obj() { return 0; } meson-0.45.1/test cases/common/129 object only target/meson.build0000644000175000017500000000232713254552064025771 0ustar jpakkanejpakkane00000000000000project('object generator', 'c') # FIXME: Note that this will not add a dependency to the compiler executable. # Code will not be rebuilt if it changes. comp = find_program('obj_generator.py') if host_machine.system() == 'windows' ext = '.obj' else ext = '.o' endif cc = meson.get_compiler('c').cmd_array().get(-1) # Generate an object file with configure_file to mimic prebuilt objects # provided by the source tree source1 = configure_file(input : 'source.c', output : 'source' + ext, command : [comp, cc, files('source.c'), join_paths(meson.current_build_dir(), 'source' + ext)]) obj = static_library('obj', objects : source1) # Generate an object file manually. gen = generator(comp, output : '@BASENAME@' + ext, arguments : [cc, '@INPUT@', '@OUTPUT@']) generated = gen.process(['source2.c']) shr = shared_library('shr', generated, vs_module_defs : 'source2.def') # Generate an object file with indexed OUTPUT replacement. gen2 = generator(comp, output : '@BASENAME@' + ext, arguments : [cc, '@INPUT@', '@OUTPUT0@']) generated2 = gen2.process(['source3.c']) stc = static_library('stc', generated2) e = executable('prog', 'prog.c', link_with : [obj, shr, stc], install : true) test('objgen', e) meson-0.45.1/test cases/common/129 object only target/source2.def0000644000175000017500000000003513024065327025657 0ustar jpakkanejpakkane00000000000000EXPORTS func2_in_obj meson-0.45.1/test cases/common/129 object only target/prog.c0000644000175000017500000000023613024065327024733 0ustar jpakkanejpakkane00000000000000int func1_in_obj(); int func2_in_obj(); int func3_in_obj(); int main(int argc, char **argv) { return func1_in_obj() + func2_in_obj() + func3_in_obj(); } meson-0.45.1/test cases/common/129 object only target/obj_generator.py0000755000175000017500000000101313057037314027010 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 # Mimic a binary that generates an object file (e.g. windres). import sys, subprocess if __name__ == '__main__': if len(sys.argv) != 4: print(sys.argv[0], 'compiler input_file output_file') sys.exit(1) compiler = sys.argv[1] ifile = sys.argv[2] ofile = sys.argv[3] if compiler.endswith('cl'): cmd = [compiler, '/nologo', '/MDd', '/Fo' + ofile, '/c', ifile] else: cmd = [compiler, '-c', ifile, '-o', ofile] sys.exit(subprocess.call(cmd)) meson-0.45.1/test cases/common/129 object only target/source3.c0000644000175000017500000000004513024065327025345 0ustar jpakkanejpakkane00000000000000int func3_in_obj() { return 0; } meson-0.45.1/test cases/common/58 run target/0000755000175000017500000000000013254552747022150 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/58 run target/configure.in0000755000175000017500000000005013134457413024446 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 print('Success')meson-0.45.1/test cases/common/58 run target/meson.build0000644000175000017500000000274313254551747024317 0ustar jpakkanejpakkane00000000000000project('run target', 'c') # Make it possible to run built programs. # In cross builds exe_wrapper should be added if it exists. exe = executable('helloprinter', 'helloprinter.c') run_target('runhello', command : [exe, 'argument']) converter = find_program('converter.py') hex = custom_target('exe.hex', input : exe, output : 'exe.hex', command : [converter, '@INPUT@', '@OUTPUT@', ], ) fakeburner = find_program('fakeburner.py') # These emulates the Arduino flasher application. It sandwiches the filename inside # a packed argument. Thus we need to declare it manually. run_target('upload', command : [fakeburner, 'x:@0@:y'.format(exe.full_path())], depends : exe, ) run_target('upload2', command : [fakeburner, 'x:@0@:y'.format(hex.full_path())], depends : hex, ) python3 = find_program('python3', required : false) if not python3.found() python3 = find_program('python') endif run_target('py3hi', command : [python3, '-c', 'print("I am Python3.")']) run_target('check_exists', command : [find_program('check_exists.py'), files('helloprinter.c')]) # What if the output of a custom_target is the command to # execute. Obviously this will not work as hex is not an # executable but test that the output is generated correctly. run_target('donotrunme', command : hex) # Ensure configure files can be passed conf = configure_file( input: 'configure.in', output: 'configure', configuration: configuration_data() ) run_target('configure_script', command : conf ) meson-0.45.1/test cases/common/58 run target/scripts/0000755000175000017500000000000013254552747023637 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/58 run target/scripts/script.sh0000755000175000017500000000015512650745767025510 0ustar jpakkanejpakkane00000000000000#!/bin/sh cd "$MESON_SOURCE_ROOT" echo My current directory is `pwd` echo Build dir is at $MESON_BUILD_ROOT meson-0.45.1/test cases/common/58 run target/converter.py0000644000175000017500000000021313057037314024512 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys with open(sys.argv[1], 'rb') as ifile, open(sys.argv[2], 'wb') as ofile: ofile.write(ifile.read()) meson-0.45.1/test cases/common/58 run target/check_exists.py0000755000175000017500000000022013057037314025160 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import os import sys if not os.path.isfile(sys.argv[1]): raise Exception("Couldn't find {!r}".format(sys.argv[1])) meson-0.45.1/test cases/common/58 run target/helloprinter.c0000644000175000017500000000034012650745767025025 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { if(argc != 2) { printf("I can not haz argument.\n"); return 1; } else { printf("I can haz argument: %s\n", argv[1]); } return 0; } meson-0.45.1/test cases/common/58 run target/fakeburner.py0000755000175000017500000000061213057037314024635 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 from __future__ import print_function import sys plain_arg = sys.argv[1] _, filename, _ = plain_arg.split(':') try: with open(filename, 'rb') as f: content = f.read() except FileNotFoundError: print('Could not open file. Missing dependency?') sys.exit(1) print('File opened, pretending to send it somewhere.') print(len(content), 'bytes uploaded') meson-0.45.1/test cases/common/114 multiple dir configure file/0000755000175000017500000000000013254552746025401 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/114 multiple dir configure file/meson.build0000644000175000017500000000045113254552036027533 0ustar jpakkanejpakkane00000000000000project('multiple dir configure file', 'c') subdir('subdir') configure_file(input : 'subdir/someinput.in', output : 'outputhere', configuration : configuration_data()) configure_file(input : cfile1, output : '@BASENAME@', configuration : configuration_data()) meson-0.45.1/test cases/common/114 multiple dir configure file/subdir/0000755000175000017500000000000013254552746026671 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/114 multiple dir configure file/subdir/foo.txt0000644000175000017500000000000013174155420030170 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/114 multiple dir configure file/subdir/meson.build0000644000175000017500000000056513174155420031026 0ustar jpakkanejpakkane00000000000000configure_file(input : 'someinput.in', output : 'outputsubdir', install : false, configuration : configuration_data()) py3 = import('python3').find_python() cfile1 = configure_file(input : 'foo.txt', output : 'foo.h.in', capture : true, command : [py3, '-c', 'print("#mesondefine FOO_BAR")']) meson-0.45.1/test cases/common/114 multiple dir configure file/subdir/someinput.in0000644000175000017500000000000012746700520031220 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/143 custom target object output/0000755000175000017500000000000013254552746025500 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/143 custom target object output/meson.build0000644000175000017500000000045613254552100027627 0ustar jpakkanejpakkane00000000000000project('custom target object output', 'c') comp = find_program('obj_generator.py') if host_machine.system() == 'windows' outputname = '@BASENAME@.obj' else outputname = '@BASENAME@.o' endif cc = meson.get_compiler('c').cmd_array().get(-1) subdir('objdir') subdir('progdir') test('objgen', e) meson-0.45.1/test cases/common/143 custom target object output/progdir/0000755000175000017500000000000013254552746027146 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/143 custom target object output/progdir/meson.build0000644000175000017500000000005113074426732031277 0ustar jpakkanejpakkane00000000000000e = executable('prog', 'prog.c', object) meson-0.45.1/test cases/common/143 custom target object output/progdir/prog.c0000644000175000017500000000012413074426732030251 0ustar jpakkanejpakkane00000000000000int func1_in_obj(); int main(int argc, char **argv) { return func1_in_obj(); } meson-0.45.1/test cases/common/143 custom target object output/obj_generator.py0000644000175000017500000000101313074426732030660 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 # Mimic a binary that generates an object file (e.g. windres). import sys, subprocess if __name__ == '__main__': if len(sys.argv) != 4: print(sys.argv[0], 'compiler input_file output_file') sys.exit(1) compiler = sys.argv[1] ifile = sys.argv[2] ofile = sys.argv[3] if compiler.endswith('cl'): cmd = [compiler, '/nologo', '/MDd', '/Fo' + ofile, '/c', ifile] else: cmd = [compiler, '-c', ifile, '-o', ofile] sys.exit(subprocess.call(cmd)) meson-0.45.1/test cases/common/143 custom target object output/objdir/0000755000175000017500000000000013254552746026751 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/143 custom target object output/objdir/source.c0000644000175000017500000000004513074426732030407 0ustar jpakkanejpakkane00000000000000int func1_in_obj() { return 0; } meson-0.45.1/test cases/common/143 custom target object output/objdir/meson.build0000644000175000017500000000024113074426732031103 0ustar jpakkanejpakkane00000000000000# Generate an object file manually. object = custom_target('object', input : 'source.c', output : outputname, command : [comp, cc, '@INPUT@', '@OUTPUT@']) meson-0.45.1/test cases/common/133 configure file in generator/0000755000175000017500000000000013254552746025365 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/133 configure file in generator/meson.build0000644000175000017500000000010413254552067027516 0ustar jpakkanejpakkane00000000000000project('conf file in generator', 'c') subdir('inc') subdir('src') meson-0.45.1/test cases/common/133 configure file in generator/src/0000755000175000017500000000000013254552746026154 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/133 configure file in generator/src/gen.py0000755000175000017500000000035013057037314027266 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys ifile = sys.argv[1] ofile = sys.argv[2] with open(ifile, 'r') as f: resval = f.readline().strip() templ = '#define RESULT (%s)\n' with open(ofile, 'w') as f: f.write(templ % (resval, )) meson-0.45.1/test cases/common/133 configure file in generator/src/main.c0000644000175000017500000000042113037214503027222 0ustar jpakkanejpakkane00000000000000#include #include"confdata.h" #if RESULT != 42 #error Configuration RESULT is not defined correctly #endif #undef RESULT #include"source.h" #if RESULT != 23 #error Source RESULT is not defined correctly #endif int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/133 configure file in generator/src/meson.build0000644000175000017500000000031313037214503030274 0ustar jpakkanejpakkane00000000000000compiler = find_program('gen.py') gen = generator(compiler, output: '@BASENAME@.h', arguments : ['@INPUT@', '@OUTPUT@']) hs = gen.process(cfile, files('source')) executable('proggie', 'main.c', hs) meson-0.45.1/test cases/common/133 configure file in generator/src/source0000644000175000017500000000000313037214503027351 0ustar jpakkanejpakkane0000000000000023 meson-0.45.1/test cases/common/133 configure file in generator/inc/0000755000175000017500000000000013254552746026136 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/133 configure file in generator/inc/confdata.in0000644000175000017500000000001013037214503030215 0ustar jpakkanejpakkane00000000000000@VALUE@ meson-0.45.1/test cases/common/133 configure file in generator/inc/meson.build0000644000175000017500000000022113037214503030254 0ustar jpakkanejpakkane00000000000000cdata = configuration_data() cdata.set('VALUE', '42') cfile = configure_file(input : 'confdata.in', output : 'confdata', configuration : cdata) meson-0.45.1/test cases/common/126 llvm ir and assembly/0000755000175000017500000000000013254552746024040 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/126 llvm ir and assembly/main.c0000644000175000017500000000034713024065327025121 0ustar jpakkanejpakkane00000000000000#include unsigned square_unsigned (unsigned a); int main (int argc, char * argv[]) { unsigned int ret = square_unsigned (2); if (ret != 4) { printf("Got %u instead of 4\n", ret); return 1; } return 0; } meson-0.45.1/test cases/common/126 llvm ir and assembly/symbol-underscore.h0000644000175000017500000000017313024065327027653 0ustar jpakkanejpakkane00000000000000#if defined(MESON_TEST__UNDERSCORE_SYMBOL) # define SYMBOL_NAME(name) _##name #else # define SYMBOL_NAME(name) name #endif meson-0.45.1/test cases/common/126 llvm ir and assembly/main.cpp0000644000175000017500000000037013024065327025455 0ustar jpakkanejpakkane00000000000000#include extern "C" { unsigned square_unsigned (unsigned a); } int main (int argc, char * argv[]) { unsigned int ret = square_unsigned (2); if (ret != 4) { printf("Got %u instead of 4\n", ret); return 1; } return 0; } meson-0.45.1/test cases/common/126 llvm ir and assembly/meson.build0000644000175000017500000000443713254552060026177 0ustar jpakkanejpakkane00000000000000project('llvm-ir', 'c', 'cpp') cpu = host_machine.cpu_family() supported_cpus = ['arm', 'x86', 'x86_64'] foreach lang : ['c', 'cpp'] cc = meson.get_compiler(lang) cc_id = cc.get_id() ## Build a trivial executable with mixed LLVM IR source if cc_id == 'clang' e = executable('square_ir_' + lang, 'square.ll', 'main.' + lang) test('test IR square' + lang, e) endif ## Build a trivial executable with mixed assembly source # This also helps test whether cc.symbols_have_underscore_prefix() is working # properly. This is done by assembling some assembly into an object that will # provide the unsigned_squared() symbol to main.c/cpp. This requires the # C symbol mangling to be known in advance. if cc.symbols_have_underscore_prefix() uscore_args = ['-DMESON_TEST__UNDERSCORE_SYMBOL'] message('underscore is prefixed') else uscore_args = [] message('underscore is NOT prefixed') endif square_base = 'square-' + cpu square_impl = square_base + '.S' # MSVC cannot directly compile assembly files, so we pass it through the # cl.exe pre-processor first and then assemble it with the ml.exe assembler. # Then we can link it into the executable. if cc_id == 'msvc' cl = find_program('cl') if cpu == 'x86' ml = find_program('ml') elif cpu == 'x86_64' ml = find_program('ml64') else error('Unsupported cpu family: "' + cpu + '"') endif # Preprocess file (ml doesn't support pre-processing) preproc_name = lang + square_base + '.i' square_preproc = custom_target(lang + square_impl + 'preproc', input : square_impl, output : preproc_name, command : [cl, '/EP', '/P', '/Fi' + preproc_name, '@INPUT@'] + uscore_args) # Use assembled object file instead of the original .S assembly source square_impl = custom_target(lang + square_impl, input : square_preproc, output : lang + square_base + '.obj', command : [ml, '/Fo', '@OUTPUT@', '/c', '@INPUT@']) endif if supported_cpus.contains(cpu) e = executable('square_asm_' + lang, square_impl, 'main.' + lang, c_args : uscore_args, cpp_args : uscore_args) test('test ASM square' + lang, e) elif cc_id != 'clang' error('MESON_SKIP_TEST: Unsupported cpu: "' + cpu + '", and LLVM not found') endif endforeach meson-0.45.1/test cases/common/126 llvm ir and assembly/square-arm.S0000644000175000017500000000031313135663205026225 0ustar jpakkanejpakkane00000000000000#include "symbol-underscore.h" .text .globl SYMBOL_NAME(square_unsigned) # ifdef __linux__ .type square_unsigned, %function #endif SYMBOL_NAME(square_unsigned): mul r1, r0, r0 mov r0, r1 mov pc, lr meson-0.45.1/test cases/common/126 llvm ir and assembly/square-x86.S0000644000175000017500000000107513135663205026101 0ustar jpakkanejpakkane00000000000000#include "symbol-underscore.h" /* This sadly doesn't test the symbol underscore stuff. I can't figure out how * to not use an automatic stdcall mechanism and do everything manually. */ #ifdef _MSC_VER .386 .MODEL FLAT, C PUBLIC square_unsigned _TEXT SEGMENT square_unsigned PROC var1:DWORD mov eax, var1 imul eax, eax ret square_unsigned ENDP _TEXT ENDS END #else .text .globl SYMBOL_NAME(square_unsigned) # ifdef __linux__ .type square_unsigned, %function #endif SYMBOL_NAME(square_unsigned): movl 4(%esp), %eax imull %eax, %eax retl #endif meson-0.45.1/test cases/common/126 llvm ir and assembly/square.ll0000644000175000017500000000011313024065327025651 0ustar jpakkanejpakkane00000000000000define i32 @square_unsigned(i32 %a) { %1 = mul i32 %a, %a ret i32 %1 } meson-0.45.1/test cases/common/126 llvm ir and assembly/square-x86_64.S0000644000175000017500000000112713135663205026410 0ustar jpakkanejpakkane00000000000000#include "symbol-underscore.h" #ifdef _MSC_VER /* MSVC on Windows */ PUBLIC SYMBOL_NAME(square_unsigned) _TEXT SEGMENT SYMBOL_NAME(square_unsigned) PROC mov eax, ecx imul eax, eax ret SYMBOL_NAME(square_unsigned) ENDP _TEXT ENDS END #else .text .globl SYMBOL_NAME(square_unsigned) # ifdef __linux__ .type square_unsigned, %function #endif # if defined(_WIN32) || defined(__CYGWIN__) /* msabi */ SYMBOL_NAME(square_unsigned): imull %ecx, %ecx movl %ecx, %eax retq # else /* sysvabi */ SYMBOL_NAME(square_unsigned): imull %edi, %edi movl %edi, %eax retq # endif #endif meson-0.45.1/test cases/common/17 if/0000755000175000017500000000000013254552747020466 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/17 if/meson.build0000644000175000017500000000074313254551650022624 0ustar jpakkanejpakkane00000000000000project('if test', 'c') var1 = true set_variable('var2', false) if var1 exe = executable('prog', 'prog.c') endif if var2 exe = executable('breakbreakbreak', 'crashing.c') endif test('iftest', exe) if not is_variable('var1') error('Is_variable fail.') endif if is_variable('nonexisting') error('Is_variable fail 2.') endif if not get_variable('var1', false) error('Get_variable fail.') endif if get_variable('nonexisting', false) error('Get_variable fail.') endif meson-0.45.1/test cases/common/17 if/prog.c0000644000175000017500000000005612650745767021607 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/117 custom target capture/0000755000175000017500000000000013254552746024355 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/117 custom target capture/installed_files.txt0000644000175000017500000000002412763077471030254 0ustar jpakkanejpakkane00000000000000usr/subdir/data.dat meson-0.45.1/test cases/common/117 custom target capture/meson.build0000644000175000017500000000125713254552043026512 0ustar jpakkanejpakkane00000000000000project('custom target', 'c') python3 = import('python3').find_python() # Note that this will not add a dependency to the compiler executable. # Code will not be rebuilt if it changes. comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py') mytarget = custom_target('bindat', output : 'data.dat', input : 'data_source.txt', capture : true, command : [python3, comp, '@INPUT@'], install : true, install_dir : 'subdir' ) ct_output_exists = '''import os, sys if not os.path.exists(sys.argv[1]): print("could not find {!r} in {!r}".format(sys.argv[1], os.getcwd())) sys.exit(1) ''' test('capture-wrote', python3, args : ['-c', ct_output_exists, mytarget]) meson-0.45.1/test cases/common/117 custom target capture/data_source.txt0000644000175000017500000000004012763077471027402 0ustar jpakkanejpakkane00000000000000This is a text only input file. meson-0.45.1/test cases/common/117 custom target capture/my_compiler.py0000755000175000017500000000054612763077471027257 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys if __name__ == '__main__': if len(sys.argv) != 2: print(sys.argv[0], 'input_file') sys.exit(1) with open(sys.argv[1]) as f: ifile = f.read() if ifile != 'This is a text only input file.\n': print('Malformed input') sys.exit(1) print('This is a binary output file.') meson-0.45.1/test cases/common/48 test args/0000755000175000017500000000000013254552747021770 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/48 test args/tester.py0000755000175000017500000000016613057037314023643 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys with open(sys.argv[1]) as f: if f.read() != 'contents\n': sys.exit(1) meson-0.45.1/test cases/common/48 test args/env2vars.c0000644000175000017500000000121313012152443023654 0ustar jpakkanejpakkane00000000000000#include #include #include int main(int argc, char **argv) { if(strcmp(getenv("first"), "something-else") != 0) { fprintf(stderr, "First envvar is wrong. %s\n", getenv("first")); return 1; } if(strcmp(getenv("second"), "val2") != 0) { fprintf(stderr, "Second envvar is wrong.\n"); return 1; } if(strcmp(getenv("third"), "val3:and_more") != 0) { fprintf(stderr, "Third envvar is wrong.\n"); return 1; } if(strstr(getenv("PATH"), "fakepath:") != NULL) { fprintf(stderr, "Third envvar is wrong.\n"); return 1; } return 0; } meson-0.45.1/test cases/common/48 test args/meson.build0000644000175000017500000000244513254551726024133 0ustar jpakkanejpakkane00000000000000project('test features', 'c') e1 = executable('cmd_args', 'cmd_args.c') e2 = executable('envvars', 'envvars.c') e3 = executable('env2vars', 'env2vars.c') env = environment() env.set('first', 'val1') env.set('second', 'val2') env.set('third', 'val3', 'and_more', separator: ':') env.append('PATH', 'fakepath', separator: ':') # Make sure environment objects are copied on assignment and we can # change the copy without affecting the original environment object. env2 = env env2.set('first', 'something-else') test('command line arguments', e1, args : ['first', 'second']) test('environment variables', e2, env : env) test('environment variables 2', e3, env : env2) # https://github.com/mesonbuild/meson/issues/2211#issuecomment-327741571 env_array = ['MESONTESTING=picklerror'] testfile = files('testfile.txt') testerpy = find_program('tester.py') test('file arg', testerpy, args : testfile, env : env_array) copy = find_program('copyfile.py') tester = executable('tester', 'tester.c') testfilect = custom_target('testfile', input : testfile, output : 'outfile.txt', build_by_default : true, command : [copy, '@INPUT@', '@OUTPUT@']) test('custom target arg', tester, args : testfilect, env : env_array) meson-0.45.1/test cases/common/48 test args/copyfile.py0000644000175000017500000000013413174155420024136 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys import shutil shutil.copyfile(sys.argv[1], sys.argv[2]) meson-0.45.1/test cases/common/48 test args/envvars.c0000644000175000017500000000120112767063125023605 0ustar jpakkanejpakkane00000000000000#include #include #include int main(int argc, char **argv) { if(strcmp(getenv("first"), "val1") != 0) { fprintf(stderr, "First envvar is wrong. %s\n", getenv("first")); return 1; } if(strcmp(getenv("second"), "val2") != 0) { fprintf(stderr, "Second envvar is wrong.\n"); return 1; } if(strcmp(getenv("third"), "val3:and_more") != 0) { fprintf(stderr, "Third envvar is wrong.\n"); return 1; } if(strstr(getenv("PATH"), "fakepath:") != NULL) { fprintf(stderr, "Third envvar is wrong.\n"); return 1; } return 0; } meson-0.45.1/test cases/common/48 test args/tester.c0000644000175000017500000000134013174155420023424 0ustar jpakkanejpakkane00000000000000#include #include #include #include #ifndef _MSC_VER #include #endif int main(int argc, char **argv) { char data[10]; int fd, size; if (argc != 2) { fprintf(stderr, "Incorrect number of arguments, got %i\n", argc); return 1; } fd = open(argv[1], O_RDONLY); if (fd < 0) { fprintf(stderr, "First argument is wrong.\n"); return 1; } size = read(fd, data, 8); if (size < 0) { fprintf(stderr, "Failed to read: %s\n", strerror(errno)); return 1; } if (strncmp(data, "contents", 8) != 0) { fprintf(stderr, "Contents don't match, got %s\n", data); return 1; } return 0; } meson-0.45.1/test cases/common/48 test args/cmd_args.c0000644000175000017500000000066112650745767023723 0ustar jpakkanejpakkane00000000000000#include #include int main(int argc, char **argv) { if(argc != 3) { fprintf(stderr, "Incorrect number of arguments.\n"); return 1; } if(strcmp(argv[1], "first") != 0) { fprintf(stderr, "First argument is wrong.\n"); return 1; } if(strcmp(argv[2], "second") != 0) { fprintf(stderr, "Second argument is wrong.\n"); return 1; } return 0; } meson-0.45.1/test cases/common/48 test args/testfile.txt0000644000175000017500000000001112650745767024345 0ustar jpakkanejpakkane00000000000000contents meson-0.45.1/test cases/common/174 dependency factory/0000755000175000017500000000000013254552747023722 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/174 dependency factory/meson.build0000644000175000017500000000315613254552137026062 0ustar jpakkanejpakkane00000000000000project('dependency factory') dep = dependency('gl', method: 'pkg-config', required: false) if dep.found() and dep.type_name() == 'pkgconfig' dep.get_pkgconfig_variable('prefix') endif dep = dependency('SDL2', method: 'pkg-config', required: false) if dep.found() and dep.type_name() == 'pkgconfig' dep.get_pkgconfig_variable('prefix') endif dep = dependency('SDL2', method: 'config-tool', required: false) if dep.found() and dep.type_name() == 'configtool' dep.get_configtool_variable('prefix') endif dep = dependency('Vulkan', method: 'pkg-config', required: false) if dep.found() and dep.type_name() == 'pkgconfig' dep.get_pkgconfig_variable('prefix') endif dep = dependency('pcap', method: 'pkg-config', required: false) if dep.found() and dep.type_name() == 'pkgconfig' dep.get_pkgconfig_variable('prefix') endif dep = dependency('pcap', method: 'config-tool', required: false) if dep.found() and dep.type_name() == 'configtool' dep.get_configtool_variable('prefix') endif dep = dependency('cups', method: 'pkg-config', required: false) if dep.found() and dep.type_name() == 'pkgconfig' dep.get_pkgconfig_variable('prefix') endif dep = dependency('cups', method: 'config-tool', required: false) if dep.found() and dep.type_name() == 'configtool' dep.get_configtool_variable('prefix') endif dep = dependency('libwmf', method: 'pkg-config', required: false) if dep.found() and dep.type_name() == 'pkgconfig' dep.get_pkgconfig_variable('prefix') endif dep = dependency('libwmf', method: 'config-tool', required: false) if dep.found() and dep.type_name() == 'configtool' dep.get_configtool_variable('prefix') endif meson-0.45.1/test cases/common/9 header install/0000755000175000017500000000000013254552750022662 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/9 header install/subdir.h0000644000175000017500000000011212650745767024330 0ustar jpakkanejpakkane00000000000000/* This file goes to subdirectory of include root. */ int subdir_func(); meson-0.45.1/test cases/common/9 header install/vanishing_subdir/0000755000175000017500000000000013254552750026220 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/9 header install/vanishing_subdir/meson.build0000644000175000017500000000003612650745767030374 0ustar jpakkanejpakkane00000000000000install_headers('vanished.h') meson-0.45.1/test cases/common/9 header install/vanishing_subdir/vanished.h0000644000175000017500000000022112650745767030200 0ustar jpakkanejpakkane00000000000000#pragma once /* This is a header in a subdirectory. Make sure it installs into * /prefix/include and not /prefix/include/vanishing_subdir. */ meson-0.45.1/test cases/common/9 header install/rootdir.h0000644000175000017500000000007612650745767024533 0ustar jpakkanejpakkane00000000000000/* This header goes to include dir root. */ int root_func(); meson-0.45.1/test cases/common/9 header install/installed_files.txt0000644000175000017500000000014213016624375026560 0ustar jpakkanejpakkane00000000000000usr/include/rootdir.h usr/include/subdir/subdir.h usr/include/vanished.h usr/include/fileheader.h meson-0.45.1/test cases/common/9 header install/meson.build0000644000175000017500000000032313254551641025020 0ustar jpakkanejpakkane00000000000000project('header install') as_array = ['subdir.h'] subdir('vanishing_subdir') subdir('sub') h1 = install_headers('rootdir.h') h2 = install_headers(as_array, subdir : 'subdir') h3 = install_headers(subheader) meson-0.45.1/test cases/common/9 header install/sub/0000755000175000017500000000000013254552750023453 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/9 header install/sub/meson.build0000644000175000017500000000004313016624375025611 0ustar jpakkanejpakkane00000000000000subheader = files('fileheader.h') meson-0.45.1/test cases/common/9 header install/sub/fileheader.h0000644000175000017500000000007113016624375025711 0ustar jpakkanejpakkane00000000000000#pragma once #define LIFE "Is life! Na naa, naa-na na." meson-0.45.1/test cases/common/159 reserved targets/0000755000175000017500000000000013254552746023427 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/dist/0000755000175000017500000000000013254552746024372 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/dist/meson.build0000644000175000017500000000004513144414313026514 0ustar jpakkanejpakkane00000000000000executable('test-dist', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/test.c0000644000175000017500000000006113144414313024530 0ustar jpakkanejpakkane00000000000000int main(int argc, char *argv[]) { return 0; } meson-0.45.1/test cases/common/159 reserved targets/reconfigure/0000755000175000017500000000000013254552746025737 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/reconfigure/meson.build0000644000175000017500000000005413144414313030061 0ustar jpakkanejpakkane00000000000000executable('test-reconfigure', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/all/0000755000175000017500000000000013254552746024177 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/all/meson.build0000644000175000017500000000004413144414313026320 0ustar jpakkanejpakkane00000000000000executable('test-all', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/clean-gcda/0000755000175000017500000000000013254552746025405 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/clean-gcda/meson.build0000644000175000017500000000005313144414313027526 0ustar jpakkanejpakkane00000000000000executable('test-clean-gcda', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/test/0000755000175000017500000000000013254552746024406 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/test/meson.build0000644000175000017500000000004513144414313026530 0ustar jpakkanejpakkane00000000000000executable('test-test', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/benchmark/0000755000175000017500000000000013254552746025361 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/benchmark/meson.build0000644000175000017500000000005213144414313027501 0ustar jpakkanejpakkane00000000000000executable('test-benchmark', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/clean-ctlist/0000755000175000017500000000000013254552746026011 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/clean-ctlist/meson.build0000644000175000017500000000005513144414313030134 0ustar jpakkanejpakkane00000000000000executable('test-clean-ctlist', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/uninstall/0000755000175000017500000000000013254552746025440 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/uninstall/meson.build0000644000175000017500000000005213144414313027560 0ustar jpakkanejpakkane00000000000000executable('test-uninstall', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/distcheck/0000755000175000017500000000000013254552746025370 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/distcheck/meson.build0000644000175000017500000000005213144414313027510 0ustar jpakkanejpakkane00000000000000executable('test-distcheck', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/phony/0000755000175000017500000000000013254552746024564 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/phony/meson.build0000644000175000017500000000004613144414313026707 0ustar jpakkanejpakkane00000000000000executable('test-phony', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/coverage-html/0000755000175000017500000000000013254552746026164 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/coverage-html/meson.build0000644000175000017500000000005613144414313030310 0ustar jpakkanejpakkane00000000000000executable('test-coverage-html', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/meson.build0000644000175000017500000000155713254552121025564 0ustar jpakkanejpakkane00000000000000project('reserved target names', 'c') # FIXME: Setting this causes it to leak to all other tests #default_options : ['b_coverage=true'] subdir('all') subdir('benchmark') subdir('clean') subdir('clean-ctlist') subdir('clean-gcda') subdir('clean-gcno') subdir('coverage') subdir('coverage-html') subdir('coverage-text') subdir('coverage-xml') subdir('dist') subdir('distcheck') subdir('install') # We don't have a 'PHONY' directory because Windows and OSX # choke horribly when there are two entries with the same # name but different case. subdir('phony') subdir('reconfigure') subdir('scan-build') subdir('test') subdir('uninstall') subdir('runtarget') py3 = import('python3').find_python() custom_target('ctlist-test', output : 'out.txt', command : [py3, '-c', 'print("")'], capture : true, build_by_default : true) meson-0.45.1/test cases/common/159 reserved targets/install/0000755000175000017500000000000013254552746025075 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/install/meson.build0000644000175000017500000000005013144414313027213 0ustar jpakkanejpakkane00000000000000executable('test-install', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/clean/0000755000175000017500000000000013254552746024511 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/clean/meson.build0000644000175000017500000000004613144414313026634 0ustar jpakkanejpakkane00000000000000executable('test-clean', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/clean-gcno/0000755000175000017500000000000013254552746025435 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/clean-gcno/meson.build0000644000175000017500000000005313144414313027556 0ustar jpakkanejpakkane00000000000000executable('test-clean-gcno', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/coverage-xml/0000755000175000017500000000000013254552746026020 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/coverage-xml/meson.build0000644000175000017500000000005513144414313030143 0ustar jpakkanejpakkane00000000000000executable('test-coverage-xml', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/coverage/0000755000175000017500000000000013254552746025222 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/coverage/meson.build0000644000175000017500000000005113144414313027341 0ustar jpakkanejpakkane00000000000000executable('test-coverage', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/coverage-text/0000755000175000017500000000000013254552746026204 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/coverage-text/meson.build0000644000175000017500000000005613144414313030330 0ustar jpakkanejpakkane00000000000000executable('test-coverage-text', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/scan-build/0000755000175000017500000000000013254552746025450 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/scan-build/meson.build0000644000175000017500000000005313144414313027571 0ustar jpakkanejpakkane00000000000000executable('test-scan-build', '../test.c') meson-0.45.1/test cases/common/159 reserved targets/runtarget/0000755000175000017500000000000013254552746025442 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/159 reserved targets/runtarget/meson.build0000644000175000017500000000016513144414313027567 0ustar jpakkanejpakkane00000000000000configure_file(output : 'config.h', configuration: configuration_data()) run_target('runtarget', command : ['echo']) meson-0.45.1/test cases/common/146 C and CPP link/0000755000175000017500000000000013254552746022400 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/146 C and CPP link/foobar.h0000644000175000017500000000116013076637146024017 0ustar jpakkanejpakkane00000000000000/* Copyright Ā© 2017 Dylan Baker * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * 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. */ void mynumbers(int nums[]); meson-0.45.1/test cases/common/146 C and CPP link/foo.c0000644000175000017500000000121413076637146023325 0ustar jpakkanejpakkane00000000000000/* Copyright Ā© 2017 Dylan Baker * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * 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. */ #include "foo.h" int forty_two(void) { return 42; } meson-0.45.1/test cases/common/146 C and CPP link/sub.c0000644000175000017500000000121313174155420023317 0ustar jpakkanejpakkane00000000000000/* Copyright Ā© 2017 Dylan Baker * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * 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. */ #include "sub.h" float a_half(void) { return .5; } meson-0.45.1/test cases/common/146 C and CPP link/foo.cpp0000644000175000017500000000156513076637146023676 0ustar jpakkanejpakkane00000000000000/* Copyright Ā© 2017 Dylan Baker * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * 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. */ #include const int cnums[] = {0, 61}; template std::vector makeVector(const T (&data)[N]) { return std::vector(data, data+N); } namespace { std::vector numbers = makeVector(cnums); } extern "C" int six_one(void) { return numbers[1]; } meson-0.45.1/test cases/common/146 C and CPP link/meson.build0000644000175000017500000000565113254552105024536 0ustar jpakkanejpakkane00000000000000# Copyright Ā© 2017 Dylan Baker # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. project('C and C++ static link test', ['c', 'cpp']) # Verify that adding link arguments works. add_global_link_arguments('', language : 'c') add_project_link_arguments('', language : 'c') libc = static_library('cfoo', ['foo.c', 'foo.h']) # Test that linking C libs to external static C++ libs uses the C++ linker # Since we can't depend on the test system to provide this, we create one # ourselves at configure time and then 'find' it with cxx.find_library(). cxx = meson.get_compiler('cpp') if cxx.get_id() == 'msvc' compile_cmd = ['/c', '@INPUT@', '/Fo@OUTPUT@'] stlib_cmd = ['lib', '/OUT:@OUTPUT@', '@INPUT@'] else compile_cmd = ['-c', '-fPIC', '@INPUT@', '-o', '@OUTPUT@'] stlib_cmd = ['ar', 'csr', '@OUTPUT@', '@INPUT@'] endif foo_cpp_o = configure_file( input : 'foo.cpp', output : 'foo.cpp.o', command : cxx.cmd_array() + compile_cmd) configure_file( input : foo_cpp_o, output : 'libstcppext.a', command : stlib_cmd) libstcppext = cxx.find_library('stcppext', dirs : meson.current_build_dir()) libfooext = shared_library( 'fooext', ['foobar.c', 'foobar.h'], link_with : libc, dependencies : libstcppext, ) # Test that linking C libs to internal static C++ libs uses the C++ linker libcpp = static_library('cppfoo', ['foo.cpp', 'foo.hpp']) libfoo = shared_library( 'foo', ['foobar.c', 'foobar.h'], link_with : [libc, libcpp], ) # Test that link_whole is also honored # # VS2010 lacks the /WHOLEARCHIVE option that later versions of MSVC support, so # don't run this tests on that backend. if not (cxx.get_id() == 'msvc' and cxx.version().version_compare('<19')) libfoowhole = shared_library( 'foowhole', ['foobar.c', 'foobar.h'], link_whole : [libc, libcpp], ) endif # Test sublinking (linking C and C++, then linking that to C) libfoo_static = static_library( 'foo_static', ['foobar.c', 'foobar.h'], link_with : [libc, libcpp], ) libsub = shared_library( 'sub', ['sub.c', 'sub.h'], link_with : libfoo_static, ) if not (cxx.get_id() == 'msvc' and cxx.version().version_compare('<19')) libsubwhole = shared_library( 'subwhole', ['sub.c', 'sub.h'], link_whole : libfoo_static, ) endif # Test that it really is recursive libsub_static = static_library( 'sub_static', ['sub.c', 'sub.h'], link_with : libfoo_static, ) libsubsub = shared_library( 'subsub', ['dummy.c'], link_with : libsub_static, ) meson-0.45.1/test cases/common/146 C and CPP link/sub.h0000644000175000017500000000115013174155420023324 0ustar jpakkanejpakkane00000000000000/* Copyright Ā© 2017 Dylan Baker * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * 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. */ float a_half(void); meson-0.45.1/test cases/common/146 C and CPP link/foo.h0000644000175000017500000000115113076637146023332 0ustar jpakkanejpakkane00000000000000/* Copyright Ā© 2017 Dylan Baker * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * 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. */ int forty_two(void); meson-0.45.1/test cases/common/146 C and CPP link/dummy.c0000644000175000017500000000000013174155420023652 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/146 C and CPP link/foo.hpp0000644000175000017500000000125413076637146023676 0ustar jpakkanejpakkane00000000000000/* Copyright Ā© 2017 Dylan Baker * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * 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. */ #ifdef __cplusplus extern "C" { #endif int six_one(void); #ifdef __cplusplus } #endif meson-0.45.1/test cases/common/146 C and CPP link/foobar.c0000644000175000017500000000134013076637146024012 0ustar jpakkanejpakkane00000000000000/* Copyright Ā© 2017 Dylan Baker * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * 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. */ #include "foo.h" #include "foo.hpp" #include "foobar.h" void mynumbers(int nums[]) { nums[0] = forty_two(); nums[1] = six_one(); } meson-0.45.1/test cases/common/95 dep fallback/0000755000175000017500000000000013254552750022360 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/95 dep fallback/subprojects/0000755000175000017500000000000013254552745024727 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/95 dep fallback/subprojects/dummylib/0000755000175000017500000000000013254552750026545 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/95 dep fallback/subprojects/dummylib/meson.build0000644000175000017500000000014713012152443030674 0ustar jpakkanejpakkane00000000000000project('dummylib', 'c') dummy_dep = declare_dependency() error('this subproject fails to configure') meson-0.45.1/test cases/common/95 dep fallback/subprojects/boblib/0000755000175000017500000000000013254552750026154 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/95 dep fallback/subprojects/boblib/meson.build0000644000175000017500000000066712774524535030335 0ustar jpakkanejpakkane00000000000000project('bob', 'c') gensrc_py = find_program('genbob.py') genbob_h = custom_target('genbob.h', output : 'genbob.h', command : [gensrc_py, '@OUTPUT@']) genbob_c = custom_target('genbob.c', output : 'genbob.c', command : [gensrc_py, '@OUTPUT@']) boblib = library('bob', ['bob.c', genbob_c]) bobinc = include_directories('.') bob_dep = declare_dependency(link_with : boblib, sources : [genbob_h], include_directories : bobinc) meson-0.45.1/test cases/common/95 dep fallback/subprojects/boblib/genbob.py0000644000175000017500000000012613057037314027754 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys with open(sys.argv[1], 'w') as f: f.write('') meson-0.45.1/test cases/common/95 dep fallback/subprojects/boblib/bob.h0000644000175000017500000000012212774524535027070 0ustar jpakkanejpakkane00000000000000#pragma once #ifdef _MSC_VER __declspec(dllimport) #endif const char* get_bob(); meson-0.45.1/test cases/common/95 dep fallback/subprojects/boblib/bob.c0000644000175000017500000000015212774524535027066 0ustar jpakkanejpakkane00000000000000#include"bob.h" #ifdef _MSC_VER __declspec(dllexport) #endif const char* get_bob() { return "bob"; } meson-0.45.1/test cases/common/95 dep fallback/meson.build0000644000175000017500000000152113254552015024513 0ustar jpakkanejpakkane00000000000000project('dep fallback', 'c') bob = dependency('boblib', fallback : ['boblib', 'bob_dep'], required: false, default_options : 'warning_level=1') if not bob.found() error('Bob is actually needed') endif # boblib subproject exists, but sita_dep doesn't exist sita = dependency('sitalib', fallback : ['boblib', 'sita_dep'], required: false) # jimmylib subproject doesn't exist jimmy = dependency('jimmylib', fallback : ['jimmylib', 'jimmy_dep'], required: false) # dummylib subproject fails to configure dummy = dependency('dummylib', fallback : ['dummylib', 'dummy_dep'], required: false) gensrc_py = find_program('gensrc.py') gensrc = custom_target('gensrc.c', input : 'tester.c', output : 'gensrc.c', command : [gensrc_py, '@INPUT@', '@OUTPUT@']) exe = executable('bobtester', [gensrc], dependencies : bob) test('bobtester', exe) meson-0.45.1/test cases/common/95 dep fallback/gensrc.py0000644000175000017500000000013413057037314024204 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys import shutil shutil.copyfile(sys.argv[1], sys.argv[2]) meson-0.45.1/test cases/common/95 dep fallback/tester.c0000644000175000017500000000043412774524535024041 0ustar jpakkanejpakkane00000000000000#include"bob.h" #include"genbob.h" #include #include int main(int argc, char **argv) { if(strcmp("bob", get_bob()) == 0) { printf("Bob is indeed bob.\n"); } else { printf("ERROR: bob is not bob.\n"); return 1; } return 0; } meson-0.45.1/test cases/common/110 extract same name/0000755000175000017500000000000013254552746023422 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/110 extract same name/main.c0000644000175000017500000000015512677267452024520 0ustar jpakkanejpakkane00000000000000int func1(); int func2(); int main(int argc, char **argv) { return !(func1() == 23 && func2() == 42); } meson-0.45.1/test cases/common/110 extract same name/lib.c0000644000175000017500000000003712677267452024341 0ustar jpakkanejpakkane00000000000000int func1() { return 23; } meson-0.45.1/test cases/common/110 extract same name/meson.build0000644000175000017500000000042013254552032025544 0ustar jpakkanejpakkane00000000000000project('object extraction', 'c') lib = shared_library('somelib', ['lib.c', 'src/lib.c']) # Also tests that the object list is flattened properly obj = lib.extract_objects(['lib.c', ['src/lib.c']]) exe = executable('main', 'main.c', objects: obj) test('extraction', exe) meson-0.45.1/test cases/common/110 extract same name/src/0000755000175000017500000000000013254552746024211 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/110 extract same name/src/lib.c0000644000175000017500000000003712677267452025130 0ustar jpakkanejpakkane00000000000000int func2() { return 42; } meson-0.45.1/test cases/common/2 cpp/0000755000175000017500000000000013254552747020564 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/2 cpp/something.txt0000644000175000017500000000010612650745767023324 0ustar jpakkanejpakkane00000000000000This file is only here so it shows up in IDEs as part of this target. meson-0.45.1/test cases/common/2 cpp/trivial.cc0000644000175000017500000000017412650745767022554 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { std::cout << "C++ seems to be working." << std::endl; return 0; } meson-0.45.1/test cases/common/2 cpp/meson.build0000644000175000017500000000045213254551630022715 0ustar jpakkanejpakkane00000000000000project('c++ test', 'cpp') if meson.get_compiler('cpp').get_id() == 'intel' # Error out if the -std=xxx option is incorrect add_project_arguments('-diag-error', '10159', language : 'cpp') endif exe = executable('trivialprog', 'trivial.cc', extra_files : 'something.txt') test('runtest', exe) meson-0.45.1/test cases/common/30 pipeline/0000755000175000017500000000000013254552747021670 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/30 pipeline/meson.build0000644000175000017500000000020013254551667024022 0ustar jpakkanejpakkane00000000000000project('pipeline test', 'c') # This is in a subdirectory to make sure # we write proper subdir paths to output. subdir('src') meson-0.45.1/test cases/common/30 pipeline/src/0000755000175000017500000000000013254552747022457 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/30 pipeline/src/meson.build0000644000175000017500000000045612650745767024633 0ustar jpakkanejpakkane00000000000000e1 = executable('srcgen', 'srcgen.c', native : true) # Generate a header file that needs to be included. gen = generator(e1, output : '@BASENAME@.h', arguments : ['@INPUT@', '@OUTPUT@']) generated = gen.process('input_src.dat') e2 = executable('prog', 'prog.c', generated) test('pipelined', e2) meson-0.45.1/test cases/common/30 pipeline/src/srcgen.c0000644000175000017500000000160512650745767024113 0ustar jpakkanejpakkane00000000000000#include #include #define ARRSIZE 80 int main(int argc, char **argv) { char arr[ARRSIZE]; char *ifilename; char *ofilename; FILE *ifile; FILE *ofile; size_t bytes; if(argc != 3) { fprintf(stderr, "%s \n", argv[0]); return 1; } ifilename = argv[1]; ofilename = argv[2]; printf("%s\n", ifilename); ifile = fopen(ifilename, "r"); if(!ifile) { fprintf(stderr, "Could not open source file %s.\n", ifilename); return 1; } ofile = fopen(ofilename, "w"); if(!ofile) { fprintf(stderr, "Could not open target file %s\n", ofilename); fclose(ifile); return 1; } bytes = fread(arr, 1, ARRSIZE, ifile); assert(bytes < 80); assert(bytes > 0); fwrite(arr, 1, bytes, ofile); fclose(ifile); fclose(ofile); return 0; } meson-0.45.1/test cases/common/30 pipeline/src/input_src.dat0000644000175000017500000000002212650745767025156 0ustar jpakkanejpakkane00000000000000#include meson-0.45.1/test cases/common/30 pipeline/src/prog.c0000644000175000017500000000020712650745767023576 0ustar jpakkanejpakkane00000000000000#include"input_src.h" int main(int argc, char **argv) { void *foo = printf; if(foo) { return 0; } return 1; } meson-0.45.1/test cases/common/4 shared/0000755000175000017500000000000013254552747021252 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/4 shared/meson.build0000644000175000017500000000011713254551630023401 0ustar jpakkanejpakkane00000000000000project('shared library test', 'c') lib = shared_library('mylib', 'libfile.c') meson-0.45.1/test cases/common/4 shared/libfile.c0000644000175000017500000000052012650745767023026 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif int DLL_PUBLIC libfunc() { return 3; } meson-0.45.1/test cases/common/168 disabler/0000755000175000017500000000000013254552747021744 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/168 disabler/meson.build0000644000175000017500000000144513254552130024074 0ustar jpakkanejpakkane00000000000000project('dolphin option', 'c') d = disabler() d2 = dependency(d) d3 = (d == d2) d4 = d + 0 d5 = d2 or true assert(d, 'Disabler did not cause this to be skipped.') assert(d2, 'Function laundered disabler did not cause this to be skipped.') assert(d3, 'Disabler comparison should yield disabler and thus this would not be called.') assert(d4, 'Disabler addition should yield disabler and thus this would not be called.') assert(d5, 'Disabler logic op should yield disabler and thus this would not be called.') number = 0 if d number = 1 else number = 2 endif assert(d == 0, 'Plain if handled incorrectly, value should be 0 but is @0@'.format(number)) if d.found() number = 1 else number = 2 endif assert(d == 1, 'If found handled incorrectly, value should be 1 but is @0@'.format(number)) meson-0.45.1/test cases/common/139 override options/0000755000175000017500000000000013254552746023447 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/139 override options/meson.build0000644000175000017500000000027313254552074025605 0ustar jpakkanejpakkane00000000000000project('option override', 'c', default_options : 'unity=on') executable('mustunity', 'one.c', 'two.c') executable('notunity', 'three.c', 'four.c', override_options : ['unity=off']) meson-0.45.1/test cases/common/139 override options/one.c0000644000175000017500000000005313070746245024365 0ustar jpakkanejpakkane00000000000000static int hidden_func() { return 0; } meson-0.45.1/test cases/common/139 override options/four.c0000644000175000017500000000020713070746245024560 0ustar jpakkanejpakkane00000000000000int func(); static int duplicate_func() { return -4; } int main(int argc, char **argv) { return duplicate_func() + func(); } meson-0.45.1/test cases/common/139 override options/two.c0000644000175000017500000000021013070746245024410 0ustar jpakkanejpakkane00000000000000/* * Requires a Unity build. Otherwise hidden_func is not specified. */ int main(int argc, char **argv) { return hidden_func(); } meson-0.45.1/test cases/common/139 override options/three.c0000644000175000017500000000013313070746245024712 0ustar jpakkanejpakkane00000000000000static int duplicate_func() { return 4; } int func() { return duplicate_func(); } meson-0.45.1/test cases/common/16 configure file/0000755000175000017500000000000013254552746022747 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/16 configure file/config.h.in0000644000175000017500000000017012650745767024776 0ustar jpakkanejpakkane00000000000000#define MESSAGE "@var@" #define OTHER "@other@" "@second@" "@empty@" #mesondefine BE_TRUE #mesondefine SHOULD_BE_UNDEF meson-0.45.1/test cases/common/16 configure file/file_contains.py0000644000175000017500000000072313116304505026121 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys import argparse def main(): parser = argparse.ArgumentParser() parser.add_argument('file', nargs=1, type=str) parser.add_argument('text', nargs=1, type=str) args = parser.parse_args() text = args.text[0] with open(args.file[0], 'r', encoding='utf-8') as f: for line in f: if line.strip() == text: return 0 return 1 if __name__ == '__main__': sys.exit(main()) meson-0.45.1/test cases/common/16 configure file/touch.py0000644000175000017500000000050613116304505024425 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys import argparse from pathlib import Path def main(): parser = argparse.ArgumentParser() parser.add_argument('files', nargs='*', type=str) args = parser.parse_args() for filepath in args.files: Path(filepath).touch() if __name__ == '__main__': sys.exit(main()) meson-0.45.1/test cases/common/16 configure file/prog2.c0000644000175000017500000000012113012152443024114 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { return ZERO_RESULT; } meson-0.45.1/test cases/common/16 configure file/prog4.c0000644000175000017500000000015713114755473024146 0ustar jpakkanejpakkane00000000000000#include #include int main(int argc, char **argv) { return RESULTA + RESULTB; } meson-0.45.1/test cases/common/16 configure file/config4a.h.in0000644000175000017500000000005013114755473025207 0ustar jpakkanejpakkane00000000000000/* Dummy file */ #define RESULTA @ZERO@ meson-0.45.1/test cases/common/16 configure file/installed_files.txt0000644000175000017500000000016513070746245026646 0ustar jpakkanejpakkane00000000000000usr/share/appdir/config2.h usr/share/appdir/config2b.h usr/share/appdireh/config2-1.h usr/share/appdirok/config2-2.h meson-0.45.1/test cases/common/16 configure file/meson.build0000644000175000017500000001107213254551651025104 0ustar jpakkanejpakkane00000000000000project('configure file test', 'c') conf = configuration_data() conf.set('var', 'mystring') conf.set('other', 'string 2') conf.set('second', ' bonus') conf.set('BE_TRUE', true) assert(conf.get('var') == 'mystring', 'Get function is not working.') assert(conf.get('var', 'default') == 'mystring', 'Get function is not working.') assert(conf.get('notthere', 'default') == 'default', 'Default value getting is not working.') cfile = configure_file(input : 'config.h.in', output : 'config.h', configuration : conf) e = executable('inctest', 'prog.c', # Note that you should NOT do this. Don't add generated headers here # This tests that we do the right thing even if people add in conf files # to their sources. cfile) test('inctest', e) # Test if we can also pass files() as input configure_file(input : files('config.h.in'), output : 'config2.h', configuration : conf) # Now generate a header file with an external script. genprog = import('python3').find_python() scriptfile = '@0@/generator.py'.format(meson.current_source_dir()) ifile = '@0@/dummy.dat'.format(meson.current_source_dir()) ofile = '@0@/config2.h'.format(meson.current_build_dir()) check_file = find_program('check_file.py') # Configure in source root with command and absolute paths configure_file(input : 'dummy.dat', output : 'config2.h', command : [genprog, scriptfile, ifile, ofile], install_dir : 'share/appdir') run_command(check_file, join_paths(meson.current_build_dir(), 'config2.h')) # Same again as before, but an input file should not be required in # this case where we use a command/script to generate the output file. genscript2b = '@0@/generator-without-input-file.py'.format(meson.current_source_dir()) ofile2b = '@0@/config2b.h'.format(meson.current_build_dir()) configure_file( output : 'config2b.h', command : [genprog, genscript2b, ofile2b], install_dir : 'share/appdir') run_command(check_file, join_paths(meson.current_build_dir(), 'config2b.h')) found_script = find_program('generator.py') # More configure_file tests in here subdir('subdir') test('inctest2', executable('prog2', 'prog2.c')) # Generate a conf file without an input file. dump = configuration_data() dump.set_quoted('SHOULD_BE_STRING', 'string', description : 'A string') dump.set_quoted('SHOULD_BE_STRING2', 'A "B" C') dump.set_quoted('SHOULD_BE_STRING3', 'A "" C') dump.set_quoted('SHOULD_BE_STRING4', 'A " C') dump.set('SHOULD_BE_RETURN', 'return') dump.set('SHOULD_BE_DEFINED', true) dump.set('SHOULD_BE_UNDEFINED', false) dump.set('SHOULD_BE_ONE', 1) dump.set('SHOULD_BE_ZERO', 0, description : 'Absolutely zero') dump.set('SHOULD_BE_QUOTED_ONE', '"1"') dump.set_quoted('INTEGER_AS_STRING', '12') if dump.get_unquoted('INTEGER_AS_STRING').to_int() == 12 dump.set('SHOULD_BE_UNQUOTED_STRING', dump.get_unquoted('SHOULD_BE_STRING')) endif configure_file(output : 'config3.h', configuration : dump) test('Configless.', executable('dumpprog', 'dumpprog.c')) # Config file generation in a loop with @BASENAME@ substitution dump = configuration_data() dump.set('ZERO', 0) config_templates = files(['config4a.h.in', 'config4b.h.in']) foreach config_template : config_templates configure_file(input : config_template, output : '@BASENAME@', configuration : dump) endforeach test('Substituted', executable('prog4', 'prog4.c')) # Test `capture` keyword basename_py = find_program('basename.py') file_contains_py = find_program('file_contains.py') test_string = 'hello world' test_input_file = join_paths(meson.current_build_dir(), test_string) run_command(find_program('touch.py'), test_input_file) configs = [ # no input configure_file(command: [ basename_py, test_string ], capture: true, output: 'capture test 1'), # with input configure_file(input: test_input_file, command: [ basename_py, '@INPUT@' ], capture: true, output: 'capture test 2'), ] foreach c : configs test('@0@'.format(c), file_contains_py, args: [ c, test_string ]) endforeach # Test variable is substituted only once conf5 = configuration_data() conf5.set('var', '@var2@') conf5.set('var2', 'error') configure_file( input : 'config5.h.in', output : '@BASENAME@', configuration : conf5 ) test('test5', executable('prog5', 'prog5.c')) # Test escaping conf6 = configuration_data() conf6.set('var1', 'foo') conf6.set('var2', 'bar') configure_file( input : 'config6.h.in', output : '@BASENAME@', configuration : conf6 ) test('test6', executable('prog6', 'prog6.c')) # test empty install dir string cfile = configure_file(input : 'config.h.in', output : 'do_not_get_installed.h', install_dir : '', configuration : conf) meson-0.45.1/test cases/common/16 configure file/subdir/0000755000175000017500000000000013254552746024237 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/16 configure file/subdir/meson.build0000644000175000017500000000157413055371477026407 0ustar jpakkanejpakkane00000000000000# Configure in subdir with absolute paths for input and relative for output configure_file(input : '../dummy.dat', output : 'config2-1.h', command : [genprog, scriptfile, ifile, 'config2-1.h'], install_dir : 'share/appdireh') run_command(check_file, join_paths(meson.current_build_dir(), 'config2-1.h')) # Configure in subdir with files() for input and relative for output configure_file(input : '../dummy.dat', output : 'config2-2.h', command : [genprog, scriptfile, files('../dummy.dat'), 'config2-2.h'], install_dir : 'share/appdirok') run_command(check_file, join_paths(meson.current_build_dir(), 'config2-2.h')) # Configure in subdir with string templates for input and output configure_file(input : '../dummy.dat', output : 'config2-3.h', command : [found_script, '@INPUT@', '@OUTPUT@']) run_command(check_file, join_paths(meson.current_build_dir(), 'config2-3.h')) meson-0.45.1/test cases/common/16 configure file/dummy.dat0000644000175000017500000000000012650745767024570 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/16 configure file/generator-without-input-file.py0000755000175000017500000000050613070746245031061 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys, os from pathlib import Path if len(sys.argv) != 2: print("Wrong amount of parameters.") build_dir = Path(os.environ['MESON_BUILD_ROOT']) subdir = Path(os.environ['MESON_SUBDIR']) outputf = Path(sys.argv[1]) with outputf.open('w') as ofile: ofile.write("#define ZERO_RESULT 0\n") meson-0.45.1/test cases/common/16 configure file/dumpprog.c0000644000175000017500000000242113203131036024722 0ustar jpakkanejpakkane00000000000000#define SHOULD_BE_UNDEFINED 1 #include"config3.h" #include #include #ifdef SHOULD_BE_UNDEFINED #error Token did not get undefined. #endif #ifndef SHOULD_BE_DEFINED #error Token did not get defined #endif #define stringify(s) str(s) #define str(s) #s int main(int argc, char **argv) { #if !(SHOULD_BE_UNQUOTED_STRING == string) printf("String token (unquoted) defined wrong.\n"); return 1; #endif if(strcmp(SHOULD_BE_STRING, "string") != 0) { printf("String token defined wrong.\n"); return 1; } if(strcmp(SHOULD_BE_STRING2, "A \"B\" C") != 0) { printf("String token 2 defined wrong.\n"); return 1; } if(strcmp(SHOULD_BE_STRING3, "A \"\" C") != 0) { printf("String token 3 defined wrong.\n"); return 1; } if(strcmp(SHOULD_BE_STRING4, "A \" C") != 0) { printf("String token 4 defined wrong.\n"); return 1; } if(SHOULD_BE_ONE != 1) { printf("One defined incorrectly.\n"); return 1; } if(SHOULD_BE_ZERO != 0) { printf("Zero defined incorrectly.\n"); return 1; } if(strcmp(SHOULD_BE_QUOTED_ONE, "1") != 0) { printf("Quoted number defined incorrectly.\n"); return 1; } SHOULD_BE_RETURN 0; } meson-0.45.1/test cases/common/16 configure file/prog.c0000644000175000017500000000045413012152443024043 0ustar jpakkanejpakkane00000000000000#include /* config.h must not be in quotes: * https://gcc.gnu.org/onlinedocs/cpp/Search-Path.html */ #include #ifdef SHOULD_BE_UNDEF #error "FAIL!" #endif int main(int argc, char **argv) { #ifndef BE_TRUE return 1; #else return strcmp(MESSAGE, "mystring"); #endif } meson-0.45.1/test cases/common/16 configure file/check_file.py0000644000175000017500000000012213055371477025367 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import os import sys assert(os.path.exists(sys.argv[1])) meson-0.45.1/test cases/common/16 configure file/prog6.c0000644000175000017500000000047313206650111024132 0ustar jpakkanejpakkane00000000000000#include #include int main(int argc, char **argv) { return strcmp(MESSAGE1, "foo") || strcmp(MESSAGE2, "@var1@") || strcmp(MESSAGE3, "\\foo") || strcmp(MESSAGE4, "\\@var1@") || strcmp(MESSAGE5, "@var1bar") || strcmp(MESSAGE6, "\\ @ @ \\@ \\@"); } meson-0.45.1/test cases/common/16 configure file/config6.h.in0000644000175000017500000000106213206650111025035 0ustar jpakkanejpakkane00000000000000/* No escape */ #define MESSAGE1 "@var1@" /* Single escape means no replace */ #define MESSAGE2 "\@var1@" /* Replace pairs of escapes before '@' or '\@' with escape characters * (note we have to double number of pairs due to C string escaping) */ #define MESSAGE3 "\\\\@var1@" /* Pairs of escapes and then single escape to avoid replace */ #define MESSAGE4 "\\\\\@var1@" /* Check escaped variable does not overlap following variable */ #define MESSAGE5 "\@var1@var2@" /* Check escape character outside variables */ #define MESSAGE6 "\\ @ \@ \\\\@ \\\\\@" meson-0.45.1/test cases/common/16 configure file/config.h0000644000175000017500000000014313012152443024341 0ustar jpakkanejpakkane00000000000000#error "This file should not be included. Build dir must become before source dir in search order" meson-0.45.1/test cases/common/16 configure file/prog5.c0000644000175000017500000000016413206650111024126 0ustar jpakkanejpakkane00000000000000#include #include int main(int argc, char **argv) { return strcmp(MESSAGE, "@var2@"); } meson-0.45.1/test cases/common/16 configure file/config4b.h.in0000644000175000017500000000005013114755473025210 0ustar jpakkanejpakkane00000000000000/* Dummy file */ #define RESULTB @ZERO@ meson-0.45.1/test cases/common/16 configure file/config5.h.in0000644000175000017500000000003013206650111025026 0ustar jpakkanejpakkane00000000000000#define MESSAGE "@var@" meson-0.45.1/test cases/common/16 configure file/basename.py0000644000175000017500000000101613116304505025053 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys import argparse import os def main(): parser = argparse.ArgumentParser() parser.add_argument('text', nargs='*', type=str) args = parser.parse_args() text = args.text if isinstance(args.text, list) else [args.text] output = '' for t in text: t = os.path.basename(t) if not output: output += t else: output += ' ' + t output += '\n' sys.stdout.write(output) if __name__ == '__main__': sys.exit(main()) meson-0.45.1/test cases/common/16 configure file/generator.py0000755000175000017500000000057213055371477025315 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys, os from pathlib import Path if len(sys.argv) != 3: print("Wrong amount of parameters.") build_dir = Path(os.environ['MESON_BUILD_ROOT']) subdir = Path(os.environ['MESON_SUBDIR']) inputf = Path(sys.argv[1]) outputf = Path(sys.argv[2]) assert(inputf.exists()) with outputf.open('w') as ofile: ofile.write("#define ZERO_RESULT 0\n") meson-0.45.1/test cases/common/40 logic ops/0000755000175000017500000000000013254552747021743 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/40 logic ops/meson.build0000644000175000017500000000207413254551702024076 0ustar jpakkanejpakkane00000000000000project('logicopts', 'c') t = true f = false if (true) message('Ok.') else error('Not ok.') endif if (false) error('Not ok.') else message('Ok.') endif if (f) error('Not ok.') else message('Ok.') endif if (t) message('Ok.') else error('Not ok.') endif if true and t message('Ok.') else error('Not ok.') endif if t and false error('Not ok.') else message('Ok.') endif if f and t error('Not ok.') else message('Ok.') endif if f or false error('Not ok.') else message('Ok.') endif if true or f message('Ok.') else error('Not ok.') endif if t or true message('Ok.') else error('Not ok.') endif if not true error('Negation failed.') else message('Ok.') endif if not f message('Ok.') else error('Negation failed.') endif if f or f or f or f or f or f or f or f or t message('Ok.') else error('Chain of ors failed.') endif if t and t and t and t and t and t and t and t and f error('Chain of ands failed.') else message('Ok.') endif if t and t or t message('Ok.') else error('Combination of and-or failed.') endif meson-0.45.1/test cases/common/33 try compile/0000755000175000017500000000000013254552747022315 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/33 try compile/invalid.c0000644000175000017500000000010613001212425024054 0ustar jpakkanejpakkane00000000000000#include void func() { printf("This won't work.\n"); } meson-0.45.1/test cases/common/33 try compile/meson.build0000644000175000017500000000151613254551672024456 0ustar jpakkanejpakkane00000000000000project('try compile', 'c', 'cpp') code = '''#include void func() { printf("Something.\n"); } ''' breakcode = '''#include void func() { printf("This won't work.\n"); } ''' foreach compiler : [meson.get_compiler('c'), meson.get_compiler('cpp')] if compiler.compiles(code, name : 'should succeed') == false error('Compiler ' + compiler.get_id() + ' is fail.') endif if compiler.compiles(files('valid.c'), name : 'should succeed') == false error('Compiler ' + compiler.get_id() + ' is fail.') endif if compiler.compiles(breakcode, name : 'should fail') error('Compiler ' + compiler.get_id() + ' returned true on broken code.') endif if compiler.compiles(files('invalid.c'), name : 'should fail') error('Compiler ' + compiler.get_id() + ' returned true on broken code.') endif endforeach meson-0.45.1/test cases/common/33 try compile/valid.c0000644000175000017500000000007213001212425023527 0ustar jpakkanejpakkane00000000000000#include void func() { printf("Something.\n"); } meson-0.45.1/test cases/common/54 same file name/0000755000175000017500000000000013254552747022617 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/54 same file name/meson.build0000644000175000017500000000014013254551742024746 0ustar jpakkanejpakkane00000000000000project('samefile', 'c') test('basic', executable('prog', 'prog.c', 'd1/file.c', 'd2/file.c')) meson-0.45.1/test cases/common/54 same file name/prog.c0000644000175000017500000000013512650745767023736 0ustar jpakkanejpakkane00000000000000int func1(); int func2(); int main(int argc, char **argv) { return func1() - func2(); } meson-0.45.1/test cases/common/54 same file name/d1/0000755000175000017500000000000013254552747023123 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/54 same file name/d1/file.c0000644000175000017500000000003312650745767024207 0ustar jpakkanejpakkane00000000000000int func1() { return 42; } meson-0.45.1/test cases/common/54 same file name/d2/0000755000175000017500000000000013254552747023124 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/54 same file name/d2/file.c0000644000175000017500000000003312650745767024210 0ustar jpakkanejpakkane00000000000000int func2() { return 42; } meson-0.45.1/test cases/common/50 subproject options/0000755000175000017500000000000013254552747023721 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/50 subproject options/subprojects/0000755000175000017500000000000013254552745026262 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/50 subproject options/subprojects/subproject/0000755000175000017500000000000013254552747030444 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/50 subproject options/subprojects/subproject/meson.build0000644000175000017500000000014612666130376032603 0ustar jpakkanejpakkane00000000000000project('subproject', 'c') if get_option('opt') error('option set when it should be unset.') endif meson-0.45.1/test cases/common/50 subproject options/subprojects/subproject/meson_options.txt0000644000175000017500000000012212650745767034101 0ustar jpakkanejpakkane00000000000000option('opt', type : 'boolean', value : false, description : 'subproject option') meson-0.45.1/test cases/common/50 subproject options/meson.build0000644000175000017500000000020313254551730026045 0ustar jpakkanejpakkane00000000000000project('suboptions', 'c') subproject('subproject') if not get_option('opt') error('option unset when it should be set') endif meson-0.45.1/test cases/common/50 subproject options/meson_options.txt0000644000175000017500000000012312650745767027357 0ustar jpakkanejpakkane00000000000000option('opt', type : 'boolean', value : true, description : 'main project option') meson-0.45.1/test cases/common/32 multiline string/0000755000175000017500000000000013254552747023356 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/32 multiline string/meson.build0000644000175000017500000000057013254551671025515 0ustar jpakkanejpakkane00000000000000project('multiline string', 'c') x = '''hello again''' y = '''hello again''' if x == y error('Things are wrong.') endif multieol = ''' ''' singleeol = '\n' if multieol != singleeol error('Newline quoting is broken.') endif # And one more for good measure. quote1 = ''' ' '''.strip() quote2 = '\'' if quote1 != quote2 error('Single quote quoting is broken.') endif meson-0.45.1/test cases/common/169 array option/0000755000175000017500000000000013254552747022567 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/169 array option/meson.build0000644000175000017500000000131413254552131024713 0ustar jpakkanejpakkane00000000000000# Copyright Ā© 2017 Intel Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. project('array default options') assert(get_option('array') == ['foo', 'bar'], 'Default value for array is not equal to choices') meson-0.45.1/test cases/common/169 array option/meson_options.txt0000644000175000017500000000121413211772701026205 0ustar jpakkanejpakkane00000000000000# Copyright Ā© 2017 Intel Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. option( 'array', type : 'array', choices : ['foo', 'bar'], ) meson-0.45.1/test cases/common/80 shared subproject 2/0000755000175000017500000000000013254552747023621 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/80 shared subproject 2/subprojects/0000755000175000017500000000000013254552745026162 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/80 shared subproject 2/subprojects/B/0000755000175000017500000000000013254552747026345 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/80 shared subproject 2/subprojects/B/meson.build0000644000175000017500000000015412650745767030514 0ustar jpakkanejpakkane00000000000000project('B', 'c') C = subproject('C') c = C.get_variable('c') b = shared_library('b', 'b.c', link_with : c) meson-0.45.1/test cases/common/80 shared subproject 2/subprojects/B/b.c0000644000175000017500000000064412650745767026743 0ustar jpakkanejpakkane00000000000000#include char func_c(); #if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif char DLL_PUBLIC func_b() { if(func_c() != 'c') { exit(3); } return 'b'; } meson-0.45.1/test cases/common/80 shared subproject 2/subprojects/C/0000755000175000017500000000000013254552747026346 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/80 shared subproject 2/subprojects/C/c.c0000644000175000017500000000052012650745767026736 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif char DLL_PUBLIC func_c() { return 'c'; } meson-0.45.1/test cases/common/80 shared subproject 2/subprojects/C/meson.build0000644000175000017500000000006112650745767030512 0ustar jpakkanejpakkane00000000000000project('C', 'c') c = shared_library('c', 'c.c') meson-0.45.1/test cases/common/80 shared subproject 2/meson.build0000644000175000017500000000036413254551776025767 0ustar jpakkanejpakkane00000000000000project('A', 'c') # Same as the previous test but use C and B in # the opposite order. C = subproject('C') c = C.get_variable('c') B = subproject('B') b = B.get_variable('b') a = executable('a', 'a.c', link_with : [b, c]) test('a test', a) meson-0.45.1/test cases/common/80 shared subproject 2/a.c0000644000175000017500000000031012650745767024204 0ustar jpakkanejpakkane00000000000000#include char func_b(); char func_c(); int main(int argc, char **argv) { if(func_b() != 'b') { return 1; } if(func_c() != 'c') { return 2; } return 0; } meson-0.45.1/test cases/common/123 subproject project arguments/0000755000175000017500000000000013254552746025742 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/123 subproject project arguments/subprojects/0000755000175000017500000000000013254552745030304 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/123 subproject project arguments/subprojects/subexe/0000755000175000017500000000000013254552746031600 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/123 subproject project arguments/subprojects/subexe/subexe.c0000644000175000017500000000043213074426732033231 0ustar jpakkanejpakkane00000000000000#ifdef PROJECT_OPTION #error #endif #ifdef PROJECT_OPTION_1 #error #endif #ifdef PROJECT_OPTION_C_CPP #error #endif #ifndef GLOBAL_ARGUMENT #error #endif #ifndef SUBPROJECT_OPTION #error #endif #ifdef OPTION_CPP #error #endif int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/123 subproject project arguments/subprojects/subexe/meson.build0000644000175000017500000000061413016624375033735 0ustar jpakkanejpakkane00000000000000project('subproject', 'c', version : '1.0.0', license : ['sublicense1', 'sublicense2']) if not meson.is_subproject() error('Claimed to be master project even though we are a subproject.') endif assert(meson.project_name() == 'subproject', 'Incorrect subproject name') add_project_arguments('-DSUBPROJECT_OPTION', language: 'c') e = executable('subexe', 'subexe.c') test('subexetest', e) meson-0.45.1/test cases/common/123 subproject project arguments/meson.build0000644000175000017500000000105613254552054030076 0ustar jpakkanejpakkane00000000000000project('project options tester', 'c', 'cpp', version : '2.3.4', license : 'mylicense') add_global_arguments('-DGLOBAL_ARGUMENT', language: 'c') add_project_arguments('-DPROJECT_OPTION', language: 'c') add_project_arguments('-DPROJECT_OPTION_CPP', language: 'cpp') add_project_arguments('-DPROJECT_OPTION_C_CPP', language: ['c', 'cpp']) sub = subproject('subexe', version : '1.0.0') add_project_arguments('-DPROJECT_OPTION_1', language: 'c') e = executable('exe', 'exe.c') e = executable('execpp', 'exe.cpp') test('exetest', e) test('execpptest', e) meson-0.45.1/test cases/common/123 subproject project arguments/exe.cpp0000644000175000017500000000044313074426732027223 0ustar jpakkanejpakkane00000000000000#ifdef PROJECT_OPTION #error #endif #ifdef PROJECT_OPTION_1 #error #endif #ifdef GLOBAL_ARGUMENT #error #endif #ifdef SUBPROJECT_OPTION #error #endif #ifndef PROJECT_OPTION_CPP #error #endif #ifndef PROJECT_OPTION_C_CPP #error #endif int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/123 subproject project arguments/exe.c0000644000175000017500000000043413074426732026663 0ustar jpakkanejpakkane00000000000000#ifndef PROJECT_OPTION #error #endif #ifndef PROJECT_OPTION_1 #error #endif #ifndef GLOBAL_ARGUMENT #error #endif #ifdef SUBPROJECT_OPTION #error #endif #ifdef OPTION_CPP #error #endif #ifndef PROJECT_OPTION_C_CPP #error #endif int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/72 build always/0000755000175000017500000000000013254552747022451 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/72 build always/main.c0000644000175000017500000000021112650745767023540 0ustar jpakkanejpakkane00000000000000#include #include"version.h" int main(int argc, char **argv) { printf("Version is %s.\n", version_string); return 0; } meson-0.45.1/test cases/common/72 build always/version.c.in0000644000175000017500000000007712650745767024720 0ustar jpakkanejpakkane00000000000000#include"version.h" const char *version_string = "@VERSION@"; meson-0.45.1/test cases/common/72 build always/meson.build0000644000175000017500000000046013254551765024612 0ustar jpakkanejpakkane00000000000000project('run always', 'c') version = '1.0.0' vgen = find_program('version_gen.py') version_src = custom_target('Version string', input : 'version.c.in', output : 'version.c', command : [vgen, '@INPUT@', '@OUTPUT@', version], build_always : true, ) executable('versionprinter', 'main.c', version_src) meson-0.45.1/test cases/common/72 build always/version.h0000644000175000017500000000005212650745767024311 0ustar jpakkanejpakkane00000000000000#pragma once const char *version_string; meson-0.45.1/test cases/common/72 build always/version_gen.py0000755000175000017500000000157413254550710025337 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys, os, subprocess def generate(infile, outfile, fallback): workdir = os.path.split(infile)[0] if workdir == '': workdir = '.' version = fallback try: p = subprocess.Popen(['git', 'describe'], cwd=workdir, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdo, _) = p.communicate() if p.returncode == 0: version = stdo.decode().strip() except: pass with open(infile) as f: newdata = f.read().replace('@VERSION@', version) try: with open(outfile) as f: olddata = f.read() if olddata == newdata: return except: pass with open(outfile, 'w') as f: f.write(newdata) if __name__ == '__main__': infile = sys.argv[1] outfile = sys.argv[2] fallback = sys.argv[3] generate(infile, outfile, fallback) meson-0.45.1/test cases/common/131 custom target directory install/0000755000175000017500000000000013254552746026341 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/131 custom target directory install/installed_files.txt0000644000175000017500000000016213025554726032236 0ustar jpakkanejpakkane00000000000000usr/share/doc/testpkgname/html/a.html usr/share/doc/testpkgname/html/b.html usr/share/doc/testpkgname/html/c.html meson-0.45.1/test cases/common/131 custom target directory install/meson.build0000644000175000017500000000036413254552064030477 0ustar jpakkanejpakkane00000000000000project('custom-target-dir-install', 'c') docgen = find_program('docgen.py') custom_target('docgen', output : 'html', command : [docgen, '@OUTPUT@'], install : true, install_dir : join_paths(get_option('datadir'), 'doc/testpkgname')) meson-0.45.1/test cases/common/131 custom target directory install/docgen.py0000644000175000017500000000027713057037314030146 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import os import sys out = sys.argv[1] os.mkdir(out) for name in ('a', 'b', 'c'): with open(os.path.join(out, name + '.html'), 'w') as f: f.write(name) meson-0.45.1/test cases/common/79 shared subproject/0000755000175000017500000000000013254552747023507 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/79 shared subproject/subprojects/0000755000175000017500000000000013254552745026050 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/79 shared subproject/subprojects/B/0000755000175000017500000000000013254552747026233 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/79 shared subproject/subprojects/B/meson.build0000644000175000017500000000015412650745767030402 0ustar jpakkanejpakkane00000000000000project('B', 'c') C = subproject('C') c = C.get_variable('c') b = shared_library('b', 'b.c', link_with : c) meson-0.45.1/test cases/common/79 shared subproject/subprojects/B/b.c0000644000175000017500000000064512650745767026632 0ustar jpakkanejpakkane00000000000000#include #if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif char func_c(); char DLL_PUBLIC func_b() { if(func_c() != 'c') { exit(3); } return 'b'; } meson-0.45.1/test cases/common/79 shared subproject/subprojects/C/0000755000175000017500000000000013254552747026234 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/79 shared subproject/subprojects/C/c.c0000644000175000017500000000052012650745767026624 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif char DLL_PUBLIC func_c() { return 'c'; } meson-0.45.1/test cases/common/79 shared subproject/subprojects/C/meson.build0000644000175000017500000000006112650745767030400 0ustar jpakkanejpakkane00000000000000project('C', 'c') c = shared_library('c', 'c.c') meson-0.45.1/test cases/common/79 shared subproject/meson.build0000644000175000017500000000025613254551776025655 0ustar jpakkanejpakkane00000000000000project('A', 'c') B = subproject('B') b = B.get_variable('b') C = subproject('C') c = C.get_variable('c') a = executable('a', 'a.c', link_with : [b, c]) test('a test', a) meson-0.45.1/test cases/common/79 shared subproject/a.c0000644000175000017500000000031012650745767024072 0ustar jpakkanejpakkane00000000000000#include char func_b(); char func_c(); int main(int argc, char **argv) { if(func_b() != 'b') { return 1; } if(func_c() != 'c') { return 2; } return 0; } meson-0.45.1/test cases/common/130 no buildincdir/0000755000175000017500000000000013254552746023030 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/130 no buildincdir/meson.build0000644000175000017500000000054213254552064025164 0ustar jpakkanejpakkane00000000000000project('nobuilddir', 'c', default_options : 'werror=true') cc = meson.get_compiler('c') incwarg = '-Wmissing-include-dirs' if cc.has_argument(incwarg) executable('prog', 'prog.c', c_args : incwarg, include_directories : include_directories('include')) else error('MESON_SKIP_TEST compiler does not support bad inc dir argument.') endif meson-0.45.1/test cases/common/130 no buildincdir/include/0000755000175000017500000000000013254552746024453 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/130 no buildincdir/include/header.h0000644000175000017500000000003413024065327026036 0ustar jpakkanejpakkane00000000000000#pragma once int foobar(); meson-0.45.1/test cases/common/130 no buildincdir/prog.c0000644000175000017500000000010613024065327024125 0ustar jpakkanejpakkane00000000000000#include"header.h" int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/121 interpreter copy mutable var on assignment/0000755000175000017500000000000013254552746030352 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/121 interpreter copy mutable var on assignment/meson.build0000644000175000017500000000105213254552051032477 0ustar jpakkanejpakkane00000000000000project('foo', 'c') a = configuration_data() a.set('HELLO', 1) b = a assert(a.has('HELLO'), 'Original config data should be set on a') assert(b.has('HELLO'), 'Original config data should be set on copy') configure_file(output : 'b.h', configuration : b) # This should still work, as we didn't use the original above but a copy! a.set('WORLD', 1) assert(a.has('WORLD'), 'New config data should have been set') assert(not b.has('WORLD'), 'New config data set should not affect var copied earlier') configure_file(output : 'a.h', configuration : a) meson-0.45.1/test cases/common/82 custom subproject dir/0000755000175000017500000000000013254552747024304 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/82 custom subproject dir/meson.build0000644000175000017500000000032613254552001026426 0ustar jpakkanejpakkane00000000000000project('A', 'c', subproject_dir:'custom_subproject_dir') B = subproject('B') b = B.get_variable('b') C = subproject('C') c = C.get_variable('c') a = executable('a', 'a.c', link_with : [b, c]) test('a test', a) meson-0.45.1/test cases/common/82 custom subproject dir/a.c0000644000175000017500000000031012650745767024667 0ustar jpakkanejpakkane00000000000000#include char func_b(); char func_c(); int main(int argc, char **argv) { if(func_b() != 'b') { return 1; } if(func_c() != 'c') { return 2; } return 0; } meson-0.45.1/test cases/common/82 custom subproject dir/custom_subproject_dir/0000755000175000017500000000000013254552745030712 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/82 custom subproject dir/custom_subproject_dir/B/0000755000175000017500000000000013254552747031075 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/82 custom subproject dir/custom_subproject_dir/B/meson.build0000644000175000017500000000015412650745767033244 0ustar jpakkanejpakkane00000000000000project('B', 'c') C = subproject('C') c = C.get_variable('c') b = shared_library('b', 'b.c', link_with : c) meson-0.45.1/test cases/common/82 custom subproject dir/custom_subproject_dir/B/b.c0000644000175000017500000000064412650745767031473 0ustar jpakkanejpakkane00000000000000#include char func_c(); #if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif char DLL_PUBLIC func_b() { if(func_c() != 'c') { exit(3); } return 'b'; } meson-0.45.1/test cases/common/82 custom subproject dir/custom_subproject_dir/C/0000755000175000017500000000000013254552747031076 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/82 custom subproject dir/custom_subproject_dir/C/c.c0000644000175000017500000000052012650745767031466 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif char DLL_PUBLIC func_c() { return 'c'; } meson-0.45.1/test cases/common/82 custom subproject dir/custom_subproject_dir/C/meson.build0000644000175000017500000000006112650745767033242 0ustar jpakkanejpakkane00000000000000project('C', 'c') c = shared_library('c', 'c.c') meson-0.45.1/test cases/common/51 pkgconfig-gen/0000755000175000017500000000000013254552747022604 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/51 pkgconfig-gen/installed_files.txt0000644000175000017500000000011513001212425026453 0ustar jpakkanejpakkane00000000000000usr/include/simple.h usr/lib/pkgconfig/simple.pc usr/lib/pkgconfig/libfoo.pc meson-0.45.1/test cases/common/51 pkgconfig-gen/simple.c0000644000175000017500000000007512650745767024250 0ustar jpakkanejpakkane00000000000000#include"simple.h" int simple_function() { return 42; } meson-0.45.1/test cases/common/51 pkgconfig-gen/meson.build0000644000175000017500000000241113254551735024740 0ustar jpakkanejpakkane00000000000000project('pkgconfig-gen', 'c') # First check we have pkg-config >= 0.29 pkgconfig = find_program('pkg-config', required: false) if not pkgconfig.found() error('MESON_SKIP_TEST: pkg-config not found') endif v = run_command(pkgconfig, '--version').stdout().strip() if v.version_compare('<0.29') error('MESON_SKIP_TEST: pkg-config version \'' + v + '\' too old') endif pkgg = import('pkgconfig') lib = shared_library('simple', 'simple.c') libver = '1.0' h = install_headers('simple.h') pkgg.generate( libraries : [lib, '-lz'], subdirs : '.', version : libver, name : 'libsimple', filebase : 'simple', description : 'A simple demo library.', requires : 'glib-2.0', # Not really, but only here to test that this works. requires_private : ['gio-2.0', 'gobject-2.0'], libraries_private : [lib, '-lz'], ) test('pkgconfig-validation', pkgconfig, args: ['--validate', 'simple'], env: [ 'PKG_CONFIG_PATH=' + meson.current_build_dir() + '/meson-private' ]) # Test that name_prefix='' and name='libfoo' results in '-lfoo' lib2 = shared_library('libfoo', 'simple.c', name_prefix : '', version : libver) pkgg.generate( libraries : lib2, name : 'libfoo', version : libver, description : 'A foo library.', variables : ['foo=bar', 'datadir=${prefix}/data'] ) meson-0.45.1/test cases/common/51 pkgconfig-gen/dependencies/0000755000175000017500000000000013254552747025232 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/51 pkgconfig-gen/dependencies/meson.build0000644000175000017500000000332113254550710027357 0ustar jpakkanejpakkane00000000000000project('pkgconfig-gen-dependencies', 'c') pkgg = import('pkgconfig') # libmain internally use libinternal and expose libexpose in its API exposed_lib = shared_library('libexposed', 'exposed.c') internal_lib = shared_library('libinternal', 'internal.c') main_lib = static_library('libmain', link_with : [exposed_lib, internal_lib]) pkgg.generate(libraries : exposed_lib, version : '1.0', name : 'libexposed', description : 'An exposed library in dependency test.' ) # Declare a few different Dependency objects pc_dep = dependency('libfoo') notfound_dep = dependency('notfound', required : false) threads_dep = dependency('threads') custom_dep = declare_dependency(link_args : ['-lcustom'], compile_args : ['-DCUSTOM']) custom2_dep = declare_dependency(link_args : ['-lcustom2'], compile_args : ['-DCUSTOM2']) # Generate a PC file: # - Having libmain in libraries should pull implicitely libexposed and libinternal in Libs.private # - Having libexposed in libraries should remove it from Libs.private # - We generated a pc file for libexposed so it should be in Requires instead of Libs # - Having threads_dep in libraries should add '-pthread' in both Libs and Cflags # - Having custom_dep in libraries and libraries_private should only add it in Libs # - Having custom2_dep in libraries_private should not add its Cflags # - Having pc_dep in libraries_private should add it in Requires.private # - notfound_dep is not required so it shouldn't appear in the pc file. pkgg.generate(libraries : [main_lib, exposed_lib, threads_dep , custom_dep], libraries_private : [custom_dep, custom2_dep, pc_dep, notfound_dep], version : '1.0', name : 'dependency-test', filebase : 'dependency-test', description : 'A dependency test.' ) meson-0.45.1/test cases/common/51 pkgconfig-gen/dependencies/exposed.c0000644000175000017500000000005213243342167027031 0ustar jpakkanejpakkane00000000000000int exposed_function() { return 42; } meson-0.45.1/test cases/common/51 pkgconfig-gen/dependencies/internal.c0000644000175000017500000000005313243342167027177 0ustar jpakkanejpakkane00000000000000int internal_function() { return 42; } meson-0.45.1/test cases/common/51 pkgconfig-gen/simple.h0000644000175000017500000000010412650745767024246 0ustar jpakkanejpakkane00000000000000#ifndef SIMPLE_H_ #define SIMPLE_H_ int simple_function(); #endif meson-0.45.1/test cases/common/57 custom target chain/0000755000175000017500000000000013254552747023720 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/57 custom target chain/installed_files.txt0000644000175000017500000000005212763077471027617 0ustar jpakkanejpakkane00000000000000usr/subdir/data2.dat usr/subdir/data3.dat meson-0.45.1/test cases/common/57 custom target chain/meson.build0000644000175000017500000000156313254551743026062 0ustar jpakkanejpakkane00000000000000project('custom target', 'c') python = find_program('python3', required : false) if not python.found() python = find_program('python') endif # files() is the correct way to do this, but some people # do this so test that it works. comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py') comp2 = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler2.py') infile = files('data_source.txt')[0] mytarget = custom_target('bindat', output : 'data.dat', command : [python, comp, infile, '@OUTPUT@'], ) mytarget2 = custom_target('bindat2', output : 'data2.dat', command : [python, comp2, mytarget, '@OUTPUT@'], install : true, install_dir : 'subdir' ) mytarget3 = custom_target('bindat3', output : 'data3.dat', input : [mytarget], command : [python, comp2, '@INPUT@', '@OUTPUT@'], install : true, install_dir : 'subdir' ) subdir('usetarget') meson-0.45.1/test cases/common/57 custom target chain/usetarget/0000755000175000017500000000000013254552747025723 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/57 custom target chain/usetarget/myexe.c0000644000175000017500000000014212665637120027205 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("I am myexe.\n"); return 0; } meson-0.45.1/test cases/common/57 custom target chain/usetarget/meson.build0000644000175000017500000000026612665637120030063 0ustar jpakkanejpakkane00000000000000e = executable('myexe', 'myexe.c') subexe = find_program('subcomp.py') custom_target('use_exe', input : e, output : 'subout.res', command : [subexe, '@INPUT@', '@OUTPUT@'], ) meson-0.45.1/test cases/common/57 custom target chain/usetarget/subcomp.py0000755000175000017500000000023413043224360027726 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python import sys with open(sys.argv[1], 'rb') as ifile: with open(sys.argv[2], 'w') as ofile: ofile.write('Everything ok.\n') meson-0.45.1/test cases/common/57 custom target chain/my_compiler2.py0000755000175000017500000000065713043224360026665 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python import sys if __name__ == '__main__': if len(sys.argv) != 3: print(sys.argv[0], 'input_file output_file') sys.exit(1) with open(sys.argv[1]) as f: ifile = f.read() if ifile != 'This is a binary output file.\n': print('Malformed input') sys.exit(1) with open(sys.argv[2], 'w') as ofile: ofile.write('This is a different binary output file.\n') meson-0.45.1/test cases/common/57 custom target chain/data_source.txt0000644000175000017500000000004012650745767026751 0ustar jpakkanejpakkane00000000000000This is a text only input file. meson-0.45.1/test cases/common/57 custom target chain/my_compiler.py0000755000175000017500000000064713043224360026602 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python import sys if __name__ == '__main__': if len(sys.argv) != 3: print(sys.argv[0], 'input_file output_file') sys.exit(1) with open(sys.argv[1]) as f: ifile = f.read() if ifile != 'This is a text only input file.\n': print('Malformed input') sys.exit(1) with open(sys.argv[2], 'w') as ofile: ofile.write('This is a binary output file.\n') meson-0.45.1/test cases/common/27 library versions/0000755000175000017500000000000013254552747023366 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/27 library versions/installed_files.txt0000644000175000017500000000003512742140120027241 0ustar jpakkanejpakkane00000000000000usr/lib/prefixsomelib.suffix meson-0.45.1/test cases/common/27 library versions/lib.c0000644000175000017500000000004012650745767024277 0ustar jpakkanejpakkane00000000000000int myFunc() { return 55; } meson-0.45.1/test cases/common/27 library versions/meson.build0000644000175000017500000000026413254551665025530 0ustar jpakkanejpakkane00000000000000project('library versions', 'c') shared_library('somelib', 'lib.c', name_prefix : 'prefix', name_suffix : 'suffix', install_dir : 'lib', install : true) subdir('subdir') meson-0.45.1/test cases/common/27 library versions/subdir/0000755000175000017500000000000013254552747024656 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/27 library versions/subdir/meson.build0000644000175000017500000000054212742140120026774 0ustar jpakkanejpakkane00000000000000# Test that using files generated with configure_file as sources works. # We do this inside a subdir so that the path isn't accidentally correct # because there is no structure in the build dir. genlib = configure_file(input : '../lib.c', output : 'genlib.c', configuration : configuration_data()) shared_library('genlib', genlib, install : false) meson-0.45.1/test cases/common/98 gen extra/0000755000175000017500000000000013254552750021750 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/98 gen extra/srcgen.py0000755000175000017500000000124213057037314023600 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys import argparse parser = argparse.ArgumentParser() parser.add_argument('--input', dest='input', help='the input file') parser.add_argument('--output', dest='output', help='the output file') parser.add_argument('--upper', dest='upper', action='store_true', default=False, help='Convert to upper case.') c_templ = '''int %s() { return 0; } ''' options = parser.parse_args(sys.argv[1:]) with open(options.input) as f: funcname = f.readline().strip() if options.upper: funcname = funcname.upper() with open(options.output, 'w') as f: f.write(c_templ % funcname) meson-0.45.1/test cases/common/98 gen extra/srcgen2.py0000644000175000017500000000130313174155420023654 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import os import sys import argparse parser = argparse.ArgumentParser() parser.add_argument('target_dir', help='the target dir') parser.add_argument('stem', help='the stem') parser.add_argument('input', help='the input file') options = parser.parse_args(sys.argv[1:]) with open(options.input) as f: content = f.read() output_c = os.path.join(options.target_dir, options.stem + ".tab.c") with open(output_c, 'w') as f: f.write(content) output_h = os.path.join(options.target_dir, options.stem + ".tab.h") h_content = '''#pragma once int myfun(void); ''' with open(output_h, 'w') as f: f.write(h_content) meson-0.45.1/test cases/common/98 gen extra/upper.c0000644000175000017500000000011612650745767023260 0ustar jpakkanejpakkane00000000000000int BOB_MCBOB(); int main(int argc, char **argv) { return BOB_MCBOB(); } meson-0.45.1/test cases/common/98 gen extra/meson.build0000644000175000017500000000217513254552017024113 0ustar jpakkanejpakkane00000000000000project('extra args in gen', 'c') prog = find_program('srcgen.py') gen = generator(prog, output : '@BASENAME@.c', arguments : ['--input=@INPUT@', '--output=@OUTPUT@', '@EXTRA_ARGS@']) g1 = gen.process('name.dat') g2 = gen.process('name.dat', extra_args: '--upper') test('basic', executable('basic', 'plain.c', g1)) test('upper', executable('upper', 'upper.c', g2)) prog2 = find_program('srcgen2.py') basename_gen = generator(prog2, output : ['@BASENAME@.tab.c', '@BASENAME@.tab.h'], arguments : ['@BUILD_DIR@', '@BASENAME@', '@INPUT@']) basename_src = basename_gen.process('name.l') test('basename', executable('basename', basename_src)) plainname_gen = generator(prog2, output : ['@PLAINNAME@.tab.c', '@PLAINNAME@.tab.h'], arguments : ['@BUILD_DIR@', '@PLAINNAME@', '@INPUT@']) plainname_src = plainname_gen.process('name.l') test('plainname', executable('plainname', plainname_src)) prog3 = find_program('srcgen3.py') capture_gen = generator(prog3, output : ['@BASENAME@.yy.c'], arguments : ['@INPUT@'], capture : true) capture_src = capture_gen.process('name.l') test('capture', executable('capture', capture_src)) meson-0.45.1/test cases/common/98 gen extra/name.l0000644000175000017500000000003113174155420023031 0ustar jpakkanejpakkane00000000000000int main() { return 0; } meson-0.45.1/test cases/common/98 gen extra/plain.c0000644000175000017500000000011612650745767023230 0ustar jpakkanejpakkane00000000000000int bob_mcbob(); int main(int argc, char **argv) { return bob_mcbob(); } meson-0.45.1/test cases/common/98 gen extra/name.dat0000644000175000017500000000001212650745767023366 0ustar jpakkanejpakkane00000000000000bob_mcbob meson-0.45.1/test cases/common/98 gen extra/srcgen3.py0000644000175000017500000000044313254550710023661 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import os import sys import argparse parser = argparse.ArgumentParser() parser.add_argument('input', help='the input file') options = parser.parse_args(sys.argv[1:]) with open(options.input) as f: content = f.read().strip() print(content) meson-0.45.1/test cases/common/41 elif/0000755000175000017500000000000013254552747021004 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/41 elif/meson.build0000644000175000017500000000042613254551702023136 0ustar jpakkanejpakkane00000000000000project('elseif', 'c') t = true f = false if true message('Ok.') elif true error('Error') else error('Error') endif if f error('Error.') elif t message('Ok') else error('Error') endif if f error('Error.') elif false error('Error') else message('Ok') endif meson-0.45.1/test cases/common/83 has type/0000755000175000017500000000000013254552747021610 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/83 has type/meson.build0000644000175000017500000000054113254552002023732 0ustar jpakkanejpakkane00000000000000project('has type', 'c', 'cpp') compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] foreach cc : compilers if not cc.has_type('time_t', prefix : '#include') error('Did not detect type that exists.') endif if cc.has_type('no_time_t', prefix : '#include') error('Not existing type found.') endif endforeach meson-0.45.1/test cases/common/89 add language/0000755000175000017500000000000013254552747022375 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/89 add language/meson.build0000644000175000017500000000044113254552007024523 0ustar jpakkanejpakkane00000000000000project('add language', 'c') test('C', executable('cprog', 'prog.c')) assert(add_languages('cpp'), 'Add_languages returned false on success') assert(not add_languages('klingon', required : false), 'Add_languages returned true on failure.') test('C++', executable('cppprog', 'prog.cc')) meson-0.45.1/test cases/common/89 add language/prog.cc0000644000175000017500000000013412650745767023656 0ustar jpakkanejpakkane00000000000000#include int main(int, char**) { std::cout << "I am C++.\n"; return 0; } meson-0.45.1/test cases/common/89 add language/prog.c0000644000175000017500000000014412650745767023514 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("I am plain C.\n"); return 0; } meson-0.45.1/test cases/common/175 get project license/0000755000175000017500000000000013254552747023766 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/175 get project license/meson.build0000644000175000017500000000030713254552136026120 0ustar jpakkanejpakkane00000000000000project('bar', 'c', license: 'Apache') executable('bar', 'bar.c') license = meson.project_license()[0] if license != 'Apache' error('The license should be Apache, but it is: ' + license) endif meson-0.45.1/test cases/common/175 get project license/bar.c0000644000175000017500000000015613243342167024667 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("I'm a main project bar.\n"); return 0; } meson-0.45.1/test cases/common/70 array arithmetic/0000755000175000017500000000000013254552747023317 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/70 array arithmetic/meson.build0000644000175000017500000000062613254551763025462 0ustar jpakkanejpakkane00000000000000project('array arithmetic', 'c') array1 = ['foo', 'bar'] array2 = ['qux', 'baz'] if array1 + array2 != ['foo', 'bar', 'qux', 'baz'] error('Array concatenation is broken') endif if array2 + array1 != ['qux', 'baz', 'foo', 'bar'] error('Array concatenation is broken') endif if array1 + array1 + array1 != ['foo', 'bar', 'foo', 'bar', 'foo', 'bar'] error('Many-array concatenation is broken') endif meson-0.45.1/test cases/common/147 mesonintrospect from scripts/0000755000175000017500000000000013254552746026003 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/147 mesonintrospect from scripts/meson.build0000644000175000017500000000051613254552105030134 0ustar jpakkanejpakkane00000000000000project('mesonintrospect from scripts', 'c') python = import('python3').find_python() ret = run_command(python, ['check_env.py', '1']) if ret.returncode() == 0 find_program(ret.stdout()) else message(ret.stdout()) message(ret.stderr()) endif meson.add_postconf_script('check_env.py') meson.add_install_script('check_env.py') meson-0.45.1/test cases/common/147 mesonintrospect from scripts/check_env.py0000644000175000017500000000107013174155420030265 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import os import sys import shlex do_print = False if len(sys.argv) > 1: do_print = bool(sys.argv[1]) if 'MESONINTROSPECT' not in os.environ: raise RuntimeError('MESONINTROSPECT not found') mesonintrospect = os.environ['MESONINTROSPECT'] introspect_arr = shlex.split(mesonintrospect) # print(mesonintrospect) # print(introspect_arr) some_executable = introspect_arr[0] if not os.path.isfile(some_executable): raise RuntimeError('{!r} does not exist'.format(mesonintrospect)) if do_print: print(some_executable, end='') meson-0.45.1/test cases/common/64 custom header generator/0000755000175000017500000000000013254552747024564 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/64 custom header generator/meson.build0000644000175000017500000000056113254551755026726 0ustar jpakkanejpakkane00000000000000project('custom header generator', 'c') gen = find_program('makeheader.py') generated_h = custom_target('makeheader.py', output : 'myheader.lh', # Suffix not .h to ensure this works with custom suffixes, too. input : 'input.def', command : [gen, '@INPUT0@', '@OUTPUT0@', files('somefile.txt')]) prog = executable('prog', 'prog.c', generated_h) test('gentest', prog) meson-0.45.1/test cases/common/64 custom header generator/somefile.txt0000644000175000017500000000000013254550743027110 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/64 custom header generator/prog.c0000644000175000017500000000011712650745767025703 0ustar jpakkanejpakkane00000000000000#include"myheader.lh" int main(int argc, char **argv) { return RET_VAL; } meson-0.45.1/test cases/common/64 custom header generator/makeheader.py0000644000175000017500000000050213254550741027211 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 # NOTE: this file does not have the executable bit set. This tests that # Meson can automatically parse shebang lines. import sys template = '#define RET_VAL %s\n' with open(sys.argv[1]) as f: output = template % (f.readline().strip(), ) with open(sys.argv[2], 'w') as f: f.write(output) meson-0.45.1/test cases/common/64 custom header generator/input.def0000644000175000017500000000000213254550740026362 0ustar jpakkanejpakkane000000000000000 meson-0.45.1/test cases/common/78 ctarget dependency/0000755000175000017500000000000013254552747023627 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/78 ctarget dependency/gen1.py0000755000175000017500000000035513057037314025026 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import time, sys # Make sure other script runs first if dependency # is missing. time.sleep(0.5) with open(sys.argv[1], 'r') as f: contents = f.read() with open(sys.argv[2], 'w') as f: f.write(contents) meson-0.45.1/test cases/common/78 ctarget dependency/meson.build0000644000175000017500000000105613254551772025770 0ustar jpakkanejpakkane00000000000000project('custom target dependency', 'c') # Sometimes custom targets do not take input files # but instead do globbing or some similar wackiness. # In this case we need to be able to specify a # manual dependency between two custom targets, # if one needs to be run before the other. g1 = find_program('gen1.py') g2 = find_program('gen2.py') c1 = custom_target('medput', input : 'input.dat', output : 'medput.tmp', command : [g1, '@INPUT@', '@OUTPUT@']) custom_target('output', output : 'output.dat', command : [g2, '@OUTDIR@', '@OUTPUT@'], depends : c1) meson-0.45.1/test cases/common/78 ctarget dependency/gen2.py0000755000175000017500000000035213057037314025024 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys, os from glob import glob files = glob(os.path.join(sys.argv[1], '*.tmp')) assert(len(files) == 1) with open(files[0], 'r') as ifile, open(sys.argv[2], 'w') as ofile: ofile.write(ifile.read()) meson-0.45.1/test cases/common/78 ctarget dependency/input.dat0000644000175000017500000000003112650745767025457 0ustar jpakkanejpakkane00000000000000This is a piece of text. meson-0.45.1/test cases/common/88 extract all/0000755000175000017500000000000013254552747022303 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/88 extract all/extractor.h0000644000175000017500000000010212650745767024465 0ustar jpakkanejpakkane00000000000000#pragma once int func1(); int func2(); int func3(); int func4(); meson-0.45.1/test cases/common/88 extract all/meson.build0000644000175000017500000000042313254552006024430 0ustar jpakkanejpakkane00000000000000project('extract all', 'c') a = static_library('a', 'one.c', 'two.c') b = static_library('b', 'three.c', 'four.c') c = static_library('c', objects : [a.extract_all_objects(), b.extract_all_objects()]) e = executable('proggie', 'prog.c', link_with : c) test('extall', e) meson-0.45.1/test cases/common/88 extract all/one.c0000644000175000017500000000006512650745767023236 0ustar jpakkanejpakkane00000000000000#include"extractor.h" int func1() { return 1; } meson-0.45.1/test cases/common/88 extract all/four.c0000644000175000017500000000006512650745767023430 0ustar jpakkanejpakkane00000000000000#include"extractor.h" int func4() { return 4; } meson-0.45.1/test cases/common/88 extract all/two.c0000644000175000017500000000006512650745767023266 0ustar jpakkanejpakkane00000000000000#include"extractor.h" int func2() { return 2; } meson-0.45.1/test cases/common/88 extract all/prog.c0000644000175000017500000000033312650745767023422 0ustar jpakkanejpakkane00000000000000#include"extractor.h" #include int main(int argc, char **argv) { if((1+2+3+4) != (func1() + func2() + func3() + func4())) { printf("Arithmetic is fail.\n"); return 1; } return 0; } meson-0.45.1/test cases/common/88 extract all/three.c0000644000175000017500000000006512650745767023564 0ustar jpakkanejpakkane00000000000000#include"extractor.h" int func3() { return 3; } meson-0.45.1/test cases/common/29 pipeline/0000755000175000017500000000000013254552747021700 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/29 pipeline/meson.build0000644000175000017500000000104013254551666024034 0ustar jpakkanejpakkane00000000000000project('pipeline test', 'c') # We need to run this executable locally so build it with # the host compiler. e1 = executable('srcgen', 'srcgen.c', native : true) # Generate a source file that needs to be included in the build. gen = generator(e1, \ depfile : '@BASENAME@.d', output : '@BASENAME@.c', # Line continuation inside arguments should work without needing a "\". arguments : ['@INPUT@', '@OUTPUT@', '@DEPFILE@']) generated = gen.process(['input_src.dat']) e2 = executable('prog', 'prog.c', generated) test('pipelined', e2) meson-0.45.1/test cases/common/29 pipeline/srcgen.c0000644000175000017500000000317412763077471023332 0ustar jpakkanejpakkane00000000000000#include #include #include #define ARRSIZE 80 int main(int argc, char **argv) { char arr[ARRSIZE]; char *ofilename; char *ifilename; char *dfilename; FILE *ifile; FILE *ofile; FILE *depfile; size_t bytes; int i; if(argc != 4) { fprintf(stderr, "%s \n", argv[0]); return 1; } ifilename = argv[1]; ofilename = argv[2]; dfilename = argv[3]; ifile = fopen(argv[1], "r"); if(!ifile) { fprintf(stderr, "Could not open source file %s.\n", argv[1]); return 1; } ofile = fopen(ofilename, "w"); if(!ofile) { fprintf(stderr, "Could not open target file %s\n", ofilename); fclose(ifile); return 1; } bytes = fread(arr, 1, ARRSIZE, ifile); assert(bytes < 80); assert(bytes > 0); fwrite(arr, 1, bytes, ofile); depfile = fopen(dfilename, "w"); if(!depfile) { fprintf(stderr, "Could not open depfile %s\n", ofilename); fclose(ifile); fclose(ofile); return 1; } for(i=0; i #include int main(int argc, char **argv) { if(INTSIZE != sizeof(int)) { fprintf(stderr, "Mismatch: detected int size %d, actual size %d.\n", INTSIZE, (int)sizeof(int)); return 1; } if(WCHARSIZE != sizeof(wchar_t)) { fprintf(stderr, "Mismatch: detected wchar size %d, actual size %d.\n", WCHARSIZE, (int)sizeof(wchar_t)); return 1; } return 0; } meson-0.45.1/test cases/common/35 sizeof/meson.build0000644000175000017500000000172613254551675023536 0ustar jpakkanejpakkane00000000000000project('sizeof', 'c', 'cpp') # Test with C cc = meson.get_compiler('c') intsize = cc.sizeof('int') wcharsize = cc.sizeof('wchar_t', prefix : '#include') cd = configuration_data() cd.set('INTSIZE', intsize) cd.set('WCHARSIZE', wcharsize) cd.set('CONFIG', 'config.h') configure_file(input : 'config.h.in', output : 'config.h', configuration : cd) s = configure_file(input : 'prog.c.in', output : 'prog.c', configuration : cd) e = executable('prog', s) test('sizeof test', e) # Test with C++ cpp = meson.get_compiler('cpp') intsize = cpp.sizeof('int') wcharsize = cpp.sizeof('wchar_t', prefix : '#include') cdpp = configuration_data() cdpp.set('INTSIZE', intsize) cdpp.set('WCHARSIZE', wcharsize) cdpp.set('CONFIG', 'config.hpp') configure_file(input : 'config.h.in', output : 'config.hpp', configuration : cdpp) spp = configure_file(input : 'prog.c.in', output : 'prog.cc', configuration : cdpp) epp = executable('progpp', spp) test('sizeof test c++', epp) meson-0.45.1/test cases/common/15 mixed pch/0000755000175000017500000000000013254552746021726 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/15 mixed pch/pch/0000755000175000017500000000000013254552746022500 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/15 mixed pch/pch/func_pch.c0000644000175000017500000000002112650745767024430 0ustar jpakkanejpakkane00000000000000#include"func.h" meson-0.45.1/test cases/common/15 mixed pch/pch/main_pch.cc0000644000175000017500000000002112650745767024564 0ustar jpakkanejpakkane00000000000000#include"main.h" meson-0.45.1/test cases/common/15 mixed pch/pch/main.h0000644000175000017500000000002312650745767023576 0ustar jpakkanejpakkane00000000000000#include meson-0.45.1/test cases/common/15 mixed pch/pch/func.h0000644000175000017500000000002212650745767023604 0ustar jpakkanejpakkane00000000000000#include meson-0.45.1/test cases/common/15 mixed pch/func.c0000644000175000017500000000020612650745767023031 0ustar jpakkanejpakkane00000000000000void tmp_func() { fprintf(stdout, "This is a function that fails if stdio is not #included.\n"); } int cfunc() { return 0; } meson-0.45.1/test cases/common/15 mixed pch/meson.build0000644000175000017500000000060213254551650024057 0ustar jpakkanejpakkane00000000000000project('mixed C and C++ pch test', 'cpp', 'c') exe = executable( 'prog', files('main.cc', 'func.c'), c_pch : ['pch/func.h', 'pch/func_pch.c'], cpp_pch : ['pch/main_pch.cc', 'pch/main.h'], ) cc = meson.get_compiler('c') if cc.get_id() != 'msvc' exe2 = executable( 'prog2', files('main.cc', 'func.c'), c_pch : 'pch/func.h', cpp_pch : 'pch/main.h', ) endif meson-0.45.1/test cases/common/15 mixed pch/main.cc0000644000175000017500000000032712650745767023171 0ustar jpakkanejpakkane00000000000000extern "C" int cfunc(); void func() { std::cout << "This is a function that fails to compile if iostream is not included." << std::endl; } int main(int argc, char **argv) { return cfunc(); } meson-0.45.1/test cases/common/22 header in file list/0000755000175000017500000000000013254552747023537 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/22 header in file list/meson.build0000644000175000017500000000014713254551657025702 0ustar jpakkanejpakkane00000000000000project('header in file list', 'c') exe = executable('prog', 'prog.c', 'header.h') test('basic', exe) meson-0.45.1/test cases/common/22 header in file list/prog.c0000644000175000017500000000010313074426732024636 0ustar jpakkanejpakkane00000000000000#include "header.h" int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/22 header in file list/header.h0000644000175000017500000000002213254551105025115 0ustar jpakkanejpakkane00000000000000#include meson-0.45.1/test cases/common/173 default options prefix dependent defaults/0000755000175000017500000000000013254552747030250 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/173 default options prefix dependent defaults/meson.build0000644000175000017500000000017513254552134032403 0ustar jpakkanejpakkane00000000000000project('default options prefix dependent defaults ', 'c', default_options : ['sharedstatedir=/sharedstate', 'prefix=/usr']) meson-0.45.1/test cases/common/115 spaces backslash/0000755000175000017500000000000013254552746023340 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/115 spaces backslash/comparer-end.c0000644000175000017500000000061112747162664026060 0ustar jpakkanejpakkane00000000000000#include "comparer.h" #ifndef COMPARER_INCLUDED #error "comparer.h not included" #endif #define COMPARE_WITH "foo\\bar\\" /* This is `foo\bar\` */ int main (int argc, char **argv) { if (strcmp (DEF_WITH_BACKSLASH, COMPARE_WITH)) { printf ("Arg string is quoted incorrectly: %s vs %s\n", DEF_WITH_BACKSLASH, COMPARE_WITH); return 1; } return 0; } meson-0.45.1/test cases/common/115 spaces backslash/asm output/0000755000175000017500000000000013254552746025441 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/115 spaces backslash/asm output/meson.build0000644000175000017500000000011412747162664027601 0ustar jpakkanejpakkane00000000000000configure_file(output : 'blank.txt', configuration : configuration_data()) meson-0.45.1/test cases/common/115 spaces backslash/meson.build0000644000175000017500000000246513254552042025476 0ustar jpakkanejpakkane00000000000000project('comparer', 'c') # Added manually as a c_arg to test handling of include paths with backslashes # and spaces. This is especially useful on Windows in vcxproj files since it # stores include directories in a separate element that has its own # context-specific escaping/quoting. include_dir = meson.current_source_dir() + '/include' default_c_args = ['-I' + include_dir] if meson.get_compiler('c').get_id() == 'msvc' default_c_args += ['/Faasm output\\'] # Hack to create the 'asm output' directory in the builddir subdir('asm output') endif # Path can contain \. Here we're sending `"foo\bar"`. test('backslash quoting', executable('comparer', 'comparer.c', c_args : default_c_args + ['-DDEF_WITH_BACKSLASH="foo\\bar"'])) # Path can end in \ without any special quoting. Here we send `"foo\bar\"`. test('backslash end quoting', executable('comparer-end', 'comparer-end.c', c_args : default_c_args + ['-DDEF_WITH_BACKSLASH="foo\\bar\\"'])) # Path can (really) end in \ if we're not passing a string literal without any # special quoting. Here we're sending `foo\bar\`. test('backslash end quoting when not a string literal', executable('comparer-end-notstring', 'comparer-end-notstring.c', c_args : default_c_args + ['-DDEF_WITH_BACKSLASH=foo\\bar\\'])) meson-0.45.1/test cases/common/115 spaces backslash/comparer.c0000644000175000017500000000063212747162664025317 0ustar jpakkanejpakkane00000000000000#include "comparer.h" #ifndef COMPARER_INCLUDED #error "comparer.h not included" #endif #define COMPARE_WITH "foo\\bar" /* This is the literal `foo\bar` */ int main (int argc, char **argv) { if (strcmp (DEF_WITH_BACKSLASH, COMPARE_WITH)) { printf ("Arg string is quoted incorrectly: %s instead of %s\n", DEF_WITH_BACKSLASH, COMPARE_WITH); return 1; } return 0; } meson-0.45.1/test cases/common/115 spaces backslash/include/0000755000175000017500000000000013254552746024763 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/115 spaces backslash/include/comparer.h0000644000175000017500000000010212747162664026737 0ustar jpakkanejpakkane00000000000000#include #include #define COMPARER_INCLUDED meson-0.45.1/test cases/common/115 spaces backslash/comparer-end-notstring.c0000644000175000017500000000102112747162664030101 0ustar jpakkanejpakkane00000000000000#include "comparer.h" #ifndef COMPARER_INCLUDED #error "comparer.h not included" #endif /* This converts foo\\\\bar\\\\ to "foo\\bar\\" (string literal) */ #define Q(x) #x #define QUOTE(x) Q(x) #define COMPARE_WITH "foo\\bar\\" /* This is the literal `foo\bar\` */ int main(int argc, char **argv) { if(strcmp(QUOTE(DEF_WITH_BACKSLASH), COMPARE_WITH)) { printf("Arg string is quoted incorrectly: %s instead of %s\n", QUOTE(DEF_WITH_BACKSLASH), COMPARE_WITH); return 1; } return 0; } meson-0.45.1/test cases/common/5 linkstatic/0000755000175000017500000000000013254552747022152 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/5 linkstatic/main.c0000644000175000017500000000010312650745767023241 0ustar jpakkanejpakkane00000000000000int func(); int main(int argc, char **arg) { return func(); } meson-0.45.1/test cases/common/5 linkstatic/libfile4.c0000644000175000017500000000003613012152443023764 0ustar jpakkanejpakkane00000000000000int func4() { return 4; } meson-0.45.1/test cases/common/5 linkstatic/meson.build0000644000175000017500000000035213254551635024307 0ustar jpakkanejpakkane00000000000000project('static library linking test', 'c') lib = build_target('mylib', 'libfile.c', 'libfile2.c', 'libfile3.c', 'libfile4.c', target_type : 'static_library') exe = executable('prog', 'main.c', link_with : lib) test('runtest', exe) meson-0.45.1/test cases/common/5 linkstatic/libfile.c0000644000175000017500000000003512650745767023727 0ustar jpakkanejpakkane00000000000000int func() { return 0; } meson-0.45.1/test cases/common/5 linkstatic/libfile3.c0000644000175000017500000000003613012152443023763 0ustar jpakkanejpakkane00000000000000int func3() { return 3; } meson-0.45.1/test cases/common/5 linkstatic/libfile2.c0000644000175000017500000000003613012152443023762 0ustar jpakkanejpakkane00000000000000int func2() { return 2; } meson-0.45.1/test cases/common/31 find program/0000755000175000017500000000000013254552747022434 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/31 find program/source.in0000644000175000017500000000006012650745767024265 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/31 find program/meson.build0000644000175000017500000000112413254551671024567 0ustar jpakkanejpakkane00000000000000project('find program', 'c') if build_machine.system() == 'windows' # Things Windows does not provide: # - an executable to copy files without prompting # - working command line quoting # - anything that you might actually need # Because of these reasons we only check that # the program can be found. cp = find_program('xcopy') else cp = find_program('donotfindme', 'cp') gen = generator(cp, \ output : '@BASENAME@.c', \ arguments : ['@INPUT@', '@OUTPUT@']) generated = gen.process('source.in') e = executable('prog', generated) test('external exe', e) endif meson-0.45.1/test cases/common/108 postconf with args/0000755000175000017500000000000013254552746023654 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/108 postconf with args/postconf.py0000644000175000017500000000066313057037314026054 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys, os template = '''#pragma once #define THE_NUMBER {} #define THE_ARG1 {} #define THE_ARG2 {} ''' input_file = os.path.join(os.environ['MESON_SOURCE_ROOT'], 'raw.dat') output_file = os.path.join(os.environ['MESON_BUILD_ROOT'], 'generated.h') with open(input_file) as f: data = f.readline().strip() with open(output_file, 'w') as f: f.write(template.format(data, sys.argv[1], sys.argv[2])) meson-0.45.1/test cases/common/108 postconf with args/meson.build0000644000175000017500000000020113254552030025771 0ustar jpakkanejpakkane00000000000000project('postconf script', 'c') meson.add_postconf_script('postconf.py', '5', '33') test('post', executable('prog', 'prog.c')) meson-0.45.1/test cases/common/108 postconf with args/prog.c0000644000175000017500000000017212665647635024776 0ustar jpakkanejpakkane00000000000000#include"generated.h" int main(int argc, char **argv) { return THE_NUMBER != 9 || THE_ARG1 != 5 || THE_ARG2 != 33; } meson-0.45.1/test cases/common/108 postconf with args/raw.dat0000644000175000017500000000000212665647635025136 0ustar jpakkanejpakkane000000000000009 meson-0.45.1/test cases/common/42 string operations/0000755000175000017500000000000013254552747023540 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/42 string operations/meson.build0000644000175000017500000000721713254551703025700 0ustar jpakkanejpakkane00000000000000project('string formatting', 'c') templ = '@0@bar@1@' assert(templ.format('foo', 'baz') == 'foobarbaz', 'Basic string formatting is broken.') assert('@0@'.format(1) == '1', 'String number formatting is broken.') assert('@0@'.format(true) == 'true', 'String boolean formatting is broken.') templ2 = '@0@' subs2 = '42' assert(templ2.format(subs2) == '42', 'String formatting with variables is broken.') assert('@@0@@ @@1@@'.format(1, 2) == '@1@ @2@', 'String format is recursive.') long = 'abcde' prefix = 'abc' suffix = 'cde' assert(long.startswith(prefix), 'Prefix.') assert(not long.startswith(suffix), 'Not prefix.') assert(long.endswith(suffix), 'Suffix.') assert(not long.endswith(prefix), 'Not suffix.') assert(long.contains(prefix), 'Does not contain prefix') assert(long.contains(suffix), 'Does not contain suffix') assert(long.contains('bcd'), 'Does not contain middle part') assert(not long.contains('dc'), 'Broken contains') assert(long.to_upper() == 'ABCDE', 'Broken to_upper') assert(long.to_upper().to_lower() == long, 'Broken to_lower') assert('struct stat.st_foo'.underscorify() == 'struct_stat_st_foo', 'Broken underscorify') assert('#include '.underscorify() == '_include__foo_bar_h_', 'Broken underscorify') # case should not change, space should be replaced, numbers are ok too assert('Do SomeThing 09'.underscorify() == 'Do_SomeThing_09', 'Broken underscorify') assert('3'.to_int() == 3, 'String int conversion does not work.') assert(true.to_string() == 'true', 'bool string conversion failed') assert(false.to_string() == 'false', 'bool string conversion failed') assert(true.to_string('yes', 'no') == 'yes', 'bool string conversion with args failed') assert(false.to_string('yes', 'no') == 'no', 'bool string conversion with args failed') assert('@0@'.format(true) == 'true', 'bool string formatting failed') assert(' '.join(['a', 'b', 'c']) == 'a b c', 'join() array broken') assert(''.join(['a', 'b', 'c']) == 'abc', 'empty join() broken') assert(' '.join(['a']) == 'a', 'single join broken') version_number = '1.2.8' assert(version_number.version_compare('>=1.2.8'), 'Version_compare gt broken') assert(not version_number.version_compare('>1.2.8'), 'Version_compare greater broken') assert(not version_number.version_compare('<1.2.8'), 'Version_compare less broken') assert(version_number.version_compare('<=1.2.8'), 'Version_compare le broken') assert(version_number.version_compare('==1.2.8'), 'Version_compare eq broken') assert(not version_number.version_compare('!=1.2.8'), 'Version_compare neq broken') assert(version_number.version_compare('<2.0'), 'Version_compare major less broken') assert(version_number.version_compare('>0.9'), 'Version_compare major greater broken') assert(' spaces tabs '.strip() == 'spaces tabs', 'Spaces and tabs badly stripped') assert(''' multiline string '''.strip() == '''multiline string''', 'Newlines badly stripped') assert('"1.1.20"'.strip('"') == '1.1.20', '" badly stripped') assert('"1.1.20"'.strip('".') == '1.1.20', '". badly stripped') assert('"1.1.20" '.strip('" ') == '1.1.20', '". badly stripped') bs_b = '''\b''' bs_bs_b = '''\\b''' nl = ''' ''' bs_n = '''\n''' bs_nl = '''\ ''' bs_bs_n = '''\\n''' bs_bs_nl = '''\\ ''' assert('\b' == bs_b, 'Single backslash broken') assert('\\b' == bs_b, 'Double backslash broken') assert('\\\b' == bs_bs_b, 'Three backslash broken') assert('\\\\b' == bs_bs_b, 'Four backslash broken') assert('\n' == nl, 'Newline escape broken') assert('\\n' == bs_n, 'Double backslash broken before n') assert('\\\n' == bs_nl, 'Three backslash broken before n') assert('\\\\n' == bs_bs_n, 'Four backslash broken before n') assert('\\\\\n' == bs_bs_nl, 'Five backslash broken before n') meson-0.45.1/test cases/common/8 install/0000755000175000017500000000000013254552747021456 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/8 install/installed_files.txt0000644000175000017500000000004712747162664025362 0ustar jpakkanejpakkane00000000000000usr/bin/prog?exe usr/libtest/libstat.a meson-0.45.1/test cases/common/8 install/meson.build0000644000175000017500000000026013254551636023612 0ustar jpakkanejpakkane00000000000000project('install test', 'c', default_options : ['libdir=libtest']) stlib = static_library('stat', 'stat.c', install : true) exe = executable('prog', 'prog.c', install : true) meson-0.45.1/test cases/common/8 install/stat.c0000644000175000017500000000003312650745767022576 0ustar jpakkanejpakkane00000000000000int func() { return 933; } meson-0.45.1/test cases/common/8 install/prog.c0000644000175000017500000000006212650745767022574 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/96 default library/0000755000175000017500000000000013254552750023142 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/96 default library/ef.h0000644000175000017500000000062612650745767023724 0ustar jpakkanejpakkane00000000000000#pragma once #if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif class Ef { private: int x; public: DLL_PUBLIC Ef(); int DLL_PUBLIC get_x() const; }; meson-0.45.1/test cases/common/96 default library/meson.build0000644000175000017500000000022113254552015025271 0ustar jpakkanejpakkane00000000000000project('default library', 'cpp') flib = library('ef', 'ef.cpp') exe = executable('eftest', 'eftest.cpp', link_with : flib) test('eftest', exe) meson-0.45.1/test cases/common/96 default library/ef.cpp0000644000175000017500000000014412650745767024252 0ustar jpakkanejpakkane00000000000000#include"ef.h" DLL_PUBLIC Ef::Ef() : x(99) { } int DLL_PUBLIC Ef::get_x() const { return x; } meson-0.45.1/test cases/common/96 default library/eftest.cpp0000644000175000017500000000036512650745767025157 0ustar jpakkanejpakkane00000000000000#include"ef.h" #include int main(int, char **) { Ef var; if(var.get_x() == 99) { std::cout << "All is fine.\n"; return 0; } else { std::cout << "Something went wrong.\n"; return 1; } } meson-0.45.1/test cases/common/20 array/0000755000175000017500000000000013254552747021200 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/20 array/func.c0000644000175000017500000000003112650745767022276 0ustar jpakkanejpakkane00000000000000int func() { return 0; } meson-0.45.1/test cases/common/20 array/meson.build0000644000175000017500000000017313254551655023340 0ustar jpakkanejpakkane00000000000000project('array test', 'c') arr = [ 'func.c', 'prog.c'] exe = executable('prog', sources : arr) test('arr test', exe) meson-0.45.1/test cases/common/20 array/prog.c0000644000175000017500000000010712650745767022316 0ustar jpakkanejpakkane00000000000000extern int func(); int main(int argc, char **argv) { return func(); } meson-0.45.1/test cases/common/109 testframework options/0000755000175000017500000000000013254552746024522 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/109 testframework options/test_args.txt0000644000175000017500000000035112672617123027247 0ustar jpakkanejpakkane00000000000000# This file is not read by meson itself, but by the test framework. # It is not possible to pass arguments to meson from a file. ['--werror', '-D', 'testoption=A string with spaces', '-D', 'other_one=true', \ '-D', 'combo_opt=one'] meson-0.45.1/test cases/common/109 testframework options/meson.build0000644000175000017500000000044113254552032026647 0ustar jpakkanejpakkane00000000000000project('options', 'c') assert(get_option('testoption') == 'A string with spaces', 'Incorrect value for testoption option.') assert(get_option('other_one') == true, 'Incorrect value for other_one option.') assert(get_option('combo_opt') == 'one', 'Incorrect value for combo_opt option.') meson-0.45.1/test cases/common/109 testframework options/meson_options.txt0000644000175000017500000000036012672617123030150 0ustar jpakkanejpakkane00000000000000option('testoption', type : 'string', value : 'optval', description : 'An option to do something') option('other_one', type : 'boolean', value : false) option('combo_opt', type : 'combo', choices : ['one', 'two', 'combo'], value : 'combo') meson-0.45.1/test cases/common/77 external test program/0000755000175000017500000000000013254552747024310 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/77 external test program/meson.build0000644000175000017500000000014213254551771026443 0ustar jpakkanejpakkane00000000000000project('test is external', 'c') test('external', find_program('mytest.py'), args : ['correct']) meson-0.45.1/test cases/common/77 external test program/mytest.py0000755000175000017500000000032313057037314026175 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 from __future__ import print_function import sys if sys.argv[1] == 'correct': print('Argument is correct.') sys.exit(0) print('Argument is incorrect:', sys.argv[1]) sys.exit(1) meson-0.45.1/test cases/common/164 subproject dir name collision/0000755000175000017500000000000013254552747025747 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/164 subproject dir name collision/meson.build0000644000175000017500000000035613254552125030103 0ustar jpakkanejpakkane00000000000000project('A', 'c', subproject_dir:'custom_subproject_dir') B = subproject('B') b = B.get_variable('b') C = subproject('C') c = C.get_variable('c') subdir('other_subdir') a = executable('a', 'a.c', link_with : [b, c]) test('a test', a) meson-0.45.1/test cases/common/164 subproject dir name collision/other_subdir/0000755000175000017500000000000013254552747030440 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/164 subproject dir name collision/other_subdir/meson.build0000644000175000017500000000010113206650111032547 0ustar jpakkanejpakkane00000000000000other = shared_library('other', 'custom_subproject_dir/other.c') meson-0.45.1/test cases/common/164 subproject dir name collision/other_subdir/custom_subproject_dir/0000755000175000017500000000000013254552747035050 5ustar jpakkanejpakkane00000000000000././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000meson-0.45.1/test cases/common/164 subproject dir name collision/other_subdir/custom_subproject_dir/other.cmeson-0.45.1/test cases/common/164 subproject dir name collision/other_subdir/custom_subproject_dir/0000644000175000017500000000062013206650111035025 0ustar jpakkanejpakkane00000000000000#include #if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif char DLL_PUBLIC func_b() { if('c' != 'c') { exit(3); } return 'b'; } meson-0.45.1/test cases/common/164 subproject dir name collision/a.c0000644000175000017500000000031013206650111026302 0ustar jpakkanejpakkane00000000000000#include char func_b(); char func_c(); int main(int argc, char **argv) { if(func_b() != 'b') { return 1; } if(func_c() != 'c') { return 2; } return 0; } meson-0.45.1/test cases/common/164 subproject dir name collision/custom_subproject_dir/0000755000175000017500000000000013254552745032355 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/164 subproject dir name collision/custom_subproject_dir/B/0000755000175000017500000000000013254552747032540 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/164 subproject dir name collision/custom_subproject_dir/B/meson.build0000644000175000017500000000015413206650111034657 0ustar jpakkanejpakkane00000000000000project('B', 'c') C = subproject('C') c = C.get_variable('c') b = shared_library('b', 'b.c', link_with : c) meson-0.45.1/test cases/common/164 subproject dir name collision/custom_subproject_dir/B/b.c0000644000175000017500000000064413206650111033106 0ustar jpakkanejpakkane00000000000000#include char func_c(); #if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif char DLL_PUBLIC func_b() { if(func_c() != 'c') { exit(3); } return 'b'; } meson-0.45.1/test cases/common/164 subproject dir name collision/custom_subproject_dir/C/0000755000175000017500000000000013254552747032541 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/164 subproject dir name collision/custom_subproject_dir/C/c.c0000644000175000017500000000052013206650111033101 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif char DLL_PUBLIC func_c() { return 'c'; } meson-0.45.1/test cases/common/164 subproject dir name collision/custom_subproject_dir/C/meson.build0000644000175000017500000000006113206650111034655 0ustar jpakkanejpakkane00000000000000project('C', 'c') c = shared_library('c', 'c.c') meson-0.45.1/test cases/common/170 custom target template substitution/0000755000175000017500000000000013254552747027262 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/170 custom target template substitution/foo.c.in0000644000175000017500000000012213211772701030574 0ustar jpakkanejpakkane00000000000000#include int main() { printf("foo is working.\n"); return 0; } meson-0.45.1/test cases/common/170 custom target template substitution/checkcopy.py0000644000175000017500000000031213211772701031563 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys import shutil if '@INPUT1@' in sys.argv[1]: shutil.copyfile(sys.argv[2], sys.argv[3]) else: sys.exit('String @INPUT1@ not found in "{}"'.format(sys.argv[1])) meson-0.45.1/test cases/common/170 custom target template substitution/meson.build0000644000175000017500000000073613254552132031416 0ustar jpakkanejpakkane00000000000000project('custom target template substitution', 'c') check = find_program('checkcopy.py') config = configuration_data() in = configure_file(configuration : config, output : 'x@IN') # Check that substitution does not find @FOO@ and then misses @INPUT0@. # Check the resulting x@INPUT1@ is not replaced. foo = custom_target('runcheck', input : [in, 'foo.c.in'], output : 'foo.c', command : [check, '-D@FOO@INPUT0@PUT1@', '@INPUT1@', '@OUTPUT@'] ) executable('foo', foo) meson-0.45.1/test cases/common/24 target arg/0000755000175000017500000000000013254552747022106 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/24 target arg/func.c0000644000175000017500000000021212650745767023205 0ustar jpakkanejpakkane00000000000000#ifndef CTHING #error "Local argument not set" #endif #ifdef CPPTHING #error "Wrong local argument set" #endif int func() { return 0; } meson-0.45.1/test cases/common/24 target arg/prog2.cc0000644000175000017500000000033312672617123023436 0ustar jpakkanejpakkane00000000000000#ifdef CTHING #error "Local C argument set in wrong target" #endif #ifdef CPPTHING #error "Local CPP argument set in wrong target" #endif extern "C" int func(); int main(int argc, char **argv) { return func(); } meson-0.45.1/test cases/common/24 target arg/meson.build0000644000175000017500000000034513254551662024245 0ustar jpakkanejpakkane00000000000000project('local arg test', 'cpp', 'c') exe1 = executable('prog', 'prog.cc', 'func.c', \ c_args : '-DCTHING', \ cpp_args : '-DCPPTHING') exe2 = executable('prog2', 'prog2.cc', 'func2.c') test('prog1', exe1) test('prog2', exe2) meson-0.45.1/test cases/common/24 target arg/prog.cc0000644000175000017500000000030012650745767023362 0ustar jpakkanejpakkane00000000000000#ifdef CTHING #error "Wrong local argument set" #endif #ifndef CPPTHING #error "Local argument not set" #endif extern "C" int func(); int main(int argc, char **argv) { return func(); } meson-0.45.1/test cases/common/24 target arg/func2.c0000644000175000017500000000024512672617123023261 0ustar jpakkanejpakkane00000000000000#ifdef CTHING #error "Local C argument set in wrong target" #endif #ifdef CPPTHING #error "Local CPP argument set in wrong target" #endif int func() { return 0; } meson-0.45.1/test cases/common/25 object extraction/0000755000175000017500000000000013254552747023476 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/25 object extraction/main.c0000644000175000017500000000012212650745767024566 0ustar jpakkanejpakkane00000000000000int func(); int main(int argc, char **argv) { return func() == 42 ? 0 : 1; } meson-0.45.1/test cases/common/25 object extraction/lib.c0000644000175000017500000000003612650745767024414 0ustar jpakkanejpakkane00000000000000int func() { return 42; } meson-0.45.1/test cases/common/25 object extraction/meson.build0000644000175000017500000000075713254551662025644 0ustar jpakkanejpakkane00000000000000project('object extraction', 'c') if meson.is_unity() message('Skipping extraction test because this is a Unity build.') else lib1 = shared_library('somelib', 'src/lib.c') lib2 = shared_library('somelib2', 'lib.c', 'lib2.c') obj1 = lib1.extract_objects('src/lib.c') obj2 = lib2.extract_objects(['lib.c']) e1 = executable('main1', 'main.c', objects : obj1) e2 = executable('main2', 'main.c', objects : obj2) test('extraction test 1', e1) test('extraction test 2', e2) endif meson-0.45.1/test cases/common/25 object extraction/lib2.c0000644000175000017500000000003613016624375024462 0ustar jpakkanejpakkane00000000000000int retval() { return 43; } meson-0.45.1/test cases/common/25 object extraction/src/0000755000175000017500000000000013254552747024265 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/25 object extraction/src/lib.c0000644000175000017500000000003612650745767025203 0ustar jpakkanejpakkane00000000000000int func() { return 42; } meson-0.45.1/test cases/common/104 stringdef/0000755000175000017500000000000013254552746022131 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/104 stringdef/stringdef.c0000644000175000017500000000027412650745767024273 0ustar jpakkanejpakkane00000000000000#include #include int main(int argc, char **argv) { if(strcmp(FOO, "bar")) { printf("FOO is misquoted: %s\n", FOO); return 1; } return 0; } meson-0.45.1/test cases/common/104 stringdef/meson.build0000644000175000017500000000015513254552024024261 0ustar jpakkanejpakkane00000000000000project('stringdef', 'c') test('stringdef', executable('stringdef', 'stringdef.c', c_args : '-DFOO="bar"')) meson-0.45.1/test cases/common/52 custom install dirs/0000755000175000017500000000000013254552747023752 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/52 custom install dirs/prog.10000644000175000017500000000001512650745767025004 0ustar jpakkanejpakkane00000000000000Man up, you. meson-0.45.1/test cases/common/52 custom install dirs/installed_files.txt0000644000175000017500000000036212763077471027655 0ustar jpakkanejpakkane00000000000000usr/dib/dab/dub/prog?exe usr/dib/dab/dub2/prog2?exe usr/some/dir/sample.h usr/some/dir2/sample.h usr/woman/prog.1.gz usr/woman2/prog.1.gz usr/meow/datafile.cat usr/meow2/datafile.cat usr/woof/subdir/datafile.dog usr/woof2/subdir/datafile.dog meson-0.45.1/test cases/common/52 custom install dirs/meson.build0000644000175000017500000000130013254551735026102 0ustar jpakkanejpakkane00000000000000project('custom install dirs', 'c') executable('prog', 'prog.c', install : true, install_dir : 'dib/dab/dub') executable('prog2', 'prog.c', install : true, install_dir : get_option('prefix') + '/dib/dab/dub2') install_headers('sample.h', install_dir : 'some/dir') install_headers('sample.h', install_dir : get_option('prefix') + '/some/dir2') install_man('prog.1', install_dir : 'woman') install_man('prog.1', install_dir : get_option('prefix') + '/woman2') install_data('datafile.cat', install_dir : 'meow') install_data('datafile.cat', install_dir : get_option('prefix') + '/meow2') install_subdir('subdir', install_dir : 'woof') install_subdir('subdir', install_dir : get_option('prefix') + '/woof2') meson-0.45.1/test cases/common/52 custom install dirs/subdir/0000755000175000017500000000000013254552747025242 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/52 custom install dirs/subdir/datafile.dog0000644000175000017500000000003412763077471027503 0ustar jpakkanejpakkane00000000000000Installed dog is installed. meson-0.45.1/test cases/common/52 custom install dirs/datafile.cat0000644000175000017500000000003412650745767026216 0ustar jpakkanejpakkane00000000000000Installed cat is installed. meson-0.45.1/test cases/common/52 custom install dirs/prog.c0000644000175000017500000000006112650745767025067 0ustar jpakkanejpakkane00000000000000int main(int argc, char **arv) { return 0; } meson-0.45.1/test cases/common/52 custom install dirs/sample.h0000644000175000017500000000007412650745767025412 0ustar jpakkanejpakkane00000000000000#ifndef SAMPLE_H #define SAMPLE_H int wackiness(); #endif meson-0.45.1/test cases/common/118 allgenerate/0000755000175000017500000000000013254552746022434 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/118 allgenerate/meson.build0000644000175000017500000000072113254552046024567 0ustar jpakkanejpakkane00000000000000# Must have two languages here to exercise linker language # selection bug project('all sources generated', 'c', 'cpp') comp = find_program('converter.py') g = generator(comp, output : '@BASENAME@', arguments : ['@INPUT@', '@OUTPUT@']) c = g.process('foobar.cpp.in') prog = executable('genexe', c) c2 = custom_target('c2gen', output : '@BASENAME@', input : 'foobar.cpp.in', command : [comp, '@INPUT@', '@OUTPUT@']) prog2 = executable('genexe2', c2) meson-0.45.1/test cases/common/118 allgenerate/converter.py0000755000175000017500000000017013057037314025004 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys ifile = sys.argv[1] ofile = sys.argv[2] open(ofile, 'w').write(open(ifile).read()) meson-0.45.1/test cases/common/118 allgenerate/foobar.cpp.in0000644000175000017500000000014212772547213025007 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("I am a program.\n"); return 0; } meson-0.45.1/test cases/common/87 declare dep/0000755000175000017500000000000013254552747022227 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/87 declare dep/main.c0000644000175000017500000000053312665647612023321 0ustar jpakkanejpakkane00000000000000#include #include #ifndef USING_ENT #error "Entity use flag not used for compilation." #endif int main(int argc, char **argv) { if(entity_func1() != 5) { printf("Error in func1.\n"); return 1; } if(entity_func2() != 9) { printf("Error in func2.\n"); return 2; } return 0; } meson-0.45.1/test cases/common/87 declare dep/meson.build0000644000175000017500000000130113254552005024347 0ustar jpakkanejpakkane00000000000000project('declare dependency', 'c') subdir('entity') exe = executable('dep_user', 'main.c', dependencies : entity_dep) test('dep', exe) # just to make sure [] works as a no-op dep here executable('dummy', 'main.c', dependencies : [entity_dep, []]) # simple case declare_dependency(dependencies : entity_dep) # nested deps should be flattened declare_dependency(dependencies : [entity_dep]) declare_dependency(dependencies : [[entity_dep]]) # check that [] properly works as a no-op dep in declare_dependency() too declare_dependency(dependencies : []) declare_dependency(dependencies : [[]]) declare_dependency(dependencies : [entity_dep, []]) declare_dependency(dependencies : [[], entity_dep]) meson-0.45.1/test cases/common/87 declare dep/entity/0000755000175000017500000000000013254552747023543 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/87 declare dep/entity/meson.build0000644000175000017500000000063013174155420025670 0ustar jpakkanejpakkane00000000000000entity_lib = static_library('entity', 'entity1.c') entity_dep = declare_dependency(link_with : [[entity_lib]], include_directories : include_directories('.'), sources : 'entity2.c', compile_args : ['-DUSING_ENT=1'], version : '1.2.3', link_args : []) # No simple way of testing linker flags :(. assert(entity_dep.version().version_compare('==1.2.3'), 'Declare_dep has incorrect version string.') meson-0.45.1/test cases/common/87 declare dep/entity/entity1.c0000644000175000017500000000021312665647612025301 0ustar jpakkanejpakkane00000000000000#include"entity.h" #ifdef USING_ENT #error "Entity use flag leaked into entity compilation." #endif int entity_func1() { return 5; } meson-0.45.1/test cases/common/87 declare dep/entity/entity2.c0000644000175000017500000000007112650745767025310 0ustar jpakkanejpakkane00000000000000#include int entity_func2() { return 9; } meson-0.45.1/test cases/common/87 declare dep/entity/entity.h0000644000175000017500000000006612650745767025237 0ustar jpakkanejpakkane00000000000000#pragma once int entity_func1(); int entity_func2(); meson-0.45.1/test cases/common/85 internal dependency/0000755000175000017500000000000013254552747024010 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/85 internal dependency/proj1/0000755000175000017500000000000013254552747025043 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/85 internal dependency/proj1/proj1f3.c0000644000175000017500000000013512650745767026477 0ustar jpakkanejpakkane00000000000000#include #include void proj1_func3() { printf("In proj1_func3.\n"); } meson-0.45.1/test cases/common/85 internal dependency/proj1/meson.build0000644000175000017500000000043712650745767027216 0ustar jpakkanejpakkane00000000000000incdirs = include_directories('include') p1lib = static_library('proj1', 'proj1f1.c', include_directories : incdirs ) indirect_source = files('proj1f2.c') proj1_dep = declare_dependency(include_directories : incdirs, link_with : p1lib, sources : ['proj1f3.c', indirect_source]) meson-0.45.1/test cases/common/85 internal dependency/proj1/include/0000755000175000017500000000000013254552747026466 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/85 internal dependency/proj1/include/proj1.h0000644000175000017500000000011212650745767027671 0ustar jpakkanejpakkane00000000000000#pragma once void proj1_func1(); void proj1_func2(); void proj1_func3(); meson-0.45.1/test cases/common/85 internal dependency/proj1/proj1f2.c0000644000175000017500000000013512650745767026476 0ustar jpakkanejpakkane00000000000000#include #include void proj1_func2() { printf("In proj1_func2.\n"); } meson-0.45.1/test cases/common/85 internal dependency/proj1/proj1f1.c0000644000175000017500000000013512650745767026475 0ustar jpakkanejpakkane00000000000000#include #include void proj1_func1() { printf("In proj1_func1.\n"); } meson-0.45.1/test cases/common/85 internal dependency/meson.build0000644000175000017500000000010313254552003026125 0ustar jpakkanejpakkane00000000000000project('internal dependency', 'c') subdir('proj1') subdir('src') meson-0.45.1/test cases/common/85 internal dependency/src/0000755000175000017500000000000013254552747024577 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/85 internal dependency/src/main.c0000644000175000017500000000027312650745767025676 0ustar jpakkanejpakkane00000000000000#include #include int main(int argc, char **argv) { printf("Now calling into library.\n"); proj1_func1(); proj1_func2(); proj1_func3(); return 0; } meson-0.45.1/test cases/common/85 internal dependency/src/meson.build0000644000175000017500000000012712650745767026746 0ustar jpakkanejpakkane00000000000000exe = executable('projtest', 'main.c', dependencies : proj1_dep) test('projtest', exe) meson-0.45.1/test cases/common/153 recursive linking/0000755000175000017500000000000013254552746023573 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/153 recursive linking/main.c0000644000175000017500000000200013116304505024634 0ustar jpakkanejpakkane00000000000000#include #include "lib.h" int get_stnodep_value (void); int get_stshdep_value (void); int get_ststdep_value (void); SYMBOL_IMPORT int get_shnodep_value (void); SYMBOL_IMPORT int get_shshdep_value (void); SYMBOL_IMPORT int get_shstdep_value (void); int main(int argc, char *argv[]) { int val; val = get_shnodep_value (); if (val != 1) { printf("shnodep was %i instead of 1\n", val); return -1; } val = get_stnodep_value (); if (val != 2) { printf("stnodep was %i instead of 2\n", val); return -2; } val = get_shshdep_value (); if (val != 1) { printf("shshdep was %i instead of 1\n", val); return -3; } val = get_shstdep_value (); if (val != 2) { printf("shstdep was %i instead of 2\n", val); return -4; } val = get_stshdep_value (); if (val != 1) { printf("shstdep was %i instead of 1\n", val); return -5; } val = get_ststdep_value (); if (val != 2) { printf("ststdep was %i instead of 2\n", val); return -6; } return 0; } meson-0.45.1/test cases/common/153 recursive linking/stshdep/0000755000175000017500000000000013254552746025245 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/153 recursive linking/stshdep/lib.c0000644000175000017500000000020213116304505026132 0ustar jpakkanejpakkane00000000000000#include "../lib.h" int get_shnodep_value (void); SYMBOL_EXPORT int get_stshdep_value (void) { return get_shnodep_value (); } meson-0.45.1/test cases/common/153 recursive linking/stshdep/meson.build0000644000175000017500000000017413116304505027372 0ustar jpakkanejpakkane00000000000000stshdep = static_library('stshdep', 'lib.c', link_with : shnodep, c_args : '-DMESON_STATIC_BUILD') meson-0.45.1/test cases/common/153 recursive linking/edge-cases/0000755000175000017500000000000013254552746025573 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/153 recursive linking/edge-cases/meson.build0000644000175000017500000000104713135663205027726 0ustar jpakkanejpakkane00000000000000# Test https://github.com/mesonbuild/meson/issues/2096 # Note that removing 'shnodep' from link_with: makes the error go away because # then it is added after the static library is added to the link command. test('shared-static', executable('shstexe', 'shstmain.c', link_with : [shnodep, stshdep])) # Static library that needs a symbol defined in an object file. This already # works, but good to add a test case early. stodep = static_library('stodep', 'libsto.c') test('stodep', executable('stodep', 'stomain.c', 'stobuilt.c', link_with : stodep)) meson-0.45.1/test cases/common/153 recursive linking/edge-cases/shstmain.c0000644000175000017500000000037413135663205027560 0ustar jpakkanejpakkane00000000000000#include #include "../lib.h" int get_stshdep_value (void); int main(int argc, char *argv[]) { int val; val = get_stshdep_value (); if (val != 1) { printf("st1 value was %i instead of 1\n", val); return -1; } return 0; } meson-0.45.1/test cases/common/153 recursive linking/edge-cases/libsto.c0000644000175000017500000000017713135663205027227 0ustar jpakkanejpakkane00000000000000#include "../lib.h" int get_builto_value (void); SYMBOL_EXPORT int get_stodep_value (void) { return get_builto_value (); } meson-0.45.1/test cases/common/153 recursive linking/edge-cases/stobuilt.c0000644000175000017500000000012013135663205027564 0ustar jpakkanejpakkane00000000000000#include "../lib.h" SYMBOL_EXPORT int get_builto_value (void) { return 1; } meson-0.45.1/test cases/common/153 recursive linking/edge-cases/stomain.c0000644000175000017500000000037213135663205027402 0ustar jpakkanejpakkane00000000000000#include #include "../lib.h" int get_stodep_value (void); int main(int argc, char *argv[]) { int val; val = get_stodep_value (); if (val != 1) { printf("st1 value was %i instead of 1\n", val); return -1; } return 0; } meson-0.45.1/test cases/common/153 recursive linking/shshdep/0000755000175000017500000000000013254552746025231 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/153 recursive linking/shshdep/lib.c0000644000175000017500000000020213116304505026116 0ustar jpakkanejpakkane00000000000000#include "../lib.h" int get_shnodep_value (void); SYMBOL_EXPORT int get_shshdep_value (void) { return get_shnodep_value (); } meson-0.45.1/test cases/common/153 recursive linking/shshdep/meson.build0000644000175000017500000000010213116304505027345 0ustar jpakkanejpakkane00000000000000shshdep = shared_library('shshdep', 'lib.c', link_with : shnodep) meson-0.45.1/test cases/common/153 recursive linking/meson.build0000644000175000017500000000152613254552115025727 0ustar jpakkanejpakkane00000000000000project('recursive dependencies', 'c') # Test that you can link a shared executable to: # - A shared library with no other deps subdir('shnodep') # - A static library with no other deps subdir('stnodep') # - A shared library with a shared library dep subdir('shshdep') # - A shared library with a static library dep subdir('shstdep') # - A static library with a shared library dep subdir('stshdep') # - A static library with a static library dep subdir('ststdep') test('alldeps', executable('alldeps', 'main.c', link_with : [shshdep, shstdep, ststdep, stshdep])) # More combinations of static and shared libraries subdir('3rdorderdeps') # Circular dependencies between static libraries # This requires the use of --start/end-group with GNU ld subdir('circular') # Various edge cases that have been reported subdir('edge-cases') meson-0.45.1/test cases/common/153 recursive linking/ststdep/0000755000175000017500000000000013254552746025261 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/153 recursive linking/ststdep/lib.c0000644000175000017500000000020213116304505026146 0ustar jpakkanejpakkane00000000000000#include "../lib.h" int get_stnodep_value (void); SYMBOL_EXPORT int get_ststdep_value (void) { return get_stnodep_value (); } meson-0.45.1/test cases/common/153 recursive linking/ststdep/meson.build0000644000175000017500000000017413116304505027406 0ustar jpakkanejpakkane00000000000000ststdep = static_library('ststdep', 'lib.c', link_with : stnodep, c_args : '-DMESON_STATIC_BUILD') meson-0.45.1/test cases/common/153 recursive linking/lib.h0000644000175000017500000000067613116304505024504 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 #ifdef MESON_STATIC_BUILD #define SYMBOL_EXPORT #define SYMBOL_IMPORT #else #define SYMBOL_IMPORT __declspec(dllimport) #define SYMBOL_EXPORT __declspec(dllexport) #endif #else #define SYMBOL_IMPORT #if defined __GNUC__ #define SYMBOL_EXPORT __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define SYMBOL_EXPORT #endif #endif meson-0.45.1/test cases/common/153 recursive linking/stnodep/0000755000175000017500000000000013254552746025247 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/153 recursive linking/stnodep/lib.c0000644000175000017500000000012013116304505026133 0ustar jpakkanejpakkane00000000000000#include "../lib.h" SYMBOL_EXPORT int get_stnodep_value (void) { return 2; } meson-0.45.1/test cases/common/153 recursive linking/stnodep/meson.build0000644000175000017500000000014713116304505027374 0ustar jpakkanejpakkane00000000000000stnodep = static_library('stnodep', 'lib.c', c_args : '-DMESON_STATIC_BUILD') meson-0.45.1/test cases/common/153 recursive linking/3rdorderdeps/0000755000175000017500000000000013254552746026173 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/153 recursive linking/3rdorderdeps/main.c.in0000644000175000017500000000050413116304505027650 0ustar jpakkanejpakkane00000000000000#include #include "../lib.h" SYMBOL_IMPORT int get_@LIBTYPE@@DEPENDENCY@dep_value (void); int main(int argc, char *argv[]) { int val; val = get_@LIBTYPE@@DEPENDENCY@dep_value (); if (val != @VALUE@) { printf("@LIBTYPE@@DEPENDENCY@ was %i instead of @VALUE@\n", val); return -1; } return 0; } meson-0.45.1/test cases/common/153 recursive linking/3rdorderdeps/meson.build0000644000175000017500000000306713116304505030324 0ustar jpakkanejpakkane00000000000000dep3_libs = [] # Permutate all combinations of shared and static libraries up to three levels # executable -> shared -> static -> shared (etc) foreach dep2 : ['sh', 'st'] foreach dep1 : ['sh', 'st'] foreach libtype : ['sh', 'st'] name = libtype + dep1 + dep2 if dep2 == 'sh' libret = 1 elif dep2 == 'st' libret = 2 else error('Unknown dep2 "@0@"'.format(dep2)) endif if libtype == 'sh' target = 'shared_library' build_args = [] elif libtype == 'st' target = 'static_library' build_args = ['-DMESON_STATIC_BUILD'] else error('Unknown libtype "@0@"'.format(libtype)) endif cdata = configuration_data() cdata.set('DEPENDENCY', dep1 + dep2) cdata.set('LIBTYPE', libtype) cdata.set('VALUE', libret) lib_c = configure_file(input : 'lib.c.in', output : name + '-lib.c', configuration : cdata) dep = get_variable(dep1 + dep2 + 'dep') dep3_lib = build_target(name, lib_c, link_with : dep, target_type : target, c_args : build_args) dep3_libs += [dep3_lib] main_c = configure_file(input : 'main.c.in', output : name + '-main.c', configuration : cdata) dep3_bin = executable(name, main_c, link_with : dep3_lib, c_args : build_args) test(name + 'test', dep3_bin) endforeach endforeach endforeach meson-0.45.1/test cases/common/153 recursive linking/3rdorderdeps/lib.c.in0000644000175000017500000000024313116304505027472 0ustar jpakkanejpakkane00000000000000#include "../lib.h" int get_@DEPENDENCY@dep_value (void); SYMBOL_EXPORT int get_@LIBTYPE@@DEPENDENCY@dep_value (void) { return get_@DEPENDENCY@dep_value (); } meson-0.45.1/test cases/common/153 recursive linking/circular/0000755000175000017500000000000013254552746025377 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/153 recursive linking/circular/main.c0000644000175000017500000000101613116304505026446 0ustar jpakkanejpakkane00000000000000#include #include "../lib.h" int get_st1_value (void); int get_st2_value (void); int get_st3_value (void); int main(int argc, char *argv[]) { int val; val = get_st1_value (); if (val != 5) { printf("st1 value was %i instead of 5\n", val); return -1; } val = get_st2_value (); if (val != 4) { printf("st2 value was %i instead of 4\n", val); return -2; } val = get_st3_value (); if (val != 3) { printf("st3 value was %i instead of 3\n", val); return -3; } return 0; } meson-0.45.1/test cases/common/153 recursive linking/circular/lib3.c0000644000175000017500000000017413116304505026357 0ustar jpakkanejpakkane00000000000000int get_st1_prop (void); int get_st2_prop (void); int get_st3_value (void) { return get_st1_prop () + get_st2_prop (); } meson-0.45.1/test cases/common/153 recursive linking/circular/prop2.c0000644000175000017500000000005013116304505026561 0ustar jpakkanejpakkane00000000000000int get_st2_prop (void) { return 2; } meson-0.45.1/test cases/common/153 recursive linking/circular/meson.build0000644000175000017500000000034413116304505027523 0ustar jpakkanejpakkane00000000000000st1 = static_library('st1', 'lib1.c', 'prop1.c') st2 = static_library('st2', 'lib2.c', 'prop2.c') st3 = static_library('st3', 'lib3.c', 'prop3.c') test('circular', executable('circular', 'main.c', link_with : [st1, st2, st3])) meson-0.45.1/test cases/common/153 recursive linking/circular/prop3.c0000644000175000017500000000005013116304505026562 0ustar jpakkanejpakkane00000000000000int get_st3_prop (void) { return 3; } meson-0.45.1/test cases/common/153 recursive linking/circular/lib2.c0000644000175000017500000000017413116304505026356 0ustar jpakkanejpakkane00000000000000int get_st1_prop (void); int get_st3_prop (void); int get_st2_value (void) { return get_st1_prop () + get_st3_prop (); } meson-0.45.1/test cases/common/153 recursive linking/circular/lib1.c0000644000175000017500000000017413116304505026355 0ustar jpakkanejpakkane00000000000000int get_st2_prop (void); int get_st3_prop (void); int get_st1_value (void) { return get_st2_prop () + get_st3_prop (); } meson-0.45.1/test cases/common/153 recursive linking/circular/prop1.c0000644000175000017500000000005013116304505026560 0ustar jpakkanejpakkane00000000000000int get_st1_prop (void) { return 1; } meson-0.45.1/test cases/common/153 recursive linking/shstdep/0000755000175000017500000000000013254552746025245 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/153 recursive linking/shstdep/lib.c0000644000175000017500000000020213116304505026132 0ustar jpakkanejpakkane00000000000000#include "../lib.h" int get_stnodep_value (void); SYMBOL_EXPORT int get_shstdep_value (void) { return get_stnodep_value (); } meson-0.45.1/test cases/common/153 recursive linking/shstdep/meson.build0000644000175000017500000000010213116304505027361 0ustar jpakkanejpakkane00000000000000shstdep = shared_library('shstdep', 'lib.c', link_with : stnodep) meson-0.45.1/test cases/common/153 recursive linking/shnodep/0000755000175000017500000000000013254552746025233 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/153 recursive linking/shnodep/lib.c0000644000175000017500000000012013116304505026117 0ustar jpakkanejpakkane00000000000000#include "../lib.h" SYMBOL_EXPORT int get_shnodep_value (void) { return 1; } meson-0.45.1/test cases/common/153 recursive linking/shnodep/meson.build0000644000175000017500000000007713135663205027370 0ustar jpakkanejpakkane00000000000000shnodep = shared_library('shnodep', 'lib.c', version: '0.0.0') meson-0.45.1/test cases/common/68 number arithmetic/0000755000175000017500000000000013254552747023500 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/68 number arithmetic/meson.build0000644000175000017500000000313513254551760025636 0ustar jpakkanejpakkane00000000000000project('number arithmetic', 'c') if 6 + 4 != 10 error('Number addition is broken') endif if 6 - 4 != 2 error('Number subtraction is broken') endif if 6 * 4 != 24 error('Number multiplication is broken') endif if 16 / 4 != 4 error('Number division is broken') endif #if (1 / 3) * 3 != 1 # error('Float interconversion broken') #endif if (5 / 3) * 3 != 3 error('Integer division is broken') endif assert((5 % 2) == 1, 'Integer modulo (odd) is broken') assert((4 % 2) == 0, 'Integer modulo (even) is broken') if 2 * 1 % 2 != 0 error('Modulo precedence with multiplication is broken') endif if 2 + 1 % 2 != 3 error('Modulo precedence with addition is broken') endif if 9 / 9 % 2 != 1 error('Modulo precedence with division is broken') endif if 9 - 9 % 2 != 8 error('Modulo precedence with subtraction is broken') endif assert(2.is_even(), 'int is_even() broken for even value') assert(not(2.is_odd()), 'int is_odd() broken for even value') assert(not(3.is_even()), 'int is_even() broken for odd value') assert(3.is_odd(), 'int is_odd() broken for odd value') assert(3 < 4, 'Lt broken') assert(not(4 < 3), 'Lt broken') assert(3 <= 4, 'Lte broken') assert(not(4 <= 3), 'Lte broken') assert(3 <= 3, 'Lte broken') assert(4 > 3, 'Gt broken') assert(not(3 > 4), 'Gt broken') assert(4 >= 3, 'Gte broken') assert(not(3 >= 4), 'Gte broken') assert(3 >= 3, 'Gte broken') assert(true.to_int() == 1,'bool to_int() broken') assert(false.to_int() == 0,'bool to_int() broken') hex_255 = 0xff hex2_255 = 0XFF assert(hex_255 == 255, 'Hex parsing is broken.') assert(hex2_255 == 255, 'Uppercase hex parsing is broken.') meson-0.45.1/test cases/common/1 trivial/0000755000175000017500000000000013254552746021452 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/1 trivial/meson.build0000644000175000017500000000115213254551630023602 0ustar jpakkanejpakkane00000000000000# Comment on the first line project('trivial test', # Comment inside a function call + array for language list ['c'], meson_version : '>=0.27.0') #this is a comment sources = 'trivial.c' if meson.get_compiler('c').get_id() == 'intel' # Error out if the -std=xxx option is incorrect add_project_arguments('-diag-error', '10159', language : 'c') endif if meson.is_cross_build() native_exe = executable('native-trivialprog', sources : sources, native : true) test('native exe in cross build', native_exe) endif exe = executable('trivialprog', sources : sources) test('runtest', exe) # This is a comment meson-0.45.1/test cases/common/1 trivial/trivial.c0000644000175000017500000000015712650745767023301 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("Trivial test is working.\n"); return 0; } meson-0.45.1/test cases/common/150 nested links/0000755000175000017500000000000013254552746022530 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/150 nested links/meson.build0000644000175000017500000000030013254552110024644 0ustar jpakkanejpakkane00000000000000project('test', 'c') libxserver_dri3 = [] libxserver = [ libxserver_dri3 ] executable('Xephyr', 'xephyr.c', link_with: [ libxserver ]) executable('Zephyr', 'xephyr.c', link_args: [[], []]) meson-0.45.1/test cases/common/150 nested links/xephyr.c0000644000175000017500000000003513105362433024174 0ustar jpakkanejpakkane00000000000000int main() { return 0; } meson-0.45.1/test cases/common/53 subproject subproject/0000755000175000017500000000000013254552747024411 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/53 subproject subproject/subprojects/0000755000175000017500000000000013254552745026752 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/53 subproject subproject/subprojects/a/0000755000175000017500000000000013254552747027174 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/53 subproject subproject/subprojects/a/meson.build0000644000175000017500000000015012650745767031337 0ustar jpakkanejpakkane00000000000000project('a', 'c') b = subproject('b') l = shared_library('a', 'a.c', link_with : b.get_variable('lb')) meson-0.45.1/test cases/common/53 subproject subproject/subprojects/a/a.c0000644000175000017500000000053612650745767027571 0ustar jpakkanejpakkane00000000000000int func2(); #if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif int DLL_PUBLIC func() { return func2(); } meson-0.45.1/test cases/common/53 subproject subproject/subprojects/b/0000755000175000017500000000000013254552747027175 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/53 subproject subproject/subprojects/b/meson.build0000644000175000017500000000006312650745767031343 0ustar jpakkanejpakkane00000000000000project('b', 'c') lb = shared_library('b', 'b.c') meson-0.45.1/test cases/common/53 subproject subproject/subprojects/b/b.c0000644000175000017500000000051712650745767027572 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif int DLL_PUBLIC func2() { return 42; } meson-0.45.1/test cases/common/53 subproject subproject/meson.build0000644000175000017500000000021613254551737026550 0ustar jpakkanejpakkane00000000000000project('sub sub', 'c') a = subproject('a') lib = a.get_variable('l') exe = executable('prog', 'prog.c', link_with : lib) test('basic', exe)meson-0.45.1/test cases/common/53 subproject subproject/prog.c0000644000175000017500000000012212650745767025524 0ustar jpakkanejpakkane00000000000000int func(); int main(int argc, char **argv) { return func() == 42 ? 0 : 1; } meson-0.45.1/test cases/common/36 define10/0000755000175000017500000000000013254552747021464 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/36 define10/config.h.in0000644000175000017500000000004312650745767023511 0ustar jpakkanejpakkane00000000000000#mesondefine ONE #mesondefine ZERO meson-0.45.1/test cases/common/36 define10/meson.build0000644000175000017500000000036613254551674023631 0ustar jpakkanejpakkane00000000000000project('set10test', 'c') conf = configuration_data() conf.set10('ONE', true) conf.set10('ZERO', false) configure_file(input : 'config.h.in', output : 'config.h', configuration : conf) exe = executable('prog', 'prog.c') test('10test', exe) meson-0.45.1/test cases/common/36 define10/prog.c0000644000175000017500000000036612650745767022611 0ustar jpakkanejpakkane00000000000000#include #include"config.h" int main(int argc, char **argv) { if(ONE != 1) { fprintf(stderr, "ONE is not 1.\n"); return 1; } if(ZERO != 0) { fprintf(stderr, "ZERO is not 0.\n"); } return 0; } meson-0.45.1/test cases/common/141 c cpp and asm/0000755000175000017500000000000013254552746022416 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/141 c cpp and asm/main.c0000644000175000017500000000021413070746245023476 0ustar jpakkanejpakkane00000000000000#include int get_retval(void); int main(int argc, char **argv) { printf("C seems to be working.\n"); return get_retval(); } meson-0.45.1/test cases/common/141 c cpp and asm/symbol-underscore.h0000644000175000017500000000017313070746245026237 0ustar jpakkanejpakkane00000000000000#if defined(MESON_TEST__UNDERSCORE_SYMBOL) # define SYMBOL_NAME(name) _##name #else # define SYMBOL_NAME(name) name #endif meson-0.45.1/test cases/common/141 c cpp and asm/main.cpp0000644000175000017500000000030613070746245024040 0ustar jpakkanejpakkane00000000000000#include extern "C" { int get_retval(void); int get_cval(void); } int main(int argc, char **argv) { std::cout << "C++ seems to be working." << std::endl; return get_retval(); } meson-0.45.1/test cases/common/141 c cpp and asm/meson.build0000644000175000017500000000146513254552077024563 0ustar jpakkanejpakkane00000000000000project('c cpp and asm', 'c', 'cpp') cpu = host_machine.cpu_family() cc = meson.get_compiler('c') supported_cpus = ['arm', 'x86', 'x86_64'] if not supported_cpus.contains(cpu) error('MESON_SKIP_TEST unsupported cpu:' + cpu) endif if meson.get_compiler('c').get_id() == 'msvc' error('MESON_SKIP_TEST MSVC can\'t compile assembly') endif if cc.symbols_have_underscore_prefix() add_project_arguments('-DMESON_TEST__UNDERSCORE_SYMBOL', language: 'c') endif test('test-c-asm', executable('c-asm', ['main.c', 'retval-' + cpu + '.S'])) test('test-cpp-asm', executable('cpp-asm', ['main.cpp', 'retval-' + cpu + '.S'])) test('test-c-cpp-asm', executable('c-cpp-asm', ['somelib.c', 'main.cpp', 'retval-' + cpu + '.S'])) test('test-cpp-c-asm', executable('cpp-c-asm', ['main.cpp', 'somelib.c', 'retval-' + cpu + '.S'])) meson-0.45.1/test cases/common/141 c cpp and asm/retval-x86_64.S0000644000175000017500000000026113123035221024745 0ustar jpakkanejpakkane00000000000000#include "symbol-underscore.h" .text .globl SYMBOL_NAME(get_retval) # ifdef __linux__ .type get_retval, %function #endif SYMBOL_NAME(get_retval): xorl %eax, %eax retq meson-0.45.1/test cases/common/141 c cpp and asm/retval-arm.S0000644000175000017500000000026213123035221024567 0ustar jpakkanejpakkane00000000000000#include "symbol-underscore.h" .text .globl SYMBOL_NAME(get_retval) # ifdef __linux__ .type get_retval, %function #endif SYMBOL_NAME(get_retval): mov r0, #0 mov pc, lr meson-0.45.1/test cases/common/141 c cpp and asm/retval-x86.S0000644000175000017500000000033013123035221024431 0ustar jpakkanejpakkane00000000000000#include "symbol-underscore.h" .text .globl SYMBOL_NAME(get_retval) /* Only supported on Linux with GAS */ # ifdef __linux__ .type get_retval, %function #endif SYMBOL_NAME(get_retval): xorl %eax, %eax retl meson-0.45.1/test cases/common/141 c cpp and asm/somelib.c0000644000175000017500000000004413070746245024205 0ustar jpakkanejpakkane00000000000000int get_cval (void) { return 0; } meson-0.45.1/test cases/common/62 exe static shared/0000755000175000017500000000000013254552747023350 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/62 exe static shared/stat2.c0000644000175000017500000000004613001212425024521 0ustar jpakkanejpakkane00000000000000int statlibfunc2() { return 18; } meson-0.45.1/test cases/common/62 exe static shared/meson.build0000644000175000017500000000100513254551754025503 0ustar jpakkanejpakkane00000000000000project('statchain', 'c') subdir('subdir') # Test that -fPIC in c_args is also accepted statlib2 = static_library('stat2', 'stat2.c', c_args : '-fPIC', pic : false) # Test that pic is needed for both direct and indirect static library # dependencies of shared libraries (on Linux and BSD) statlib = static_library('stat', 'stat.c', link_with : [shlib, statlib2], pic : true) shlib2 = shared_library('shr2', 'shlib2.c', link_with : statlib) exe = executable('prog', 'prog.c', link_with : shlib2) test('runtest', exe) meson-0.45.1/test cases/common/62 exe static shared/subdir/0000755000175000017500000000000013254552747024640 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/62 exe static shared/subdir/exports.h0000644000175000017500000000046213001212425026467 0ustar jpakkanejpakkane00000000000000#pragma once #if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif meson-0.45.1/test cases/common/62 exe static shared/subdir/meson.build0000644000175000017500000000005212650745767027004 0ustar jpakkanejpakkane00000000000000shlib = shared_library('shar', 'shlib.c') meson-0.45.1/test cases/common/62 exe static shared/subdir/shlib.c0000644000175000017500000000010413001212425026050 0ustar jpakkanejpakkane00000000000000#include "exports.h" int DLL_PUBLIC shlibfunc() { return 42; } meson-0.45.1/test cases/common/62 exe static shared/stat.c0000644000175000017500000000015013012152443024440 0ustar jpakkanejpakkane00000000000000#include "subdir/exports.h" int shlibfunc(); int DLL_PUBLIC statlibfunc() { return shlibfunc(); } meson-0.45.1/test cases/common/62 exe static shared/prog.c0000644000175000017500000000026513001212425024436 0ustar jpakkanejpakkane00000000000000int shlibfunc2(); int statlibfunc(); int main(int argc, char **argv) { if (statlibfunc() != 42) return 1; if (shlibfunc2() != 24) return 1; return 0; } meson-0.45.1/test cases/common/62 exe static shared/shlib2.c0000644000175000017500000000023413001212425024646 0ustar jpakkanejpakkane00000000000000#include "subdir/exports.h" int statlibfunc(void); int statlibfunc2(void); int DLL_PUBLIC shlibfunc2(void) { return statlibfunc() - statlibfunc2(); } meson-0.45.1/test cases/common/49 subproject/0000755000175000017500000000000013254552747022255 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/49 subproject/subprojects/0000755000175000017500000000000013254552745024616 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/49 subproject/subprojects/sublib/0000755000175000017500000000000013254552747026100 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/49 subproject/subprojects/sublib/simpletest.c0000644000175000017500000000013512650745767030441 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { return subfunc() == 42 ? 0 : 1; } meson-0.45.1/test cases/common/49 subproject/subprojects/sublib/meson.build0000644000175000017500000000116012742140120030213 0ustar jpakkanejpakkane00000000000000project('subproject', 'c', version : '1.0.0', license : ['sublicense1', 'sublicense2']) if not meson.is_subproject() error('Claimed to be master project even though we are a subproject.') endif assert(meson.project_name() == 'subproject', 'Incorrect subproject name') if meson.project_version() != '1.0.0' error('Incorrect version string in subproject.') endif i = include_directories('include') l = shared_library('sublib', 'sublib.c', include_directories : i, install : false, c_args : '-DBUILDING_SUB=2') t = executable('simpletest', 'simpletest.c', include_directories : i, link_with : l) test('plain', t) meson-0.45.1/test cases/common/49 subproject/subprojects/sublib/sublib.c0000644000175000017500000000010112650745767027521 0ustar jpakkanejpakkane00000000000000#include int DLL_PUBLIC subfunc() { return 42; } meson-0.45.1/test cases/common/49 subproject/subprojects/sublib/include/0000755000175000017500000000000013254552747027523 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/49 subproject/subprojects/sublib/include/subdefs.h0000644000175000017500000000067712650745767031346 0ustar jpakkanejpakkane00000000000000#ifndef SUBDEFS_H_ #define SUBDEFS_H_ #if defined _WIN32 || defined __CYGWIN__ #if defined BUILDING_SUB #define DLL_PUBLIC __declspec(dllexport) #else #define DLL_PUBLIC __declspec(dllimport) #endif #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif int DLL_PUBLIC subfunc(); #endif meson-0.45.1/test cases/common/49 subproject/installed_files.txt0000644000175000017500000000005712742140120026134 0ustar jpakkanejpakkane00000000000000usr/bin/user?exe usr/share/sublib/sublib.depmf meson-0.45.1/test cases/common/49 subproject/meson.build0000644000175000017500000000123213254551730024404 0ustar jpakkanejpakkane00000000000000project('subproj user', 'c', version : '2.3.4', license : 'mylicense') assert(meson.project_name() == 'subproj user', 'Incorrect project name') sub = subproject('sublib', version : '1.0.0') if meson.project_version() != '2.3.4' error('Incorrect master project version string:' + meson.project_version()) endif if meson.is_subproject() error('Claimed to be a subproject even though we are the master project.') endif inc = sub.get_variable('i') lib = sub.get_variable('l') e = executable('user', 'user.c', include_directories : inc, link_with : lib, install : true) test('subdirtest', e) meson.install_dependency_manifest('share/sublib/sublib.depmf') meson-0.45.1/test cases/common/49 subproject/user.c0000644000175000017500000000046712650745767023413 0ustar jpakkanejpakkane00000000000000#include #include int main(int argc, char **argv) { int res; printf("Calling into sublib now.\n"); res = subfunc(); if(res == 42) { printf("Everything is fine.\n"); return 0; } else { printf("Something went wrong.\n"); return 1; } } meson-0.45.1/test cases/common/176 yield/0000755000175000017500000000000013254552747021264 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/176 yield/subprojects/0000755000175000017500000000000013254552745023625 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/176 yield/subprojects/sub/0000755000175000017500000000000013254552747024420 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/176 yield/subprojects/sub/meson.build0000644000175000017500000000033013243342167026545 0ustar jpakkanejpakkane00000000000000project('subbie', 'c') assert(get_option('unshared_option') == 'three', 'Unshared option has wrong value in subproject.') assert(get_option('shared_option') == 'two', 'Shared option has wrong value in subproject.') meson-0.45.1/test cases/common/176 yield/subprojects/sub/meson_options.txt0000644000175000017500000000022213243342167030040 0ustar jpakkanejpakkane00000000000000option('unshared_option', type : 'string', value : 'three', yield : false) option('shared_option', type : 'string', value : 'four', yield : true) meson-0.45.1/test cases/common/176 yield/meson.build0000644000175000017500000000036713254552137023425 0ustar jpakkanejpakkane00000000000000project('yield_options', 'c') subproject('sub') assert(get_option('unshared_option') == 'one', 'Unshared option has wrong value in superproject.') assert(get_option('shared_option') == 'two', 'Unshared option has wrong value in superproject..') meson-0.45.1/test cases/common/176 yield/meson_options.txt0000644000175000017500000000016213243342167024707 0ustar jpakkanejpakkane00000000000000option('unshared_option', type : 'string', value : 'one') option('shared_option', type : 'string', value : 'two') meson-0.45.1/test cases/common/167 external program shebang parsing/0000755000175000017500000000000013254552747026444 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/167 external program shebang parsing/main.c0000644000175000017500000000243513210623121027511 0ustar jpakkanejpakkane00000000000000#include #include #include #include #include #include #ifdef _WIN32 #include #include #else #include #endif /* Who cares about stack sizes in test programs anyway */ #define LINE_LENGTH 4096 static int intrp_copyfile (char * src, char * dest) { #ifdef _WIN32 if (!CopyFile (src, dest, FALSE)) return 1; return 0; #else return execlp ("cp", "copyfile", src, dest, NULL); #endif } static void parser_get_line (FILE * f, char line[LINE_LENGTH]) { if (!fgets (line, LINE_LENGTH, f)) fprintf (stderr, "%s\n", strerror (errno)); } int main (int argc, char * argv[]) { FILE *f = NULL; char line[LINE_LENGTH]; if (argc != 4) { fprintf (stderr, "Invalid number of arguments: %i\n", argc); goto err; } if ((f = fopen (argv[1], "r")) == NULL) { fprintf (stderr, "%s\n", strerror (errno)); goto err; } parser_get_line (f, line); if (!line || line[0] != '#' || line[1] != '!') { fprintf (stderr, "Invalid script\n"); goto err; } parser_get_line (f, line); if (!line || strncmp (line, "copy", 4) != 0) { fprintf (stderr, "Syntax error: %s\n", line); goto err; } return intrp_copyfile (argv[2], argv[3]); err: fclose (f); return 1; } meson-0.45.1/test cases/common/167 external program shebang parsing/meson.build0000644000175000017500000000121513254552127030575 0ustar jpakkanejpakkane00000000000000project('shebang parsing', 'c') interpreter = executable('aninterp', 'main.c', native : true) cdata = configuration_data() cdata.set('INTRP', interpreter.full_path()) f = configure_file(input : 'script.int.in', output : 'script.int', configuration : cdata) # Test that parsing a shebang with spaces works properly. See `man execve`, # specifically the section on "Interpreter scripts" and the one under "NOTES". script = find_program(f) custom_target('interpthis', input : 'input.txt', output : 'output.txt', depends : interpreter, command : [script, '@INPUT@', '@OUTPUT@'], build_by_default : true) meson-0.45.1/test cases/common/167 external program shebang parsing/input.txt0000644000175000017500000000002013210623121030305 0ustar jpakkanejpakkane00000000000000some stuff here meson-0.45.1/test cases/common/167 external program shebang parsing/script.int.in0000644000175000017500000000003413210623121031037 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env @INTRP@ copy meson-0.45.1/test cases/common/157 configure file in test/0000755000175000017500000000000013254552746024364 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/157 configure file in test/meson.build0000644000175000017500000000026113254552117026515 0ustar jpakkanejpakkane00000000000000project('conf file in test') test_file = configure_file( input: 'test.py.in', output: 'test.py', configuration: configuration_data() ) test('configure-file', test_file) meson-0.45.1/test cases/common/157 configure file in test/test.py.in0000755000175000017500000000005713140423077026313 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys sys.exit(0) meson-0.45.1/test cases/common/138 include order/0000755000175000017500000000000013254552746022672 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/138 include order/meson.build0000644000175000017500000000223713254552073025031 0ustar jpakkanejpakkane00000000000000project('include order', 'c') # Test that the order of priority of include paths (from first to last) is: # # 1. Target's current build directory # 2. Target's current source directory # 3. Include paths added with the `c_args:` kwarg # 4. Include paths added with the `include_directories`: kwarg # Within this, the build dir takes precedence over the source dir # 5. Include paths added via `include_directories:` of internal deps # Within this, the build dir takes precedence over the source dir # Custom target dir with a built header subdir('ctsub') # Defines an internal dep subdir('sub1') # Defines a per-target include path subdir('sub2') # Directory for `c_args:` include path subdir('sub3') # The directory where the target resides subdir('sub4') # Test that the order in which internal dependencies are specified is # preserved. This is needed especially when subprojects get involved and # multiple build-root config.h files exist, and we must be sure that the # correct one is found: https://github.com/mesonbuild/meson/issues/1495 f = executable('somefxe', 'sub4/main.c', dependencies : [correctinc, dep, wronginc]) test('eh', e) test('oh', f) meson-0.45.1/test cases/common/138 include order/sub3/0000755000175000017500000000000013254552746023546 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/138 include order/sub3/meson.build0000644000175000017500000000004213043224360025664 0ustar jpakkanejpakkane00000000000000sub3 = meson.current_source_dir() meson-0.45.1/test cases/common/138 include order/sub3/main.h0000644000175000017500000000003613043224360024622 0ustar jpakkanejpakkane00000000000000#error "sub3/main.h included" meson-0.45.1/test cases/common/138 include order/sub4/0000755000175000017500000000000013254552746023547 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/138 include order/sub4/main.c0000644000175000017500000000027013043224360024616 0ustar jpakkanejpakkane00000000000000/* Use the <> include notation to force searching in include directories */ #include int main(int argc, char *argv[]) { if (somefunc() == 1984) return 0; return 1; } meson-0.45.1/test cases/common/138 include order/sub4/meson.build0000644000175000017500000000035713174155420025703 0ustar jpakkanejpakkane00000000000000e = executable('someexe', 'main.c', ctfile, c_args : ['-I' + sub3], include_directories : j, dependencies : dep) correctinc = declare_dependency(include_directories : include_directories('.')) meson-0.45.1/test cases/common/138 include order/sub4/main.h0000644000175000017500000000004013043224360024616 0ustar jpakkanejpakkane00000000000000#pragma once #include "some.h" meson-0.45.1/test cases/common/138 include order/sub2/0000755000175000017500000000000013254552746023545 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/138 include order/sub2/meson.build0000644000175000017500000000012413066536047025701 0ustar jpakkanejpakkane00000000000000j = include_directories('.') wronginc = declare_dependency(include_directories : j) meson-0.45.1/test cases/common/138 include order/sub2/main.h0000644000175000017500000000003613043224360024621 0ustar jpakkanejpakkane00000000000000#error "sub2/main.h included" meson-0.45.1/test cases/common/138 include order/ctsub/0000755000175000017500000000000013254552746024012 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/138 include order/ctsub/meson.build0000644000175000017500000000061713174155420026145 0ustar jpakkanejpakkane00000000000000# https://github.com/mesonbuild/meson/pull/2291 copy = find_program('copyfile.py') configure_file(input : 'main.h', output : 'main.h', command : [copy, '@INPUT@', '@OUTPUT@']) ctfile = custom_target('emptyfile', input : 'emptyfile.c', output : 'emptyfile.c', command : [copy, '@INPUT@', '@OUTPUT@']) meson-0.45.1/test cases/common/138 include order/ctsub/copyfile.py0000644000175000017500000000013413174155420026161 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys import shutil shutil.copyfile(sys.argv[1], sys.argv[2]) meson-0.45.1/test cases/common/138 include order/ctsub/main.h0000644000175000017500000000003713174155420025074 0ustar jpakkanejpakkane00000000000000#error "ctsub/main.h included" meson-0.45.1/test cases/common/138 include order/ctsub/emptyfile.c0000644000175000017500000000000013174155420026127 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/138 include order/sub1/0000755000175000017500000000000013254552746023544 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/138 include order/sub1/some.h0000644000175000017500000000024413043224360024640 0ustar jpakkanejpakkane00000000000000#pragma once #if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllimport) #else #define DLL_PUBLIC #endif DLL_PUBLIC int somefunc(void); meson-0.45.1/test cases/common/138 include order/sub1/meson.build0000644000175000017500000000023713043224360025670 0ustar jpakkanejpakkane00000000000000i = include_directories('.') l = shared_library('somelib', 'some.c') dep = declare_dependency(link_with : l, include_directories : i) meson-0.45.1/test cases/common/138 include order/sub1/main.h0000644000175000017500000000003613043224360024620 0ustar jpakkanejpakkane00000000000000#error "sub1/main.h included" meson-0.45.1/test cases/common/138 include order/sub1/some.c0000644000175000017500000000015613043224360024635 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ __declspec(dllexport) #endif int somefunc(void) { return 1984; } meson-0.45.1/test cases/common/148 custom target multiple outputs/0000755000175000017500000000000013254552746026255 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/148 custom target multiple outputs/installed_files.txt0000644000175000017500000000014013102373363032136 0ustar jpakkanejpakkane00000000000000usr/include/diff.h usr/include/first.h usr/bin/diff.sh usr/bin/second.sh opt/same.h opt/same.sh meson-0.45.1/test cases/common/148 custom target multiple outputs/meson.build0000644000175000017500000000165613254552105030414 0ustar jpakkanejpakkane00000000000000project('multiple outputs install', 'c') gen = find_program('generator.py') custom_target('different-install-dirs', output : ['diff.h', 'diff.sh'], command : [gen, 'diff', '@OUTDIR@'], install : true, install_dir : [join_paths(get_option('prefix'), get_option('includedir')), join_paths(get_option('prefix'), get_option('bindir'))]) custom_target('same-install-dir', output : ['same.h', 'same.sh'], command : [gen, 'same', '@OUTDIR@'], install : true, install_dir : '/opt') custom_target('only-install-first', output : ['first.h', 'first.sh'], command : [gen, 'first', '@OUTDIR@'], install : true, install_dir : [join_paths(get_option('prefix'), get_option('includedir')), false]) custom_target('only-install-second', output : ['second.h', 'second.sh'], command : [gen, 'second', '@OUTDIR@'], install : true, install_dir : [false, join_paths(get_option('prefix'), get_option('bindir'))]) meson-0.45.1/test cases/common/148 custom target multiple outputs/generator.py0000755000175000017500000000050213102373363030601 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys, os if len(sys.argv) != 3: print(sys.argv[0], '', '') name = sys.argv[1] odir = sys.argv[2] with open(os.path.join(odir, name + '.h'), 'w') as f: f.write('int func();\n') with open(os.path.join(odir, name + '.sh'), 'w') as f: f.write('#!/bin/bash') meson-0.45.1/test cases/common/7 mixed/0000755000175000017500000000000013254552747021115 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/7 mixed/func.c0000644000175000017500000000006412650745767022221 0ustar jpakkanejpakkane00000000000000int func() { int class = 0; return class; } meson-0.45.1/test cases/common/7 mixed/meson.build0000644000175000017500000000015213254551636023251 0ustar jpakkanejpakkane00000000000000project('mixed C and C++', 'c', 'cpp') exe = executable('prog', 'main.cc', 'func.c') test('mixtest', exe) meson-0.45.1/test cases/common/7 mixed/main.cc0000644000175000017500000000015312650745767022354 0ustar jpakkanejpakkane00000000000000extern "C" int func(); class BreakPlainCCompiler; int main(int argc, char **argv) { return func(); } meson-0.45.1/test cases/common/132 dependency file generation/0000755000175000017500000000000013254552746025277 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/132 dependency file generation/meson.build0000644000175000017500000000070213254552066027433 0ustar jpakkanejpakkane00000000000000project('dep file gen', 'c') cc_id = meson.get_compiler('c').get_id() if cc_id == 'intel' # ICC does not escape spaces in paths in the dependency file, so Ninja # (correctly) thinks that the rule has multiple outputs and errors out: # 'depfile has multiple output paths' error('MESON_SKIP_TEST: Skipping test with Intel compiler because it generates broken dependency files') endif e = executable('main file', 'main .c') test('test it', e) meson-0.45.1/test cases/common/132 dependency file generation/main .c0000644000175000017500000000006113033265323026407 0ustar jpakkanejpakkane00000000000000int main(int argc, char *argv[]) { return 0; } meson-0.45.1/test cases/common/76 configure file in custom target/0000755000175000017500000000000013254552747026107 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/76 configure file in custom target/meson.build0000644000175000017500000000011013254551770030234 0ustar jpakkanejpakkane00000000000000project('conf file in custom target', 'c') subdir('inc') subdir('src') meson-0.45.1/test cases/common/76 configure file in custom target/src/0000755000175000017500000000000013254552747026676 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/76 configure file in custom target/src/mycompiler.py0000644000175000017500000000032213057037314031412 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys with open(sys.argv[1]) as ifile: if ifile.readline().strip() != '42': print('Incorrect input') with open(sys.argv[2], 'w') as ofile: ofile.write('Success\n') meson-0.45.1/test cases/common/76 configure file in custom target/src/meson.build0000644000175000017500000000105712742140120031016 0ustar jpakkanejpakkane00000000000000custom_target('thing', output : 'final.dat', input : cfile, command : [find_program('mycompiler.py'), '@INPUT@', '@OUTPUT@']) # Test usage of a `configure_file` as part of the command list py3 = find_program('python3', required : false) if not py3.found() # Maybe 'python' is Python 3 py3 = find_program('python') endif compiler = configure_file(input : 'mycompiler.py', output : 'mycompiler2.py', configuration : configuration_data()) custom_target('thing2', output : 'final2.dat', input : cfile, command : [py3, compiler, '@INPUT@', '@OUTPUT@']) meson-0.45.1/test cases/common/76 configure file in custom target/inc/0000755000175000017500000000000013254552747026660 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/76 configure file in custom target/inc/confdata.in0000644000175000017500000000001012650745767030763 0ustar jpakkanejpakkane00000000000000@VALUE@ meson-0.45.1/test cases/common/76 configure file in custom target/inc/meson.build0000644000175000017500000000022112650745767031022 0ustar jpakkanejpakkane00000000000000cdata = configuration_data() cdata.set('VALUE', '42') cfile = configure_file(input : 'confdata.in', output : 'confdata', configuration : cdata) meson-0.45.1/test cases/common/26 endian/0000755000175000017500000000000013254552747021326 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/26 endian/meson.build0000644000175000017500000000025213254551664023464 0ustar jpakkanejpakkane00000000000000project('endian check', 'c') if host_machine.endian() == 'big' add_global_arguments('-DIS_BE', language : 'c') endif test('endiantest', executable('prog', 'prog.c')) meson-0.45.1/test cases/common/26 endian/prog.c0000644000175000017500000000061012650745767022443 0ustar jpakkanejpakkane00000000000000#include int is_big_endian(void) { uint32_t one = 1; if(*((uint8_t*) &one) == 1) return 0; return 1; } int main(int argc, char **argv) { int is_be_check = is_big_endian(); int is_be; #ifdef IS_BE is_be = 1; #else is_be = 0; #endif if(is_be_check && is_be) return 0; if(!is_be_check && !is_be) return 0; return 1; } meson-0.45.1/test cases/common/59 object generator/0000755000175000017500000000000013254552747023313 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/59 object generator/source2.c0000644000175000017500000000004512650745767025045 0ustar jpakkanejpakkane00000000000000int func2_in_obj() { return 0; } meson-0.45.1/test cases/common/59 object generator/source.c0000644000175000017500000000004512650745767024763 0ustar jpakkanejpakkane00000000000000int func1_in_obj() { return 0; } meson-0.45.1/test cases/common/59 object generator/meson.build0000644000175000017500000000166513254551750025456 0ustar jpakkanejpakkane00000000000000project('object generator', 'c') python = find_program('python3', required : false) if not python.found() python = find_program('python') endif # Note that this will not add a dependency to the compiler executable. # Code will not be rebuilt if it changes. comp = '@0@/@1@'.format(meson.current_source_dir(), 'obj_generator.py') if host_machine.system() == 'windows' outputname = '@BASENAME@.obj' else outputname = '@BASENAME@.o' endif cc = meson.get_compiler('c').cmd_array().get(-1) # Generate an object file manually. gen = generator(python, output : outputname, arguments : [comp, cc, '@INPUT@', '@OUTPUT@']) generated = gen.process(['source.c', 'source2.c']) # Generate an object file with indexed OUTPUT replacement. gen2 = generator(python, output : outputname, arguments : [comp, cc, '@INPUT@', '@OUTPUT0@']) generated2 = gen2.process(['source3.c']) e = executable('prog', 'prog.c', generated, generated2) test('objgen', e)meson-0.45.1/test cases/common/59 object generator/prog.c0000644000175000017500000000023612723634706024423 0ustar jpakkanejpakkane00000000000000int func1_in_obj(); int func2_in_obj(); int func3_in_obj(); int main(int argc, char **argv) { return func1_in_obj() + func2_in_obj() + func3_in_obj(); } meson-0.45.1/test cases/common/59 object generator/obj_generator.py0000755000175000017500000000101313032764405026471 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 # Mimic a binary that generates an object file (e.g. windres). import sys, subprocess if __name__ == '__main__': if len(sys.argv) != 4: print(sys.argv[0], 'compiler input_file output_file') sys.exit(1) compiler = sys.argv[1] ifile = sys.argv[2] ofile = sys.argv[3] if compiler.endswith('cl'): cmd = [compiler, '/nologo', '/MDd', '/Fo' + ofile, '/c', ifile] else: cmd = [compiler, '-c', ifile, '-o', ofile] sys.exit(subprocess.call(cmd)) meson-0.45.1/test cases/common/59 object generator/source3.c0000644000175000017500000000004512723634706025035 0ustar jpakkanejpakkane00000000000000int func3_in_obj() { return 0; } meson-0.45.1/test cases/common/152 link depends custom target/0000755000175000017500000000000013254552746025251 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/152 link depends custom target/foo.c0000644000175000017500000000034213111335362026160 0ustar jpakkanejpakkane00000000000000#include int main() { const char *fn = DEPFILE; FILE *f = fopen(fn, "r"); if (!f) { printf("could not open %s", fn); return 1; } else { printf("successfully opened %s", fn); } return 0; } meson-0.45.1/test cases/common/152 link depends custom target/meson.build0000644000175000017500000000105713254552111027400 0ustar jpakkanejpakkane00000000000000project('link_depends_custom_target', 'c') if meson.backend().startswith('vs') # FIXME: Broken on the VS backends error('MESON_SKIP_TEST see https://github.com/mesonbuild/meson/issues/1799') endif cmd = find_program('make_file.py') dep_file = custom_target('gen_dep', command: [cmd, '@OUTPUT@'], output: 'dep_file') exe = executable('foo', 'foo.c', link_depends: dep_file, c_args: ['-DDEPFILE="' + dep_file.full_path()+ '"']) # check that dep_file exists, which means that link_depends target ran test('runtest', exe) meson-0.45.1/test cases/common/152 link depends custom target/make_file.py0000755000175000017500000000016313111335362027523 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys with open(sys.argv[1], 'w') as f: print('# this file does nothing', file=f) meson-0.45.1/test cases/common/34 compiler id/0000755000175000017500000000000013254552747022256 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/34 compiler id/meson.build0000644000175000017500000000017313254551672024415 0ustar jpakkanejpakkane00000000000000project('compiler id', 'c') comp = meson.get_compiler('c') str = comp.get_id() message('Compiler name is:') message(str) meson-0.45.1/test cases/common/105 find program path/0000755000175000017500000000000013254552746023432 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/105 find program path/meson.build0000644000175000017500000000146213254552026025566 0ustar jpakkanejpakkane00000000000000project('find program', 'c') python = import('python3').find_python() # Source file via string prog = find_program('program.py') # Source file via files() progf = files('program.py') # Built file py = configure_file(input : 'program.py', output : 'builtprogram.py', configuration : configuration_data()) foreach f : [prog, progf, py, find_program(py), find_program(progf)] ret = run_command(python, f) assert(ret.returncode() == 0, 'can\'t manually run @0@'.format(prog.path())) assert(ret.stdout().strip() == 'Found', 'wrong output from manually-run @0@'.format(prog.path())) ret = run_command(f) assert(ret.returncode() == 0, 'can\'t run @0@'.format(prog.path())) assert(ret.stdout().strip() == 'Found', 'wrong output from @0@'.format(prog.path())) endforeach meson-0.45.1/test cases/common/105 find program path/program.py0000755000175000017500000000004713104161766025447 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 print("Found") meson-0.45.1/test cases/common/39 tryrun/0000755000175000017500000000000013254552747021437 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/39 tryrun/ok.c0000644000175000017500000000020313001212425022157 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("%s\n", "stdout"); fprintf(stderr, "%s\n", "stderr"); return 0; } meson-0.45.1/test cases/common/39 tryrun/meson.build0000644000175000017500000000356713254551703023603 0ustar jpakkanejpakkane00000000000000project('tryrun', 'c', 'cpp') # Complex to exercise all code paths. if meson.is_cross_build() if meson.has_exe_wrapper() compilers = [meson.get_compiler('c', native : false), meson.get_compiler('cpp', native : false)] else compilers = [meson.get_compiler('c', native : true), meson.get_compiler('cpp', native : true)] endif else compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] endif ok_code = '''#include int main(int argc, char **argv) { printf("%s\n", "stdout"); fprintf(stderr, "%s\n", "stderr"); return 0; } ''' error_code = '''int main(int argc, char **argv) { return 1; } ''' no_compile_code = '''int main(int argc, char **argv) { ''' INPUTS = [ ['String', ok_code, error_code, no_compile_code], ['File', files('ok.c'), files('error.c'), files('no_compile.c')], ] foreach cc : compilers foreach input : INPUTS type = input[0] ok = cc.run(input[1], name : type + ' should succeed') err = cc.run(input[2], name : type + ' should fail') noc = cc.run(input[3], name : type + ' does not compile') if noc.compiled() error(type + ' compilation fail test failed.') else message(type + ' fail detected properly.') endif if ok.compiled() message(type + ' compilation worked.') else error(type + ' compilation did not work.') endif if ok.returncode() == 0 message(type + ' return code ok.') else error(type + ' return code fail') endif if err.returncode() == 1 message(type + ' bad return code ok.') else error(type + ' bad return code fail.') endif if ok.stdout().strip() == 'stdout' message(type + ' stdout ok.') else message(type + ' bad stdout.') endif if ok.stderr().strip() == 'stderr' message(type + ' stderr ok.') else message(type + ' bad stderr.') endif endforeach endforeach meson-0.45.1/test cases/common/39 tryrun/no_compile.c0000644000175000017500000000004213001212425023673 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { meson-0.45.1/test cases/common/39 tryrun/error.c0000644000175000017500000000006013001212425022700 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 1; } meson-0.45.1/test cases/common/106 subproject subdir/0000755000175000017500000000000013254552746023577 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/106 subproject subdir/subprojects/0000755000175000017500000000000013254552745026141 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/106 subproject subdir/subprojects/sub/0000755000175000017500000000000013254552746026733 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/106 subproject subdir/subprojects/sub/meson.build0000644000175000017500000000004212664266514031070 0ustar jpakkanejpakkane00000000000000project('sub', 'c') subdir('lib') meson-0.45.1/test cases/common/106 subproject subdir/subprojects/sub/lib/0000755000175000017500000000000013254552746027501 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/106 subproject subdir/subprojects/sub/lib/sub.c0000644000175000017500000000005312664266514030433 0ustar jpakkanejpakkane00000000000000#include "sub.h" int sub() { return 0; } meson-0.45.1/test cases/common/106 subproject subdir/subprojects/sub/lib/meson.build0000644000175000017500000000020012664266514031632 0ustar jpakkanejpakkane00000000000000lib = static_library('sub', 'sub.c') libSub = declare_dependency(include_directories: include_directories('.'), link_with: lib) meson-0.45.1/test cases/common/106 subproject subdir/subprojects/sub/lib/sub.h0000644000175000017500000000006012664266514030436 0ustar jpakkanejpakkane00000000000000#ifndef SUB_H #define SUB_H int sub(); #endif meson-0.45.1/test cases/common/106 subproject subdir/meson.build0000644000175000017500000000027013254552026025727 0ustar jpakkanejpakkane00000000000000project('proj', 'c') subproject('sub') libSub = dependency('sub', fallback: ['sub', 'libSub']) exe = executable('prog', 'prog.c', dependencies: libSub) test('subproject subdir', exe) meson-0.45.1/test cases/common/106 subproject subdir/prog.c0000644000175000017500000000006012664266514024705 0ustar jpakkanejpakkane00000000000000#include int main() { return sub(); } meson-0.45.1/test cases/common/142 compute int/0000755000175000017500000000000013254552746022375 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/142 compute int/foobar.h0000644000175000017500000000014513074426732024011 0ustar jpakkanejpakkane00000000000000#ifndef __FOOBAR_H__ #define __FOOBAR_H__ #define FOOBAR_IN_FOOBAR_H 10 #endif /*__FOOBAR_H__*/ meson-0.45.1/test cases/common/142 compute int/config.h.in0000644000175000017500000000007613074426732024416 0ustar jpakkanejpakkane00000000000000#define INTSIZE @INTSIZE@ #define FOOBAR_IN_CONFIG_H @FOOBAR@ meson-0.45.1/test cases/common/142 compute int/prog.c.in0000644000175000017500000000073513074426732024115 0ustar jpakkanejpakkane00000000000000#include "@CONFIG@" #include #include #include "foobar.h" int main(int argc, char **argv) { if(INTSIZE != sizeof(int)) { fprintf(stderr, "Mismatch: computed int size %d, actual size %d.\n", INTSIZE, (int)sizeof(int)); return 1; } if(FOOBAR_IN_CONFIG_H != FOOBAR_IN_FOOBAR_H) { fprintf(stderr, "Mismatch: computed int %d, should be %d.\n", FOOBAR_IN_CONFIG_H, FOOBAR_IN_FOOBAR_H); return 1; } return 0; } meson-0.45.1/test cases/common/142 compute int/meson.build0000644000175000017500000000220613254552101024520 0ustar jpakkanejpakkane00000000000000project('compute int', 'c', 'cpp') inc = include_directories('.') # Test with C cc = meson.get_compiler('c') intsize = cc.compute_int('sizeof(int)', low : 1, high : 16, guess : 4) foobar = cc.compute_int('FOOBAR_IN_FOOBAR_H', prefix : '#include "foobar.h"', include_directories : inc) cd = configuration_data() cd.set('INTSIZE', intsize) cd.set('FOOBAR', foobar) cd.set('CONFIG', 'config.h') configure_file(input : 'config.h.in', output : 'config.h', configuration : cd) s = configure_file(input : 'prog.c.in', output : 'prog.c', configuration : cd) e = executable('prog', s) test('compute int test', e) # Test with C++ cpp = meson.get_compiler('cpp') intsize = cpp.compute_int('sizeof(int)') foobar = cpp.compute_int('FOOBAR_IN_FOOBAR_H', prefix : '#include "foobar.h"', include_directories : inc) cdpp = configuration_data() cdpp.set('INTSIZE', intsize) cdpp.set('FOOBAR', foobar) cdpp.set('CONFIG', 'config.hpp') configure_file(input : 'config.h.in', output : 'config.hpp', configuration : cdpp) spp = configure_file(input : 'prog.c.in', output : 'prog.cc', configuration : cdpp) epp = executable('progpp', spp) test('compute int test c++', epp) meson-0.45.1/test cases/common/155 simd/0000755000175000017500000000000013254552746021106 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/155 simd/simd_avx.c0000644000175000017500000000175213141361617023057 0ustar jpakkanejpakkane00000000000000#include #ifndef I_CAN_HAZ_SIMD #error The correct internal header was not used #endif #include #include #include #ifdef _MSC_VER #include int avx_available() { return 1; } #else #include #include #ifdef __APPLE__ /* * Apple ships a broken __builtin_cpu_supports and * some machines in the CI farm seem to be too * old to have AVX so just always return 0 here. */ int avx_available() { return 0; } #else int avx_available() { return __builtin_cpu_supports("avx"); } #endif #endif void increment_avx(float arr[4]) { double darr[4]; darr[0] = arr[0]; darr[1] = arr[1]; darr[2] = arr[2]; darr[3] = arr[3]; __m256d val = _mm256_loadu_pd(darr); __m256d one = _mm256_set1_pd(1.0); __m256d result = _mm256_add_pd(val, one); _mm256_storeu_pd(darr, result); arr[0] = (float)darr[0]; arr[1] = (float)darr[1]; arr[2] = (float)darr[2]; arr[3] = (float)darr[3]; } meson-0.45.1/test cases/common/155 simd/simd_mmx.c0000644000175000017500000000242613134457413023063 0ustar jpakkanejpakkane00000000000000#include #include #include #ifdef _MSC_VER #include int mmx_available() { return 1; } /* Contrary to MSDN documentation, MMX intrinsics * just plain don't work. */ void increment_mmx(float arr[4]) { arr[0]++; arr[1]++; arr[2]++; arr[3]++; } #elif defined(__MINGW32__) int mmx_available() { return 1; } /* MinGW does not seem to ship with MMX or it is broken. */ void increment_mmx(float arr[4]) { arr[0]++; arr[1]++; arr[2]++; arr[3]++; } #else #include #include #if defined(__APPLE__) int mmx_available() { return 1; } #else int mmx_available() { return __builtin_cpu_supports("mmx"); } #endif void increment_mmx(float arr[4]) { /* Super ugly but we know that values in arr are always small * enough to fit in int16; */ int i; __m64 packed = _mm_set_pi16(arr[3], arr[2], arr[1], arr[0]); __m64 incr = _mm_set1_pi16(1); __m64 result = _mm_add_pi16(packed, incr); /* Should be * int64_t unpacker = _m_to_int64(result); * but it does not exist on 32 bit platforms for some reason. */ int64_t unpacker = (int64_t)(result); _mm_empty(); for(i=0; i<4; i++) { arr[i] = (float)(unpacker & ((1<<16)-1)); unpacker >>= 16; } } #endif meson-0.45.1/test cases/common/155 simd/simd_sse.c0000644000175000017500000000077513134457413023061 0ustar jpakkanejpakkane00000000000000#include #include #ifdef _MSC_VER #include int sse_available() { return 1; } #else #include #include #include #if defined(__APPLE__) int sse_available() { return 1; } #else int sse_available() { return __builtin_cpu_supports("sse"); } #endif #endif void increment_sse(float arr[4]) { __m128 val = _mm_load_ps(arr); __m128 one = _mm_set_ps1(1.0); __m128 result = _mm_add_ps(val, one); _mm_storeu_ps(arr, result); } meson-0.45.1/test cases/common/155 simd/meson.build0000644000175000017500000000223113254552116023235 0ustar jpakkanejpakkane00000000000000project('simd', 'c') simd = import('unstable-simd') cc = meson.get_compiler('c') cdata = configuration_data() if not meson.is_cross_build() and host_machine.cpu_family() == 'arm' and cc.get_id() == 'clang' message('Adding -march=armv7 because assuming that this build happens on Raspbian.') message('Its Clang seems to be misconfigured and does not support NEON by default.') add_project_arguments('-march=armv7', language : 'c') endif if cc.get_id() == 'msvc' and cc.version().version_compare('<17') error('MESON_SKIP_TEST VS2010 produces broken binaries on x86.') endif # FIXME add [a, b] = function() rval = simd.check('mysimds', mmx : 'simd_mmx.c', sse : 'simd_sse.c', sse2 : 'simd_sse2.c', sse3 : 'simd_sse3.c', ssse3 : 'simd_ssse3.c', sse41 : 'simd_sse41.c', sse42 : 'simd_sse42.c', avx : 'simd_avx.c', avx2 : 'simd_avx2.c', neon : 'simd_neon.c', compiler : cc, include_directories : include_directories('include')) simdlibs = rval[0] cdata.merge_from(rval[1]) configure_file(output : 'simdconfig.h', configuration : cdata) p = executable('simdtest', 'simdchecker.c', 'fallback.c', link_with : simdlibs) test('simdtest', p) meson-0.45.1/test cases/common/155 simd/simd_avx2.c0000644000175000017500000000157313134457413023144 0ustar jpakkanejpakkane00000000000000#include #include #include /* * FIXME add proper runtime detection for VS. */ #ifdef _MSC_VER #include int avx2_available() { return 0; } #else #include #include #if defined(__APPLE__) int avx2_available() { return 0; } #else int avx2_available() { return __builtin_cpu_supports("avx2"); } #endif #endif void increment_avx2(float arr[4]) { double darr[4]; darr[0] = arr[0]; darr[1] = arr[1]; darr[2] = arr[2]; darr[3] = arr[3]; __m256d val = _mm256_loadu_pd(darr); __m256d one = _mm256_set1_pd(1.0); __m256d result = _mm256_add_pd(val, one); _mm256_storeu_pd(darr, result); one = _mm256_permute4x64_pd(one, 66); /* A no-op, just here to use AVX2. */ arr[0] = (float)darr[0]; arr[1] = (float)darr[1]; arr[2] = (float)darr[2]; arr[3] = (float)darr[3]; } meson-0.45.1/test cases/common/155 simd/fallback.c0000644000175000017500000000017513134457413023004 0ustar jpakkanejpakkane00000000000000#include void increment_fallback(float arr[4]) { int i; for(i=0; i<4; i++) { arr[i]++; } } meson-0.45.1/test cases/common/155 simd/simd_sse42.c0000644000175000017500000000155513134457413023224 0ustar jpakkanejpakkane00000000000000#include #include #include #ifdef _MSC_VER #include int sse42_available() { return 1; } #else #include #include #ifdef __APPLE__ int sse42_available() { return 1; } #else int sse42_available() { return __builtin_cpu_supports("sse4.2"); } #endif #endif void increment_sse42(float arr[4]) { double darr[4]; __m128d val1 = _mm_set_pd(arr[0], arr[1]); __m128d val2 = _mm_set_pd(arr[2], arr[3]); __m128d one = _mm_set_pd(1.0, 1.0); __m128d result = _mm_add_pd(val1, one); _mm_store_pd(darr, result); result = _mm_add_pd(val2, one); _mm_store_pd(&darr[2], result); _mm_crc32_u32(42, 99); /* A no-op, only here to use an SSE4.2 instruction. */ arr[0] = (float)darr[1]; arr[1] = (float)darr[0]; arr[2] = (float)darr[3]; arr[3] = (float)darr[2]; } meson-0.45.1/test cases/common/155 simd/simd_sse2.c0000644000175000017500000000140213134457413023127 0ustar jpakkanejpakkane00000000000000#include #include #include #ifdef _MSC_VER int sse2_available() { return 1; } #else #include #include #if defined(__APPLE__) int sse2_available() { return 1; } #else int sse2_available() { return __builtin_cpu_supports("sse2"); } #endif #endif void increment_sse2(float arr[4]) { double darr[4]; __m128d val1 = _mm_set_pd(arr[0], arr[1]); __m128d val2 = _mm_set_pd(arr[2], arr[3]); __m128d one = _mm_set_pd(1.0, 1.0); __m128d result = _mm_add_pd(val1, one); _mm_store_pd(darr, result); result = _mm_add_pd(val2, one); _mm_store_pd(&darr[2], result); arr[0] = (float)darr[1]; arr[1] = (float)darr[0]; arr[2] = (float)darr[3]; arr[3] = (float)darr[2]; } meson-0.45.1/test cases/common/155 simd/simd_sse41.c0000644000175000017500000000156213134457413023221 0ustar jpakkanejpakkane00000000000000#include #include #include #ifdef _MSC_VER #include int sse41_available() { return 1; } #else #include #include #if defined(__APPLE__) int sse41_available() { return 1; } #else int sse41_available() { return __builtin_cpu_supports("sse4.1"); } #endif #endif void increment_sse41(float arr[4]) { double darr[4]; __m128d val1 = _mm_set_pd(arr[0], arr[1]); __m128d val2 = _mm_set_pd(arr[2], arr[3]); __m128d one = _mm_set_pd(1.0, 1.0); __m128d result = _mm_add_pd(val1, one); result = _mm_ceil_pd(result); /* A no-op, only here to use a SSE4.1 intrinsic. */ _mm_store_pd(darr, result); result = _mm_add_pd(val2, one); _mm_store_pd(&darr[2], result); arr[0] = (float)darr[1]; arr[1] = (float)darr[0]; arr[2] = (float)darr[3]; arr[3] = (float)darr[2]; } meson-0.45.1/test cases/common/155 simd/simdchecker.c0000644000175000017500000000406413134457413023527 0ustar jpakkanejpakkane00000000000000#include #include /* * A function that checks at runtime which simd accelerations are * available and calls the best one. Falls * back to plain C implementation if SIMD is not available. */ int main(int argc, char **argv) { float four[4] = {2.0, 3.0, 4.0, 5.0}; const float expected[4] = {3.0, 4.0, 5.0, 6.0}; void (*fptr)(float[4]) = NULL; const char *type; int i; /* Add here. The first matched one is used so put "better" instruction * sets at the top. */ #if HAVE_NEON if(fptr == NULL && neon_available()) { fptr = increment_neon; type = "NEON"; } #endif #if HAVE_AVX2 if(fptr == NULL && avx2_available()) { fptr = increment_avx2; type = "AVX2"; } #endif #if HAVE_AVX if(fptr == NULL && avx_available()) { fptr = increment_avx; type = "AVX"; } #endif #if HAVE_SSE42 if(fptr == NULL && sse42_available()) { fptr = increment_sse42; type = "SSE42"; } #endif #if HAVE_SSE41 if(fptr == NULL && sse41_available()) { fptr = increment_sse41; type = "SSE41"; } #endif #if HAVE_SSSE3 if(fptr == NULL && ssse3_available()) { fptr = increment_ssse3; type = "SSSE3"; } #endif #if HAVE_SSE3 if(fptr == NULL && sse3_available()) { fptr = increment_sse3; type = "SSE3"; } #endif #if HAVE_SSE2 if(fptr == NULL && sse2_available()) { fptr = increment_sse2; type = "SSE2"; } #endif #if HAVE_SSE if(fptr == NULL && sse_available()) { fptr = increment_sse; type = "SSE"; } #endif #if HAVE_MMX if(fptr == NULL && mmx_available()) { fptr = increment_mmx; type = "MMX"; } #endif if(fptr == NULL) { fptr = increment_fallback; type = "fallback"; } printf("Using %s.\n", type); fptr(four); for(i=0; i<4; i++) { if(four[i] != expected[i]) { printf("Increment function failed, got %f expected %f.\n", four[i], expected[i]); return 1; } } return 0; } meson-0.45.1/test cases/common/155 simd/include/0000755000175000017500000000000013254552746022531 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/155 simd/include/simdheader.h0000644000175000017500000000004513141361617024774 0ustar jpakkanejpakkane00000000000000#pragma once #define I_CAN_HAZ_SIMD meson-0.45.1/test cases/common/155 simd/simdfuncs.h0000644000175000017500000000213313134457413023241 0ustar jpakkanejpakkane00000000000000#pragma once #include /* Yes, I do know that arr[4] decays into a pointer * as a function argument. Don't do this in real code * but for this test it is ok. */ void increment_fallback(float arr[4]); #if HAVE_MMX int mmx_available(); void increment_mmx(float arr[4]); #endif #if HAVE_SSE int sse_available(); void increment_sse(float arr[4]); #endif #if HAVE_SSE2 int sse2_available(); void increment_sse2(float arr[4]); #endif #if HAVE_SSE3 int sse3_available(); void increment_sse3(float arr[4]); #endif #if HAVE_SSSE3 int ssse3_available(); void increment_ssse3(float arr[4]); #endif #if HAVE_SSE41 int sse41_available(); void increment_sse41(float arr[4]); #endif #if HAVE_SSE42 int sse42_available(); void increment_sse42(float arr[4]); #endif #if HAVE_AVX int avx_available(); void increment_avx(float arr[4]); #endif #if HAVE_AVX2 int avx2_available(); void increment_avx2(float arr[4]); #endif #if HAVE_NEON int neon_available(); void increment_neon(float arr[4]); #endif #if HAVE_ALTIVEC int altivec_available(); void increment_altivec(float arr[4]); #endif /* And so on. */ meson-0.45.1/test cases/common/155 simd/simd_neon.c0000644000175000017500000000067113134457413023221 0ustar jpakkanejpakkane00000000000000#include #include #include #include int neon_available() { return 1; /* Incorrect, but I don't know how to check this properly. */ } void increment_neon(float arr[4]) { float32x2_t a1, a2, one; a1 = vld1_f32(arr); a2 = vld1_f32(&arr[2]); one = vdup_n_f32(1.0); a1 = vadd_f32(a1, one); a2 = vadd_f32(a2, one); vst1_f32(arr, a1); vst1_f32(&arr[2], a2); } meson-0.45.1/test cases/common/155 simd/simd_ssse3.c0000644000175000017500000000207113134457413023316 0ustar jpakkanejpakkane00000000000000#include #include #include #include #ifdef _MSC_VER #include int ssse3_available() { return 1; } #else #include #include int ssse3_available() { #ifdef __APPLE__ return 1; #elif defined(__clang__) /* https://github.com/numpy/numpy/issues/8130 */ return __builtin_cpu_supports("sse4.1"); #else return __builtin_cpu_supports("ssse3"); #endif } #endif void increment_ssse3(float arr[4]) { double darr[4]; __m128d val1 = _mm_set_pd(arr[0], arr[1]); __m128d val2 = _mm_set_pd(arr[2], arr[3]); __m128d one = _mm_set_pd(1.0, 1.0); __m128d result = _mm_add_pd(val1, one); __m128i tmp1, tmp2; tmp1 = tmp2 = _mm_set1_epi16(0); _mm_store_pd(darr, result); result = _mm_add_pd(val2, one); _mm_store_pd(&darr[2], result); tmp1 = _mm_hadd_epi32(tmp1, tmp2); /* This does nothing. Only here so we use an SSSE3 instruction. */ arr[0] = (float)darr[1]; arr[1] = (float)darr[0]; arr[2] = (float)darr[3]; arr[3] = (float)darr[2]; } meson-0.45.1/test cases/common/155 simd/simd_sse3.c0000644000175000017500000000157613134457413023144 0ustar jpakkanejpakkane00000000000000#include #include #ifdef _MSC_VER #include int sse3_available() { return 1; } #else #include #include #include #if defined(__APPLE__) int sse3_available() { return 1; } #else int sse3_available() { return __builtin_cpu_supports("sse3"); } #endif #endif void increment_sse3(float arr[4]) { double darr[4]; __m128d val1 = _mm_set_pd(arr[0], arr[1]); __m128d val2 = _mm_set_pd(arr[2], arr[3]); __m128d one = _mm_set_pd(1.0, 1.0); __m128d result = _mm_add_pd(val1, one); _mm_store_pd(darr, result); result = _mm_add_pd(val2, one); _mm_store_pd(&darr[2], result); result = _mm_hadd_pd(val1, val2); /* This does nothing. Only here so we use an SSE3 instruction. */ arr[0] = (float)darr[1]; arr[1] = (float)darr[0]; arr[2] = (float)darr[3]; arr[3] = (float)darr[2]; } meson-0.45.1/test cases/common/13 pch/0000755000175000017500000000000013254552746020635 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/13 pch/pch/0000755000175000017500000000000013254552746021407 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/13 pch/pch/prog.h0000644000175000017500000000002212650745767022527 0ustar jpakkanejpakkane00000000000000#include meson-0.45.1/test cases/common/13 pch/pch/prog_pch.c0000644000175000017500000000013712650745767023363 0ustar jpakkanejpakkane00000000000000#if !defined(_MSC_VER) #error "This file is only for use with MSVC." #endif #include "prog.h" meson-0.45.1/test cases/common/13 pch/meson.build0000644000175000017500000000014713254551644022775 0ustar jpakkanejpakkane00000000000000project('pch test', 'c') exe = executable('prog', 'prog.c', c_pch : ['pch/prog_pch.c', 'pch/prog.h']) meson-0.45.1/test cases/common/13 pch/prog.c0000644000175000017500000000031412650745767021754 0ustar jpakkanejpakkane00000000000000// 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; } meson-0.45.1/test cases/common/112 has arg/0000755000175000017500000000000013254552746021450 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/112 has arg/meson.build0000644000175000017500000000443713254552035023611 0ustar jpakkanejpakkane00000000000000project('has arg', 'c', 'cpp') cc = meson.get_compiler('c') cpp = meson.get_compiler('cpp') if cc.get_id() == 'msvc' is_arg = '/O2' useless = '/DFOO' else is_arg = '-O2' useless = '-DFOO' endif isnt_arg = '-fiambroken' assert(cc.has_argument(is_arg), 'Arg that should have worked does not work.') assert(not cc.has_argument(isnt_arg), 'Arg that should be broken is not.') assert(cpp.has_argument(is_arg), 'Arg that should have worked does not work.') assert(not cpp.has_argument(isnt_arg), 'Arg that should be broken is not.') assert(cc.get_supported_arguments([is_arg, isnt_arg, useless]) == [is_arg, useless], 'Arg filtering returned different result.') assert(cpp.get_supported_arguments([is_arg, isnt_arg, useless]) == [is_arg, useless], 'Arg filtering returned different result.') # Have useless at the end to ensure that the search goes from front to back. l1 = cc.first_supported_argument([isnt_arg, is_arg, isnt_arg, useless]) l2 = cc.first_supported_argument(isnt_arg, isnt_arg, isnt_arg) assert(l1.length() == 1, 'First supported returned wrong result.') assert(l1.get(0) == is_arg, 'First supported returned wrong argument.') assert(l2.length() == 0, 'First supported did not return empty array.') l1 = cpp.first_supported_argument([isnt_arg, is_arg, isnt_arg, useless]) l2 = cpp.first_supported_argument(isnt_arg, isnt_arg, isnt_arg) assert(l1.length() == 1, 'First supported returned wrong result.') assert(l1.get(0) == is_arg, 'First supported returned wrong argument.') assert(l2.length() == 0, 'First supported did not return empty array.') if cc.get_id() == 'gcc' pre_arg = '-Wformat' anti_pre_arg = '-Wno-format' arg = '-Werror=format-security' assert(not cc.has_multi_arguments([anti_pre_arg, arg]), 'Arg that should be broken is not.') assert(cc.has_multi_arguments(pre_arg), 'Arg that should have worked does not work.') assert(cc.has_multi_arguments([pre_arg, arg]), 'Arg that should have worked does not work.') endif if cc.get_id() == 'clang' and cc.version().version_compare('<=4.0.0') # 4.0.0 does not support -fpeel-loops. Newer versions may. # Please adjust above version number as new versions of clang are released. notyet_arg = '-fpeel-loops' assert(not cc.has_argument(notyet_arg), 'Arg that should be broken (unless clang added support recently) is not.') endif meson-0.45.1/test cases/common/67 foreach/0000755000175000017500000000000013254552747021504 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/67 foreach/prog2.c0000644000175000017500000000014712650745767022710 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("This is test #2.\n"); return 0; } meson-0.45.1/test cases/common/67 foreach/installed_files.txt0000644000175000017500000000006612742140120025363 0ustar jpakkanejpakkane00000000000000usr/bin/prog1?exe usr/bin/prog2?exe usr/bin/prog3?exe meson-0.45.1/test cases/common/67 foreach/meson.build0000644000175000017500000000133213254551760023637 0ustar jpakkanejpakkane00000000000000project('foreach', 'c') tests = [['test1', 'prog1', 'prog1.c'], ['test2', 'prog2', 'prog2.c', 'fallback'], ['test3', 'prog3', 'prog3.c', 'urgh']] assert(tests[0].get(3, 'fallbck') == 'fallbck', 'array #1 fallback did not match') assert(tests[1].get(3, 'failbk') == 'fallback', 'array #2 value did not match') assert(tests[2].get(3, 'urgh') == 'urgh', 'array #3 value did not match') foreach i : tests test(i.get(0), executable(i.get(1), i.get(2), install : true)) # Ensure that changing the tests variable does not # affect ongoing iteration in the foreach loop. # # Being able to do that would make Meson Turing complete and # we definitely don't want that. tests = ['test4', 'prog4', 'prog4.c'] endforeach meson-0.45.1/test cases/common/67 foreach/prog3.c0000644000175000017500000000014712650745767022711 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("This is test #3.\n"); return 0; } meson-0.45.1/test cases/common/67 foreach/prog1.c0000644000175000017500000000014712650745767022707 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("This is test #1.\n"); return 0; } meson-0.45.1/test cases/common/119 pathjoin/0000755000175000017500000000000013254552746021766 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/119 pathjoin/meson.build0000644000175000017500000000204313254552046024120 0ustar jpakkanejpakkane00000000000000project('pathjoin', 'c') # Test string-args form since that is the canonical way assert(join_paths('foo') == 'foo', 'Single argument join is broken') assert(join_paths('foo', 'bar') == 'foo/bar', 'Path joining is broken') assert(join_paths('foo', 'bar', 'baz') == 'foo/bar/baz', 'Path joining is broken') assert(join_paths('/foo', 'bar') == '/foo/bar', 'Path joining is broken') assert(join_paths('foo', '/bar') == '/bar', 'Absolute path joining is broken') assert(join_paths('/foo', '/bar') == '/bar', 'Absolute path joining is broken') # Test array form since people are using that too assert(join_paths(['foo']) == 'foo', 'Single argument join is broken') assert(join_paths(['foo', 'bar']) == 'foo/bar', 'Path joining is broken') assert(join_paths(['foo', 'bar', 'baz']) == 'foo/bar/baz', 'Path joining is broken') assert(join_paths(['/foo', 'bar']) == '/foo/bar', 'Path joining is broken') assert(join_paths(['foo', '/bar']) == '/bar', 'Absolute path joining is broken') assert(join_paths(['/foo', '/bar']) == '/bar', 'Absolute path joining is broken') meson-0.45.1/test cases/common/99 benchmark/0000755000175000017500000000000013254552750022026 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/99 benchmark/delayer.c0000644000175000017500000000060112650745767023627 0ustar jpakkanejpakkane00000000000000/* Simple prog that sleeps for a random time. */ #include #include #if defined(_WIN32) #include #endif int main(int argc, char **argv) { srand(time(NULL)); #if !defined(_WIN32) struct timespec t; t.tv_sec = 0; t.tv_nsec = 199999999.0*rand()/RAND_MAX; nanosleep(&t, NULL); #else Sleep(50.0*rand()/RAND_MAX); #endif return 0; } meson-0.45.1/test cases/common/99 benchmark/meson.build0000644000175000017500000000020013254552020024146 0ustar jpakkanejpakkane00000000000000project('benchmark', 'c') delayer = executable('delayer', 'delayer.c', c_args : '-D_GNU_SOURCE') benchmark('delayer', delayer) meson-0.45.1/test cases/common/60 install script/0000755000175000017500000000000013254552747023021 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/60 install script/installed_files.txt0000644000175000017500000000016113026303756026710 0ustar jpakkanejpakkane00000000000000usr/bin/prog?exe usr/diiba/daaba/file.dat usr/this/should/also-work.dat usr/this/does/something-different.dat.in meson-0.45.1/test cases/common/60 install script/meson.build0000644000175000017500000000036013254551750025153 0ustar jpakkanejpakkane00000000000000project('custom install script', 'c') executable('prog', 'prog.c', install : true) meson.add_install_script('myinstall.py', 'diiba/daaba', 'file.dat') meson.add_install_script('myinstall.py', 'this/should', 'also-work.dat') subdir('src') meson-0.45.1/test cases/common/60 install script/myinstall.py0000644000175000017500000000035613057037314025400 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import os import sys prefix = os.environ['MESON_INSTALL_DESTDIR_PREFIX'] dirname = os.path.join(prefix, sys.argv[1]) os.makedirs(dirname) with open(os.path.join(dirname, sys.argv[2]), 'w') as f: f.write('') meson-0.45.1/test cases/common/60 install script/prog.c0000644000175000017500000000014412650745767024140 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("This is text.\n"); return 0; } meson-0.45.1/test cases/common/60 install script/src/0000755000175000017500000000000013254552747023610 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/60 install script/src/meson.build0000644000175000017500000000012113026303756025733 0ustar jpakkanejpakkane00000000000000meson.add_install_script('myinstall.py', 'this/does', 'something-different.dat') meson-0.45.1/test cases/common/60 install script/src/myinstall.py0000644000175000017500000000036613057037314026170 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import os import sys prefix = os.environ['MESON_INSTALL_DESTDIR_PREFIX'] dirname = os.path.join(prefix, sys.argv[1]) os.makedirs(dirname) with open(os.path.join(dirname, sys.argv[2] + '.in'), 'w') as f: f.write('') meson-0.45.1/test cases/common/60 install script/no-installed-files0000644000175000017500000000000012742140120026376 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/163 includedir subproj/0000755000175000017500000000000013254552747023741 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/163 includedir subproj/subprojects/0000755000175000017500000000000013254552745026302 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/163 includedir subproj/subprojects/inctest/0000755000175000017500000000000013254552747027755 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/163 includedir subproj/subprojects/inctest/meson.build0000644000175000017500000000044313201146766032110 0ustar jpakkanejpakkane00000000000000 project('subproj with includedir', 'c') compile_check = ''' #include "incfile.h" ''' if not meson.get_compiler('c').compiles(compile_check, name : 'include in subproj', include_directories: include_directories('include')) error('failed') endif meson-0.45.1/test cases/common/163 includedir subproj/subprojects/inctest/include/0000755000175000017500000000000013254552747031400 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/163 includedir subproj/subprojects/inctest/include/incfile.h0000644000175000017500000000005413201146766033151 0ustar jpakkanejpakkane00000000000000 /* file which is used in the subproject */ meson-0.45.1/test cases/common/163 includedir subproj/meson.build0000644000175000017500000000017513254552124026073 0ustar jpakkanejpakkane00000000000000project('include dir in subproj test', 'c') subproject('inctest') exe = executable('prog', 'prog.c') test('dummy', exe) meson-0.45.1/test cases/common/163 includedir subproj/prog.c0000644000175000017500000000006113201146766025041 0ustar jpakkanejpakkane00000000000000 int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/102 threads/0000755000175000017500000000000013254552746021574 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/102 threads/meson.build0000644000175000017500000000046713254552022023730 0ustar jpakkanejpakkane00000000000000project('threads', 'cpp', 'c', default_options : ['cpp_std=c++11']) threaddep = dependency('threads') test('cppthreadtest', executable('cppthreadprog', 'threadprog.cpp', dependencies : threaddep ) ) test('cthreadtest', executable('cthreadprog', 'threadprog.c', dependencies : threaddep ) ) meson-0.45.1/test cases/common/102 threads/threadprog.cpp0000644000175000017500000000157212650745767024452 0ustar jpakkanejpakkane00000000000000/* On Windows not all versions of VS support C++11 and * some (most?) versions of mingw don't support std::thread, * even though they do support c++11. Since we only care about * threads working, do the test with raw win threads. */ #if defined _WIN32 #include #include DWORD WINAPI thread_func(LPVOID) { printf("Printing from a thread.\n"); return 0; } int main(int, char**) { printf("Starting thread.\n"); HANDLE th; DWORD id; th = CreateThread(NULL, 0, thread_func, NULL, 0, &id); WaitForSingleObject(th, INFINITE); printf("Stopped thread.\n"); return 0; } #else #include #include void main_func() { printf("Printing from a thread.\n"); } int main(int, char**) { printf("Starting thread.\n"); std::thread th(main_func); th.join(); printf("Stopped thread.\n"); return 0; } #endif meson-0.45.1/test cases/common/102 threads/threadprog.c0000644000175000017500000000143612650745767024111 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 #include #include DWORD WINAPI thread_func(LPVOID ignored) { printf("Printing from a thread.\n"); return 0; } int main(int argc, char **argv) { DWORD id; HANDLE th; printf("Starting thread.\n"); th = CreateThread(NULL, 0, thread_func, NULL, 0, &id); WaitForSingleObject(th, INFINITE); printf("Stopped thread.\n"); return 0; } #else #include #include void* main_func(void* ignored) { printf("Printing from a thread.\n"); return NULL; } int main(int argc, char** argv) { pthread_t thread; int rc; printf("Starting thread.\n"); rc = pthread_create(&thread, NULL, main_func, NULL); rc = pthread_join(thread, NULL); printf("Stopped thread.\n"); return rc; } #endif meson-0.45.1/test cases/common/140 get define/0000755000175000017500000000000013254552746022136 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/140 get define/meson.build0000644000175000017500000000671613254552076024306 0ustar jpakkanejpakkane00000000000000project('get define', 'c', 'cpp') host_system = host_machine.system() foreach lang : ['c', 'cpp'] cc = meson.get_compiler(lang) if host_system == 'linux' d = cc.get_define('__linux__') assert(d == '1', '__linux__ value is @0@ instead of 1'.format(d)) elif host_system == 'darwin' d = cc.get_define('__APPLE__') assert(d == '1', '__APPLE__ value is @0@ instead of 1'.format(d)) elif host_system == 'windows' d = cc.get_define('_WIN32') assert(d == '1', '_WIN32 value is @0@ instead of 1'.format(d)) elif host_system == 'cygwin' d = cc.get_define('__CYGWIN__') assert(d == '1', '__CYGWIN__ value is @0@ instead of 1'.format(d)) elif host_system == 'haiku' d = cc.get_define('__HAIKU__') assert(d == '1', '__HAIKU__ value is @0@ instead of 1'.format(d)) elif host_system == 'freebsd' # the __FreeBSD__ define will be equal to the major version of the release # (ex, in FreeBSD 11.x, __FreeBSD__ == 11). To make the test robust when # being run on various versions of FreeBSD, just test that the define is # set. d = cc.get_define('__FreeBSD__') assert(d != '', '__FreeBSD__ value is unset') elif host_system == 'dragonfly' d = cc.get_define('__DragonFly__') assert(d == '1', '__DragonFly__ value is @0@ instead of 1'.format(d)) elif host_system == 'netbsd' d = cc.get_define('__NetBSD__') assert(d == '1', '__NetBSD__ value is @0@ instead of 1'.format(d)) else error('Please report a bug and help us improve support for this platform') endif if cc.find_library('z', required : false).found() # When a C file containing #include is pre-processed and foo.h is # found in the compiler's default search path, GCC inserts an extra comment # between the delimiter and the define which causes a parsing error. # https://github.com/mesonbuild/meson/issues/1726 if host_machine.system() == 'netbsd' # NetBSD's zlib doesn't is version 1.2.3 and doesn't have a # ZLIB_VER_MAJOR, but it does have a ZLIB_VERSION (which is a string), so # check the first non-quote character of that. ver = cc.get_define('ZLIB_VERSION', prefix : '#include ')[1] assert(ver == '1', 'ZLIB_VERSION (major) value is "@0@" instead of "1"'.format(ver)) else ver = cc.get_define('ZLIB_VER_MAJOR', prefix : '#include ') assert(ver == '1', 'ZLIB_VER_MAJOR value is "@0@" instead of "1"'.format(ver)) endif endif # Check that an undefined value is empty. have = cc.get_define('MESON_FAIL_VALUE') assert(have == '', 'MESON_FAIL_VALUE value is "@0@" instead of ""'.format(have)) # This is used in the test_preprocessor_checks_CPPFLAGS() unit test. have = cc.get_define('MESON_TEST_DEFINE_VALUE') expect = get_option('MESON_TEST_DEFINE_VALUE') assert(have == expect, 'MESON_TEST_DEFINE_VALUE value is "@0@" instead of "@1@"'.format(have, expect)) run_1665_test = false if meson.is_cross_build() # Can't use an empty array as a fallback here because of # https://github.com/mesonbuild/meson/issues/1481 lang_args = meson.get_cross_property(lang + '_args', []) if lang_args.length() != 0 foreach lang_arg : lang_args if lang_arg.contains('MESON_TEST_ISSUE_1665') run_1665_test = true endif endforeach endif endif if run_1665_test have = cc.get_define('MESON_TEST_ISSUE_1665') assert(have == '1', 'MESON_TEST_ISSUE_1665 value is "@0@" instead of "1"'.format(have)) endif endforeach meson-0.45.1/test cases/common/140 get define/meson_options.txt0000644000175000017500000000007713174155420025564 0ustar jpakkanejpakkane00000000000000option('MESON_TEST_DEFINE_VALUE', type : 'string', value : '') meson-0.45.1/test cases/common/125 shared module/0000755000175000017500000000000013254552746022663 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/125 shared module/runtime.c0000644000175000017500000000070313024065327024477 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif /* * This file pretends to be a language runtime that supports extension * modules. */ int DLL_PUBLIC func_from_language_runtime(void) { return 86; } meson-0.45.1/test cases/common/125 shared module/meson.build0000644000175000017500000000107113254552057025017 0ustar jpakkanejpakkane00000000000000project('shared module', 'c') dl = meson.get_compiler('c').find_library('dl', required : false) l = shared_library('runtime', 'runtime.c') # Do NOT link the module with the runtime library. This # is a common approach for plugins that are only used # with dlopen. Any symbols are resolved dynamically # at runtime. This requires extra help on Windows, so # should be avoided unless really necessary. m = shared_module('mymodule', 'module.c') e = executable('prog', 'prog.c', link_with : l, export_dynamic : true, dependencies : dl) test('import test', e, args : m) meson-0.45.1/test cases/common/125 shared module/prog.c0000644000175000017500000000402413024065327023763 0ustar jpakkanejpakkane00000000000000 #include int func_from_language_runtime(void); typedef int (*fptr) (void); #ifdef _WIN32 #include wchar_t* win32_get_last_error (void) { wchar_t *msg = NULL; FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError (), 0, (LPWSTR) &msg, 0, NULL); return msg; } int main (int argc, char **argv) { HINSTANCE handle; fptr importedfunc; int expected, actual; int ret = 1; handle = LoadLibraryA (argv[1]); if (!handle) { wchar_t *msg = win32_get_last_error (); printf ("Could not open %s: %S\n", argv[1], msg); goto nohandle; } importedfunc = (fptr) GetProcAddress (handle, "func"); if (importedfunc == NULL) { wchar_t *msg = win32_get_last_error (); printf ("Could not find 'func': %S\n", msg); goto out; } actual = importedfunc (); expected = func_from_language_runtime (); if (actual != expected) { printf ("Got %i instead of %i\n", actual, expected); goto out; } ret = 0; out: FreeLibrary (handle); nohandle: return ret; } #else #include #include int main(int argc, char **argv) { void *dl; fptr importedfunc; int expected, actual; char *error; int ret = 1; dlerror(); dl = dlopen(argv[1], RTLD_LAZY); error = dlerror(); if(error) { printf("Could not open %s: %s\n", argv[1], error); goto nodl; } importedfunc = (fptr) dlsym(dl, "func"); if (importedfunc == NULL) { printf ("Could not find 'func'\n"); goto out; } assert(importedfunc != func_from_language_runtime); actual = (*importedfunc)(); expected = func_from_language_runtime (); if (actual != expected) { printf ("Got %i instead of %i\n", actual, expected); goto out; } ret = 0; out: dlclose(dl); nodl: return ret; } #endif meson-0.45.1/test cases/common/125 shared module/module.c0000644000175000017500000000372513074426732024316 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif #if defined(_WIN32) || defined(__CYGWIN__) #include typedef int (*fptr) (void); #ifdef __CYGWIN__ #include fptr find_any_f (const char *name) { return (fptr) dlsym(RTLD_DEFAULT, name); } #else /* _WIN32 */ #include #include /* Unlike Linux and OS X, when a library is loaded, all the symbols aren't * loaded into a single namespace. You must fetch the symbol by iterating over * all loaded modules. Code for finding the function from any of the loaded * modules is taken from gmodule.c in glib */ fptr find_any_f (const char *name) { fptr f; HANDLE snapshot; MODULEENTRY32 me32; snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0); if (snapshot == (HANDLE) -1) { printf("Could not get snapshot\n"); return 0; } me32.dwSize = sizeof (me32); f = NULL; if (Module32First (snapshot, &me32)) { do { if ((f = (fptr) GetProcAddress (me32.hModule, name)) != NULL) break; } while (Module32Next (snapshot, &me32)); } CloseHandle (snapshot); return f; } #endif int DLL_PUBLIC func() { fptr f; f = find_any_f ("func_from_language_runtime"); if (f != NULL) return f(); printf ("Could not find function\n"); return 1; } #else /* * Shared modules often have references to symbols that are not defined * at link time, but which will be provided from deps of the executable that * dlopens it. We need to make sure that this works, i.e. that we do * not pass -Wl,--no-undefined when linking modules. */ int func_from_language_runtime(); int DLL_PUBLIC func(void) { return func_from_language_runtime(); } #endif meson-0.45.1/test cases/common/116 ternary/0000755000175000017500000000000013254552746021633 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/116 ternary/meson.build0000644000175000017500000000043513254552042023764 0ustar jpakkanejpakkane00000000000000project('ternary operator', 'c') one = true ? 1 : error('False branch should not be evaluated') two = false ? error('True branch should not be evaluated.') : 2 assert(one == 1, 'Return value from ternary true is wrong.') assert(two == 2, 'Return value from ternary false is wrong.') meson-0.45.1/test cases/common/44 has member/0000755000175000017500000000000013254552747022073 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/44 has member/meson.build0000644000175000017500000000140113254551713024221 0ustar jpakkanejpakkane00000000000000project('has member', 'c', 'cpp') compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] foreach cc : compilers if not cc.has_member('struct tm', 'tm_sec', prefix : '#include') error('Did not detect member of "struct tm" that exists: "tm_sec"') endif if cc.has_member('struct tm', 'tm_nonexistent', prefix : '#include') error('Not existing member "tm_nonexistent" found.') endif if not cc.has_members('struct tm', 'tm_sec', 'tm_min', prefix : '#include') error('Did not detect members of "struct tm" that exist: "tm_sec" "tm_min"') endif if cc.has_members('struct tm', 'tm_sec', 'tm_nonexistent2', prefix : '#include') error('Not existing member "tm_nonexistent2" found.') endif endforeach meson-0.45.1/test cases/common/185 ndebug if-release enabled/0000755000175000017500000000000013254552747024772 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/185 ndebug if-release enabled/main.c0000644000175000017500000000053013254550704026047 0ustar jpakkanejpakkane00000000000000#include #include int meson_test_side_effect = EXIT_FAILURE; int meson_test_set_side_effect(void) { meson_test_side_effect = EXIT_SUCCESS; return 1; } int main(void) { // meson_test_side_effect is set only if assert is executed assert(meson_test_set_side_effect()); return meson_test_side_effect; } meson-0.45.1/test cases/common/185 ndebug if-release enabled/meson.build0000644000175000017500000000046313254552142027124 0ustar jpakkanejpakkane00000000000000project('ndebug enabled', 'c', default_options : [ 'buildtype=debugoptimized', 'b_ndebug=if-release', ]) if meson.get_compiler('c').get_id() == 'msvc' error('MESON_SKIP_TEST b_ndebug is not supported on Visual Studio') endif test('exe', executable('main', 'main.c')) meson-0.45.1/test cases/common/37 has header/0000755000175000017500000000000013254552747022056 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/37 has header/meson.build0000644000175000017500000000417113254551677024224 0ustar jpakkanejpakkane00000000000000project('has header', 'c', 'cpp') host_system = host_machine.system() non_existant_header = 'ouagadougou.h' # Copy it into the builddir to ensure that it isn't found even if it's there configure_file(input : non_existant_header, output : non_existant_header, configuration : configuration_data()) # Test that the fallback to __has_include also works on all compilers if host_system != 'darwin' fallbacks = ['', '\n#undef __has_include'] else # On Darwin's clang you can't redefine builtin macros so the above doesn't work fallbacks = [''] endif foreach fallback : fallbacks foreach comp : [meson.get_compiler('c'), meson.get_compiler('cpp')] assert(comp.has_header('stdio.h', prefix : fallback), 'Stdio missing.') # stdio.h doesn't actually need stdlib.h, but just test that setting the # prefix does not result in an error. assert(comp.has_header('stdio.h', prefix : '#include ' + fallback), 'Stdio missing.') # XInput.h should not require type definitions from windows.h, but it does # require macro definitions. Specifically, it requires an arch setting for # VS2015 at least. # We only do this check on MSVC because MinGW often defines its own wrappers # that pre-include windows.h if comp.get_id() == 'msvc' assert(comp.has_header('XInput.h', prefix : '#include ' + fallback), 'XInput.h should not be missing on Windows') assert(comp.has_header('XInput.h', prefix : '#define _X86_' + fallback), 'XInput.h should not need windows.h') endif # Test that the following GCC bug doesn't happen: # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80005 # https://github.com/mesonbuild/meson/issues/1458 if host_system == 'linux' assert(comp.has_header('linux/if.h', prefix : fallback), 'Could not find ') endif # This header exists in the source and the builddir, but we still must not # find it since we are looking in the system directories. assert(not comp.has_header(non_existant_header, prefix : fallback), 'Found non-existant header.') endforeach endforeach meson-0.45.1/test cases/common/37 has header/ouagadougou.h0000644000175000017500000000004313062323030024515 0ustar jpakkanejpakkane00000000000000#define OMG_THIS_SHOULDNT_BE_FOUND meson-0.45.1/test cases/common/135 generated assembly/0000755000175000017500000000000013254552746023706 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/135 generated assembly/main.c0000644000175000017500000000046013074426732024771 0ustar jpakkanejpakkane00000000000000#include #if defined(_WIN32) || defined(__CYGWIN__) __declspec(dllimport) #endif unsigned square_unsigned (unsigned a); int main (int argc, char * argv[]) { unsigned int ret = square_unsigned (2); if (ret != 4) { printf("Got %u instead of 4\n", ret); return 1; } return 0; } meson-0.45.1/test cases/common/135 generated assembly/symbol-underscore.h0000644000175000017500000000017313043224360027514 0ustar jpakkanejpakkane00000000000000#if defined(MESON_TEST__UNDERSCORE_SYMBOL) # define SYMBOL_NAME(name) _##name #else # define SYMBOL_NAME(name) name #endif meson-0.45.1/test cases/common/135 generated assembly/square-x86.S.in0000644000175000017500000000102013243342167026343 0ustar jpakkanejpakkane00000000000000#include "symbol-underscore.h" #ifdef _MSC_VER .386 .MODEL FLAT, C PUBLIC square_unsigned _TEXT SEGMENT square_unsigned PROC var1:DWORD mov eax, var1 imul eax, eax ret square_unsigned ENDP _TEXT ENDS END #else .text .globl SYMBOL_NAME(square_unsigned) /* Only supported with GAS */ # if defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) .type square_unsigned,@function # endif SYMBOL_NAME(square_unsigned): movl 4(%esp), %eax imull %eax, %eax retl #endif meson-0.45.1/test cases/common/135 generated assembly/meson.build0000644000175000017500000000201013254552070026027 0ustar jpakkanejpakkane00000000000000project('generated assembly', 'c') cc = meson.get_compiler('c') if cc.get_id() == 'msvc' error('MESON_SKIP_TEST: assembly files cannot be compiled directly by MSVC') endif cpu = host_machine.cpu_family() supported_cpus = ['arm', 'x86', 'x86_64'] if not supported_cpus.contains(cpu) error('MESON_SKIP_TEST: unsupported cpu family: ' + cpu) endif if cc.symbols_have_underscore_prefix() add_project_arguments('-DMESON_TEST__UNDERSCORE_SYMBOL', language : 'c') endif copy = find_program('copyfile.py') output = 'square-@0@.S'.format(cpu) input = output + '.in' copygen = generator(copy, arguments : ['@INPUT@', '@OUTPUT@'], output : '@BASENAME@') l = shared_library('square-gen', copygen.process(input)) test('square-gen-test', executable('square-gen-test', 'main.c', link_with : l)) copyct = custom_target('square', input : input, output : output, command : [copy, '@INPUT@', '@OUTPUT@']) l = shared_library('square-ct', copyct) test('square-ct-test', executable('square-ct-test', 'main.c', link_with : l)) meson-0.45.1/test cases/common/135 generated assembly/copyfile.py0000644000175000017500000000013413057037314026056 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys import shutil shutil.copyfile(sys.argv[1], sys.argv[2]) meson-0.45.1/test cases/common/135 generated assembly/square-arm.S.in0000644000175000017500000000046713243342167026513 0ustar jpakkanejpakkane00000000000000#include "symbol-underscore.h" .text .globl SYMBOL_NAME(square_unsigned) /* Only supported with GAS */ # if defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) .type square_unsigned,%function #endif SYMBOL_NAME(square_unsigned): mul r1, r0, r0 mov r0, r1 mov pc, lr meson-0.45.1/test cases/common/135 generated assembly/square-x86_64.S.in0000644000175000017500000000130513243342167026662 0ustar jpakkanejpakkane00000000000000#include "symbol-underscore.h" #ifdef _MSC_VER /* MSVC on Windows */ PUBLIC SYMBOL_NAME(square_unsigned) _TEXT SEGMENT SYMBOL_NAME(square_unsigned) PROC mov eax, ecx imul eax, eax ret SYMBOL_NAME(square_unsigned) ENDP _TEXT ENDS END #else .text .globl SYMBOL_NAME(square_unsigned) /* Only supported with GAS */ # if defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) .type square_unsigned,@function # endif # if defined(_WIN32) || defined(__CYGWIN__) /* msabi */ SYMBOL_NAME(square_unsigned): imull %ecx, %ecx movl %ecx, %eax retq # else /* sysvabi */ SYMBOL_NAME(square_unsigned): imull %edi, %edi movl %edi, %eax retq # endif #endif meson-0.45.1/test cases/common/90 identical target name in subproject/0000755000175000017500000000000013254552750026717 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/90 identical target name in subproject/subprojects/0000755000175000017500000000000013254552745031266 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/90 identical target name in subproject/subprojects/foo/0000755000175000017500000000000013254552750032045 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/90 identical target name in subproject/subprojects/foo/meson.build0000644000175000017500000000013113243342167034177 0ustar jpakkanejpakkane00000000000000project('subfoo', 'c') executable('bar', 'bar.c') run_target('nop', command : ['true']) meson-0.45.1/test cases/common/90 identical target name in subproject/subprojects/foo/bar.c0000644000175000017500000000015412650745767032770 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("I'm a subproject bar.\n"); return 0; } meson-0.45.1/test cases/common/90 identical target name in subproject/meson.build0000644000175000017500000000016213254552010031045 0ustar jpakkanejpakkane00000000000000project('toplevel bar', 'c') subproject('foo') executable('bar', 'bar.c') run_target('nop', command : ['true']) meson-0.45.1/test cases/common/90 identical target name in subproject/bar.c0000644000175000017500000000015612650745767027644 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("I'm a main project bar.\n"); return 0; } meson-0.45.1/test cases/common/86 same basename/0000755000175000017500000000000013254552747022557 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/86 same basename/exe2.c0000644000175000017500000000012112650745767023565 0ustar jpakkanejpakkane00000000000000int func(); int main(int argc, char **argv) { return func() == 1 ? 0 : 1; } meson-0.45.1/test cases/common/86 same basename/lib.c0000644000175000017500000000067412650745767023505 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif #if defined SHAR int DLL_PUBLIC func() { return 1; } #elif defined STAT int func() { return 0; } #else #error "Missing type definition." #endif meson-0.45.1/test cases/common/86 same basename/meson.build0000644000175000017500000000060513254552005024705 0ustar jpakkanejpakkane00000000000000project('same basename', 'c') subdir('sharedsub') subdir('staticsub') # Use the same source file to check that each top level target # has its own unique working directory. If they don't # then the .o files will clobber each other. exe1 = executable('name', 'exe1.c', link_with : stlib) exe2 = executable('name2', 'exe2.c', link_with : shlib) test('static', exe1) test('shared', exe2) meson-0.45.1/test cases/common/86 same basename/exe1.c0000644000175000017500000000010412650745767023565 0ustar jpakkanejpakkane00000000000000int func(); int main(int argc, char **argv) { return func(); } meson-0.45.1/test cases/common/86 same basename/sharedsub/0000755000175000017500000000000013254552747024537 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/86 same basename/sharedsub/meson.build0000644000175000017500000000007612765341571026701 0ustar jpakkanejpakkane00000000000000shlib = shared_library('name', '../lib.c', c_args : '-DSHAR') meson-0.45.1/test cases/common/86 same basename/staticsub/0000755000175000017500000000000013254552747024560 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/86 same basename/staticsub/meson.build0000644000175000017500000000025612765341571026722 0ustar jpakkanejpakkane00000000000000# On Windows a static lib is now libfoo.a, so it does not conflict with foo.lib # from the shared library above stlib = static_library('name', '../lib.c', c_args : '-DSTAT') meson-0.45.1/test cases/common/38 run program/0000755000175000017500000000000013254552747022327 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/38 run program/meson.build0000644000175000017500000000203213254551676024466 0ustar jpakkanejpakkane00000000000000project('run command', 'c') if build_machine.system() == 'windows' c = run_command('cmd', '/c', 'echo', 'hello') else c = run_command('echo', 'hello') endif correct = 'hello' if c.returncode() != 0 error('Executing echo failed.') endif result = c.stdout().strip() if result != correct error('Getting stdout failed.') endif if c.stderr() != '' error('Extra text in stderr.') endif # Now the same with a script. if build_machine.system() == 'windows' cs = run_command('scripts/hello.bat') else cs = run_command('scripts/hello.sh') endif if cs.returncode() != 0 error('Executing script failed.') endif if cs.stdout().strip() != correct error('Getting stdout failed (script).') endif if cs.stderr() != '' error('Extra text in stderr (script).') endif # We should be able to have files() in argument f = files('meson.build') if build_machine.system() == 'windows' c = run_command('cmd', '/c', 'echo', f) else c = run_command('echo', f) endif if c.returncode() != 0 error('Using files() in argument failed.') endif meson-0.45.1/test cases/common/38 run program/scripts/0000755000175000017500000000000013254552747024016 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/38 run program/scripts/hello.bat0000644000175000017500000000002512650745767025613 0ustar jpakkanejpakkane00000000000000@ECHO OFF ECHO hello meson-0.45.1/test cases/common/38 run program/scripts/hello.sh0000755000175000017500000000002612650745767025463 0ustar jpakkanejpakkane00000000000000#!/bin/sh echo hello meson-0.45.1/test cases/common/177 subproject nested subproject dirs/0000755000175000017500000000000013254552747026665 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/0000755000175000017500000000000013254552745030323 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/0000755000175000017500000000000013254552745032666 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/beta/0000755000175000017500000000000013254552747033603 5ustar jpakkanejpakkane00000000000000././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000meson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/beta/meson.buildmeson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/beta/meson.0000644000175000017500000000007613242407024034710 0ustar jpakkanejpakkane00000000000000project('beta project', 'c') lb = shared_library('b', 'b.c') meson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/beta/b.c0000644000175000017500000000051713242407024034153 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif int DLL_PUBLIC func2() { return 42; } meson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/0000755000175000017500000000000013254552747033755 5ustar jpakkanejpakkane00000000000000././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000meson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/meson.buildmeson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/meson0000644000175000017500000000023213242407024034776 0ustar jpakkanejpakkane00000000000000project('alpha project', 'c', subproject_dir: 'var/subprojects') b = subproject('beta') l = shared_library('a', 'a.c', link_with : b.get_variable('lb')) meson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/a.c0000644000175000017500000000053613242407024034325 0ustar jpakkanejpakkane00000000000000int func2(); #if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif int DLL_PUBLIC func() { return func2(); } meson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/var/0000755000175000017500000000000013254552745034543 5ustar jpakkanejpakkane00000000000000././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000meson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/meson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/var/s0000755000175000017500000000000013254552747034730 5ustar jpakkanejpakkane00000000000000././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000meson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_heremeson-0.45.1/test cases/common/177 subproject nested subproject dirs/contrib/subprojects/alpha/var/s0000644000175000017500000000000213242407024034702 0ustar jpakkanejpakkane00000000000000 meson-0.45.1/test cases/common/177 subproject nested subproject dirs/meson.build0000644000175000017500000000030013254552140031003 0ustar jpakkanejpakkane00000000000000project('gamma project', 'c', subproject_dir: 'contrib/subprojects') a = subproject('alpha') lib = a.get_variable('l') exe = executable('prog', 'prog.c', link_with : lib) test('basic', exe) meson-0.45.1/test cases/common/177 subproject nested subproject dirs/prog.c0000644000175000017500000000012213242407024027753 0ustar jpakkanejpakkane00000000000000int func(); int main(int argc, char **argv) { return func() == 42 ? 0 : 1; } meson-0.45.1/test cases/common/134 generated llvm ir/0000755000175000017500000000000013254552746023433 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/134 generated llvm ir/main.c0000644000175000017500000000034713043224360024507 0ustar jpakkanejpakkane00000000000000#include unsigned square_unsigned (unsigned a); int main (int argc, char * argv[]) { unsigned int ret = square_unsigned (2); if (ret != 4) { printf("Got %u instead of 4\n", ret); return 1; } return 0; } meson-0.45.1/test cases/common/134 generated llvm ir/meson.build0000644000175000017500000000125113046167604025566 0ustar jpakkanejpakkane00000000000000project('generated llvm ir', 'c') if meson.get_compiler('c').get_id() != 'clang' error('MESON_SKIP_TEST: LLVM IR files can only be built with clang') endif copy = find_program('copyfile.py') copygen = generator(copy, arguments : ['@INPUT@', '@OUTPUT@'], output : '@BASENAME@') l = shared_library('square-gen', copygen.process('square.ll.in')) test('square-gen-test', executable('square-gen-test', 'main.c', link_with : l)) copyct = custom_target('square', input : 'square.ll.in', output : 'square.ll', command : [copy, '@INPUT@', '@OUTPUT@']) l = shared_library('square-ct', copyct) test('square-ct-test', executable('square-ct-test', 'main.c', link_with : l)) meson-0.45.1/test cases/common/134 generated llvm ir/copyfile.py0000644000175000017500000000013413057037314025603 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys import shutil shutil.copyfile(sys.argv[1], sys.argv[2]) meson-0.45.1/test cases/common/134 generated llvm ir/square.ll.in0000644000175000017500000000011313043224360025644 0ustar jpakkanejpakkane00000000000000define i32 @square_unsigned(i32 %a) { %1 = mul i32 %a, %a ret i32 %1 } meson-0.45.1/test cases/common/103 manygen/0000755000175000017500000000000013254552746021601 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/103 manygen/depuser.c0000644000175000017500000000037412650745767023426 0ustar jpakkanejpakkane00000000000000#include"gen_func.h" int main(int argc, char **argv) { unsigned int i = (unsigned int) gen_func_in_lib(); unsigned int j = (unsigned int) gen_func_in_obj(); unsigned int k = (unsigned int) gen_func_in_src(); return (int)(i + j + k); } meson-0.45.1/test cases/common/103 manygen/meson.build0000644000175000017500000000046013254552024023730 0ustar jpakkanejpakkane00000000000000project('manygen', 'c') if meson.is_cross_build() # FIXME error out with skip message once cross test runner # recognizes it. message('Not running this test during cross build.') else subdir('subdir') exe = executable('depuser', 'depuser.c', generated) test('depuser test', exe) endif meson-0.45.1/test cases/common/103 manygen/subdir/0000755000175000017500000000000013254552746023071 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/103 manygen/subdir/funcinfo.def0000644000175000017500000000001112650745767025356 0ustar jpakkanejpakkane00000000000000gen_func meson-0.45.1/test cases/common/103 manygen/subdir/meson.build0000644000175000017500000000153213043224360025214 0ustar jpakkanejpakkane00000000000000gen = files('manygen.py') py3_bin = import('python3').find_python() buildtype = get_option('buildtype') buildtype_args = '-Dfooxxx' # a useless compiler argument if meson.get_compiler('c').get_id() == 'msvc' # We need our manually generated code to use the same CRT as the executable. # Taken from compilers.py since build files do not have access to this. if buildtype == 'debug' buildtype_args = '/MDd' elif buildtype == 'debugoptimized' buildtype_args = '/MDd' elif buildtype == 'release' buildtype_args = '/MD' endif outfiles = ['gen_func.lib', 'gen_func.c', 'gen_func.h', 'gen_func.o'] else outfiles = ['gen_func.a', 'gen_func.c', 'gen_func.h', 'gen_func.o'] endif generated = custom_target('manygen', output : outfiles, input : ['funcinfo.def'], command : [py3_bin, gen[0], '@INPUT@', '@OUTDIR@', buildtype_args], ) meson-0.45.1/test cases/common/103 manygen/subdir/manygen.py0000755000175000017500000000412113043224360025062 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python from __future__ import print_function # Generates a static library, object file, source # file and a header file. import sys, os import shutil, subprocess with open(sys.argv[1]) as f: funcname = f.readline().strip() outdir = sys.argv[2] buildtype_args = sys.argv[3] if not os.path.isdir(outdir): print('Outdir does not exist.') sys.exit(1) # Emulate the environment.detect_c_compiler() logic compiler = os.environ.get('CC', None) if not compiler: compiler = shutil.which('cl') or \ shutil.which('gcc') or \ shutil.which('clang') or \ shutil.which('cc') compbase = os.path.basename(compiler) if 'cl' in compbase and 'clang' not in compbase: libsuffix = '.lib' is_vs = True compiler = 'cl' linker = 'lib' else: libsuffix = '.a' is_vs = False linker = 'ar' if compiler is None: print('No known compilers found.') sys.exit(1) objsuffix = '.o' outo = os.path.join(outdir, funcname + objsuffix) outa = os.path.join(outdir, funcname + libsuffix) outh = os.path.join(outdir, funcname + '.h') outc = os.path.join(outdir, funcname + '.c') tmpc = 'diibadaaba.c' tmpo = 'diibadaaba' + objsuffix with open(outc, 'w') as f: f.write('''#include"%s.h" int %s_in_src() { return 0; } ''' % (funcname, funcname)) with open(outh, 'w') as f: f.write('''#pragma once int %s_in_lib(); int %s_in_obj(); int %s_in_src(); ''' % (funcname, funcname, funcname)) with open(tmpc, 'w') as f: f.write('''int %s_in_obj() { return 0; } ''' % funcname) if is_vs: subprocess.check_call([compiler, '/nologo', '/c', buildtype_args, '/Fo' + outo, tmpc]) else: subprocess.check_call([compiler, '-c', '-o', outo, tmpc]) with open(tmpc, 'w') as f: f.write('''int %s_in_lib() { return 0; } ''' % funcname) if is_vs: subprocess.check_call([compiler, '/nologo', '/c', '/Fo' + tmpo, tmpc]) subprocess.check_call([linker, '/NOLOGO', '/OUT:' + outa, tmpo]) else: subprocess.check_call([compiler, '-c', '-o', tmpo, tmpc]) subprocess.check_call([linker, 'csr', outa, tmpo]) os.unlink(tmpo) os.unlink(tmpc) meson-0.45.1/test cases/common/161 index customtarget/0000755000175000017500000000000013254552746023760 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/161 index customtarget/lib.c0000644000175000017500000000124313174155420024657 0ustar jpakkanejpakkane00000000000000/* Copyright Ā© 2017 Intel Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * 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. */ #include "gen.h" void func(char * buffer) { stringify(1, buffer); } meson-0.45.1/test cases/common/161 index customtarget/meson.build0000644000175000017500000000171613254552122026113 0ustar jpakkanejpakkane00000000000000# Copyright Ā© 2017 Intel Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. project('custom_target_index', 'c', default_options : 'c_std=c89') py_mod = import('python3') prog_python = py_mod.find_python() gen = custom_target( 'gen.[ch]', input : 'gen_sources.py', output : ['gen.c', 'gen.h'], command : [prog_python, '@INPUT@', '--header', '@OUTPUT1@', '--code', '@OUTPUT0@'], ) lib = static_library( 'libfoo', ['lib.c', gen[1]], ) subdir('subdir') meson-0.45.1/test cases/common/161 index customtarget/subdir/0000755000175000017500000000000013254552746025250 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/161 index customtarget/subdir/foo.c0000644000175000017500000000126713174155420026172 0ustar jpakkanejpakkane00000000000000/* Copyright Ā© 2017 Intel Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * 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. */ #include "gen.h" int main(void) { char buf[50]; stringify(10, buf); return 0; } meson-0.45.1/test cases/common/161 index customtarget/subdir/meson.build0000644000175000017500000000123113174155420027374 0ustar jpakkanejpakkane00000000000000# Copyright Ā© 2017 Intel Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. foo = executable( 'foo', ['foo.c', gen[0], gen[1]], c_args : '-DWORKS', ) meson-0.45.1/test cases/common/161 index customtarget/gen_sources.py0000644000175000017500000000233413174155420026635 0ustar jpakkanejpakkane00000000000000# Copyright Ā© 2017 Intel Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. import argparse import textwrap HEADER = textwrap.dedent('''\ void stringify(int foo, char * buffer); ''') CODE = textwrap.dedent('''\ #include #ifndef WORKS # error "This shouldn't have been included" #endif void stringify(int foo, char * buffer) { sprintf(buffer, "%i", foo); } ''') def main(): parser = argparse.ArgumentParser() parser.add_argument('--header') parser.add_argument('--code') args = parser.parse_args() with open(args.header, 'w') as f: f.write(HEADER) with open(args.code, 'w') as f: f.write(CODE) if __name__ == '__main__': main() meson-0.45.1/test cases/common/160 duplicate source names/0000755000175000017500000000000013254552746024465 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/160 duplicate source names/meson.build0000644000175000017500000000023413254552121026611 0ustar jpakkanejpakkane00000000000000project('proj', 'c') sources = [] subdir('dir1') subdir('dir2') subdir('dir3') executable('a.out', sources : sources, objects : lib.extract_all_objects()) meson-0.45.1/test cases/common/160 duplicate source names/dir2/0000755000175000017500000000000013254552746025325 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/160 duplicate source names/dir2/meson.build0000644000175000017500000000005213174155420027451 0ustar jpakkanejpakkane00000000000000sources += files('file.c', 'dir1/file.c') meson-0.45.1/test cases/common/160 duplicate source names/dir2/file.c0000644000175000017500000000001713174155420026373 0ustar jpakkanejpakkane00000000000000int dir2 = 20; meson-0.45.1/test cases/common/160 duplicate source names/dir2/dir1/0000755000175000017500000000000013254552746026164 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/160 duplicate source names/dir2/dir1/file.c0000644000175000017500000000002413174155420027230 0ustar jpakkanejpakkane00000000000000int dir2_dir1 = 21; meson-0.45.1/test cases/common/160 duplicate source names/dir3/0000755000175000017500000000000013254552746025326 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/160 duplicate source names/dir3/meson.build0000644000175000017500000000006513174155420027456 0ustar jpakkanejpakkane00000000000000lib = static_library('lib', 'file.c', 'dir1/file.c') meson-0.45.1/test cases/common/160 duplicate source names/dir3/file.c0000644000175000017500000000001713174155420026374 0ustar jpakkanejpakkane00000000000000int dir3 = 30; meson-0.45.1/test cases/common/160 duplicate source names/dir3/dir1/0000755000175000017500000000000013254552746026165 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/160 duplicate source names/dir3/dir1/file.c0000644000175000017500000000002413174155420027231 0ustar jpakkanejpakkane00000000000000int dir3_dir1 = 31; meson-0.45.1/test cases/common/160 duplicate source names/dir1/0000755000175000017500000000000013254552746025324 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/160 duplicate source names/dir1/meson.build0000644000175000017500000000003313174155420027447 0ustar jpakkanejpakkane00000000000000sources += files('file.c') meson-0.45.1/test cases/common/160 duplicate source names/dir1/file.c0000644000175000017500000000041613174155420026375 0ustar jpakkanejpakkane00000000000000extern int dir2; extern int dir2_dir1; extern int dir3; extern int dir3_dir1; int main() { if (dir2 != 20) return 1; if (dir2_dir1 != 21) return 1; if (dir3 != 30) return 1; if (dir3_dir1 != 31) return 1; return 0; } meson-0.45.1/test cases/common/3 static/0000755000175000017500000000000013254552747021272 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/3 static/meson.build0000644000175000017500000000025313254551630023422 0ustar jpakkanejpakkane00000000000000project('static library test', 'c') lib = static_library('mylib', get_option('source'), link_args : '-THISMUSTNOBEUSED') # Static linker needs to ignore all link args. meson-0.45.1/test cases/common/3 static/libfile.c0000644000175000017500000000004012650745767023043 0ustar jpakkanejpakkane00000000000000int libfunc() { return 3; } meson-0.45.1/test cases/common/3 static/meson_options.txt0000644000175000017500000000013513055371450024713 0ustar jpakkanejpakkane00000000000000option('source', type : 'combo', choices : ['libfile.c', 'libfile2.c'], value : 'libfile.c') meson-0.45.1/test cases/common/3 static/libfile2.c0000644000175000017500000000004113055371450023106 0ustar jpakkanejpakkane00000000000000int libfunc2() { return 4; } meson-0.45.1/test cases/common/151 list of file sources/0000755000175000017500000000000013254552746024052 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/151 list of file sources/gen.py0000644000175000017500000000025613105362433025163 0ustar jpakkanejpakkane00000000000000import shutil import sys if __name__ == '__main__': if len(sys.argv) != 3: raise Exception('Requires exactly 2 args') shutil.copy2(sys.argv[1], sys.argv[2]) meson-0.45.1/test cases/common/151 list of file sources/meson.build0000644000175000017500000000042213254552111026174 0ustar jpakkanejpakkane00000000000000project('test', 'c') mod_py = import('python3') python = mod_py.find_python() test_target = custom_target( 'test_target', input : [files('gen.py'), files('foo')], output : 'bar', command : [python, '@INPUT0@', '@INPUT1@', '@OUTPUT@'], build_by_default : true, ) meson-0.45.1/test cases/common/151 list of file sources/foo0000644000175000017500000000001213105362433024534 0ustar jpakkanejpakkane00000000000000some text meson-0.45.1/test cases/common/171 not-found dependency/0000755000175000017500000000000013254552747024161 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/171 not-found dependency/meson.build0000644000175000017500000000047413254552133026315 0ustar jpakkanejpakkane00000000000000project('dep-test', 'c') dep = dependency('', required:false) if dep.found() error('not-found dependency was found') endif assert(dep.type_name() == 'not-found', 'dependency should be of type "not-found" not ' + dep.type_name()) library('testlib', 'testlib.c', dependencies: [dep]) subdir('sub', if_found: dep) meson-0.45.1/test cases/common/171 not-found dependency/testlib.c0000644000175000017500000000000013224470574025753 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/171 not-found dependency/sub/0000755000175000017500000000000013254552747024752 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/171 not-found dependency/sub/meson.build0000644000175000017500000000006113224470574027103 0ustar jpakkanejpakkane00000000000000error('should be disabled by subdir(if_found:)') meson-0.45.1/test cases/common/14 cpp pch/0000755000175000017500000000000013254552746021401 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/14 cpp pch/pch/0000755000175000017500000000000013254552746022153 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/14 cpp pch/pch/prog.hh0000644000175000017500000000002312650745767023444 0ustar jpakkanejpakkane00000000000000#include meson-0.45.1/test cases/common/14 cpp pch/pch/prog_pch.cc0000644000175000017500000000014012650745767024264 0ustar jpakkanejpakkane00000000000000#if !defined(_MSC_VER) #error "This file is only for use with MSVC." #endif #include "prog.hh" meson-0.45.1/test cases/common/14 cpp pch/meson.build0000644000175000017500000000016113254551646023537 0ustar jpakkanejpakkane00000000000000project('c++ pch test', 'cpp') exe = executable('prog', 'prog.cc', cpp_pch : ['pch/prog.hh', 'pch/prog_pch.cc']) meson-0.45.1/test cases/common/14 cpp pch/prog.cc0000644000175000017500000000027012650745767022664 0ustar jpakkanejpakkane00000000000000void func() { std::cout << "This is a function that fails to compile if iostream is not included." << std::endl; } int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/124 test skip/0000755000175000017500000000000013254552746022054 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/124 test skip/test_skip.c0000644000175000017500000000006113020525005024175 0ustar jpakkanejpakkane00000000000000int main(int argc, char *argv[]) { return 77; } meson-0.45.1/test cases/common/124 test skip/meson.build0000644000175000017500000000016313254552053024205 0ustar jpakkanejpakkane00000000000000project('test skip', 'c') exe_test_skip = executable('test_skip', 'test_skip.c') test('test_skip', exe_test_skip) meson-0.45.1/test cases/common/84 extract from nested subdir/0000755000175000017500000000000013254552747025206 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/84 extract from nested subdir/meson.build0000644000175000017500000000024313254552002027327 0ustar jpakkanejpakkane00000000000000project('Extract objects from subdirs.', 'c') if meson.is_unity() message('Unity build: skipping incompatible test') else subdir('src') subdir('tst') endif meson-0.45.1/test cases/common/84 extract from nested subdir/tst/0000755000175000017500000000000013254552747026020 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/84 extract from nested subdir/tst/first/0000755000175000017500000000000013254552747027147 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/84 extract from nested subdir/tst/first/meson.build0000644000175000017500000000021012650745767031307 0ustar jpakkanejpakkane00000000000000first_exe = executable('first_exe', 'exe_first.c', objects : first_lib.extract_objects('lib_first.c')) test('first_test', first_exe) meson-0.45.1/test cases/common/84 extract from nested subdir/tst/first/exe_first.c0000644000175000017500000000007112650745767031306 0ustar jpakkanejpakkane00000000000000int first(void); int main() { return first() - 1001; } meson-0.45.1/test cases/common/84 extract from nested subdir/tst/meson.build0000644000175000017500000000002012650745767030157 0ustar jpakkanejpakkane00000000000000subdir('first') meson-0.45.1/test cases/common/84 extract from nested subdir/src/0000755000175000017500000000000013254552747025775 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/84 extract from nested subdir/src/first/0000755000175000017500000000000013254552747027124 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/84 extract from nested subdir/src/first/meson.build0000644000175000017500000000006712650745767031276 0ustar jpakkanejpakkane00000000000000first_lib = shared_library('first_lib', 'lib_first.c') meson-0.45.1/test cases/common/84 extract from nested subdir/src/first/lib_first.c0000644000175000017500000000003612650745767031251 0ustar jpakkanejpakkane00000000000000int first() { return 1001; } meson-0.45.1/test cases/common/84 extract from nested subdir/src/meson.build0000644000175000017500000000002012650745767030134 0ustar jpakkanejpakkane00000000000000subdir('first') meson-0.45.1/test cases/common/94 default options/0000755000175000017500000000000013254552750023167 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/94 default options/meson.build0000644000175000017500000000241613254552013025324 0ustar jpakkanejpakkane00000000000000project('default options', 'cpp', 'c', default_options : [ 'prefix=/absoluteprefix', 'buildtype=debugoptimized', 'cpp_std=c++11', 'cpp_eh=none', 'warning_level=3', ]) cpp_id = meson.get_compiler('cpp').get_id() assert(get_option('buildtype') == 'debugoptimized', 'Build type default value wrong.') if cpp_id == 'msvc' cpp_eh = get_option('cpp_eh') assert(cpp_eh == 'none', 'MSVC eh value is "' + cpp_eh + '" instead of "none"') else cpp_std = get_option('cpp_std') assert(cpp_std == 'c++11', 'C++ std value is "' + cpp_std + '" instead of c++11.') endif w_level = get_option('warning_level') assert(w_level == '3', 'warning level "' + w_level + '" instead of "3"') # FIXME. Since we no longer accept invalid options to c_std etc, # there is no simple way to test this. Gcc does not seem to expose # the C std used in a preprocessor token so we can't check for it. # Think of a way to fix this. # # # Verify that project args are not used when told not to. # # MSVC plain C does not have a simple arg to test so skip it. # if cpp.get_id() != 'msvc' # cc = meson.get_compiler('c') # assert(not cc.compiles('int foobar;'), 'Default arg not used in test.') # assert(cc.compiles('int foobar;', no_builtin_args : true), 'No_builtin did not disable builtins.') # endif meson-0.45.1/test cases/common/100 test workdir/0000755000175000017500000000000013254552746022561 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/100 test workdir/meson.build0000644000175000017500000000024413254552021024705 0ustar jpakkanejpakkane00000000000000project('test workdir', 'c') exe = executable('opener', 'opener.c') test('basic', exe, workdir : meson.source_root()) test('shouldfail', exe, should_fail : true) meson-0.45.1/test cases/common/100 test workdir/opener.c0000644000175000017500000000033412650745767024223 0ustar jpakkanejpakkane00000000000000// This test only succeeds if run in the source root dir. #include int main(int arg, char **argv) { FILE *f = fopen("opener.c", "r"); if(f) { fclose(f); return 0; } return 1; } meson-0.45.1/test cases/common/47 options/0000755000175000017500000000000013254552747021566 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/47 options/meson.build0000644000175000017500000000135513254551722023724 0ustar jpakkanejpakkane00000000000000project('options', 'c') if get_option('testoption') != 'optval' error('Incorrect value to test option') endif if get_option('other_one') != false error('Incorrect value to boolean option.') endif if get_option('combo_opt') != 'combo' error('Incorrect value to combo option.') endif if get_option('array_opt') != ['one', 'two'] message(get_option('array_opt')) error('Incorrect value for array option') endif # If the default changes, update test cases/unit/13 reconfigure if get_option('b_lto') != false error('Incorrect value in base option.') endif if get_option('includedir') != 'include' error('Incorrect value in builtin option.') endif if get_option('integer_opt') != 3 error('Incorrect value in integer option.') endif meson-0.45.1/test cases/common/47 options/meson_options.txt0000644000175000017500000000067513243342167025222 0ustar jpakkanejpakkane00000000000000option('testoption', type : 'string', value : 'optval', description : 'An option to do something') option('other_one', type : 'boolean', value : false) option('combo_opt', type : 'combo', choices : ['one', 'two', 'combo'], value : 'combo') option('array_opt', type : 'array', choices : ['one', 'two', 'three'], value : ['one', 'two']) option('free_array_opt', type : 'array') option('integer_opt', type : 'integer', min : 0, max : 5, value : 3) meson-0.45.1/test cases/common/120 subdir subproject/0000755000175000017500000000000013254552746023573 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/120 subdir subproject/subprojects/0000755000175000017500000000000013254552745026135 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/120 subdir subproject/subprojects/sub/0000755000175000017500000000000013254552746026727 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/120 subdir subproject/subprojects/sub/sub.c0000644000175000017500000000005313012152443027640 0ustar jpakkanejpakkane00000000000000#include "sub.h" int sub() { return 0; } meson-0.45.1/test cases/common/120 subdir subproject/subprojects/sub/meson.build0000644000175000017500000000022413012152443031045 0ustar jpakkanejpakkane00000000000000project('sub', 'c') lib = static_library('sub', 'sub.c') libSub = declare_dependency(include_directories: include_directories('.'), link_with: lib) meson-0.45.1/test cases/common/120 subdir subproject/subprojects/sub/sub.h0000644000175000017500000000006013012152443027643 0ustar jpakkanejpakkane00000000000000#ifndef SUB_H #define SUB_H int sub(); #endif meson-0.45.1/test cases/common/120 subdir subproject/meson.build0000644000175000017500000000004413254552046025724 0ustar jpakkanejpakkane00000000000000project('proj', 'c') subdir('prog') meson-0.45.1/test cases/common/120 subdir subproject/prog/0000755000175000017500000000000013254552746024542 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/120 subdir subproject/prog/meson.build0000644000175000017500000000024313012152443026661 0ustar jpakkanejpakkane00000000000000subproject('sub') libSub = dependency('sub', fallback: ['sub', 'libSub']) exe = executable('prog', 'prog.c', dependencies: libSub) test('subdir subproject', exe) meson-0.45.1/test cases/common/120 subdir subproject/prog/prog.c0000644000175000017500000000006013012152443025627 0ustar jpakkanejpakkane00000000000000#include int main() { return sub(); } meson-0.45.1/test cases/common/127 cpp and asm/0000755000175000017500000000000013254552746022217 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/127 cpp and asm/symbol-underscore.h0000644000175000017500000000017313070746245026040 0ustar jpakkanejpakkane00000000000000#if defined(MESON_TEST__UNDERSCORE_SYMBOL) # define SYMBOL_NAME(name) _##name #else # define SYMBOL_NAME(name) name #endif meson-0.45.1/test cases/common/127 cpp and asm/trivial.cc0000644000175000017500000000043413024065327024166 0ustar jpakkanejpakkane00000000000000#include extern "C" { int get_retval(void); } int main(int argc, char **argv) { std::cout << "C++ seems to be working." << std::endl; #if defined(USE_ASM) return get_retval(); #elif defined(NO_USE_ASM) return 0; #else #error "Forgot to pass asm define" #endif } meson-0.45.1/test cases/common/127 cpp and asm/meson.build0000644000175000017500000000130613254552060024346 0ustar jpakkanejpakkane00000000000000project('c++ and assembly test', 'cpp') cpp = meson.get_compiler('cpp') cpu = host_machine.cpu_family() supported_cpus = ['arm', 'x86', 'x86_64'] if not supported_cpus.contains(cpu) error('MESON_SKIP_TEST unsupported cpu:' + cpu) endif if cpp.symbols_have_underscore_prefix() add_project_arguments('-DMESON_TEST__UNDERSCORE_SYMBOL', language : 'cpp') endif sources = ['trivial.cc'] # If the compiler cannot compile assembly, don't use it if meson.get_compiler('cpp').get_id() != 'msvc' sources += ['retval-' + cpu + '.S'] cpp_args = ['-DUSE_ASM'] message('Using ASM') else cpp_args = ['-DNO_USE_ASM'] endif exe = executable('trivialprog', sources, cpp_args : cpp_args) test('runtest', exe) meson-0.45.1/test cases/common/127 cpp and asm/retval-x86_64.S0000644000175000017500000000026113123035221024546 0ustar jpakkanejpakkane00000000000000#include "symbol-underscore.h" .text .globl SYMBOL_NAME(get_retval) # ifdef __linux__ .type get_retval, %function #endif SYMBOL_NAME(get_retval): xorl %eax, %eax retq meson-0.45.1/test cases/common/127 cpp and asm/retval-arm.S0000644000175000017500000000026213123035221024370 0ustar jpakkanejpakkane00000000000000#include "symbol-underscore.h" .text .globl SYMBOL_NAME(get_retval) # ifdef __linux__ .type get_retval, %function #endif SYMBOL_NAME(get_retval): mov r0, #0 mov pc, lr meson-0.45.1/test cases/common/127 cpp and asm/retval-x86.S0000644000175000017500000000026113123035221024235 0ustar jpakkanejpakkane00000000000000#include "symbol-underscore.h" .text .globl SYMBOL_NAME(get_retval) # ifdef __linux__ .type get_retval, %function #endif SYMBOL_NAME(get_retval): xorl %eax, %eax retl meson-0.45.1/test cases/common/19 comparison/0000755000175000017500000000000013254552747022244 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/19 comparison/meson.build0000644000175000017500000000511713254551655024407 0ustar jpakkanejpakkane00000000000000project('comparison', 'c') # Compare equality of strings var1 = 'foo' var2 = 'bar' if var1 == var2 exe1 = executable('broken', 'broken.c') else exe1 = executable('prog1', 'prog.c') endif if var1 == var1 exe2 = executable('prog2', 'prog.c') else exe2 = executable('broken', 'broken.c') endif if var1 != var2 exe3 = executable('prog3', 'prog.c') else exe3 = executable('broken', 'broken.c') endif if var1 != var1 exe4 = executable('broken', 'broken.c') else exe4 = executable('prog4', 'prog.c') endif test('equalfalse', exe1) test('equaltrue', exe2) test('nequaltrue', exe3) test('nequalfalse', exe4) # Non-equality comparisons var3 = 3 var4 = 4 if var3 < var4 exe5 = executable('prog5', 'prog.c') else exe5 = executable('broken', 'broken.c') endif if var3 < var3 exe6 = executable('broken', 'broken.c') else exe6 = executable('prog6', 'prog.c') endif if var4 > var3 exe7 = executable('prog7', 'prog.c') else exe7 = executable('broken', 'broken.c') endif if var3 > var3 exe8 = executable('broken', 'broken.c') else exe8 = executable('prog8', 'prog.c') endif if var4 <= var3 exe9 = executable('broken', 'broken.c') else exe9 = executable('prog9', 'prog.c') endif if var3 <= var3 exe10 = executable('prog10', 'prog.c') else exe10 = executable('broken', 'broken.c') endif if var3 >= var4 exe11 = executable('broken', 'broken.c') else exe11 = executable('prog11', 'prog.c') endif if var3 >= var3 exe12 = executable('prog12', 'prog.c') else exe12 = executable('broken', 'broken.c') endif test('lttrue', exe5) test('ltfalse', exe6) test('gttrue', exe7) test('gtfalse', exe8) test('lefalse', exe9) test('letrue', exe10) test('gefalse', exe11) test('getrue', exe12) # Non-elementary type comparisons if exe1 == exe2 exe13 = executable('broken', 'broken.c') else exe13 = executable('prog13', 'prog.c') endif if exe1 == exe1 exe14 = executable('prog14', 'prog.c') else exe14 = executable('broken', 'broken.c') endif if exe1 != exe2 exe15 = executable('prog15', 'prog.c') else exe15 = executable('broken', 'broken.c') endif if exe1 != exe1 exe16 = executable('broken', 'broken.c') else exe16 = executable('prog16', 'prog.c') endif test('equalfalse', exe13) test('equaltrue', exe14) test('nequaltrue', exe15) test('nequalfalse', exe16) # Equality comparisons of different elementary types # (these all cause warnings currently, will become an error in future) assert([] != 'st', 'not equal') assert([] != 1, 'not equal') assert(2 != 'st', 'not equal') assert(not ([] == 'st'), 'not equal') assert(not ([] == 1), 'not equal') assert(not (2 == 'st'), 'not equal') meson-0.45.1/test cases/common/19 comparison/prog.c0000644000175000017500000000005612650745767023365 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/149 special characters/0000755000175000017500000000000013254552746023675 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/149 special characters/installed_files.txt0000644000175000017500000000004313103323022027544 0ustar jpakkanejpakkane00000000000000usr/share/result usr/share/result2 meson-0.45.1/test cases/common/149 special characters/check_quoting.py0000644000175000017500000000106213103323022027041 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys expected = { 'newline': '\n', 'dollar': '$', 'colon': ':', 'space': ' ', 'multi1': ' ::$$ ::$$', 'multi2': ' ::$$\n\n \n\n::$$', } output = None for arg in sys.argv[1:]: try: name, value = arg.split('=', 1) except ValueError: output = arg continue if expected[name] != value: raise RuntimeError('{!r} is {!r} but should be {!r}'.format(name, value, expected[name])) if output is not None: with open(output, 'w') as f: f.write('Success!') meson-0.45.1/test cases/common/149 special characters/meson.build0000644000175000017500000000135213254552107026027 0ustar jpakkanejpakkane00000000000000project('ninja special characters' ,'c') python = import('python3').find_python() # Without newlines, this should appear directly in build.ninja. gen = custom_target('gen', command : [ python, files('check_quoting.py'), 'dollar=$', 'colon=:', 'space= ', '''multi1= ::$$ ::$$''', '@OUTPUT@'], output : 'result', install : true, install_dir : get_option('datadir')) # With newlines, this should go through the exe wrapper. gen2 = custom_target('gen2', command : [ python, files('check_quoting.py'), '''newline= ''', 'dollar=$', 'colon=:', 'space= ', '''multi2= ::$$ ::$$''', '@OUTPUT@'], output : 'result2', install : true, install_dir : get_option('datadir')) meson-0.45.1/test cases/common/66 install subdir/0000755000175000017500000000000013254552747023013 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/installed_files.txt0000644000175000017500000000050413243342167026703 0ustar jpakkanejpakkane00000000000000usr/share/dircheck/fifth.dat usr/share/dircheck/seventh.dat usr/share/dircheck/nineth.dat usr/share/eighth.dat usr/share/fourth.dat usr/share/sixth.dat usr/share/sub1/data1.dat usr/share/sub1/second.dat usr/share/sub1/third.dat usr/share/sub1/sub2/data2.dat usr/share/sub2/one.dat usr/share/sub2/dircheck/excluded-three.dat meson-0.45.1/test cases/common/66 install subdir/sub_elided/0000755000175000017500000000000013254552747025112 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/sub_elided/fourth.dat0000644000175000017500000000007413243342167027103 0ustar jpakkanejpakkane00000000000000Test that this file is installed directly into install_dir. meson-0.45.1/test cases/common/66 install subdir/sub_elided/dircheck/0000755000175000017500000000000013254552747026666 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/sub_elided/dircheck/fifth.dat0000644000175000017500000000005313243342167030445 0ustar jpakkanejpakkane00000000000000Data file in a subdir of elided directory. meson-0.45.1/test cases/common/66 install subdir/meson.build0000644000175000017500000000115113254551757025153 0ustar jpakkanejpakkane00000000000000project('install a whole subdir', 'c') # A subdir with an exclusion: install_subdir('sub2', exclude_files : ['excluded-three.dat'], exclude_directories : ['excluded'], install_dir : 'share') subdir('subdir') # A subdir with write perms only for the owner # and read-list perms for owner and group install_subdir('sub1', install_dir : 'share', install_mode : ['rwxr-x--t', 'root']) install_subdir('sub/sub1', install_dir : 'share') # strip_directory install_subdir('sub_elided', install_dir : 'share', strip_directory : true) install_subdir('nested_elided/sub', install_dir : 'share', strip_directory : true) meson-0.45.1/test cases/common/66 install subdir/subdir/0000755000175000017500000000000013254552747024303 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/subdir/sub_elided/0000755000175000017500000000000013254552747026402 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/subdir/sub_elided/sixth.dat0000644000175000017500000000003513243342167030220 0ustar jpakkanejpakkane00000000000000Elide test file in a subdir. meson-0.45.1/test cases/common/66 install subdir/subdir/sub_elided/dircheck/0000755000175000017500000000000013254552747030156 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/subdir/sub_elided/dircheck/seventh.dat0000644000175000017500000000003113243342167032305 0ustar jpakkanejpakkane00000000000000Nested file in a subdir. meson-0.45.1/test cases/common/66 install subdir/subdir/meson.build0000644000175000017500000000034613243342167026437 0ustar jpakkanejpakkane00000000000000install_subdir('sub1', install_dir : 'share', # This mode will be overridden by the mode set in the outer install_subdir install_mode : 'rwxr-x---') install_subdir('sub_elided', install_dir : 'share', strip_directory : true) meson-0.45.1/test cases/common/66 install subdir/subdir/sub1/0000755000175000017500000000000013254552747025155 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/subdir/sub1/data1.dat0000644000175000017500000000004112650745767026641 0ustar jpakkanejpakkane00000000000000This is a data file in a subdir. meson-0.45.1/test cases/common/66 install subdir/subdir/sub1/sub2/0000755000175000017500000000000013254552747026030 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/subdir/sub1/sub2/data2.dat0000644000175000017500000000005012650745767027515 0ustar jpakkanejpakkane00000000000000This is a data file in a deeper subdir. meson-0.45.1/test cases/common/66 install subdir/sub2/0000755000175000017500000000000013254552747023666 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/sub2/excluded/0000755000175000017500000000000013254552747025463 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/sub2/excluded/two.dat0000644000175000017500000000000013144116705026740 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/sub2/excluded-three.dat0000644000175000017500000000000013144116705027234 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/sub2/dircheck/0000755000175000017500000000000013254552747025442 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/sub2/dircheck/excluded-three.dat0000644000175000017500000000000013144116705031010 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/sub2/one.dat0000644000175000017500000000000013144116705025113 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/nested_elided/0000755000175000017500000000000013254552745025601 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/nested_elided/sub/0000755000175000017500000000000013254552747026374 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/nested_elided/sub/dircheck/0000755000175000017500000000000013254552747030150 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/nested_elided/sub/dircheck/nineth.dat0000644000175000017500000000005313243342167032114 0ustar jpakkanejpakkane00000000000000Nested file under nested elided directory. meson-0.45.1/test cases/common/66 install subdir/nested_elided/sub/eighth.dat0000644000175000017500000000004113243342167030320 0ustar jpakkanejpakkane00000000000000File in nested elided directory. meson-0.45.1/test cases/common/66 install subdir/sub/0000755000175000017500000000000013254552745023602 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/sub/sub1/0000755000175000017500000000000013254552747024456 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/sub/sub1/third.dat0000644000175000017500000000005012723634706026251 0ustar jpakkanejpakkane00000000000000This is a third data file for sub1 dir. meson-0.45.1/test cases/common/66 install subdir/sub1/0000755000175000017500000000000013254552747023665 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/66 install subdir/sub1/second.dat0000644000175000017500000000006612723634706025630 0ustar jpakkanejpakkane00000000000000Test that multiple install_subdirs meld their results.meson-0.45.1/test cases/common/73 vcstag/0000755000175000017500000000000013254552747021361 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/73 vcstag/vcstag.c.in0000644000175000017500000000004312650745767023423 0ustar jpakkanejpakkane00000000000000const char *vcstag = "@VCS_TAG@"; meson-0.45.1/test cases/common/73 vcstag/meson.build0000644000175000017500000000102413254551765023517 0ustar jpakkanejpakkane00000000000000project('vcstag', 'c') version_src = vcs_tag(input : 'vcstag.c.in', output : 'vcstag.c', fallback : '1.0.0') version_src_custom = vcs_tag(input : 'vcstag.c.in', output : 'vcstag-custom.c', command : ['git', 'show-ref', '-s', 'refs/heads/master'], fallback : '1.0.0') version_src_fallback = vcs_tag(input : 'vcstag.c.in', output : 'vcstag-fallback.c') executable('tagprog', 'tagprog.c', version_src) executable('tagprog-custom', 'tagprog.c', version_src_custom) executable('tagprog-fallback', 'tagprog.c', version_src_fallback) meson-0.45.1/test cases/common/73 vcstag/tagprog.c0000644000175000017500000000020212650745767023167 0ustar jpakkanejpakkane00000000000000#include const char *vcstag; int main(int argc, char **argv) { printf("Version is %s\n", vcstag); return 0; } meson-0.45.1/test cases/common/166 custom target subdir depend files/0000755000175000017500000000000013254552747026512 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/166 custom target subdir depend files/meson.build0000644000175000017500000000020413254552127030640 0ustar jpakkanejpakkane00000000000000project('custom target subdir depend files', 'c') copy = find_program('copyfile.py') subdir('subdir') executable('foo', foo_src) meson-0.45.1/test cases/common/166 custom target subdir depend files/copyfile.py0000644000175000017500000000013413211772701030657 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys import shutil shutil.copyfile(sys.argv[1], sys.argv[2]) meson-0.45.1/test cases/common/166 custom target subdir depend files/subdir/0000755000175000017500000000000013254552747030002 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/166 custom target subdir depend files/subdir/foo.c.in0000644000175000017500000000012213211772701031314 0ustar jpakkanejpakkane00000000000000#include int main() { printf("foo is working.\n"); return 0; } meson-0.45.1/test cases/common/166 custom target subdir depend files/subdir/meson.build0000644000175000017500000000022513211772701032126 0ustar jpakkanejpakkane00000000000000foo_src = custom_target('foo_src', depend_files : 'dep.dat', input : 'foo.c.in', output : 'foo.c', command : [copy, '@INPUT@', '@OUTPUT@'] ) meson-0.45.1/test cases/common/166 custom target subdir depend files/subdir/dep.dat0000644000175000017500000000003413211772701031224 0ustar jpakkanejpakkane00000000000000You can depend on this file.meson-0.45.1/test cases/common/101 suites/0000755000175000017500000000000013254552746021455 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/101 suites/subprojects/0000755000175000017500000000000013254552745024017 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/101 suites/subprojects/sub/0000755000175000017500000000000013254552746024611 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/101 suites/subprojects/sub/sub1.c0000644000175000017500000000014612650745767025636 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("I am test sub1.\n"); return 0; } meson-0.45.1/test cases/common/101 suites/subprojects/sub/meson.build0000644000175000017500000000025112650745767026757 0ustar jpakkanejpakkane00000000000000project('subproject test suites', 'c') sub1 = executable('sub1', 'sub1.c') sub2 = executable('sub2', 'sub2.c') test('sub1', sub1) test('sub2', sub2, suite : 'suite2') meson-0.45.1/test cases/common/101 suites/subprojects/sub/sub2.c0000644000175000017500000000014612650745767025637 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("I am test sub2.\n"); return 0; } meson-0.45.1/test cases/common/101 suites/exe2.c0000644000175000017500000000014612650745767022473 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("I am test exe2.\n"); return 0; } meson-0.45.1/test cases/common/101 suites/meson.build0000644000175000017500000000031513254552021023600 0ustar jpakkanejpakkane00000000000000project('multiple test suites', 'c') subproject('sub') exe1 = executable('exe1', 'exe1.c') exe2 = executable('exe2', 'exe2.c') test('exe1', exe1) test('exe2', exe2, suite : ['suite2', 'super-special']) meson-0.45.1/test cases/common/101 suites/exe1.c0000644000175000017500000000014612650745767022472 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("I am test exe1.\n"); return 0; } meson-0.45.1/test cases/common/63 array methods/0000755000175000017500000000000013254552747022633 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/63 array methods/meson.build0000644000175000017500000000151013254551754024767 0ustar jpakkanejpakkane00000000000000project('array methods', 'c') empty = [] one = ['abc'] two = ['def', 'ghi'] combined = [empty, one, two] if empty.contains('abc') error('Empty is not empty.') endif if one.contains('a') error('One claims to contain a') endif if not one.contains('abc') error('One claims to not contain abc.') endif if one.contains('abcd') error('One claims to contain abcd.') endif if two.contains('abc') error('Two claims to contain abc.') endif if not two.contains('def') error('Two claims not to contain def.') endif if not two.contains('ghi') error('Two claims not to contain ghi.') endif if two.contains('defg') error('Two claims to contain defg.') endif if not combined.contains('abc') error('Combined claims not to contain abc.') endif if not combined.contains('ghi') error('Combined claims not to contain ghi.') endif meson-0.45.1/test cases/common/11 subdir/0000755000175000017500000000000013254552746021351 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/11 subdir/meson.build0000644000175000017500000000005513254551642023505 0ustar jpakkanejpakkane00000000000000project('subdir test', 'c') subdir('subdir') meson-0.45.1/test cases/common/11 subdir/subdir/0000755000175000017500000000000013254552746022641 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/11 subdir/subdir/meson.build0000644000175000017500000000003512650745767025007 0ustar jpakkanejpakkane00000000000000executable('prog', 'prog.c') meson-0.45.1/test cases/common/11 subdir/subdir/prog.c0000644000175000017500000000005612650745767023763 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/12 data/0000755000175000017500000000000013254552746020773 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/12 data/installed_files.txt0000644000175000017500000000033413254550710024662 0ustar jpakkanejpakkane00000000000000usr/share/progname/datafile.dat usr/share/progname/fileobject_datafile.dat usr/share/progname/vanishing.dat usr/share/progname/vanishing2.dat usr/share/data install test/somefile.txt etc/etcfile.dat usr/bin/runscript.sh meson-0.45.1/test cases/common/12 data/vanishing/0000755000175000017500000000000013254552746022761 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/12 data/vanishing/meson.build0000644000175000017500000000011012650745767025121 0ustar jpakkanejpakkane00000000000000install_data(sources : 'vanishing.dat', install_dir : 'share/progname') meson-0.45.1/test cases/common/12 data/vanishing/vanishing.dat0000644000175000017500000000006712650745767025452 0ustar jpakkanejpakkane00000000000000This is a data file to be installed in a subdirectory. meson-0.45.1/test cases/common/12 data/vanishing/vanishing2.dat0000644000175000017500000000023612703007422025504 0ustar jpakkanejpakkane00000000000000This is a data file to be installed in a subdirectory. It is installed from a different subdir to test that the installer strips the source tree dir prefix. meson-0.45.1/test cases/common/12 data/meson.build0000644000175000017500000000127313254551642023132 0ustar jpakkanejpakkane00000000000000project('data install test', 'c') install_data(sources : 'datafile.dat', install_dir : 'share/progname') # Some file in /etc that is only read-write by root; add a sticky bit for testing install_data(sources : 'etcfile.dat', install_dir : '/etc', install_mode : 'rw------T') # Some script that needs to be executable by the group install_data('runscript.sh', install_dir : get_option('bindir'), install_mode : ['rwxr-sr-x', 'root', 0]) install_data(files('fileobject_datafile.dat'), install_dir : 'share/progname', install_mode : [false, false, 0]) install_data(files('somefile.txt')) subdir('vanishing') install_data(sources : 'vanishing/vanishing2.dat', install_dir : 'share/progname') meson-0.45.1/test cases/common/12 data/fileobject_datafile.dat0000644000175000017500000000007113016624375025414 0ustar jpakkanejpakkane00000000000000This is a data file that is installed via a File object. meson-0.45.1/test cases/common/12 data/somefile.txt0000644000175000017500000000000013246615532023317 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/12 data/etcfile.dat0000644000175000017500000000004012650745767023100 0ustar jpakkanejpakkane00000000000000This goes into /etc/etcfile.dat meson-0.45.1/test cases/common/12 data/datafile.dat0000644000175000017500000000002412650745767023240 0ustar jpakkanejpakkane00000000000000this is a data file meson-0.45.1/test cases/common/12 data/runscript.sh0000644000175000017500000000003413043224360023335 0ustar jpakkanejpakkane00000000000000#!/bin/sh echo "Runscript" meson-0.45.1/test cases/common/75 should fail/0000755000175000017500000000000013254552747022266 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/75 should fail/meson.build0000644000175000017500000000015413254551767024431 0ustar jpakkanejpakkane00000000000000project('should fail', 'c') exe = executable('prog', 'failing.c') test('failing', exe, should_fail : true) meson-0.45.1/test cases/common/75 should fail/failing.c0000644000175000017500000000006212650745767024046 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 1; } meson-0.45.1/test cases/common/136 build by default targets in tests/0000755000175000017500000000000013254552746026414 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/136 build by default targets in tests/main.c0000644000175000017500000000006213043224360027462 0ustar jpakkanejpakkane00000000000000int main (int argc, char *argv[]) { return 0; } meson-0.45.1/test cases/common/136 build by default targets in tests/meson.build0000644000175000017500000000164413254552070030551 0ustar jpakkanejpakkane00000000000000project('unit-test', 'c', version : '1.0') write_file = find_program('write_file.py') # A test that consumes and verifies the output generated by a custom target. # Should work even if target is not built by default. Makes sure that foo.out # is actually created before the test command that uses foo_out is run. foo_out = custom_target('foo.out', output : 'foo.out', command : [write_file, '@OUTPUT@']) # Also verify that a build_by_default : false BuildTarget added to a test is # built before the test is run. exe_out = executable('out', 'main.c', build_by_default : false) py_file_exists = '''import os, sys if not os.path.exists(sys.argv[1]) or not os.path.exists(sys.argv[2]): print("could not find {!r} or {!r} in {!r}" "".format(sys.argv[1], sys.argv[2], os.getcwd())) sys.exit(1)''' python = import('python3').find_python() test('output-check', python, args : ['-c', py_file_exists, foo_out, exe_out]) meson-0.45.1/test cases/common/136 build by default targets in tests/write_file.py0000644000175000017500000000013213043224360031073 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys with open(sys.argv[1], 'w') as f: f.write('Test') meson-0.45.1/test cases/common/179 source in dep/0000755000175000017500000000000013254552747022601 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/179 source in dep/foo.c0000644000175000017500000000003513246615532023517 0ustar jpakkanejpakkane00000000000000int foo() { return 42; } meson-0.45.1/test cases/common/179 source in dep/meson.build0000644000175000017500000000017413254552142024732 0ustar jpakkanejpakkane00000000000000project('foo', 'c', 'cpp') dep = declare_dependency(sources : 'foo.c') executable('bar', 'bar.cpp', dependencies : dep) meson-0.45.1/test cases/common/179 source in dep/bar.cpp0000644000175000017500000000011113246615532024033 0ustar jpakkanejpakkane00000000000000extern "C" int foo(); int main(int, char**) { return foo() != 42; } meson-0.45.1/test cases/common/186 ndebug if-release disabled/0000755000175000017500000000000013254552747025150 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/186 ndebug if-release disabled/main.c0000644000175000017500000000014413254550704026226 0ustar jpakkanejpakkane00000000000000#include #include int main(void) { assert(0); return EXIT_SUCCESS; } meson-0.45.1/test cases/common/186 ndebug if-release disabled/meson.build0000644000175000017500000000045513254552143027304 0ustar jpakkanejpakkane00000000000000project('ndebug disabled', 'c', default_options : [ 'buildtype=release', 'b_ndebug=if-release', ]) if meson.get_compiler('c').get_id() == 'msvc' error('MESON_SKIP_TEST b_ndebug is not supported on Visual Studio') endif test('exe', executable('main', 'main.c')) meson-0.45.1/test cases/common/162 wrap file should not failed/0000755000175000017500000000000013254552746025266 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/162 wrap file should not failed/subprojects/0000755000175000017500000000000013254552746027631 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/162 wrap file should not failed/subprojects/packagecache/0000755000175000017500000000000013254552747032211 5ustar jpakkanejpakkane00000000000000././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000meson-0.45.1/test cases/common/162 wrap file should not failed/subprojects/packagecache/zlib-1.2.8.tar.gzmeson-0.45.1/test cases/common/162 wrap file should not failed/subprojects/packagecache/zlib-1.2.8.t0000644000175000017500000000000613174155420033762 0ustar jpakkanejpakkane00000000000000dummy ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000meson-0.45.1/test cases/common/162 wrap file should not failed/subprojects/packagecache/zlib-1.2.8-8-wrap.zipmeson-0.45.1/test cases/common/162 wrap file should not failed/subprojects/packagecache/zlib-1.2.8-80000644000175000017500000000000613174155420033665 0ustar jpakkanejpakkane00000000000000dummy meson-0.45.1/test cases/common/162 wrap file should not failed/subprojects/zlib.wrap0000644000175000017500000000061713174155420031455 0ustar jpakkanejpakkane00000000000000[wrap-file] directory = zlib-1.2.8 source_url = http://zlib.net/fossils/zlib-1.2.8.tar.gz source_filename = zlib-1.2.8.tar.gz source_hash = 36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d patch_url = https://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.8/8/get_zip patch_filename = zlib-1.2.8-8-wrap.zip patch_hash = 17c52a0e0c59ce926d3959005d5cd8178c6c7e2c9a4a1304279a8320c955ac60 meson-0.45.1/test cases/common/162 wrap file should not failed/subprojects/zlib-1.2.8/0000755000175000017500000000000013254552747031236 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/162 wrap file should not failed/subprojects/zlib-1.2.8/foo.c0000644000175000017500000000004413174155432032152 0ustar jpakkanejpakkane00000000000000int dummy_func() { return 42; } meson-0.45.1/test cases/common/162 wrap file should not failed/subprojects/zlib-1.2.8/meson.build0000644000175000017500000000007213174155420033363 0ustar jpakkanejpakkane00000000000000project('shared lib', 'c') shared_library('foo', 'foo.c') meson-0.45.1/test cases/common/162 wrap file should not failed/meson.build0000644000175000017500000000026213254552124027416 0ustar jpakkanejpakkane00000000000000project('mainproj', 'c') subproject('zlib') executable('grabprog', files('src/subprojects/prog.c')) executable('grabprog2', files('src/subprojects/foo/prog2.c')) subdir('src') meson-0.45.1/test cases/common/162 wrap file should not failed/src/0000755000175000017500000000000013254552746026055 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/162 wrap file should not failed/src/subprojects/0000755000175000017500000000000013254552746030420 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/162 wrap file should not failed/src/subprojects/prog.c0000644000175000017500000000030713174155432031523 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("Do not have a file layout like this in your own projects.\n"); printf("This is only to test that this works.\n"); return 0; } meson-0.45.1/test cases/common/162 wrap file should not failed/src/subprojects/foo/0000755000175000017500000000000013254552746031203 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/162 wrap file should not failed/src/subprojects/foo/prog2.c0000644000175000017500000000030713174155432032370 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("Do not have a file layout like this in your own projects.\n"); printf("This is only to test that this works.\n"); return 0; } meson-0.45.1/test cases/common/162 wrap file should not failed/src/meson.build0000644000175000017500000000015713174155432030212 0ustar jpakkanejpakkane00000000000000executable('grabprog3', files('subprojects/prog.c')) executable('grabprog4', files('subprojects/foo/prog2.c')) meson-0.45.1/test cases/common/56 custom target/0000755000175000017500000000000013254552747022654 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/56 custom target/installed_files.txt0000644000175000017500000000002412650745767026557 0ustar jpakkanejpakkane00000000000000usr/subdir/data.dat meson-0.45.1/test cases/common/56 custom target/meson.build0000644000175000017500000000122013254551743025004 0ustar jpakkanejpakkane00000000000000project('custom target', 'c') python = find_program('python3', required : false) if not python.found() python = find_program('python') endif # Note that this will not add a dependency to the compiler executable. # Code will not be rebuilt if it changes. comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py') # Test that files() in command: works. The compiler just discards it. useless = files('installed_files.txt') mytarget = custom_target('bindat', output : 'data.dat', input : 'data_source.txt', command : [python, comp, '--input=@INPUT@', '--output=@OUTPUT@', useless], install : true, install_dir : 'subdir' ) subdir('depfile') meson-0.45.1/test cases/common/56 custom target/data_source.txt0000644000175000017500000000004012650745767025705 0ustar jpakkanejpakkane00000000000000This is a text only input file. meson-0.45.1/test cases/common/56 custom target/depfile/0000755000175000017500000000000013254552747024264 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/56 custom target/depfile/meson.build0000644000175000017500000000026212763077471026426 0ustar jpakkanejpakkane00000000000000 mytarget = custom_target('depfile', output : 'dep.dat', depfile : 'dep.dat.d', command : [find_program('dep.py'), meson.current_source_dir(), '@DEPFILE@', '@OUTPUT@'], ) meson-0.45.1/test cases/common/56 custom target/depfile/dep.py0000755000175000017500000000056113043224360025372 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python import sys, os from glob import glob _, srcdir, depfile, output = sys.argv depfiles = glob(os.path.join(srcdir, '*')) quoted_depfiles = [x.replace(' ', '\ ') for x in depfiles] with open(output, 'w') as f: f.write('I am the result of globbing.') with open(depfile, 'w') as f: f.write('%s: %s\n' % (output, ' '.join(quoted_depfiles))) meson-0.45.1/test cases/common/56 custom target/my_compiler.py0000755000175000017500000000113613055371450025536 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import os import sys assert(os.path.exists(sys.argv[3])) args = sys.argv[:-1] if __name__ == '__main__': if len(args) != 3 or not args[1].startswith('--input') or \ not args[2].startswith('--output'): print(args[0], '--input=input_file --output=output_file') sys.exit(1) with open(args[1].split('=')[1]) as f: ifile = f.read() if ifile != 'This is a text only input file.\n': print('Malformed input') sys.exit(1) with open(args[2].split('=')[1], 'w') as ofile: ofile.write('This is a binary output file.\n') meson-0.45.1/test cases/common/55 file grabber/0000755000175000017500000000000013254552747022376 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/55 file grabber/grabber2.bat0000644000175000017500000000007512650745767024563 0ustar jpakkanejpakkane00000000000000@ECHO OFF echo suba.c echo subb.c echo subc.c echo subprog.c meson-0.45.1/test cases/common/55 file grabber/grabber.sh0000755000175000017500000000005312650745767024344 0ustar jpakkanejpakkane00000000000000#!/bin/sh for i in *.c; do echo $i done meson-0.45.1/test cases/common/55 file grabber/c.c0000644000175000017500000000003212650745767022764 0ustar jpakkanejpakkane00000000000000int funcc() { return 0; } meson-0.45.1/test cases/common/55 file grabber/meson.build0000644000175000017500000000167513254551743024544 0ustar jpakkanejpakkane00000000000000project('grabber', 'c') # What this script does is NOT reliable. Simply adding a file in this directory # will NOT make it automatically appear in the build. You have to manually # re-invoke Meson (not just Ninja) for that to happen. The simplest way # is to touch meson-private/coredata.dat. # This is not the recommended way to do things, but if the tradeoffs are # acceptable to you, then we're certainly not going to stop you. Just don't # file bugs when it fails. :) if build_machine.system() == 'windows' c = run_command('grabber.bat') grabber = find_program('grabber2.bat') else c = run_command('grabber.sh') grabber = find_program('grabber.sh') endif # First test running command explicitly. if c.returncode() != 0 error('Executing script failed.') endif newline = ''' ''' sources = c.stdout().strip().split(newline) e = executable('prog', sources) test('grabtest', e) # Then test using program with find_program subdir('subdir') meson-0.45.1/test cases/common/55 file grabber/b.c0000644000175000017500000000003212650745767022763 0ustar jpakkanejpakkane00000000000000int funcb() { return 0; } meson-0.45.1/test cases/common/55 file grabber/subdir/0000755000175000017500000000000013254552747023666 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/55 file grabber/subdir/meson.build0000644000175000017500000000021212650745767026030 0ustar jpakkanejpakkane00000000000000sc = run_command(grabber) subsources = sc.stdout().strip().split(newline) se = executable('subprog', subsources) test('subgrabtest', se) meson-0.45.1/test cases/common/55 file grabber/subdir/subc.c0000644000175000017500000000003212650745767024766 0ustar jpakkanejpakkane00000000000000int funcc() { return 0; } meson-0.45.1/test cases/common/55 file grabber/subdir/subb.c0000644000175000017500000000003212650745767024765 0ustar jpakkanejpakkane00000000000000int funcb() { return 0; } meson-0.45.1/test cases/common/55 file grabber/subdir/subprog.c0000644000175000017500000000016412650745767025521 0ustar jpakkanejpakkane00000000000000int funca(); int funcb(); int funcc(); int main(int argc, char **argv) { return funca() + funcb() + funcc(); } meson-0.45.1/test cases/common/55 file grabber/subdir/suba.c0000644000175000017500000000003212650745767024764 0ustar jpakkanejpakkane00000000000000int funca() { return 0; } meson-0.45.1/test cases/common/55 file grabber/grabber.bat0000644000175000017500000000006112650745767024474 0ustar jpakkanejpakkane00000000000000@ECHO OFF echo a.c echo b.c echo c.c echo prog.c meson-0.45.1/test cases/common/55 file grabber/prog.c0000644000175000017500000000016412650745767023517 0ustar jpakkanejpakkane00000000000000int funca(); int funcb(); int funcc(); int main(int argc, char **argv) { return funca() + funcb() + funcc(); } meson-0.45.1/test cases/common/55 file grabber/a.c0000644000175000017500000000003212650745767022762 0ustar jpakkanejpakkane00000000000000int funca() { return 0; } meson-0.45.1/test cases/common/45 alignment/0000755000175000017500000000000013254552747022047 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/45 alignment/meson.build0000644000175000017500000000154413254551716024210 0ustar jpakkanejpakkane00000000000000project('alignment', 'c', 'cpp') compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] foreach cc : compilers # These tests should return the same value on all # platforms. If (and when) they don't, fix 'em up. if cc.alignment('char') != 1 error('Alignment of char misdetected.') endif ptr_size = cc.sizeof('void*') dbl_alignment = cc.alignment('double') # These tests are not thorough. Doing this properly # would take a lot of work because it is strongly # platform and compiler dependent. So just check # that they produce something fairly sane. if ptr_size == 8 or ptr_size == 4 message('Size of ptr ok.') else error('Size of ptr misdetected.') endif if dbl_alignment == 8 or dbl_alignment == 4 message('Alignment of double ok.') else error('Alignment of double misdetected.') endif endforeach meson-0.45.1/test cases/common/165 config tool variable/0000755000175000017500000000000013254552747024125 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/165 config tool variable/meson.build0000644000175000017500000000202513254552126026255 0ustar jpakkanejpakkane00000000000000# Copyright Ā© 2017 Intel Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. project('config tool variable', 'cpp') dep_llvm = dependency('llvm', required : false) if not dep_llvm.found() error('MESON_SKIP_TEST LLVM not installed.') endif includedir = dep_llvm.get_configtool_variable('includedir') includedir = join_paths(includedir, 'llvm') if host_machine.system() == 'windows' cmd = run_command(['dir', includedir]) else cmd = run_command(['ls', includedir]) endif assert(cmd.returncode() == 0, 'did not run successfully') meson-0.45.1/test cases/common/10 man install/0000755000175000017500000000000013254552746022262 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/10 man install/installed_files.txt0000644000175000017500000000023013140423077026143 0ustar jpakkanejpakkane00000000000000usr/share/man/man1/foo.1.gz usr/share/man/man2/bar.2.gz usr/share/man/man1/vanishing.1.gz usr/share/man/man2/vanishing.2.gz usr/share/man/man1/baz.1.gz meson-0.45.1/test cases/common/10 man install/vanishing/0000755000175000017500000000000013254552746024250 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/10 man install/vanishing/meson.build0000644000175000017500000000003312650745767026414 0ustar jpakkanejpakkane00000000000000install_man('vanishing.1') meson-0.45.1/test cases/common/10 man install/vanishing/vanishing.20000644000175000017500000000007112723634706026314 0ustar jpakkanejpakkane00000000000000This is a second man page of the vanishing subdirectory. meson-0.45.1/test cases/common/10 man install/vanishing/vanishing.10000644000175000017500000000006212650745767026324 0ustar jpakkanejpakkane00000000000000This is a man page of the vanishing subdirectory. meson-0.45.1/test cases/common/10 man install/meson.build0000644000175000017500000000045513254551642024422 0ustar jpakkanejpakkane00000000000000project('man install', 'c') m1 = install_man('foo.1') m2 = install_man('bar.2') install_man('vanishing/vanishing.2') subdir('vanishing') cdata = configuration_data() cdata.set('TODAY', '$this_day') b1 = configure_file(input : 'baz.1.in', output : 'baz.1', configuration : cdata) install_man(b1) meson-0.45.1/test cases/common/10 man install/bar.20000644000175000017500000000007012650745767023114 0ustar jpakkanejpakkane00000000000000this is a man page of bar.2, its contents are irrelevantmeson-0.45.1/test cases/common/10 man install/baz.1.in0000644000175000017500000000041413140423077023510 0ustar jpakkanejpakkane00000000000000This is a man page of baz.1 it was generated @TODAY@. You should not put generation timestamps in real world projects because they break reproducible builds. This manpage is written by professionals or under the supervision of professionals. Do not try this at home. meson-0.45.1/test cases/common/10 man install/foo.10000644000175000017500000000007012650745767023132 0ustar jpakkanejpakkane00000000000000this is a man page of foo.1 its contents are irrelevant meson-0.45.1/test cases/common/93 private include/0000755000175000017500000000000013254552750023144 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/93 private include/stlib/0000755000175000017500000000000013254552750024261 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/93 private include/stlib/meson.build0000644000175000017500000000045212650745767026437 0ustar jpakkanejpakkane00000000000000genbin = find_program('compiler.py') gen = generator(genbin, output : ['@BASENAME@.h', '@BASENAME@.c'], arguments : ['@INPUT@', '@BUILD_DIR@'] ) defs = ['foo1.def', 'foo2.def'] generated = gen.process(defs) stlib = static_library('st', generated) st_priv_inc = stlib.private_dir_include() meson-0.45.1/test cases/common/93 private include/stlib/foo2.def0000644000175000017500000000000012650745767025607 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/93 private include/stlib/compiler.py0000755000175000017500000000101013057037314026433 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys, os assert(len(sys.argv) == 3) h_templ = '''#pragma once unsigned int %s(); ''' c_templ = '''#include"%s.h" unsigned int %s() { return 0; } ''' ifile = sys.argv[1] outdir = sys.argv[2] base = os.path.splitext(os.path.split(ifile)[-1])[0] cfile = os.path.join(outdir, base + '.c') hfile = os.path.join(outdir, base + '.h') c_code = c_templ % (base, base) h_code = h_templ % base with open(cfile, 'w') as f: f.write(c_code) with open(hfile, 'w') as f: f.write(h_code) meson-0.45.1/test cases/common/93 private include/stlib/foo1.def0000644000175000017500000000000012650745767025606 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/93 private include/meson.build0000644000175000017500000000007713254552012025301 0ustar jpakkanejpakkane00000000000000project('access private', 'c') subdir('stlib') subdir('user') meson-0.45.1/test cases/common/93 private include/user/0000755000175000017500000000000013254552750024122 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/93 private include/user/meson.build0000644000175000017500000000017112650745767026276 0ustar jpakkanejpakkane00000000000000exe = executable('libuser', 'libuser.c', link_with : stlib, include_directories : st_priv_inc) test('libuser', exe) meson-0.45.1/test cases/common/93 private include/user/libuser.c0000644000175000017500000000014312650745767025744 0ustar jpakkanejpakkane00000000000000#include"foo1.h" #include"foo2.h" int main(int argc, char **argv) { return foo1() + foo2(); } meson-0.45.1/test cases/common/97 selfbuilt custom/0000755000175000017500000000000013254552750023356 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/97 selfbuilt custom/meson.build0000644000175000017500000000057613254552016025523 0ustar jpakkanejpakkane00000000000000project('selfbuilt custom', 'cpp') # Build an exe and use it in a custom target # whose output is used to build a different exe. tool = executable('tool', 'tool.cpp', native : true) hfile = custom_target('datah', output : 'data.h', input : 'data.dat', command : [tool, '@INPUT@', '@OUTPUT@'], ) main = executable('mainprog', 'mainprog.cpp', hfile) test('maintest', main) meson-0.45.1/test cases/common/97 selfbuilt custom/tool.cpp0000644000175000017500000000133712650745767025056 0ustar jpakkanejpakkane00000000000000#include #include #include using namespace std; const char prefix[] = "int "; const char suffix[] = " () {\n return 52;}\n"; int main(int argc, char **argv) { if(argc != 3) { cout << "You is fail.\n"; return 1; } ifstream is(argv[1], ifstream::binary); if(!is) { cout << "Opening input file failed.\n"; return 1; } string funcname; is >> funcname; ofstream os(argv[2], ofstream::binary); if(!os) { cout << "Opening output file failed.\n"; return 1; } os << prefix << funcname << suffix; os.close(); if(!os.good()) { cout << "Writing data out failed.\n"; return 1; } return 0; } meson-0.45.1/test cases/common/97 selfbuilt custom/mainprog.cpp0000644000175000017500000000012412650745767025706 0ustar jpakkanejpakkane00000000000000#include"data.h" int main(int, char **) { return generated_function() != 52; } meson-0.45.1/test cases/common/97 selfbuilt custom/data.dat0000644000175000017500000000002312650745767024767 0ustar jpakkanejpakkane00000000000000generated_function meson-0.45.1/test cases/common/18 else/0000755000175000017500000000000013254552747021021 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/18 else/meson.build0000644000175000017500000000023513254551652023155 0ustar jpakkanejpakkane00000000000000project('else test', 'c') var = false if var exe = executable('break', 'break.c') else exe = executable('prog', 'prog.c') endif test('elsetest', exe) meson-0.45.1/test cases/common/18 else/prog.c0000644000175000017500000000005612650745767022142 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/43 has function/0000755000175000017500000000000013254552747022450 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/43 has function/meson.build0000644000175000017500000001001513254551730024576 0ustar jpakkanejpakkane00000000000000project('has function', 'c', 'cpp') host_system = host_machine.system() # This is used in the `test_compiler_check_flags_order` unit test unit_test_args = '-I/tmp' defines_has_builtin = '''#ifndef __has_builtin #error "no __has_builtin" #endif ''' compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] foreach cc : compilers if not cc.has_function('printf', prefix : '#include', args : unit_test_args) error('"printf" function not found (should always exist).') endif # Should also be able to detect it without specifying the header # We check for a different function here to make sure the result is # not taken from a cache (ie. the check above) # On MSVC fprintf is defined as an inline function in the header, so it cannot # be found without the include. if cc.get_id() != 'msvc' assert(cc.has_function('fprintf', args : unit_test_args), '"fprintf" function not found without include (on !msvc).') else assert(cc.has_function('fprintf', prefix : '#include ', args : unit_test_args), '"fprintf" function not found with include (on msvc).') # Compiler intrinsics assert(cc.has_function('strcmp'), 'strcmp intrinsic should have been found on MSVC') assert(cc.has_function('strcmp', prefix : '#include '), 'strcmp intrinsic should have been found with #include on MSVC') endif if cc.has_function('hfkerhisadf', prefix : '#include', args : unit_test_args) error('Found non-existent function "hfkerhisadf".') endif if cc.has_function('hfkerhisadf', args : unit_test_args) error('Found non-existent function "hfkerhisadf".') endif # With glibc on Linux lchmod is a stub that will always return an error, # we want to detect that and declare that the function is not available. # We can't check for the C library used here of course, but if it's not # implemented in glibc it's probably not implemented in any other 'slimmer' # C library variants either, so the check should be safe either way hopefully. if host_system == 'linux' or host_system == 'darwin' assert (cc.has_function('poll', prefix : '#include ', args : unit_test_args), 'couldn\'t detect "poll" when defined by a header') lchmod_prefix = '#include \n#include ' if host_system == 'linux' assert (not cc.has_function('lchmod', prefix : lchmod_prefix, args : unit_test_args), '"lchmod" check should have failed') else # macOS and *BSD have lchmod assert (cc.has_function('lchmod', prefix : lchmod_prefix, args : unit_test_args), '"lchmod" check should have succeeded') endif # Check that built-ins are found properly both with and without headers assert(cc.has_function('alloca', args : unit_test_args), 'built-in alloca must be found on ' + host_system) assert(cc.has_function('alloca', prefix : '#include ', args : unit_test_args), 'built-in alloca must be found with #include') if not cc.compiles(defines_has_builtin, args : unit_test_args) assert(not cc.has_function('alloca', prefix : '#include \n#undef alloca', args : unit_test_args), 'built-in alloca must not be found with #include and #undef') endif endif # For some functions one needs to define _GNU_SOURCE before including the # right headers to get them picked up. Make sure we can detect these functions # as well without any prefix if cc.has_header_symbol('sys/socket.h', 'recvmmsg', prefix : '#define _GNU_SOURCE', args : unit_test_args) # We assume that if recvmmsg exists sendmmsg does too assert (cc.has_function('sendmmsg', args : unit_test_args), 'Failed to detect function "sendmmsg" (should always exist).') endif endforeach meson-0.45.1/test cases/common/156 shared module resolving symbol in executable/0000755000175000017500000000000013254552746030637 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/156 shared module resolving symbol in executable/meson.build0000644000175000017500000000145113254552116032771 0ustar jpakkanejpakkane00000000000000project('shared module resolving symbol in executable', 'c') # The shared module contains a reference to the symbol 'func_from_executable', # which is always provided by the executable which loads it. This symbol can be # resolved at run-time by an ELF loader. But when building PE/COFF objects, all # symbols must be resolved at link-time, so an implib is generated for the # executable, and the shared module linked with it. # # See testcase 125 for an example of the more complex portability gymnastics # required if we do not know (at link-time) what provides the symbol. dl = meson.get_compiler('c').find_library('dl', required: false) e = executable('prog', 'prog.c', dependencies: dl, export_dynamic: true) m = shared_module('module', 'module.c', link_with: e) test('test', e, args: m.full_path()) meson-0.45.1/test cases/common/156 shared module resolving symbol in executable/prog.c0000644000175000017500000000205513134457413031744 0ustar jpakkanejpakkane00000000000000#include #include #ifdef _WIN32 #include #else #include #endif #if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif typedef int (*fptr) (void); int DLL_PUBLIC func_from_executable(void) { return 42; } int main (int argc, char **argv) { int expected, actual; fptr importedfunc; #ifdef _WIN32 HMODULE h = LoadLibraryA(argv[1]); #else void *h = dlopen(argv[1], RTLD_NOW); #endif assert(h != NULL); #ifdef _WIN32 importedfunc = (fptr) GetProcAddress (h, "func"); #else importedfunc = (fptr) dlsym(h, "func"); #endif assert(importedfunc != NULL); assert(importedfunc != func_from_executable); actual = (*importedfunc)(); expected = func_from_executable(); assert(actual == expected); #ifdef _WIN32 FreeLibrary(h); #else dlclose(h); #endif return 0; } meson-0.45.1/test cases/common/156 shared module resolving symbol in executable/module.c0000644000175000017500000000061513134457413032262 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif extern int func_from_executable(void); int DLL_PUBLIC func(void) { return func_from_executable(); } meson-0.45.1/test cases/common/144 empty build file/0000755000175000017500000000000013254552746023266 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/144 empty build file/meson.build0000644000175000017500000000010413254552102025405 0ustar jpakkanejpakkane00000000000000project('subdir with empty meson.build test', 'c') subdir('subdir') meson-0.45.1/test cases/common/144 empty build file/subdir/0000755000175000017500000000000013254552746024556 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/144 empty build file/subdir/meson.build0000644000175000017500000000000013074426732026701 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/23 global arg/0000755000175000017500000000000013254552747022057 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/23 global arg/meson.build0000644000175000017500000000051013254551661024207 0ustar jpakkanejpakkane00000000000000project('global arg test', 'cpp', 'c') add_global_arguments('-DMYTHING', language : 'c') add_global_arguments('-DMYCPPTHING', language : 'cpp') add_global_arguments('-DMYCANDCPPTHING', language: ['c', 'cpp']) exe1 = executable('prog', 'prog.c') exe2 = executable('prog2', 'prog.cc') test('prog1', exe1) test('prog2', exe2) meson-0.45.1/test cases/common/23 global arg/prog.cc0000644000175000017500000000035013074426732023325 0ustar jpakkanejpakkane00000000000000#ifdef MYTHING #error "Wrong global argument set" #endif #ifndef MYCPPTHING #error "Global argument not set" #endif #ifndef MYCANDCPPTHING #error "Global argument not set" #endif int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/23 global arg/prog.c0000644000175000017500000000035013074426732023162 0ustar jpakkanejpakkane00000000000000#ifndef MYTHING #error "Global argument not set" #endif #ifdef MYCPPTHING #error "Wrong global argument set" #endif #ifndef MYCANDCPPTHING #error "Global argument not set" #endif int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/common/122 skip/0000755000175000017500000000000013254552746021112 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/122 skip/meson.build0000644000175000017500000000011513016624375023243 0ustar jpakkanejpakkane00000000000000project('skip', 'c') error('MESON_SKIP_TEST this test is always skipped.') meson-0.45.1/test cases/common/178 preserve gendir/0000755000175000017500000000000013254552747023244 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/178 preserve gendir/testprog.c0000644000175000017500000000016613246615532025253 0ustar jpakkanejpakkane00000000000000#include"base.h" #include"com/mesonbuild/subbie.h" int main(int argc, char **argv) { return base() + subbie(); } meson-0.45.1/test cases/common/178 preserve gendir/meson.build0000644000175000017500000000064313254552142025376 0ustar jpakkanejpakkane00000000000000project('preserve subdir', 'c') gprog = find_program('genprog.py') gen = generator(gprog, \ output : ['@BASENAME@.c', '@BASENAME@.h'], arguments : ['--searchdir=@CURRENT_SOURCE_DIR@', '--outdir=@BUILD_DIR@', '@INPUT@']) generated = gen.process('base.inp', 'com/mesonbuild/subbie.inp', preserve_path_from : meson.current_source_dir()) e = executable('testprog', 'testprog.c', generated) test('testprog', e) meson-0.45.1/test cases/common/178 preserve gendir/base.inp0000644000175000017500000000000513246615532024652 0ustar jpakkanejpakkane00000000000000base meson-0.45.1/test cases/common/178 preserve gendir/com/0000755000175000017500000000000013254552745024020 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/178 preserve gendir/com/mesonbuild/0000755000175000017500000000000013254552747026163 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/178 preserve gendir/com/mesonbuild/subbie.inp0000644000175000017500000000000713246615532030132 0ustar jpakkanejpakkane00000000000000subbie meson-0.45.1/test cases/common/178 preserve gendir/genprog.py0000755000175000017500000000225213246615532025254 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import os, sys, argparse h_templ = '''#pragma once int %s(); ''' c_templ = '''#include"%s.h" int %s() { return 0; } ''' parser = argparse.ArgumentParser() parser.add_argument('--searchdir', required=True) parser.add_argument('--outdir', required=True) parser.add_argument('ifiles', nargs='+') options = parser.parse_args() searchdir = options.searchdir outdir = options.outdir ifiles = options.ifiles rel_ofiles = [] for ifile in ifiles: if not ifile.startswith(options.searchdir): sys.exit('Input file %s does not start with search dir %s.' % (ifile, searchdir)) rel_ofile = ifile[len(searchdir):] if rel_ofile[0] == '/' or rel_ofile[0] == '\\': rel_ofile = rel_ofile[1:] rel_ofiles.append(os.path.splitext(rel_ofile)[0]) ofile_bases = [os.path.join(outdir, i) for i in rel_ofiles] for i, ifile_name in enumerate(ifiles): proto_name = open(ifile_name).readline().strip() h_out = ofile_bases[i] + '.h' c_out = ofile_bases[i] + '.c' os.makedirs(os.path.split(ofile_bases[i])[0], exist_ok=True) open(h_out, 'w').write(h_templ % (proto_name)) open(c_out, 'w').write(c_templ % (proto_name, proto_name)) meson-0.45.1/test cases/common/158 dotinclude/0000755000175000017500000000000013254552746022307 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/common/158 dotinclude/meson.build0000644000175000017500000000015013254552121024430 0ustar jpakkanejpakkane00000000000000project('dotinclude', 'c') executable('dotproc', 'dotproc.c', implicit_include_directories : false) meson-0.45.1/test cases/common/158 dotinclude/dotproc.c0000644000175000017500000000027613141361617024120 0ustar jpakkanejpakkane00000000000000#include"stdio.h" #ifndef WRAPPER_INCLUDED #error The wrapper stdio.h was not included. #endif int main(int argc, char **argv) { printf("Eventually I got printed.\n"); return 0; } meson-0.45.1/test cases/common/158 dotinclude/stdio.h0000644000175000017500000000022713141361617023571 0ustar jpakkanejpakkane00000000000000// There is no #pragma once because we _want_ to cause an eternal loop // if this wrapper invokes itself. #define WRAPPER_INCLUDED #include meson-0.45.1/test cases/rust/0000755000175000017500000000000013254552745017363 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/rust/7 private crate collision/0000755000175000017500000000000013254552751024214 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/rust/7 private crate collision/installed_files.txt0000644000175000017500000000004613246615532030114 0ustar jpakkanejpakkane00000000000000usr/bin/prog?exe usr/lib/librand.rlib meson-0.45.1/test cases/rust/7 private crate collision/meson.build0000644000175000017500000000027413254552263026357 0ustar jpakkanejpakkane00000000000000project('rust private crate collision', 'rust') l = static_library('rand', 'rand.rs', install : true) e = executable('prog', 'prog.rs', link_with : l, install : true) test('linktest', e) meson-0.45.1/test cases/rust/7 private crate collision/rand.rs0000644000175000017500000000022213246615532025500 0ustar jpakkanejpakkane00000000000000// use a name that collides with one of the rustc_private libraries #![crate_name = "rand"] pub fn explore() -> &'static str { "librarystring" } meson-0.45.1/test cases/rust/7 private crate collision/prog.rs0000644000175000017500000000011513246615532025524 0ustar jpakkanejpakkane00000000000000extern crate rand; fn main() { println!("printing: {}", rand::explore()); } meson-0.45.1/test cases/rust/1 basic/0000755000175000017500000000000013254552751020562 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/rust/1 basic/installed_files.txt0000644000175000017500000000005113070746245024457 0ustar jpakkanejpakkane00000000000000usr/bin/program?exe usr/bin/program2?exe meson-0.45.1/test cases/rust/1 basic/meson.build0000644000175000017500000000024613254552265022726 0ustar jpakkanejpakkane00000000000000project('rustprog', 'rust') e = executable('program', 'prog.rs', rust_args : ['-C', 'lto'], # Just a test install : true ) test('rusttest', e) subdir('subdir') meson-0.45.1/test cases/rust/1 basic/subdir/0000755000175000017500000000000013254552751022052 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/rust/1 basic/subdir/meson.build0000644000175000017500000000011313070746245024206 0ustar jpakkanejpakkane00000000000000e = executable('program2', 'prog.rs', install : true) test('rusttest2', e) meson-0.45.1/test cases/rust/1 basic/subdir/prog.rs0000644000175000017500000000007013070746245023363 0ustar jpakkanejpakkane00000000000000fn main() { println!("rust compiler is working"); } meson-0.45.1/test cases/rust/1 basic/prog.rs0000644000175000017500000000007012650745767022106 0ustar jpakkanejpakkane00000000000000fn main() { println!("rust compiler is working"); } meson-0.45.1/test cases/rust/5 polyglot static/0000755000175000017500000000000013254552751022626 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/rust/5 polyglot static/installed_files.txt0000644000175000017500000000004413134457406026524 0ustar jpakkanejpakkane00000000000000usr/bin/prog?exe usr/lib/libstuff.a meson-0.45.1/test cases/rust/5 polyglot static/stuff.rs0000644000175000017500000000013713134457406024322 0ustar jpakkanejpakkane00000000000000#![crate_name = "stuff"] #[no_mangle] pub extern fn f() { println!("Hello from Rust!"); } meson-0.45.1/test cases/rust/5 polyglot static/meson.build0000644000175000017500000000052513254552263024770 0ustar jpakkanejpakkane00000000000000project('static rust and c polyglot executable', 'c', 'rust') deps = [ meson.get_compiler('c').find_library('dl'), dependency('threads'), ] l = static_library('stuff', 'stuff.rs', rust_crate_type : 'staticlib', install : true) e = executable('prog', 'prog.c', dependencies: deps, link_with : l, install : true) test('polyglottest', e) meson-0.45.1/test cases/rust/5 polyglot static/prog.c0000644000175000017500000000012613134457406023736 0ustar jpakkanejpakkane00000000000000#include void f(); int main() { printf("Hello from C!\n"); f(); } meson-0.45.1/test cases/rust/6 named staticlib/0000755000175000017500000000000013254552751022531 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/rust/6 named staticlib/installed_files.txt0000644000175000017500000000005513134673730026431 0ustar jpakkanejpakkane00000000000000usr/bin/prog?exe usr/lib/libnamed_stuff.rlib meson-0.45.1/test cases/rust/6 named staticlib/stuff.rs0000644000175000017500000000006513134673730024225 0ustar jpakkanejpakkane00000000000000pub fn explore() -> &'static str { "librarystring" } meson-0.45.1/test cases/rust/6 named staticlib/meson.build0000644000175000017500000000027313254552263024673 0ustar jpakkanejpakkane00000000000000project('rust static library', 'rust') l = static_library('named_stuff', 'stuff.rs', install : true) e = executable('prog', 'prog.rs', link_with : l, install : true) test('linktest', e) meson-0.45.1/test cases/rust/6 named staticlib/prog.rs0000644000175000017500000000013313134673730024041 0ustar jpakkanejpakkane00000000000000extern crate named_stuff; fn main() { println!("printing: {}", named_stuff::explore()); } meson-0.45.1/test cases/rust/4 polyglot/0000755000175000017500000000000013254552751021355 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/rust/4 polyglot/installed_files.txt0000644000175000017500000000004513134457406025254 0ustar jpakkanejpakkane00000000000000usr/bin/prog?exe usr/lib/libstuff.so meson-0.45.1/test cases/rust/4 polyglot/stuff.rs0000644000175000017500000000013713134457406023051 0ustar jpakkanejpakkane00000000000000#![crate_name = "stuff"] #[no_mangle] pub extern fn f() { println!("Hello from Rust!"); } meson-0.45.1/test cases/rust/4 polyglot/meson.build0000644000175000017500000000033413254552253023514 0ustar jpakkanejpakkane00000000000000project('rust and c polyglot executable', 'c', 'rust') l = library('stuff', 'stuff.rs', rust_crate_type: 'cdylib', install : true) e = executable('prog', 'prog.c', link_with : l, install : true) test('polyglottest', e) meson-0.45.1/test cases/rust/4 polyglot/prog.c0000644000175000017500000000012613134457406022465 0ustar jpakkanejpakkane00000000000000#include void f(); int main() { printf("Hello from C!\n"); f(); } meson-0.45.1/test cases/rust/3 staticlib/0000755000175000017500000000000013254552751021461 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/rust/3 staticlib/installed_files.txt0000644000175000017500000000004712742140120025344 0ustar jpakkanejpakkane00000000000000usr/bin/prog?exe usr/lib/libstuff.rlib meson-0.45.1/test cases/rust/3 staticlib/stuff.rs0000644000175000017500000000011712650745767023167 0ustar jpakkanejpakkane00000000000000#![crate_name = "stuff"] pub fn explore() -> &'static str { "librarystring" } meson-0.45.1/test cases/rust/3 staticlib/meson.build0000644000175000017500000000026513254552253023623 0ustar jpakkanejpakkane00000000000000project('rust static library', 'rust') l = static_library('stuff', 'stuff.rs', install : true) e = executable('prog', 'prog.rs', link_with : l, install : true) test('linktest', e) meson-0.45.1/test cases/rust/3 staticlib/prog.rs0000644000175000017500000000011712650745767023007 0ustar jpakkanejpakkane00000000000000extern crate stuff; fn main() { println!("printing: {}", stuff::explore()); } meson-0.45.1/test cases/rust/2 sharedlib/0000755000175000017500000000000013254552751021437 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/rust/2 sharedlib/installed_files.txt0000644000175000017500000000004513134457406025336 0ustar jpakkanejpakkane00000000000000usr/bin/prog?exe usr/lib/libstuff.so meson-0.45.1/test cases/rust/2 sharedlib/stuff.rs0000644000175000017500000000011712650745767023145 0ustar jpakkanejpakkane00000000000000#![crate_name = "stuff"] pub fn explore() -> &'static str { "librarystring" } meson-0.45.1/test cases/rust/2 sharedlib/meson.build0000644000175000017500000000026513254552253023601 0ustar jpakkanejpakkane00000000000000project('rust shared library', 'rust') l = shared_library('stuff', 'stuff.rs', install : true) e = executable('prog', 'prog.rs', link_with : l, install : true) test('linktest', e) meson-0.45.1/test cases/rust/2 sharedlib/prog.rs0000644000175000017500000000011712650745767022765 0ustar jpakkanejpakkane00000000000000extern crate stuff; fn main() { println!("printing: {}", stuff::explore()); } meson-0.45.1/test cases/java/0000755000175000017500000000000013254552745017307 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/java/1 basic/0000755000175000017500000000000013254552750020505 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/java/1 basic/installed_files.txt0000644000175000017500000000002313046167604024401 0ustar jpakkanejpakkane00000000000000usr/bin/myprog.jar meson-0.45.1/test cases/java/1 basic/meson.build0000644000175000017500000000031713254552177022653 0ustar jpakkanejpakkane00000000000000project('simplejava', 'java') javaprog = jar('myprog', 'com/mesonbuild/Simple.java', main_class : 'com.mesonbuild.Simple', install : true, install_dir : get_option('bindir')) test('mytest', javaprog) meson-0.45.1/test cases/java/1 basic/com/0000755000175000017500000000000013254552745021267 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/java/1 basic/com/mesonbuild/0000755000175000017500000000000013254552751023425 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/java/1 basic/com/mesonbuild/Simple.java0000644000175000017500000000022012650745767025525 0ustar jpakkanejpakkane00000000000000package com.mesonbuild; class Simple { public static void main(String [] args) { System.out.println("Java is working.\n"); } } meson-0.45.1/test cases/java/2 subdir/0000755000175000017500000000000013254552751020716 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/java/2 subdir/meson.build0000644000175000017500000000005513254552200023045 0ustar jpakkanejpakkane00000000000000project('subdirjava', 'java') subdir('sub') meson-0.45.1/test cases/java/2 subdir/sub/0000755000175000017500000000000013254552751021507 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/java/2 subdir/sub/meson.build0000644000175000017500000000032312650745767023661 0ustar jpakkanejpakkane00000000000000javaprog = jar('myprog', 'com/mesonbuild/Simple.java', 'com/mesonbuild/TextPrinter.java', main_class : 'com.mesonbuild.Simple', include_directories : include_directories('.')) test('subdirtest', javaprog) meson-0.45.1/test cases/java/2 subdir/sub/com/0000755000175000017500000000000013254552745022270 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/java/2 subdir/sub/com/mesonbuild/0000755000175000017500000000000013254552751024426 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/java/2 subdir/sub/com/mesonbuild/Simple.java0000644000175000017500000000026112650745767026533 0ustar jpakkanejpakkane00000000000000package com.mesonbuild; class Simple { public static void main(String [] args) { TextPrinter t = new TextPrinter("Printing from Java."); t.print(); } } meson-0.45.1/test cases/java/2 subdir/sub/com/mesonbuild/TextPrinter.java0000644000175000017500000000030612650745767027572 0ustar jpakkanejpakkane00000000000000package com.mesonbuild; class TextPrinter { private String msg; TextPrinter(String s) { msg = s; } public void print() { System.out.println(msg); } } meson-0.45.1/test cases/java/3 args/0000755000175000017500000000000013254552751020363 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/java/3 args/meson.build0000644000175000017500000000036613254552200022517 0ustar jpakkanejpakkane00000000000000project('simplejava', 'java') add_project_arguments('-target', '1.6', language : 'java') javaprog = jar('myprog', 'com/mesonbuild/Simple.java', main_class : 'com.mesonbuild.Simple', java_args : ['-source', '1.6']) test('mytest', javaprog) meson-0.45.1/test cases/java/3 args/com/0000755000175000017500000000000013254552745021144 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/java/3 args/com/mesonbuild/0000755000175000017500000000000013254552751023302 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/java/3 args/com/mesonbuild/Simple.java0000644000175000017500000000022013016624375025366 0ustar jpakkanejpakkane00000000000000package com.mesonbuild; class Simple { public static void main(String [] args) { System.out.println("Java is working.\n"); } } meson-0.45.1/test cases/java/4 inner class/0000755000175000017500000000000013254552751021631 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/java/4 inner class/meson.build0000644000175000017500000000022713254552200023761 0ustar jpakkanejpakkane00000000000000project('simplejava', 'java') javaprog = jar('myprog', 'com/mesonbuild/Simple.java', main_class : 'com.mesonbuild.Simple') test('mytest', javaprog) meson-0.45.1/test cases/java/4 inner class/com/0000755000175000017500000000000013254552745022412 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/java/4 inner class/com/mesonbuild/0000755000175000017500000000000013254552751024550 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/java/4 inner class/com/mesonbuild/Simple.java0000644000175000017500000000051313024065327026634 0ustar jpakkanejpakkane00000000000000package com.mesonbuild; class Simple { class Inner { public String getString() { return "Inner class is working.\n"; } } public static void main(String [] args) { Simple s = new Simple(); Simple.Inner ic = s.new Inner(); System.out.println(ic.getString()); } } meson-0.45.1/test cases/failing/0000755000175000017500000000000013254552745017777 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/45 abs subdir/0000755000175000017500000000000013254552750022222 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/45 abs subdir/meson.build0000644000175000017500000000027613102373363024362 0ustar jpakkanejpakkane00000000000000project('abs subdir', 'c') # For some reason people insist on doing this, probably # because Make has taught them to never rely on anything. subdir(join_paths(meson.source_root(), 'bob')) meson-0.45.1/test cases/failing/45 abs subdir/bob/0000755000175000017500000000000013254552750022764 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/45 abs subdir/bob/meson.build0000644000175000017500000000004413102373363025115 0ustar jpakkanejpakkane00000000000000# This file is never reached. x = 3 meson-0.45.1/test cases/failing/30 nested ternary/0000755000175000017500000000000013254552750023125 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/30 nested ternary/meson.build0000644000175000017500000000007712752712447025276 0ustar jpakkanejpakkane00000000000000project('nested ternary', 'c') x = true ? (false ? 1 : 0) : 2 meson-0.45.1/test cases/failing/1 project not first/0000755000175000017500000000000013254552750023453 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/1 project not first/meson.build0000644000175000017500000000016112650745767025626 0ustar jpakkanejpakkane00000000000000var = 'assignment before project() call' project('no worky', 'c') test('not run', executable('prog', 'prog.c')) meson-0.45.1/test cases/failing/1 project not first/prog.c0000644000175000017500000000005612650745767024602 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/failing/21 subver/0000755000175000017500000000000013254552750021504 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/21 subver/subprojects/0000755000175000017500000000000013254552745024053 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/21 subver/subprojects/foo/0000755000175000017500000000000013254552750024632 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/21 subver/subprojects/foo/meson.build0000644000175000017500000000004712650745767027010 0ustar jpakkanejpakkane00000000000000project('foo', 'c', version : '1.0.0') meson-0.45.1/test cases/failing/21 subver/meson.build0000644000175000017500000000010212650745767023652 0ustar jpakkanejpakkane00000000000000project('master', 'c') x = subproject('foo', version : '>1.0.0') meson-0.45.1/test cases/failing/3 missing subdir/0000755000175000017500000000000013254552750023040 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/3 missing subdir/meson.build0000644000175000017500000000005212650745767025212 0ustar jpakkanejpakkane00000000000000project('subdir', 'c') subdir('missing') meson-0.45.1/test cases/failing/59 link with executable/0000755000175000017500000000000013254552750024204 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/59 link with executable/meson.build0000644000175000017500000000016613134457413026346 0ustar jpakkanejpakkane00000000000000project('link with exe', 'c') e = executable('prog', 'prog.c') m = shared_module('module', 'module.c', link_with: e) meson-0.45.1/test cases/failing/59 link with executable/prog.c0000644000175000017500000000006113134457413025311 0ustar jpakkanejpakkane00000000000000int main (int argc, char **argv) { return 0; } meson-0.45.1/test cases/failing/59 link with executable/module.c0000644000175000017500000000004213134457413025626 0ustar jpakkanejpakkane00000000000000 int func(void) { return 42; } meson-0.45.1/test cases/failing/67 dependency not-found and required/0000755000175000017500000000000013254552750026544 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/67 dependency not-found and required/meson.build0000644000175000017500000000007013211772701030674 0ustar jpakkanejpakkane00000000000000project('dep-test') dep = dependency('', required:true) meson-0.45.1/test cases/failing/38 has function external dependency/0000755000175000017500000000000013254552750026471 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/38 has function external dependency/meson.build0000644000175000017500000000040013024065327030617 0ustar jpakkanejpakkane00000000000000project('has function ext dep', 'c') cc = meson.get_compiler('c') mylib = shared_library('mylib', 'mylib.c') mylib_dep = declare_dependency(link_with : mylib) # Only external dependencies can work here cc.has_function('malloc', dependencies : mylib_dep) meson-0.45.1/test cases/failing/38 has function external dependency/mylib.c0000644000175000017500000000004113024065327027736 0ustar jpakkanejpakkane00000000000000int testfunc(void) { return 0; } meson-0.45.1/test cases/failing/27 output subdir/0000755000175000017500000000000013254552750023015 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/27 output subdir/meson.build0000644000175000017500000000017712660161176025162 0ustar jpakkanejpakkane00000000000000project('outdir path', 'c') configure_file(input : 'foo.in', output : 'subdir/foo', configuration : configuration_data()) meson-0.45.1/test cases/failing/27 output subdir/subdir/0000755000175000017500000000000013254552750024305 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/27 output subdir/subdir/dummy.txt0000644000175000017500000000006712660161176026202 0ustar jpakkanejpakkane00000000000000I'm only here because Git is stupid about empty dirs. meson-0.45.1/test cases/failing/27 output subdir/foo.in0000644000175000017500000000001612660161176024123 0ustar jpakkanejpakkane00000000000000Nothing here. meson-0.45.1/test cases/failing/69 wrong boost module/0000755000175000017500000000000013254552750023723 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/69 wrong boost module/meson.build0000644000175000017500000000024513220442136026053 0ustar jpakkanejpakkane00000000000000project('boosttest', 'cpp', default_options : ['cpp_std=c++11']) # abc doesn't exist linkdep = dependency('boost', modules : ['thread', 'system', 'test', 'abc']) meson-0.45.1/test cases/failing/14 invalid option name/0000755000175000017500000000000013254552750024020 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/14 invalid option name/meson.build0000644000175000017500000000002412650745767026171 0ustar jpakkanejpakkane00000000000000project('foo', 'c') meson-0.45.1/test cases/failing/14 invalid option name/meson_options.txt0000644000175000017500000000007013074426732027452 0ustar jpakkanejpakkane00000000000000option('invalid:name', type : 'boolean', value : false) meson-0.45.1/test cases/failing/7 go to subproject/0000755000175000017500000000000013254552750023273 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/7 go to subproject/subprojects/0000755000175000017500000000000013254552750025636 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/7 go to subproject/subprojects/meson.build0000644000175000017500000000001012650745767030002 0ustar jpakkanejpakkane00000000000000x = 'x' meson-0.45.1/test cases/failing/7 go to subproject/meson.build0000644000175000017500000000005312650745767025446 0ustar jpakkanejpakkane00000000000000project('fff', 'c') subdir('subprojects') meson-0.45.1/test cases/failing/31 invalid man extension/0000755000175000017500000000000013254552750024356 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/31 invalid man extension/meson.build0000644000175000017500000000006712763077471026531 0ustar jpakkanejpakkane00000000000000project('man install', 'c') m1 = install_man('foo.a1') meson-0.45.1/test cases/failing/37 pkgconfig dependency impossible conditions/0000755000175000017500000000000013254552750030534 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/37 pkgconfig dependency impossible conditions/meson.build0000644000175000017500000000014613024065327032671 0ustar jpakkanejpakkane00000000000000project('impossible-dep-test', 'c', version : '1.0') dependency('zlib', version : ['>=1.0', '<1.0']) meson-0.45.1/test cases/failing/13 array arithmetic/0000755000175000017500000000000013254552750023427 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/13 array arithmetic/meson.build0000644000175000017500000000006712650745767025607 0ustar jpakkanejpakkane00000000000000project('array arithmetic', 'c') foo = ['a', 'b'] * 3 meson-0.45.1/test cases/failing/26 badlang/0000755000175000017500000000000013254552750021573 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/26 badlang/meson.build0000644000175000017500000000006612653573126023741 0ustar jpakkanejpakkane00000000000000project('badlang', 'c') add_languages('nonexisting') meson-0.45.1/test cases/failing/20 version/0000755000175000017500000000000013254552750021662 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/20 version/meson.build0000644000175000017500000000007512650745767024041 0ustar jpakkanejpakkane00000000000000project('version mismatch', 'c', meson_version : '>100.0.0') meson-0.45.1/test cases/failing/54 reserved meson prefix/0000755000175000017500000000000013254552750024403 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/54 reserved meson prefix/meson-foo/0000755000175000017500000000000013254552750026305 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/54 reserved meson prefix/meson-foo/meson.build0000644000175000017500000000000013113247026030424 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/54 reserved meson prefix/meson.build0000644000175000017500000000004513113247026026533 0ustar jpakkanejpakkane00000000000000project('test') subdir('meson-foo') meson-0.45.1/test cases/failing/19 target clash/0000755000175000017500000000000013254552750022546 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/19 target clash/clash.c0000644000175000017500000000013712650745767024020 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("Clash 2.\n"); return 0; } meson-0.45.1/test cases/failing/19 target clash/meson.build0000644000175000017500000000075213074426732024714 0ustar jpakkanejpakkane00000000000000project('clash', 'c') # This setup causes a namespace clash when two Meson targets would # produce a Ninja targets with the same name. It only works on # unix, because on Windows the target has a '.exe' suffix. # # This test might fail to work on different backends or when # output location is redirected. if host_machine.system() == 'windows' or host_machine.system() == 'cygwin' error('This is expected.') endif executable('clash', 'clash.c') run_target('clash', 'echo', 'clash 1') meson-0.45.1/test cases/failing/32 no man extension/0000755000175000017500000000000013254552750023345 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/32 no man extension/meson.build0000644000175000017500000000006412763077471025515 0ustar jpakkanejpakkane00000000000000project('man install', 'c') m1 = install_man('foo') meson-0.45.1/test cases/failing/10 out of bounds/0000755000175000017500000000000013254552750022643 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/10 out of bounds/meson.build0000644000175000017500000000005712650745767025022 0ustar jpakkanejpakkane00000000000000project('out of bounds', 'c') x = [] y = x[0] meson-0.45.1/test cases/failing/6 missing incdir/0000755000175000017500000000000013254552750023023 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/6 missing incdir/meson.build0000644000175000017500000000010712650745767025176 0ustar jpakkanejpakkane00000000000000project('missing incdir', 'c') inc = include_directories('nosuchdir') meson-0.45.1/test cases/failing/18 wrong plusassign/0000755000175000017500000000000013254552750023511 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/18 wrong plusassign/meson.build0000644000175000017500000000005112650745767025662 0ustar jpakkanejpakkane00000000000000project('false plusassign', 'c') 3 += 4 meson-0.45.1/test cases/failing/43 custom target outputs not matching install_dirs/0000755000175000017500000000000013254552750031473 5ustar jpakkanejpakkane00000000000000././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000meson-0.45.1/test cases/failing/43 custom target outputs not matching install_dirs/installed_files.txtmeson-0.45.1/test cases/failing/43 custom target outputs not matching install_dirs/installed_files.t0000644000175000017500000000014013074426732035014 0ustar jpakkanejpakkane00000000000000usr/include/diff.h usr/include/first.h usr/bin/diff.sh usr/bin/second.sh opt/same.h opt/same.sh meson-0.45.1/test cases/failing/43 custom target outputs not matching install_dirs/meson.build0000644000175000017500000000064413074426732033641 0ustar jpakkanejpakkane00000000000000project('outputs not matching install_dirs', 'c') gen = find_program('generator.py') if meson.backend() != 'ninja' error('Failing manually, test is only for the ninja backend') endif custom_target('too-few-install-dirs', output : ['toofew.h', 'toofew.c', 'toofew.sh'], command : [gen, 'toofew', '@OUTDIR@'], install : true, install_dir : [join_paths(get_option('prefix'), get_option('includedir')), false]) meson-0.45.1/test cases/failing/43 custom target outputs not matching install_dirs/generator.py0000755000175000017500000000066613074426732034046 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys, os if len(sys.argv) != 3: print(sys.argv[0], '', '') name = sys.argv[1] odir = sys.argv[2] with open(os.path.join(odir, name + '.h'), 'w') as f: f.write('int func();\n') with open(os.path.join(odir, name + '.c'), 'w') as f: f.write('int main(int argc, char *argv[]) { return 0; }') with open(os.path.join(odir, name + '.sh'), 'w') as f: f.write('#!/bin/bash') meson-0.45.1/test cases/failing/62 bad option argument/0000755000175000017500000000000013254552750024025 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/62 bad option argument/meson.build0000644000175000017500000000005213174155420026156 0ustar jpakkanejpakkane00000000000000project('bad option') get_option('name') meson-0.45.1/test cases/failing/62 bad option argument/meson_options.txt0000644000175000017500000000005713174155420027456 0ustar jpakkanejpakkane00000000000000option('name', type : 'string', vaule : 'foo') meson-0.45.1/test cases/failing/52 inconsistent comparison/0000755000175000017500000000000013254552750025055 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/52 inconsistent comparison/meson.build0000644000175000017500000000035313110002662027177 0ustar jpakkanejpakkane00000000000000project('kwarg before arg', 'c') # All of these should fail, though only the first one will error out if # everything's working correctly. assert([] < 'st', 'should fail') assert([] < 1, 'should fail') assert(2 < 'st', 'should fail') meson-0.45.1/test cases/failing/36 project argument after target/0000755000175000017500000000000013254552750026006 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/36 project argument after target/meson.build0000644000175000017500000000036713016624375030155 0ustar jpakkanejpakkane00000000000000project('project argument after target failing', 'c', version : '2.3.4', license : 'mylicense') add_project_arguments('-DPROJECT_OPTION', language: 'c') e = executable('exe', 'exe.c') add_project_arguments('-DPROJECT_OPTION1', language: 'c') meson-0.45.1/test cases/failing/36 project argument after target/exe.c0000644000175000017500000000006213016624375026730 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/failing/23 rel testdir/0000755000175000017500000000000013254552750022421 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/23 rel testdir/simple.c0000644000175000017500000000006212650745767024067 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/failing/23 rel testdir/meson.build0000644000175000017500000000015212650745767024574 0ustar jpakkanejpakkane00000000000000project('nonabs workdir', 'c') exe = executable('simple', 'simple.c') test('simple', exe, workdir : '.') meson-0.45.1/test cases/failing/35 dependency not-required then required/0000755000175000017500000000000013254552750027440 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/35 dependency not-required then required/meson.build0000644000175000017500000000021713016624375031601 0ustar jpakkanejpakkane00000000000000project('dep-test', 'c', version : '1.0') foo_dep = dependency('foo-bar-xyz-12.3', required : false) bar_dep = dependency('foo-bar-xyz-12.3') meson-0.45.1/test cases/failing/15 kwarg before arg/0000755000175000017500000000000013254552750023271 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/15 kwarg before arg/meson.build0000644000175000017500000000011112650745767025437 0ustar jpakkanejpakkane00000000000000project('kwarg before arg', 'c') executable(sources : 'prog.c', 'prog') meson-0.45.1/test cases/failing/15 kwarg before arg/prog.c0000644000175000017500000000005612650745767024420 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/failing/28 noprog use/0000755000175000017500000000000013254552750022266 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/28 noprog use/meson.build0000644000175000017500000000030712674573632024437 0ustar jpakkanejpakkane00000000000000project('using not found exe', 'c') nope = find_program('nonexisting', required : false) custom_target( 'aa', input: 'meson.build', output: 'foobar', command: [nope, '@INPUT@', '@OUTPUT@'] ) meson-0.45.1/test cases/failing/57 or on new line/0000755000175000017500000000000013254552750022706 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/57 or on new line/meson.build0000644000175000017500000000033413134457406025047 0ustar jpakkanejpakkane00000000000000project('silent_or', 'c') if get_option('foo') == 'true' or get_option('foo') == 'auto' else message('If this message is printed then something is wrong. The or above should give a syntax error.') endif meson-0.45.1/test cases/failing/57 or on new line/meson_options.txt0000644000175000017500000000012013134457406026333 0ustar jpakkanejpakkane00000000000000option('foo', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto') meson-0.45.1/test cases/failing/50 pkgconfig variables not key value/0000755000175000017500000000000013254552750026527 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/50 pkgconfig variables not key value/simple.c0000644000175000017500000000007513104701646030160 0ustar jpakkanejpakkane00000000000000#include"simple.h" int simple_function() { return 42; } meson-0.45.1/test cases/failing/50 pkgconfig variables not key value/meson.build0000644000175000017500000000061313104701646030663 0ustar jpakkanejpakkane00000000000000project('variables-not-key-value-test', 'c', version : '1.0') pkgg = import('pkgconfig') lib = shared_library('simple', 'simple.c') libver = '1.0' h = install_headers('simple.h') pkgg.generate( libraries : [lib, '-lz'], subdirs : '.', version : libver, name : 'libsimple', filebase : 'simple', description : 'A simple demo library.', variables : [ 'this_should_be_key_value' ] ) meson-0.45.1/test cases/failing/50 pkgconfig variables not key value/simple.h0000644000175000017500000000010413104701646030156 0ustar jpakkanejpakkane00000000000000#ifndef SIMPLE_H_ #define SIMPLE_H_ int simple_function(); #endif meson-0.45.1/test cases/failing/42 custom target plainname many inputs/0000755000175000017500000000000013254552750027137 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/42 custom target plainname many inputs/meson.build0000644000175000017500000000033513055371477031306 0ustar jpakkanejpakkane00000000000000project('plain name many inputs', 'c') catfiles = find_program('catfiles.py') custom_target('plainname-inputs', input : ['1.txt', '2.txt'], output : '@PLAINNAME@.dat', command : [catfiles, '@INPUT@', '@OUTPUT@']) meson-0.45.1/test cases/failing/42 custom target plainname many inputs/1.txt0000644000175000017500000000000213055371477030034 0ustar jpakkanejpakkane000000000000001 meson-0.45.1/test cases/failing/42 custom target plainname many inputs/catfiles.py0000644000175000017500000000027013055371477031306 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 import sys out = sys.argv[-1] with open(out, 'wb') as o: for infile in sys.argv[1:-1]: with open(infile, 'rb') as f: o.write(f.read()) meson-0.45.1/test cases/failing/42 custom target plainname many inputs/2.txt0000644000175000017500000000000213055371477030035 0ustar jpakkanejpakkane000000000000002 meson-0.45.1/test cases/failing/47 pkgconfig variables reserved/0000755000175000017500000000000013254552750025706 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/47 pkgconfig variables reserved/simple.c0000644000175000017500000000007513104701646027337 0ustar jpakkanejpakkane00000000000000#include"simple.h" int simple_function() { return 42; } meson-0.45.1/test cases/failing/47 pkgconfig variables reserved/meson.build0000644000175000017500000000057213104701646030046 0ustar jpakkanejpakkane00000000000000project('variables-reserved-test', 'c', version : '1.0') pkgg = import('pkgconfig') lib = shared_library('simple', 'simple.c') libver = '1.0' h = install_headers('simple.h') pkgg.generate( libraries : [lib, '-lz'], subdirs : '.', version : libver, name : 'libsimple', filebase : 'simple', description : 'A simple demo library.', variables : [ 'prefix=/tmp/' ] ) meson-0.45.1/test cases/failing/47 pkgconfig variables reserved/simple.h0000644000175000017500000000010413104701646027335 0ustar jpakkanejpakkane00000000000000#ifndef SIMPLE_H_ #define SIMPLE_H_ int simple_function(); #endif meson-0.45.1/test cases/failing/49 pkgconfig variables zero length value/0000755000175000017500000000000013254552750027407 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/49 pkgconfig variables zero length value/simple.c0000644000175000017500000000007513104701646031040 0ustar jpakkanejpakkane00000000000000#include"simple.h" int simple_function() { return 42; } meson-0.45.1/test cases/failing/49 pkgconfig variables zero length value/meson.build0000644000175000017500000000057313104701646031550 0ustar jpakkanejpakkane00000000000000project('variables-zero-length-value-test', 'c', version : '1.0') pkgg = import('pkgconfig') lib = shared_library('simple', 'simple.c') libver = '1.0' h = install_headers('simple.h') pkgg.generate( libraries : [lib, '-lz'], subdirs : '.', version : libver, name : 'libsimple', filebase : 'simple', description : 'A simple demo library.', variables : [ 'key=' ] ) meson-0.45.1/test cases/failing/49 pkgconfig variables zero length value/simple.h0000644000175000017500000000010413104701646031036 0ustar jpakkanejpakkane00000000000000#ifndef SIMPLE_H_ #define SIMPLE_H_ int simple_function(); #endif meson-0.45.1/test cases/failing/11 object arithmetic/0000755000175000017500000000000013254552750023555 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/11 object arithmetic/meson.build0000644000175000017500000000006512650745767025733 0ustar jpakkanejpakkane00000000000000project('object arithmetic', 'c') foo = '5' + meson meson-0.45.1/test cases/failing/55 wrong shared crate type/0000755000175000017500000000000013254552750024611 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/55 wrong shared crate type/foo.rs0000644000175000017500000000000013134457406025727 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/55 wrong shared crate type/meson.build0000644000175000017500000000013113134457406026745 0ustar jpakkanejpakkane00000000000000project('test', 'rust') shared_library('test', 'foo.rs', rust_crate_type : 'staticlib') meson-0.45.1/test cases/failing/44 project name colon/0000755000175000017500000000000013254552750023645 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/44 project name colon/meson.build0000644000175000017500000000002713076164167026011 0ustar jpakkanejpakkane00000000000000project('name with :') meson-0.45.1/test cases/failing/16 extract from subproject/0000755000175000017500000000000013254552750024741 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/16 extract from subproject/main.c0000644000175000017500000000011612650745767026042 0ustar jpakkanejpakkane00000000000000int sub_lib_method(void); int main() { return 1337 - sub_lib_method(); } meson-0.45.1/test cases/failing/16 extract from subproject/subprojects/0000755000175000017500000000000013254552745027310 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/16 extract from subproject/subprojects/sub_project/0000755000175000017500000000000013254552750031623 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/16 extract from subproject/subprojects/sub_project/sub_lib.c0000644000175000017500000000005212650745767033416 0ustar jpakkanejpakkane00000000000000int sub_lib_method() { return 1337; } meson-0.45.1/test cases/failing/16 extract from subproject/subprojects/sub_project/meson.build0000644000175000017500000000014612650745767034001 0ustar jpakkanejpakkane00000000000000project('extract subproject object -- subproject', 'c') lib = shared_library('sub_lib', 'sub_lib.c') meson-0.45.1/test cases/failing/16 extract from subproject/meson.build0000644000175000017500000000033012650745767027112 0ustar jpakkanejpakkane00000000000000project('extract subproject object', 'c') sub = subproject('sub_project') lib = sub.get_variable('lib') exe = executable('exe', 'main.c', objects : lib.extract_objects('sub_lib.c')) test('extraction test', exe) meson-0.45.1/test cases/failing/22 assert/0000755000175000017500000000000013254552750021500 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/22 assert/meson.build0000644000175000017500000000007412650745767023656 0ustar jpakkanejpakkane00000000000000project('failing assert', 'c') assert(false, 'I am fail.') meson-0.45.1/test cases/failing/65 grab sibling/0000755000175000017500000000000013254552750022531 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/65 grab sibling/subprojects/0000755000175000017500000000000013254552745025100 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/65 grab sibling/subprojects/a/0000755000175000017500000000000013254552750025314 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/65 grab sibling/subprojects/a/meson.build0000644000175000017500000000007113174155432027451 0ustar jpakkanejpakkane00000000000000project('a', 'c') executable('sneaky', '../b/sneaky.c') meson-0.45.1/test cases/failing/65 grab sibling/subprojects/b/0000755000175000017500000000000013254552750025315 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/65 grab sibling/subprojects/b/meson.build0000644000175000017500000000005413174155432027453 0ustar jpakkanejpakkane00000000000000projecT('b', 'c') message('I do nothing.') meson-0.45.1/test cases/failing/65 grab sibling/subprojects/b/sneaky.c0000644000175000017500000000020313206650111026731 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("I can only come into existence via trickery.\n"); return 0; } meson-0.45.1/test cases/failing/65 grab sibling/meson.build0000644000175000017500000000005013174155432024663 0ustar jpakkanejpakkane00000000000000project('master', 'c') subproject('a') meson-0.45.1/test cases/failing/56 wrong static crate type/0000755000175000017500000000000013254552750024633 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/56 wrong static crate type/foo.rs0000644000175000017500000000000013134457406025751 0ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/56 wrong static crate type/meson.build0000644000175000017500000000012613134457406026773 0ustar jpakkanejpakkane00000000000000project('test', 'rust') static_library('test', 'foo.rs', rust_crate_type : 'cdylib') meson-0.45.1/test cases/failing/12 string arithmetic/0000755000175000017500000000000013254552750023616 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/12 string arithmetic/meson.build0000644000175000017500000000006112650745767025770 0ustar jpakkanejpakkane00000000000000project('string arithmetic', 'c') foo = 'a' + 3 meson-0.45.1/test cases/failing/58 kwarg in module/0000755000175000017500000000000013254552750023160 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/58 kwarg in module/meson.build0000644000175000017500000000015413134457406025321 0ustar jpakkanejpakkane00000000000000project('module test', 'c') modtest = import('modtest', i_cause: 'a_build_failure') modtest.print_hello() meson-0.45.1/test cases/failing/40 prefix absolute/0000755000175000017500000000000013254552750023273 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/40 prefix absolute/meson.build0000644000175000017500000000011413043224360025416 0ustar jpakkanejpakkane00000000000000project('prefix-abs', 'c', default_options : ['prefix=some/path/notabs']) meson-0.45.1/test cases/failing/34 non-root subproject/0000755000175000017500000000000013254552750024116 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/34 non-root subproject/meson.build0000644000175000017500000000006413012152443026243 0ustar jpakkanejpakkane00000000000000project('non-root subproject', 'c') subdir('some') meson-0.45.1/test cases/failing/34 non-root subproject/some/0000755000175000017500000000000013254552750025061 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/34 non-root subproject/some/meson.build0000644000175000017500000000011313012152443027201 0ustar jpakkanejpakkane00000000000000dependency('definitely-doesnt-exist', fallback : ['someproj', 'some_dep']) meson-0.45.1/test cases/failing/51 executable comparison/0000755000175000017500000000000013254552750024455 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/51 executable comparison/meson.build0000644000175000017500000000025113110002662026574 0ustar jpakkanejpakkane00000000000000project('executable comparison', 'c') exe1 = executable('prog1', sources : 'prog.c') exe2 = executable('prog2', sources : 'prog.c') assert(exe1 < exe2, 'should fail') meson-0.45.1/test cases/failing/51 executable comparison/prog.c0000644000175000017500000000005613110002662025550 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/failing/48 pkgconfig variables zero length/0000755000175000017500000000000013254552750026311 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/48 pkgconfig variables zero length/simple.c0000644000175000017500000000007513104701646027742 0ustar jpakkanejpakkane00000000000000#include"simple.h" int simple_function() { return 42; } meson-0.45.1/test cases/failing/48 pkgconfig variables zero length/meson.build0000644000175000017500000000056713104701646030455 0ustar jpakkanejpakkane00000000000000project('variables-zero-length-test', 'c', version : '1.0') pkgg = import('pkgconfig') lib = shared_library('simple', 'simple.c') libver = '1.0' h = install_headers('simple.h') pkgg.generate( libraries : [lib, '-lz'], subdirs : '.', version : libver, name : 'libsimple', filebase : 'simple', description : 'A simple demo library.', variables : [ '=value' ] ) meson-0.45.1/test cases/failing/48 pkgconfig variables zero length/simple.h0000644000175000017500000000010413104701646027740 0ustar jpakkanejpakkane00000000000000#ifndef SIMPLE_H_ #define SIMPLE_H_ int simple_function(); #endif meson-0.45.1/test cases/failing/60 assign custom target index/0000755000175000017500000000000013254552750025317 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/60 assign custom target index/meson.build0000644000175000017500000000151413174155420027454 0ustar jpakkanejpakkane00000000000000# Copyright Ā© 2017 Intel Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # 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. prog_python = import('python3').find_python() target = custom_target( 'target', output : ['1', '2'], command : [prog_python, '-c', 'with open("1", "w") as f: f.write("foo"); with open("2", "w") as f: f.write("foo")'], ) target[0] = 'foo' meson-0.45.1/test cases/failing/64 grab subproj/0000755000175000017500000000000013254552750022565 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/64 grab subproj/subprojects/0000755000175000017500000000000013254552745025134 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/64 grab subproj/subprojects/foo/0000755000175000017500000000000013254552750025713 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/64 grab subproj/subprojects/foo/sub.c0000644000175000017500000000017113174155432026644 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("I am a subproject executable file.\n"); return 0; } meson-0.45.1/test cases/failing/64 grab subproj/subprojects/foo/meson.build0000644000175000017500000000005613174155432030053 0ustar jpakkanejpakkane00000000000000project('foo', 'c') message('I do nothing.') meson-0.45.1/test cases/failing/64 grab subproj/meson.build0000644000175000017500000000020613174155432024722 0ustar jpakkanejpakkane00000000000000project('grabber', 'c') # Try to grab a file from a child subproject. subproject('foo') executable('foo', 'subprojects/foo/sub.c') meson-0.45.1/test cases/failing/5 misplaced option/0000755000175000017500000000000013254552750023352 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/5 misplaced option/meson.build0000644000175000017500000000010312650745767025521 0ustar jpakkanejpakkane00000000000000project('misplaced option', 'c') option('dummy', type : 'string') meson-0.45.1/test cases/failing/8 recursive/0000755000175000017500000000000013254552750022132 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/8 recursive/subprojects/0000755000175000017500000000000013254552745024501 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/8 recursive/subprojects/a/0000755000175000017500000000000013254552750024715 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/8 recursive/subprojects/a/meson.build0000644000175000017500000000004712650745767027073 0ustar jpakkanejpakkane00000000000000project('a', 'c') b = subproject('b') meson-0.45.1/test cases/failing/8 recursive/subprojects/b/0000755000175000017500000000000013254552750024716 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/8 recursive/subprojects/b/meson.build0000644000175000017500000000004712650745767027074 0ustar jpakkanejpakkane00000000000000project('b', 'c') a = subproject('a') meson-0.45.1/test cases/failing/8 recursive/meson.build0000644000175000017500000000005712650745767024311 0ustar jpakkanejpakkane00000000000000project('recursive', 'c') a = subproject('a') meson-0.45.1/test cases/failing/29 no crossprop/0000755000175000017500000000000013254552750022635 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/29 no crossprop/meson.build0000644000175000017500000000011712740763357025004 0ustar jpakkanejpakkane00000000000000project('no crossprop', 'c') message(meson.get_cross_property('nonexisting')) meson-0.45.1/test cases/failing/68 subproj different versions/0000755000175000017500000000000013254552750025455 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/68 subproj different versions/main.c0000644000175000017500000000024013243342167026536 0ustar jpakkanejpakkane00000000000000#include #include "a.h" #include "b.h" int main(int argc, char **argv) { int life = a_fun() + b_fun(); printf("%d\n", life); return 0; } meson-0.45.1/test cases/failing/68 subproj different versions/subprojects/0000755000175000017500000000000013254552745030024 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/68 subproj different versions/subprojects/a/0000755000175000017500000000000013254552750030240 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/68 subproj different versions/subprojects/a/meson.build0000644000175000017500000000035013243342167032375 0ustar jpakkanejpakkane00000000000000project('a', 'c') c_dep = dependency('c', version:'1', fallback: ['c', 'c_dep']) alib = library('a', 'a.c', dependencies: c_dep) a_dep = declare_dependency( link_with: alib, include_directories: include_directories('.'), ) meson-0.45.1/test cases/failing/68 subproj different versions/subprojects/a/a.c0000644000175000017500000000006413243342167030621 0ustar jpakkanejpakkane00000000000000#include "c.h" int a_fun() { return c_fun(); } meson-0.45.1/test cases/failing/68 subproj different versions/subprojects/a/a.h0000644000175000017500000000001513243342167030622 0ustar jpakkanejpakkane00000000000000int a_fun(); meson-0.45.1/test cases/failing/68 subproj different versions/subprojects/c/0000755000175000017500000000000013254552750030242 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/68 subproj different versions/subprojects/c/meson.build0000644000175000017500000000015613243342167032403 0ustar jpakkanejpakkane00000000000000project('c', 'c', version:'1') c_dep = declare_dependency( include_directories: include_directories('.') ) meson-0.45.1/test cases/failing/68 subproj different versions/subprojects/c/c.h0000644000175000017500000000004413243342167030630 0ustar jpakkanejpakkane00000000000000static int c_fun(){ return 3; } meson-0.45.1/test cases/failing/68 subproj different versions/subprojects/b/0000755000175000017500000000000013254552750030241 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/68 subproj different versions/subprojects/b/b.h0000644000175000017500000000001513243342167030624 0ustar jpakkanejpakkane00000000000000int b_fun(); meson-0.45.1/test cases/failing/68 subproj different versions/subprojects/b/meson.build0000644000175000017500000000035013243342167032376 0ustar jpakkanejpakkane00000000000000project('b', 'c') c_dep = dependency('c', version:'2', fallback: ['c', 'c_dep']) blib = library('b', 'b.c', dependencies: c_dep) b_dep = declare_dependency( link_with: blib, include_directories: include_directories('.'), ) meson-0.45.1/test cases/failing/68 subproj different versions/subprojects/b/b.c0000644000175000017500000000005713243342167030625 0ustar jpakkanejpakkane00000000000000#include "c.h" int b_fun(){ return c_fun(); } meson-0.45.1/test cases/failing/68 subproj different versions/meson.build0000644000175000017500000000042313243342167027613 0ustar jpakkanejpakkane00000000000000project('super', 'c') # A will use version 1 of C a_dep = dependency('a', fallback: ['a', 'a_dep']) # B will fail because it requests version 2 of C b_dep = dependency('b', fallback: ['b', 'b_dep']) main = executable('main', files('main.c'), dependencies: [a_dep, b_dep]) meson-0.45.1/test cases/failing/17 same name/0000755000175000017500000000000013254552750022031 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/17 same name/meson.build0000644000175000017500000000011112650745767024177 0ustar jpakkanejpakkane00000000000000project('same name', 'c') static_library('foo', 'file.c') subdir('sub') meson-0.45.1/test cases/failing/17 same name/file.c0000644000175000017500000000003512650745767023125 0ustar jpakkanejpakkane00000000000000int func() { return 0; } meson-0.45.1/test cases/failing/17 same name/sub/0000755000175000017500000000000013254552750022622 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/17 same name/sub/meson.build0000644000175000017500000000004112650745767024772 0ustar jpakkanejpakkane00000000000000static_library('foo', 'file2.c') meson-0.45.1/test cases/failing/17 same name/sub/file2.c0000644000175000017500000000003512650745767024000 0ustar jpakkanejpakkane00000000000000int func() { return 5; } meson-0.45.1/test cases/failing/4 missing meson.build/0000755000175000017500000000000013254552750023770 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/4 missing meson.build/meson.build0000644000175000017500000000006612650745767026147 0ustar jpakkanejpakkane00000000000000project('missing meson.build', 'c') subdir('subdir') meson-0.45.1/test cases/failing/4 missing meson.build/subdir/0000755000175000017500000000000013254552750025260 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/4 missing meson.build/subdir/dummy.txt0000644000175000017500000000007312650745767027167 0ustar jpakkanejpakkane00000000000000This needs to be here because Git can't handle empty dirs. meson-0.45.1/test cases/failing/41 kwarg assign/0000755000175000017500000000000013254552750022560 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/41 kwarg assign/meson.build0000644000175000017500000000012113043224360024701 0ustar jpakkanejpakkane00000000000000project('assign in kwarg', 'c') executable('prog', 'dummy.c', args = 'prog.c') meson-0.45.1/test cases/failing/41 kwarg assign/dummy.c0000644000175000017500000000006413043224360024044 0ustar jpakkanejpakkane00000000000000const char* dummy() { return "I do nothing."; } meson-0.45.1/test cases/failing/41 kwarg assign/prog.c0000644000175000017500000000006213043224360023656 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/failing/33 exe static shared/0000755000175000017500000000000013254552750023461 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/33 exe static shared/meson.build0000644000175000017500000000055613001212425025607 0ustar jpakkanejpakkane00000000000000project('statchain', 'c') host_system = host_machine.system() if host_system == 'windows' or host_system == 'darwin' error('Test only fails on Linux and BSD') endif statlib = static_library('stat', 'stat.c', pic : false) shlib2 = shared_library('shr2', 'shlib2.c', link_with : statlib) exe = executable('prog', 'prog.c', link_with : shlib2) test('runtest', exe) meson-0.45.1/test cases/failing/33 exe static shared/stat.c0000644000175000017500000000004513001212425024555 0ustar jpakkanejpakkane00000000000000int statlibfunc() { return 42; } meson-0.45.1/test cases/failing/33 exe static shared/prog.c0000644000175000017500000000026513001212425024555 0ustar jpakkanejpakkane00000000000000int shlibfunc2(); int statlibfunc(); int main(int argc, char **argv) { if (statlibfunc() != 42) return 1; if (shlibfunc2() != 24) return 1; return 0; } meson-0.45.1/test cases/failing/33 exe static shared/shlib2.c0000644000175000017500000000056013001212425024767 0ustar jpakkanejpakkane00000000000000#if defined _WIN32 || defined __CYGWIN__ #define DLL_PUBLIC __declspec(dllexport) #else #if defined __GNUC__ #define DLL_PUBLIC __attribute__ ((visibility("default"))) #else #pragma message ("Compiler does not support symbol visibility.") #define DLL_PUBLIC #endif #endif int statlibfunc(void); int DLL_PUBLIC shlibfunc2(void) { return 24; } meson-0.45.1/test cases/failing/2 missing file/0000755000175000017500000000000013254552750022466 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/2 missing file/meson.build0000644000175000017500000000007612650745767024646 0ustar jpakkanejpakkane00000000000000project('missing file', 'c') executable('prog', 'missing.c') meson-0.45.1/test cases/failing/9 missing extra file/0000755000175000017500000000000013254552750023601 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/9 missing extra file/meson.build0000644000175000017500000000014012650745767025751 0ustar jpakkanejpakkane00000000000000project('missing extra file', 'c') executable('myprog', 'prog.c', extra_files : 'missing.txt') meson-0.45.1/test cases/failing/9 missing extra file/prog.c0000644000175000017500000000006212650745767024725 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/failing/66 string as link target/0000755000175000017500000000000013254552750024266 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/66 string as link target/meson.build0000644000175000017500000000013213175453711026423 0ustar jpakkanejpakkane00000000000000project('string as link argument', 'c') executable('myprog', 'prog.c', link_with: [ '' ]) meson-0.45.1/test cases/failing/66 string as link target/prog.c0000644000175000017500000000005613175453711025401 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/failing/61 getoption prefix/0000755000175000017500000000000013254552750023470 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/61 getoption prefix/subprojects/0000755000175000017500000000000013254552745026037 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/61 getoption prefix/subprojects/abc/0000755000175000017500000000000013254552750026560 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/61 getoption prefix/subprojects/abc/meson.build0000644000175000017500000000002413174155420030710 0ustar jpakkanejpakkane00000000000000project('abc', 'c') meson-0.45.1/test cases/failing/61 getoption prefix/subprojects/abc/meson_options.txt0000644000175000017500000000004013174155420032201 0ustar jpakkanejpakkane00000000000000option('foo', type : 'boolean') meson-0.45.1/test cases/failing/61 getoption prefix/meson.build0000644000175000017500000000010313174155420025616 0ustar jpakkanejpakkane00000000000000project('getopt prefix') subproject('abc') get_option('abc:foo') meson-0.45.1/test cases/failing/53 slashname/0000755000175000017500000000000013254552750022156 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/53 slashname/meson.build0000644000175000017500000000050313112126250024277 0ustar jpakkanejpakkane00000000000000project('slashname', 'c') # Traverse this subdir so the corresponding dir # is created inside the build dir. subdir('sub') # Try to create an executable that would go in the "sub" dir # inside the build dir. This is prohibited. executable('sub/prog', pf) error('Re-enable me once slash in name is finally prohibited.') meson-0.45.1/test cases/failing/53 slashname/sub/0000755000175000017500000000000013254552750022747 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/53 slashname/sub/meson.build0000644000175000017500000000002613112126250025070 0ustar jpakkanejpakkane00000000000000pf = files('prog.c') meson-0.45.1/test cases/failing/53 slashname/sub/prog.c0000644000175000017500000000016013112126250024040 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { printf("I should not be run ever.\n"); return 1; } meson-0.45.1/test cases/failing/25 int conversion/0000755000175000017500000000000013254552750023142 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/25 int conversion/meson.build0000644000175000017500000000006612653573126025310 0ustar jpakkanejpakkane00000000000000project('int conversion', 'c') 'notanumber'.to_int() meson-0.45.1/test cases/failing/39 libdir must be inside prefix/0000755000175000017500000000000013254552750025506 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/39 libdir must be inside prefix/meson.build0000644000175000017500000000010713043224360027633 0ustar jpakkanejpakkane00000000000000project('libdir prefix', 'c', default_options : ['libdir=/opt/lib']) meson-0.45.1/test cases/failing/46 abspath to srcdir/0000755000175000017500000000000013254552750023501 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/46 abspath to srcdir/meson.build0000644000175000017500000000010713102373363025632 0ustar jpakkanejpakkane00000000000000project('meson', 'c') include_directories(meson.current_source_dir()) meson-0.45.1/test cases/failing/63 subproj filegrab/0000755000175000017500000000000013254552750023424 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/63 subproj filegrab/subprojects/0000755000175000017500000000000013254552745025773 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/63 subproj filegrab/subprojects/a/0000755000175000017500000000000013254552750026207 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/failing/63 subproj filegrab/subprojects/a/meson.build0000644000175000017500000000006613174155420030345 0ustar jpakkanejpakkane00000000000000project('a', 'c') executable('prog', '../../prog.c') meson-0.45.1/test cases/failing/63 subproj filegrab/meson.build0000644000175000017500000000012713174155432025563 0ustar jpakkanejpakkane00000000000000project('mainproj', 'c') # Try to grab a file from a parent project. subproject('a') meson-0.45.1/test cases/failing/63 subproj filegrab/prog.c0000644000175000017500000000005613174155420024532 0ustar jpakkanejpakkane00000000000000int main(int argc, char **argv) { return 0; } meson-0.45.1/test cases/objc/0000755000175000017500000000000013254552745017303 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/objc/3 objc args/0000755000175000017500000000000013254552751021255 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/objc/3 objc args/prog.m0000644000175000017500000000020213243342167022370 0ustar jpakkanejpakkane00000000000000#import int main(int argc, char **argv) { #ifdef MESON_TEST int x = 3; #endif printf("x = %d\n", x); return 0; } meson-0.45.1/test cases/objc/3 objc args/meson.build0000644000175000017500000000020413254552320023403 0ustar jpakkanejpakkane00000000000000project('objective c args', 'objc') exe = executable('prog', 'prog.m', objc_args : ['-DMESON_TEST']) test('objective c args', exe) meson-0.45.1/test cases/objc/1 simple/0000755000175000017500000000000013254552751020712 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/objc/1 simple/prog.m0000644000175000017500000000010312650745767022043 0ustar jpakkanejpakkane00000000000000#import int main(int argc, char **argv) { return 0; }meson-0.45.1/test cases/objc/1 simple/meson.build0000644000175000017500000000013113254552320023037 0ustar jpakkanejpakkane00000000000000project('objective c', 'objc') exe = executable('prog', 'prog.m') test('objctest', exe) meson-0.45.1/test cases/objc/6 c++ project objc subproject/0000755000175000017500000000000013254552751024464 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/objc/6 c++ project objc subproject/subprojects/0000755000175000017500000000000013254552745027032 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/objc/6 c++ project objc subproject/subprojects/foo/0000755000175000017500000000000013254552751027612 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/objc/6 c++ project objc subproject/subprojects/foo/meson.build0000644000175000017500000000015213243342167031746 0ustar jpakkanejpakkane00000000000000project('foo', ['objc']) l = static_library('foo', 'foo.m') foo_dep = declare_dependency(link_with : l) meson-0.45.1/test cases/objc/6 c++ project objc subproject/subprojects/foo/foo.m0000644000175000017500000000003413243342167030544 0ustar jpakkanejpakkane00000000000000 int foo() { return 42; } meson-0.45.1/test cases/objc/6 c++ project objc subproject/master.cpp0000644000175000017500000000020313243342167026452 0ustar jpakkanejpakkane00000000000000 #include extern "C" int foo(); int main() { std::cout << "Starting\n"; std::cout << foo() << "\n"; return 0; } meson-0.45.1/test cases/objc/6 c++ project objc subproject/meson.build0000644000175000017500000000021513254552320026614 0ustar jpakkanejpakkane00000000000000project('master', ['cpp']) foo = subproject('foo') dep = foo.get_variable('foo_dep') executable('master', 'master.cpp', dependencies: dep) meson-0.45.1/test cases/objc/2 nsstring/0000755000175000017500000000000013254552751021271 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/objc/2 nsstring/stringprog.m0000644000175000017500000000026012650745767023655 0ustar jpakkanejpakkane00000000000000#import int main(int argc, char **argv) { int result; NSString *str = [NSString new]; result = [str length]; [str release]; return result; } meson-0.45.1/test cases/objc/2 nsstring/meson.build0000644000175000017500000000116513254552320023426 0ustar jpakkanejpakkane00000000000000project('nsstring', 'objc') if host_machine.system() == 'darwin' dep = dependency('appleframeworks', modules : 'foundation') elif host_machine.system() == 'cygwin' error('MESON_SKIP_TEST GNUstep is not packaged for Cygwin.') else dep = dependency('gnustep', required : false) if not dep.found() error('MESON_SKIP_TEST: GNUstep is not installed') endif if host_machine.system() == 'linux' and meson.get_compiler('objc').get_id() == 'clang' error('MESON_SKIP_TEST: GNUstep is broken on Linux with Clang') endif endif exe = executable('stringprog', 'stringprog.m', dependencies : dep) test('stringtest', exe) meson-0.45.1/test cases/frameworks/0000755000175000017500000000000013254552745020546 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/frameworks/17 mpi/0000755000175000017500000000000013254552750021537 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/frameworks/17 mpi/main.c0000644000175000017500000000110613144116705022617 0ustar jpakkanejpakkane00000000000000#include #include int main(int argc, char **argv) { int ier, flag; ier = MPI_Init(&argc, &argv); if (ier) { printf("Unable to initialize MPI: %d\n", ier); return 1; } ier = MPI_Initialized(&flag); if (ier) { printf("Unable to check MPI initialization state: %d\n", ier); return 1; } if (!flag) { printf("MPI did not initialize!\n"); return 1; } ier = MPI_Finalize(); if (ier) { printf("Unable to finalize MPI: %d\n", ier); return 1; } return 0; } meson-0.45.1/test cases/frameworks/17 mpi/main.cpp0000644000175000017500000000031513144116705023160 0ustar jpakkanejpakkane00000000000000#include int main(int argc, char **argv) { MPI::Init(argc, argv); if (!MPI::Is_initialized()) { printf("MPI did not initialize!\n"); return 1; } MPI::Finalize(); } meson-0.45.1/test cases/frameworks/17 mpi/main.f900000644000175000017500000000071513144116705023000 0ustar jpakkanejpakkane00000000000000program mpitest implicit none include 'mpif.h' logical :: flag integer :: ier call MPI_Init(ier) if (ier /= 0) then print *, 'Unable to initialize MPI: ', ier stop 1 endif call MPI_Initialized(flag, ier) if (ier /= 0) then print *, 'Unable to check MPI initialization state: ', ier stop 1 endif call MPI_Finalize(ier) if (ier /= 0) then print *, 'Unable to finalize MPI: ', ier stop 1 endif end program mpitest meson-0.45.1/test cases/frameworks/17 mpi/is_artful.py0000755000175000017500000000027713175453711024111 0ustar jpakkanejpakkane00000000000000#!/usr/bin/env python3 # Any exception causes return value to be not zero, which is sufficient. import sys fc = open('/etc/apt/sources.list').read() if 'artful' not in fc: sys.exit(1) meson-0.45.1/test cases/frameworks/17 mpi/meson.build0000644000175000017500000000222413254552405023676 0ustar jpakkanejpakkane00000000000000project('mpi', 'c', 'cpp') cc = meson.get_compiler('c') if build_machine.system() == 'windows' and cc.get_id() != 'msvc' error('MESON_SKIP_TEST: MPI not available on Windows without MSVC.') endif mpic = dependency('mpi', language : 'c', required : false) if not mpic.found() error('MESON_SKIP_TEST: MPI not found, skipping.') endif exec = executable('exec', 'main.c', dependencies : [mpic]) test('MPI C', exec) if build_machine.system() != 'windows' # C++ MPI not supported by MS-MPI used on AppVeyor. mpicpp = dependency('mpi', language : 'cpp') execpp = executable('execpp', 'main.cpp', dependencies : [mpicpp]) test('MPI C++', execpp) endif # OpenMPI is broken with Fortran on Ubuntu Artful. # Remove this once the following bug has been fixed: # # https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1727474 ubudetector = find_program('is_artful.py') uburesult = run_command(ubudetector) if uburesult.returncode() != 0 and add_languages('fortran', required : false) mpifort = dependency('mpi', language : 'fortran') exef = executable('exef', 'main.f90', dependencies : [mpifort]) test('MPI Fortran', exef) endif meson-0.45.1/test cases/frameworks/20 cups/0000755000175000017500000000000013254552750021716 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/frameworks/20 cups/meson.build0000644000175000017500000000074313254552413024060 0ustar jpakkanejpakkane00000000000000project('cups test', 'c') cups_dep = dependency('cups', version : '>=1.4', required: false) if not cups_dep.found() error('MESON_SKIP_TEST cups not found.') endif e = executable('cups_prog', 'cups_prog.c', dependencies : cups_dep) test('cupstest', e) # ensure we can find the cups dependency via the legacy and modern config-tool # options dep = dependency('cups', version : '>=1.4', method : 'cups-config') dep = dependency('cups', version : '>=1.4', method : 'config-tool') meson-0.45.1/test cases/frameworks/20 cups/cups_prog.c0000644000175000017500000000011313174155420024050 0ustar jpakkanejpakkane00000000000000#include int main() { cupsGetDefault(); return 0; } meson-0.45.1/test cases/frameworks/14 doxygen/0000755000175000017500000000000013254552750022424 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/frameworks/14 doxygen/installed_files.txt0000644000175000017500000000707513104701646026331 0ustar jpakkanejpakkane00000000000000usr/share/doc/spede/html/annotated.html usr/share/doc/spede/html/bc_s.png usr/share/doc/spede/html/bdwn.png usr/share/doc/spede/html/classComedy_1_1Comedian.html usr/share/doc/spede/html/classComedy_1_1Comedian.png usr/share/doc/spede/html/classComedy_1_1Comedian-members.html usr/share/doc/spede/html/classComedy_1_1Spede.html usr/share/doc/spede/html/classComedy_1_1Spede.png usr/share/doc/spede/html/classComedy_1_1Spede-members.html usr/share/doc/spede/html/classes.html usr/share/doc/spede/html/closed.png usr/share/doc/spede/html/comedian_8h_source.html usr/share/doc/spede/html/dir_7bdce917e28dfbd493cadd1d2e5c7d80.html usr/share/doc/spede/html/dir_44a4667d36a4476878de085754f6d2b9.html usr/share/doc/spede/html/dir_68b523c5b3a2dcea45d5ce70397fb722.html usr/share/doc/spede/html/dir_a7e6472d2301212032fd74682f8217f3.html usr/share/doc/spede/html/dir_ee191f21c02d247cc959e80c1a3acadf.html usr/share/doc/spede/html/doc.png usr/share/doc/spede/html/doxygen.css usr/share/doc/spede/html/doxygen.png usr/share/doc/spede/html/dynsections.js usr/share/doc/spede/html/files.html usr/share/doc/spede/html/folderclosed.png usr/share/doc/spede/html/folderopen.png usr/share/doc/spede/html/functions.html usr/share/doc/spede/html/functions_func.html usr/share/doc/spede/html/hierarchy.html usr/share/doc/spede/html/index.html usr/share/doc/spede/html/jquery.js usr/share/doc/spede/html/menu.js usr/share/doc/spede/html/menudata.js usr/share/doc/spede/html/namespaceComedy.html usr/share/doc/spede/html/namespacemembers.html usr/share/doc/spede/html/namespacemembers_func.html usr/share/doc/spede/html/namespaces.html usr/share/doc/spede/html/nav_f.png usr/share/doc/spede/html/nav_g.png usr/share/doc/spede/html/nav_h.png usr/share/doc/spede/html/open.png usr/share/doc/spede/html/search/all_0.html usr/share/doc/spede/html/search/all_0.js usr/share/doc/spede/html/search/all_1.html usr/share/doc/spede/html/search/all_1.js usr/share/doc/spede/html/search/all_2.html usr/share/doc/spede/html/search/all_2.js usr/share/doc/spede/html/search/all_3.html usr/share/doc/spede/html/search/all_3.js usr/share/doc/spede/html/search/classes_0.html usr/share/doc/spede/html/search/classes_0.js usr/share/doc/spede/html/search/classes_1.html usr/share/doc/spede/html/search/classes_1.js usr/share/doc/spede/html/search/close.png usr/share/doc/spede/html/search/files_0.html usr/share/doc/spede/html/search/files_0.js usr/share/doc/spede/html/search/functions_0.html usr/share/doc/spede/html/search/functions_0.js usr/share/doc/spede/html/search/functions_1.html usr/share/doc/spede/html/search/functions_1.js usr/share/doc/spede/html/search/functions_2.html usr/share/doc/spede/html/search/functions_2.js usr/share/doc/spede/html/search/mag_sel.png usr/share/doc/spede/html/search/namespaces_0.html usr/share/doc/spede/html/search/namespaces_0.js usr/share/doc/spede/html/search/nomatches.html usr/share/doc/spede/html/search/pages_0.html usr/share/doc/spede/html/search/pages_0.js usr/share/doc/spede/html/search/search.css usr/share/doc/spede/html/search/search.js usr/share/doc/spede/html/search/searchdata.js usr/share/doc/spede/html/search/search_l.png usr/share/doc/spede/html/search/search_m.png usr/share/doc/spede/html/search/search_r.png usr/share/doc/spede/html/spede_8cpp.html usr/share/doc/spede/html/spede_8h.html usr/share/doc/spede/html/spede_8h_source.html usr/share/doc/spede/html/splitbar.png usr/share/doc/spede/html/sync_off.png usr/share/doc/spede/html/sync_on.png usr/share/doc/spede/html/tabs.css usr/share/doc/spede/html/tab_a.png usr/share/doc/spede/html/tab_b.png usr/share/doc/spede/html/tab_h.png usr/share/doc/spede/html/tab_s.png meson-0.45.1/test cases/frameworks/14 doxygen/meson.build0000644000175000017500000000106213254552402024557 0ustar jpakkanejpakkane00000000000000project('doxygen test', 'cpp', version : '0.1.0') doxygen = find_program('doxygen', required : false) if not doxygen.found() error('MESON_SKIP_TEST doxygen not found.') endif cdata = configuration_data() cdata.set('VERSION', meson.project_version()) if find_program('dot', required : false).found() # In the real world this would set the variable # to YES. However we set it to NO so that the # list of generated files is always the same # so tests always pass. cdata.set('HAVE_DOT', 'NO') else cdata.set('HAVE_DOT', 'NO') endif subdir('doc') meson-0.45.1/test cases/frameworks/14 doxygen/doc/0000755000175000017500000000000013254552750023171 5ustar jpakkanejpakkane00000000000000meson-0.45.1/test cases/frameworks/14 doxygen/doc/Doxyfile.in0000644000175000017500000032212713057037357025315 0ustar jpakkanejpakkane00000000000000# Doxyfile 1.8.13 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "The Vast Comedian Project" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = @VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = Comedy generator # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = doc # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = YES # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. # Minimum value: 0, maximum value: 99, default value: 0. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 0 # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO, these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. # The default value is: NO. WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = "@TOP_SRCDIR@/include" "@TOP_SRCDIR@/src" # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, # *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.idl \ *.ddl \ *.odl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.cs \ *.d \ *.php \ *.php4 \ *.php5 \ *.phtml \ *.inc \ *.m \ *.markdown \ *.md \ *.mm \ *.dox \ *.py \ *.pyw \ *.f90 \ *.f95 \ *.f03 \ *.f08 \ *.f \ *.for \ *.tcl \ *.vhd \ *.vhdl \ *.ucf \ *.qsf # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to YES can help to show when doxygen was last run and thus if the # documentation is up to date. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the master .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /