aboutsummaryrefslogtreecommitdiff
path: root/meson
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2016-01-16 17:35:29 +0200
committerJussi Pakkanen <jpakkane@gmail.com>2016-01-16 17:35:29 +0200
commit23b98cd6e66c6ae0f070e28e0f8b1566c0b5e585 (patch)
treee349597556abe3d22578cfb1f9529f4626ceb5aa /meson
parent1510522b1b9970376a1e1cc5f39e00d8749ec19a (diff)
downloadmeson-23b98cd6e66c6ae0f070e28e0f8b1566c0b5e585.zip
meson-23b98cd6e66c6ae0f070e28e0f8b1566c0b5e585.tar.gz
meson-23b98cd6e66c6ae0f070e28e0f8b1566c0b5e585.tar.bz2
Renamed meson package to mesonbuild so that we can have a script named meson in the same toplevel dir.
Diffstat (limited to 'meson')
-rwxr-xr-x[-rw-r--r--]meson (renamed from meson/modules/modtest.py)15
-rw-r--r--meson/__init__.py0
-rw-r--r--meson/backends.py423
-rw-r--r--meson/build.py969
-rw-r--r--meson/compilers.py1837
-rw-r--r--meson/coredata.py222
-rw-r--r--meson/dependencies.py1120
-rw-r--r--meson/environment.py673
-rw-r--r--meson/interpreter.py2259
-rw-r--r--meson/mconf.py209
-rw-r--r--meson/mesonlib.py284
-rw-r--r--meson/mesonmain.py263
-rw-r--r--meson/mesonmain.ui248
-rw-r--r--meson/mesonrunner.ui52
-rw-r--r--meson/mesonstart.ui119
-rw-r--r--meson/mgui.py565
-rw-r--r--meson/mintro.py212
-rw-r--r--meson/mlog.py81
-rw-r--r--meson/modules/gnome.py330
-rw-r--r--meson/modules/pkgconfig.py82
-rw-r--r--meson/modules/qt4.py155
-rw-r--r--meson/modules/qt5.py162
-rw-r--r--meson/modules/rpm.py163
-rw-r--r--meson/modules/windows.py47
-rw-r--r--meson/mparser.py565
-rw-r--r--meson/ninjabackend.py1819
-rw-r--r--meson/optinterpreter.py148
-rw-r--r--meson/scripts/commandrunner.py59
-rw-r--r--meson/scripts/delwithsuffix.py37
-rw-r--r--meson/scripts/depfixer.py302
-rw-r--r--meson/scripts/dirchanger.py30
-rw-r--r--meson/scripts/gtkdochelper.py122
-rw-r--r--meson/scripts/meson_benchmark.py97
-rw-r--r--meson/scripts/meson_install.py215
-rw-r--r--meson/scripts/meson_test.py233
-rw-r--r--meson/scripts/regen_checker.py45
-rw-r--r--meson/scripts/symbolextractor.py106
-rw-r--r--meson/scripts/vcstagger.py36
-rw-r--r--meson/vs2010backend.py640
-rw-r--r--meson/wrap/wrap.py212
-rwxr-xr-xmeson/wrap/wraptool.py200
-rw-r--r--meson/xcodebackend.py775
42 files changed, 9 insertions, 16122 deletions
diff --git a/meson/modules/modtest.py b/meson
index c9247e6..b977368 100644..100755
--- a/meson/modules/modtest.py
+++ b/meson
@@ -1,4 +1,6 @@
-# Copyright 2015 The Meson development team
+#!/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.
@@ -12,10 +14,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-class TestModule:
+from mesonbuild import mesonmain
+import sys, os
- def print_hello(self, state, args, kwargs):
- print('Hello from a Meson module')
+thisfile = __file__
+if not os.path.isabs(thisfile):
+ thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile))
-def initialize():
- return TestModule()
+sys.exit(mesonmain.run(thisfile, sys.argv[1:]))
diff --git a/meson/__init__.py b/meson/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/meson/__init__.py
+++ /dev/null
diff --git a/meson/backends.py b/meson/backends.py
deleted file mode 100644
index c583a7b..0000000
--- a/meson/backends.py
+++ /dev/null
@@ -1,423 +0,0 @@
-# Copyright 2012-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, pickle, re
-from . import build
-from . import dependencies
-from . import mesonlib
-import json
-from .coredata import MesonException
-
-class InstallData():
- def __init__(self, source_dir, build_dir, prefix, depfixer):
- self.source_dir = source_dir
- self.build_dir= build_dir
- self.prefix = prefix
- self.targets = []
- self.depfixer = depfixer
- self.headers = []
- self.man = []
- self.data = []
- self.po_package_name = ''
- self.po = []
- self.install_scripts = []
- self.install_subdirs = []
-
-class TestSerialisation:
- def __init__(self, name, suite, fname, is_cross, exe_wrapper, is_parallel, cmd_args, env,
- should_fail, valgrind_args, timeout, workdir, extra_paths):
- self.name = name
- self.suite = suite
- self.fname = fname
- self.is_cross = is_cross
- self.exe_runner = exe_wrapper
- self.is_parallel = is_parallel
- self.cmd_args = cmd_args
- self.env = env
- self.should_fail = should_fail
- self.valgrind_args = valgrind_args
- self.timeout = timeout
- self.workdir = workdir
- self.extra_paths = extra_paths
-
-# 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.dep_rules = {}
- 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_compiler_for_lang(self, lang):
- for i in self.build.compilers:
- if i.language == lang:
- return i
- raise RuntimeError('No compiler for language ' + lang)
-
- def get_compiler_for_source(self, src):
- for i in self.build.compilers:
- if i.can_compile(src):
- return i
- if isinstance(src, mesonlib.File):
- src = src.fname
- raise RuntimeError('No specified compiler can handle file ' + src)
-
- def get_target_filename(self, target):
- targetdir = self.get_target_dir(target)
- fname = target.get_filename()
- if isinstance(fname, list):
- fname = fname[0] # HORROR, HORROR! Fix this.
- filename = os.path.join(targetdir, fname)
- return filename
-
- 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_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 generate_unity_files(self, target, unity_src):
- langlist = {}
- abs_files = []
- result = []
- for src in unity_src:
- comp = self.get_compiler_for_source(src)
- language = comp.get_language()
- suffix = '.' + comp.get_default_suffix()
- if language not in langlist:
- outfilename = os.path.join(self.get_target_private_dir_abs(target), target.name + '-unity' + suffix)
- outfileabs = os.path.join(self.environment.get_build_dir(), outfilename)
- outfileabs_tmp = outfileabs + '.tmp'
- abs_files.append(outfileabs)
- outfile = open(outfileabs_tmp, 'w')
- langlist[language] = outfile
- result.append(outfilename)
- ofile = langlist[language]
- ofile.write('#include<%s>\n' % src)
- [x.close() for x in langlist.values()]
- [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, build.ExtractedObjects):
- obj_list += self.determine_ext_objs(obj, proj_dir_to_build_root)
- else:
- raise MesonException('Unknown data type in object list.')
- return obj_list
-
- def serialise_tests(self):
- test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat')
- datafile = open(test_data, 'wb')
- self.write_test_file(datafile)
- datafile.close()
- benchmark_data = os.path.join(self.environment.get_scratch_dir(), 'meson_benchmark_setup.dat')
- datafile = open(benchmark_data, 'wb')
- self.write_benchmark_file(datafile)
- datafile.close()
-
- def has_source_suffix(self, target, suffix):
- for s in target.get_sources():
- if s.endswith(suffix):
- return True
- return False
-
- def has_vala(self, target):
- return self.has_source_suffix(target, '.vala')
-
- def has_rust(self, target):
- return self.has_source_suffix(target, '.rs')
-
- def has_cs(self, target):
- return self.has_source_suffix(target, '.cs')
-
- def has_swift(self, target):
- return self.has_source_suffix(target, '.swift')
-
- def determine_linker(self, target, src):
- if isinstance(target, build.StaticLibrary):
- return self.build.static_linker
- if len(self.build.compilers) == 1:
- return self.build.compilers[0]
- # Currently a bit naive. C++ must
- # be linked with a C++ compiler, but
- # otherwise we don't care. This will
- # become trickier if and when Fortran
- # and the like become supported.
- cpp = None
- for c in self.build.compilers:
- if c.get_language() == 'cpp':
- cpp = c
- break
- if cpp is not None:
- for s in src:
- if c.can_compile(s):
- return cpp
- for c in self.build.compilers:
- if c.get_language() != 'vala':
- return c
- raise RuntimeError('Unreachable code')
-
- def determine_ext_objs(self, extobj, proj_dir_to_build_root=''):
- result = []
- targetdir = self.get_target_private_dir(extobj.target)
- suffix = '.' + self.environment.get_object_suffix()
- for osrc in extobj.srclist:
- osrc_base = osrc.fname
- if not self.source_suffix_in_objs:
- osrc_base = '.'.join(osrc.split('.')[:-1])
- # If extracting in a subproject, the subproject
- # name gets duplicated in the file name.
- pathsegs = osrc.subdir.split(os.sep)
- if pathsegs[0] == 'subprojects':
- pathsegs = pathsegs[2:]
- fixedpath = os.sep.join(pathsegs)
- objbase = osrc.fname.replace('/', '_').replace('\\', '_')
- objname = os.path.join(proj_dir_to_build_root,
- targetdir, os.path.basename(objbase) + suffix)
- result.append(objname)
- 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)
- for lang in ['c', 'cpp']:
- p = target.get_pch(lang)
- if len(p) == 0:
- continue
- if compiler.can_compile(p[-1]):
- header = p[0]
- args += compiler.get_pch_use_args(pchpath, header)
- if len(args) > 0:
- args = includeargs + args
- return args
-
- def generate_basic_compiler_args(self, target, compiler):
- commands = []
- commands += compiler.get_always_args()
- if self.environment.coredata.get_builtin_option('buildtype') != 'plain':
- commands += compiler.get_warn_args(self.environment.coredata.get_builtin_option('warning_level'))
- commands += compiler.get_option_compile_args(self.environment.coredata.compiler_options)
- commands += self.build.get_global_args(compiler)
- commands += self.environment.coredata.external_args[compiler.get_language()]
- commands += target.get_extra_args(compiler.get_language())
- commands += compiler.get_buildtype_args(self.environment.coredata.get_builtin_option('buildtype'))
- if self.environment.coredata.get_builtin_option('coverage'):
- commands += compiler.get_coverage_args()
- if self.environment.coredata.get_builtin_option('werror'):
- commands += compiler.get_werror_args()
- if isinstance(target, build.SharedLibrary):
- commands += compiler.get_pic_args()
- for dep in target.get_external_deps():
- commands += dep.get_compile_args()
- if isinstance(target, build.Executable):
- commands += dep.get_exe_args()
-
- # 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 isinstance(d, build.StaticLibrary) and\
- not isinstance(d, build.SharedLibrary):
- raise RuntimeError('Tried to link with a non-library target "%s".' % d.get_basename())
- fname = self.get_target_filename(d)
- if compiler.id == 'msvc':
- if fname.endswith('dll'):
- fname = fname[:-3] + 'lib'
- args.append(fname)
- # If you have executable e that links to shared lib s1 that links to shared library s2
- # you have to specify s2 as well as s1 when linking e even if e does not directly use
- # s2. Gcc handles this case fine but Clang does not for some reason. Thus we need to
- # explictly specify all libraries every time.
- args += self.build_target_link_arguments(compiler, d.get_dependencies())
- return args
-
- def determine_windows_extra_paths(self, target):
- '''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.'''
- if not isinstance(target, build.Executable):
- return []
- prospectives = target.get_transitive_link_deps()
- result = []
- 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):
- fname = exe.fullpath
- else:
- fname = [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()
- if is_cross:
- exe_wrapper = self.environment.cross_info.config['binaries'].get('exe_wrapper', None)
- else:
- exe_wrapper = None
- if mesonlib.is_windows():
- extra_paths = self.determine_windows_extra_paths(exe)
- else:
- extra_paths = []
- cmd_args = []
- for a in t.cmd_args:
- 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)
- ts = TestSerialisation(t.get_name(), t.suite, fname, is_cross, exe_wrapper,
- t.is_parallel, cmd_args, t.env, t.should_fail, t.valgrind_args,
- 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'}
- mfobj['projects'] = self.build.dep_manifest
- open(ifilename, 'w').write(json.dumps(mfobj))
- d.data.append([ifilename, ofilename])
-
- 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 \
- isinstance(exe, build.BuildTarget) and exe.is_cross:
- if 'exe_wrapper' not in self.environment.cross_info:
- 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 eval_custom_target_command(self, target, absolute_paths=False):
- ofilenames = [os.path.join(self.get_target_dir(target), i) for i in target.output]
- srcs = []
- outdir = self.get_target_dir(target)
- # Many external programs fail on empty arguments.
- if outdir == '':
- outdir = '.'
- if absolute_paths:
- outdir = os.path.join(self.environment.get_build_dir(), outdir)
- for i in target.sources:
- if isinstance(i, str):
- fname = os.path.join(self.build_to_src, target.subdir, i)
- else:
- fname = i.rel_to_builddir(self.build_to_src)
- if absolute_paths:
- fname = os.path.join(self.environment.get_build_dir(), fname)
- srcs.append(fname)
- cmd = []
- for i in target.command:
- if isinstance(i, build.Executable):
- cmd += self.exe_object_to_cmd_array(i)
- continue
- if 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_filename()[0]
- i = os.path.join(self.get_target_dir(i), tmp)
- for (j, src) in enumerate(srcs):
- i = i.replace('@INPUT%d@' % j, src)
- for (j, res) in enumerate(ofilenames):
- i = i.replace('@OUTPUT%d@' % j, res)
- if i == '@INPUT@':
- cmd += srcs
- elif i == '@OUTPUT@':
- cmd += ofilenames
- else:
- if '@OUTDIR@' in i:
- i = i.replace('@OUTDIR@', outdir)
- elif '@PRIVATE_OUTDIR_' in i:
- match = re.search('@PRIVATE_OUTDIR_(ABS_)?([-a-zA-Z0-9.@:]*)@', i)
- source = match.group(0)
- if match.group(1) is None and not absolute_paths:
- lead_dir = ''
- else:
- lead_dir = self.environment.get_build_dir()
- target_id = match.group(2)
- i = i.replace(source,
- os.path.join(lead_dir,
- outdir))
- cmd.append(i)
- cmd = [i.replace('\\', '/') for i in cmd]
- return (srcs, ofilenames, cmd)
diff --git a/meson/build.py b/meson/build.py
deleted file mode 100644
index c0ba895..0000000
--- a/meson/build.py
+++ /dev/null
@@ -1,969 +0,0 @@
-# Copyright 2012-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.
-
-from . import coredata
-from . import environment
-from . import dependencies
-from . import mlog
-import copy, os
-from .mesonlib import File, flatten
-
-known_basic_kwargs = {'install' : True,
- 'c_pch' : True,
- 'cpp_pch' : True,
- 'c_args' : True,
- 'cpp_args' : True,
- 'cs_args' : True,
- 'vala_args' : True,
- 'link_args' : True,
- 'link_depends': True,
- 'link_with' : True,
- 'include_directories': True,
- 'dependencies' : True,
- 'install_dir' : True,
- 'main_class' : True,
- 'gui_app' : True,
- 'extra_files' : True,
- 'install_rpath' : True,
- 'resources' : True,
- 'sources' : True,
- 'objects' : True,
- 'native' : True,
- }
-
-known_shlib_kwargs = known_basic_kwargs.copy()
-known_shlib_kwargs.update({'version' : True,
- 'soversion' : True})
-
-backslash_explanation = \
-'''Compiler arguments have a backslash "\\" character. This is unfortunately not
-permitted. The reason for this is that backslash is a shell quoting character
-that behaves differently across different systems. Because of this is it not
-possible to make it work reliably across all the platforms Meson needs to
-support.
-
-There are several different ways of working around this issue. Most of the time
-you are using this to provide a -D define to your compiler. Try instead to
-create a config.h file and put all of your definitions in it using
-configure_file().
-
-Another approach is to move the backslashes into the source and have the other
-bits in the def. So you would have an arg -DPLAIN_TEXT="foo" and then in your
-C sources something like this:
-
-const char *fulltext = "\\\\" PLAIN_TEXT;
-
-We are fully aware that these are not really usable or pleasant ways to do
-this but it's the best we can do given the way shell quoting works.
-'''
-
-class InvalidArguments(coredata.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 = {}
- self.compilers = []
- self.cross_compilers = []
- self.global_args = {}
- self.tests = []
- self.benchmarks = []
- self.headers = []
- self.man = []
- self.data = []
- self.static_linker = None
- self.static_cross_linker = None
- self.pot = []
- self.subprojects = {}
- self.install_scripts = []
- self.install_dirs = []
- self.dep_manifest_name = None
- self.dep_manifest = {}
-
- def has_language(self, language):
- for i in self.compilers:
- if i.get_language() == language:
- return True
- return False
-
- 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)
- if self.has_language(compiler.get_language()):
- return
- self.compilers.append(compiler)
-
- def add_cross_compiler(self, compiler):
- if len(self.cross_compilers) == 0:
- self.static_cross_linker = self.environment.detect_static_linker(compiler)
- for i in self.cross_compilers:
- if i.get_language() == compiler.get_language():
- return
- self.cross_compilers.append(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(), [])
-
-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 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():
- def __init__(self, target, srclist):
- self.target = target
- self.srclist = srclist
-
-class BuildTarget():
- def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
- self.name = name
- self.subdir = subdir
- self.subproject = subproject # Can not be calculated from subdir as subproject dirname can be changed per project.
- self.is_cross = is_cross
- self.sources = []
- self.objects = []
- self.external_deps = []
- self.include_dirs = []
- self.link_targets = []
- self.link_depends = []
- self.filename = 'no_name'
- self.need_install = False
- self.pch = {}
- self.extra_args = {}
- self.generated = []
- self.extra_files = []
- self.process_sourcelist(sources)
- self.process_objectlist(objects)
- self.process_kwargs(kwargs, environment)
- self.check_unknown_kwargs(kwargs)
- if len(self.sources) == 0 and \
- len(self.generated) == 0 and \
- len(self.objects) == 0:
- raise InvalidArguments('Build target %s has no sources.' % name)
- self.validate_sources()
-
- 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 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 not k in known_kwargs:
- unknowns.append(k)
- if len(unknowns) > 0:
- mlog.log(mlog.bold('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):
- self.objects.append(s)
- elif isinstance(s, ExtractedObjects):
- self.objects.append(s)
- else:
- raise InvalidArguments('Bad object in target %s.' % self.name)
-
- def process_sourcelist(self, sources):
- if not isinstance(sources, list):
- sources = [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 not s in added_sources:
- self.sources.append(s)
- added_sources[s] = True
- elif isinstance(s, GeneratedList) or isinstance(s, CustomTarget):
- self.generated.append(s)
- else:
- raise InvalidArguments('Bad source in target %s.' % self.name)
-
- def validate_sources(self):
- if len(self.sources) > 0:
- firstname = self.sources[0]
- if isinstance(firstname, File):
- firstname = firstname.fname
- first = os.path.split(firstname)[1]
- (base, suffix) = os.path.splitext(first)
- if suffix == '.rs':
- if self.name != base:
- raise InvalidArguments('In Rust targets, the first source file must be named projectname.rs.')
-
- def get_original_kwargs(self):
- return self.kwargs
-
- def unpack_holder(self, d):
- if not isinstance(d, list):
- d = [d]
- newd = []
- for i in d:
- if hasattr(i, 'held_object'):
- newd.append(i.held_object)
- else:
- 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.
- if 'dependencies' in self.kwargs:
- self.kwargs['dependencies'] = self.unpack_holder(self.kwargs['dependencies'])
- if 'link_with' in self.kwargs:
- self.kwargs['link_with'] = self.unpack_holder(self.kwargs['link_with'])
-
- def extract_objects(self, srcargs):
- obj_src = []
- for srclist in srcargs:
- if not isinstance(srclist, list):
- srclist = [srclist]
- for src in srclist:
- if not isinstance(src, str):
- raise coredata.MesonException('Extraction arguments must be strings.')
- src = File(False, self.subdir, src)
- if src not in self.sources:
- raise coredata.MesonException('Tried to extract unknown source %s.' % src)
- obj_src.append(src)
- return ExtractedObjects(self, obj_src)
-
- def extract_all_objects(self):
- return ExtractedObjects(self, self.sources)
-
- 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.custom_install_dir
-
- def process_kwargs(self, kwargs, environment):
- self.copy_kwargs(kwargs)
- kwargs.get('modules', [])
- self.need_install = kwargs.get('install', self.need_install)
- llist = kwargs.get('link_with', [])
- if not isinstance(llist, list):
- llist = [llist]
- 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
- self.link(linktarget)
- c_pchlist = kwargs.get('c_pch', [])
- if not isinstance(c_pchlist, list):
- c_pchlist = [c_pchlist]
- self.add_pch('c', c_pchlist)
- cpp_pchlist = kwargs.get('cpp_pch', [])
- if not isinstance(cpp_pchlist, list):
- cpp_pchlist = [cpp_pchlist]
- self.add_pch('cpp', cpp_pchlist)
- clist = kwargs.get('c_args', [])
- if not isinstance(clist, list):
- clist = [clist]
- self.add_compiler_args('c', clist)
- cpplist = kwargs.get('cpp_args', [])
- if not isinstance(cpplist, list):
- cpplist = [cpplist]
- self.add_compiler_args('cpp', cpplist)
- cslist = kwargs.get('cs_args', [])
- if not isinstance(cslist, list):
- cslist = [cslist]
- self.add_compiler_args('cs', cslist)
- valalist = kwargs.get('vala_args', [])
- if not isinstance(valalist, list):
- valalist = [valalist]
- self.add_compiler_args('vala', valalist)
- self.link_args = kwargs.get('link_args', [])
- if not isinstance(self.link_args, list):
- self.link_args = [self.link_args]
- for i in self.link_args:
- if not isinstance(i, str):
- raise InvalidArguments('Link_args arguments must be strings.')
- self.link_depends = kwargs.get('link_depends', [])
- if not isinstance(self.link_depends, list):
- self.link_depends = [self.link_depends]
- for i in self.link_depends:
- if not isinstance(i, str):
- raise InvalidArguments('Link_depends arguments must be strings.')
- inclist = kwargs.get('include_directories', [])
- if not isinstance(inclist, list):
- inclist = [inclist]
- self.add_include_dirs(inclist)
- deplist = kwargs.get('dependencies', [])
- if not isinstance(deplist, list):
- deplist = [deplist]
- self.add_external_deps(deplist)
- 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 InvalidArguments('Custom_install_dir must be a string')
- 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 = kwargs.get('extra_files', [])
- if isinstance(extra_files, str):
- extra_files = [extra_files]
- for i in extra_files:
- if not isinstance(i, str):
- raise InvalidArguments('Arguments to extra_files must be strings.')
- trial = os.path.join(environment.get_source_dir(), self.subdir, i)
- 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.')
- resources = kwargs.get('resources', [])
- if not isinstance(resources, list):
- resources = [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
-
- def get_subdir(self):
- return self.subdir
-
- def get_filename(self):
- return self.filename
-
- def get_extra_args(self, language):
- return self.extra_args.get(language, [])
-
- def get_dependencies(self):
- transitive_deps = []
- for t in self.link_targets:
- transitive_deps.append(t)
- if isinstance(t, StaticLibrary):
- transitive_deps += t.get_dependencies()
- return transitive_deps
-
- def get_basename(self):
- return self.name
-
- 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_external_deps(self, deps):
- if not isinstance(deps, list):
- deps = [deps]
- for dep in deps:
- if hasattr(dep, 'held_object'):
- dep = dep.held_object
- if isinstance(dep, dependencies.InternalDependency):
- self.process_sourcelist(dep.sources)
- self.add_include_dirs(dep.include_directories)
- for l in dep.libraries:
- self.link(l)
- self.add_external_deps(dep.ext_deps)
- elif isinstance(dep, dependencies.Dependency):
- self.external_deps.append(dep)
- self.process_sourcelist(dep.get_sources())
- else:
- raise InvalidArguments('Argument is not an external dependency')
-
- def get_external_deps(self):
- return self.external_deps
-
- def link(self, target):
- if not isinstance(target, list):
- target = [target]
- for t in target:
- if hasattr(t, 'held_object'):
- t = t.held_object
- if not isinstance(t, StaticLibrary) and \
- not isinstance(t, SharedLibrary):
- raise InvalidArguments('Link target is not library.')
- if self.is_cross != t.is_cross:
- raise InvalidArguments('Tried to mix cross built and native libraries in target %s.' % self.name)
- self.link_targets.append(t)
-
- def set_generated(self, genlist):
- for g in genlist:
- if not(isinstance(g, GeneratedList)):
- raise InvalidArguments('Generated source argument is not the output of a generator.')
- self.generated.append(g)
-
- def add_pch(self, language, pchlist):
- if len(pchlist) == 0:
- 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 = flatten(args)
- for a in args:
- if not isinstance(a, (str, File)):
- raise InvalidArguments('A non-string passed to compiler args.')
- if isinstance(a, str) and '\\' in a:
- raise InvalidArguments(backslash_explanation)
- if language in self.extra_args:
- self.extra_args[language] += args
- else:
- self.extra_args[language] = args
-
- def get_aliaslist(self):
- return []
-
-
-class Generator():
- def __init__(self, args, kwargs):
- if len(args) != 1:
- raise InvalidArguments('Generator requires one and only one positional argument')
-
- exe = args[0]
- if hasattr(exe, 'held_object'):
- exe = exe.held_object
- if not isinstance(exe, Executable) and not isinstance(exe, dependencies.ExternalProgram):
- raise InvalidArguments('First generator argument must be an executable.')
- self.exe = exe
- self.process_kwargs(kwargs)
-
- 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 = kwargs['output']
- if not isinstance(outputs, list):
- outputs = [outputs]
- for rule in outputs:
- if not isinstance(rule, str):
- raise InvalidArguments('"output" may only contain strings.')
- if not '@BASENAME@' in rule and not '@PLAINNAME@' 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
-
- def get_base_outnames(self, inname):
- plainname = os.path.split(inname)[1]
- basename = plainname.split('.')[0]
- return [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.outputs]
-
- def get_arglist(self):
- return self.arglist
-
-class GeneratedList():
- def __init__(self, generator, extra_args=[]):
- if hasattr(generator, 'held_object'):
- generator = generator.held_object
- self.generator = generator
- self.infilelist = []
- self.outfilelist = []
- self.outmap = {}
- self.extra_depends = []
- self.extra_args = extra_args
-
- def add_file(self, newfile):
- self.infilelist.append(newfile)
- outfiles = self.generator.get_base_outnames(newfile)
- self.outfilelist += outfiles
- self.outmap[newfile] = outfiles
-
- def get_infilelist(self):
- return self.infilelist
-
- def get_outfilelist(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)
- self.prefix = ''
- self.suffix = environment.get_exe_suffix()
- suffix = environment.get_exe_suffix()
- if len(self.sources) > 0 and self.sources[0].endswith('.cs'):
- suffix = 'exe'
- if suffix != '':
- self.filename = self.name + '.' + suffix
- else:
- self.filename = self.name
-
- def type_suffix(self):
- return "@exe"
-
-class StaticLibrary(BuildTarget):
- def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
- super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs)
- if len(self.sources) > 0 and self.sources[0].endswith('.cs'):
- raise InvalidArguments('Static libraries not supported for C#.')
- self.prefix = environment.get_static_lib_prefix()
- self.suffix = environment.get_static_lib_suffix()
- if len(self.sources) > 0 and self.sources[0].endswith('.rs'):
- self.suffix = 'rlib'
- self.filename = self.prefix + self.name + '.' + self.suffix
-
- def get_import_filename(self):
- return self.filename
-
- def get_osx_filename(self):
- return self.get_filename()
-
- def type_suffix(self):
- return "@sta"
-
-class SharedLibrary(BuildTarget):
- def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
- self.version = None
- self.soversion = None
- super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs);
- if len(self.sources) > 0 and self.sources[0].endswith('.cs'):
- self.suffix = 'dll'
- self.prefix = 'lib'
- else:
- self.prefix = environment.get_shared_lib_prefix()
- self.suffix = environment.get_shared_lib_suffix()
- if len(self.sources) > 0 and self.sources[0].endswith('.rs'):
- self.suffix = 'rlib'
- self.importsuffix = environment.get_import_lib_suffix()
- self.filename = self.prefix + self.name + '.' + self.suffix
-
- def process_kwargs(self, kwargs, environment):
- super().process_kwargs(kwargs, environment)
- if 'version' in kwargs:
- self.set_version(kwargs['version'])
- if 'soversion' in kwargs:
- self.set_soversion(kwargs['soversion'])
-
- def check_unknown_kwargs(self, kwargs):
- self.check_unknown_kwargs_int(kwargs, known_shlib_kwargs)
-
- def get_shbase(self):
- return self.prefix + self.name + '.' + self.suffix
-
- def get_import_filename(self):
- return self.prefix + self.name + '.' + self.importsuffix
-
- def get_all_link_deps(self):
- return [self] + self.get_transitive_link_deps()
-
- def get_filename(self):
- '''Works on all platforms except OSX, which does its own thing.'''
- fname = self.get_shbase()
- if self.version is None:
- return fname
- else:
- return fname + '.' + self.version
-
- def get_osx_filename(self):
- if self.version is None:
- return self.get_shbase()
- return self.prefix + self.name + '.' + self.version + '.' + self.suffix
-
- def set_version(self, version):
- if not isinstance(version, str):
- raise InvalidArguments('Shared library version is not a string.')
- self.version = version
-
- def set_soversion(self, version):
- if isinstance(version, int):
- version = str(version)
- if not isinstance(version, str):
- raise InvalidArguments('Shared library soversion is not a string or integer.')
- self.soversion = version
-
- def get_aliaslist(self):
- aliases = []
- if self.soversion is not None:
- aliases.append(self.get_shbase() + '.' + self.soversion)
- if self.version is not None:
- aliases.append(self.get_shbase())
- return aliases
-
- def type_suffix(self):
- return "@sha"
-
-class CustomTarget:
- known_kwargs = {'input' : True,
- 'output' : True,
- 'command' : True,
- 'install' : True,
- 'install_dir' : True,
- 'build_always' : True,
- 'depends' : True,
- 'depend_files' : True,
- }
-
- def __init__(self, name, subdir, kwargs):
- self.name = name
- self.subdir = subdir
- self.dependencies = []
- self.extra_depends = []
- self.depend_files = [] # Files that this target depends on but are not on the command line.
- self.process_kwargs(kwargs)
- self.extra_files = []
- self.install_rpath = ''
- unknowns = []
- for k in kwargs:
- if k not in CustomTarget.known_kwargs:
- unknowns.append(k)
- if len(unknowns) > 0:
- mlog.log(mlog.bold('Warning:'), 'Unknown keyword arguments in target %s: %s' %
- (self.name, ', '.join(unknowns)))
-
- def get_id(self):
- return self.name + self.type_suffix()
-
- def process_kwargs(self, kwargs):
- self.sources = kwargs.get('input', [])
- if not isinstance(self.sources, list):
- self.sources = [self.sources]
- if 'output' not in kwargs:
- raise InvalidArguments('Missing keyword argument "output".')
- self.output = kwargs['output']
- if not isinstance(self.output, list):
- self.output = [self.output]
- for i in self.output:
- if not(isinstance(i, str)):
- raise InvalidArguments('Output argument not a string.')
- if '/' in i:
- raise InvalidArguments('Output must not contain a path segment.')
- if 'command' not in kwargs:
- raise InvalidArguments('Missing keyword argument "command".')
- cmd = kwargs['command']
- if not(isinstance(cmd, list)):
- cmd = [cmd]
- final_cmd = []
- for i, c in enumerate(cmd):
- if hasattr(c, 'held_object'):
- c = c.held_object
- if isinstance(c, str):
- final_cmd.append(c)
- elif isinstance(c, dependencies.ExternalProgram):
- final_cmd += c.get_command()
- elif isinstance(c, BuildTarget) or isinstance(c, CustomTarget):
- self.dependencies.append(c)
- final_cmd.append(c)
- elif isinstance(c, list):
- # Hackety hack, only supports one level of flattening. Should really
- # work to arbtrary depth.
- for s in c:
- if not isinstance(s, str):
- raise InvalidArguments('Array as argument %d contains a non-string.' % i)
- final_cmd.append(s)
- else:
- raise InvalidArguments('Argument %s in "command" is invalid.' % i)
- self.command = final_cmd
- if 'install' in kwargs:
- self.install = kwargs['install']
- if not isinstance(self.install, bool):
- raise InvalidArguments('"install" must be boolean.')
- if 'install_dir' not in kwargs:
- raise InvalidArguments('"install_dir" not specified.')
- self.install_dir = kwargs['install_dir']
- if not(isinstance(self.install_dir, str)):
- raise InvalidArguments('"install_dir" must be a string.')
- else:
- self.install = False
- 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 = kwargs.get('depends', [])
- if not isinstance(extra_deps, list):
- extra_deps = [extra_deps]
- for ed in extra_deps:
- while hasattr(ed, 'held_object'):
- ed = ed.held_object
- if not isinstance(ed, CustomTarget) and not isinstance(ed, BuildTarget):
- raise InvalidArguments('Can only depend on toplevel targets.')
- self.extra_depends.append(ed)
- depend_files = kwargs.get('depend_files', [])
- if not isinstance(depend_files, list):
- depend_files = [depend_files]
- for i in depend_files:
- if isinstance(i, (File, str)):
- self.depend_files.append(i)
- else:
- mlog.debug(i)
- raise InvalidArguments('Unknown type in depend_files.')
-
- def get_basename(self):
- return self.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_subdir(self):
- return self.subdir
-
- def get_filename(self):
- return self.output
-
- def get_aliaslist(self):
- return []
-
- def get_sources(self):
- return self.sources
-
- def get_generated_sources(self):
- return []
-
- def type_suffix(self):
- return "@cus"
-
-class RunTarget:
- def __init__(self, name, command, args, subdir):
- self.name = name
- self.command = command
- self.args = args
- self.subdir = subdir
-
- def get_id(self):
- return self.name + self.type_suffix()
-
- def get_basename(self):
- return self.name
-
- def get_dependencies(self):
- return []
-
- def get_generated_sources(self):
- return []
-
- def get_sources(self):
- return []
-
- def get_subdir(self):
- return self.subdir
-
- 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'
- incdirs = kwargs.get('include_directories', [])
-
- def get_main_class(self):
- return self.main_class
-
- def type_suffix(self):
- return "@jar"
-
-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 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 get(self, name):
- return self.values[name]
-
- 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, in_sourcetree, source_subdir, sources, install_dir):
- self.in_sourcetree = in_sourcetree
- self.source_subdir = source_subdir
- self.sources = sources
- self.install_dir = install_dir
-
-class InstallScript:
- def __init__(self, cmd_arr):
- assert(isinstance(cmd_arr, list))
- self.cmd_arr = cmd_arr
diff --git a/meson/compilers.py b/meson/compilers.py
deleted file mode 100644
index ec0181e..0000000
--- a/meson/compilers.py
+++ /dev/null
@@ -1,1837 +0,0 @@
-# Copyright 2012-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 subprocess, os.path
-import tempfile
-from .import mesonlib
-from . import mlog
-from .coredata import MesonException
-from . import coredata
-
-"""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', 'moc', 'vapi']
-cpp_suffixes = ['cc', 'cpp', 'cxx', 'h', 'hh', 'hpp', 'hxx', 'c++']
-c_suffixes = ['c']
-clike_suffixes = c_suffixes + cpp_suffixes
-obj_suffixes = ['o', 'obj', 'res']
-lib_suffixes = ['a', 'lib', 'dll', 'dylib', 'so']
-
-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]
- return suffix in clike_suffixes
-
-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' : [],
- 'debug' : ['-g'],
- 'debugoptimized' : ['-O2', '-g'],
- 'release' : ['-O3']}
-
-msvc_buildtype_args = {'plain' : [],
- 'debug' : ["/MDd", "/ZI", "/Ob0", "/Od", "/RTC1"],
- 'debugoptimized' : ["/MD", "/Zi", "/O2", "/Ob1", "/D"],
- 'release' : ["/MD", "/O2", "/Ob2"]}
-
-gnulike_buildtype_linker_args = {}
-
-if mesonlib.is_osx():
- gnulike_buildtype_linker_args.update({'plain' : [],
- 'debug' : [],
- 'debugoptimized' : [],
- 'release' : [],
- })
-else:
- gnulike_buildtype_linker_args.update({'plain' : [],
- 'debug' : [],
- 'debugoptimized' : [],
- 'release' : ['-Wl,-O1'],
- })
-
-msvc_buildtype_linker_args = {'plain' : [],
- 'debug' : [],
- 'debugoptimized' : [],
- 'release' : []}
-
-java_buildtype_args = {'plain' : [],
- 'debug' : ['-g'],
- 'debugoptimized' : ['-g'],
- 'release' : []}
-
-rust_buildtype_args = {'plain' : [],
- 'debug' : ['-g'],
- 'debugoptimized' : ['-g', '--opt-level', '2'],
- 'release' : ['--opt-level', '3']}
-
-mono_buildtype_args = {'plain' : [],
- 'debug' : ['-debug'],
- 'debugoptimized': ['-debug', '-optimize+'],
- 'release' : ['-optimize+']}
-
-swift_buildtype_args = {'plain' : [],
- 'debug' : ['-g'],
- 'debugoptimized': ['-g', '-O'],
- 'release' : ['-O']}
-
-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']
-
-def build_unix_rpath_args(build_dir, rpath_paths, install_rpath):
- if len(rpath_paths) == 0 and len(install_rpath) == 0:
- return []
- paths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths])
- if len(paths) < len(install_rpath):
- padding = 'X'*(len(install_rpath) - len(paths))
- if len(paths) == 0:
- paths = padding
- else:
- paths = paths + ':' + padding
- return ['-Wl,-rpath,' + paths]
-
-class EnvironmentException(MesonException):
- def __init(self, *args, **kwargs):
- Exception.__init__(self, *args, **kwargs)
-
-class CrossNoRunException(MesonException):
- def __init(self, *args, **kwargs):
- Exception.__init__(self, *args, **kwargs)
-
-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 Compiler():
- def __init__(self, exelist, version):
- if type(exelist) == type(''):
- self.exelist = [exelist]
- elif type(exelist) == type([]):
- self.exelist = exelist
- else:
- raise TypeError('Unknown argument to Compiler')
- self.version = version
-
- def get_always_args(self):
- return []
-
- def get_linker_always_args(self):
- 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.language)
-
- def compiles(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support compile checks.' % self.language)
-
- def links(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support link checks.' % self.language)
-
- def run(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support run checks.' % self.language)
-
- def sizeof(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support sizeof checks.' % self.language)
-
- def alignment(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support alignment checks.' % self.language)
-
- def has_function(self, *args, **kwargs):
- raise EnvironmentException('Language %s does not support function checks.' % self.language)
-
- def unixtype_flags_to_native(self, args):
- return args
-
-class CCompiler(Compiler):
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- super().__init__(exelist, version)
- self.language = 'c'
- self.default_suffix = 'c'
- self.id = 'unknown'
- self.is_cross = is_cross
- 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):
- return []
-
- def get_warn_args(self, level):
- return self.warn_args[level]
-
- def get_soname_args(self, shlib_name, path, soversion):
- return []
-
- def split_shlib_to_parts(self, fname):
- return (None, fname)
-
- # The default behaviour is this, override in
- # OSX and MSVC.
- def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
- return build_unix_rpath_args(build_dir, rpath_paths, install_rpath)
-
- def get_id(self):
- return self.id
-
- def get_dependency_gen_args(self, outtarget, outfile):
- return ['-MMD', '-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_language(self):
- return self.language
-
- def get_default_suffix(self):
- return self.default_suffix
-
- def get_exelist(self):
- return self.exelist[:]
-
- def get_linker_exelist(self):
- return self.exelist[:]
-
- def get_compile_only_args(self):
- return ['-c']
-
- 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 ['-lgcov']
-
- 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 can_compile(self, filename):
- suffix = filename.split('.')[-1]
- if suffix == 'c' or suffix == 'h':
- return True
- return False
-
- 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.split(header)[-1]]
-
- def get_pch_name(self, header_name):
- return os.path.split(header_name)[-1] + '.' + self.get_pch_suffix()
-
- def sanity_check(self, work_dir):
- mlog.debug('Sanity testing C compiler:', ' '.join(self.exelist))
- mlog.debug('Is cross compiler: %s.' % str(self.is_cross))
-
- source_name = os.path.join(work_dir, 'sanitycheckc.c')
- if self.is_cross:
- binname = 'sanitycheckc_cross'
- else:
- binname = 'sanitycheckc'
- binary_name = os.path.join(work_dir, binname)
- ofile = open(source_name, 'w')
- ofile.write('int main(int argc, char **argv) { int class=0; return class; }\n')
- ofile.close()
- if self.is_cross and 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 = ['-c']
- else:
- extra_flags = []
- cmdlist = self.exelist + extra_flags + [source_name, '-o', binary_name]
- pc = subprocess.Popen(cmdlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdo, stde) = pc.communicate()
- stdo = stdo.decode()
- stde = stde.decode()
- 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 %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]
- mlog.debug('Running test binary command: ' + ' '.join(cmdlist))
- pe = subprocess.Popen(cmdlist)
- pe.wait()
- if pe.returncode != 0:
- raise EnvironmentException('Executables created by C compiler %s are not runnable.' % self.name_string())
-
- def has_header(self, hname, extra_args=[]):
- templ = '''#include<%s>
-int someSymbolHereJustForFun;
-'''
- return self.compiles(templ % hname, extra_args)
-
- def compile(self, code, srcname, extra_args=[]):
- commands = self.get_exelist()
- commands.append(srcname)
- commands += extra_args
- mlog.debug('Running compile:')
- mlog.debug('Command line: ', ' '.join(commands))
- mlog.debug('Code:\n', code)
- p = subprocess.Popen(commands, cwd=os.path.split(srcname)[0], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stde, stdo) = p.communicate()
- stde = stde.decode()
- stdo = stdo.decode()
- mlog.debug('Compiler stdout:\n', stdo)
- mlog.debug('Compiler stderr:\n', stde)
- os.remove(srcname)
- return p
-
- def compiles(self, code, extra_args = []):
- suflen = len(self.default_suffix)
- (fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix)
- os.close(fd)
- ofile = open(srcname, 'w')
- ofile.write(code)
- ofile.close()
- extra_args = extra_args + self.get_compile_only_args()
- p = self.compile(code, srcname, extra_args)
- try:
- trial = srcname[:-suflen] + 'o'
- os.remove(trial)
- except FileNotFoundError:
- pass
- try:
- os.remove(srcname[:-suflen] + 'obj')
- except FileNotFoundError:
- pass
- return p.returncode == 0
-
- def links(self, code, extra_args = []):
- suflen = len(self.default_suffix)
- (fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix)
- os.close(fd)
- (fd, dstname) = tempfile.mkstemp()
- os.close(fd)
- ofile = open(srcname, 'w')
- ofile.write(code)
- ofile.close()
- extra_args = extra_args + self.get_output_args(dstname)
- p = self.compile(code, srcname, extra_args)
- try:
- os.remove(dstname)
- except FileNotFoundError:
- pass
- return p.returncode == 0
-
- def run(self, code, extra_args=[]):
- mlog.debug('Running code:\n\n', code)
- if self.is_cross and self.exe_wrapper is None:
- raise CrossNoRunException('Can not run test applications in this cross environment.')
- (fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix)
- os.close(fd)
- ofile = open(srcname, 'w')
- ofile.write(code)
- ofile.close()
- exename = srcname + '.exe' # Is guaranteed to be executable on every platform.
- commands = self.get_exelist()
- commands += extra_args
- commands.append(srcname)
- commands += self.get_output_args(exename)
- p = subprocess.Popen(commands, cwd=os.path.split(srcname)[0], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdo, stde) = p.communicate()
- stde = stde.decode()
- stdo = stdo.decode()
- mlog.debug('Compiler stdout:\n', stdo)
- mlog.debug('Compiler stderr:\n', stde)
- os.remove(srcname)
- if p.returncode != 0:
- return RunResult(False)
- if self.is_cross:
- cmdlist = self.exe_wrapper + [exename]
- else:
- cmdlist = exename
- try:
- pe = subprocess.Popen(cmdlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- except Exception as e:
- mlog.debug('Could not run: %s (error: %s)\n' % (cmdlist, e))
- return RunResult(False)
-
- (so, se) = pe.communicate()
- so = so.decode()
- se = se.decode()
- mlog.debug('Program stdout:\n', so)
- mlog.debug('Program stderr:\n', se)
- os.remove(exename)
- return RunResult(True, pe.returncode, so, se)
-
- def cross_sizeof(self, element, prefix, env, extra_args=[]):
- templ = '''%s
-int temparray[%d-sizeof(%s)];
-'''
- try:
- extra_args += env.cross_info.config['properties'][self.language + '_args']
- except KeyError:
- pass
- for i in range(1, 1024):
- code = templ % (prefix, i, element)
- if self.compiles(code, extra_args):
- return i
- raise EnvironmentException('Cross checking sizeof overflowed.')
-
- def sizeof(self, element, prefix, env, extra_args=[]):
- if self.is_cross:
- return self.cross_sizeof(element, prefix, env, extra_args)
- templ = '''#include<stdio.h>
-%s
-
-int main(int argc, char **argv) {
- printf("%%ld\\n", (long)(sizeof(%s)));
- return 0;
-};
-'''
- res = self.run(templ % (prefix, element), extra_args)
- if not res.compiled:
- raise EnvironmentException('Could not compile sizeof test.')
- if res.returncode != 0:
- raise EnvironmentException('Could not run sizeof test binary.')
- return int(res.stdout)
-
- def cross_alignment(self, typename, env, extra_args=[]):
- templ = '''#include<stddef.h>
-struct tmp {
- char c;
- %s target;
-};
-
-int testarray[%d-offsetof(struct tmp, target)];
-'''
- try:
- extra_args += env.cross_info.config['properties'][self.language + '_args']
- except KeyError:
- pass
- for i in range(1, 1024):
- code = templ % (typename, i)
- if self.compiles(code, extra_args):
- return i
- raise EnvironmentException('Cross checking offsetof overflowed.')
-
- def alignment(self, typename, env, extra_args=[]):
- if self.is_cross:
- return self.cross_alignment(typename, env, extra_args)
- templ = '''#include<stdio.h>
-#include<stddef.h>
-
-struct tmp {
- char c;
- %s target;
-};
-
-int main(int argc, char **argv) {
- printf("%%d", (int)offsetof(struct tmp, target));
- return 0;
-}
-'''
- res = self.run(templ % typename, extra_args)
- 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 has_function(self, funcname, prefix, env, extra_args=[]):
- # This fails (returns true) if funcname is a ptr or a variable.
- # The correct check is a lot more difficult.
- # Fix this to do that eventually.
- templ = '''%s
-int main(int argc, char **argv) {
- void *ptr = (void*)(%s);
- return 0;
-};
-'''
- 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))
- return self.compiles(templ % (prefix, funcname), extra_args)
-
- def has_member(self, typename, membername, prefix, extra_args=[]):
- templ = '''%s
-void bar() {
- %s foo;
- foo.%s;
-};
-'''
- return self.compiles(templ % (prefix, typename, membername), extra_args)
-
- def has_type(self, typename, prefix, extra_args):
- templ = '''%s
-void bar() {
- sizeof(%s);
-};
-'''
- return self.compiles(templ % (prefix, typename), extra_args)
-
- def thread_flags(self):
- return ['-pthread']
-
- def thread_link_flags(self):
- return ['-pthread']
-
-class CPPCompiler(CCompiler):
- def __init__(self, exelist, version, is_cross, exe_wrap):
- CCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
- self.language = 'cpp'
- self.default_suffix = 'cpp'
-
- def can_compile(self, filename):
- suffix = filename.split('.')[-1]
- if suffix in cpp_suffixes:
- return True
- return False
-
- def sanity_check(self, work_dir):
- source_name = os.path.join(work_dir, 'sanitycheckcpp.cc')
- binary_name = os.path.join(work_dir, 'sanitycheckcpp')
- ofile = open(source_name, 'w')
- ofile.write('class breakCCompiler;int main(int argc, char **argv) { return 0; }\n')
- ofile.close()
- if self.is_cross and self.exe_wrapper is None:
- # Skipping link because of the same reason as for C.
- # The comment in CCompiler explains why this is done.
- extra_flags = ['-c']
- else:
- extra_flags = []
- cmdlist = self.exelist + extra_flags + [source_name, '-o', binary_name]
- pc = subprocess.Popen(cmdlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdo, stde) = pc.communicate()
- stdo = stdo.decode()
- stde = stde.decode()
- 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('-----')
- 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)
- pe.wait()
- if pe.returncode != 0:
- raise EnvironmentException('Executables created by C++ compiler %s are not runnable.' % self.name_string())
-
-class ObjCCompiler(CCompiler):
- def __init__(self, exelist, version, is_cross, exe_wrap):
- CCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
- self.language = 'objc'
- self.default_suffix = 'm'
-
- def can_compile(self, filename):
- suffix = filename.split('.')[-1]
- if suffix == 'm' or suffix == 'h':
- return True
- return False
-
- def sanity_check(self, work_dir):
- source_name = os.path.join(work_dir, 'sanitycheckobjc.m')
- binary_name = os.path.join(work_dir, 'sanitycheckobjc')
- ofile = open(source_name, 'w')
- ofile.write('#import<stdio.h>\nint main(int argc, char **argv) { return 0; }\n')
- ofile.close()
- pc = subprocess.Popen(self.exelist + [source_name, '-o', binary_name])
- pc.wait()
- if pc.returncode != 0:
- raise EnvironmentException('ObjC compiler %s can not compile programs.' % self.name_string())
- 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 ObjCPPCompiler(CPPCompiler):
- def __init__(self, exelist, version, is_cross, exe_wrap):
- CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
- self.language = 'objcpp'
- self.default_suffix = 'mm'
-
- def can_compile(self, filename):
- suffix = filename.split('.')[-1]
- if suffix == 'mm' or suffix == 'h':
- return True
- return False
-
- def sanity_check(self, work_dir):
- source_name = os.path.join(work_dir, 'sanitycheckobjcpp.mm')
- binary_name = os.path.join(work_dir, 'sanitycheckobjcpp')
- ofile = open(source_name, 'w')
- ofile.write('#import<stdio.h>\nclass MyClass;int main(int argc, char **argv) { return 0; }\n')
- ofile.close()
- pc = subprocess.Popen(self.exelist + [source_name, '-o', binary_name])
- pc.wait()
- if pc.returncode != 0:
- raise EnvironmentException('ObjC++ compiler %s can not compile programs.' % self.name_string())
- 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 MonoCompiler(Compiler):
- def __init__(self, exelist, version):
- super().__init__(exelist, version)
- self.language = 'cs'
- self.default_suffix = 'cs'
- self.id = 'mono'
- self.monorunner = 'mono'
-
- def get_output_args(self, fname):
- return ['-out:' + fname]
-
- def get_link_args(self, fname):
- return ['-r:' + fname]
-
- def get_soname_args(self, shlib_name, path, soversion):
- 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, rpath_paths, install_rpath):
- return []
-
- def get_id(self):
- return self.id
-
- def get_dependency_gen_args(self, outtarget, outfile):
- return []
-
- def get_language(self):
- return self.language
-
- def get_default_suffix(self):
- return self.default_suffix
-
- def get_exelist(self):
- return self.exelist[:]
-
- 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_std_shared_lib_link_args(self):
- return []
-
- def can_compile(self, filename):
- suffix = filename.split('.')[-1]
- if suffix == 'cs':
- return True
- return False
-
- 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):
- src = 'sanity.cs'
- obj = 'sanity.exe'
- source_name = os.path.join(work_dir, src)
- ofile = open(source_name, 'w')
- ofile.write('''public class Sanity {
- static public void Main () {
- }
-}
-''')
- ofile.close()
- pc = subprocess.Popen(self.exelist + [src], cwd=work_dir)
- pc.wait()
- if pc.returncode != 0:
- raise EnvironmentException('Mono compiler %s can not compile programs.' % self.name_string())
- cmdlist = [self.monorunner, 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 JavaCompiler(Compiler):
- def __init__(self, exelist, version):
- super().__init__(exelist, version)
- self.language = 'java'
- self.default_suffix = 'java'
- self.id = 'unknown'
- self.javarunner = 'java'
-
- def get_soname_args(self, shlib_name, path, soversion):
- 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, rpath_paths, install_rpath):
- return []
-
- def get_id(self):
- return self.id
-
- def get_dependency_gen_args(self, outtarget, outfile):
- return []
-
- def get_language(self):
- return self.language
-
- def get_default_suffix(self):
- return self.default_suffix
-
- def get_exelist(self):
- return self.exelist[:]
-
- 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_std_shared_lib_link_args(self):
- return []
-
- def can_compile(self, filename):
- suffix = filename.split('.')[-1]
- if suffix == 'java':
- return True
- return False
-
- 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):
- src = 'SanityCheck.java'
- obj = 'SanityCheck'
- source_name = os.path.join(work_dir, src)
- ofile = open(source_name, 'w')
- ofile.write('''class SanityCheck {
- public static void main(String[] args) {
- int i;
- }
-}
-''')
- ofile.close()
- 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())
- cmdlist = [self.javarunner, 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())
-
- def needs_static_linker(self):
- return False
-
-class ValaCompiler(Compiler):
- def __init__(self, exelist, version):
- super().__init__(exelist, version)
- self.version = version
- self.id = 'unknown'
- self.language = 'vala'
-
- def name_string(self):
- return ' '.join(self.exelist)
-
- def needs_static_linker(self):
- return False # Because compiles into C.
-
- def get_exelist(self):
- return self.exelist
-
- def get_werror_args(self):
- return ['--fatal-warnings']
-
- def get_language(self):
- return self.language
-
- def sanity_check(self, work_dir):
- src = 'valatest.vala'
- source_name = os.path.join(work_dir, src)
- ofile = open(source_name, 'w')
- ofile.write('''class SanityCheck : Object {
-}
-''')
- ofile.close()
- pc = subprocess.Popen(self.exelist + ['-C', '-c', src], cwd=work_dir)
- pc.wait()
- if pc.returncode != 0:
- raise EnvironmentException('Vala compiler %s can not compile programs.' % self.name_string())
-
- def can_compile(self, filename):
- suffix = filename.split('.')[-1]
- return suffix in ('vala', 'vapi')
-
-class RustCompiler(Compiler):
- def __init__(self, exelist, version):
- super().__init__(exelist, version)
- self.id = 'unknown'
- self.language = 'rust'
-
- def needs_static_linker(self):
- return False
-
- def name_string(self):
- return ' '.join(self.exelist)
-
- def get_exelist(self):
- return self.exelist
-
- def get_id(self):
- return self.id
-
- def get_language(self):
- return self.language
-
- def sanity_check(self, work_dir):
- source_name = os.path.join(work_dir, 'sanity.rs')
- output_name = os.path.join(work_dir, 'rusttest')
- ofile = open(source_name, 'w')
- ofile.write('''fn main() {
-}
-''')
- ofile.close()
- 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 subprocess.call(output_name) != 0:
- raise EnvironmentException('Executables created by Rust compiler %s are not runnable.' % self.name_string())
-
- def can_compile(self, fname):
- return fname.endswith('.rs')
-
- def get_dependency_gen_args(self, outfile):
- return ['--dep-info', outfile]
-
- def get_buildtype_args(self, buildtype):
- return rust_buildtype_args[buildtype]
-
-class SwiftCompiler(Compiler):
- def __init__(self, exelist, version):
- super().__init__(exelist, version)
- self.version = version
- self.id = 'llvm'
- self.language = 'swift'
- self.is_cross = False
-
- def get_id(self):
- return self.id
-
- 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_exelist(self):
- return self.exelist
-
- def get_werror_args(self):
- return ['--fatal-warnings']
-
- def get_language(self):
- return self.language
-
- 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):
- src = 'swifttest.swift'
- source_name = os.path.join(work_dir, src)
- output_name = os.path.join(work_dir, 'swifttest')
- ofile = open(source_name, 'w')
- ofile.write('''1 + 2
-''')
- ofile.close()
- pc = subprocess.Popen(self.exelist + ['-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())
-
- def can_compile(self, filename):
- suffix = filename.split('.')[-1]
- return suffix in ('swift')
-
-class VisualStudioCCompiler(CCompiler):
- std_warn_args = ['/W3']
- std_opt_args= ['/O2']
- vs2010_always_args = ['/nologo', '/showIncludes']
- vs2013_always_args = ['/nologo', '/showIncludes', '/FS']
-
- def __init__(self, exelist, version, is_cross, exe_wrap):
- CCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
- self.id = 'msvc'
- if int(version.split('.')[0]) > 17:
- self.always_args = VisualStudioCCompiler.vs2013_always_args
- else:
- self.always_args = VisualStudioCCompiler.vs2010_always_args
- self.warn_args = {'1': ['/W2'],
- '2': ['/W3'],
- '3': ['/w4']}
-
- def get_always_args(self):
- return self.always_args
-
- 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.split(header)[-1].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.split(header)[-1]
- pchname = self.get_pch_name(header)
- return ['/FI' + base, '/Yu' + base, '/Fp' + os.path.join(pch_dir, pchname)]
-
- def get_compile_only_args(self):
- return ['/c']
-
- 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_pic_args(self):
- return ['/LD']
-
- def get_std_shared_lib_link_args(self):
- return ['/DLL']
-
- def gen_pch_args(self, header, source, pchname):
- objname = os.path.splitext(pchname)[0] + '.obj'
- return (objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname ])
-
- def sanity_check(self, work_dir):
- source_name = 'sanitycheckc.c'
- binary_name = 'sanitycheckc'
- ofile = open(os.path.join(work_dir, source_name), 'w')
- ofile.write('int main(int argc, char **argv) { return 0; }\n')
- ofile.close()
- pc = subprocess.Popen(self.exelist + [source_name, '/Fe' + binary_name],
- stdout=subprocess.DEVNULL,
- stderr=subprocess.DEVNULL,
- cwd=work_dir)
- pc.wait()
- if pc.returncode != 0:
- raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string())
- pe = subprocess.Popen(os.path.join(work_dir, binary_name))
- pe.wait()
- if pe.returncode != 0:
- raise EnvironmentException('Executables created by C++ compiler %s are not runnable.' % self.name_string())
-
- def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
- return []
-
- # FIXME, no idea what these should be.
- def thread_flags(self):
- return []
-
- def thread_link_flags(self):
- return []
-
- def get_options(self):
- return {'c_winlibs' : coredata.UserStringArrayOption('c_winlibs',
- 'Windows libs to link against.',
- msvc_winlibs)
- }
-
- def get_option_link_args(self, options):
- return options['c_winlibs'].value
-
- def unixtype_flags_to_native(self, args):
- result = []
- for i in args:
- if i.startswith('-L'):
- i = '/LIBPATH:' + i[2:]
- result.append(i)
- return result
-
- def get_include_args(self, path, is_system):
- if path == '':
- path = '.'
- # msvc does not have a concept of system header dirs.
- return ['-I' + path]
-
-class VisualStudioCPPCompiler(VisualStudioCCompiler):
- def __init__(self, exelist, version, is_cross, exe_wrap):
- VisualStudioCCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
- self.language = 'cpp'
- self.default_suffix = 'cpp'
-
- def can_compile(self, filename):
- suffix = filename.split('.')[-1]
- if suffix in cpp_suffixes:
- return True
- return False
-
- def sanity_check(self, work_dir):
- source_name = 'sanitycheckcpp.cpp'
- binary_name = 'sanitycheckcpp'
- ofile = open(os.path.join(work_dir, source_name), 'w')
- ofile.write('class BreakPlainC;int main(int argc, char **argv) { return 0; }\n')
- ofile.close()
- pc = subprocess.Popen(self.exelist + [source_name, '/Fe' + binary_name],
- stdout=subprocess.DEVNULL,
- stderr=subprocess.DEVNULL,
- cwd=work_dir)
- pc.wait()
- if pc.returncode != 0:
- raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string())
- pe = subprocess.Popen(os.path.join(work_dir, binary_name))
- pe.wait()
- if pe.returncode != 0:
- raise EnvironmentException('Executables created by C++ compiler %s are not runnable.' % self.name_string())
-
- def get_options(self):
- return {'cpp_eh' : coredata.UserComboOption('cpp_eh',
- 'C++ exception handling type.',
- ['none', 'a', 's', 'sc'],
- 'sc'),
- 'cpp_winlibs' : coredata.UserStringArrayOption('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
-
-GCC_STANDARD = 0
-GCC_OSX = 1
-GCC_MINGW = 2
-
-def get_gcc_soname_args(gcc_type, shlib_name, path, soversion):
- if soversion is None:
- sostr = ''
- else:
- sostr = '.' + soversion
- if gcc_type == GCC_STANDARD or gcc_type == GCC_MINGW:
- # Might not be correct for mingw but seems to work.
- return ['-Wl,-soname,lib%s.so%s' % (shlib_name, sostr)]
- elif gcc_type == GCC_OSX:
- return ['-install_name', os.path.join(path, 'lib' + shlib_name + '.dylib')]
- else:
- raise RuntimeError('Not implemented yet.')
-
-
-class GnuCCompiler(CCompiler):
- def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None):
- CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
- self.id = 'gcc'
- self.gcc_type = gcc_type
- self.warn_args = {'1': ['-Wall', '-Winvalid-pch'],
- '2': ['-Wall', '-Wextra', '-Winvalid-pch'],
- '3' : ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch']}
-
- def get_pic_args(self):
- if self.gcc_type == GCC_MINGW:
- return [] # On Window gcc defaults to fpic being always on.
- return ['-fPIC']
-
- def get_always_args(self):
- return ['-pipe']
-
- 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 'gch'
-
- def split_shlib_to_parts(self, fname):
- return (os.path.split(fname)[0], fname)
-
- def get_soname_args(self, shlib_name, path, soversion):
- return get_gcc_soname_args(self.gcc_type, shlib_name, path, soversion)
-
- def can_compile(self, filename):
- return super().can_compile(filename) or filename.split('.')[-1].lower() == 's' # Gcc can do asm, too.
-
- 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.UserStringArrayOption('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 []
-
-class GnuObjCCompiler(ObjCCompiler):
- std_opt_args = ['-O2']
-
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- ObjCCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
- self.id = 'gcc'
- # Not really correct, but GNU objc is only used on non-OSX non-win. File a bug
- # if this breaks your use case.
- self.gcc_type = GCC_STANDARD
- self.warn_args = {'1': ['-Wall', '-Winvalid-pch'],
- '2': ['-Wall', '-Wextra', '-Winvalid-pch'],
- '3' : ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch']}
-
- 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 'gch'
-
- def get_soname_args(self, shlib_name, path, soversion):
- return get_gcc_soname_args(self.gcc_type, shlib_name, path, soversion)
-
-class GnuObjCPPCompiler(ObjCPPCompiler):
- std_opt_args = ['-O2']
-
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- ObjCCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
- self.id = 'gcc'
- # Not really correct, but GNU objc is only used on non-OSX non-win. File a bug
- # if this breaks your use case.
- self.gcc_type = GCC_STANDARD
- self.warn_args = {'1': ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'],
- '2': ['-Wall', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor'],
- '3' : ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor']}
-
- 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 'gch'
-
- def get_soname_args(self, shlib_name, path, soversion):
- return get_gcc_soname_args(self.gcc_type, shlib_name, path, soversion)
-
-class ClangObjCCompiler(GnuObjCCompiler):
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- super().__init__(exelist, version, is_cross, exe_wrapper)
- self.id = 'clang'
-
-class ClangObjCPPCompiler(GnuObjCPPCompiler):
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- super().__init__(exelist, version, is_cross, exe_wrapper)
- self.id = 'clang'
-
-class ClangCCompiler(CCompiler):
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
- self.id = 'clang'
- self.warn_args = {'1': ['-Wall', '-Winvalid-pch'],
- '2': ['-Wall', '-Wextra', '-Winvalid-pch'],
- '3' : ['-Weverything']}
-
- 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 'pch'
-
- def can_compile(self, filename):
- return super().can_compile(filename) or filename.split('.')[-1].lower() == 's' # Clang can do asm, too.
-
- 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_options(self):
- return {'c_std' : coredata.UserComboOption('c_std', 'C language standard to use',
- ['none', 'c89', 'c99', 'c11'],
- '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 []
-
-class GnuCPPCompiler(CPPCompiler):
- # may need to separate the latter to extra_debug_args or something
- std_debug_args = ['-g']
-
- def __init__(self, exelist, version, gcc_type, is_cross, exe_wrap):
- CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
- self.id = 'gcc'
- self.gcc_type = gcc_type
- self.warn_args = {'1': ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'],
- '2': ['-Wall', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor'],
- '3': ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor']}
-
- def get_always_args(self):
- return ['-pipe']
-
- 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 'gch'
-
- def get_soname_args(self, shlib_name, path, soversion):
- return get_gcc_soname_args(self.gcc_type, shlib_name, path, soversion)
-
- def get_options(self):
- opts = {'cpp_std' : coredata.UserComboOption('cpp_std', 'C++ language standard to use',
- ['none', 'c++03', 'c++11', 'c++14'],
- 'none')}
- if self.gcc_type == GCC_MINGW:
- opts.update({
- 'cpp_winlibs': coredata.UserStringArrayOption('c_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)
- return args
-
- def get_option_link_args(self, options):
- if self.gcc_type == GCC_MINGW:
- return options['cpp_winlibs'].value
- return []
-
-class ClangCPPCompiler(CPPCompiler):
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
- self.id = 'clang'
- self.warn_args = {'1': ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'],
- '2': ['-Wall', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor'],
- '3': ['-Weverything']}
-
- 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 '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_options(self):
- return {'cpp_std' : coredata.UserComboOption('cpp_std', 'C++ language standard to use',
- ['none', 'c++03', 'c++11', 'c++14'],
- '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 FortranCompiler(Compiler):
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- super().__init__(exelist, version)
- self.is_cross = is_cross
- self.exe_wrapper = exe_wrapper
- self.language = 'fortran'
- # 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 get_id(self):
- return self.id
-
- def name_string(self):
- return ' '.join(self.exelist)
-
- def get_exelist(self):
- return self.exelist
-
- def get_language(self):
- return self.language
-
- def get_pic_args(self):
- if self.gcc_type == GCC_MINGW:
- return [] # On Windows gcc defaults to fpic being 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):
- source_name = os.path.join(work_dir, 'sanitycheckf.f90')
- binary_name = os.path.join(work_dir, 'sanitycheckf')
- ofile = open(source_name, 'w')
- ofile.write('''program prog
- print *, "Fortran compilation is working."
-end program prog
-''')
- ofile.close()
- pc = subprocess.Popen(self.exelist + [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):
- return gnulike_buildtype_linker_args[buildtype]
-
- def split_shlib_to_parts(self, fname):
- return (os.path.split(fname)[0], fname)
-
- def get_soname_args(self, shlib_name, path, soversion):
- return get_gcc_soname_args(self.gcc_type, shlib_name, path, soversion)
-
- 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', '-MMD', '-MQ', outtarget]
- return []
-
- def get_output_args(self, target):
- return ['-o', target]
-
- 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 can_compile(self, src):
- if hasattr(src, 'fname'):
- src = src.fname
- suffix = os.path.splitext(src)[1].lower()
- if suffix == '.f' or suffix == '.f95' or suffix == '.f90':
- return True
- return False
-
- def get_include_args(self, path, is_system):
- return ['-I' + path]
-
- 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, rpath_paths, install_rpath):
- return build_unix_rpath_args(build_dir, rpath_paths, install_rpath)
-
- def module_name_to_filename(self, module_name):
- return module_name.lower() + '.mod'
-
- def get_warn_args(self, level):
- return ['-Wall']
-
-
-class GnuFortranCompiler(FortranCompiler):
- def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
- self.gcc_type = gcc_type
- self.id = 'gcc'
-
- def get_always_args(self):
- return ['-pipe']
-
-class G95FortranCompiler(FortranCompiler):
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
- self.id = 'g95'
-
- def get_module_outdir_args(self, path):
- return ['-fmod='+path]
-
- def get_always_args(self):
- return ['-pipe']
-
-class SunFortranCompiler(FortranCompiler):
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
- self.id = 'sun'
-
- def get_dependency_gen_args(self, outtarget, outfile):
- return ['-fpp']
-
- def get_always_args(self):
- return []
-
- def get_warn_args(self):
- return []
-
- def get_module_outdir_args(self, path):
- return ['-moddir='+path]
-
-class IntelFortranCompiler(FortranCompiler):
- std_warn_args = ['-warn', 'all']
-
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
- self.id = 'intel'
-
- def get_module_outdir_args(self, path):
- return ['-module', path]
-
- def can_compile(self, src):
- suffix = os.path.splitext(src)[1].lower()
- if suffix == '.f' or suffix == '.f90':
- return True
- return False
-
- 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):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
- self.id = 'pathscale'
-
- def get_module_outdir_args(self, path):
- return ['-module', path]
-
- def can_compile(self, src):
- suffix = os.path.splitext(src)[1].lower()
- if suffix == '.f' or suffix == '.f90' or suffix == '.f95':
- return True
- return False
-
- 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):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
- self.id = 'pgi'
-
- def get_module_outdir_args(self, path):
- return ['-module', path]
-
- def can_compile(self, src):
- suffix = os.path.splitext(src)[1].lower()
- if suffix == '.f' or suffix == '.f90' or suffix == '.f95':
- return True
- return False
-
- def get_warn_args(self, level):
- return PGIFortranCompiler.std_warn_args
-
-
-class Open64FortranCompiler(FortranCompiler):
- std_warn_args = ['-fullwarn']
-
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
- self.id = 'open64'
-
- def get_module_outdir_args(self, path):
- return ['-module', path]
-
- def can_compile(self, src):
- suffix = os.path.splitext(src)[1].lower()
- if suffix == '.f' or suffix == '.f90' or suffix == '.f95':
- return True
- return False
-
- 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):
- super().__init__(exelist, version, is_cross, exe_wrapper=None)
- self.id = 'nagfor'
-
- def get_module_outdir_args(self, path):
- return ['-mdir', path]
-
- def get_always_args(self):
- return []
-
- def can_compile(self, src):
- suffix = os.path.splitext(src)[1].lower()
- if suffix == '.f' or suffix == '.f90' or suffix == '.f95':
- return True
- return False
-
- def get_warn_args(self, level):
- return NAGFortranCompiler.std_warn_args
-
-
-class VisualStudioLinker():
- 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, rpath_paths, install_rpath):
- return []
-
- def thread_link_flags(self):
- return []
-
- def get_option_link_args(self, options):
- return []
-
- def unixtype_flags_to_native(self, args):
- return args
-
-class ArLinker():
- std_args = ['csr']
-
- def __init__(self, exelist):
- self.exelist = exelist
- self.id = 'ar'
-
- def build_rpath_args(self, build_dir, rpath_paths, 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):
- return []
-
- def get_option_link_args(self, options):
- return []
-
- def unixtype_flags_to_native(self, args):
- return args
diff --git a/meson/coredata.py b/meson/coredata.py
deleted file mode 100644
index 5b1102c..0000000
--- a/meson/coredata.py
+++ /dev/null
@@ -1,222 +0,0 @@
-# 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.
-
-import pickle, os, uuid
-
-version = '0.29.0-research'
-
-build_types = ['plain', 'debug', 'debugoptimized', 'release']
-layouts = ['mirror', 'flat']
-warning_levels = ['1', '2', '3']
-libtypelist = ['shared', 'static']
-
-builtin_options = {'buildtype': True,
- 'strip': True,
- 'coverage': True,
- 'pch': True,
- 'unity': True,
- 'prefix': True,
- 'libdir' : True,
- 'bindir' : True,
- 'includedir' : True,
- 'datadir' : True,
- 'mandir' : True,
- 'localedir' : True,
- 'werror' : True,
- 'warning_level': True,
- 'layout' : True,
- 'default_library': True,
- }
-
-class MesonException(Exception):
- def __init__(self, *args, **kwargs):
- Exception.__init__(self, *args, **kwargs)
-
-class UserOption:
- def __init__(self, name, description, choices):
- super().__init__()
- self.name = name
- self.choices = choices
- self.description = description
-
- def parse_string(self, valuestring):
- return valuestring
-
-class UserStringOption(UserOption):
- def __init__(self, name, description, value, choices=None):
- super().__init__(name, description, choices)
- 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(newvalue), self.name))
- if self.name == 'prefix' and not os.path.isabs(value):
- raise MesonException('Prefix option must be an absolute path.')
- if self.name in ('libdir', 'bindir', 'includedir', 'datadir', 'mandir', 'localedir') \
- and os.path.isabs(value):
- raise MesonException('Option %s must not be an absolute path.' % self.name)
-
- def set_value(self, newvalue):
- self.validate(newvalue)
- self.value = newvalue
-
-class UserBooleanOption(UserOption):
- def __init__(self, name, description, value):
- super().__init__(name, description, '[true, false]')
- 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 parse_string(self, valuestring):
- if valuestring == 'false':
- return False
- if valuestring == 'true':
- return True
- raise MesonException('Value "%s" for boolean option "%s" is not a boolean.' % (valuestring, self.name))
-
-class UserComboOption(UserOption):
- def __init__(self, name, description, choices, value):
- super().__init__(name, description, choices)
- 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
-
-class UserStringArrayOption(UserOption):
- def __init__(self, name, description, value, **kwargs):
- super().__init__(name, description, kwargs.get('choices', []))
- self.set_value(value)
-
- def set_value(self, newvalue):
- if isinstance(newvalue, str):
- if not newvalue.startswith('['):
- raise MesonException('Valuestring does not define an array: ' + newvalue)
- newvalue = eval(newvalue, {}, {}) # Yes, it is unsafe.
- if not isinstance(newvalue, list):
- raise MesonException('String array value is not an array.')
- for i in newvalue:
- if not isinstance(i, str):
- raise MesonException('String array element not a string.')
- self.value = newvalue
-
-# 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.builtin_options = {}
- self.init_builtins(options)
- self.user_options = {}
- self.compiler_options = {}
- self.external_args = {} # These are set from "the outside" with e.g. mesonconf
- self.external_link_args = {}
- if options.cross_file is not None:
- self.cross_file = os.path.join(os.getcwd(), options.cross_file)
- else:
- self.cross_file = None
-
- self.compilers = {}
- self.cross_compilers = {}
- self.deps = {}
- self.ext_progs = {}
- self.modules = {}
-
- def init_builtins(self, options):
- self.builtin_options['prefix'] = UserStringOption('prefix', 'Installation prefix', options.prefix)
- self.builtin_options['libdir'] = UserStringOption('libdir', 'Library dir', options.libdir)
- self.builtin_options['bindir'] = UserStringOption('bindir', 'Executable dir', options.bindir)
- self.builtin_options['includedir'] = UserStringOption('includedir', 'Include dir', options.includedir)
- self.builtin_options['datadir'] = UserStringOption('datadir', 'Data directory', options.datadir)
- self.builtin_options['mandir'] = UserStringOption('mandir', 'Man page dir', options.mandir)
- self.builtin_options['localedir'] = UserStringOption('localedir', 'Locale dir', options.localedir)
- self.builtin_options['backend'] = UserStringOption('backend', 'Backend to use', options.backend)
- self.builtin_options['buildtype'] = UserComboOption('buildtype', 'Build type', build_types, options.buildtype)
- self.builtin_options['strip'] = UserBooleanOption('strip', 'Strip on install', options.strip)
- self.builtin_options['use_pch'] = UserBooleanOption('use_pch', 'Use precompiled headers', options.use_pch)
- self.builtin_options['unity'] = UserBooleanOption('unity', 'Unity build', options.unity)
- self.builtin_options['coverage'] = UserBooleanOption('coverage', 'Enable coverage', options.coverage)
- self.builtin_options['warning_level'] = UserComboOption('warning_level', 'Warning level', warning_levels, options.warning_level)
- self.builtin_options['werror'] = UserBooleanOption('werror', 'Warnings are errors', options.werror)
- self.builtin_options['layout'] = UserComboOption('layout', 'Build dir layout', layouts, options.layout)
- self.builtin_options['default_library'] = UserComboOption('default_library', 'Default_library type', libtypelist, options.default_library)
-
- def get_builtin_option(self, optname):
- if optname in self.builtin_options:
- return self.builtin_options[optname].value
- raise RuntimeError('Tried to get unknown builtin option %s' % optname)
-
- def set_builtin_option(self, optname, value):
- if optname in self.builtin_options:
- self.builtin_options[optname].set_value(value)
- else:
- raise RuntimeError('Tried to set unknown builtin option %s' % optname)
-
- def is_builtin_option(self, optname):
- return optname in self.builtin_options
-
-def load(filename):
- obj = pickle.load(open(filename, 'rb'))
- if not isinstance(obj, CoreData):
- raise RuntimeError('Core data file is corrupted.')
- if obj.version != version:
- raise RuntimeError('Build tree has been generated with Meson version %s, which is incompatible with current version %s.'%
- (obj.version, version))
- return obj
-
-def save(obj, filename):
- if obj.version != version:
- raise RuntimeError('Fatal version mismatch corruption.')
- pickle.dump(obj, open(filename, 'wb'))
-
-forbidden_target_names = {'clean': None,
- 'clean-gcno': None,
- 'clean-gcda': None,
- 'coverage-text': None,
- 'coverage-xml': None,
- 'coverage-html': None,
- 'phony': None,
- 'PHONY': None,
- 'all': None,
- 'test': None,
- 'test-valgrind': None,
- 'test-': None,
- 'benchmark': None,
- 'install': None,
- 'build.ninja': None,
- }
diff --git a/meson/dependencies.py b/meson/dependencies.py
deleted file mode 100644
index 974559f..0000000
--- a/meson/dependencies.py
+++ /dev/null
@@ -1,1120 +0,0 @@
-# Copyright 2013-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 file contains the detection logic for external
-# dependencies. Mostly just uses pkg-config but also contains
-# custom logic for packages that don't provide them.
-
-# Currently one file, should probably be split into a
-# package before this gets too big.
-
-import re
-import os, stat, glob, subprocess, shutil
-from . coredata import MesonException
-from . import mlog
-from . import mesonlib
-
-class DependencyException(MesonException):
- def __init__(self, *args, **kwargs):
- MesonException.__init__(self, *args, **kwargs)
-
-class Dependency():
- def __init__(self):
- self.name = "null"
- self.is_found = False
-
- def get_compile_args(self):
- return []
-
- def get_link_args(self):
- return []
-
- 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 []
-
- def get_name(self):
- return self.name
-
- def get_exe_args(self):
- return []
-
- def need_threads(self):
- return False
-
-class InternalDependency():
- def __init__(self, incdirs, libraries, sources, ext_deps):
- super().__init__()
- self.include_directories = incdirs
- self.libraries = libraries
- self.sources = sources
- self.ext_deps = ext_deps
-
-class PkgConfigDependency(Dependency):
- pkgconfig_found = None
-
- def __init__(self, name, environment, kwargs):
- Dependency.__init__(self)
- self.is_libtool = False
- self.required = kwargs.get('required', True)
- if 'native' in kwargs and environment.is_cross_build():
- want_cross = not kwargs['native']
- else:
- want_cross = environment.is_cross_build()
- self.name = name
- if PkgConfigDependency.pkgconfig_found is None:
- self.check_pkgconfig()
-
- self.is_found = False
- if not PkgConfigDependency.pkgconfig_found:
- if self.required:
- raise DependencyException('Pkg-config not found.')
- self.cargs = []
- self.libs = []
- return
- if environment.is_cross_build() and want_cross:
- if "pkgconfig" not in environment.cross_info.config["binaries"]:
- raise DependencyException('Pkg-config binary missing from cross file.')
- pkgbin = environment.cross_info.config["binaries"]['pkgconfig']
- self.type_string = 'Cross'
- else:
- pkgbin = 'pkg-config'
- self.type_string = 'Native'
-
- mlog.debug('Determining dependency %s with pkg-config executable %s.' % (name, pkgbin))
- self.pkgbin = pkgbin
- p = subprocess.Popen([pkgbin, '--modversion', name],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out = p.communicate()[0]
- if p.returncode != 0:
- if self.required:
- raise DependencyException('%s dependency %s not found.' % (self.type_string, name))
- self.modversion = 'none'
- self.cargs = []
- self.libs = []
- else:
- self.modversion = out.decode().strip()
- mlog.log('%s dependency' % self.type_string, mlog.bold(name), 'found:',
- mlog.green('YES'), self.modversion)
- self.version_requirement = kwargs.get('version', None)
- if self.version_requirement is None:
- self.is_found = True
- else:
- if not isinstance(self.version_requirement, str):
- raise DependencyException('Version argument must be string.')
- self.is_found = mesonlib.version_compare(self.modversion, self.version_requirement)
- if not self.is_found and self.required:
- raise DependencyException(
- 'Invalid version of a dependency, needed %s %s found %s.' %
- (name, self.version_requirement, self.modversion))
- if not self.is_found:
- return
- p = subprocess.Popen([pkgbin, '--cflags', name], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out = p.communicate()[0]
- if p.returncode != 0:
- raise DependencyException('Could not generate cargs for %s:\n\n%s' % \
- (name, out.decode(errors='ignore')))
- self.cargs = out.decode().split()
-
- p = subprocess.Popen([pkgbin, '--libs', name], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out = p.communicate()[0]
- if p.returncode != 0:
- raise DependencyException('Could not generate libs for %s:\n\n%s' % \
- (name, out.decode(errors='ignore')))
- self.libs = []
- for lib in out.decode().split():
- if 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.libs.append(lib)
-
- def get_variable(self, variable_name):
- p = subprocess.Popen([self.pkgbin, '--variable=%s' % variable_name, self.name],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out = p.communicate()[0]
- if p.returncode != 0:
- if self.required:
- raise DependencyException('%s dependency %s not found.' %
- (self.type_string, self.name))
- else:
- variable = out.decode().strip()
- mlog.debug('return of subprocess : %s' % variable)
-
- return variable
-
- def get_modversion(self):
- return self.modversion
-
- def get_compile_args(self):
- return self.cargs
-
- def get_link_args(self):
- return self.libs
-
- def check_pkgconfig(self):
- try:
- p = subprocess.Popen(['pkg-config', '--version'], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out = p.communicate()[0]
- if p.returncode == 0:
- mlog.log('Found pkg-config:', mlog.bold(shutil.which('pkg-config')),
- '(%s)' % out.decode().strip())
- PkgConfigDependency.pkgconfig_found = True
- return
- except Exception:
- pass
- PkgConfigDependency.pkgconfig_found = False
- mlog.log('Found Pkg-config:', mlog.red('NO'))
-
- def found(self):
- return self.is_found
-
- def extract_field(self, la_file, fieldname):
- for line in open(la_file):
- 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 WxDependency(Dependency):
- wx_found = None
-
- def __init__(self, environment, kwargs):
- Dependency.__init__(self)
- if WxDependency.wx_found is None:
- self.check_wxconfig()
-
- if not WxDependency.wx_found:
- raise DependencyException('Wx-config not found.')
- self.is_found = False
- p = subprocess.Popen([self.wxc, '--version'],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out = p.communicate()[0]
- if p.returncode != 0:
- mlog.log('Dependency wxwidgets found:', mlog.red('NO'))
- self.cargs = []
- self.libs = []
- else:
- self.modversion = out.decode().strip()
- version_req = kwargs.get('version', None)
- if version_req is not None:
- if not mesonlib.version_compare(self.modversion, version_req):
- mlog.log('Wxwidgets version %s does not fullfill requirement %s' %\
- (self.modversion, version_req))
- return
- mlog.log('Dependency wxwidgets found:', mlog.green('YES'))
- self.is_found = True
- 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.
- p = subprocess.Popen([self.wxc, '--cxxflags'],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out = p.communicate()[0]
- if p.returncode != 0:
- raise DependencyException('Could not generate cargs for wxwidgets.')
- self.cargs = out.decode().split()
-
- p = subprocess.Popen([self.wxc, '--libs'] + self.requested_modules,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out = p.communicate()[0]
- if p.returncode != 0:
- raise DependencyException('Could not generate libs for wxwidgets.')
- self.libs = out.decode().split()
-
- def get_requested(self, kwargs):
- modules = 'modules'
- if not modules in kwargs:
- return []
- candidates = kwargs[modules]
- if isinstance(candidates, str):
- return [candidates]
- for c in candidates:
- if not isinstance(c, str):
- raise DependencyException('wxwidgets module argument is not a string.')
- return candidates
-
- def get_modversion(self):
- return self.modversion
-
- def get_compile_args(self):
- return self.cargs
-
- def get_link_args(self):
- return self.libs
-
- def check_wxconfig(self):
- for wxc in ['wx-config-3.0', 'wx-config']:
- try:
- p = subprocess.Popen([wxc, '--version'], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out = p.communicate()[0]
- if p.returncode == 0:
- mlog.log('Found wx-config:', mlog.bold(shutil.which(wxc)),
- '(%s)' % out.decode().strip())
- self.wxc = wxc
- WxDependency.wx_found = True
- return
- except Exception:
- pass
- WxDependency.wxconfig_found = False
- mlog.log('Found wx-config:', mlog.red('NO'))
-
- def found(self):
- return self.is_found
-
-class ExternalProgram():
- def __init__(self, name, fullpath=None, silent=False, search_dir=None):
- self.name = name
- self.fullpath = None
- if fullpath is not None:
- if not isinstance(fullpath, list):
- self.fullpath = [fullpath]
- else:
- self.fullpath = fullpath
- else:
- self.fullpath = [shutil.which(name)]
- if self.fullpath[0] is None and search_dir is not None:
- trial = os.path.join(search_dir, name)
- suffix = os.path.splitext(trial)[-1].lower()[1:]
- if mesonlib.is_windows() and (suffix == 'exe' or suffix == 'com'\
- or suffix == 'bat'):
- self.fullpath = [trial]
- elif not mesonlib.is_windows() and os.access(trial, os.X_OK):
- self.fullpath = [trial]
- else:
- # 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.
- try:
- first_line = open(trial).readline().strip()
- if first_line.startswith('#!'):
- commands = first_line[2:].split('#')[0].strip().split()
- if mesonlib.is_windows():
- # Windows does not have /usr/bin.
- commands[0] = commands[0].split('/')[-1]
- if commands[0] == 'env':
- commands = commands[1:]
- self.fullpath = commands + [trial]
- except Exception:
- pass
- if not silent:
- if self.found():
- mlog.log('Program', mlog.bold(name), 'found:', mlog.green('YES'),
- '(%s)' % ' '.join(self.fullpath))
- else:
- mlog.log('Program', mlog.bold(name), 'found:', mlog.red('NO'))
-
- def found(self):
- return self.fullpath[0] is not None
-
- def get_command(self):
- return self.fullpath
-
- def get_name(self):
- return self.name
-
-class ExternalLibrary(Dependency):
- def __init__(self, name, fullpath=None, silent=False):
- super().__init__()
- self.name = name
- self.fullpath = fullpath
- if not silent:
- if self.found():
- mlog.log('Library', mlog.bold(name), 'found:', mlog.green('YES'),
- '(%s)' % self.fullpath)
- else:
- mlog.log('Library', mlog.bold(name), 'found:', mlog.red('NO'))
-
- def found(self):
- return self.fullpath is not None
-
- def get_link_args(self):
- if self.found():
- return [self.fullpath]
- return []
-
-class BoostDependency(Dependency):
- # Some boost libraries have different names for
- # their sources and libraries. This dict maps
- # between the two.
- name2lib = {'test' : 'unit_test_framework'}
-
- def __init__(self, environment, kwargs):
- Dependency.__init__(self)
- self.name = 'boost'
- self.libdir = ''
- try:
- self.boost_root = os.environ['BOOST_ROOT']
- if not os.path.isabs(self.boost_root):
- raise DependencyException('BOOST_ROOT must be an absolute path.')
- except KeyError:
- self.boost_root = None
- if self.boost_root is None:
- if mesonlib.is_windows():
- self.boost_root = self.detect_win_root()
- self.incdir = self.boost_root
- else:
- self.incdir = '/usr/include'
- else:
- self.incdir = os.path.join(self.boost_root, 'include')
- self.boost_inc_subdir = os.path.join(self.incdir, 'boost')
- mlog.debug('Boost library root dir is', self.boost_root)
- self.src_modules = {}
- self.lib_modules = {}
- self.lib_modules_mt = {}
- self.detect_version()
- self.requested_modules = self.get_requested(kwargs)
- module_str = ', '.join(self.requested_modules)
- if self.version is not None:
- self.detect_src_modules()
- self.detect_lib_modules()
- self.validate_requested()
- if self.boost_root is not None:
- info = self.version + ', ' + self.boost_root
- else:
- info = self.version
- mlog.log('Dependency Boost (%s) found:' % module_str, mlog.green('YES'),
- '(' + info + ')')
- else:
- mlog.log("Dependency Boost (%s) found:" % module_str, mlog.red('NO'))
-
- def detect_win_root(self):
- globtext = 'c:\\local\\boost_*'
- files = glob.glob(globtext)
- if len(files) > 0:
- return files[0]
- return 'C:\\'
-
- def get_compile_args(self):
- args = []
- if self.boost_root is not None:
- if mesonlib.is_windows():
- args.append('-I' + self.boost_root)
- else:
- args.append('-I' + os.path.join(self.boost_root, 'include'))
- else:
- args.append('-I' + self.incdir)
- return args
-
- def get_requested(self, kwargs):
- candidates = kwargs.get('modules', [])
- if isinstance(candidates, str):
- return [candidates]
- for c in candidates:
- if not isinstance(c, str):
- raise DependencyException('Boost module argument is not a string.')
- return candidates
-
- def validate_requested(self):
- for m in self.requested_modules:
- if m not in self.src_modules:
- raise DependencyException('Requested Boost module "%s" not found.' % m)
-
- def found(self):
- return self.version is not None
-
- def get_version(self):
- return self.version
-
- def detect_version(self):
- try:
- ifile = open(os.path.join(self.boost_inc_subdir, 'version.hpp'))
- except FileNotFoundError:
- self.version = None
- return
- for line in ifile:
- if line.startswith("#define") and 'BOOST_LIB_VERSION' in line:
- ver = line.split()[-1]
- ver = ver[1:-1]
- self.version = ver.replace('_', '.')
- return
- self.version = None
-
- def detect_src_modules(self):
- for entry in os.listdir(self.boost_inc_subdir):
- entry = os.path.join(self.boost_inc_subdir, entry)
- if stat.S_ISDIR(os.stat(entry).st_mode):
- self.src_modules[os.path.split(entry)[-1]] = True
-
- def detect_lib_modules(self):
- if mesonlib.is_windows():
- return self.detect_lib_modules_win()
- return self.detect_lib_modules_nix()
-
- def detect_lib_modules_win(self):
- if mesonlib.is_32bit():
- gl = 'lib32*'
- else:
- gl = 'lib64*'
- libdir = glob.glob(os.path.join(self.boost_root, gl))
- if len(libdir) == 0:
- return
- libdir = libdir[0]
- self.libdir = libdir
- globber = 'boost_*-gd-*.lib' # FIXME
- for entry in glob.glob(os.path.join(libdir, globber)):
- (_, fname) = os.path.split(entry)
- base = fname.split('_', 1)[1]
- modname = base.split('-', 1)[0]
- self.lib_modules_mt[modname] = fname
-
- def detect_lib_modules_nix(self):
- libsuffix = None
- if mesonlib.is_osx():
- libsuffix = 'dylib'
- else:
- libsuffix = 'so'
-
- globber = 'libboost_*.{}'.format(libsuffix)
- if self.boost_root is None:
- libdirs = mesonlib.get_library_dirs()
- else:
- libdirs = [os.path.join(self.boost_root, 'lib')]
- for libdir in libdirs:
- for entry in glob.glob(os.path.join(libdir, globber)):
- lib = os.path.basename(entry)
- name = lib.split('.')[0].split('_', 1)[-1]
- # I'm not 100% sure what to do here. Some distros
- # have modules such as thread only as -mt versions.
- if entry.endswith('-mt.so'):
- self.lib_modules_mt[name] = True
- else:
- self.lib_modules[name] = True
-
- def get_win_link_args(self):
- args = []
- if self.boost_root:
- args.append('-L' + self.libdir)
- for module in self.requested_modules:
- module = BoostDependency.name2lib.get(module, module)
- if module in self.lib_modules_mt:
- args.append(self.lib_modules_mt[module])
- return args
-
- def get_link_args(self):
- if mesonlib.is_windows():
- return self.get_win_link_args()
- args = []
- if self.boost_root:
- args.append('-L' + os.path.join(self.boost_root, 'lib'))
- for module in self.requested_modules:
- module = BoostDependency.name2lib.get(module, module)
- if module in self.lib_modules or module in self.lib_modules_mt:
- linkcmd = '-lboost_' + module
- args.append(linkcmd)
- # FIXME a hack, but Boost's testing framework has a lot of
- # different options and it's hard to determine what to do
- # without feedback from actual users. Update this
- # as we get more bug reports.
- if module == 'unit_testing_framework':
- args.append('-lboost_test_exec_monitor')
- elif module + '-mt' in self.lib_modules_mt:
- linkcmd = '-lboost_' + module + '-mt'
- args.append(linkcmd)
- if module == 'unit_testing_framework':
- args.append('-lboost_test_exec_monitor-mt')
- return args
-
- def get_sources(self):
- return []
-
- def need_threads(self):
- return 'thread' in self.requested_modules
-
-class GTestDependency(Dependency):
- def __init__(self, environment, kwargs):
- Dependency.__init__(self)
- self.main = kwargs.get('main', False)
- self.name = 'gtest'
- self.libname = 'libgtest.so'
- self.libmain_name = 'libgtest_main.so'
- self.include_dir = '/usr/include'
- self.src_include_dir = '/usr/src/gtest'
- self.src_dir = '/usr/src/gtest/src'
- 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.detect()
-
- def found(self):
- return self.is_found
-
- def detect(self):
- trial_dirs = mesonlib.get_library_dirs()
- glib_found = False
- gmain_found = False
- for d in trial_dirs:
- if os.path.isfile(os.path.join(d, self.libname)):
- glib_found = True
- if os.path.isfile(os.path.join(d, self.libmain_name)):
- gmain_found = True
- if glib_found and gmain_found:
- self.is_found = True
- self.compile_args = []
- self.link_args = ['-lgtest']
- if self.main:
- self.link_args.append('-lgtest_main')
- self.sources = []
- mlog.log('Dependency GTest found:', mlog.green('YES'), '(prebuilt)')
- elif os.path.exists(self.src_dir):
- 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
- return self.is_found
-
- def get_compile_args(self):
- arr = []
- if self.include_dir != '/usr/include':
- arr.append('-I' + self.include_dir)
- arr.append('-I' + self.src_include_dir)
- return arr
-
- def get_link_args(self):
- return self.link_args
- def get_version(self):
- return '1.something_maybe'
- def get_sources(self):
- return self.sources
-
- def need_threads(self):
- return True
-
-class GMockDependency(Dependency):
- def __init__(self, environment, kwargs):
- Dependency.__init__(self)
- # GMock may be a library or just source.
- # Work with both.
- self.name = 'gmock'
- self.libname = 'libgmock.so'
- trial_dirs = mesonlib.get_library_dirs()
- gmock_found = False
- for d in trial_dirs:
- if os.path.isfile(os.path.join(d, self.libname)):
- gmock_found = True
- if gmock_found:
- self.is_found = True
- self.compile_args = []
- self.link_args = ['-lgmock']
- self.sources = []
- mlog.log('Dependency GMock found:', mlog.green('YES'), '(prebuilt)')
- return
-
- for d in ['/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.
- self.compile_args = ['-I/usr/src/gmock', '-I/usr/src/gmock/src']
- 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
-
- def get_version(self):
- return '1.something_maybe'
-
- def get_compile_args(self):
- return self.compile_args
-
- def get_sources(self):
- return self.sources
-
- def get_link_args(self):
- return self.link_args
-
- def found(self):
- return self.is_found
-
-class Qt5Dependency(Dependency):
- def __init__(self, environment, kwargs):
- Dependency.__init__(self)
- self.name = 'qt5'
- self.root = '/usr'
- mods = kwargs.get('modules', [])
- self.cargs = []
- self.largs = []
- self.is_found = False
- if isinstance(mods, str):
- mods = [mods]
- if len(mods) == 0:
- raise DependencyException('No Qt5 modules specified.')
- type_text = 'native'
- if environment.is_cross_build() and kwargs.get('native', False):
- type_text = 'cross'
- self.pkgconfig_detect(mods, environment, kwargs)
- elif not environment.is_cross_build() and shutil.which('pkg-config') is not None:
- self.pkgconfig_detect(mods, environment, kwargs)
- elif shutil.which('qmake') is not None:
- self.qmake_detect(mods, kwargs)
- else:
- self.version = 'none'
- if not self.is_found:
- mlog.log('Qt5 %s dependency found: ' % type_text, mlog.red('NO'))
- else:
- mlog.log('Qt5 %s dependency found: ' % type_text, mlog.green('YES'))
-
- def pkgconfig_detect(self, mods, environment, kwargs):
- modules = []
- for module in mods:
- modules.append(PkgConfigDependency('Qt5' + module, environment, kwargs))
- for m in modules:
- self.cargs += m.get_compile_args()
- self.largs += m.get_link_args()
- self.is_found = True
- self.version = modules[0].modversion
-
- def qmake_detect(self, mods, kwargs):
- pc = subprocess.Popen(['qmake', '-v'], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- (stdo, _) = pc.communicate()
- if pc.returncode != 0:
- return
- stdo = stdo.decode()
- if not 'version 5' in stdo:
- mlog.log('QMake is not for Qt5.')
- return
- self.version = re.search('5(\.\d+)+', stdo).group(0)
- (stdo, _) = subprocess.Popen(['qmake', '-query'], stdout=subprocess.PIPE).communicate()
- qvars = {}
- for line in stdo.decode().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.cargs.append('-I' + incdir)
- libdir = qvars['QT_INSTALL_LIBS']
- bindir = qvars['QT_INSTALL_BINS']
- #self.largs.append('-L' + libdir)
- for module in mods:
- mincdir = os.path.join(incdir, 'Qt' + module)
- self.cargs.append('-I' + mincdir)
- libfile = os.path.join(libdir, 'Qt5' + module + '.lib')
- if not os.path.isfile(libfile):
- # MinGW links directly to .dll, not to .lib.
- libfile = os.path.join(bindir, 'Qt5' + module + '.dll')
- self.largs.append(libfile)
- self.is_found = True
-
- def framework_detect(self, qvars, modules, kwargs):
- libdir = qvars['QT_INSTALL_LIBS']
- for m in modules:
- fname = 'Qt' + m
- fwdep = ExtraFrameworkDependency(fname, kwargs.get('required', True), libdir)
- self.cargs.append('-F' + libdir)
- if fwdep.found():
- self.is_found = True
- self.cargs += fwdep.get_compile_args()
- self.largs += fwdep.get_link_args()
-
-
- def get_version(self):
- return self.version
-
- def get_compile_args(self):
- return self.cargs
-
- def get_sources(self):
- return []
-
- def get_link_args(self):
- return self.largs
-
- def found(self):
- return self.is_found
-
- def get_exe_args(self):
- # 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.
- # Fix this to be more portable, especially to MSVC.
- return ['-fPIC']
-
-class Qt4Dependency(Dependency):
- def __init__(self, environment, kwargs):
- Dependency.__init__(self)
- self.name = 'qt4'
- self.root = '/usr'
- self.modules = []
- mods = kwargs.get('modules', [])
- if isinstance(mods, str):
- mods = [mods]
- for module in mods:
- self.modules.append(PkgConfigDependency('Qt' + module, environment, kwargs))
- if len(self.modules) == 0:
- raise DependencyException('No Qt4 modules specified.')
-
- def get_version(self):
- return self.modules[0].get_version()
-
- def get_compile_args(self):
- args = []
- for m in self.modules:
- args += m.get_compile_args()
- return args
-
- def get_sources(self):
- return []
-
- def get_link_args(self):
- args = []
- for module in self.modules:
- args += module.get_link_args()
- return args
-
- def found(self):
- for i in self.modules:
- if not i.found():
- return False
- return True
-
-class GnuStepDependency(Dependency):
- def __init__(self, environment, kwargs):
- Dependency.__init__(self)
- self.modules = kwargs.get('modules', [])
- self.detect()
-
- def detect(self):
- confprog = 'gnustep-config'
- try:
- gp = subprocess.Popen([confprog, '--help'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- gp.communicate()
- except FileNotFoundError:
- self.args = None
- mlog.log('Dependency GnuStep found:', mlog.red('NO'), '(no gnustep-config)')
- return
- if gp.returncode != 0:
- self.args = None
- mlog.log('Dependency GnuStep found:', mlog.red('NO'))
- return
- if 'gui' in self.modules:
- arg = '--gui-libs'
- else:
- arg = '--base-libs'
- fp = subprocess.Popen([confprog, '--objc-flags'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (flagtxt, flagerr) = fp.communicate()
- flagtxt = flagtxt.decode()
- flagerr = flagerr.decode()
- if fp.returncode != 0:
- raise DependencyException('Error getting objc-args: %s %s' % (flagtxt, flagerr))
- args = flagtxt.split()
- self.args = self.filter_arsg(args)
- fp = subprocess.Popen([confprog, arg],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (libtxt, liberr) = fp.communicate()
- libtxt = libtxt.decode()
- liberr = liberr.decode()
- if fp.returncode != 0:
- raise DependencyException('Error getting objc-lib args: %s %s' % (libtxt, liberr))
- self.libs = self.weird_filter(libtxt.split())
- mlog.log('Dependency GnuStep found:', mlog.green('YES'))
-
- 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_arsg(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 found(self):
- return self.args is not None
-
- def get_compile_args(self):
- if self.args is None:
- return []
- return self.args
-
- def get_link_args(self):
- return self.libs
-
-class AppleFrameworks(Dependency):
- def __init__(self, environment, kwargs):
- Dependency.__init__(self)
- modules = kwargs.get('modules', [])
- if isinstance(modules, str):
- modules = [modules]
- if len(modules) == 0:
- raise DependencyException("AppleFrameworks dependency requires at least one module.")
- self.frameworks = modules
-
- def get_link_args(self):
- args = []
- for f in self.frameworks:
- args.append('-framework')
- args.append(f)
- return args
-
- def found(self):
- return mesonlib.is_osx()
-
-class GLDependency(Dependency):
- def __init__(self, environment, kwargs):
- Dependency.__init__(self)
- self.is_found = False
- self.cargs = []
- self.linkargs = []
- try:
- pcdep = PkgConfigDependency('gl', environment, kwargs)
- if pcdep.found():
- self.is_found = True
- self.cargs = pcdep.get_compile_args()
- self.linkargs = pcdep.get_link_args()
- return
- except Exception:
- pass
- if mesonlib.is_osx():
- self.is_found = True
- self.linkargs = ['-framework', 'OpenGL']
- return
- if mesonlib.is_windows():
- self.is_found = True
- self.linkargs = ['-lopengl32']
- return
-
- def get_link_args(self):
- return self.linkargs
-
-# There are three different ways of depending on SDL2:
-# sdl2-config, pkg-config and OSX framework
-class SDL2Dependency(Dependency):
- def __init__(self, environment, kwargs):
- Dependency.__init__(self)
- self.is_found = False
- self.cargs = []
- self.linkargs = []
- sdlconf = shutil.which('sdl2-config')
- if sdlconf:
- pc = subprocess.Popen(['sdl2-config', '--cflags'],
- stdout=subprocess.PIPE,
- stderr=subprocess.DEVNULL)
- (stdo, _) = pc.communicate()
- self.cargs = stdo.decode().strip().split()
- pc = subprocess.Popen(['sdl2-config', '--libs'],
- stdout=subprocess.PIPE,
- stderr=subprocess.DEVNULL)
- (stdo, _) = pc.communicate()
- self.linkargs = stdo.decode().strip().split()
- self.is_found = True
- mlog.log('Dependency', mlog.bold('sdl2'), 'found:', mlog.green('YES'), '(%s)' % sdlconf)
- return
- try:
- pcdep = PkgConfigDependency('sdl2', kwargs)
- if pcdep.found():
- self.is_found = True
- self.cargs = pcdep.get_compile_args()
- self.linkargs = pcdep.get_link_args()
- return
- except Exception:
- pass
- if mesonlib.is_osx():
- fwdep = ExtraFrameworkDependency('sdl2', kwargs.get('required', True))
- if fwdep.found():
- self.is_found = True
- self.cargs = fwdep.get_compile_args()
- self.linkargs = fwdep.get_link_args()
- return
- mlog.log('Dependency', mlog.bold('sdl2'), 'found:', mlog.red('NO'))
-
- def get_compile_args(self):
- return self.cargs
-
- def get_link_args(self):
- return self.linkargs
-
- def found(self):
- return self.is_found
-
-class ExtraFrameworkDependency(Dependency):
- def __init__(self, name, required, path=None):
- Dependency.__init__(self)
- self.name = None
- 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 = ['/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
- return
-
- 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 found(self):
- return self.name is not None
-
-class ThreadDependency(Dependency):
- def __init__(self, environment, kwargs):
- super().__init__()
- 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_dep_identifier(name, kwargs):
- elements = [name]
- modlist = kwargs.get('modules', [])
- if isinstance(modlist, str):
- modlist = [modlist]
- for module in modlist:
- elements.append(module)
- return '/'.join(elements) + '/main' + str(kwargs.get('main', False))
-
-def find_external_dependency(name, environment, kwargs):
- required = kwargs.get('required', True)
- if not isinstance(required, bool):
- raise DependencyException('Keyword "required" must be a boolean.')
- lname = name.lower()
- if lname in packages:
- dep = packages[lname](environment, kwargs)
- if required and not dep.found():
- raise DependencyException('Dependency "%s" not found' % name)
- return dep
- pkg_exc = None
- pkgdep = None
- try:
- pkgdep = PkgConfigDependency(name, environment, kwargs)
- if pkgdep.found():
- return pkgdep
- except Exception as e:
- pkg_exc = e
- if mesonlib.is_osx():
- fwdep = ExtraFrameworkDependency(name, required)
- if required and not fwdep.found():
- raise DependencyException('Dependency "%s" not found' % name)
- return fwdep
- if pkg_exc is not None:
- raise pkg_exc
- mlog.log('Dependency', mlog.bold(name), 'found:', mlog.red('NO'))
- return pkgdep
-
-# This has to be at the end so the classes it references
-# are defined.
-packages = {'boost': BoostDependency,
- 'gtest': GTestDependency,
- 'gmock': GMockDependency,
- 'qt5': Qt5Dependency,
- 'qt4': Qt4Dependency,
- 'gnustep': GnuStepDependency,
- 'appleframeworks': AppleFrameworks,
- 'wxwidgets' : WxDependency,
- 'sdl2' : SDL2Dependency,
- 'gl' : GLDependency,
- 'threads' : ThreadDependency,
- }
diff --git a/meson/environment.py b/meson/environment.py
deleted file mode 100644
index 8df856c..0000000
--- a/meson/environment.py
+++ /dev/null
@@ -1,673 +0,0 @@
-# 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, re, subprocess
-from . import coredata, mesonlib
-from .compilers import *
-import configparser
-
-build_filename = 'meson.build'
-
-class EnvironmentException(coredata.MesonException):
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
-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 find_valgrind():
- valgrind_exe = 'valgrind'
- if not mesonlib.exe_exists([valgrind_exe, '--version']):
- valgrind_exe = None
- return valgrind_exe
-
-def detect_ninja():
- for n in ['ninja', 'ninja-build']:
- try:
- p = subprocess.Popen([n, '--version'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
- except FileNotFoundError:
- continue
- p.communicate()
- if p.returncode == 0:
- return n
-
-
-class Environment():
- private_dir = 'meson-private'
- log_dir = 'meson-logs'
- coredata_file = os.path.join(private_dir, 'coredata.dat')
- version_regex = '\d+(\.\d+)+(-[a-zA-Z0-9]+)?'
- def __init__(self, source_dir, build_dir, main_script_file, options):
- assert(os.path.isabs(main_script_file))
- assert(not os.path.islink(main_script_file))
- self.source_dir = source_dir
- self.build_dir = build_dir
- self.meson_script_file = main_script_file
- self.scratch_dir = os.path.join(build_dir, Environment.private_dir)
- self.log_dir = os.path.join(build_dir, Environment.log_dir)
- os.makedirs(self.scratch_dir, exist_ok=True)
- os.makedirs(self.log_dir, exist_ok=True)
- try:
- cdf = os.path.join(self.get_build_dir(), Environment.coredata_file)
- self.coredata = coredata.load(cdf)
- self.first_invocation = False
- except FileNotFoundError:
- self.coredata = coredata.CoreData(options)
- self.first_invocation = True
- if self.coredata.cross_file:
- self.cross_info = CrossBuildInfo(self.coredata.cross_file)
- else:
- self.cross_info = None
- self.cmd_line_options = options
-
- # List of potential compilers.
- if mesonlib.is_windows():
- self.default_c = ['cl', 'cc', 'gcc', 'clang']
- self.default_cpp = ['cl', 'c++', 'g++', 'clang++']
- else:
- self.default_c = ['cc']
- self.default_cpp = ['c++']
- self.default_objc = ['cc']
- self.default_objcpp = ['c++']
- self.default_fortran = ['gfortran', 'g95', 'f95', 'f90', 'f77']
- self.default_static_linker = 'ar'
- self.vs_static_linker = 'lib'
-
- cross = self.is_cross_build()
- if (not cross and mesonlib.is_windows()) \
- or (cross and self.cross_info.has_host() and self.cross_info.config['host_machine']['system'] == 'windows'):
- self.exe_suffix = 'exe'
- self.import_lib_suffix = 'lib'
- self.shared_lib_suffix = 'dll'
- self.shared_lib_prefix = ''
- self.static_lib_suffix = 'lib'
- self.static_lib_prefix = ''
- self.object_suffix = 'obj'
- else:
- self.exe_suffix = ''
- if (not cross and mesonlib.is_osx()) or \
- (cross and self.cross_info.has_host() and self.cross_info.config['host_machine']['system'] == 'darwin'):
- self.shared_lib_suffix = 'dylib'
- else:
- self.shared_lib_suffix = 'so'
- self.shared_lib_prefix = 'lib'
- self.static_lib_suffix = 'a'
- self.static_lib_prefix = 'lib'
- self.object_suffix = 'o'
- self.import_lib_suffix = self.shared_lib_suffix
-
- def is_cross_build(self):
- return self.cross_info is not None
-
- def generating_finished(self):
- cdf = os.path.join(self.get_build_dir(), Environment.coredata_file)
- coredata.save(self.coredata, cdf)
-
- def get_script_dir(self):
- return os.path.join(os.path.dirname(self.meson_script_file), '../scripts')
-
- def get_log_dir(self):
- return self.log_dir
-
- def get_coredata(self):
- return self.coredata
-
- def get_build_command(self):
- return self.meson_script_file
-
- def is_header(self, fname):
- return is_header(fname)
-
- def is_source(self, fname):
- return is_source(fname)
-
- def is_object(self, fname):
- return is_object(fname)
-
- def is_library(self, fname):
- return is_library(fname)
-
- def merge_options(self, options):
- for (name, value) in options.items():
- if name not in self.coredata.user_options:
- self.coredata.user_options[name] = value
- else:
- oldval = self.coredata.user_options[name]
- if type(oldval) != type(value):
- self.coredata.user_options[name] = value
-
- def detect_c_compiler(self, want_cross):
- evar = 'CC'
- if self.is_cross_build() and want_cross:
- compilers = [self.cross_info.config['binaries']['c']]
- ccache = []
- is_cross = True
- exe_wrap = self.cross_info.config['binaries'].get('exe_wrapper', None)
- elif evar in os.environ:
- compilers = os.environ[evar].split()
- ccache = []
- is_cross = False
- exe_wrap = None
- else:
- compilers = self.default_c
- ccache = self.detect_ccache()
- is_cross = False
- exe_wrap = None
- for compiler in compilers:
- try:
- basename = os.path.basename(compiler).lower()
- if basename == 'cl' or basename == 'cl.exe':
- arg = '/?'
- else:
- arg = '--version'
- p = subprocess.Popen([compiler] + [arg], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- except OSError:
- continue
- (out, err) = p.communicate()
- out = out.decode(errors='ignore')
- err = err.decode(errors='ignore')
- vmatch = re.search(Environment.version_regex, out)
- if vmatch:
- version = vmatch.group(0)
- else:
- version = 'unknown version'
- if 'apple' in out and 'Free Software Foundation' in out:
- return GnuCCompiler(ccache + [compiler], version, GCC_OSX, is_cross, exe_wrap)
- if (out.startswith('cc') or 'gcc' in out) and \
- 'Free Software Foundation' in out:
- lowerout = out.lower()
- if 'mingw' in lowerout or 'msys' in lowerout or 'mingw' in compiler.lower():
- gtype = GCC_MINGW
- else:
- gtype = GCC_STANDARD
- return GnuCCompiler(ccache + [compiler], version, gtype, is_cross, exe_wrap)
- if 'clang' in out:
- return ClangCCompiler(ccache + [compiler], version, is_cross, exe_wrap)
- if 'Microsoft' in out or 'Microsoft' in err:
- # Visual Studio prints version number to stderr but
- # everything else to stdout. Why? Lord only knows.
- version = re.search(Environment.version_regex, err).group()
- return VisualStudioCCompiler([compiler], version, is_cross, exe_wrap)
- raise EnvironmentException('Unknown compiler(s): "' + ', '.join(compilers) + '"')
-
- def detect_fortran_compiler(self, want_cross):
- evar = 'FC'
- if self.is_cross_build() and want_cross:
- compilers = [self.cross_info['fortran']]
- is_cross = True
- exe_wrap = self.cross_info.get('exe_wrapper', None)
- elif evar in os.environ:
- compilers = os.environ[evar].split()
- is_cross = False
- exe_wrap = None
- else:
- compilers = self.default_fortran
- is_cross = False
- exe_wrap = None
- for compiler in compilers:
- for arg in ['--version', '-V']:
- try:
- p = subprocess.Popen([compiler] + [arg],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- except OSError:
- continue
- (out, err) = p.communicate()
- out = out.decode(errors='ignore')
- err = err.decode(errors='ignore')
-
- version = 'unknown version'
- vmatch = re.search(Environment.version_regex, out)
- if vmatch:
- version = vmatch.group(0)
-
- if 'GNU Fortran' in out:
- return GnuFortranCompiler([compiler], version, GCC_STANDARD, is_cross, exe_wrap)
-
- if 'G95' in out:
- return G95FortranCompiler([compiler], version, is_cross, exe_wrap)
-
- if 'Sun Fortran' in err:
- version = 'unknown version'
- vmatch = re.search(Environment.version_regex, err)
- if vmatch:
- version = vmatch.group(0)
- return SunFortranCompiler([compiler], version, is_cross, exe_wrap)
-
- if 'ifort (IFORT)' in out:
- return IntelFortranCompiler([compiler], version, is_cross, exe_wrap)
-
- if 'PathScale EKOPath(tm)' in err:
- return PathScaleFortranCompiler([compiler], version, is_cross, exe_wrap)
-
- if 'pgf90' in out:
- return PGIFortranCompiler([compiler], version, is_cross, exe_wrap)
-
- if 'Open64 Compiler Suite' in err:
- return Open64FortranCompiler([compiler], version, is_cross, exe_wrap)
-
- if 'NAG Fortran' in err:
- return NAGFortranCompiler([compiler], version, is_cross, exe_wrap)
-
- raise EnvironmentException('Unknown compiler(s): "' + ', '.join(compilers) + '"')
-
- def get_scratch_dir(self):
- return self.scratch_dir
-
- def get_depfixer(self):
- path = os.path.split(__file__)[0]
- return os.path.join(path, 'depfixer.py')
-
- def detect_cpp_compiler(self, want_cross):
- evar = 'CXX'
- if self.is_cross_build() and want_cross:
- compilers = [self.cross_info.config['binaries']['cpp']]
- ccache = []
- is_cross = True
- exe_wrap = self.cross_info.config['binaries'].get('exe_wrapper', None)
- elif evar in os.environ:
- compilers = os.environ[evar].split()
- ccache = []
- is_cross = False
- exe_wrap = None
- else:
- compilers = self.default_cpp
- ccache = self.detect_ccache()
- is_cross = False
- exe_wrap = None
- for compiler in compilers:
- basename = os.path.basename(compiler).lower()
- if basename == 'cl' or basename == 'cl.exe':
- arg = '/?'
- else:
- arg = '--version'
- try:
- p = subprocess.Popen([compiler, arg],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- except OSError:
- continue
- (out, err) = p.communicate()
- out = out.decode(errors='ignore')
- err = err.decode(errors='ignore')
- vmatch = re.search(Environment.version_regex, out)
- if vmatch:
- version = vmatch.group(0)
- else:
- version = 'unknown version'
- if 'apple' in out and 'Free Software Foundation' in out:
- return GnuCPPCompiler(ccache + [compiler], version, GCC_OSX, is_cross, exe_wrap)
- if (out.startswith('c++ ') or 'g++' in out or 'GCC' in out) and \
- 'Free Software Foundation' in out:
- lowerout = out.lower()
- if 'mingw' in lowerout or 'msys' in lowerout or 'mingw' in compiler.lower():
- gtype = GCC_MINGW
- else:
- gtype = GCC_STANDARD
- return GnuCPPCompiler(ccache + [compiler], version, gtype, is_cross, exe_wrap)
- if 'clang' in out:
- return ClangCPPCompiler(ccache + [compiler], version, is_cross, exe_wrap)
- if 'Microsoft' in out or 'Microsoft' in err:
- version = re.search(Environment.version_regex, err).group()
- return VisualStudioCPPCompiler([compiler], version, is_cross, exe_wrap)
- raise EnvironmentException('Unknown compiler(s) "' + ', '.join(compilers) + '"')
-
- def detect_objc_compiler(self, want_cross):
- if self.is_cross_build() and want_cross:
- exelist = [self.cross_info['objc']]
- is_cross = True
- exe_wrap = self.cross_info.get('exe_wrapper', None)
- else:
- exelist = self.get_objc_compiler_exelist()
- is_cross = False
- exe_wrap = None
- try:
- p = subprocess.Popen(exelist + ['--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- except OSError:
- raise EnvironmentException('Could not execute ObjC compiler "%s"' % ' '.join(exelist))
- (out, err) = p.communicate()
- out = out.decode(errors='ignore')
- err = err.decode(errors='ignore')
- vmatch = re.search(Environment.version_regex, out)
- if vmatch:
- version = vmatch.group(0)
- else:
- version = 'unknown version'
- if (out.startswith('cc ') or 'gcc' in out) and \
- 'Free Software Foundation' in out:
- return GnuObjCCompiler(exelist, version, is_cross, exe_wrap)
- if out.startswith('Apple LLVM'):
- return ClangObjCCompiler(exelist, version, is_cross, exe_wrap)
- if 'apple' in out and 'Free Software Foundation' in out:
- return GnuObjCCompiler(exelist, version, is_cross, exe_wrap)
- raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
-
- def detect_objcpp_compiler(self, want_cross):
- if self.is_cross_build() and want_cross:
- exelist = [self.cross_info['objcpp']]
- is_cross = True
- exe_wrap = self.cross_info.get('exe_wrapper', None)
- else:
- exelist = self.get_objcpp_compiler_exelist()
- is_cross = False
- exe_wrap = None
- try:
- p = subprocess.Popen(exelist + ['--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- except OSError:
- raise EnvironmentException('Could not execute ObjC++ compiler "%s"' % ' '.join(exelist))
- (out, err) = p.communicate()
- out = out.decode(errors='ignore')
- err = err.decode(errors='ignore')
- vmatch = re.search(Environment.version_regex, out)
- if vmatch:
- version = vmatch.group(0)
- else:
- version = 'unknown version'
- if (out.startswith('c++ ') or out.startswith('g++')) and \
- 'Free Software Foundation' in out:
- return GnuObjCPPCompiler(exelist, version, is_cross, exe_wrap)
- if out.startswith('Apple LLVM'):
- return ClangObjCPPCompiler(exelist, version, is_cross, exe_wrap)
- if 'apple' in out and 'Free Software Foundation' in out:
- return GnuObjCPPCompiler(exelist, version, is_cross, exe_wrap)
- raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
-
- def detect_java_compiler(self):
- exelist = ['javac']
- try:
- p = subprocess.Popen(exelist + ['-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- except OSError:
- raise EnvironmentException('Could not execute Java compiler "%s"' % ' '.join(exelist))
- (out, err) = p.communicate()
- out = out.decode(errors='ignore')
- err = err.decode(errors='ignore')
- vmatch = re.search(Environment.version_regex, err)
- if vmatch:
- version = vmatch.group(0)
- else:
- version = 'unknown version'
- if 'javac' in err:
- return JavaCompiler(exelist, version)
- raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
-
- def detect_cs_compiler(self):
- exelist = ['mcs']
- try:
- p = subprocess.Popen(exelist + ['--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- except OSError:
- raise EnvironmentException('Could not execute C# compiler "%s"' % ' '.join(exelist))
- (out, err) = p.communicate()
- out = out.decode(errors='ignore')
- err = err.decode(errors='ignore')
- vmatch = re.search(Environment.version_regex, out)
- if vmatch:
- version = vmatch.group(0)
- else:
- version = 'unknown version'
- if 'Mono' in out:
- return MonoCompiler(exelist, version)
- raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
-
- def detect_vala_compiler(self):
- exelist = ['valac']
- try:
- p = subprocess.Popen(exelist + ['--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- except OSError:
- raise EnvironmentException('Could not execute Vala compiler "%s"' % ' '.join(exelist))
- (out, _) = p.communicate()
- out = out.decode(errors='ignore')
- vmatch = re.search(Environment.version_regex, out)
- if vmatch:
- version = vmatch.group(0)
- else:
- version = 'unknown version'
- if 'Vala' in out:
- return ValaCompiler(exelist, version)
- raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
-
- def detect_rust_compiler(self):
- exelist = ['rustc']
- try:
- p = subprocess.Popen(exelist + ['--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- except OSError:
- raise EnvironmentException('Could not execute Rust compiler "%s"' % ' '.join(exelist))
- (out, _) = p.communicate()
- out = out.decode(errors='ignore')
- vmatch = re.search(Environment.version_regex, out)
- if vmatch:
- version = vmatch.group(0)
- else:
- version = 'unknown version'
- if 'rustc' in out:
- return RustCompiler(exelist, version)
- raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
-
- def detect_swift_compiler(self):
- exelist = ['swiftc']
- try:
- p = subprocess.Popen(exelist + ['-v'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- except OSError:
- raise EnvironmentException('Could not execute Swift compiler "%s"' % ' '.join(exelist))
- (_, err) = p.communicate()
- err = err.decode(errors='ignore')
- vmatch = re.search(Environment.version_regex, err)
- if vmatch:
- version = vmatch.group(0)
- else:
- version = 'unknown version'
- if 'Swift' in err:
- return SwiftCompiler(exelist, version)
- raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
-
- def detect_static_linker(self, compiler):
- if compiler.is_cross:
- linker = self.cross_info.config['binaries']['ar']
- else:
- evar = 'AR'
- if evar in os.environ:
- linker = os.environ[evar].strip()
- if isinstance(compiler, VisualStudioCCompiler):
- linker= self.vs_static_linker
- else:
- linker = self.default_static_linker
- basename = os.path.basename(linker).lower()
- if basename == 'lib' or basename == 'lib.exe':
- arg = '/?'
- else:
- arg = '--version'
- try:
- p = subprocess.Popen([linker, arg], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- except OSError:
- raise EnvironmentException('Could not execute static linker "%s".' % linker)
- (out, err) = p.communicate()
- out = out.decode(errors='ignore')
- err = err.decode(errors='ignore')
- if '/OUT:' in out or '/OUT:' in err:
- return VisualStudioLinker([linker])
- if p.returncode == 0:
- return ArLinker([linker])
- if p.returncode == 1 and err.startswith('usage'): # OSX
- return ArLinker([linker])
- raise EnvironmentException('Unknown static linker "%s"' % linker)
-
- def detect_ccache(self):
- try:
- has_ccache = subprocess.call(['ccache', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- except OSError:
- has_ccache = 1
- if has_ccache == 0:
- cmdlist = ['ccache']
- else:
- cmdlist = []
- return cmdlist
-
- def get_objc_compiler_exelist(self):
- ccachelist = self.detect_ccache()
- evar = 'OBJCC'
- if evar in os.environ:
- return os.environ[evar].split()
- return ccachelist + self.default_objc
-
- def get_objcpp_compiler_exelist(self):
- ccachelist = self.detect_ccache()
- evar = 'OBJCXX'
- if evar in os.environ:
- return os.environ[evar].split()
- return ccachelist + self.default_objcpp
-
- def get_source_dir(self):
- return self.source_dir
-
- def get_build_dir(self):
- return self.build_dir
-
- def get_exe_suffix(self):
- return self.exe_suffix
-
- # On Windows the library has suffix dll
- # but you link against a file that has suffix lib.
- def get_import_lib_suffix(self):
- return self.import_lib_suffix
-
- def get_shared_lib_prefix(self):
- return self.shared_lib_prefix
-
- def get_shared_lib_suffix(self):
- return self.shared_lib_suffix
-
- def get_static_lib_prefix(self):
- return self.static_lib_prefix
-
- def get_static_lib_suffix(self):
- return self.static_lib_suffix
-
- def get_object_suffix(self):
- return self.object_suffix
-
- def get_prefix(self):
- return self.coredata.get_builtin_option('prefix')
-
- def get_libdir(self):
- return self.coredata.get_builtin_option('libdir')
-
- def get_bindir(self):
- return self.coredata.get_builtin_option('bindir')
-
- def get_includedir(self):
- return self.coredata.get_builtin_option('includedir')
-
- def get_mandir(self):
- return self.coredata.get_builtin_option('mandir')
-
- def get_datadir(self):
- return self.coredata.get_builtin_option('datadir')
-
- def find_library(self, libname, dirs):
- if dirs is None:
- dirs = mesonlib.get_library_dirs()
- suffixes = [self.get_shared_lib_suffix(), self.get_static_lib_suffix()]
- prefix = self.get_shared_lib_prefix()
- for d in dirs:
- for suffix in suffixes:
- trial = os.path.join(d, prefix + libname + '.' + suffix)
- if os.path.isfile(trial):
- return trial
-
-
-def get_args_from_envvars(lang):
- if lang == 'c':
- compile_args = os.environ.get('CFLAGS', '').split()
- link_args = compile_args + os.environ.get('LDFLAGS', '').split()
- compile_args += os.environ.get('CPPFLAGS', '').split()
- elif lang == 'cpp':
- compile_args = os.environ.get('CXXFLAGS', '').split()
- link_args = compile_args + os.environ.get('LDFLAGS', '').split()
- compile_args += os.environ.get('CPPFLAGS', '').split()
- elif lang == 'objc':
- compile_args = os.environ.get('OBJCFLAGS', '').split()
- link_args = compile_args + os.environ.get('LDFLAGS', '').split()
- compile_args += os.environ.get('CPPFLAGS', '').split()
- elif lang == 'objcpp':
- compile_args = os.environ.get('OBJCXXFLAGS', '').split()
- link_args = compile_args + os.environ.get('LDFLAGS', '').split()
- compile_args += os.environ.get('CPPFLAGS', '').split()
- elif lang == 'fortran':
- compile_args = os.environ.get('FFLAGS', '').split()
- link_args = compile_args + os.environ.get('LDFLAGS', '').split()
- else:
- compile_args = []
- link_args = []
- return (compile_args, link_args)
-
-class CrossBuildInfo():
- def __init__(self, filename):
- self.config = {}
- self.parse_datafile(filename)
- if 'target_machine' in self.config:
- return
- if not 'host_machine' in self.config:
- raise coredata.MesonException('Cross info file must have either host or a target machine.')
- if not 'properties' in self.config:
- raise coredata.MesonException('Cross file is missing "properties".')
- if not 'binaries' in self.config:
- raise coredata.MesonException('Cross file is missing "binaries".')
-
- def ok_type(self, i):
- return isinstance(i, str) or isinstance(i, int) or isinstance(i, bool)
-
- def parse_datafile(self, filename):
- config = configparser.ConfigParser()
- config.read(filename)
- # This is a bit hackish at the moment.
- for s in config.sections():
- self.config[s] = {}
- for entry in config[s]:
- value = config[s][entry]
- if ' ' in entry or '\t' in entry or "'" in entry or '"' in entry:
- raise EnvironmentException('Malformed variable name %s in cross file..' % varname)
- try:
- res = eval(value, {'true' : True, 'false' : False})
- except Exception:
- raise EnvironmentException('Malformed value in cross file variable %s.' % varname)
- if self.ok_type(res):
- self.config[s][entry] = res
- elif isinstance(res, list):
- for i in res:
- if not self.ok_type(i):
- raise EnvironmentException('Malformed value in cross file variable %s.' % varname)
- self.config[s][entry] = res
- else:
- raise EnvironmentException('Malformed value in cross file variable %s.' % varname)
-
- def has_host(self):
- return 'host_machine' in self.config
-
- def has_target(self):
- return 'target_machine' in self.config
-
- # Wehn compiling a cross compiler we use the native compiler for everything.
- # But not when cross compiling a cross compiler.
- def need_cross_compiler(self):
- return 'host_machine' in self.config
diff --git a/meson/interpreter.py b/meson/interpreter.py
deleted file mode 100644
index 1a32998..0000000
--- a/meson/interpreter.py
+++ /dev/null
@@ -1,2259 +0,0 @@
-# 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.
-
-from . import mparser
-from . import environment
-from . import coredata
-from . import dependencies
-from . import mlog
-from . import build
-from . import optinterpreter
-from .wrap import wrap
-from . import mesonlib
-
-import os, sys, platform, subprocess, shutil, uuid, re
-from functools import wraps
-
-import importlib
-
-class InterpreterException(coredata.MesonException):
- pass
-
-class InvalidCode(InterpreterException):
- pass
-
-class InvalidArguments(InterpreterException):
- pass
-
-# 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 len(args) != 0:
- 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 len(kwargs) != 0:
- 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
-
-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 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 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, command_array, source_dir, build_dir, subdir, in_builddir=False):
- super().__init__()
- pc = self.run_command(command_array, source_dir, build_dir, subdir, in_builddir)
- (stdout, stderr) = pc.communicate()
- self.returncode = pc.returncode
- self.stdout = stdout.decode().replace('\r\n', '\n')
- self.stderr = stderr.decode().replace('\r\n', '\n')
- self.methods.update({'returncode' : self.returncode_method,
- 'stdout' : self.stdout_method,
- 'stderr' : self.stderr_method,
- })
-
- def run_command(self, command_array, source_dir, build_dir, subdir, in_builddir):
- cmd_name = command_array[0]
- env = {'MESON_SOURCE_ROOT' : source_dir,
- 'MESON_BUILD_ROOT' : build_dir,
- 'MESON_SUBDIR' : subdir}
- 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)
- try:
- return subprocess.Popen(command_array, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- env=child_env, cwd=cwd)
- except FileNotFoundError:
- pass
- # Was not a command, is a program in path?
- exe = shutil.which(cmd_name)
- if exe is not None:
- command_array = [exe] + command_array[1:]
- return subprocess.Popen(command_array, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- env=child_env, cwd=cwd)
- # No? Maybe it is a script in the source tree.
- fullpath = os.path.join(source_dir, subdir, cmd_name)
- command_array = [fullpath] + command_array[1:]
- try:
- return subprocess.Popen(command_array, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- env=child_env, cwd=cwd)
- except FileNotFoundError:
- raise InterpreterException('Could not execute command "%s".' % cmd_name)
-
- 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):
-
- def __init__(self, subdir, sourcename, targetname, configuration_data):
- InterpreterObject.__init__(self)
- self.held_object = build.ConfigureFile(subdir, sourcename, targetname, configuration_data)
-
-class ConfigurationDataHolder(InterpreterObject):
- def __init__(self):
- super().__init__()
- self.used = False # These objects become immutable after use in configure_file.
- self.held_object = build.ConfigurationData()
- self.methods.update({'set': self.set_method,
- 'set10': self.set10_method,
- 'has' : self.has_method,
- })
-
- def is_used(self):
- return self.used
-
- def mark_used(self):
- self.used = True
-
- def validate_args(self, args):
- 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]
- if not isinstance(name, str):
- raise InterpreterException("First argument to set must be a string.")
- return (name, val)
-
- def set_method(self, args, kwargs):
- (name, val) = self.validate_args(args)
- self.held_object.values[name] = val
-
- def set10_method(self, args, kwargs):
- (name, val) = self.validate_args(args)
- if val:
- self.held_object.values[name] = 1
- else:
- self.held_object.values[name] = 0
-
- def has_method(self, args, kwargs):
- return args[0] in self.held_object.values
-
- def get(self, name):
- return self.held_object.values[name]
-
- def keys(self):
- return self.held_object.values.keys()
-
-# Interpreter objects can not be pickled so we must have
-# these wrappers.
-
-class DependencyHolder(InterpreterObject):
- def __init__(self, dep):
- InterpreterObject.__init__(self)
- self.held_object = dep
- self.methods.update({'found' : self.found_method})
-
- def found_method(self, args, kwargs):
- return self.held_object.found()
-
-class InternalDependencyHolder(InterpreterObject):
- def __init__(self, dep):
- InterpreterObject.__init__(self)
- self.held_object = dep
- self.methods.update({'found' : self.found_method})
-
- def found_method(self, args, kwargs):
- return True
-
-class ExternalProgramHolder(InterpreterObject):
- def __init__(self, ep):
- InterpreterObject.__init__(self)
- self.held_object = ep
- self.methods.update({'found': self.found_method})
-
- def found_method(self, args, kwargs):
- return self.found()
-
- def found(self):
- return self.held_object.found()
-
- def get_command(self):
- return self.held_object.fullpath
-
- def get_name(self):
- return self.held_object.name
-
-class ExternalLibraryHolder(InterpreterObject):
- def __init__(self, el):
- InterpreterObject.__init__(self)
- self.held_object = 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_filename(self):
- return self.held_object.fullpath
-
- 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):
- def __init__(self, interpreter, args, kwargs):
- super().__init__()
- self.interpreter = interpreter
- self.held_object = build.Generator(args, kwargs)
- self.methods.update({'process' : self.process_method})
-
- def process_method(self, args, kwargs):
- check_stringlist(args)
- extras = mesonlib.stringlistify(kwargs.get('extra_args', []))
- gl = GeneratedListHolder(self, extras)
- [gl.add_file(os.path.join(self.interpreter.subdir, a)) for a in args]
- return gl
-
-class GeneratedListHolder(InterpreterObject):
- def __init__(self, arg1, extra_args=[]):
- super().__init__()
- if isinstance(arg1, GeneratorHolder):
- self.held_object = build.GeneratedList(arg1.held_object, extra_args)
- else:
- self.held_object = arg1
-
- def add_file(self, a):
- self.held_object.add_file(a)
-
-class BuildMachine(InterpreterObject):
- def __init__(self):
- InterpreterObject.__init__(self)
- self.methods.update({'system' : self.system_method,
- 'cpu_family' : self.cpu_family_method,
- 'cpu' : self.cpu_method,
- 'endian' : self.endian_method,
- })
-
- # 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.
- def cpu_family_method(self, args, kwargs):
- trial = platform.machine().lower()
- if trial.startswith('i') and trial.endswith('86'):
- return 'x86'
- if trial.startswith('arm'):
- return 'arm'
- # Add fixes here as bugs are reported.
- return trial
-
- def cpu_method(self, args, kwargs):
- return platform.machine().lower()
-
- def system_method(self, args, kwargs):
- return platform.system().lower()
-
- def endian_method(self, args, kwargs):
- return sys.byteorder
-
-# This class will provide both host_machine and
-# target_machine
-class CrossMachineInfo(InterpreterObject):
- 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
- self.methods.update({'system' : self.system_method,
- 'cpu' : self.cpu_method,
- 'cpu_family' : self.cpu_family_method,
- 'endian' : self.endian_method,
- })
-
- def system_method(self, args, kwargs):
- return self.info['system']
-
- def cpu_method(self, args, kwargs):
- return self.info['cpu']
-
- def cpu_family_method(self, args, kwargs):
- return self.info['cpu_family']
-
- def endian_method(self, args, kwargs):
- return self.info['endian']
-
-class IncludeDirsHolder(InterpreterObject):
- def __init__(self, idobj):
- super().__init__()
- self.held_object = idobj
-
-class Headers(InterpreterObject):
-
- def __init__(self, src_subdir, sources, kwargs):
- InterpreterObject.__init__(self)
- self.sources = sources
- self.source_subdir = src_subdir
- 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_source_subdir(self):
- return self.source_subdir
-
- def get_sources(self):
- return self.sources
-
- def get_custom_install_dir(self):
- return self.custom_install_dir
-
-class DataHolder(InterpreterObject):
- def __init__(self, in_sourcetree, source_subdir, sources, kwargs):
- super().__init__()
- kwsource = mesonlib.stringlistify(kwargs.get('sources', []))
- sources += kwsource
- check_stringlist(sources)
- install_dir = kwargs.get('install_dir', None)
- if not isinstance(install_dir, str):
- raise InterpreterException('Custom_install_dir must be a string.')
- self.held_object = build.Data(in_sourcetree, source_subdir, sources, install_dir)
-
- 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, source_subdir, installable_subdir, install_dir):
- InterpreterObject.__init__(self)
- self.source_subdir = source_subdir
- self.installable_subdir = installable_subdir
- self.install_dir = install_dir
-
-class Man(InterpreterObject):
-
- def __init__(self, source_subdir, sources, kwargs):
- InterpreterObject.__init__(self)
- self.source_subdir = source_subdir
- self.sources = sources
- self.validate_sources()
- if len(kwargs) > 1:
- raise InvalidArguments('Man function takes at most one keyword arguments.')
- 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:
- num = int(s.split('.')[-1])
- 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
-
- def get_source_subdir(self):
- return self.source_subdir
-
-class GeneratedObjectsHolder(InterpreterObject):
- def __init__(self, held_object):
- super().__init__()
- self.held_object = held_object
-
-class BuildTargetHolder(InterpreterObject):
- def __init__(self, target, interp):
- super().__init__()
- self.held_object = target
- self.interpreter = 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,
- 'private_dir_include' : self.private_dir_include_method,
- })
-
- 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 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 JarHolder(BuildTargetHolder):
- def __init__(self, target, interp):
- super().__init__(target, interp)
-
-class CustomTargetHolder(InterpreterObject):
- def __init__(self, object_to_hold):
- self.held_object = object_to_hold
-
- def is_cross(self):
- return self.held_object.is_cross()
-
- def extract_objects_method(self, args, kwargs):
- gobjs = self.held_object.extract_objects(args)
- return GeneratedObjectsHolder(gobjs)
-
-class RunTargetHolder(InterpreterObject):
- def __init__(self, name, command, args, subdir):
- self.held_object = build.RunTarget(name, command, args, subdir)
-
-class Test(InterpreterObject):
- def __init__(self, name, suite, exe, is_parallel, cmd_args, env, should_fail, valgrind_args, timeout, workdir):
- InterpreterObject.__init__(self)
- self.name = name
- self.suite = suite
- self.exe = exe
- self.is_parallel = is_parallel
- self.cmd_args = cmd_args
- self.env = env
- self.should_fail = should_fail
- self.valgrind_args = valgrind_args
- self.timeout = timeout
- self.workdir = workdir
-
- def get_exe(self):
- return self.exe
-
- def get_name(self):
- return self.name
-
-class SubprojectHolder(InterpreterObject):
-
- def __init__(self, subinterpreter):
- super().__init__()
- self.subinterpreter = 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.')
- return self.subinterpreter.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,
- 'sizeof': self.sizeof_method,
- 'has_header': self.has_header_method,
- 'run' : self.run_method,
- 'has_function' : self.has_function_method,
- 'has_member' : self.has_member_method,
- 'has_type' : self.has_type_method,
- 'alignment' : self.alignment_method,
- 'version' : self.version_method,
- 'cmd_array' : self.cmd_array_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 = []
- 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 alignment_method(self, args, kwargs):
- if len(args) != 1:
- raise InterpreterException('Alignment method takes exactly one positional argument.')
- check_stringlist(args)
- typename = args[0]
- extra_args = mesonlib.stringlistify(kwargs.get('args', []))
- result = self.compiler.alignment(typename, self.environment, extra_args)
- 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.')
- check_stringlist(args)
- code = args[0]
- testname = kwargs.get('name', '')
- if not isinstance(testname, str):
- raise InterpreterException('Testname argument must be a string.')
- extra_args = self.determine_args(kwargs)
- result = self.compiler.run(code, extra_args)
- 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 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_function must be a string.')
- extra_args = self.determine_args(kwargs)
- had = self.compiler.has_member(typename, membername, prefix, extra_args)
- 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_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)
- had = self.compiler.has_function(funcname, prefix, self.environment, extra_args)
- 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)
- had = self.compiler.has_type(typename, prefix, extra_args)
- if had:
- hadtxt = mlog.green('YES')
- else:
- hadtxt = mlog.red('NO')
- mlog.log('Checking for type "', mlog.bold(typename), '": ', hadtxt, sep='')
- return had
-
- 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)
- esize = self.compiler.sizeof(element, prefix, self.environment, extra_args)
- mlog.log('Checking for size of "%s": %d' % (element, esize))
- return esize
-
- def compiles_method(self, args, kwargs):
- if len(args) != 1:
- raise InterpreterException('compiles method takes exactly one argument.')
- check_stringlist(args)
- code = args[0]
- testname = kwargs.get('name', '')
- if not isinstance(testname, str):
- raise InterpreterException('Testname argument must be a string.')
- extra_args = self.determine_args(kwargs)
- result = self.compiler.compiles(code, extra_args)
- 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.')
- check_stringlist(args)
- code = args[0]
- testname = kwargs.get('name', '')
- if not isinstance(testname, str):
- raise InterpreterException('Testname argument must be a string.')
- extra_args = self.determine_args(kwargs)
- result = self.compiler.links(code, extra_args)
- 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)
- string = args[0]
- extra_args = self.determine_args(kwargs)
- haz = self.compiler.has_header(string, extra_args)
- if haz:
- h = mlog.green('YES')
- else:
- h = mlog.red('NO')
- mlog.log('Has header "%s":' % string, h)
- return haz
-
-class ModuleState:
- pass
-
-class ModuleHolder(InterpreterObject):
- def __init__(self, modname, module, interpreter):
- InterpreterObject.__init__(self)
- self.modname = modname
- self.held_object = module
- 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))
- state = ModuleState()
- state.build_to_src = os.path.relpath(self.interpreter.environment.get_source_dir(),
- self.interpreter.environment.get_build_dir())
- state.subdir = self.interpreter.subdir
- state.environment = self.interpreter.environment
- state.project_name = self.interpreter.build.project_name
- state.project_version = self.interpreter.build.dep_manifest[self.interpreter.active_projectname]
- state.compilers = self.interpreter.build.compilers
- state.targets = self.interpreter.build.targets
- state.headers = self.interpreter.build.get_headers()
- state.man = self.interpreter.build.get_man()
- state.global_args = self.interpreter.build.global_args
- value = fn(state, args, kwargs)
- 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.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,
- 'install_dependency_manifest': self.install_dependency_manifest_method,
- 'project_version': self.project_version_method,
- })
-
- def add_install_script_method(self, args, kwargs):
- if len(args) != 1:
- raise InterpreterException('Set_install_script takes exactly one argument.')
- check_stringlist(args)
- scriptbase = args[0]
- scriptfile = os.path.join(self.interpreter.environment.source_dir,
- self.interpreter.subdir, scriptbase)
- if not os.path.isfile(scriptfile):
- raise InterpreterException('Can not find install script %s.' % scriptbase)
- self.build.install_scripts.append(build.InstallScript([scriptfile]))
-
- 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 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:
- return 'exe_wrap' in self.build.environment.cross_info.config['binaries']
- return True # This is semantically confusing.
-
- 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
- for c in clist:
- if c.get_language() == cname:
- return CompilerHolder(c, self.build.environment)
- raise InterpreterException('Tried to access compiler for unspecified language "%s".' % cname)
-
- def is_unity_method(self, args, kwargs):
- return self.build.environment.coredata.get_builtin_option('unity')
-
- 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']
-
-class Interpreter():
-
- def __init__(self, build, backend, subproject='', subdir='', subproject_dir='subprojects'):
- self.build = build
- self.backend = backend
- self.subproject = subproject
- self.subdir = subdir
- self.source_root = build.environment.get_source_dir()
- self.subproject_dir = subproject_dir
- option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt')
- if os.path.exists(option_file):
- oi = optinterpreter.OptionInterpreter(self.subproject, \
- self.build.environment.cmd_line_options.projectoptions)
- oi.process(option_file)
- self.build.environment.merge_options(oi.options)
- 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)
- code = open(mesonfile).read()
- if len(code.strip()) == 0:
- raise InvalidCode('Builder file is empty.')
- assert(isinstance(code, str))
- try:
- self.ast = mparser.Parser(code).parse()
- except coredata.MesonException as me:
- me.file = environment.build_filename
- raise me
- self.sanity_check_ast()
- self.variables = {}
- self.builtin = {}
- self.builtin['build_machine'] = BuildMachine()
- 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']
- self.builtin['meson'] = MesonMain(build, self)
- self.environment = build.environment
- self.build_func_dict()
- self.build_def_files = [os.path.join(self.subdir, environment.build_filename)]
- self.coredata = self.environment.get_coredata()
- self.generators = []
- self.visited_subdirs = {}
- self.global_args_frozen = False
- self.subprojects = {}
- self.subproject_stack = []
-
- def build_func_dict(self):
- self.funcs = {'project' : self.func_project,
- 'message' : self.func_message,
- 'error' : self.func_error,
- 'executable': self.func_executable,
- 'dependency' : self.func_dependency,
- 'static_library' : self.func_static_lib,
- 'shared_library' : self.func_shared_lib,
- 'library' : self.func_library,
- 'jar' : self.func_jar,
- 'build_target': self.func_build_target,
- 'custom_target' : self.func_custom_target,
- 'run_target' : self.func_run_target,
- 'generator' : self.func_generator,
- 'test' : self.func_test,
- 'benchmark' : self.func_benchmark,
- 'install_headers' : self.func_install_headers,
- 'install_man' : self.func_install_man,
- 'subdir' : self.func_subdir,
- 'install_data' : self.func_install_data,
- 'install_subdir' : self.func_install_subdir,
- 'configure_file' : self.func_configure_file,
- 'include_directories' : self.func_include_directories,
- 'add_global_arguments' : self.func_add_global_arguments,
- 'add_languages' : self.func_add_languages,
- 'find_program' : self.func_find_program,
- 'find_library' : self.func_find_library,
- 'configuration_data' : self.func_configuration_data,
- 'run_command' : self.func_run_command,
- 'gettext' : self.func_gettext,
- 'option' : self.func_option,
- 'get_option' : self.func_get_option,
- 'subproject' : self.func_subproject,
- 'vcs_tag' : self.func_vcs_tag,
- 'set_variable' : self.func_set_variable,
- 'is_variable' : self.func_is_variable,
- 'get_variable' : self.func_get_variable,
- 'import' : self.func_import,
- 'files' : self.func_files,
- 'declare_dependency': self.func_declare_dependency,
- 'assert': self.func_assert,
- }
-
- def module_method_callback(self, invalues):
- unwrap_single = False
- if invalues is None:
- return
- if not isinstance(invalues, list):
- unwrap_single = True
- invalues = [invalues]
- outvalues = []
- for v in invalues:
- if isinstance(v, build.CustomTarget):
- if v.name in self.build.targets:
- raise InterpreterException('Tried to create target %s which already exists.' % v.name)
- self.build.targets[v.name] = v
- outvalues.append(CustomTargetHolder(v))
- elif isinstance(v, int) or isinstance(v, str):
- outvalues.append(v)
- elif isinstance(v, build.Executable):
- if v.name in self.build.targets:
- raise InterpreterException('Tried to create target %s which already exists.' % v.name)
- self.build.targets[v.name] = v
- outvalues.append(ExecutableHolder(v))
- elif isinstance(v, list):
- outvalues.append(self.module_method_callback(v))
- elif isinstance(v, build.GeneratedList):
- outvalues.append(GeneratedListHolder(v))
- elif isinstance(v, build.RunTarget):
- if v.name in self.build.targets:
- raise InterpreterException('Tried to create target %s which already exists.' % v.name)
- self.build.targets[v.name] = v
- elif isinstance(v, build.InstallScript):
- self.build.install_scripts.append(v)
- elif isinstance(v, build.Data):
- self.build.data.append(v)
- else:
- print(v)
- raise InterpreterException('Module returned a value of unknown type.')
- if len(outvalues) == 1 and unwrap_single:
- return outvalues[0]
- return outvalues
-
- def get_build_def_files(self):
- return self.build_def_files
-
- def get_variables(self):
- return self.variables
-
- 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 len(self.ast.lines) == 0:
- 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):
- self.evaluate_codeblock(self.ast)
- mlog.log('Build targets in project:', mlog.bold(str(len(self.build.targets))))
-
- def evaluate_codeblock(self, node):
- 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
- i = 0
- while i < len(statements):
- cur = statements[i]
- try:
- 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 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 func_set_variable(self, node, args, kwargs):
- if len(args) != 2:
- raise InvalidCode('Set_variable takes two arguments.')
- varname = args[0]
- value = self.to_native(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
-
- @stringArgs
- @noKwargs
- def func_import(self, node, args, kwargs):
- if len(args) != 1:
- raise InvalidCode('Import takes one argument.')
- modname = args[0]
- if not modname in self.environment.coredata.modules:
- module = importlib.import_module('meson.modules.' + modname).initialize()
- self.environment.coredata.modules[modname] = module
- 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]
-
- @noPosargs
- def func_declare_dependency(self, node, args, kwargs):
- incs = kwargs.get('include_directories', [])
- if not isinstance(incs, list):
- incs = [incs]
- libs = kwargs.get('link_with', [])
- if not isinstance(libs, list):
- libs = [libs]
- sources = kwargs.get('sources', [])
- if not isinstance(sources, list):
- sources = [sources]
- sources = self.source_strings_to_files(self.flatten(sources))
- deps = kwargs.get('dependencies', [])
- if not isinstance(deps, list):
- deps = [deps]
- 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)
- dep = dependencies.InternalDependency(incs, libs, sources, final_deps)
- return InternalDependencyHolder(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 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 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 self.is_elementary_type(cur):
- return cur
- else:
- raise InvalidCode("Unknown statement.")
-
- 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 != None:
- if not isinstance(actual, wanted):
- raise InvalidArguments('Incorrect argument type.')
-
- def func_run_command(self, node, args, kwargs):
- if len(args) < 1:
- raise InterpreterException('Not enough arguments')
- cmd = args[0]
- cargs = args[1:]
- if isinstance(cmd, ExternalProgramHolder):
- cmd = cmd.get_command()
- elif isinstance(cmd, str):
- cmd = [cmd]
- else:
- raise InterpreterException('First argument is of incorrect type.')
- check_stringlist(cargs, 'Run_command arguments must be strings.')
- args = cmd + cargs
- in_builddir = kwargs.get('in_builddir', False)
- if not isinstance(in_builddir, bool):
- raise InterpreterException('in_builddir must be boolean.')
- return RunProcess(args, self.environment.source_dir, self.environment.build_dir,
- self.subdir, in_builddir)
-
- @stringArgs
- def func_gettext(self, nodes, args, kwargs):
- if len(args) != 1:
- raise InterpreterException('Gettext requires one positional argument (package name).')
- packagename = args[0]
- languages = kwargs.get('languages', None)
- check_stringlist(languages, 'Argument languages must be a list of strings.')
- # TODO: check that elements are strings
- if len(self.build.pot) > 0:
- raise InterpreterException('More than one gettext definition currently not supported.')
- self.build.pot.append((packagename, languages, self.subdir))
-
- 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.')
-
- @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 self.subdir != '':
- segs = os.path.split(self.subdir)
- if len(segs) != 2 or segs[0] != self.subproject_dir:
- raise InterpreterException('Subprojects must be defined at the root directory.')
- if dirname in self.subproject_stack:
- fullstack = self.subproject_stack + [dirname]
- incpath = ' => '.join(fullstack)
- raise InterpreterException('Recursive include of subprojects: %s.' % incpath)
- if dirname in self.subprojects:
- return self.subprojects[dirname]
- r = wrap.Resolver(os.path.join(self.build.environment.get_source_dir(), self.subproject_dir))
- resolved = r.resolve(dirname)
- if resolved is None:
- raise InterpreterException('Subproject directory does not exist and can not be downloaded.')
- 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)
- 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 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] = True
- 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.')
- optname = args[0]
- try:
- return self.environment.get_coredata().get_builtin_option(optname)
- except RuntimeError:
- pass
- try:
- return self.environment.coredata.compiler_options[optname].value
- except KeyError:
- pass
- if optname not in coredata.builtin_options and self.is_subproject():
- optname = self.subproject + ':' + optname
- try:
- return self.environment.coredata.user_options[optname].value
- except KeyError:
- raise InterpreterException('Tried to access unknown option "%s".' % optname)
-
- @noKwargs
- def func_configuration_data(self, node, args, kwargs):
- if len(args) != 0:
- raise InterpreterException('configuration_data takes no arguments')
- return ConfigurationDataHolder()
-
- def parse_default_options(self, default_options):
- if not isinstance(default_options, list):
- default_options = [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)
- builtin_options = self.coredata.builtin_options
- if key in builtin_options:
- if not hasattr(self.environment.cmd_line_options, value):
- self.coredata.set_builtin_option(key, value)
- # If this was set on the command line, do not override.
- else:
- newoptions = [option] + self.environment.cmd_line_options.projectoptions
- self.environment.cmd_line_options.projectoptions = newoptions
-
- @stringArgs
- def func_project(self, node, args, kwargs):
- if len(args) < 2:
- raise InvalidArguments('Not enough arguments to project(). Needs at least the project name and one language')
-
- if not self.is_subproject():
- self.build.project_name = args[0]
- if self.environment.first_invocation and 'default_options' in kwargs:
- self.parse_default_options(kwargs['default_options'])
- self.active_projectname = args[0]
- self.project_version = kwargs.get('version', 'undefined')
- proj_license = mesonlib.stringlistify(kwargs.get('license', 'unknown'))
- self.build.dep_manifest[args[0]] = {'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:
- self.subproject_dir = kwargs['subproject_dir']
-
- 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] = args[0]
- mlog.log('Project name: ', mlog.bold(args[0]), sep='')
- self.add_languages(node, args[1:])
- langs = self.coredata.compilers.keys()
- if 'vala' in langs:
- if not 'c' in langs:
- raise InterpreterException('Compiling Vala requires C. Add C to your project languages and rerun Meson.')
-
- @noKwargs
- @stringArgs
- def func_add_languages(self, node, args, kwargs):
- self.add_languages(node, args)
-
- @noKwargs
- def func_message(self, node, args, kwargs):
- # 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.')
-
- mlog.log(mlog.bold('Message:'), argstr)
- return
-
-
- @noKwargs
- def func_error(self, node, args, kwargs):
- self.validate_arguments(args, 1, [str])
- raise InterpreterException('Error encountered: ' + args[0])
-
- def add_languages(self, node, args):
- need_cross_compiler = self.environment.is_cross_build() and self.environment.cross_info.need_cross_compiler()
- for lang in args:
- lang = lang.lower()
- if lang in self.coredata.compilers:
- comp = self.coredata.compilers[lang]
- cross_comp = self.coredata.cross_compilers.get(lang, None)
- else:
- 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 is too (I think).
- elif lang == 'rust':
- comp = self.environment.detect_rust_compiler()
- if need_cross_compiler:
- cross_comp = comp # FIXME, probably not correct.
- 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.coredata.compilers[lang] = comp
- if cross_comp is not None:
- cross_comp.sanity_check(self.environment.get_scratch_dir())
- self.coredata.cross_compilers[lang] = cross_comp
- new_options = 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
- mlog.log('Native %s compiler: ' % lang, mlog.bold(' '.join(comp.get_exelist())), ' (%s %s)' % (comp.id, comp.version), sep='')
- if not comp.get_language() in self.coredata.external_args:
- (ext_compile_args, ext_link_args) = environment.get_args_from_envvars(comp.get_language())
- self.coredata.external_args[comp.get_language()] = ext_compile_args
- self.coredata.external_link_args[comp.get_language()] = ext_link_args
- self.build.add_compiler(comp)
- if need_cross_compiler:
- mlog.log('Cross %s compiler: ' % lang, 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)
-
- def func_find_program(self, node, args, kwargs):
- self.validate_arguments(args, 1, [str])
- required = kwargs.get('required', True)
- if not isinstance(required, bool):
- raise InvalidArguments('"required" argument must be a boolean.')
- exename = args[0]
- if exename in self.coredata.ext_progs and\
- self.coredata.ext_progs[exename].found():
- return ExternalProgramHolder(self.coredata.ext_progs[exename])
- # Search for scripts relative to current subdir.
- search_dir = os.path.join(self.environment.get_source_dir(), self.subdir)
- extprog = dependencies.ExternalProgram(exename, search_dir=search_dir)
- progobj = ExternalProgramHolder(extprog)
- self.coredata.ext_progs[exename] = extprog
- if required and not progobj.found():
- raise InvalidArguments('Program "%s" not found.' % exename)
- return progobj
-
- def func_find_library(self, node, args, kwargs):
- self.validate_arguments(args, 1, [str])
- required = kwargs.get('required', True)
- if not isinstance(required, bool):
- raise InvalidArguments('"required" argument must be a boolean.')
- libname = args[0]
- # We do not cache found libraries because they can come
- # and go between invocations wildly. As an example we
- # may find the 64 bit version but need instead the 32 bit
- # one that is not installed. If we cache the found path
- # then we will never found the new one if it get installed.
- # This causes a bit of a slowdown as libraries are rechecked
- # on every regen, but since it is a fast operation it should be
- # ok.
- if 'dirs' in kwargs:
- search_dirs = kwargs['dirs']
- if not isinstance(search_dirs, list):
- search_dirs = [search_dirs]
- for i in search_dirs:
- if not isinstance(i, str):
- raise InvalidCode('Directory entry is not a string.')
- if not os.path.isabs(i):
- raise InvalidCode('Search directory %s is not an absolute path.' % i)
- else:
- search_dirs = None
- result = self.environment.find_library(libname, search_dirs)
- extlib = dependencies.ExternalLibrary(libname, result)
- libobj = ExternalLibraryHolder(extlib)
- if required and not libobj.found():
- raise InvalidArguments('External library "%s" not found.' % libname)
- return libobj
-
- def func_dependency(self, node, args, kwargs):
- self.validate_arguments(args, 1, [str])
- name = args[0]
- identifier = dependencies.get_dep_identifier(name, kwargs)
- if identifier in self.coredata.deps:
- dep = self.coredata.deps[identifier]
- else:
- dep = dependencies.Dependency() # Returns always false for dep.found()
- if not dep.found():
- try:
- dep = dependencies.find_external_dependency(name, self.environment, kwargs)
- except dependencies.DependencyException:
- if 'fallback' in kwargs:
- return self.dependency_fallback(kwargs)
- raise
- self.coredata.deps[identifier] = dep
- return DependencyHolder(dep)
-
- def dependency_fallback(self, kwargs):
- fbinfo = kwargs['fallback']
- check_stringlist(fbinfo)
- if len(fbinfo) != 2:
- raise InterpreterException('Fallback info must have exactly two items.')
- dirname, varname = fbinfo
- self.do_subproject(dirname, kwargs)
- return self.subprojects[dirname].get_variable_method([varname], {})
-
- def func_executable(self, node, args, kwargs):
- return self.build_target(node, args, kwargs, ExecutableHolder)
-
- def func_static_lib(self, node, args, kwargs):
- return self.build_target(node, args, kwargs, StaticLibraryHolder)
-
- def func_shared_lib(self, node, args, kwargs):
- return self.build_target(node, args, kwargs, SharedLibraryHolder)
-
- 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)
-
- def func_jar(self, node, args, kwargs):
- return self.build_target(node, args, kwargs, JarHolder)
-
- 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.')
-
- def func_vcs_tag(self, node, args, kwargs):
- fallback = kwargs.pop('fallback', None)
- if not isinstance(fallback, str):
- raise InterpreterException('Keyword argument fallback must exist and 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'] = [sys.executable,
- 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
- def func_custom_target(self, node, args, kwargs):
- if len(args) != 1:
- raise InterpreterException('Incorrect number of arguments')
- name = args[0]
- tg = CustomTargetHolder(build.CustomTarget(name, self.subdir, kwargs))
- self.add_target(name, tg.held_object)
- return tg
-
- @noKwargs
- def func_run_target(self, node, args, kwargs):
- if len(args) < 2:
- raise InterpreterException('Incorrect number of arguments')
- cleaned_args = []
- for i in args:
- try:
- i = i.held_object
- except AttributeError:
- pass
- if not isinstance(i, (str, build.BuildTarget, build.CustomTarget)):
- mlog.debug('Wrong type:', str(i))
- raise InterpreterException('Invalid argument to run_target.')
- cleaned_args.append(i)
- name = cleaned_args[0]
- command = cleaned_args[1]
- cmd_args = cleaned_args[2:]
- tg = RunTargetHolder(name, command, cmd_args, self.subdir)
- self.add_target(name, tg.held_object)
- return tg
-
- def func_generator(self, node, args, kwargs):
- gen = GeneratorHolder(self, args, kwargs)
- self.generators.append(gen)
- return gen
-
- def func_benchmark(self, node, args, kwargs):
- self.add_test(node, args, kwargs, False)
-
- def func_test(self, node, args, kwargs):
- self.add_test(node, args, kwargs, True)
-
- 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.')
- if not isinstance(args[1], (ExecutableHolder, JarHolder, ExternalProgramHolder)):
- 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 = kwargs.get('args', [])
- if not isinstance(cmd_args, list):
- cmd_args = [cmd_args]
- for i in cmd_args:
- if not isinstance(i, (str, mesonlib.File)):
- raise InterpreterException('Command line arguments must be strings')
- envlist = kwargs.get('env', [])
- if not isinstance(envlist, list):
- envlist = [envlist]
- env = {}
- 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[k] = val
- valgrind_args = kwargs.get('valgrind_args', [])
- if not isinstance(valgrind_args, list):
- valgrind_args = [valgrind_args]
- for a in valgrind_args:
- if not isinstance(a, str):
- raise InterpreterException('Valgrind_arg not a string.')
- 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 = mesonlib.stringlistify(kwargs.get('suite', ''))
- if self.is_subproject():
- newsuite = []
- for s in suite:
- newsuite.append(self.subproject.replace(' ', '_').replace('.', '_') + '.' + s)
- suite = newsuite
- t = Test(args[0], suite, args[1].held_object, par, cmd_args, env, should_fail, valgrind_args, 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='')
-
- @stringArgs
- def func_install_headers(self, node, args, kwargs):
- h = Headers(self.subdir, args, kwargs)
- self.build.headers.append(h)
- return h
-
- @stringArgs
- def func_install_man(self, node, args, kwargs):
- m = Man(self.subdir, args, kwargs)
- self.build.man.append(m)
- return m
-
- @noKwargs
- def func_subdir(self, node, args, kwargs):
- self.validate_arguments(args, 1, [str])
- 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.')
- prev_subdir = self.subdir
- subdir = os.path.join(prev_subdir, args[0])
- if subdir in self.visited_subdirs:
- raise InvalidArguments('Tried to enter directory "%s", which has already been visited.'\
- % subdir)
- self.visited_subdirs[subdir] = True
- self.subdir = subdir
- try:
- os.makedirs(os.path.join(self.environment.build_dir, subdir))
- except FileExistsError:
- pass
- 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):
- raise InterpreterException('Nonexistant build def file %s.' % buildfilename)
- code = open(absname).read()
- assert(isinstance(code, str))
- try:
- codeblock = mparser.Parser(code).parse()
- except coredata.MesonException as me:
- me.file = buildfilename
- raise me
- self.evaluate_codeblock(codeblock)
- self.subdir = prev_subdir
-
- @stringArgs
- def func_install_data(self, node, args, kwargs):
- data = DataHolder(True, self.subdir, args, kwargs)
- self.build.data.append(data.held_object)
- return data
-
- @stringArgs
- def func_install_subdir(self, node, args, kwargs):
- if len(args) != 1:
- raise InvalidArguments('Install_subdir requires exactly one argument.')
- if not 'install_dir' 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.')
- idir = InstallDir(self.subdir, args[0], install_dir)
- self.build.install_dirs.append(idir)
- return idir
-
- def func_configure_file(self, node, args, kwargs):
- if len(args) > 0:
- raise InterpreterException("configure_file takes only keyword arguments.")
- if not 'input' in kwargs:
- raise InterpreterException('Required keyword argument "input" not defined.')
- if not 'output' in kwargs:
- raise InterpreterException('Required keyword argument "output" not defined.')
- inputfile = kwargs['input']
- output = kwargs['output']
- if not isinstance(inputfile, str):
- raise InterpreterException('Input must be a string.')
- if not isinstance(output, str):
- raise InterpreterException('Output must be a string.')
- if 'configuration' in kwargs:
- conf = kwargs['configuration']
- if not isinstance(conf, ConfigurationDataHolder):
- raise InterpreterException('Argument "configuration" is not of type configuration_data')
-
- conffile = os.path.join(self.subdir, inputfile)
- if conffile not in self.build_def_files:
- self.build_def_files.append(conffile)
- os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True)
- ifile_abs = os.path.join(self.environment.source_dir, self.subdir, inputfile)
- ofile_abs = os.path.join(self.environment.build_dir, self.subdir, output)
- mesonlib.do_conf_file(ifile_abs, ofile_abs, conf.held_object)
- conf.mark_used()
- elif 'command' in kwargs:
- res = self.func_run_command(node, kwargs['command'], {})
- if res.returncode != 0:
- raise InterpreterException('Running configure command failed.\n%s\n%s' %
- (res.stdout, res.stderr))
- else:
- raise InterpreterException('Configure_file must have either "configuration" or "command".')
- if isinstance(kwargs.get('install_dir', None), str):
- self.build.data.append(DataHolder(False, self.subdir, [output], kwargs).held_object)
- return mesonlib.File.from_built_file(self.subdir, output)
-
- @stringArgs
- def func_include_directories(self, node, args, kwargs):
- absbase = os.path.join(self.environment.get_source_dir(), self.subdir)
- for a in args:
- absdir = os.path.join(absbase, a)
- if not os.path.isdir(absdir):
- raise InvalidArguments('Include dir %s does not exist.' % a)
- is_system = kwargs.get('is_system', False)
- if not isinstance(is_system, bool):
- raise InvalidArguments('Is_system must be boolean.')
- i = IncludeDirsHolder(build.IncludeDirs(self.subdir, args, is_system))
- return i
-
- @stringArgs
- def func_add_global_arguments(self, node, args, kwargs):
- if self.subproject != '':
- raise InvalidCode('Global arguments can not be set in subprojects because there is no way to make that reliable.')
- if self.global_args_frozen:
- raise InvalidCode('Tried to set global arguments after a build target has been declared.\nThis is not permitted. Please declare all global arguments before your targets.')
- if not 'language' in kwargs:
- raise InvalidCode('Missing language definition in add_global_arguments')
- lang = kwargs['language'].lower()
- if lang in self.build.global_args:
- self.build.global_args[lang] += args
- else:
- self.build.global_args[lang] = args
-
- def flatten(self, args):
- if isinstance(args, mparser.StringNode):
- return args.value
- if isinstance(args, str):
- return args
- if isinstance(args, InterpreterObject):
- return args
- if isinstance(args, int):
- 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 source_strings_to_files(self, sources):
- results = []
- for s in sources:
- if isinstance(s, mesonlib.File) or isinstance(s, GeneratedListHolder) or \
- isinstance(s, CustomTargetHolder):
- pass
- elif isinstance(s, str):
- s = mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, s)
- else:
- raise InterpreterException("Source item is not string or File-type object.")
- results.append(s)
- return results
-
- def add_target(self, name, tobj):
- 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):
- name = args[0]
- sources = args[1:]
- if self.environment.is_cross_build():
- if kwargs.get('native', False):
- is_cross = False
- else:
- is_cross = True
- else:
- is_cross = False
- try:
- kw_src = self.flatten(kwargs['sources'])
- if not isinstance(kw_src, list):
- kw_src = [kw_src]
- except KeyError:
- kw_src = []
- sources += kw_src
- sources = self.source_strings_to_files(sources)
- objs = self.flatten(kwargs.get('objects', []))
- kwargs['dependencies'] = self.flatten(kwargs.get('dependencies', []))
- if not isinstance(objs, list):
- objs = [objs]
- 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 StaticLibraryHolder:
- targetclass = build.StaticLibrary
- elif targetholder is JarHolder:
- targetclass = build.Jar
- else:
- mlog.debug('Unknown target type:', str(targetholder))
- raise RuntimeError('Unreachable code')
- target = targetclass(name, self.subdir, self.subproject, is_cross, sources, objs, self.environment, kwargs)
- l = targetholder(target, self)
- self.add_target(name, l.held_object)
- self.global_args_frozen = True
- return 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 %s.' % s)
-
- def function_call(self, node):
- func_name = node.func_name
- (posargs, kwargs) = self.reduce_arguments(node.args)
- if func_name in self.funcs:
- return self.funcs[func_name](node, self.flatten(posargs), kwargs)
- else:
- raise InvalidCode('Unknown function "%s".' % func_name)
-
- def is_assignable(self, value):
- if isinstance(value, InterpreterObject) or \
- isinstance(value, dependencies.Dependency) or\
- isinstance(value, str) or\
- isinstance(value, int) or \
- isinstance(value, list) or \
- isinstance(value, mesonlib.File):
- return True
- return False
-
- def assignment(self, node):
- assert(isinstance(node, mparser.AssignmentNode))
- 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)
- value = self.to_native(value)
- if not self.is_assignable(value):
- raise InvalidCode('Tried to assign an invalid value to variable.')
- self.set_variable(var_name, value)
- return value
-
- def reduce_arguments(self, args):
- assert(isinstance(args, mparser.ArgumentNode))
- if args.incorrect_order():
- raise InvalidArguments('All keyword arguments must be after positional arguments.')
- 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)
- if not isinstance(reduced_pos, list):
- reduced_pos = [reduced_pos]
- return (reduced_pos, reduced_kw)
-
- def string_method_call(self, obj, method_name, args):
- obj = self.to_native(obj)
- (posargs, _) = self.reduce_arguments(args)
- if method_name == 'strip':
- return obj.strip()
- elif method_name == 'format':
- return self.format_string(obj, args)
- elif method_name == 'split':
- if len(posargs) > 1:
- raise InterpreterException('Split() must have at most one argument.')
- elif len(posargs) == 1:
- s = posargs[0]
- if not isinstance(s, str):
- raise InterpreterException('Split() argument must be a string')
- return obj.split(s)
- else:
- return obj.split()
- elif method_name == 'startswith' 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)
- return obj.endswith(s)
- raise InterpreterException('Unknown method "%s" for a string.' % method_name)
-
- def to_native(self, arg):
- if isinstance(arg, mparser.StringNode) or \
- isinstance(arg, mparser.NumberNode) or \
- isinstance(arg, mparser.BooleanNode):
- return arg.value
- return arg
-
- def format_string(self, templ, args):
- templ = self.to_native(templ)
- if isinstance(args, mparser.ArgumentNode):
- args = args.arguments
- for (i, arg) in enumerate(args):
- arg = self.to_native(self.evaluate_statement(arg))
- if isinstance(arg, bool): # Python boolean is upper case.
- arg = str(arg).lower()
- templ = templ.replace('@{}@'.format(i), str(arg))
- return templ
-
- 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
- if method_name == 'extract_objects' and self.environment.coredata.get_builtin_option('unity'):
- raise InterpreterException('Single object files can not be extracted in Unity builds.')
- args = node.args
- if isinstance(obj, mparser.StringNode):
- obj = obj.get_value()
- if isinstance(obj, str):
- return self.string_method_call(obj, method_name, args)
- if isinstance(obj, list):
- return self.array_method_call(obj, method_name, self.reduce_arguments(args)[0])
- if not isinstance(obj, InterpreterObject):
- raise InvalidArguments('Variable "%s" is not callable.' % object_name)
- (args, kwargs) = self.reduce_arguments(args)
- if method_name == 'extract_objects':
- self.validate_extraction(obj.held_object)
- return obj.method_call(method_name, self.flatten(args), kwargs)
-
- # 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 array_method_call(self, obj, method_name, args):
- if method_name == 'contains':
- return self.check_contains(obj, args)
- elif method_name == 'length':
- return len(obj)
- elif method_name == 'get':
- index = args[0]
- if not isinstance(index, int):
- raise InvalidArguments('Array index must be a number.')
- if index < -len(obj) or index >= len(obj):
- raise InvalidArguments('Array index %s is out of bounds for array of size %d.' % (index, len(obj)))
- return obj[index]
- raise InterpreterException('Arrays do not have a method called "%s".' % method_name)
-
- 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
- try:
- if element == item:
- return True
- except Exception:
- pass
- return False
-
- def evaluate_if(self, node):
- assert(isinstance(node, mparser.IfClauseNode))
- for i in node.ifs:
- result = self.evaluate_statement(i.condition)
- if not(isinstance(result, bool)):
- print(result)
- raise InvalidCode('If clause does not evaluate to true or false.')
- if result:
- self.evaluate_codeblock(i.block)
- return
- if not isinstance(node.elseblock, mparser.EmptyNode):
- self.evaluate_codeblock(node.elseblock)
-
- def evaluate_foreach(self, node):
- assert(isinstance(node, mparser.ForeachClauseNode))
- varname = node.varname.value
- items = self.evaluate_statement(node.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)
- # 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 not isinstance(old_variable, list):
- raise InvalidArguments('The += operator currently only works with arrays.')
- # 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 not isinstance(iobject, list):
- raise InterpreterException('Tried to index a non-array object.')
- index = self.evaluate_statement(node.index)
- if not isinstance(index, int):
- raise InterpreterException('Index value is not an integer.')
- if index < -len(iobject) or index >= len(iobject):
- raise InterpreterException('Index %d out of bounds of array of size %d.' % (index, len(iobject)))
- return iobject[index]
-
- def is_elementary_type(self, v):
- if isinstance(v, (int, float, str, bool, list)):
- return True
- return False
-
- def evaluate_comparison(self, node):
- v1 = self.evaluate_statement(node.left)
- v2 = self.evaluate_statement(node.right)
- if self.is_elementary_type(v1):
- val1 = v1
- else:
- val1 = v1.value
- if self.is_elementary_type(v2):
- val2 = v2
- else:
- val2 = v2.value
- if node.ctype == '==':
- return val1 == val2
- elif node.ctype == '!=':
- return val1 != val2
- else:
- raise InvalidCode('You broke me.')
-
- def evaluate_andstatement(self, cur):
- l = self.evaluate_statement(cur.left)
- if isinstance(l, mparser.BooleanNode):
- l = l.value
- 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 isinstance(r, mparser.BooleanNode):
- r = r.value
- 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 isinstance(l, mparser.BooleanNode):
- l = l.get_value()
- 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 isinstance(r, mparser.BooleanNode):
- r = r.get_value()
- if not isinstance(r, bool):
- raise InterpreterException('Second argument to "or" is not a boolean.')
- return r
-
- def evaluate_notstatement(self, cur):
- v = self.evaluate_statement(cur.value)
- if isinstance(v, mparser.BooleanNode):
- v = v.value
- if not isinstance(v, bool):
- raise InterpreterException('Argument to "not" is not a boolean.')
- return not v
-
- def evaluate_uminusstatement(self, cur):
- v = self.evaluate_statement(cur.value)
- if isinstance(v, mparser.NumberNode):
- v = v.value
- if not isinstance(v, int):
- raise InterpreterException('Argument to negation is not an integer.')
- return -v
-
- def evaluate_arithmeticstatement(self, cur):
- l = self.to_native(self.evaluate_statement(cur.left))
- r = self.to_native(self.evaluate_statement(cur.right))
-
- 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
- else:
- raise InvalidCode('You broke me.')
-
- 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 is_subproject(self):
- return self.subproject != ''
diff --git a/meson/mconf.py b/meson/mconf.py
deleted file mode 100644
index f174425..0000000
--- a/meson/mconf.py
+++ /dev/null
@@ -1,209 +0,0 @@
-#!/usr/bin/env python3
-
-# 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 sys, os
-import pickle
-import argparse
-from . import coredata, mesonlib
-from .coredata import build_types, warning_levels, libtypelist
-
-parser = argparse.ArgumentParser()
-
-parser.add_argument('-D', action='append', default=[], dest='sets',
- help='Set an option to the given value.')
-parser.add_argument('directory', nargs='*')
-
-class ConfException(coredata.MesonException):
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
-class Conf:
- def __init__(self, build_dir):
- self.build_dir = build_dir
- self.coredata_file = os.path.join(build_dir, 'meson-private/coredata.dat')
- self.build_file = os.path.join(build_dir, 'meson-private/build.dat')
- if not os.path.isfile(self.coredata_file) or not os.path.isfile(self.build_file):
- raise ConfException('Directory %s does not seem to be a Meson build directory.' % build_dir)
- self.coredata = pickle.load(open(self.coredata_file, 'rb'))
- self.build = pickle.load(open(self.build_file, 'rb'))
- if self.coredata.version != coredata.version:
- raise ConfException('Version mismatch (%s vs %s)' %
- (coredata.version, self.coredata.version))
-
- def save(self):
- # Only called if something has changed so overwrite unconditionally.
- pickle.dump(self.coredata, open(self.coredata_file, 'wb'))
- # We don't write the build file because any changes to it
- # are erased when Meson is executed the nex time, i.e. the next
- # time Ninja is run.
-
- def print_aligned(self, arr):
- if len(arr) == 0:
- return
- titles = ['Option', 'Description', 'Current Value', '']
- longest_name = len(titles[0])
- longest_descr = len(titles[1])
- longest_value = len(titles[2])
- longest_possible_value = len(titles[3])
- for x in arr:
- longest_name = max(longest_name, len(x[0]))
- longest_descr = max(longest_descr, len(x[1]))
- longest_value = max(longest_value, len(str(x[2])))
- longest_possible_value = max(longest_possible_value, len(x[3]))
-
- if longest_possible_value > 0:
- titles[3] = 'Possible Values'
- print(' %s%s %s%s %s%s %s' % (titles[0], ' '*(longest_name - len(titles[0])), titles[1], ' '*(longest_descr - len(titles[1])), titles[2], ' '*(longest_value - len(titles[2])), titles[3]))
- print(' %s%s %s%s %s%s %s' % ('-'*len(titles[0]), ' '*(longest_name - len(titles[0])), '-'*len(titles[1]), ' '*(longest_descr - len(titles[1])), '-'*len(titles[2]), ' '*(longest_value - len(titles[2])), '-'*len(titles[3])))
- for i in arr:
- name = i[0]
- descr = i[1]
- value = i[2]
- if isinstance(value, bool):
- value = 'true' if value else 'false'
- possible_values = i[3]
- namepad = ' '*(longest_name - len(name))
- descrpad = ' '*(longest_descr - len(descr))
- valuepad = ' '*(longest_value - len(str(value)))
- f = ' %s%s %s%s %s%s %s' % (name, namepad, descr, descrpad, value, valuepad, possible_values)
- print(f)
-
- def set_options(self, options):
- for o in options:
- if '=' not in o:
- raise ConfException('Value "%s" not of type "a=b".' % o)
- (k, v) = o.split('=', 1)
- if self.coredata.is_builtin_option(k):
- self.coredata.set_builtin_option(k, v)
- elif k in self.coredata.user_options:
- tgt = self.coredata.user_options[k]
- tgt.set_value(v)
- elif k in self.coredata.compiler_options:
- tgt = self.coredata.compiler_options[k]
- tgt.set_value(v)
- elif k.endswith('linkargs'):
- lang = k[:-8]
- if not lang in self.coredata.external_link_args:
- raise ConfException('Unknown language %s in linkargs.' % lang)
- # TODO, currently split on spaces, make it so that user
- # can pass in an array string.
- newvalue = v.split()
- self.coredata.external_link_args[lang] = newvalue
- elif k.endswith('args'):
- lang = k[:-4]
- if not lang in self.coredata.external_args:
- raise ConfException('Unknown language %s in compile args' % lang)
- # TODO same fix as above
- newvalue = v.split()
- self.coredata.external_args[lang] = newvalue
- else:
- raise ConfException('Unknown option %s.' % k)
-
-
- def print_conf(self):
- print('Core properties:')
- print(' Source dir', self.build.environment.source_dir)
- print(' Build dir ', self.build.environment.build_dir)
- print('')
- print('Core options:')
- carr = []
- booleans = '[true, false]'
- carr.append(['buildtype', 'Build type', self.coredata.get_builtin_option('buildtype'), build_types])
- carr.append(['warning_level', 'Warning level', self.coredata.get_builtin_option('warning_level'), warning_levels])
- carr.append(['strip', 'Strip on install', self.coredata.get_builtin_option('strip'), booleans])
- carr.append(['coverage', 'Coverage report', self.coredata.get_builtin_option('coverage'), booleans])
- carr.append(['use_pch', 'Precompiled headers', self.coredata.get_builtin_option('use_pch'), booleans])
- carr.append(['unity', 'Unity build', self.coredata.get_builtin_option('unity'), booleans])
- carr.append(['default_library', 'Default library type', self.coredata.get_builtin_option('default_library'), libtypelist])
- self.print_aligned(carr)
- print('')
- print('Compiler arguments:')
- for (lang, args) in self.coredata.external_args.items():
- print(' ' + lang + 'args', str(args))
- print('')
- print('Linker args:')
- for (lang, args) in self.coredata.external_link_args.items():
- print(' ' + lang + 'linkargs', str(args))
- print('')
- print('Compiler options:')
- okeys = sorted(self.coredata.compiler_options.keys())
- if len(okeys) == 0:
- print(' No compiler options\n')
- else:
- coarr = []
- for k in okeys:
- o = self.coredata.compiler_options[k]
- coarr.append([k, o.description, o.value, ''])
- self.print_aligned(coarr)
- print('')
- print('Directories:')
- parr = []
- parr.append(['prefix', 'Install prefix', self.coredata.get_builtin_option('prefix'), ''])
- parr.append(['libdir', 'Library directory', self.coredata.get_builtin_option('libdir'), ''])
- parr.append(['bindir', 'Binary directory', self.coredata.get_builtin_option('bindir'), ''])
- parr.append(['includedir', 'Header directory', self.coredata.get_builtin_option('includedir'), ''])
- parr.append(['datadir', 'Data directory', self.coredata.get_builtin_option('datadir'), ''])
- parr.append(['mandir', 'Man page directory', self.coredata.get_builtin_option('mandir'), ''])
- parr.append(['localedir', 'Locale file directory', self.coredata.get_builtin_option('localedir'), ''])
- self.print_aligned(parr)
- print('')
- print('Project options:')
- if len(self.coredata.user_options) == 0:
- print(' This project does not have any options')
- else:
- options = self.coredata.user_options
- keys = list(options.keys())
- keys.sort()
- optarr = []
- for key in keys:
- opt = options[key]
- if (opt.choices is None) or (len(opt.choices) == 0):
- # Zero length list or string
- choices = '';
- else:
- # A non zero length list or string, convert to string
- choices = str(opt.choices);
- optarr.append([key, opt.description, opt.value, choices])
- self.print_aligned(optarr)
-
-def run(args):
- args = mesonlib.expand_arguments(args)
- if not args:
- sys.exit(1)
- options = parser.parse_args(args)
- if len(options.directory) > 1:
- print('%s <build directory>' % args[0])
- print('If you omit the build directory, the current directory is substituted.')
- return 1
- if len(options.directory) == 0:
- builddir = os.getcwd()
- else:
- builddir = options.directory[0]
- try:
- c = Conf(builddir)
- if len(options.sets) > 0:
- c.set_options(options.sets)
- c.save()
- else:
- c.print_conf()
- 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:]))
diff --git a/meson/mesonlib.py b/meson/mesonlib.py
deleted file mode 100644
index 2ab5ce4..0000000
--- a/meson/mesonlib.py
+++ /dev/null
@@ -1,284 +0,0 @@
-# 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 platform, subprocess, operator, os, shutil, re, sys
-
-from glob import glob
-
-from .coredata import MesonException
-
-class File:
- def __init__(self, is_built, subdir, fname):
- self.is_built = is_built
- self.subdir = subdir
- self.fname = fname
-
- @staticmethod
- def from_source_file(source_root, subdir, fname):
- if not os.path.isfile(os.path.join(source_root, subdir, fname)):
- raise MesonException('File %s does not exist.' % fname)
- return File(False, subdir, fname)
-
- @staticmethod
- def from_built_file(subdir, fname):
- return File(True, subdir, fname)
-
- @staticmethod
- def from_absolute_file(fname):
- return File(False, '', fname)
-
- def rel_to_builddir(self, build_to_src):
- if self.is_built:
- return os.path.join(self.subdir, self.fname)
- else:
- return os.path.join(build_to_src, self.subdir, self.fname)
-
- def endswith(self, ending):
- return self.fname.endswith(ending)
-
- def split(self, s):
- return self.fname.split(s)
-
- def __eq__(self, other):
- return (self.fname, self.subdir, self.is_built) == (other.fname, other.subdir, other.is_built)
-
- def __hash__(self):
- return hash((self.fname, self.subdir, self.is_built))
-
-def flatten(item):
- if not isinstance(item, list):
- return item
- result = []
- for i in item:
- if isinstance(i, list):
- result += flatten(i)
- else:
- result.append(i)
- return result
-
-def is_osx():
- return platform.system().lower() == 'darwin'
-
-def is_linux():
- return platform.system().lower() == 'linux'
-
-def is_windows():
- platname = platform.system().lower()
- return platname == 'windows' or 'mingw' in platname
-
-def is_32bit():
- return not(sys.maxsize > 2**32)
-
-def is_debianlike():
- try:
- open('/etc/debian_version', 'r')
- return True
- except FileNotFoundError:
- return False
-
-def exe_exists(arglist):
- try:
- p = subprocess.Popen(arglist, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- p.communicate()
- if p.returncode == 0:
- return True
- except FileNotFoundError:
- pass
- return False
-
-def detect_vcs(source_dir):
- vcs_systems = [
- dict(name = 'git', cmd = 'git', repo_dir = '.git', get_rev = 'git describe --dirty=+', rev_regex = '(.*)', dep = '.git/logs/HEAD'),
- dict(name = 'mercurial', cmd = 'hg', repo_dir = '.hg', get_rev = 'hg id -n', rev_regex = '(.*)', dep = '.hg/dirstate'),
- dict(name = 'subversion', cmd = 'svn', repo_dir = '.svn', get_rev = 'svn info', rev_regex = 'Revision: (.*)', dep = '.svn/wc.db'),
- dict(name = 'bazaar', cmd = 'bzr', repo_dir = '.bzr', get_rev = 'bzr revno', rev_regex = '(.*)', dep = '.bzr'),
- ]
-
- segs = source_dir.replace('\\', '/').split('/')
- for i in range(len(segs), -1, -1):
- curdir = '/'.join(segs[:i])
- for vcs in vcs_systems:
- if os.path.isdir(os.path.join(curdir, vcs['repo_dir'])) and shutil.which(vcs['cmd']):
- vcs['wc_dir'] = curdir
- return vcs
- return None
-
-numpart = re.compile('[0-9.]+')
-
-def version_compare(vstr1, vstr2):
- match = numpart.match(vstr1.strip())
- if match is None:
- raise MesonException('Unconparable version string %s.' % vstr1)
- vstr1 = match.group(0)
- if vstr2.startswith('>='):
- 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 = [int(x) for x in vstr1.split('.')]
- varr2 = [int(x) for x in vstr2.split('.')]
- return cmpop(varr1, varr2)
-
-def default_libdir():
- try:
- archpath = subprocess.check_output(['dpkg-architecture', '-qDEB_HOST_MULTIARCH']).decode().strip()
- return 'lib/' + archpath
- except:
- pass
- if os.path.isdir('/usr/lib64'):
- return 'lib64'
- return 'lib'
-
-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):
- match = re.search(regex, line)
- while match:
- varname = match.group(1)
- if varname in confdata.keys():
- var = 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:
- var = ''
- line = line.replace('@' + varname + '@', var)
- match = re.search(regex, line)
- return line
-
-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 = 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):
- data = open(src).readlines()
- regex = re.compile('@(.*?)@')
- result = []
- for line in data:
- if line.startswith('#mesondefine'):
- line = do_mesondefine(line, confdata)
- else:
- line = do_replacement(regex, line, confdata)
- result.append(line)
- dst_tmp = dst + '~'
- open(dst_tmp, 'w').writelines(result)
- shutil.copymode(src, dst_tmp)
- replace_if_different(dst, dst_tmp)
-
-
-def replace_if_different(dst, dst_tmp):
- # If contents are identical, don't touch the file to prevent
- # unnecessary rebuilds.
- try:
- if open(dst, 'r').read() == open(dst_tmp, 'r').read():
- os.unlink(dst_tmp)
- return
- except FileNotFoundError:
- pass
- os.replace(dst_tmp, dst)
-
-def stringlistify(item):
- if isinstance(item, str):
- item = [item]
- if not isinstance(item, list):
- raise MesonException('Item is not an array')
- for i in item:
- if not isinstance(i, str):
- raise MesonException('List item not a string.')
- return item
-
-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
diff --git a/meson/mesonmain.py b/meson/mesonmain.py
deleted file mode 100644
index 7b4f2c2..0000000
--- a/meson/mesonmain.py
+++ /dev/null
@@ -1,263 +0,0 @@
-#!/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.
-
-import sys, stat, traceback, pickle, argparse
-import datetime
-import os.path
-from . import environment, interpreter, mesonlib
-from . import build
-import platform
-from . import mlog, coredata
-
-from .coredata import MesonException, build_types, layouts, warning_levels, libtypelist
-
-backendlist = ['ninja', 'vs2010', 'xcode']
-
-parser = argparse.ArgumentParser()
-
-default_warning = '1'
-
-if mesonlib.is_windows():
- def_prefix = 'c:/'
-else:
- def_prefix = '/usr/local'
-
-parser.add_argument('--prefix', default=def_prefix, dest='prefix',
- help='the installation prefix (default: %(default)s)')
-parser.add_argument('--libdir', default=mesonlib.default_libdir(), dest='libdir',
- help='the installation subdir of libraries (default: %(default)s)')
-parser.add_argument('--bindir', default='bin', dest='bindir',
- help='the installation subdir of executables (default: %(default)s)')
-parser.add_argument('--includedir', default='include', dest='includedir',
- help='relative path of installed headers (default: %(default)s)')
-parser.add_argument('--datadir', default='share', dest='datadir',
- help='relative path to the top of data file subdirectory (default: %(default)s)')
-parser.add_argument('--mandir', default='share/man', dest='mandir',
- help='relative path of man files (default: %(default)s)')
-parser.add_argument('--localedir', default='share/locale', dest='localedir',
- help='relative path of locale data (default: %(default)s)')
-parser.add_argument('--backend', default='ninja', dest='backend', choices=backendlist,
- help='backend to use (default: %(default)s)')
-parser.add_argument('--buildtype', default='debug', choices=build_types, dest='buildtype',
- help='build type go use (default: %(default)s)')
-parser.add_argument('--strip', action='store_true', dest='strip', default=False,\
- help='strip targets on install (default: %(default)s)')
-parser.add_argument('--enable-gcov', action='store_true', dest='coverage', default=False,\
- help='measure test coverage')
-parser.add_argument('--disable-pch', action='store_false', dest='use_pch', default=True,\
- help='do not use precompiled headers')
-parser.add_argument('--unity', action='store_true', dest='unity', default=False,\
- help='unity build')
-parser.add_argument('--werror', action='store_true', dest='werror', default=False,\
- help='Treat warnings as errors')
-parser.add_argument('--layout', choices=layouts, dest='layout', default='mirror',\
- help='Build directory layout.')
-parser.add_argument('--default-library', choices=libtypelist, dest='default_library',
- default='shared', help='Default library type.')
-parser.add_argument('--warnlevel', default=default_warning, dest='warning_level', choices=warning_levels,\
- help='Level of compiler warnings to use (larger is more, default is %(default)s)')
-parser.add_argument('--cross-file', default=None, dest='cross_file',
- help='file describing cross compilation environment')
-parser.add_argument('-D', action='append', dest='projectoptions', default=[],
- help='Set project options.')
-parser.add_argument('-v', '--version', action='store_true', dest='print_version', default=False,
- help='Print version.')
-parser.add_argument('directories', nargs='*')
-
-class MesonApp():
-
- def __init__(self, dir1, dir2, script_file, handshake, options):
- (self.source_dir, self.build_dir) = self.validate_dirs(dir1, dir2, handshake)
- if not os.path.isabs(options.prefix):
- raise RuntimeError('--prefix must be an absolute path.')
- self.meson_script_file = script_file
- self.options = options
-
- 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(dir1)
- ndir2 = os.path.abspath(dir2)
- 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:
- msg = '''Trying to run Meson on a build directory that has already been configured.
-If you want to build it, just run your build command (e.g. ninja) inside the
-build directory. Meson will autodetect any changes in your setup and regenerate
-itself as required.'''
- raise RuntimeError(msg)
- else:
- if handshake:
- raise RuntimeError('Something went terribly wrong. Please file a bug.')
- return (src_dir, build_dir)
-
- def generate(self):
- env = environment.Environment(self.source_dir, self.build_dir, self.meson_script_file, self.options)
- mlog.initialize(env.get_log_dir())
- mlog.debug('Build started at', datetime.datetime.now().isoformat())
- mlog.debug('Python binary:', sys.executable)
- mlog.debug('Python system:', platform.system())
- mlog.log(mlog.bold('The Meson build system'))
- 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 . import ninjabackend
- g = ninjabackend.NinjaBackend(b)
- elif self.options.backend == 'vs2010':
- from . import vs2010backend
- g = vs2010backend.Vs2010Backend(b)
- elif self.options.backend == 'xcode':
- from . 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()
- g.generate(intr)
- env.generating_finished()
- dumpfile = os.path.join(env.get_scratch_dir(), 'build.dat')
- pickle.dump(b, open(dumpfile, 'wb'))
-
-def run_script_command(args):
- cmdname = args[0]
- cmdargs = args[1:]
- if cmdname == 'test':
- import meson.scripts.meson_test as abc
- cmdfunc = abc.run
- elif cmdname == 'benchmark':
- import meson.scripts.meson_benchmark as abc
- cmdfunc = abc.run
- elif cmdname == 'install':
- import meson.scripts.meson_install as abc
- cmdfunc = abc.run
- elif cmdname == 'commandrunner':
- import meson.scripts.commandrunner as abc
- cmdfunc = abc.run
- elif cmdname == 'delsuffix':
- import meson.scripts.delwithsuffix as abc
- cmdfunc = abc.run
- elif cmdname == 'depfixer':
- import meson.scripts.depfixer as abc
- cmdfunc = abc.run
- elif cmdname == 'dirchanger':
- import meson.scripts.dirchanger as abc
- cmdfunc = abc.run
- elif cmdname == 'gtkdoc':
- import meson.scripts.gtkdochelper as abc
- cmdfunc = abc.run
- elif cmdname == 'regencheck':
- import meson.scripts.regen_checker as abc
- cmdfunc = abc.run
- elif cmdname == 'symbolextractor':
- import meson.scripts.symbolextractor as abc
- cmdfunc = abc.run
- elif cmdname == 'vcstagger':
- import meson.scripts.vcstagger as abc
- cmdfunc = abc.run
- else:
- raise MesonException('Unknown internal command {}.'.format(cmdname))
- return cmdfunc(cmdargs)
-
-def run(mainfile, args):
- if sys.version_info < (3, 3):
- print('Meson works correctly only with python 3.3+.')
- print('You have python %s.' % sys.version)
- print('Please update your environment')
- return 1
- if args[0] == '--internal':
- if args[1] != 'regenerate':
- sys.exit(run_script_command(args[1:]))
- args = args[2:]
- handshake = True
- else:
- handshake = False
- args = mesonlib.expand_arguments(args)
- if not args:
- return 1
- options = parser.parse_args(args)
- if options.print_version:
- print(coredata.version)
- return 0
- args = options.directories
- if len(args) == 0 or len(args) > 2:
- print('%s <source directory> <build directory>' % sys.argv[0])
- print('If you omit either directory, the current directory is substituted.')
- return 1
- dir1 = args[0]
- if len(args) > 1:
- dir2 = args[1]
- else:
- dir2 = '.'
- while os.path.islink(mainfile):
- resolved = os.readlink(mainfile)
- if resolved[0] != '/':
- mainfile = os.path.join(os.path.dirname(mainfile), resolved)
- else:
- mainfile = resolved
-
- try:
- app = MesonApp(dir1, dir2, mainfile, handshake, options)
- 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):
- 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
diff --git a/meson/mesonmain.ui b/meson/mesonmain.ui
deleted file mode 100644
index 209584b..0000000
--- a/meson/mesonmain.ui
+++ /dev/null
@@ -1,248 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>740</width>
- <height>613</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Meson</string>
- </property>
- <widget class="QWidget" name="centralwidget">
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Project</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="project_label">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>TextLabel</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Source directory</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="srcdir_label">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>TextLabel</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_5">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Build directory</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLabel" name="builddir_label">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>TextLabel</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_7">
- <property name="text">
- <string>Build type</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLabel" name="buildtype_label">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>TextLabel</string>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Backend</string>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QLabel" name="backend_label">
- <property name="text">
- <string>Ninja</string>
- </property>
- </widget>
- </item>
- <item row="5" column="0" colspan="2">
- <widget class="QTabWidget" name="tabWidget">
- <property name="currentIndex">
- <number>2</number>
- </property>
- <widget class="QWidget" name="core_tab">
- <attribute name="title">
- <string>Core data</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_6">
- <item row="0" column="0">
- <widget class="QTreeView" name="core_view"/>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="path_tab">
- <attribute name="title">
- <string>Paths</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="0" column="0">
- <widget class="QTreeView" name="path_view"/>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="option_tab">
- <attribute name="title">
- <string>Options</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_4">
- <item row="0" column="0">
- <layout class="QFormLayout" name="option_form"/>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="dependency_tab">
- <attribute name="title">
- <string>Dependencies</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_5">
- <item row="0" column="0">
- <widget class="QTreeView" name="dep_view"/>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="target_tab">
- <attribute name="title">
- <string>Build targets</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="0">
- <widget class="QTreeView" name="target_view"/>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- <item row="6" column="0" colspan="2">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QPushButton" name="save_button">
- <property name="text">
- <string>Save</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="compile_button">
- <property name="text">
- <string>Compile</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="test_button">
- <property name="text">
- <string>Run tests</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="install_button">
- <property name="text">
- <string>Install</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="clean_button">
- <property name="text">
- <string>Clean</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <widget class="QMenuBar" name="menubar">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>740</width>
- <height>25</height>
- </rect>
- </property>
- <widget class="QMenu" name="menuFile">
- <property name="title">
- <string>File</string>
- </property>
- <addaction name="actionSave"/>
- <addaction name="actionQuit"/>
- </widget>
- <addaction name="menuFile"/>
- </widget>
- <widget class="QStatusBar" name="statusbar"/>
- <action name="actionSave">
- <property name="text">
- <string>&amp;Save</string>
- </property>
- </action>
- <action name="actionQuit">
- <property name="text">
- <string>&amp;Quit</string>
- </property>
- </action>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/meson/mesonrunner.ui b/meson/mesonrunner.ui
deleted file mode 100644
index 942c6bd..0000000
--- a/meson/mesonrunner.ui
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>rundialog</class>
- <widget class="QDialog" name="rundialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>581</width>
- <height>368</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>External process output</string>
- </property>
- <property name="modal">
- <bool>true</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="1" column="0">
- <widget class="QLabel" name="timelabel">
- <property name="text">
- <string>Compile time: 0:0</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QPushButton" name="termbutton">
- <property name="text">
- <string>Terminate</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0" colspan="2">
- <widget class="QTextEdit" name="console">
- <property name="readOnly">
- <bool>true</bool>
- </property>
- <property name="html">
- <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
-&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
-p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/meson/mesonstart.ui b/meson/mesonstart.ui
deleted file mode 100644
index c6c5f96..0000000
--- a/meson/mesonstart.ui
+++ /dev/null
@@ -1,119 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>644</width>
- <height>192</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Meson</string>
- </property>
- <widget class="QWidget" name="centralwidget">
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Source directory</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="source_entry">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QPushButton" name="source_browse_button">
- <property name="text">
- <string>Browse</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Build directory</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="build_entry">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QPushButton" name="build_browse_button">
- <property name="text">
- <string>Browse</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Cross file</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLineEdit" name="cross_entry">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QPushButton" name="cross_browse_button">
- <property name="text">
- <string>Browse</string>
- </property>
- </widget>
- </item>
- <item row="3" column="2">
- <widget class="QPushButton" name="generate_button">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Generate</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QMenuBar" name="menubar">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>644</width>
- <height>25</height>
- </rect>
- </property>
- </widget>
- <widget class="QStatusBar" name="statusbar"/>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/meson/mgui.py b/meson/mgui.py
deleted file mode 100644
index 6e57ce7..0000000
--- a/meson/mgui.py
+++ /dev/null
@@ -1,565 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright 2013-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 sys, os, pickle, time, shutil
-from . import build, coredata, environment, mesonlib
-from PyQt5 import uic
-from PyQt5.QtWidgets import QApplication, QMainWindow, QHeaderView
-from PyQt5.QtWidgets import QComboBox, QCheckBox
-from PyQt5.QtCore import QAbstractItemModel, QModelIndex, QVariant, QTimer
-import PyQt5.QtCore
-import PyQt5.QtWidgets
-
-priv_dir = os.path.split(os.path.abspath(os.path.realpath(__file__)))[0]
-
-class PathModel(QAbstractItemModel):
- def __init__(self, coredata):
- super().__init__()
- self.coredata = coredata
- self.names = ['Prefix', 'Library dir', 'Binary dir', 'Include dir', 'Data dir',\
- 'Man dir', 'Locale dir']
- self.attr_name = ['prefix', 'libdir', 'bindir', 'includedir', 'datadir', \
- 'mandir', 'localedir']
-
- def args(self, index):
- if index.column() == 1:
- editable = PyQt5.QtCore.Qt.ItemIsEditable
- else:
- editable= 0
- return PyQt5.QtCore.Qt.ItemIsSelectable | PyQt5.QtCore.Qt.ItemIsEnabled | editable
-
- def rowCount(self, index):
- if index.isValid():
- return 0
- return len(self.names)
-
- def columnCount(self, index):
- return 2
-
- def headerData(self, section, orientation, role):
- if role != PyQt5.QtCore.Qt.DisplayRole:
- return QVariant()
- if section == 1:
- return QVariant('Path')
- return QVariant('Type')
-
- def index(self, row, column, parent):
- return self.createIndex(row, column)
-
- def data(self, index, role):
- if role != PyQt5.QtCore.Qt.DisplayRole:
- return QVariant()
- row = index.row()
- column = index.column()
- if column == 0:
- return self.names[row]
- return getattr(self.coredata, self.attr_name[row])
-
- def parent(self, index):
- return QModelIndex()
-
- def setData(self, index, value, role):
- if role != PyQt5.QtCore.Qt.EditRole:
- return False
- row = index.row()
- column = index.column()
- s = str(value)
- setattr(self.coredata, self.attr_name[row], s)
- self.dataChanged.emit(self.createIndex(row, column), self.createIndex(row, column))
- return True
-
-class TargetModel(QAbstractItemModel):
- def __init__(self, builddata):
- super().__init__()
- self.targets = []
- for target in builddata.get_targets().values():
- name = target.get_basename()
- num_sources = len(target.get_sources()) + len(target.get_generated_sources())
- 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'
- else:
- typename = 'unknown'
- if target.should_install():
- installed = 'Yes'
- else:
- installed = 'No'
- self.targets.append((name, typename, installed, num_sources))
-
- def args(self, index):
- return PyQt5.QtCore.Qt.ItemIsSelectable | PyQt5.QtCore.Qt.ItemIsEnabled
-
- def rowCount(self, index):
- if index.isValid():
- return 0
- return len(self.targets)
-
- def columnCount(self, index):
- return 4
-
- def headerData(self, section, orientation, role):
- if role != PyQt5.QtCore.Qt.DisplayRole:
- return QVariant()
- if section == 3:
- return QVariant('Source files')
- if section == 2:
- return QVariant('Installed')
- if section == 1:
- return QVariant('Type')
- return QVariant('Name')
-
- def data(self, index, role):
- if role != PyQt5.QtCore.Qt.DisplayRole:
- return QVariant()
- row = index.row()
- column = index.column()
- return self.targets[row][column]
-
- def index(self, row, column, parent):
- return self.createIndex(row, column)
-
- def parent(self, index):
- return QModelIndex()
-
-class DependencyModel(QAbstractItemModel):
- def __init__(self, coredata):
- super().__init__()
- self.deps = []
- for k in coredata.deps.keys():
- bd = coredata.deps[k]
- name = k
- found = bd.found()
- if found:
- cflags = str(bd.get_compile_args())
- libs = str(bd.get_link_args())
- found = 'yes'
- else:
- cflags = ''
- libs = ''
- found = 'no'
- self.deps.append((name, found, cflags, libs))
-
- def args(self, index):
- return PyQt5.QtCore.Qt.ItemIsSelectable | PyQt5.QtCore.Qt.ItemIsEnabled
-
- def rowCount(self, index):
- if index.isValid():
- return 0
- return len(self.deps)
-
- def columnCount(self, index):
- return 4
-
- def headerData(self, section, orientation, role):
- if role != PyQt5.QtCore.Qt.DisplayRole:
- return QVariant()
- if section == 3:
- return QVariant('Link args')
- if section == 2:
- return QVariant('Compile args')
- if section == 1:
- return QVariant('Found')
- return QVariant('Name')
-
- def data(self, index, role):
- if role != PyQt5.QtCore.Qt.DisplayRole:
- return QVariant()
- row = index.row()
- column = index.column()
- return self.deps[row][column]
-
- def index(self, row, column, parent):
- return self.createIndex(row, column)
-
- def parent(self, index):
- return QModelIndex()
-
-class CoreModel(QAbstractItemModel):
- def __init__(self, core_data):
- super().__init__()
- self.elems = []
- for langname, comp in core_data.compilers.items():
- self.elems.append((langname + ' compiler', str(comp.get_exelist())))
- for langname, comp in core_data.cross_compilers.items():
- self.elems.append((langname + ' cross compiler', str(comp.get_exelist())))
-
- def args(self, index):
- return PyQt5.QtCore.Qt.ItemIsSelectable | PyQt5.QtCore.Qt.ItemIsEnabled
-
- def rowCount(self, index):
- if index.isValid():
- return 0
- return len(self.elems)
-
- def columnCount(self, index):
- return 2
-
- def headerData(self, section, orientation, role):
- if role != PyQt5.QtCore.Qt.DisplayRole:
- return QVariant()
- if section == 1:
- return QVariant('Value')
- return QVariant('Name')
-
- def data(self, index, role):
- if role != PyQt5.QtCore.Qt.DisplayRole:
- return QVariant()
- row = index.row()
- column = index.column()
- return self.elems[row][column]
-
- def index(self, row, column, parent):
- return self.createIndex(row, column)
-
- def parent(self, index):
- return QModelIndex()
-
-class OptionForm:
- def __init__(self, coredata, form):
- self.coredata = coredata
- self.form = form
- form.addRow(PyQt5.QtWidgets.QLabel("Meson options"))
- combo = QComboBox()
- combo.addItem('plain')
- combo.addItem('debug')
- combo.addItem('debugoptimized')
- combo.addItem('release')
- combo.setCurrentText(self.coredata.get_builtin_option('buildtype'))
- combo.currentTextChanged.connect(self.build_type_changed)
- self.form.addRow('Build type', combo)
- strip = QCheckBox("")
- strip.setChecked(self.coredata.get_builtin_option('strip'))
- strip.stateChanged.connect(self.strip_changed)
- self.form.addRow('Strip on install', strip)
- coverage = QCheckBox("")
- coverage.setChecked(self.coredata.get_builtin_option('coverage'))
- coverage.stateChanged.connect(self.coverage_changed)
- self.form.addRow('Enable coverage', coverage)
- pch = QCheckBox("")
- pch.setChecked(self.coredata.get_builtin_option('use_pch'))
- pch.stateChanged.connect(self.pch_changed)
- self.form.addRow('Enable pch', pch)
- unity = QCheckBox("")
- unity.setChecked(self.coredata.get_builtin_option('unity'))
- unity.stateChanged.connect(self.unity_changed)
- self.form.addRow('Unity build', unity)
- form.addRow(PyQt5.QtWidgets.QLabel("Project options"))
- self.set_user_options()
-
- def set_user_options(self):
- options = self.coredata.user_options
- keys = list(options.keys())
- keys.sort()
- self.opt_keys = keys
- self.opt_widgets = []
- for key in keys:
- opt = options[key]
- if isinstance(opt, mesonlib.UserStringOption):
- w = PyQt5.QtWidgets.QLineEdit(opt.value)
- w.textChanged.connect(self.user_option_changed)
- elif isinstance(opt, mesonlib.UserBooleanOption):
- w = QCheckBox('')
- w.setChecked(opt.value)
- w.stateChanged.connect(self.user_option_changed)
- elif isinstance(opt, mesonlib.UserComboOption):
- w = QComboBox()
- for i in opt.choices:
- w.addItem(i)
- w.setCurrentText(opt.value)
- w.currentTextChanged.connect(self.user_option_changed)
- else:
- raise RuntimeError("Unknown option type")
- self.opt_widgets.append(w)
- self.form.addRow(opt.description, w)
-
- def user_option_changed(self, dummy=None):
- for i in range(len(self.opt_keys)):
- key = self.opt_keys[i]
- w = self.opt_widgets[i]
- if isinstance(w, PyQt5.QtWidgets.QLineEdit):
- newval = w.text()
- elif isinstance(w, QComboBox):
- newval = w.currentText()
- elif isinstance(w, QCheckBox):
- if w.checkState() == 0:
- newval = False
- else:
- newval = True
- else:
- raise RuntimeError('Unknown widget type')
- self.coredata.user_options[key].set_value(newval)
-
- def build_type_changed(self, newtype):
- self.coredata.buildtype = newtype
-
- def strip_changed(self, newState):
- if newState == 0:
- ns = False
- else:
- ns = True
- self.coredata.strip = ns
-
- def coverage_changed(self, newState):
- if newState == 0:
- ns = False
- else:
- ns = True
- self.coredata.coverage = ns
-
- def pch_changed(self, newState):
- if newState == 0:
- ns = False
- else:
- ns = True
- self.coredata.use_pch = ns
-
- def unity_changed(self, newState):
- if newState == 0:
- ns = False
- else:
- ns = True
- self.coredata.unity = ns
-
-class ProcessRunner():
- def __init__(self, rundir, cmdlist):
- self.cmdlist = cmdlist
- self.ui = uic.loadUi(os.path.join(priv_dir, 'mesonrunner.ui'))
- self.timer = QTimer(self.ui)
- self.timer.setInterval(1000)
- self.timer.timeout.connect(self.timeout)
- self.process = PyQt5.QtCore.QProcess()
- self.process.setProcessChannelMode(PyQt5.QtCore.QProcess.MergedChannels)
- self.process.setWorkingDirectory(rundir)
- self.process.readyRead.connect(self.read_data)
- self.process.finished.connect(self.finished)
- self.ui.termbutton.clicked.connect(self.terminated)
- self.return_value = 100
-
- def run(self):
- self.process.start(self.cmdlist[0], self.cmdlist[1:])
- self.timer.start()
- self.start_time = time.time()
- return self.ui.exec()
-
- def read_data(self):
- while(self.process.canReadLine()):
- txt = bytes(self.process.readLine()).decode('utf8')
- self.ui.console.append(txt)
-
- def finished(self):
- self.read_data()
- self.ui.termbutton.setText('Done')
- self.timer.stop()
- self.return_value = self.process.exitCode()
-
- def terminated(self, foo):
- self.process.kill()
- self.timer.stop()
- self.ui.done(self.return_value)
-
- def timeout(self):
- now = time.time()
- duration = int(now - self.start_time)
- msg = 'Elapsed time: %d:%d' % (duration // 60, duration % 60)
- self.ui.timelabel.setText(msg)
-
-class MesonGui():
- def __init__(self, respawner, build_dir):
- self.respawner = respawner
- uifile = os.path.join(priv_dir, 'mesonmain.ui')
- self.ui = uic.loadUi(uifile)
- self.coredata_file = os.path.join(build_dir, 'meson-private/coredata.dat')
- self.build_file = os.path.join(build_dir, 'meson-private/build.dat')
- if not os.path.exists(self.coredata_file):
- print("Argument is not build directory.")
- sys.exit(1)
- self.coredata = pickle.load(open(self.coredata_file, 'rb'))
- self.build = pickle.load(open(self.build_file, 'rb'))
- self.build_dir = self.build.environment.build_dir
- self.src_dir = self.build.environment.source_dir
- self.build_models()
- self.options = OptionForm(self.coredata, self.ui.option_form)
- self.ui.show()
-
- def hide(self):
- self.ui.hide()
-
- def geometry(self):
- return self.ui.geometry()
-
- def move(self, x, y):
- return self.ui.move(x, y)
-
- def size(self):
- return self.ui.size()
-
- def resize(self, s):
- return self.ui.resize(s)
-
- def build_models(self):
- self.path_model = PathModel(self.coredata)
- self.target_model = TargetModel(self.build)
- self.dep_model = DependencyModel(self.coredata)
- self.core_model = CoreModel(self.coredata)
- self.fill_data()
- self.ui.core_view.setModel(self.core_model)
- hv = QHeaderView(1)
- hv.setModel(self.core_model)
- self.ui.core_view.setHeader(hv)
- self.ui.path_view.setModel(self.path_model)
- hv = QHeaderView(1)
- hv.setModel(self.path_model)
- self.ui.path_view.setHeader(hv)
- self.ui.target_view.setModel(self.target_model)
- hv = QHeaderView(1)
- hv.setModel(self.target_model)
- self.ui.target_view.setHeader(hv)
- self.ui.dep_view.setModel(self.dep_model)
- hv = QHeaderView(1)
- hv.setModel(self.dep_model)
- self.ui.dep_view.setHeader(hv)
- self.ui.compile_button.clicked.connect(self.compile)
- self.ui.test_button.clicked.connect(self.run_tests)
- self.ui.install_button.clicked.connect(self.install)
- self.ui.clean_button.clicked.connect(self.clean)
- self.ui.save_button.clicked.connect(self.save)
-
- def fill_data(self):
- self.ui.project_label.setText(self.build.projects[''])
- self.ui.srcdir_label.setText(self.src_dir)
- self.ui.builddir_label.setText(self.build_dir)
- if self.coredata.cross_file is None:
- btype = 'Native build'
- else:
- btype = 'Cross build'
- self.ui.buildtype_label.setText(btype)
-
- def run_process(self, cmdlist):
- cmdlist = [shutil.which(environment.detect_ninja())] + cmdlist
- dialog = ProcessRunner(self.build.environment.build_dir, cmdlist)
- dialog.run()
- # All processes (at the moment) may change cache state
- # so reload.
- self.respawner.respawn()
-
- def compile(self, foo):
- self.run_process([])
-
- def run_tests(self, foo):
- self.run_process(['test'])
-
- def install(self, foo):
- self.run_process(['install'])
-
- def clean(self, foo):
- self.run_process(['clean'])
-
- def save(self, foo):
- pickle.dump(self.coredata, open(self.coredata_file, 'wb'))
-
-class Starter():
- def __init__(self, sdir):
- uifile = os.path.join(priv_dir, 'mesonstart.ui')
- self.ui = uic.loadUi(uifile)
- self.ui.source_entry.setText(sdir)
- self.dialog = PyQt5.QtWidgets.QFileDialog()
- if len(sdir) == 0:
- self.dialog.setDirectory(os.getcwd())
- else:
- self.dialog.setDirectory(sdir)
- self.ui.source_browse_button.clicked.connect(self.src_browse_clicked)
- self.ui.build_browse_button.clicked.connect(self.build_browse_clicked)
- self.ui.cross_browse_button.clicked.connect(self.cross_browse_clicked)
- self.ui.source_entry.textChanged.connect(self.update_button)
- self.ui.build_entry.textChanged.connect(self.update_button)
- self.ui.generate_button.clicked.connect(self.generate)
- self.update_button()
- self.ui.show()
-
- def generate(self):
- srcdir = self.ui.source_entry.text()
- builddir = self.ui.build_entry.text()
- cross = self.ui.cross_entry.text()
- cmdlist = [os.path.join(os.path.split(__file__)[0], 'meson.py'), srcdir, builddir]
- if cross != '':
- cmdlist += ['--cross', cross]
- pr = ProcessRunner(os.getcwd(), cmdlist)
- rvalue = pr.run()
- if rvalue == 0:
- os.execl(__file__, 'dummy', builddir)
-
- def update_button(self):
- if self.ui.source_entry.text() == '' or self.ui.build_entry.text() == '':
- self.ui.generate_button.setEnabled(False)
- else:
- self.ui.generate_button.setEnabled(True)
-
- def src_browse_clicked(self):
- self.dialog.setFileMode(2)
- if self.dialog.exec():
- self.ui.source_entry.setText(self.dialog.selectedFiles()[0])
-
- def build_browse_clicked(self):
- self.dialog.setFileMode(2)
- if self.dialog.exec():
- self.ui.build_entry.setText(self.dialog.selectedFiles()[0])
-
- def cross_browse_clicked(self):
- self.dialog.setFileMode(1)
- if self.dialog.exec():
- self.ui.cross_entry.setText(self.dialog.selectedFiles()[0])
-
-# Rather than rewrite all classes and arrays to be
-# updateable, just rebuild the entire GUI from
-# scratch whenever data on disk changes.
-
-class MesonGuiRespawner():
- def __init__(self, arg):
- self.arg = arg
- self.gui = MesonGui(self, self.arg)
-
- def respawn(self):
- geo = self.gui.geometry()
- s = self.gui.size()
- self.gui.hide()
- self.gui = MesonGui(self, self.arg)
- self.gui.move(geo.x(), geo.y())
- self.gui.resize(s)
- # Garbage collection takes care of the old gui widget
-
-
-def run(args): # SPECIAL, Qt wants all args, including command name.
- app = QApplication(sys.argv)
- if len(args) == 1:
- arg = ""
- elif len(args) == 2:
- arg = sys.argv[1]
- else:
- print(sys.argv[0], "<build or source dir>")
- return 1
- if os.path.exists(os.path.join(arg, 'meson-private/coredata.dat')):
- guirespawner = MesonGuiRespawner(arg)
- else:
- runner = Starter(arg)
- return app.exec_()
-
-if __name__ == '__main__':
- sys.exit(run(sys.argv))
diff --git a/meson/mintro.py b/meson/mintro.py
deleted file mode 100644
index b088117..0000000
--- a/meson/mintro.py
+++ /dev/null
@@ -1,212 +0,0 @@
-#!/usr/bin/env python3
-
-# 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, pickle
-from . import coredata, build, mesonlib
-import argparse
-import sys, os
-
-parser = argparse.ArgumentParser()
-parser.add_argument('--targets', action='store_true', dest='list_targets', default=False,
- help='List top level targets.')
-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('args', nargs='+')
-
-def list_targets(coredata, builddata):
- tlist = []
- for (idname, target) in builddata.get_targets().items():
- t = {}
- t['name'] = target.get_basename()
- t['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 target.should_install():
- t['installed'] = True
- else:
- t['installed'] = False
- 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
- subdir = t.subdir
- 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):
- buildtype= {'choices': ['plain', 'debug', 'debugoptimized', 'release'],
- 'type' : 'combo',
- 'value' : coredata.buildtype,
- 'description' : 'Build type',
- 'name' : 'type'}
- strip = {'value' : coredata.strip,
- 'type' : 'boolean',
- 'description' : 'Strip on install',
- 'name' : 'strip'}
- coverage = {'value': coredata.coverage,
- 'type' : 'boolean',
- 'description' : 'Enable coverage',
- 'name' : 'coverage'}
- pch = {'value' : coredata.use_pch,
- 'type' : 'boolean',
- 'description' : 'Use precompiled headers',
- 'name' : 'pch'}
- unity = {'value' : coredata.unity,
- 'type' : 'boolean',
- 'description' : 'Unity build',
- 'name' : 'unity'}
- optlist = [buildtype, strip, coverage, pch, unity]
- add_keys(optlist, coredata.user_options)
- add_keys(optlist, coredata.compiler_options)
- print(json.dumps(optlist))
-
-def add_keys(optlist, options):
- keys = list(options.keys())
- keys.sort()
- for key in keys:
- opt = options[key]
- optdict = {}
- optdict['name'] = key
- optdict['value'] = opt.value
- if isinstance(opt, mesonlib.UserStringOption):
- typestr = 'string'
- elif isinstance(opt, mesonlib.UserBooleanOption):
- typestr = 'boolean'
- elif isinstance(opt, mesonlib.UserComboOption):
- optdict['choices'] = opt.choices
- typestr = 'combo'
- elif isinstance(opt, mesonlib.UserStringArrayOption):
- typestr = 'stringarray'
- else:
- raise RuntimeError("Unknown option type")
- optdict['type'] = typestr
- optdict['description'] = opt.description
- optlist.append(optdict)
-
-def list_buildsystem_files(coredata, 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():
- args = {'compile_args': d.get_compile_args(),
- 'link_args': d.get_link_args()}
- result[d.name] = 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
- 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 run(args):
- options = parser.parse_args(args)
- if len(options.args) > 1:
- print('Too many arguments')
- return 1
- elif len(options.args) == 1:
- bdir = options.args[0]
- else:
- bdir = ''
- corefile = os.path.join(bdir, 'meson-private/coredata.dat')
- buildfile = os.path.join(bdir, 'meson-private/build.dat')
- testfile = os.path.join(bdir, 'meson-private/meson_test_setup.dat')
- benchmarkfile = os.path.join(bdir, 'meson-private/meson_benchmark_setup.dat')
- coredata = pickle.load(open(corefile, 'rb'))
- builddata = pickle.load(open(buildfile, 'rb'))
- testdata = pickle.load(open(testfile, 'rb'))
- benchmarkdata = pickle.load(open(benchmarkfile, 'rb'))
- if options.list_targets:
- list_targets(coredata, builddata)
- elif options.target_files is not None:
- list_target_files(options.target_files, coredata, builddata)
- elif options.buildsystem_files:
- list_buildsystem_files(coredata, 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)
- else:
- print('No command specified')
- return 1
- return 0
-
-if __name__ == '__main__':
- sys.exit(run(sys.argv[1:]))
diff --git a/meson/mlog.py b/meson/mlog.py
deleted file mode 100644
index 2807c2b..0000000
--- a/meson/mlog.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# 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
-
-"""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."""
-
-colorize_console = platform.system().lower() != 'windows' and os.isatty(sys.stdout.fileno())
-log_dir = None
-log_file = None
-
-def initialize(logdir):
- global log_dir, log_file
- log_dir = logdir
- log_file = open(os.path.join(logdir, 'meson-log.txt'), 'w')
-
-def shutdown():
- global log_file
- if log_file is not None:
- log_file.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 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 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.
-
-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.
- if colorize_console:
- arr = process_markup(args, True)
- print(*arr, **kwargs)
diff --git a/meson/modules/gnome.py b/meson/modules/gnome.py
deleted file mode 100644
index e552b84..0000000
--- a/meson/modules/gnome.py
+++ /dev/null
@@ -1,330 +0,0 @@
-# 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 and gresources.'''
-
-from .. import build
-import os, sys
-import subprocess
-from ..coredata import MesonException
-from .. import mlog
-import xml.etree.ElementTree as ET
-from ..mesonlib import File
-
-girwarning_printed = False
-
-class GnomeModule:
-
- def compile_resources(self, state, args, kwargs):
- cmd = ['glib-compile-resources', '@INPUT@', '--generate']
- if 'source_dir' in kwargs:
- resource_loc = os.path.join(state.subdir, kwargs.pop('source_dir'))
- d = os.path.join(state.build_to_src, resource_loc)
- cmd += ['--sourcedir', d]
- else:
- resource_loc = state.subdir
- if 'c_name' in kwargs:
- cmd += ['--c-name', kwargs.pop('c_name')]
- cmd += ['--target', '@OUTPUT@']
- kwargs['command'] = cmd
- output_c = args[0] + '.c'
- output_h = args[0] + '.h'
- resfile = args[1]
- kwargs['depend_files'] = self.parse_gresource_xml(state, resfile, resource_loc)
- kwargs['input'] = resfile
- kwargs['output'] = output_c
- target_c = build.CustomTarget(args[0]+'_c', state.subdir, kwargs)
- kwargs['output'] = output_h
- target_h = build.CustomTarget(args[0] + '_h', state.subdir, kwargs)
- return [target_c, target_h]
-
- def parse_gresource_xml(self, state, fobj, resource_loc):
- if isinstance(fobj, File):
- fname = fobj.fname
- subdir = fobj.subdir
- else:
- fname = fobj
- subdir = state.subdir
- abspath = os.path.join(state.environment.source_dir, state.subdir, fname)
- relative_part = os.path.split(fname)[0]
- try:
- tree = ET.parse(abspath)
- root = tree.getroot()
- result = []
- for child in root[0]:
- if child.tag != 'file':
- mlog.log("Warning, malformed rcc file: ", os.path.join(state.subdir, fname))
- break
- else:
- relfname = os.path.join(resource_loc, child.text)
- absfname = os.path.join(state.environment.source_dir, relfname)
- if os.path.isfile(absfname):
- result.append(relfname)
- else:
- mlog.log('Warning, resource file points to nonexisting file %s.' % relfname)
- return result
- except Exception:
- return []
-
- def generate_gir(self, state, args, kwargs):
- if len(args) != 1:
- raise MesonException('Gir takes one argument')
- 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:
- pkgstr = subprocess.check_output(['pkg-config', '--cflags', 'gobject-introspection-1.0'])
- except Exception:
- global girwarning_printed
- if not girwarning_printed:
- mlog.log(mlog.bold('Warning:'), 'gobject-introspection dependency was not found, disabling gir generation.')
- girwarning_printed = True
- return []
- pkgargs = pkgstr.decode().strip().split()
- ns = kwargs.pop('namespace')
- nsversion = kwargs.pop('nsversion')
- libsources = kwargs.pop('sources')
- girfile = '%s-%s.gir' % (ns, nsversion)
- depends = [girtarget]
-
- scan_command = ['g-ir-scanner', '@INPUT@']
- scan_command += pkgargs
- scan_command += ['--no-libtool', '--namespace='+ns, '--nsversion=' + nsversion, '--warn-all',
- '--output', '@OUTPUT@']
-
- extra_args = kwargs.pop('extra_args', [])
- if not isinstance(extra_args, list):
- extra_args = [extra_args]
- scan_command += extra_args
-
- for incdirs in girtarget.include_dirs:
- for incdir in incdirs.get_incdirs():
- scan_command += ['-I%s' % os.path.join(state.environment.get_source_dir(), incdir)]
-
- if 'link_with' in kwargs:
- link_with = kwargs.pop('link_with')
- if not isinstance(link_with, list):
- link_with = [link_with]
- for link in link_with:
- lib = link.held_object
- scan_command += ['-l%s' % lib.name]
- if isinstance(lib, build.SharedLibrary):
- scan_command += ['-L%s' %
- os.path.join(state.environment.get_build_dir(),
- lib.subdir)]
- depends.append(lib)
-
- if 'includes' in kwargs:
- includes = kwargs.pop('includes')
- if isinstance(includes, str):
- scan_command += ['--include=%s' % includes]
- elif isinstance(includes, list):
- scan_command += ['--include=%s' % inc for inc in includes]
- else:
- raise MesonException('Gir includes must be str or list')
- if state.global_args.get('c'):
- scan_command += ['--cflags-begin']
- scan_command += state.global_args['c']
- scan_command += ['--cflags-end']
- if kwargs.get('symbol_prefix'):
- sym_prefix = kwargs.pop('symbol_prefix')
- if not isinstance(sym_prefix, str):
- raise MesonException('Gir symbol prefix must be str')
- scan_command += ['--symbol-prefix=%s' % sym_prefix]
- if kwargs.get('identifier_prefix'):
- 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 kwargs.get('export_packages'):
- 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 = None
- if 'dependencies' in kwargs:
- deps = kwargs.pop('dependencies')
- if not isinstance (deps, list):
- deps = [deps]
- for dep in deps:
- girdir = dep.held_object.get_variable ("girdir")
- if girdir:
- scan_command += ["--add-include-path=%s" % girdir]
- for lib in dep.held_object.libs:
- if os.path.isabs(lib) and dep.held_object.is_libtool:
- scan_command += ["-L%s" % os.path.dirname(lib)]
- libname = os.path.basename(lib)
- if libname.startswith("lib"):
- libname = libname[3:]
- libname = libname.split(".so")[0]
- lib = "-l%s" % libname
- scan_command += [lib]
-
- inc_dirs = None
- if kwargs.get('include_directories'):
- inc_dirs = kwargs.pop('include_directories')
- if not isinstance(inc_dirs, list):
- inc_dirs = [inc_dirs]
- for ind in inc_dirs:
- if isinstance(ind.held_object, build.IncludeDirs):
- scan_command += ['--add-include-path=%s' % inc for inc in ind.held_object.get_incdirs()]
- else:
- raise MesonException('Gir include dirs should be include_directories()')
- if isinstance(girtarget, build.Executable):
- scan_command += ['--program', girtarget]
- elif isinstance(girtarget, build.SharedLibrary):
- scan_command += ["-L@PRIVATE_OUTDIR_ABS_%s@" % girtarget.get_id()]
- libname = girtarget.get_basename()
- scan_command += ['--library', libname]
- scankwargs = {'output' : girfile,
- 'input' : libsources,
- 'command' : scan_command,
- 'depends' : depends,
- }
- if kwargs.get('install'):
- scankwargs['install'] = kwargs['install']
- scankwargs['install_dir'] = os.path.join(state.environment.get_datadir(), 'gir-1.0')
- scan_target = GirTarget(girfile, state.subdir, scankwargs)
-
- typelib_output = '%s-%s.typelib' % (ns, nsversion)
- typelib_cmd = ['g-ir-compiler', scan_target, '--output', '@OUTPUT@']
- if inc_dirs:
- for incd in inc_dirs:
- typelib_cmd += ['--includedir=%s' % inc for inc in
- incd.held_object.get_incdirs()]
- if deps:
- for dep in deps:
- girdir = dep.held_object.get_variable ("girdir")
- if girdir:
- typelib_cmd += ["--includedir=%s" % girdir]
-
- kwargs['output'] = typelib_output
- kwargs['command'] = typelib_cmd
- # Note that this can't be libdir, because e.g. on Debian it points to
- # lib/x86_64-linux-gnu but the girepo dir is always under lib.
- kwargs['install_dir'] = 'lib/girepository-1.0'
- typelib_target = TypelibTarget(typelib_output, state.subdir, kwargs)
- return [scan_target, typelib_target]
-
- def compile_schemas(self, state, args, kwargs):
- if len(args) != 0:
- raise MesonException('Compile_schemas does not take positional arguments.')
- srcdir = os.path.join(state.build_to_src, state.subdir)
- outdir = state.subdir
- cmd = ['glib-compile-schemas', '--targetdir', outdir, srcdir]
- kwargs['command'] = cmd
- kwargs['input'] = []
- kwargs['output'] = 'gschemas.compiled'
- if state.subdir == '':
- targetname = 'gsettings-compile'
- else:
- targetname = 'gsettings-compile-' + state.subdir
- target_g = build.CustomTarget(targetname, state.subdir, kwargs)
- return target_g
-
- 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 not 'src_dir' 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
- src_dir = kwargs['src_dir']
- targetname = modulename + '-doc'
- command = os.path.normpath(os.path.join(os.path.split(__file__)[0], "../gtkdochelper.py"))
- if hasattr(src_dir, 'held_object'):
- src_dir= src_dir.held_object
- if not isinstance(src_dir, build.IncludeDirs):
- raise MesonException('Invalidt keyword argument for src_dir.')
- incdirs = src_dir.get_incdirs()
- if len(incdirs) != 1:
- raise MesonException('Argument src_dir has more than one directory specified.')
- header_dir = os.path.join(state.environment.get_source_dir(), src_dir.get_curdir(), incdirs[0])
- else:
- header_dir = os.path.normpath(os.path.join(state.subdir, src_dir))
- args = ['--sourcedir=' + state.environment.get_source_dir(),
- '--builddir=' + state.environment.get_build_dir(),
- '--subdir=' + state.subdir,
- '--headerdir=' + header_dir,
- '--mainfile=' + main_file,
- '--modulename=' + modulename]
- args += self.unpack_args('--htmlargs=', 'html_args', kwargs)
- args += self.unpack_args('--scanargs=', 'scan_args', kwargs)
- res = [build.RunTarget(targetname, command, args, state.subdir)]
- if kwargs.get('install', True):
- res.append(build.InstallScript([command] + args))
- return res
-
- def unpack_args(self, arg, kwarg_name, kwargs):
- try:
- new_args = kwargs[kwarg_name]
- if not isinstance(new_args, list):
- new_args = [new_args]
- for i in new_args:
- if not isinstance(i, str):
- raise MesonException('html_args values must be strings.')
- except KeyError:
- return[]
- if len(new_args) > 0:
- return [arg + '@@'.join(new_args)]
- return []
-
- 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]
- cmd = ['gdbus-codegen']
- if 'interface_prefix' in kwargs:
- cmd += ['--interface-prefix', kwargs.pop('interface_prefix')]
- if 'namespace' in kwargs:
- cmd += ['--c-namespace', kwargs.pop('namespace')]
- cmd += ['--generate-c-code', '@OUTDIR@/' + namebase, '@INPUT@']
- outputs = [namebase + '.c', namebase + '.h']
- custom_kwargs = {'input' : xml_file,
- 'output' : outputs,
- 'command' : cmd
- }
- return build.CustomTarget(namebase + '-gdbus', state.subdir, custom_kwargs)
-
-def initialize():
- mlog.log('Warning, glib compiled dependencies will not work until this upstream issue is fixed:',
- mlog.bold('https://bugzilla.gnome.org/show_bug.cgi?id=745754'))
- return GnomeModule()
-
-class GirTarget(build.CustomTarget):
- def __init__(self, name, subdir, kwargs):
- super().__init__(name, subdir, kwargs)
-
-class TypelibTarget(build.CustomTarget):
- def __init__(self, name, subdir, kwargs):
- super().__init__(name, subdir, kwargs)
diff --git a/meson/modules/pkgconfig.py b/meson/modules/pkgconfig.py
deleted file mode 100644
index f18decf..0000000
--- a/meson/modules/pkgconfig.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# 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 coredata, build
-from .. import mesonlib
-import os
-
-class PkgConfigModule:
-
- def print_hello(self, state, args, kwargs):
- print('Hello from a Meson module')
-
- def generate_pkgconfig_file(self, state, libraries, subdirs, name, description, version, filebase):
- outdir = state.environment.scratch_dir
- fname = os.path.join(outdir, filebase + '.pc')
- ofile = open(fname, 'w')
- coredata = state.environment.get_coredata()
- ofile.write('prefix=%s\n' % coredata.get_builtin_option('prefix'))
- ofile.write('libdir=${prefix}/%s\n' % coredata.get_builtin_option('libdir'))
- ofile.write('includedir=${prefix}/%s\n\n' % coredata.get_builtin_option('includedir'))
- ofile.write('Name: %s\n' % name)
- if len(description) > 0:
- ofile.write('Description: %s\n' % description)
- if len(version) > 0:
- ofile.write('Version: %s\n' % version)
- ofile.write('Libs: -L${libdir} ')
- for l in libraries:
- ofile.write('-l%s ' % l.name)
- ofile.write('\n')
- ofile.write('CFlags: ')
- for h in subdirs:
- if h == '.':
- h = ''
- ofile.write(os.path.join('-I${includedir}', h))
- ofile.write(' ')
- ofile.write('\n')
-
- def generate(self, state, args, kwargs):
- if len(args) > 0:
- raise coredata.MesonException('Pkgconfig_gen takes no positional arguments.')
- libs = kwargs.get('libraries', [])
- if not isinstance(libs, list):
- libs = [libs]
- processed_libs = []
- for l in libs:
- if hasattr(l, 'held_object'):
- l = l.held_object
- if not (isinstance(l, build.SharedLibrary) or isinstance(l, build.StaticLibrary)):
- raise coredata.MesonException('Library argument not a library object.')
- processed_libs.append(l)
- libs = processed_libs
- subdirs = mesonlib.stringlistify(kwargs.get('subdirs', ['.']))
- version = kwargs.get('version', '')
- if not isinstance(version, str):
- raise coredata.MesonException('Version must be a string.')
- name = kwargs.get('name', None)
- if not isinstance(name, str):
- raise coredata.MesonException('Name not specified.')
- filebase = kwargs.get('filebase', name)
- if not isinstance(filebase, str):
- raise coredata.MesonException('Filebase must be a string.')
- description = kwargs.get('description', None)
- if not isinstance(description, str):
- raise coredata.MesonException('Description is not a string.')
- pcfile = filebase + '.pc'
- pkgroot = os.path.join(state.environment.coredata.get_builtin_option('libdir'), 'pkgconfig')
- self.generate_pkgconfig_file(state, libs, subdirs, name, description, version, filebase)
- return build.Data(False, state.environment.get_scratch_dir(), [pcfile], pkgroot)
-
-def initialize():
- return PkgConfigModule()
diff --git a/meson/modules/qt4.py b/meson/modules/qt4.py
deleted file mode 100644
index 162b553..0000000
--- a/meson/modules/qt4.py
+++ /dev/null
@@ -1,155 +0,0 @@
-# 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 dependencies, mlog
-import os, subprocess
-from .. import build
-from ..coredata import MesonException
-import xml.etree.ElementTree as ET
-
-class Qt4Module():
- def __init__(self):
- mlog.log('Detecting Qt tools.')
- # The binaries have different names on different
- # distros. Joy.
- self.moc = dependencies.ExternalProgram('moc-qt4', silent=True)
- if not self.moc.found():
- self.moc = dependencies.ExternalProgram('moc', silent=True)
- self.uic = dependencies.ExternalProgram('uic-qt4', silent=True)
- if not self.uic.found():
- self.uic = dependencies.ExternalProgram('uic', silent=True)
- self.rcc = dependencies.ExternalProgram('rcc-qt4', silent=True)
- if not self.rcc.found():
- self.rcc = dependencies.ExternalProgram('rcc', silent=True)
- # 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?
- if self.moc.found():
- mp = subprocess.Popen(self.moc.get_command() + ['-v'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdout, stderr) = mp.communicate()
- stdout = stdout.decode().strip()
- stderr = stderr.decode().strip()
- if 'Qt Meta' in stderr:
- moc_ver = stderr
- else:
- raise MesonException('Moc preprocessor is not for Qt 4. Output:\n%s\n%s' %
- (stdout, stderr))
- mlog.log(' moc:', mlog.green('YES'), '(%s, %s)' % \
- (' '.join(self.moc.fullpath), moc_ver.split()[-1]))
- else:
- mlog.log(' moc:', mlog.red('NO'))
- if self.uic.found():
- up = subprocess.Popen(self.uic.get_command() + ['-v'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdout, stderr) = up.communicate()
- stdout = stdout.decode().strip()
- stderr = stderr.decode().strip()
- if 'version 4.' in stderr:
- uic_ver = stderr
- else:
- raise MesonException('Uic compiler is not for Qt4. Output:\n%s\n%s' %
- (stdout, stderr))
- mlog.log(' uic:', mlog.green('YES'), '(%s, %s)' % \
- (' '.join(self.uic.fullpath), uic_ver.split()[-1]))
- else:
- mlog.log(' uic:', mlog.red('NO'))
- if self.rcc.found():
- rp = subprocess.Popen(self.rcc.get_command() + ['-v'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdout, stderr) = rp.communicate()
- stdout = stdout.decode().strip()
- stderr = stderr.decode().strip()
- if 'version 4.' in stderr:
- rcc_ver = stderr
- else:
- raise MesonException('Rcc compiler is not for Qt 4. Output:\n%s\n%s' %
- (stdout, stderr))
- mlog.log(' rcc:', mlog.green('YES'), '(%s, %s)'\
- % (' '.join(self.rcc.fullpath), rcc_ver.split()[-1]))
- else:
- mlog.log(' rcc:', mlog.red('NO'))
-
- def parse_qrc(self, state, fname):
- abspath = os.path.join(state.environment.source_dir, state.subdir, fname)
- relative_part = os.path.split(fname)[0]
- try:
- tree = ET.parse(abspath)
- root = tree.getroot()
- result = []
- for child in root[0]:
- if child.tag != 'file':
- mlog.log("Warning, malformed rcc file: ", os.path.join(state.subdir, fname))
- break
- else:
- result.append(os.path.join(state.subdir, relative_part, child.text))
- return result
- except Exception:
- return []
-
- def preprocess(self, state, args, kwargs):
- rcc_files = kwargs.pop('qresources', [])
- if not isinstance(rcc_files, list):
- rcc_files = [rcc_files]
- ui_files = kwargs.pop('ui_files', [])
- if not isinstance(ui_files, list):
- ui_files = [ui_files]
- moc_headers = kwargs.pop('moc_headers', [])
- if not isinstance(moc_headers, list):
- moc_headers = [moc_headers]
- moc_sources = kwargs.pop('moc_sources', [])
- if not isinstance(moc_sources, list):
- moc_sources = [moc_sources]
- srctmp = kwargs.pop('sources', [])
- if not isinstance(srctmp, list):
- srctmp = [srctmp]
- sources = args[1:] + srctmp
- if len(rcc_files) > 0:
- rcc_kwargs = {'output' : '@BASENAME@.cpp',
- 'arguments' : ['@INPUT@', '-o', '@OUTPUT@']}
- rcc_gen = build.Generator([self.rcc], rcc_kwargs)
- rcc_output = build.GeneratedList(rcc_gen)
- qrc_deps = []
- for i in rcc_files:
- qrc_deps += self.parse_qrc(state, i)
- rcc_output.extra_depends = qrc_deps
- [rcc_output.add_file(os.path.join(state.subdir, a)) for a in rcc_files]
- sources.append(rcc_output)
- if len(ui_files) > 0:
- ui_kwargs = {'output' : 'ui_@BASENAME@.h',
- 'arguments' : ['-o', '@OUTPUT@', '@INPUT@']}
- ui_gen = build.Generator([self.uic], ui_kwargs)
- ui_output = build.GeneratedList(ui_gen)
- [ui_output.add_file(os.path.join(state.subdir, a)) for a in ui_files]
- sources.append(ui_output)
- if len(moc_headers) > 0:
- moc_kwargs = {'output' : 'moc_@BASENAME@.cpp',
- 'arguments' : ['@INPUT@', '-o', '@OUTPUT@']}
- moc_gen = build.Generator([self.moc], moc_kwargs)
- moc_output = build.GeneratedList(moc_gen)
- [moc_output.add_file(os.path.join(state.subdir, a)) for a in moc_headers]
- sources.append(moc_output)
- if len(moc_sources) > 0:
- moc_kwargs = {'output' : '@BASENAME@.moc',
- 'arguments' : ['@INPUT@', '-o', '@OUTPUT@']}
- moc_gen = build.Generator([self.moc], moc_kwargs)
- moc_output = build.GeneratedList(moc_gen)
- [moc_output.add_file(os.path.join(state.subdir, a)) for a in moc_sources]
- sources.append(moc_output)
- return sources
-
-def initialize():
- mlog.log('Warning, rcc dependencies will not work properly until this upstream issue is fixed:',
- mlog.bold('https://bugreports.qt.io/browse/QTBUG-45460'))
- return Qt4Module()
diff --git a/meson/modules/qt5.py b/meson/modules/qt5.py
deleted file mode 100644
index 81edc76..0000000
--- a/meson/modules/qt5.py
+++ /dev/null
@@ -1,162 +0,0 @@
-# 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 dependencies, mlog
-import os, subprocess
-from .. import build
-from ..coredata import MesonException
-import xml.etree.ElementTree as ET
-
-class Qt5Module():
-
- def __init__(self):
- mlog.log('Detecting Qt tools.')
- # The binaries have different names on different
- # distros. Joy.
- self.moc = dependencies.ExternalProgram('moc-qt5', silent=True)
- if not self.moc.found():
- self.moc = dependencies.ExternalProgram('moc', silent=True)
- self.uic = dependencies.ExternalProgram('uic-qt5', silent=True)
- if not self.uic.found():
- self.uic = dependencies.ExternalProgram('uic', silent=True)
- self.rcc = dependencies.ExternalProgram('rcc-qt5', silent=True)
- if not self.rcc.found():
- self.rcc = dependencies.ExternalProgram('rcc', silent=True)
- # 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?
- if self.moc.found():
- mp = subprocess.Popen(self.moc.get_command() + ['-v'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdout, stderr) = mp.communicate()
- stdout = stdout.decode().strip()
- stderr = stderr.decode().strip()
- if 'Qt 5' in stderr:
- moc_ver = stderr
- elif '5.' in stdout:
- moc_ver = stdout
- else:
- raise MesonException('Moc preprocessor is not for Qt 5. Output:\n%s\n%s' %
- (stdout, stderr))
- mlog.log(' moc:', mlog.green('YES'), '(%s, %s)' % \
- (' '.join(self.moc.fullpath), moc_ver.split()[-1]))
- else:
- mlog.log(' moc:', mlog.red('NO'))
- if self.uic.found():
- up = subprocess.Popen(self.uic.get_command() + ['-v'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdout, stderr) = up.communicate()
- stdout = stdout.decode().strip()
- stderr = stderr.decode().strip()
- if 'version 5.' in stderr:
- uic_ver = stderr
- elif '5.' in stdout:
- uic_ver = stdout
- else:
- raise MesonException('Uic compiler is not for Qt 5. Output:\n%s\n%s' %
- (stdout, stderr))
- mlog.log(' uic:', mlog.green('YES'), '(%s, %s)' % \
- (' '.join(self.uic.fullpath), uic_ver.split()[-1]))
- else:
- mlog.log(' uic:', mlog.red('NO'))
- if self.rcc.found():
- rp = subprocess.Popen(self.rcc.get_command() + ['-v'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdout, stderr) = rp.communicate()
- stdout = stdout.decode().strip()
- stderr = stderr.decode().strip()
- if 'version 5.' in stderr:
- rcc_ver = stderr
- elif '5.' in stdout:
- rcc_ver = stdout
- else:
- raise MesonException('Rcc compiler is not for Qt 5. Output:\n%s\n%s' %
- (stdout, stderr))
- mlog.log(' rcc:', mlog.green('YES'), '(%s, %s)'\
- % (' '.join(self.rcc.fullpath), rcc_ver.split()[-1]))
- else:
- mlog.log(' rcc:', mlog.red('NO'))
-
- def parse_qrc(self, state, fname):
- abspath = os.path.join(state.environment.source_dir, state.subdir, fname)
- relative_part = os.path.split(fname)[0]
- try:
- tree = ET.parse(abspath)
- root = tree.getroot()
- result = []
- for child in root[0]:
- if child.tag != 'file':
- mlog.log("Warning, malformed rcc file: ", os.path.join(state.subdir, fname))
- break
- else:
- result.append(os.path.join(state.subdir, relative_part, child.text))
- return result
- except Exception:
- return []
-
- def preprocess(self, state, args, kwargs):
- rcc_files = kwargs.pop('qresources', [])
- if not isinstance(rcc_files, list):
- rcc_files = [rcc_files]
- ui_files = kwargs.pop('ui_files', [])
- if not isinstance(ui_files, list):
- ui_files = [ui_files]
- moc_headers = kwargs.pop('moc_headers', [])
- if not isinstance(moc_headers, list):
- moc_headers = [moc_headers]
- moc_sources = kwargs.pop('moc_sources', [])
- if not isinstance(moc_sources, list):
- moc_sources = [moc_sources]
- srctmp = kwargs.pop('sources', [])
- if not isinstance(srctmp, list):
- srctmp = [srctmp]
- sources = args[1:] + srctmp
- if len(rcc_files) > 0:
- rcc_kwargs = {'output' : '@BASENAME@.cpp',
- 'arguments' : ['@INPUT@', '-o', '@OUTPUT@']}
- rcc_gen = build.Generator([self.rcc], rcc_kwargs)
- rcc_output = build.GeneratedList(rcc_gen)
- qrc_deps = []
- for i in rcc_files:
- qrc_deps += self.parse_qrc(state, i)
- rcc_output.extra_depends = qrc_deps
- [rcc_output.add_file(os.path.join(state.subdir, a)) for a in rcc_files]
- sources.append(rcc_output)
- if len(ui_files) > 0:
- ui_kwargs = {'output' : 'ui_@BASENAME@.h',
- 'arguments' : ['-o', '@OUTPUT@', '@INPUT@']}
- ui_gen = build.Generator([self.uic], ui_kwargs)
- ui_output = build.GeneratedList(ui_gen)
- [ui_output.add_file(os.path.join(state.subdir, a)) for a in ui_files]
- sources.append(ui_output)
- if len(moc_headers) > 0:
- moc_kwargs = {'output' : 'moc_@BASENAME@.cpp',
- 'arguments' : ['@INPUT@', '-o', '@OUTPUT@']}
- moc_gen = build.Generator([self.moc], moc_kwargs)
- moc_output = build.GeneratedList(moc_gen)
- [moc_output.add_file(os.path.join(state.subdir, a)) for a in moc_headers]
- sources.append(moc_output)
- if len(moc_sources) > 0:
- moc_kwargs = {'output' : '@BASENAME@.moc',
- 'arguments' : ['@INPUT@', '-o', '@OUTPUT@']}
- moc_gen = build.Generator([self.moc], moc_kwargs)
- moc_output = build.GeneratedList(moc_gen)
- [moc_output.add_file(os.path.join(state.subdir, a)) for a in moc_sources]
- sources.append(moc_output)
- return sources
-
-def initialize():
- mlog.log('Warning, rcc dependencies will not work properly until this upstream issue is fixed:',
- mlog.bold('https://bugreports.qt.io/browse/QTBUG-45460'))
- return Qt5Module()
diff --git a/meson/modules/rpm.py b/meson/modules/rpm.py
deleted file mode 100644
index a2c0502..0000000
--- a/meson/modules/rpm.py
+++ /dev/null
@@ -1,163 +0,0 @@
-# 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
-from .. import datetime
-from .. import mlog
-from .. import modules.gnome
-import os
-
-class RPMModule:
-
- def generate_spec_template(self, state, args, kwargs):
- compiler_deps = set()
- for compiler in state.compilers:
- 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_aliaslist():
- 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.log('Warning, removing', mlog.bold(target.get_filename()),
- 'from package because packaging static libs not recommended')
- elif isinstance(target, modules.gnome.GirTarget) and target.should_install():
- files_devel.add('%%{_datadir}/gir-1.0/%s' % target.get_filename()[0])
- elif isinstance(target, modules.gnome.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))
- for pkgconfig in state.pkgconfig_gens:
- files_devel.add('%%{_libdir}/pkgconfig/%s.pc' % pkgconfig.filebase)
- if len(files_devel) > 0:
- devel_subpkg = True
- fn = open('%s.spec' % os.path.join(state.environment.get_build_dir(), proj), 'w+')
- 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)
- for lib in state.environment.coredata.ext_libs.values():
- fn.write('BuildRequires: %s # FIXME\n' % lib.fullpath)
- mlog.log('Warning, replace', mlog.bold(lib.fullpath), 'with real package.',
- 'You can use following command to find package which contains this lib:',
- mlog.bold('dnf provides %s' % lib.fullpath))
- for prog in state.environment.coredata.ext_progs.values():
- if not prog.found():
- fn.write('BuildRequires: /usr/bin/%s # FIXME\n' % prog.get_name())
- else:
- fn.write('BuildRequires: %s\n' % ' '.join(prog.fullpath))
- 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} = %{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('rm -rf rpmbuilddir && mkdir rpmbuilddir\n')
- fn.write('\n')
- fn.write('%build\n')
- fn.write('pushd rpmbuilddir\n')
- fn.write(' %meson ..\n')
- fn.write(' ninja-build -v\n')
- fn.write('popd\n')
- fn.write('\n')
- fn.write('%install\n')
- fn.write('pushd rpmbuilddir\n')
- fn.write(' DESTDIR=%{buildroot} ninja-build -v install\n')
- fn.write('popd\n')
- if len(to_delete) > 0:
- fn.write('rm -rf %s\n' % ' '.join(to_delete))
- fn.write('\n')
- fn.write('%check\n')
- fn.write('pushd rpmbuilddir\n')
- fn.write(' ninja-build -v test\n')
- fn.write('popd\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('\n')
- fn.write('%postun -p /sbin/ldconfig\n')
- fn.write('\n')
- fn.write('%changelog\n')
- fn.write('* %s meson <meson@example.com> - \n' % datetime.date.today().strftime('%a %b %d %Y'))
- fn.write('- \n')
- fn.write('\n')
- fn.close()
- mlog.log('RPM spec template written to %s.spec.\n' % proj)
-
-def initialize():
- return RPMModule()
diff --git a/meson/modules/windows.py b/meson/modules/windows.py
deleted file mode 100644
index a785250..0000000
--- a/meson/modules/windows.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# 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 mesonlib, dependencies, build
-from ..coredata import MesonException
-import os
-
-class WindowsModule:
-
- def detect_compiler(self, compilers):
- for c in compilers:
- if c.language == 'c' or c.language == 'cpp':
- return c
- raise MesonException('Resource compilation requires a C or C++ compiler.')
-
- def compile_resources(self, state, args, kwargs):
- comp = self.detect_compiler(state.compilers)
- extra_args = mesonlib.stringlistify(kwargs.get('args', []))
- if comp.id == 'msvc':
- rescomp = dependencies.ExternalProgram('rc', silent=True)
- res_args = extra_args + ['/nologo', '/fo@OUTPUT@', '@INPUT@']
- suffix = 'res'
- else:
- rescomp = dependencies.ExternalProgram('windres', silent=True)
- res_args = extra_args + ['@INPUT@', '@OUTPUT@']
- suffix = 'o'
- res_files = mesonlib.stringlistify(args)
- res_kwargs = {'output' : '@BASENAME@.' + suffix,
- 'arguments': res_args}
- res_gen = build.Generator([rescomp], res_kwargs)
- res_output = build.GeneratedList(res_gen)
- [res_output.add_file(os.path.join(state.subdir, a)) for a in res_files]
- return res_output
-
-def initialize():
- return WindowsModule()
diff --git a/meson/mparser.py b/meson/mparser.py
deleted file mode 100644
index 1d569d5..0000000
--- a/meson/mparser.py
+++ /dev/null
@@ -1,565 +0,0 @@
-# Copyright 2014-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 re
-from .coredata import MesonException
-
-class ParseException(MesonException):
- def __init__(self, text, lineno, colno):
- super().__init__(text)
- self.lineno = lineno
- self.colno = colno
-
-class Token:
- def __init__(self, tid, lineno, colno, value):
- self.tid = tid
- self.lineno = lineno
- self.colno = colno
- 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):
- 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]*')),
- ('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'\*')),
- ('fslash', re.compile(r'/')),
- ('colon', re.compile(r':')),
- ('equal', re.compile(r'==')),
- ('nequal', re.compile(r'\!=')),
- ('assign', re.compile(r'=')),
- ]
-
- def lex(self, code):
- lineno = 1
- line_start = 0
- loc = 0;
- par_count = 0
- bracket_count = 0
- col = 0
- while(loc < len(code)):
- matched = False
- value = None
- for (tid, reg) in self.token_specification:
- mo = reg.match(code, loc)
- if mo:
- curline = lineno
- col = mo.start()-line_start
- matched = True
- loc = mo.end()
- match_text = mo.group()
- if tid == 'ignore' or tid == 'comment':
- break
- elif tid == 'lparen':
- par_count += 1
- elif tid == 'rparen':
- par_count -= 1
- elif tid == 'lbracket':
- bracket_count += 1
- elif tid == 'rbracket':
- bracket_count -= 1
- elif tid == 'dblquote':
- raise ParseException('Double quotes are not supported. Use single quotes.', lineno, col)
- elif tid == 'string':
- value = match_text[1:-1].replace(r"\'", "'").replace(r" \\ ".strip(), r" \ ".strip())\
- .replace("\\n", "\n")
- elif tid == 'multiline_string':
- tid = 'string'
- value = match_text[3:-3]
- lines = match_text.split('\n')
- if len(lines) > 1:
- lineno += len(lines) - 1
- line_start = mo.end() - len(lines[-1])
- elif tid == 'number':
- value = int(match_text)
- 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, curline, col, value)
- break
- if not matched:
- raise ParseException('lexer', lineno, col)
-
-class BooleanNode:
- def __init__(self, token, value):
- self.lineno = token.lineno
- self.colno = token.colno
- self.value = value
- assert(isinstance(self.value, bool))
-
-class IdNode:
- def __init__(self, token):
- self.lineno = token.lineno
- self.colno = token.colno
- self.value = token.value
- assert(isinstance(self.value, str))
-
- def __str__(self):
- return "Id node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno)
-
-class NumberNode:
- def __init__(self, token):
- self.lineno = token.lineno
- self.colno = token.colno
- self.value = token.value
- assert(isinstance(self.value, int))
-
-class StringNode:
- def __init__(self, token):
- self.lineno = token.lineno
- self.colno = token.colno
- self.value = token.value
- 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.lineno = args.lineno
- self.colno = args.colno
- self.args = args
-
-class EmptyNode:
- def __init__(self):
- self.lineno = 0
- self.colno = 0
- self.value = None
-
-class OrNode:
- def __init__(self, lineno, colno, left, right):
- self.lineno = lineno
- self.colno = colno
- self.left = left
- self.right = right
-
-class AndNode:
- def __init__(self, lineno, colno, left, right):
- self.lineno = lineno
- self.colno = colno
- self.left = left
- self.right = right
-
-class ComparisonNode:
- def __init__(self, lineno, colno, ctype, left, right):
- self.lineno = lineno
- self.colno = colno
- self.left = left
- self.right = right
- self.ctype = ctype
-
-class ArithmeticNode:
- def __init__(self, lineno, colno, operation, left, right):
- self.lineno = lineno
- self.colno = colno
- self.left = left
- self.right = right
- self.operation = operation
-
-class NotNode:
- def __init__(self, lineno, colno, value):
- self.lineno = lineno
- self.colno = colno
- self.value = value
-
-class CodeBlockNode:
- def __init__(self, lineno, colno):
- self.lineno = lineno
- self.colno = colno
- self.lines = []
-
-class IndexNode:
- def __init__(self, iobject, index):
- self.iobject = iobject
- self.index = index
- self.lineno = iobject.lineno
- self.colno = iobject.colno
-
-class MethodNode:
- def __init__(self, lineno, colno, source_object, name, args):
- 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, lineno, colno, func_name, args):
- 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()
-
-class UMinusNode():
- def __init__(self, lineno, colno, value):
- self.lineno = lineno
- self.colno = 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 ArgumentNode():
- def __init__(self, token):
- self.lineno = token.lineno
- self.colno = token.colno
- self.arguments = []
- 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 = self.arguments + [statement]
-
- def set_kwarg(self, name, value):
- 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
-
-# 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):
- self.stream = Lexer().lex(code)
- self.getsym()
-
- def getsym(self):
- try:
- self.current = next(self.stream)
- except StopIteration:
- self.current = Token('eof', 0, 0, None)
-
- 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.current.lineno, self.current.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.', 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.',
- left.lineno, left.colno)
- return AssignmentNode(left.lineno, left.colno, left.value, value)
- return left
-
- def e2(self):
- left = self.e3()
- while self.accept('or'):
- left = OrNode(left.lineno, left.colno, left, self.e3())
- return left
-
- def e3(self):
- left = self.e4()
- while self.accept('and'):
- left = AndNode(left.lineno, left.colno, left, self.e4())
- return left
-
- def e4(self):
- left = self.e5()
- if self.accept('equal'):
- return ComparisonNode(left.lineno, left.colno, '==', left, self.e5())
- if self.accept('nequal'):
- return ComparisonNode(left.lineno, left.colno, '!=', left, self.e5())
- return left
-
- def e5(self):
- return self.e5add()
-
- def e5add(self):
- left = self.e5sub()
- if self.accept('plus'):
- return ArithmeticNode(left.lineno, left.colno, 'add', left, self.e5add())
- return left
-
- def e5sub(self):
- left = self.e5mul()
- if self.accept('dash'):
- return ArithmeticNode(left.lineno, left.colno, 'sub', left, self.e5sub())
- return left
-
- def e5mul(self):
- left = self.e5div()
- if self.accept('star'):
- return ArithmeticNode(left.lineno, left.colno, 'mul', left, self.e5mul())
- return left
-
- def e5div(self):
- left = self.e6()
- if self.accept('fslash'):
- return ArithmeticNode(left.lineno, left.colno, 'div', left, self.e5div())
- return left
-
- def e6(self):
- if self.accept('not'):
- return NotNode(self.current.lineno, self.current.colno, self.e7())
- if self.accept('dash'):
- return UMinusNode(self.current.lineno, self.current.colno, self.e7())
- return self.e7()
-
- def e7(self):
- left = self.e8()
- if self.accept('lparen'):
- args = self.args()
- self.expect('rparen')
- if not isinstance(left, IdNode):
- raise ParseException('Function call must be applied to plain id',
- left.lineno, left.colno)
- left = FunctionNode(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):
- if self.accept('lparen'):
- e = self.statement()
- self.expect('rparen')
- return e
- elif self.accept('lbracket'):
- args = self.args()
- self.expect('rbracket')
- 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()
-
- def args(self):
- s = self.statement()
- a = ArgumentNode(s)
-
- while not isinstance(s, EmptyNode):
- if self.accept('comma'):
- a.append(s)
- elif self.accept('colon'):
- if not isinstance(s, IdNode):
- raise ParseException('Keyword argument must be a plain identifier.',
- s.lineno, s.colno)
- a.set_kwarg(s.value, self.statement())
- if not self.accept('comma'):
- return a
- 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.current.lineno, self.current.colno)
- self.expect('lparen')
- args = self.args()
- self.expect('rparen')
- method = MethodNode(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)
- 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):
- if self.current == 'eol':
- return EmptyNode()
- if self.accept('if'):
- block = self.ifblock()
- self.expect('endif')
- return block
- if self.accept('foreach'):
- block = self.foreachblock()
- self.expect('endforeach')
- return block
- return self.statement()
-
- def codeblock(self):
- block = CodeBlockNode(self.current.lineno, self.current.colno)
- cond = True
- while cond:
- curline = self.line()
- if not isinstance(curline, EmptyNode):
- block.lines.append(curline)
- cond = self.accept('eol')
- return block
diff --git a/meson/ninjabackend.py b/meson/ninjabackend.py
deleted file mode 100644
index 36c5ce9..0000000
--- a/meson/ninjabackend.py
+++ /dev/null
@@ -1,1819 +0,0 @@
-# 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 . import backends
-from . import environment, mesonlib
-from . import build
-from . import mlog
-from . import dependencies
-from .mesonlib import File
-from .backends import InstallData
-from .build import InvalidArguments
-from .coredata import MesonException
-import os, sys, pickle, re
-import subprocess, shutil
-
-if mesonlib.is_windows():
- quote_char = '"'
- execute_wrapper = 'cmd /c'
-else:
- quote_char = "'"
- execute_wrapper = ''
-
-def ninja_quote(text):
- return text.replace(' ', '$ ').replace(':', '$:')
-
-class RawFilename():
- def __init__(self, fname):
- self.fname = fname
-
- def split(self, c):
- return self.fname.split(c)
-
- def startswith(self, s):
- return self.fname.startswith(s)
-
-class NinjaBuildElement():
- def __init__(self, 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 = []
- self.orderdeps = []
- self.elems = []
-
- def add_dep(self, dep):
- if isinstance(dep, list):
- self.deps += dep
- else:
- self.deps.append(dep)
-
- def add_orderdep(self, dep):
- if isinstance(dep, list):
- self.orderdeps += dep
- else:
- self.orderdeps.append(dep)
-
- def add_item(self, name, elems):
- if isinstance(elems, str):
- elems = [elems]
- self.elems.append((name, elems))
-
- def write(self, outfile):
- line = 'build %s: %s %s' % (' '.join([ninja_quote(i) for i in self.outfilenames]),\
- self.rule,
- ' '.join([ninja_quote(i) for i in self.infilenames]))
- if len(self.deps) > 0:
- line += ' | ' + ' '.join([ninja_quote(x) for x in self.deps])
- if len(self.orderdeps) > 0:
- line += ' || ' + ' '.join([ninja_quote(x) 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.
- line = line.replace('\\', '/')
- outfile.write(line)
-
- for e in self.elems:
- (name, elems) = e
- should_quote = True
- if name == 'DEPFILE' or name == 'DESC' or name == 'pool':
- should_quote = False
- line = ' %s = ' % name
- q_templ = quote_char + "%s" + quote_char
- noq_templ = "%s"
- newelems = []
- for i in elems:
- if not should_quote or i == '&&': # Hackety hack hack
- templ = noq_templ
- else:
- templ = q_templ
- i = i.replace('\\', '\\\\')
- if quote_char == '"':
- i = i.replace('"', '\\"')
- newelems.append(templ % ninja_quote(i))
- line += ' '.join(newelems)
- line += '\n'
- outfile.write(line)
- outfile.write('\n')
-
-class NinjaBackend(backends.Backend):
-
- def __init__(self, build):
- super().__init__(build)
- self.source_suffix_in_objs = True
- self.ninja_filename = 'build.ninja'
- self.fortran_deps = {}
- self.all_outputs = {}
-
- def check_outputs(self, elem):
- for n in elem.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
-
- def detect_vs_dep_prefix(self, outfile, tempfilename):
- '''VS writes its dependency in a locale dependent format.
- Detect the search prefix to use.'''
- if shutil.which('cl') is None:
- return outfile
- outfile.close()
- open(os.path.join(self.environment.get_scratch_dir(), 'incdetect.c'),
- 'w').write('''#include<stdio.h>
-int dummy;
-''')
-
- pc = subprocess.Popen(['cl', '/showIncludes', '/c', 'incdetect.c'],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- cwd=self.environment.get_scratch_dir())
-
- (stdo, _) = pc.communicate()
-
- for line in stdo.split(b'\r\n'):
- if line.endswith(b'stdio.h'):
- matchstr = b':'.join(line.split(b':')[0:2]) + b':'
- binfile = open(tempfilename, 'ab')
- binfile.write(b'msvc_deps_prefix = ' + matchstr + b'\r\n')
- binfile.close()
- return open(tempfilename, 'a')
- raise MesonException('Could not determine vs dep dependency prefix string.')
-
- def generate(self, interp):
- self.interpreter = interp
- outfilename = os.path.join(self.environment.get_build_dir(), self.ninja_filename)
- tempfilename = outfilename + '~'
- outfile = open(tempfilename, 'w')
- 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')
- outfile = self.detect_vs_dep_prefix(outfile, tempfilename)
- self.generate_rules(outfile)
- self.generate_phony(outfile)
- outfile.write('# Build rules for targets\n\n')
- [self.generate_target(t, outfile) for t in self.build.get_targets().values()]
- if len(self.build.pot) > 0:
- outfile.write('# Build rules for localisation.\n\n')
- self.generate_po(outfile)
- outfile.write('# Test rules\n\n')
- self.generate_tests(outfile)
- outfile.write('# Install rules\n\n')
- self.generate_install(outfile)
- if self.environment.coredata.get_builtin_option('coverage'):
- outfile.write('# Coverage rules\n\n')
- self.generate_coverage_rules(outfile)
- outfile.write('# Suffix\n\n')
- self.generate_ending(outfile)
- # Only ovewrite the old build file after the new one has been
- # fully created.
- outfile.close()
- os.replace(tempfilename, outfilename)
- self.generate_compdb()
-
- # http://clang.llvm.org/docs/JSONCompilationDatabase.html
- def generate_compdb(self):
- ninja_exe = environment.detect_ninja()
- builddir = self.environment.get_build_dir()
- jsondb = subprocess.check_output([ninja_exe, '-t', 'compdb', 'c_COMPILER', 'cpp_COMPILER'], cwd=builddir)
- open(os.path.join(builddir, 'compile_commands.json'), 'wb').write(jsondb)
-
- # 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 = []
- for gensource in target.get_generated_sources():
- if isinstance(gensource, build.CustomTarget):
- continue
- for src in gensource.get_outfilelist():
- if self.environment.is_header(src):
- header_deps.append(os.path.join(self.get_target_private_dir(target), src))
- for dep in target.link_targets:
- if isinstance(dep, (build.StaticLibrary, build.SharedLibrary)):
- header_deps += self.get_generated_headers(dep)
- return header_deps
-
- 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()
- gen_src_deps = []
- if name in self.processed_targets:
- return
- if isinstance(target, build.Jar):
- self.generate_jar_target(target, outfile)
- return
- if 'rust' in self.environment.coredata.compilers.keys() and self.has_rust(target):
- self.generate_rust_target(target, outfile)
- return
- if 'cs' in self.environment.coredata.compilers.keys() and self.has_cs(target):
- self.generate_cs_target(target, outfile)
- return
- if 'vala' in self.environment.coredata.compilers.keys() and self.has_vala(target):
- gen_src_deps += self.generate_vala_compile(target, outfile)
- if 'swift' in self.environment.coredata.compilers.keys() and self.has_swift(target):
- self.generate_swift_target(target, outfile)
- return
- self.scan_fortran_module_outputs(target)
- # The following deals with C/C++ compilation.
- (gen_src, gen_other_deps) = self.process_dep_gens(outfile, target)
- gen_src_deps += gen_src
- self.process_target_dependencies(target, outfile)
- self.generate_custom_generator_rules(target, outfile)
- outname = self.get_target_filename(target)
- obj_list = []
- use_pch = self.environment.coredata.get_builtin_option('use_pch')
- is_unity = self.environment.coredata.get_builtin_option('unity')
- if use_pch and target.has_pch():
- pch_objects = self.generate_pch(target, outfile)
- else:
- pch_objects = []
- header_deps = gen_other_deps
- unity_src = []
- unity_deps = [] # Generated sources that must be built before compiling a Unity target.
- header_deps += self.get_generated_headers(target)
- for gensource in target.get_generated_sources():
- if isinstance(gensource, build.CustomTarget):
- for src in gensource.output:
- src = os.path.join(self.get_target_dir(gensource), src)
- if self.environment.is_source(src) and not self.environment.is_header(src):
- if is_unity:
- unity_deps.append(os.path.join(self.environment.get_build_dir(), RawFilename(src)))
- else:
- obj_list.append(self.generate_single_compile(target, outfile, RawFilename(src), True,
- header_deps))
- elif self.environment.is_object(src):
- obj_list.append(src)
- elif self.environment.is_library(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(RawFilename(src))
- else:
- for src in gensource.get_outfilelist():
- if self.environment.is_object(src):
- obj_list.append(os.path.join(self.get_target_private_dir(target), src))
- elif not self.environment.is_header(src):
- if is_unity:
- if self.has_dir_part(src):
- rel_src = src
- else:
- rel_src = os.path.join(self.get_target_private_dir(target), src)
- unity_deps.append(rel_src)
- abs_src = os.path.join(self.environment.get_build_dir(), rel_src)
- unity_src.append(abs_src)
- else:
- obj_list.append(self.generate_single_compile(target, outfile, src, True,
- header_deps=header_deps))
- src_list = []
- for src in gen_src_deps:
- src_list.append(src)
- if is_unity:
- unity_src.append(os.path.join(self.environment.get_build_dir(), src))
- header_deps.append(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.
- obj_list.append(self.generate_single_compile(target, outfile, src, True, [], header_deps))
- for src in target.get_sources():
- if src.endswith('.vala'):
- continue
- if not self.environment.is_header(src):
- src_list.append(src)
- if is_unity:
- 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, src_list)
- 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)
- self.processed_targets[name] = True
-
- def process_target_dependencies(self, target, outfile):
- for t in target.get_dependencies():
- tname = t.get_basename() + t.type_suffix()
- if not tname in self.processed_targets:
- self.generate_target(t, outfile)
-
- def generate_custom_target(self, target, outfile):
- (srcs, ofilenames, cmd) = self.eval_custom_target_command(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]
- fname = i.get_filename()
- if isinstance(fname, list):
- fname = fname[0]
- deps.append(os.path.join(self.get_target_dir(i), fname))
- if target.build_always:
- deps.append('PHONY')
- elem = NinjaBuildElement(ofilenames, 'CUSTOM_COMMAND', srcs)
- for i in target.depend_files:
- if isinstance(i, mesonlib.File):
- deps.append(i.rel_to_builddir(self.build_to_src))
- else:
- deps.append(os.path.join(self.build_to_src, i))
- elem.add_dep(deps)
- for d in target.extra_depends:
- tmp = d.get_filename()
- if not isinstance(tmp, list):
- tmp = [tmp]
- for fname in tmp:
- elem.add_dep(os.path.join(self.get_target_dir(d), fname))
-
- elem.add_item('COMMAND', cmd)
- elem.add_item('description', 'Generating %s with a custom command.' % target.name)
- elem.write(outfile)
- self.check_outputs(elem)
- self.processed_targets[target.name + target.type_suffix()] = True
-
- def generate_run_target(self, target, outfile):
- runnerscript = os.path.join(self.environment.get_script_dir(), 'commandrunner.py')
- deps = []
- 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)
- deps.append(relfname)
- arg_strings.append(os.path.join(self.environment.get_build_dir(), relfname))
- else:
- mlog.debug(str(i))
- raise MesonException('Unreachable code in generate_run_target.')
- elem = NinjaBuildElement(target.name, 'CUSTOM_COMMAND', deps)
- cmd = [sys.executable, runnerscript, self.environment.get_source_dir(), self.environment.get_build_dir(), target.subdir]
- 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.config['binaries'].get('exe_wrapper', None) is not None:
- cmd += [self.environment.cross_info.config['binaries']['exe_wrapper']]
- cmd.append(abs_exe)
- else:
- cmd.append(target.command)
- cmd += arg_strings
- elem.add_item('COMMAND', cmd)
- elem.add_item('description', 'Running external command %s.' % target.name)
- elem.add_item('pool', 'console')
- elem.write(outfile)
- self.check_outputs(elem)
- self.processed_targets[target.name + target.type_suffix()] = True
-
- def generate_po(self, outfile):
- for p in self.build.pot:
- (packagename, languages, subdir) = p
- input_file = os.path.join(subdir, 'POTFILES')
- elem = NinjaBuildElement('pot', 'GEN_POT', [])
- elem.add_item('PACKAGENAME', packagename)
- elem.add_item('OUTFILE', packagename + '.pot')
- elem.add_item('FILELIST', os.path.join(self.environment.get_source_dir(), input_file))
- elem.add_item('OUTDIR', os.path.join(self.environment.get_source_dir(), subdir))
- elem.write(outfile)
- self.check_outputs(elem)
- for l in languages:
- infile = os.path.join(self.environment.get_source_dir(), subdir, l + '.po')
- outfilename = os.path.join(subdir, l + '.gmo')
- lelem = NinjaBuildElement(outfilename, 'GEN_GMO', infile)
- lelem.add_item('INFILE', infile)
- lelem.add_item('OUTFILE', outfilename)
- lelem.write(outfile)
- self.check_outputs(lelem)
-
- def generate_coverage_rules(self, outfile):
- (gcovr_exe, lcov_exe, genhtml_exe) = environment.find_coverage_tools()
- added_rule = False
- if gcovr_exe:
- added_rule = True
- elem = NinjaBuildElement('coverage-xml', 'CUSTOM_COMMAND', '')
- elem.add_item('COMMAND', [gcovr_exe, '-x', '-r', self.environment.get_build_dir(),\
- '-o', os.path.join(self.environment.get_log_dir(), 'coverage.xml')])
- elem.add_item('DESC', 'Generating XML coverage report.')
- elem.write(outfile)
- elem = NinjaBuildElement('coverage-text', 'CUSTOM_COMMAND', '')
- elem.add_item('COMMAND', [gcovr_exe, '-r', self.environment.get_build_dir(),\
- '-o', os.path.join(self.environment.get_log_dir(), 'coverage.txt')])
- elem.add_item('DESC', 'Generating text coverage report.')
- elem.write(outfile)
- self.check_outputs(elem)
- if lcov_exe and genhtml_exe:
- added_rule = True
- phony_elem = NinjaBuildElement('coverage-html', 'phony', 'coveragereport/index.html')
- phony_elem.write(outfile)
-
- elem = NinjaBuildElement('coveragereport/index.html', 'CUSTOM_COMMAND', '')
- command = [lcov_exe, '--directory', self.environment.get_build_dir(),\
- '--capture', '--output-file', 'coverage.info', '--no-checksum',\
- '&&', genhtml_exe, '--prefix', self.environment.get_build_dir(),\
- '--output-directory', self.environment.get_log_dir(), '--title', 'Code coverage',\
- '--legend', '--show-details', 'coverage.info']
- elem.add_item('COMMAND', command)
- elem.add_item('DESC', 'Generating HTML coverage report.')
- self.check_outputs(elem)
- elem.write(outfile)
- if not added_rule:
- mlog.log(mlog.red('Warning:'), 'coverage requested but neither gcovr nor lcov/genhtml found.')
-
- def generate_install(self, outfile):
- script_root = self.environment.get_script_dir()
- install_script = os.path.join(script_root, 'meson_install.py')
- install_data_file = os.path.join(self.environment.get_scratch_dir(), 'install.dat')
- depfixer = [sys.executable, self.environment.get_build_command(), '--internal', 'depfixer']
- d = InstallData(self.environment.get_source_dir(),
- self.environment.get_build_dir(),
- self.environment.get_prefix(), depfixer)
- elem = NinjaBuildElement('install', 'CUSTOM_COMMAND', 'PHONY')
- elem.add_dep('all')
- elem.add_item('DESC', 'Installing files.')
- elem.add_item('COMMAND', [sys.executable, 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_po_install(d, elem)
- self.generate_custom_install_script(d)
- self.generate_subdir_install(d)
- elem.write(outfile)
- self.check_outputs(elem)
-
- ofile = open(install_data_file, 'wb')
- pickle.dump(d, ofile)
-
- def generate_po_install(self, d, elem):
- for p in self.build.pot:
- (package_name, languages, subdir) = p
- # FIXME: assumes only one po package per source
- d.po_package_name = package_name
- for lang in languages:
- rel_src = os.path.join(subdir, lang + '.gmo')
- src_file = os.path.join(self.environment.get_build_dir(), rel_src)
- d.po.append((src_file, self.environment.coredata.get_builtin_option('localedir'), lang))
- elem.add_dep(rel_src)
-
- def generate_target_install(self, d):
- libdir = self.environment.get_libdir()
- bindir = self.environment.get_bindir()
-
- should_strip = self.environment.coredata.get_builtin_option('strip')
- for t in self.build.get_targets().values():
- if t.should_install():
- outdir = t.get_custom_install_dir()
- if outdir is None:
- if isinstance(t, build.Executable):
- outdir = bindir
- else:
- outdir = libdir
- i = [self.get_target_filename(t), outdir, t.get_aliaslist(),\
- should_strip, t.install_rpath]
- d.targets.append(i)
-
- def generate_custom_install_script(self, d):
- d.install_scripts = self.build.install_scripts
-
- def generate_header_install(self, d):
- incroot = self.environment.get_includedir()
- headers = self.build.get_headers()
-
- 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():
- abspath = os.path.join(self.environment.get_source_dir(), h.get_source_subdir(), f)
- 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 = os.path.join(self.environment.get_source_dir(), m.get_source_subdir(), f)
- dstabs = os.path.join(subdir, f + '.gz')
- i = [srcabs, dstabs]
- d.man.append(i)
-
- def generate_data_install(self, d):
- data = self.build.get_data()
- for de in data:
- assert(isinstance(de, build.Data))
- subdir = de.install_dir
- for f in de.sources:
- if de.in_sourcetree:
- srcprefix = self.environment.get_source_dir()
- else:
- srcprefix = self.environment.get_build_dir()
- srcabs = os.path.join(srcprefix, de.source_subdir, f)
- dstabs = os.path.join(subdir, f)
- i = [srcabs, dstabs]
- 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)
- dst_dir = os.path.join(self.environment.get_prefix(), sd.install_dir)
- d.install_subdirs.append([src_dir, dst_dir])
-
- def write_test_suite_targets(self, cmd, outfile):
- suites = {}
- for t in self.build.get_tests():
- for s in t.suite:
- suites[s] = True
- suites = list(suites.keys())
- suites.sort()
- for s in suites:
- if s == '':
- visible_name = 'for top level tests'
- else:
- visible_name = s
- elem = NinjaBuildElement('test-' + s, 'CUSTOM_COMMAND', ['all', 'PHONY'])
- elem.add_item('COMMAND', cmd + ['--suite=' + s])
- elem.add_item('DESC', 'Running test suite %s.' % visible_name)
- elem.add_item('pool', 'console')
- elem.write(outfile)
- self.check_outputs(elem)
-
- def generate_tests(self, outfile):
- self.serialise_tests()
- valgrind = environment.find_valgrind()
- script_root = self.environment.get_script_dir()
- test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat')
- cmd = [sys.executable, self.environment.get_build_command(), '--internal', 'test', test_data]
- elem = NinjaBuildElement('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)
- self.check_outputs(elem)
- self.write_test_suite_targets(cmd, outfile)
-
- if valgrind:
- velem = NinjaBuildElement('test-valgrind', 'CUSTOM_COMMAND', ['all', 'PHONY'])
- velem.add_item('COMMAND', cmd + ['--wrapper=' + valgrind])
- velem.add_item('DESC', 'Running test suite under Valgrind.')
- velem.add_item('pool', 'console')
- velem.write(outfile)
- self.check_outputs(velem)
-
- # And then benchmarks.
- benchmark_script = os.path.join(script_root, 'meson_benchmark.py')
- benchmark_data = os.path.join(self.environment.get_scratch_dir(), 'meson_benchmark_setup.dat')
- cmd = [sys.executable, self.environment.get_build_command(), '--internal', 'benchmark', benchmark_data]
- elem = NinjaBuildElement('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)
- self.check_outputs(elem)
-
- def generate_rules(self, outfile):
- outfile.write('# Rules for compiling.\n\n')
- self.generate_compile_rules(outfile)
- outfile.write('# Rules for linking.\n\n')
- 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')
- outfile.write('rule REGENERATE_BUILD\n')
- c = (quote_char + ninja_quote(sys.executable) + quote_char,
- quote_char + ninja_quote(self.environment.get_build_command()) + quote_char,
- '--internal',
- 'regenerate',
- quote_char + ninja_quote(self.environment.get_source_dir()) + quote_char,
- quote_char + ninja_quote(self.environment.get_build_dir()) + quote_char)
- outfile.write(" command = %s %s %s %s %s %s --backend ninja\n" % c)
- outfile.write(' description = Regenerating build files\n')
- outfile.write(' generator = 1\n\n')
- if len(self.build.pot) > 0:
- self.generate_gettext_rules(outfile)
- outfile.write('\n')
-
- def generate_gettext_rules(self, outfile):
- rule = 'rule GEN_POT\n'
- command = " command = xgettext --package-name=$PACKAGENAME -p $OUTDIR -f $FILELIST -D '%s' -k_ -o $OUTFILE\n" % \
- self.environment.get_source_dir()
- desc = " description = Creating pot file for package $PACKAGENAME.\n"
- outfile.write(rule)
- outfile.write(command)
- outfile.write(desc)
- outfile.write('\n')
- rule = 'rule GEN_GMO\n'
- command = ' command = msgfmt $INFILE -o $OUTFILE\n'
- desc = ' description = Generating gmo file $OUTFILE\n'
- outfile.write(rule)
- outfile.write(command)
- outfile.write(desc)
- 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()
- subdir = target.get_subdir()
- outname_rel = os.path.join(self.get_target_dir(target), fname)
- src_list = target.get_sources()
- class_list = []
- compiler = self.get_compiler_for_source(src_list[0])
- assert(compiler.get_language() == '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))
- for cls in class_list:
- commands += ['-C', self.get_target_private_dir(target), cls]
- elem = NinjaBuildElement(outname_rel, jar_rule, [])
- elem.add_dep(class_dep_list)
- elem.add_item('ARGS', commands)
- elem.write(outfile)
- self.check_outputs(elem)
-
- 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(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)
- self.check_outputs(elem)
- 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.environment.coredata.get_builtin_option('buildtype')
- fname = target.get_filename()
- outname_rel = os.path.join(self.get_target_dir(target), fname)
- src_list = target.get_sources()
- compiler = self.get_compiler_for_source(src_list[0])
- assert(compiler.get_language() == 'cs')
- rel_srcs = [s.rel_to_builddir(self.build_to_src) for s in src_list]
- deps = []
- commands = 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]
- elem = NinjaBuildElement(outputs, 'cs_COMPILER', rel_srcs)
- elem.add_dep(deps)
- elem.add_item('ARGS', commands)
- self.check_outputs(elem)
- elem.write(outfile)
-
- def generate_single_java_compile(self, src, target, compiler, outfile):
- args = []
- args += compiler.get_buildtype_args(self.environment.coredata.get_builtin_option('buildtype'))
- 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(rel_obj, compiler.get_language() + '_COMPILER', rel_src)
- element.add_item('ARGS', args)
- element.write(outfile)
- self.check_outputs(element)
- 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 generate_fastvapi_compile(self, target, valac, outfile):
- fastvapis = {}
- for s in target.get_sources():
- if not s.endswith('.vala'):
- continue
- vapibase = os.path.basename(s.fname)[:-4] + 'vapi'
- rel_vapi = os.path.join(self.get_target_private_dir(target), vapibase)
- args = ['--fast-vapi=' + rel_vapi]
- rel_s = s.rel_to_builddir(self.build_to_src)
- element = NinjaBuildElement(rel_vapi, valac.get_language() + '_COMPILER', rel_s)
- element.add_item('ARGS', args)
- element.write(outfile)
- self.check_outputs(element)
- fastvapis[s] = (vapibase, rel_vapi)
- return fastvapis
-
- def split_vala_sources(self, sources):
- src = []
- vapi_src = []
- for s in sources:
- if s.endswith('.vapi'):
- vapi_src.append(s)
- else:
- src.append(s)
- return (src, vapi_src)
-
- def generate_vala_compile(self, target, outfile):
- """Vala is compiled into C. Set up all necessary build steps here."""
- valac = self.environment.coredata.compilers['vala']
- fast_vapis = self.generate_fastvapi_compile(target, valac, outfile)
- generated_c = []
- (src, vapi_src) = self.split_vala_sources(target.get_sources())
- vapi_src = [x.rel_to_builddir(self.build_to_src) for x in vapi_src]
- extra_dep_files = []
- for s in src:
- if not s.endswith('.vala'):
- continue
- args = ['-d', self.get_target_private_dir(target)]
- sc = os.path.basename(s.fname)[:-4] + 'c'
- args += ['-C']
- vapi_order_deps = []
- for (sourcefile, vapi_info) in fast_vapis.items():
- if sourcefile == s:
- continue
- (vapibase, rel_vapi) = vapi_info
- args += ['--use-fast-vapi=' + rel_vapi]
- vapi_order_deps.append(rel_vapi)
- relsc = os.path.join(self.get_target_private_dir(target), sc)
- rel_s = s.rel_to_builddir(self.build_to_src)
- args += ['--deps', relsc + '.d']
- if self.environment.coredata.get_builtin_option('werror'):
- args += valac.get_werror_args()
- for d in target.external_deps:
- if isinstance(d, dependencies.PkgConfigDependency):
- if d.name == 'glib-2.0' and d.version_requirement is not None \
- and d.version_requirement.startswith(('>=', '==')):
- args += ['--target-glib', d.version_requirement[2:]]
- args += ['--pkg', d.name]
- args += vapi_src
- 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)
- args += extra_args
- generated_c += [relsc]
- element = NinjaBuildElement(relsc, valac.get_language() + '_COMPILER', rel_s)
- element.add_item('ARGS', args)
- element.add_orderdep(vapi_order_deps)
- element.add_dep(extra_dep_files)
- element.write(outfile)
- self.check_outputs(element)
- return generated_c
-
- def generate_rust_target(self, target, outfile):
- rustc = self.environment.coredata.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 isinstance(target, build.SharedLibrary):
- cratetype = 'rlib'
- elif isinstance(target, build.StaticLibrary):
- cratetype = 'rlib'
- else:
- raise InvalidArguments('Unknown target type for rustc.')
- args.append(cratetype)
- args += rustc.get_buildtype_args(self.environment.coredata.get_builtin_option('buildtype'))
- depfile = target.name + '.d'
- args += ['--out-dir', target.subdir]
- args += ['--emit', 'dep-info', '--emit', 'link']
- orderdeps = [os.path.join(t.subdir, t.get_filename()) for t in target.link_targets]
- linkdirs = {}
- for d in target.link_targets:
- linkdirs[d.subdir] = True
- for d in linkdirs.keys():
- if d == '':
- d = '.'
- args += ['-L', d]
- element = NinjaBuildElement(target_name, 'rust_COMPILER', 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)
- self.check_outputs(element)
-
- 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 = []
- for genlist in target.get_generated_sources():
- if isinstance(genlist, build.CustomTarget):
- for ifile in genlist.get_filename():
- rel = os.path.join(self.get_target_dir(genlist), ifile)
- all_srcs.append(rel)
- else:
- for ifile in genlist.get_outfilelist():
- rel = os.path.join(self.get_target_private_dir(target), ifile)
- all_srcs.append(rel)
- 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 = self.environment.coredata.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)
- link_args = swiftc.get_output_args(os.path.join(self.environment.get_build_dir(), self.get_target_filename(target)))
- 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]
- (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.split(i)[1]
- 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(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)
- self.check_outputs(elem)
- elem = NinjaBuildElement(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)
- self.check_outputs(elem)
- 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.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)
- self.check_outputs(elem)
- else:
- raise MesonException('Swift supports only executable and static library targets.')
-
- def generate_static_link_rules(self, is_cross, outfile):
- if self.build.has_language('java'):
- 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
- if mesonlib.is_windows():
- command_templ = ''' command = %s @$out.rsp
- rspfile = $out.rsp
- rspfile_content = $LINK_ARGS %s $in
-'''
- else:
- command_templ = ' command = %s $LINK_ARGS %s $in\n'
- command = command_templ %\
- (' '.join(static_linker.get_exelist()),
- ' '.join(static_linker.get_output_args('$out')))
- description = ' description = Static linking library $out\n\n'
- outfile.write(rule)
- outfile.write(command)
- outfile.write(description)
-
- def generate_dynamic_link_rules(self, outfile):
- 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 compiler in complist:
- langname = compiler.get_language()
- 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 = %s @$out.rsp
- rspfile = $out.rsp
- rspfile_content = %s $ARGS %s $in $LINK_ARGS $aliasing
-'''
- else:
- command_template = ' command = %s %s $ARGS %s $in $LINK_ARGS $aliasing\n'
- command = command_template % \
- (' '.join(compiler.get_linker_exelist()),\
- ' '.join(cross_args),\
- ' '.join(compiler.get_linker_output_args('$out')))
- description = ' description = Linking target $out'
- outfile.write(rule)
- outfile.write(command)
- outfile.write(description)
- outfile.write('\n')
- scriptdir = self.environment.get_script_dir()
- outfile.write('\n')
- symrule = 'rule SHSYM\n'
- symcmd = ' command = "%s" "%s" %s %s %s %s $CROSS\n' % (ninja_quote(sys.executable),
- self.environment.get_build_command(),
- '--internal',
- 'symbolextractor',
- '$in',
- '$out')
- 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()])
- command = ' command = %s $ARGS $in\n' % invoc
- description = ' description = Compiling cs 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.
- depfile = ' depfile = $out.d\n'
- depstyle = ' deps = gcc\n'
- outfile.write(rule)
- outfile.write(command)
- outfile.write(description)
- outfile.write(restat)
- outfile.write(depfile)
- outfile.write(depstyle)
- outfile.write('\n')
-
- def generate_rust_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 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 = [sys.executable,
- os.path.join(self.environment.get_script_dir(), 'dirchanger.py'),
- '$RUNDIR'] + compiler.get_exelist()
- invoc = ' '.join([ninja_quote(i) for i in full_exe])
- 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_compile_rule_for(self, langname, compiler, qstr, 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':
- if not is_cross:
- self.generate_rust_compile_rules(compiler, outfile)
- 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 = qstr % d
- quoted_depargs.append(d)
- cross_args = []
- if is_cross:
- try:
- cross_args = self.environment.cross_info.config['properties'][langname + '_args']
- except KeyError:
- pass
- if mesonlib.is_windows():
- command_template = ''' command = %s @$out.rsp
- rspfile = $out.rsp
- rspfile_content = %s $ARGS %s %s %s $in
-'''
- else:
- command_template = ' command = %s %s $ARGS %s %s %s $in\n'
- command = command_template % \
- (' '.join(compiler.get_exelist()),\
- ' '.join(cross_args),
- ' '.join(quoted_depargs),\
- ' '.join(compiler.get_output_args('$out')),\
- ' '.join(compiler.get_compile_only_args()))
- description = ' description = Compiling %s object $out\n' % langname
- 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, qstr, 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 = qstr % d
- quoted_depargs.append(d)
- if compiler.get_id() == 'msvc':
- output = ''
- else:
- output = ' '.join(compiler.get_output_args('$out'))
- command = " command = %s %s $ARGS %s %s %s $in\n" % \
- (' '.join(compiler.get_exelist()),\
- ' '.join(cross_args),\
- ' '.join(quoted_depargs),\
- output,\
- ' '.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):
- qstr = quote_char + "%s" + quote_char
- for compiler in self.build.compilers:
- langname = compiler.get_language()
- self.generate_compile_rule_for(langname, compiler, qstr, False, outfile)
- self.generate_pch_rule_for(langname, compiler, qstr, 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 compiler in cclist:
- langname = compiler.get_language()
- self.generate_compile_rule_for(langname, compiler, qstr, True, outfile)
- self.generate_pch_rule_for(langname, compiler, qstr, True, outfile)
- outfile.write('\n')
-
- 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 generate_custom_generator_rules(self, target, outfile):
- for genlist in target.get_generated_sources():
- if isinstance(genlist, build.CustomTarget):
- continue # Customtarget has already written its output rules
- generator = genlist.get_generator()
- exe = generator.get_exe()
- exe_arr = self.exe_object_to_cmd_array(exe)
- infilelist = genlist.get_infilelist()
- outfilelist = genlist.get_outfilelist()
- base_args = generator.get_arglist()
- 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 = os.path.join(self.build_to_src, curfile)
- outfiles = genlist.get_outputs_for(curfile)
- outfiles = [os.path.join(self.get_target_private_dir(target), of) for of in outfiles]
- args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output)\
- for x in base_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):]
- relout = self.get_target_private_dir(target)
- args = [x.replace("@SOURCE_DIR@", self.build_to_src).replace("@BUILD_DIR@", relout)
- for x in args]
- final_args = []
- for a in args:
- if a == '@EXTRA_ARGS@':
- final_args += genlist.get_extra_args()
- else:
- final_args.append(a)
- cmdlist = exe_arr + final_args
- elem = NinjaBuildElement(outfiles, 'CUSTOM_COMMAND', infilename)
- if len(extra_dependencies) > 0:
- elem.add_dep(extra_dependencies)
- elem.add_item('DESC', 'Generating $out')
- if isinstance(exe, build.BuildTarget):
- elem.add_dep(self.get_target_filename(exe))
- elem.add_item('COMMAND', cmdlist)
- elem.write(outfile)
- self.check_outputs(elem)
-
- def scan_fortran_module_outputs(self, target):
- compiler = None
- for c in self.build.compilers:
- if c.get_language() == '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 generated Fortran sources,
- # but those are really rare. I hope.
- if not compiler.can_compile(s):
- continue
- for line in open(os.path.join(self.environment.get_source_dir(), s.subdir, s.fname)):
- modmatch = modre.match(line)
- if modmatch is not None:
- modname = modmatch.group(1)
- if modname.lower() == '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()]
- for line in open(src):
- usematch = usere.match(line)
- if usematch is not None:
- usename = usematch.group(1)
- 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 occurrance,
- # 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.split(src)[1]:
- continue
- mod_name = compiler.module_name_to_filename(usematch.group(1))
- mod_files.append(os.path.join(dirname, mod_name))
- return mod_files
-
- def generate_single_compile(self, target, outfile, src, is_generated=False, header_deps=[], order_deps=[]):
- if(isinstance(src, str) and src.endswith('.h')):
- raise RuntimeError('Fug')
- if isinstance(src, RawFilename) and src.fname.endswith('.h'):
- raise RuntimeError('Fug')
- extra_orderdeps = []
- compiler = self.get_compiler_for_source(src)
- commands = self.generate_basic_compiler_args(target, compiler)
- commands += compiler.get_include_args(self.get_target_private_dir(target), False)
- curdir = target.get_subdir()
- tmppath = os.path.normpath(os.path.join(self.build_to_src, curdir))
- commands += compiler.get_include_args(tmppath, False)
- if curdir == '':
- curdir = '.'
- commands += compiler.get_include_args(curdir, False)
- for d in target.external_deps:
- if d.need_threads():
- commands += compiler.thread_flags()
- break
- if isinstance(src, RawFilename):
- rel_src = src.fname
- elif is_generated:
- if self.has_dir_part(src):
- rel_src = src
- else:
- rel_src = os.path.join(self.get_target_private_dir(target), src)
- abs_src = os.path.join(self.environment.get_source_dir(), rel_src)
- else:
- if isinstance(src, File):
- rel_src = src.rel_to_builddir(self.build_to_src)
- else:
- raise build.InvalidArguments('Invalid source type.')
- abs_src = os.path.join(self.environment.get_build_dir(), rel_src)
- if isinstance(src, RawFilename):
- src_filename = src.fname
- elif isinstance(src, File):
- 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()
- dep_file = compiler.depfile_for_object(rel_obj)
- if self.environment.coredata.get_builtin_option('use_pch'):
- pchlist = target.get_pch(compiler.language)
- else:
- pchlist = []
- if len(pchlist) == 0:
- 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
- for i in target.get_include_dirs():
- basedir = i.get_curdir()
- for d in i.get_incdirs():
- expdir = os.path.join(basedir, d)
- srctreedir = os.path.join(self.build_to_src, expdir)
- bargs = compiler.get_include_args(expdir, i.is_system)
- sargs = compiler.get_include_args(srctreedir, i.is_system)
- commands += bargs
- commands += sargs
- for d in i.get_extra_build_dirs():
- commands += compiler.get_include_args(d, i.is_system)
- custom_target_include_dirs = []
- for i in target.generated:
- if isinstance(i, build.CustomTarget):
- idir = self.get_target_dir(i)
- if idir not in custom_target_include_dirs:
- custom_target_include_dirs.append(idir)
- for i in custom_target_include_dirs:
- commands+= compiler.get_include_args(i, False)
- if self.environment.coredata.get_builtin_option('use_pch'):
- commands += self.get_pch_include_args(compiler, target)
- crstr = ''
- if target.is_cross:
- crstr = '_CROSS'
- compiler_name = '%s%s_COMPILER' % (compiler.get_language(), crstr)
- extra_deps = []
- if compiler.get_language() == 'fortran':
- 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(modfile, 'FORTRAN_DEP_HACK', rel_obj)
- depelem.write(outfile)
- self.check_outputs(depelem)
- commands += compiler.get_module_outdir_args(self.get_target_private_dir(target))
-
- element = NinjaBuildElement(rel_obj, compiler_name, rel_src)
- for d in header_deps:
- if isinstance(d, RawFilename):
- d = d.fname
- 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, RawFilename):
- d = d.fname
- 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)
- element.add_orderdep(extra_orderdeps)
- 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)
- self.check_outputs(element)
- return rel_obj
-
- def has_dir_part(self, fname):
- 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 dependendy 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 RuntimeError('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.split(header)[1]
- (objname, pch_args) = compiler.gen_pch_args(just_name, source, dst)
- commands += pch_args
- dep = dst + '.' + compiler.get_depfile_suffix()
- return (commands, dep, dst, [objname])
-
- def generate_gcc_pch_command(self, target, compiler, pch):
- commands = []
- commands += self.generate_basic_compiler_args(target, compiler)
- dst = os.path.join(self.get_target_private_dir(target),
- os.path.split(pch)[-1] + '.' + 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 len(pch) == 0:
- continue
- if '/' not in pch[0] or '/' not in pch[-1]:
- raise build.InvalidArguments('Precompiled header of "%s" must not be in the same directory as source, please put it in a subdirectory.' % target.get_basename())
- compiler = self.get_compiler_for_lang(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])
- 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(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)
- self.check_outputs(elem)
- 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(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)
- self.check_outputs(elem)
-
- 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'
- abspath = os.path.join(self.environment.get_build_dir(), target.subdir)
- commands = []
- commands += linker.get_linker_always_args()
- commands += linker.get_buildtype_linker_args(self.environment.coredata.get_builtin_option('buildtype'))
- commands += linker.get_option_link_args(self.environment.coredata.compiler_options)
- if not(isinstance(target, build.StaticLibrary)):
- commands += self.environment.coredata.external_link_args[linker.get_language()]
- if isinstance(target, build.Executable):
- commands += linker.get_std_exe_link_args()
- elif isinstance(target, build.SharedLibrary):
- commands += linker.get_std_shared_lib_link_args()
- commands += linker.get_pic_args()
- if hasattr(target, 'soversion'):
- soversion = target.soversion
- else:
- soversion = None
- commands += linker.get_soname_args(target.name, abspath, soversion)
- elif isinstance(target, build.StaticLibrary):
- commands += linker.get_std_link_args()
- else:
- raise RuntimeError('Unknown build target type.')
- # 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.
- if linker_base == 'STATIC':
- dependencies = []
- else:
- dependencies = target.get_dependencies()
- commands += self.build_target_link_arguments(linker, dependencies)
- for d in target.external_deps:
- if d.need_threads():
- commands += linker.thread_link_flags()
- if not isinstance(target, build.StaticLibrary):
- commands += target.link_args
- # External deps must be last because target link libraries may depend on them.
- if not(isinstance(target, build.StaticLibrary)):
- for dep in target.get_external_deps():
- commands += dep.get_link_args()
- for d in target.get_dependencies():
- if isinstance(d, build.StaticLibrary):
- for dep in d.get_external_deps():
- commands += dep.get_link_args()
- commands += linker.build_rpath_args(self.environment.get_build_dir(),\
- self.determine_rpath_dirs(target), target.install_rpath)
- if self.environment.coredata.get_builtin_option('coverage'):
- commands += linker.get_coverage_link_args()
- custom_target_libraries = self.get_custom_target_provided_libraries(target)
- commands += extra_args
- commands += custom_target_libraries
- commands = linker.unixtype_flags_to_native(commands)
- dep_targets = [self.get_dependency_filename(t) for t in dependencies]
- dep_targets += [os.path.join(self.environment.source_dir,
- target.subdir, t) for t in target.link_depends]
- elem = NinjaBuildElement(outname, linker_rule, obj_list)
- elem.add_dep(dep_targets + custom_target_libraries)
- elem.add_item('LINK_ARGS', commands)
- self.check_outputs(elem)
- return elem
-
- 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.output:
- if self.environment.is_library(f):
- libs.append(os.path.join(self.get_target_dir(t), f))
- return libs
-
- def determine_rpath_dirs(self, target):
- link_deps = target.get_all_link_deps()
- result = []
- for ld in link_deps:
- prospective = self.get_target_dir(ld)
- if not prospective in result:
- result.append(prospective)
- return result
-
- 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')
- return self.get_target_filename(t)
-
- def generate_shlib_aliases(self, target, outdir):
- basename = target.get_filename()
- aliases = target.get_aliaslist()
- if not mesonlib.is_windows():
- for alias in aliases:
- aliasfile = os.path.join(self.environment.get_build_dir(), outdir, alias)
- try:
- os.remove(aliasfile)
- except Exception:
- pass
- os.symlink(basename, aliasfile)
- else:
- mlog.debug("Library versioning disabled because host does not support symlinks.")
-
- def generate_gcov_clean(self, outfile):
- gcno_elem = NinjaBuildElement('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', [sys.executable, clean_script, '.', 'gcno'])
- gcno_elem.add_item('description', 'Deleting gcno files')
- gcno_elem.write(outfile)
- self.check_outputs(gcno_elem)
-
- gcda_elem = NinjaBuildElement('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', [sys.executable, clean_script, '.', 'gcda'])
- gcda_elem.add_item('description', 'Deleting gcda files')
- gcda_elem.write(outfile)
- self.check_outputs(gcda_elem)
-
- def is_compilable_file(self, filename):
- if filename.endswith('.cpp') or\
- filename.endswith('.c') or\
- filename.endswith('.cxx') or\
- filename.endswith('.cc') or\
- filename.endswith('.C'):
- return True
- return False
-
- def process_dep_gens(self, outfile, target):
- src_deps = []
- other_deps = []
- for rule in self.dep_rules.values():
- srcs = target.get_original_kwargs().get(rule.src_keyword, [])
- if isinstance(srcs, str):
- srcs = [srcs]
- for src in srcs:
- plainname = os.path.split(src)[1]
- basename = plainname.split('.')[0]
- outname = rule.name_templ.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname)
- outfilename = os.path.join(self.get_target_private_dir(target), outname)
- infilename = os.path.join(self.build_to_src, target.get_source_subdir(), src)
- elem = NinjaBuildElement(outfilename, rule.name, infilename)
- elem.write(outfile)
- self.check_outputs(elem)
- if self.is_compilable_file(outfilename):
- src_deps.append(outfilename)
- else:
- other_deps.append(outfilename)
- return (src_deps, other_deps)
-
- def generate_ending(self, outfile):
- targetlist = [self.get_target_filename(t) for t in self.build.get_targets().values()\
- if not isinstance(t, build.RunTarget)]
-
- elem = NinjaBuildElement('all', 'phony', targetlist)
- elem.write(outfile)
- self.check_outputs(elem)
-
- default = 'default all\n\n'
- outfile.write(default)
-
- ninja_command = environment.detect_ninja()
- if ninja_command is None:
- raise MesonException('Could not detect ninja command')
- elem = NinjaBuildElement('clean', 'CUSTOM_COMMAND', 'PHONY')
- elem.add_item('COMMAND', [ninja_command, '-t', 'clean'])
- elem.add_item('description', 'Cleaning')
- if self.environment.coredata.get_builtin_option('coverage'):
- self.generate_gcov_clean(outfile)
- elem.add_dep('clean-gcda')
- elem.add_dep('clean-gcno')
- elem.write(outfile)
- self.check_outputs(elem)
-
- deps = self.get_regen_filelist()
- elem = NinjaBuildElement('build.ninja', 'REGENERATE_BUILD', deps)
- elem.add_item('pool', 'console')
- elem.write(outfile)
-
- elem = NinjaBuildElement(deps, 'phony', '')
- elem.write(outfile)
- self.check_outputs(elem)
diff --git a/meson/optinterpreter.py b/meson/optinterpreter.py
deleted file mode 100644
index f0c93ae..0000000
--- a/meson/optinterpreter.py
+++ /dev/null
@@ -1,148 +0,0 @@
-# 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.
-
-from . import mparser
-from . import coredata, mesonlib
-import os, re
-
-forbidden_option_names = coredata.builtin_options
-forbidden_prefixes = {'c_': True,
- 'cpp_': True,
- 'rust_': True,
- 'fortran_': True,
- 'objc_': True,
- 'objcpp_': True,
- 'vala_': True,
- 'csharp_': True
- }
-
-def is_invalid_name(name):
- if name in forbidden_option_names:
- return True
- if name in forbidden_prefixes:
- return True
- return False
-
-class OptionException(coredata.MesonException):
- pass
-
-optname_regex = re.compile('[^a-zA-Z0-9_-]')
-
-def StringParser(name, description, kwargs):
- return coredata.UserStringOption(name, description,
- kwargs.get('value', ''), kwargs.get('choices', []))
-
-def BooleanParser(name, description, kwargs):
- return coredata.UserBooleanOption(name, description, kwargs.get('value', True))
-
-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]))
-
-option_types = {'string' : StringParser,
- 'boolean' : BooleanParser,
- 'combo' : ComboParser,
- }
-
-class OptionInterpreter:
- def __init__(self, subproject, command_line_options):
- self.options = {}
- self.subproject = subproject
- self.cmd_line_options = {}
- for o in command_line_options:
- (key, value) = o.split('=', 1)
- self.cmd_line_options[key] = value
-
- def process(self, option_file):
- try:
- ast = mparser.Parser(open(option_file, 'r').read()).parse()
- except coredata.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
-
- def reduce_single(self, arg):
- if isinstance(arg, str):
- return arg
- elif isinstance(arg, mparser.StringNode):
- return arg.value
- elif isinstance(arg, mparser.BooleanNode):
- return arg.value
- elif isinstance(arg, mparser.ArrayNode):
- return [self.reduce_single(curarg) for curarg in arg.args.arguments]
- elif isinstance(arg, mparser.NumberNode):
- return arg.value
- 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['type']
- if not opt_type 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.get('description', ''), kwargs)
- if opt.description == '':
- opt.description = opt_name
- if opt_name in self.cmd_line_options:
- opt.set_value(opt.parse_string(self.cmd_line_options[opt_name]))
- self.options[opt_name] = opt
diff --git a/meson/scripts/commandrunner.py b/meson/scripts/commandrunner.py
deleted file mode 100644
index f5a2fff..0000000
--- a/meson/scripts/commandrunner.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env python3
-
-# 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
-
-def run_command(source_dir, build_dir, subdir, command, arguments):
- env = {'MESON_SOURCE_ROOT' : source_dir,
- 'MESON_BUILD_ROOT' : build_dir,
- 'MESON_SUBDIR' : subdir
- }
- 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
- return subprocess.Popen(command_array, env=child_env, cwd=cwd)
- # 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".' % command)
- sys.exit(1)
-
-def run(args):
- if len(sys.argv) < 4:
- print('commandrunner.py <source dir> <build dir> <subdir> <command> [arguments]')
- sys.exit(1)
- src_dir = sys.argv[1]
- build_dir = sys.argv[2]
- subdir = sys.argv[3]
- command = sys.argv[4]
- arguments = sys.argv[5:]
- pc = run_command(src_dir, build_dir, subdir, command, arguments)
- pc.wait()
- return pc.returncode
-
-if __name__ == '__main__':
- sys.exit(run(sys.argv[1:]))
diff --git a/meson/scripts/delwithsuffix.py b/meson/scripts/delwithsuffix.py
deleted file mode 100644
index 38ab406..0000000
--- a/meson/scripts/delwithsuffix.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python3
-
-# 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(sys.argv) != 2:
- print('delwithsuffix.py <root of subdir to process> <suffix to delete>')
- sys.exit(1)
-
- topdir = sys.argv[1]
- suffix = sys.argv[2]
- 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:])
diff --git a/meson/scripts/depfixer.py b/meson/scripts/depfixer.py
deleted file mode 100644
index 1ab83b6..0000000
--- a/meson/scripts/depfixer.py
+++ /dev/null
@@ -1,302 +0,0 @@
-#!/usr/bin/env python3
-
-# 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, struct
-
-SHT_STRTAB = 3
-DT_NEEDED = 1
-DT_RPATH = 15
-DT_STRTAB = 5
-DT_SONAME = 14
-
-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):
- self.bfile = bfile
- self.bf = open(bfile, 'r+b')
- (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()
-
- 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.
- 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:
- print('File "%s" has unknown ELF class.' % self.bfile)
- sys.exit(1)
- if data[5] == 1:
- is_le = True
- elif data[5] == 2:
- is_le = False
- else:
- print('File "%s" has unknown ELF endianness.' % self.bfile)
- sys.exit(1)
- 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 = []
- 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
- self.bf.seek(strtab.val + soname.val)
- print(self.read_str())
-
- def get_rpath_offset(self):
- sec = self.find_section(b'.dynstr')
- for i in self.dynamic:
- if i.d_tag == DT_RPATH:
- return sec.sh_offset + i.val
- return None
-
- def print_rpath(self):
- offset = self.get_rpath_offset()
- if offset is None:
- print("This file does not have an rpath.")
- 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):
- rp_off = self.get_rpath_offset()
- if rp_off is None:
- 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):
- print("New rpath must not be longer than the old one.")
- self.bf.seek(rp_off)
- self.bf.write(new_rpath)
- self.bf.write(b'\0'*(len(old_rpath) - len(new_rpath) + 1))
- if len(new_rpath) == 0:
- self.remove_rpath_entry()
-
- def remove_rpath_entry(self):
- sec = self.find_section(b'.dynamic')
- for (i, entry) in enumerate(self.dynamic):
- if entry.d_tag == DT_RPATH:
- rpentry = self.dynamic[i]
- rpentry.d_tag = 0
- self.dynamic = self.dynamic[:i] + self.dynamic[i+1:] + [rpentry]
- 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: <binary file> <prefix>' % sys.argv[0])
- exit(1)
- e = Elf(args[0])
- if len(args) == 1:
- e.print_rpath()
- else:
- new_rpath = args[1]
- e.fix_rpath(new_rpath.encode('utf8'))
- return 0
-
-if __name__ == '__main__':
- run(sys.argv[1:])
diff --git a/meson/scripts/dirchanger.py b/meson/scripts/dirchanger.py
deleted file mode 100644
index 93a901d..0000000
--- a/meson/scripts/dirchanger.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env python3
-
-# 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:]))
diff --git a/meson/scripts/gtkdochelper.py b/meson/scripts/gtkdochelper.py
deleted file mode 100644
index 68be8f2..0000000
--- a/meson/scripts/gtkdochelper.py
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/usr/bin/env python3
-# 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 shutil
-import argparse
-
-parser = argparse.ArgumentParser()
-
-parser.add_argument('--sourcedir', dest='sourcedir')
-parser.add_argument('--builddir', dest='builddir')
-parser.add_argument('--subdir', dest='subdir')
-parser.add_argument('--headerdir', dest='headerdir')
-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='')
-
-def build_gtkdoc(source_root, build_root, doc_subdir, src_subdir,
- main_file, module, html_args, scan_args):
- abs_src = os.path.join(source_root, src_subdir)
- abs_out = os.path.join(build_root, doc_subdir)
- htmldir = os.path.join(abs_out, 'html')
- scan_cmd = ['gtkdoc-scan',
- '--module=' + module,
- '--source-dir=' + abs_src] + scan_args
-# print(scan_cmd)
-# sys.exit(1)
- subprocess.check_call(scan_cmd,
- cwd=abs_out)
- if main_file.endswith('sgml'):
- modeflag = '--sgml-mode'
- else:
- modeflag = '--xml-mode'
- mkdb_cmd = ['gtkdoc-mkdb',
- '--module=' + module,
- '--output-format=xml',
- modeflag,
- '--source-dir=' + abs_src]
- main_abs = os.path.join(source_root, doc_subdir, main_file)
- 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)
-# print(mkdb_cmd)
-# sys.exit(1)
- subprocess.check_call(mkdb_cmd, cwd=abs_out)
- shutil.rmtree(htmldir, ignore_errors=True)
- try:
- os.mkdir(htmldir)
- except Exception:
- pass
- mkhtml_cmd = ['gtkdoc-mkhtml',
- '--path=' + abs_src,
- 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
-# print(mkhtml_cmd)
-# sys.exit(1)
- subprocess.check_call(mkhtml_cmd, cwd=os.path.join(abs_out, 'html'), shell=False)
- fixref_cmd = ['gtkdoc-fixxref',
- '--module=' + module,
- '--module-dir=html']
-# print(fixref_cmd)
-# sys.exit(1)
- subprocess.check_call(fixref_cmd, cwd=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 = []
- build_gtkdoc(options.sourcedir,
- options.builddir,
- options.subdir,
- options.headerdir,
- options.mainfile,
- options.modulename,
- htmlargs,
- scanargs)
-
- if 'MESON_INSTALL_PREFIX' in os.environ:
- if 'DESTDIR' in os.environ:
- installdir = os.environ['DESTDIR'] + os.environ['MESON_INSTALL_PREFIX']
- else:
- installdir = os.environ['MESON_INSTALL_PREFIX']
- install_gtkdoc(options.builddir,
- options.subdir,
- installdir,
- 'share/gtk-doc/html',
- options.modulename)
- return 0
-
-if __name__ == '__main__':
- sys.exit(run(sys.argv[1:]))
diff --git a/meson/scripts/meson_benchmark.py b/meson/scripts/meson_benchmark.py
deleted file mode 100644
index 26f1f95..0000000
--- a/meson/scripts/meson_benchmark.py
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/usr/bin/env python3
-
-# 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 subprocess, sys, os, argparse
-import pickle, statistics, json
-from . import meson_test
-
-parser = argparse.ArgumentParser()
-parser.add_argument('--wd', default=None, dest='wd',
- help='directory to cd into before running')
-parser.add_argument('args', nargs='+')
-
-def print_stats(numlen, num_tests, name, res, i, duration, stdev):
- startpad = ' '*(numlen - len('%d' % (i+1)))
- num = '%s%d/%d' % (startpad, i+1, num_tests)
- padding1 = ' '*(38-len(name))
- padding2 = ' '*(8-len(res))
- result_str = '%s %s %s%s%s%5.5f s +- %5.5f s' % \
- (num, name, padding1, res, padding2, duration, stdev)
- print(result_str)
-# write_json_log(jsonlogfile, name, result)
-
-def print_json_log(jsonlogfile, rawruns, test_name, i):
- jsonobj = {'name' : test_name}
- runs = []
- for r in rawruns:
- runobj = {'duration': r.duration,
- 'stdout': r.stdo,
- 'stderr': r.stde,
- 'returncode' : r.returncode,
- 'duration' : r.duration}
- runs.append(runobj)
- jsonobj['runs'] = runs
- jsonlogfile.write(json.dumps(jsonobj) + '\n')
- jsonlogfile.flush()
-
-def run_benchmarks(options, datafile):
- failed_tests = 0
- logfile_base = 'meson-logs/benchmarklog'
- jsonlogfilename = logfile_base+ '.json'
- jsonlogfile = open(jsonlogfilename, 'w')
- tests = pickle.load(open(datafile, 'rb'))
- num_tests = len(tests)
- if num_tests == 0:
- print('No benchmarks defined.')
- return 0
- iteration_count = 5
- wrap = [] # Benchmarks on cross builds are pointless so don't support them.
- for i, test in enumerate(tests):
- runs = []
- durations = []
- failed = False
- for _ in range(iteration_count):
- res = meson_test.run_single_test(wrap, test)
- runs.append(res)
- durations.append(res.duration)
- if res.returncode != 0:
- failed = True
- mean = statistics.mean(durations)
- stddev = statistics.stdev(durations)
- if failed:
- resultstr = 'FAIL'
- failed_tests += 1
- else:
- resultstr = 'OK'
- print_stats(3, num_tests, test.name, resultstr, i, mean, stddev)
- print_json_log(jsonlogfile, runs, test.name, i)
- print('\nFull log written to meson-logs/benchmarklog.json.')
- return failed_tests
-
-def run(args):
- global failed_tests
- options = parser.parse_args(args)
- if len(options.args) != 1:
- print('Benchmark runner for Meson. Do not run on your own, mmm\'kay?')
- print('%s [data file]' % sys.argv[0])
- if options.wd is not None:
- os.chdir(options.wd)
- datafile = options.args[0]
- returncode = run_benchmarks(options, datafile)
- return returncode
-
-if __name__ == '__main__':
- sys.exit(run(sys.argv[1:]))
diff --git a/meson/scripts/meson_install.py b/meson/scripts/meson_install.py
deleted file mode 100644
index 1ede757..0000000
--- a/meson/scripts/meson_install.py
+++ /dev/null
@@ -1,215 +0,0 @@
-#!/usr/bin/env python3
-
-# 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
-from glob import glob
-
-def do_install(datafilename):
- ifile = open(datafilename, 'rb')
- d = pickle.load(ifile)
- destdir_var = 'DESTDIR'
- if destdir_var in os.environ:
- d.destdir = os.environ[destdir_var]
- else:
- d.destdir = ''
- d.fullprefix = d.destdir + d.prefix
-
- 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)
- install_po(d)
- run_install_script(d)
-
-def install_subdirs(d):
- for (src_dir, dst_dir) in d.install_subdirs:
- if os.path.isabs(dst_dir):
- dst_dir = d.destdir + dst_dir
- else:
- dst_dir = d.fullprefix + dst_dir
- # Python's copytree works in strange ways.
- last_level = os.path.split(src_dir)[-1]
- final_dst = os.path.join(dst_dir, last_level)
-# Don't do rmtree because final_dst might point to e.g. /var/www
-# We might need to revert to walking the directory tree by hand.
-# shutil.rmtree(final_dst, ignore_errors=True)
- shutil.copytree(src_dir, final_dst, symlinks=True)
- print('Installing subdir %s to %s.' % (src_dir, dst_dir))
-
-def install_po(d):
- packagename = d.po_package_name
- for f in d.po:
- srcfile = f[0]
- localedir = f[1]
- languagename = f[2]
- outfile = os.path.join(d.fullprefix, localedir, languagename, 'LC_MESSAGES',
- packagename + '.mo')
- os.makedirs(os.path.split(outfile)[0], exist_ok=True)
- shutil.copyfile(srcfile, outfile)
- shutil.copystat(srcfile, outfile)
- print('Installing %s to %s.' % (srcfile, outfile))
-
-def install_data(d):
- for i in d.data:
- fullfilename = i[0]
- outfilename = i[1]
- if os.path.isabs(outfilename):
- outdir = d.destdir + os.path.split(outfilename)[0]
- outfilename = d.destdir + outfilename
- else:
- outdir = os.path.join(d.fullprefix, os.path.split(outfilename)[0])
- outfilename = os.path.join(outdir, os.path.split(outfilename)[1])
- os.makedirs(outdir, exist_ok=True)
- print('Installing %s to %s.' % (fullfilename, outdir))
- shutil.copyfile(fullfilename, outfilename)
- shutil.copystat(fullfilename, outfilename)
-
-def install_man(d):
- for m in d.man:
- outfileroot = m[1]
- outfilename = os.path.join(d.fullprefix, outfileroot)
- full_source_filename = m[0]
- outdir = os.path.split(outfilename)[0]
- os.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'):
- open(outfilename, 'wb').write(gzip.compress(open(full_source_filename, 'rb').read()))
- else:
- shutil.copyfile(full_source_filename, outfilename)
- shutil.copystat(full_source_filename, outfilename)
-
-def install_headers(d):
- for t in d.headers:
- fullfilename = t[0]
- outdir = os.path.join(d.fullprefix, t[1])
- fname = os.path.split(fullfilename)[1]
- outfilename = os.path.join(outdir, fname)
- print('Installing %s to %s' % (fname, outdir))
- os.makedirs(outdir, exist_ok=True)
- shutil.copyfile(fullfilename, outfilename)
- shutil.copystat(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
- }
- child_env = os.environ.copy()
- child_env.update(env)
-
- for i in d.install_scripts:
- script = i.cmd_arr[0]
- print('Running custom install script %s' % script)
- suffix = os.path.splitext(script)[1].lower()
- if platform.system().lower() == 'windows' and suffix != '.bat':
- first_line = open(script).readline().strip()
- if first_line.startswith('#!'):
- commands = first_line[2:].split('#')[0].strip().split()
- commands[0] = shutil.which(commands[0].split('/')[-1])
- if commands[0] is None:
- raise RuntimeError("Don't know how to run script %s." % script)
- final_command = commands + [script] + i.cmd_arr[1:]
- else:
- final_command = i.cmd_arr
- subprocess.check_call(final_command, env=child_env)
-
-def is_elf_platform():
- platname = platform.system().lower()
- if platname == 'darwin' or platname == 'windows':
- 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 = os.path.join(d.fullprefix, t[1])
- aliases = t[2]
- outname = os.path.join(outdir, os.path.split(fname)[-1])
- should_strip = t[3]
- install_rpath = t[4]
- print('Installing %s to %s' % (fname, outname))
- os.makedirs(outdir, exist_ok=True)
- shutil.copyfile(fname, outname)
- shutil.copystat(fname, outname)
- if should_strip:
- print('Stripping target')
- ps = subprocess.Popen(['strip', outname], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdo, stde) = ps.communicate()
- if ps.returncode != 0:
- print('Could not strip file.\n')
- print('Stdout:\n%s\n' % stdo.decode())
- print('Stderr:\n%s\n' % stde.decode())
- sys.exit(1)
- printed_symlink_error = False
- for alias in aliases:
- try:
- symlinkfilename = os.path.join(outdir, alias)
- try:
- os.unlink(symlinkfilename)
- except FileNotFoundError:
- pass
- os.symlink(os.path.split(fname)[-1], symlinkfilename)
- except NotImplementedError:
- if not printed_symlink_error:
- print("Symlink creation does not work on this platform.")
- printed_symlink_error = True
- if is_elf_platform():
- p = subprocess.Popen(d.depfixer + [outname, install_rpath],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- (stdo, stde) = p.communicate()
- if p.returncode != 0:
- print('Could not fix dependency info.\n')
- print('Stdout:\n%s\n' % stdo.decode())
- print('Stderr:\n%s\n' % stde.decode())
- sys.exit(1)
-
-def run(args):
- 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]
- do_install(datafilename)
- return 0
-
-if __name__ == '__main__':
- sys.exit(run(sys.argv[1:]))
diff --git a/meson/scripts/meson_test.py b/meson/scripts/meson_test.py
deleted file mode 100644
index c5814ef..0000000
--- a/meson/scripts/meson_test.py
+++ /dev/null
@@ -1,233 +0,0 @@
-#!/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.
-
-import meson
-import sys, os, subprocess, time, datetime, pickle, multiprocessing, json
-import concurrent.futures as conc
-import argparse
-import platform
-
-def is_windows():
- platname = platform.system().lower()
- return platname == 'windows' or 'mingw' in platname
-
-tests_failed = []
-
-parser = argparse.ArgumentParser()
-parser.add_argument('--wrapper', default=None, dest='wrapper',
- help='wrapper to run tests with (e.g. valgrind)')
-parser.add_argument('--wd', default=None, dest='wd',
- help='directory to cd into before running')
-parser.add_argument('--suite', default=None, dest='suite',
- help='Only run tests belonging to this suite.')
-parser.add_argument('args', nargs='+')
-
-
-class TestRun():
- def __init__(self, res, returncode, duration, stdo, stde, cmd):
- self.res = res
- self.returncode = returncode
- self.duration = duration
- self.stdo = stdo
- self.stde = stde
- self.cmd = cmd
-
-def decode(stream):
- try:
- return stream.decode('utf-8')
- except UnicodeDecodeError:
- return stream.decode('iso-8859-1', errors='ignore')
-
-def write_log(logfile, test_name, result_str, result):
- logfile.write(result_str + '\n\n')
- logfile.write('--- command ---\n')
- if result.cmd is None:
- logfile.write('NONE')
- else:
- logfile.write(' '.join(result.cmd))
- logfile.write('\n--- "%s" stdout ---\n' % test_name)
- logfile.write(result.stdo)
- logfile.write('\n--- "%s" stderr ---\n' % test_name)
- logfile.write(result.stde)
- logfile.write('\n-------\n\n')
-
-def write_json_log(jsonlogfile, test_name, result):
- result = {'name' : test_name,
- 'stdout' : result.stdo,
- 'stderr' : result.stde,
- 'result' : result.res,
- 'duration' : result.duration,
- 'returncode' : result.returncode,
- 'command' : result.cmd}
- jsonlogfile.write(json.dumps(result) + '\n')
-
-def run_with_mono(fname):
- if fname.endswith('.exe') and not is_windows():
- return True
- return False
-
-def run_single_test(wrap, test):
- global tests_failed
- if test.fname[0].endswith('.jar'):
- cmd = ['java', '-jar'] + test.fname
- elif not test.is_cross and run_with_mono(test.fname[0]):
- cmd = ['mono'] + test.fname
- else:
- if test.is_cross:
- 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 len(wrap) > 0 and 'valgrind' in wrap[0]:
- wrap += test.valgrind_args
- if cmd is None:
- res = 'SKIP'
- duration = 0.0
- stdo = 'Not run because can not execute cross compiled binaries.'
- stde = ''
- returncode = -1
- else:
- cmd = wrap + cmd + test.cmd_args
- starttime = time.time()
- child_env = os.environ.copy()
- child_env.update(test.env)
- if len(test.extra_paths) > 0:
- child_env['PATH'] = child_env['PATH'] + ';'.join([''] + test.extra_paths)
- p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- env=child_env, cwd=test.workdir)
- timed_out = False
- try:
- (stdo, stde) = p.communicate(timeout=test.timeout)
- except subprocess.TimeoutExpired:
- timed_out = True
- p.kill()
- (stdo, stde) = p.communicate()
- endtime = time.time()
- duration = endtime - starttime
- stdo = decode(stdo)
- stde = decode(stde)
- if timed_out:
- res = 'TIMEOUT'
- tests_failed.append((test.name, stdo, stde))
- elif (not test.should_fail and p.returncode == 0) or \
- (test.should_fail and p.returncode != 0):
- res = 'OK'
- else:
- res = 'FAIL'
- tests_failed.append((test.name, stdo, stde))
- returncode = p.returncode
- return TestRun(res, returncode, duration, stdo, stde, cmd)
-
-def print_stats(numlen, tests, name, result, i, logfile, jsonlogfile):
- 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)
- print(result_str)
- write_log(logfile, name, result_str, result)
- write_json_log(jsonlogfile, name, result)
-
-def drain_futures(futures):
- for i in futures:
- (result, numlen, tests, name, i, logfile, jsonlogfile) = i
- print_stats(numlen, tests, name, result.result(), i, logfile, jsonlogfile)
-
-def filter_tests(suite, tests):
- if suite is None:
- return tests
- return [x for x in tests if suite in x.suite]
-
-def run_tests(options, datafilename):
- logfile_base = 'meson-logs/testlog'
- if options.wrapper is None:
- wrap = []
- logfilename = logfile_base + '.txt'
- jsonlogfilename = logfile_base+ '.json'
- else:
- wrap = [options.wrapper]
- logfilename = logfile_base + '-' + options.wrapper.replace(' ', '_') + '.txt'
- jsonlogfilename = logfile_base + '-' + options.wrapper.replace(' ', '_') + '.json'
- logfile = open(logfilename, 'w')
- jsonlogfile = open(jsonlogfilename, 'w')
- logfile.write('Log of Meson test suite run on %s.\n\n' % datetime.datetime.now().isoformat())
- tests = pickle.load(open(datafilename, 'rb'))
- if len(tests) == 0:
- print('No tests defined.')
- return
- numlen = len('%d' % len(tests))
- 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:
- num_workers = multiprocessing.cpu_count()
- executor = conc.ThreadPoolExecutor(max_workers=num_workers)
- futures = []
- filtered_tests = filter_tests(options.suite, tests)
- for i, test in enumerate(filtered_tests):
- if test.suite[0] == '':
- visible_name = test.name
- else:
- if options.suite is not None:
- visible_name = options.suite + ' / ' + test.name
- else:
- visible_name = test.suite[0] + ' / ' + test.name
-
- if not test.is_parallel:
- drain_futures(futures)
- futures = []
- res = run_single_test(wrap, test)
- print_stats(numlen, filtered_tests, visible_name, res, i, logfile, jsonlogfile)
- else:
- f = executor.submit(run_single_test, wrap, test)
- futures.append((f, numlen, filtered_tests, visible_name, i, logfile, jsonlogfile))
- drain_futures(futures)
- return logfilename
-
-def run(args):
- global tests_failed
- options = parser.parse_args(args)
- if len(options.args) != 1:
- print('Test runner for Meson. Do not run on your own, mmm\'kay?')
- print('%s [data file]' % sys.argv[0])
- if options.wd is not None:
- os.chdir(options.wd)
- datafile = options.args[0]
- logfilename = run_tests(options, datafile)
- returncode = 0
- if len(tests_failed) > 0:
- print('\nOutput of failed tests (max 10):')
- for (name, stdo, stde) in tests_failed[:10]:
- print("{} stdout:\n".format(name))
- print(stdo)
- print('\n{} stderr:\n'.format(name))
- print(stde)
- print('\n')
- returncode = 1
- print('\nFull log written to %s.' % logfilename)
- return returncode
-
-if __name__ == '__main__':
- sys.exit(run(sys.argv[1:]))
diff --git a/meson/scripts/regen_checker.py b/meson/scripts/regen_checker.py
deleted file mode 100644
index f360a7c..0000000
--- a/meson/scripts/regen_checker.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env python3
-
-# 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
-
-# This could also be used for XCode.
-
-def need_regen(regeninfo):
- sln_time = os.stat(os.path.join(regeninfo.build_dir, regeninfo.solutionfile)).st_mtime
- for i in regeninfo.depfiles:
- curfile = os.path.join(regeninfo.build_dir, i)
- curtime = os.stat(curfile).st_mtime
- if curtime > sln_time:
- return True
- return False
-
-def regen(regeninfo):
- scriptdir = os.path.split(__file__)[0]
- mesonscript = os.path.join(scriptdir, 'meson.py')
- cmd = [sys.executable, mesonscript, regeninfo.build_dir, regeninfo.source_dir,
- '--backend=vs2010', 'secret-handshake']
- subprocess.check_call(cmd)
-
-def run(args):
- regeninfo = pickle.load(open(os.path.join(args[0], 'regeninfo.dump'), 'rb'))
- if need_regen(regeninfo):
- regen(regeninfo)
- sys.exit(0)
-
-if __name__ == '__main__':
- run(sys.argv[1:])
diff --git a/meson/scripts/symbolextractor.py b/meson/scripts/symbolextractor.py
deleted file mode 100644
index 9607466..0000000
--- a/meson/scripts/symbolextractor.py
+++ /dev/null
@@ -1,106 +0,0 @@
-#!/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.
-
-# 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 sys, subprocess
-from meson import mesonlib
-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."""
- open(outfilename, 'w').close()
-
-def write_if_changed(text, outfilename):
- try:
- oldtext = open(outfilename, 'r').read()
- if text == oldtext:
- return
- except FileNotFoundError:
- pass
- open(outfilename, 'w').write(text)
-
-def linux_syms(libfilename, outfilename):
- pe = subprocess.Popen(['readelf', '-d', libfilename], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- output = pe.communicate()[0].decode()
- 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 = subprocess.Popen(['nm', '--dynamic', '--extern-only', '--defined-only', '--format=posix', libfilename],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- output = pnm.communicate()[0].decode()
- 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 = subprocess.Popen(['otool', '-l', libfilename], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- output = pe.communicate()[0].decode()
- 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 = subprocess.Popen(['nm', '-g', '-P', libfilename], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- output = pnm.communicate()[0].decode()
- 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 <shared library file> <output file>')
- 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:]))
diff --git a/meson/scripts/vcstagger.py b/meson/scripts/vcstagger.py
deleted file mode 100644
index 390e37a..0000000
--- a/meson/scripts/vcstagger.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python3
-
-# 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
-
- new_data = open(infile).read().replace(replace_string, new_string)
- if (not os.path.exists(outfile)) or (open(outfile).read() != new_data):
- open(outfile, 'w').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)
-
-if __name__ == '__main__':
- sys.exit(run(sys.argv[1:]))
diff --git a/meson/vs2010backend.py b/meson/vs2010backend.py
deleted file mode 100644
index 33e9646..0000000
--- a/meson/vs2010backend.py
+++ /dev/null
@@ -1,640 +0,0 @@
-# Copyright 2014-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, sys
-import pickle
-from . import backends, build
-from . import dependencies
-from . import mlog
-import xml.etree.ElementTree as ET
-import xml.dom.minidom
-from .coredata import MesonException
-
-class RegenInfo():
- def __init__(self, source_dir, build_dir, depfiles, solutionfile):
- self.source_dir = source_dir
- self.build_dir = build_dir
- self.depfiles = depfiles
- self.solutionfile = solutionfile
-
-class Vs2010Backend(backends.Backend):
- def __init__(self, build):
- super().__init__(build)
- self.project_file_version = '10.0.30319.1'
- # foo.c compiles to foo.obj, not foo.c.obj
- self.source_suffix_in_obj = False
-
- def generate_custom_generator_commands(self, target, parent_node):
- idgroup = ET.SubElement(parent_node, 'ItemDefinitionGroup')
- all_output_files = []
- for genlist in target.get_generated_sources():
- if isinstance(genlist, build.CustomTarget):
- all_output_files += [os.path.join(self.get_target_dir(genlist), i) for i in genlist.output]
- else:
- generator = genlist.get_generator()
- exe = generator.get_exe()
- infilelist = genlist.get_infilelist()
- outfilelist = genlist.get_outfilelist()
- if isinstance(exe, build.BuildTarget):
- exe_file = os.path.join(self.environment.get_build_dir(), self.get_target_filename(exe))
- else:
- exe_file = exe.get_command()
- base_args = generator.get_arglist()
- for i in range(len(infilelist)):
- if len(infilelist) == len(outfilelist):
- sole_output = os.path.join(self.get_target_private_dir(target), outfilelist[i])
- else:
- sole_output = ''
- curfile = infilelist[i]
- infilename = os.path.join(self.environment.get_source_dir(), curfile)
- outfiles = genlist.get_outputs_for(curfile)
- outfiles = [os.path.join(self.get_target_private_dir(target), of) for of in outfiles]
- all_output_files += outfiles
- args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output)\
- for x in base_args]
- args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()).replace("@BUILD_DIR@", self.get_target_private_dir(target))
- for x in args]
- fullcmd = [exe_file] + args
- cbs = ET.SubElement(idgroup, 'CustomBuildStep')
- ET.SubElement(cbs, 'Command').text = ' '.join(self.special_quote(fullcmd))
- ET.SubElement(cbs, 'Inputs').text = infilename
- ET.SubElement(cbs, 'Outputs').text = ';'.join(outfiles)
- ET.SubElement(cbs, 'Message').text = 'Generating sources from %s.' % infilename
- pg = ET.SubElement(parent_node, 'PropertyGroup')
- ET.SubElement(pg, 'CustomBuildBeforeTargets').text = 'ClCompile'
- return all_output_files
-
- def generate(self, interp):
- self.interpreter = interp
- self.platform = 'Win32'
- 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(sln_filename)
- open(os.path.join(self.environment.get_scratch_dir(), 'regen.stamp'), 'wb')
- rulefile = os.path.join(self.environment.get_scratch_dir(), 'regen.rule')
- if not os.path.exists(rulefile):
- open(rulefile, 'w').write("# For some reason this needs to be here.")
-
- def generate_regen_info(self, sln_filename):
- deps = self.get_regen_filelist()
- regeninfo = RegenInfo(self.environment.get_source_dir(),
- self.environment.get_build_dir(),
- deps,
- sln_filename)
- pickle.dump(regeninfo, open(os.path.join(self.environment.get_scratch_dir(), 'regeninfo.dump'), 'wb'))
-
- def get_obj_target_deps(self, obj_list):
- result = {}
- for o in obj_list:
- if isinstance(o, build.ExtractedObjects):
- result[o.target.get_basename()] = True
- return result.keys()
-
- def determine_deps(self, p):
- all_deps = {}
- target = self.build.targets[p[0]]
- if isinstance(target, build.CustomTarget):
- for d in target.dependencies:
- all_deps[d.get_id()] = True
- return all_deps
- if isinstance(target, build.RunTarget):
- for d in [target.command] + target.args:
- if isinstance(d, build.BuildTarget):
- all_deps[d.get_id()] = True
- return all_deps
- for ldep in target.link_targets:
- all_deps[ldep.get_id()] = True
- for objdep in self.get_obj_target_deps(target.objects):
- all_deps[objdep] = True
- for gendep in target.generated:
- if isinstance(gendep, build.CustomTarget):
- all_deps[gendep.get_id()] = True
- else:
- gen_exe = gendep.generator.get_exe()
- if isinstance(gen_exe, build.Executable):
- all_deps[gen_exe.get_id()] = True
- return all_deps
-
- def generate_solution(self, sln_filename, projlist):
- ofile = open(sln_filename, 'w')
- ofile.write('Microsoft Visual Studio Solution File, Format Version 11.00\n')
- ofile.write('# Visual Studio 2010\n')
- prj_templ = prj_line = '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)
- all_deps = self.determine_deps(p)
- 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')
- 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))
- for p in projlist:
- ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' %
- (p[2], self.buildtype, self.platform,
- self.buildtype, self.platform))
- if not isinstance(self.build.targets[p[0]], build.RunTarget):
- 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 = []
- comp = None
- for l, c in self.environment.coredata.compilers.items():
- if l == 'c' or l == 'cpp':
- comp = c
- break
- if comp is None:
- raise RuntimeError('C and C++ compilers missing.')
- 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, comp)
- projlist.append((name, relname, uuid))
- return projlist
-
- def split_sources(self, srclist):
- sources = []
- headers = []
- for i in srclist:
- if self.environment.is_header(i):
- headers.append(i)
- else:
- sources.append(i)
- return (sources, headers)
-
- def target_to_build_root(self, target):
- if target.subdir == '':
- return ''
-
- directories = os.path.split(target.subdir)
- directories = list(filter(bool,directories)) #Filter out empty strings
-
- return '/'.join(['..']*len(directories))
-
- def special_quote(self, arr):
- return ['&quot;%s&quot;' % i for i in arr]
-
- 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 = 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
- 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'
- 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
- 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 = [sys.executable, 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)]
- 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.fullpath
- 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')
- tree = ET.ElementTree(root)
- tree.write(ofname, encoding='utf-8', xml_declaration=True)
-
- 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')
- (srcs, ofilenames, cmd) = self.eval_custom_target_command(target, True)
- cmd_templ = '''"%s" '''*len(cmd)
- ET.SubElement(customstep, 'Command').text = cmd_templ % tuple(cmd)
- ET.SubElement(customstep, 'Outputs').text = ';'.join([os.path.join(self.environment.get_build_dir(), i)\
- for i in ofilenames])
- ET.SubElement(customstep, 'Inputs').text = ';'.join([os.path.join(self.environment.get_build_dir(), i) \
- for i in srcs])
- ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets')
- tree = ET.ElementTree(root)
- tree.write(ofname, encoding='utf-8', xml_declaration=True)
-
- def gen_vcxproj(self, target, ofname, guid, compiler):
- 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())
- down = self.target_to_build_root(target)
- proj_to_src_root = os.path.join(down, self.build_to_src)
- proj_to_src_dir = os.path.join(proj_to_src_root, target.subdir)
- (sources, headers) = self.split_sources(target.sources)
- buildtype = 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= buildtype
- pl = ET.SubElement(prjconf, 'Platform')
- pl.text = self.platform
- globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals')
- guidelem = ET.SubElement(globalgroup, 'ProjectGuid')
- guidelem.text = 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
- ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.Default.props')
- type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration')
- ET.SubElement(type_config, 'ConfigurationType').text = conftype
- ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte'
- ET.SubElement(type_config, 'WholeProgramOptimization').text = 'false'
- ET.SubElement(type_config, 'UseDebugLibraries').text = 'true'
- ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.props')
- generated_files = self.generate_custom_generator_commands(target, root)
- (gen_src, gen_hdrs) = self.split_sources(generated_files)
- 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 = os.path.join(self.get_target_dir(target), target.get_basename() + '.dir') + '\\'
- tname = ET.SubElement(direlem, 'TargetName')
- tname.text = target_name
- inclinc = ET.SubElement(direlem, 'LinkIncremental')
- inclinc.text = 'true'
-
- compiles = ET.SubElement(root, 'ItemDefinitionGroup')
- clconf = ET.SubElement(compiles, 'ClCompile')
- opt = ET.SubElement(clconf, 'Optimization')
- opt.text = 'disabled'
- inc_dirs = [proj_to_src_dir, self.get_target_private_dir(target)]
- cur_dir = target.subdir
- if cur_dir == '':
- cur_dir= '.'
- inc_dirs.append(cur_dir)
- extra_args = []
- # SUCKS, VS can not handle per-language type flags, so just use
- # them all.
- extra_args += compiler.get_buildtype_args(self.buildtype)
- for l in self.environment.coredata.external_args.values():
- for a in l:
- extra_args.append(a)
- for l in self.build.global_args.values():
- for a in l:
- extra_args.append(a)
- for l in target.extra_args.values():
- for a in l:
- extra_args.append(a)
- # FIXME all the internal flags of VS (optimization etc) are represented
- # by their own XML elements. In theory we should split all flags to those
- # that have an XML element and those that don't and serialise them
- # properly. This is a crapton of work for no real gain, so just dump them
- # here.
- extra_args = compiler.get_option_compile_args(self.environment.coredata.compiler_options)
- if len(extra_args) > 0:
- extra_args.append('%(AdditionalOptions)')
- ET.SubElement(clconf, "AdditionalOptions").text = ' '.join(extra_args)
- for d in target.include_dirs:
- for i in d.incdirs:
- curdir = os.path.join(d.curdir, i)
- inc_dirs.append(self.relpath(curdir, target.subdir)) # build dir
- inc_dirs.append(os.path.join(proj_to_src_root, curdir)) # src dir
- inc_dirs.append('%(AdditionalIncludeDirectories)')
- ET.SubElement(clconf, 'AdditionalIncludeDirectories').text = ';'.join(inc_dirs)
- preproc = ET.SubElement(clconf, 'PreprocessorDefinitions')
- rebuild = ET.SubElement(clconf, 'MinimalRebuild')
- rebuild.text = 'true'
- rtlib = ET.SubElement(clconf, 'RuntimeLibrary')
- rtlib.text = 'MultiThreadedDebugDLL'
- funclink = ET.SubElement(clconf, 'FunctionLevelLinking')
- funclink.text = 'true'
- pch = ET.SubElement(clconf, 'PrecompiledHeader')
- warnings = ET.SubElement(clconf, 'WarningLevel')
- warnings.text = 'Level3'
- debinfo = ET.SubElement(clconf, 'DebugInformationFormat')
- debinfo.text = 'EditAndContinue'
- resourcecompile = ET.SubElement(compiles, 'ResourceCompile')
- ET.SubElement(resourcecompile, 'PreprocessorDefinitions')
- link = ET.SubElement(compiles, 'Link')
- # Put all language args here, too.
- extra_link_args = compiler.get_option_link_args(self.environment.coredata.compiler_options)
- extra_link_args += compiler.get_buildtype_linker_args(self.buildtype)
- for l in self.environment.coredata.external_link_args.values():
- for a in l:
- extra_link_args.append(a)
- for l in target.link_args:
- for a in l:
- extra_link_args.append(a)
- if len(extra_args) > 0:
- extra_args.append('%(AdditionalOptions)')
- ET.SubElement(link, "AdditionalOptions").text = ' '.join(extra_args)
-
- additional_links = []
- for t in target.link_targets:
- lobj = self.build.targets[t.get_id()]
- rel_path = self.relpath(lobj.subdir, target.subdir)
- linkname = os.path.join(rel_path, lobj.get_import_filename())
- additional_links.append(linkname)
- for o in self.flatten_object_list(target, down):
- assert(isinstance(o, str))
- additional_links.append(o)
- 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()
- addlibdir = ET.SubElement(link, 'AdditionalLibraryDirectories')
- addlibdir.text = '%(AdditionalLibraryDirectories)'
- subsys = ET.SubElement(link, 'SubSystem')
- subsys.text = subsystem
- gendeb = ET.SubElement(link, 'GenerateDebugInformation')
- gendeb.text = 'true'
- if isinstance(target, build.SharedLibrary):
- ET.SubElement(link, 'ImportLibrary').text = target.get_import_filename()
- 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')
- targetmachine.text = 'MachineX86'
-
- if len(headers) + len(gen_hdrs) > 0:
- inc_hdrs = ET.SubElement(root, 'ItemGroup')
- for h in headers:
- relpath = h.rel_to_builddir(proj_to_src_root)
- ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath)
- for h in gen_hdrs:
- if isinstance(h, str):
- relpath = h
- else:
- relpath = h.rel_to_builddir(proj_to_src_root)
- ET.SubElement(inc_hdrs, 'CLInclude', Include = relpath)
- if len(sources) + len(gen_src) > 0:
- inc_src = ET.SubElement(root, 'ItemGroup')
- for s in sources:
- relpath = s.rel_to_builddir(proj_to_src_root)
- ET.SubElement(inc_src, 'CLCompile', Include=relpath)
- for s in gen_src:
- relpath = self.relpath(s, target.subdir)
- ET.SubElement(inc_src, 'CLCompile', Include=relpath)
- ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets')
- # Reference the regen target.
- ig = ET.SubElement(root, 'ItemGroup')
- pref = ET.SubElement(ig, 'ProjectReference', Include=os.path.join(self.environment.get_build_dir(), 'REGEN.vcxproj'))
- ET.SubElement(pref, 'Project').text = self.environment.coredata.regen_guid
- tree = ET.ElementTree(root)
- tree.write(ofname, encoding='utf-8', xml_declaration=True)
- # ElementTree can not do prettyprinting so do it manually
- doc = xml.dom.minidom.parse(ofname)
- open(ofname, 'w').write(doc.toprettyxml())
- # World of horror! Python insists on not quoting quotes and
- # fixing the escaped &quot; into &amp;quot; whereas MSVS
- # requires quoted but not fixed elements. Enter horrible hack.
- txt = open(ofname, 'r').read()
- open(ofname, 'w').write(txt.replace('&amp;quot;', '&quot;'))
-
- 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 = 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
- 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'
- 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 = 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'
- script_root = self.environment.get_script_dir()
- regen_script = os.path.join(script_root, 'regen_checker.py')
- private_dir = self.environment.get_scratch_dir()
- cmd_templ = '''setlocal
-"%s" "%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')
- custombuild = ET.SubElement(igroup, 'CustomBuild', Include='meson-private/regen.rule')
- message = ET.SubElement(custombuild, 'Message')
- message.text = 'Checking whether solution needs to be regenerated.'
- ET.SubElement(custombuild, 'Command').text = cmd_templ % \
- (sys.executable, regen_script, private_dir)
- ET.SubElement(custombuild, 'Outputs').text = os.path.join(self.environment.get_scratch_dir(), 'regen.stamp')
- deps = self.get_regen_filelist()
- depstr = ';'.join([os.path.join(self.environment.get_source_dir(), d) for d in deps])
- ET.SubElement(custombuild, 'AdditionalInputs').text = depstr
- ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets')
- ET.SubElement(root, 'ImportGroup', Label='ExtensionTargets')
- tree = ET.ElementTree(root)
- tree.write(ofname, encoding='utf-8', xml_declaration=True)
-
- 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 = 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
- 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'
- 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')
- script_root = self.environment.get_script_dir()
- test_script = os.path.join(script_root, 'meson_test.py')
- test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat')
- cmd_templ = '''setlocal
-"%s" "%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'''
- ET.SubElement(postbuild, 'Command').text = cmd_templ % (sys.executable, test_script, test_data)
- ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets')
- tree = ET.ElementTree(root)
- tree.write(ofname, encoding='utf-8', xml_declaration=True)
- datafile = open(test_data, 'wb')
- self.serialise_tests()
- datafile.close()
- # ElementTree can not do prettyprinting so do it manually
- #doc = xml.dom.minidom.parse(ofname)
- #open(ofname, 'w').write(doc.toprettyxml())
diff --git a/meson/wrap/wrap.py b/meson/wrap/wrap.py
deleted file mode 100644
index 2818fa0..0000000
--- a/meson/wrap/wrap.py
+++ /dev/null
@@ -1,212 +0,0 @@
-# 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 urllib.request, os, hashlib, shutil
-import subprocess
-import sys
-
-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/'
-
-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 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 = {}
- ifile = open(fname)
- first = ifile.readline().strip()
-
- if first == '[wrap-file]':
- self.type = 'file'
- elif first == '[wrap-git]':
- self.type = 'git'
- 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):
- self.subdir_root = subdir_root
- self.cachedir = os.path.join(self.subdir_root, 'packagecache')
-
- def resolve(self, packagename):
- fname = os.path.join(self.subdir_root, packagename + '.wrap')
- dirname = os.path.join(self.subdir_root, packagename)
- if not os.path.isfile(fname):
- if os.path.isdir(dirname):
- # No wrap file but dir exists -> user put it there manually.
- return packagename
- return None
- 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)
- else:
- raise RuntimeError('Unreachable code.')
- return p.get('directory')
-
- 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:
- if revno.lower() == 'head':
- subprocess.check_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)
-
-
- def get_data(self, url):
- blocksize = 10*1024
- if url.startswith('https://wrapdb.mesonbuild.com'):
- resp = open_wrapdburl(url)
- else:
- resp = urllib.request.urlopen(url)
- dlsize = int(resp.info()['Content-Length'])
- print('Download size:', dlsize)
- print('Downloading: ', end='')
- sys.stdout.flush()
- printed_dots = 0
- blocks = []
- downloaded = 0
- while True:
- block = resp.read(blocksize)
- if block == b'':
- break
- downloaded += len(block)
- blocks.append(block)
- ratio = int(downloaded/dlsize * 10)
- while printed_dots < ratio:
- print('.', end='')
- sys.stdout.flush()
- printed_dots += 1
- print('')
- resp.close()
- return b''.join(blocks)
-
- 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.')
- return
- srcurl = p.get('source_url')
- mlog.log('Dowloading', mlog.bold(packagename), 'from', mlog.bold(srcurl))
- srcdata = self.get_data(srcurl)
- dhash = self.get_hash(srcdata)
- expected = p.get('source_hash')
- if dhash != expected:
- raise RuntimeError('Incorrect hash for source %s:\n %s expected\n %s actual.' % (packagename, expected, dhash))
- open(ofname, 'wb').write(srcdata)
- if p.has_patch():
- purl = p.get('patch_url')
- mlog.log('Downloading patch from', mlog.bold(purl))
- pdata = self.get_data(purl)
- phash = self.get_hash(pdata)
- expected = p.get('patch_hash')
- if phash != expected:
- raise RuntimeError('Incorrect hash for patch %s:\n %s expected\n %s actual' % (packagename, expected, phash))
- open(os.path.join(self.cachedir, p.get('patch_filename')), 'wb').write(pdata)
- else:
- mlog.log('Package does not require patch.')
-
- def extract_package(self, package):
- if sys.version_info < (3, 5):
- try:
- import lzma
- del lzma
- try:
- shutil.register_unpack_format('xztar', ['.tar.xz', '.txz'], shutil._unpack_tarfile, [], "xz'ed tar-file")
- except shutil.RegistryError:
- pass
- except ImportError:
- 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():
- shutil.unpack_archive(os.path.join(self.cachedir, package.get('patch_filename')), self.subdir_root)
diff --git a/meson/wrap/wraptool.py b/meson/wrap/wraptool.py
deleted file mode 100755
index d2f0a28..0000000
--- a/meson/wrap/wraptool.py
+++ /dev/null
@@ -1,200 +0,0 @@
-#!/usr/bin/env python3
-
-# 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
-
-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 <command> [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
-
-'''
-
-
-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()
- open(wrapfile, 'wb').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
- open(wrapfile, 'wb').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 len(versions) == 0:
- 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 status():
- print('Subproject status')
- for w in glob('subprojects/*.wrap'):
- name = os.path.split(w)[1][:-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 len(sys.argv) < 1 or sys.argv[0] == '-h' or sys.argv[1] == '--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 == 'status':
- status()
- else:
- print('Unknown command', command)
- return 1
- return 0
-
-if __name__ == '__main__':
- sys.exit(run(sys.argv[1:]))
diff --git a/meson/xcodebackend.py b/meson/xcodebackend.py
deleted file mode 100644
index 8ac3f67..0000000
--- a/meson/xcodebackend.py
+++ /dev/null
@@ -1,775 +0,0 @@
-# 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.
-
-from . import backends, build
-from . import mesonlib
-import uuid, os, sys
-
-from .coredata import MesonException
-
-class XCodeBackend(backends.Backend):
- def __init__(self, build):
- super().__init__(build)
- 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
- self.serialise_tests()
- 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_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')
- self.ofile = open(self.proj_file, 'w')
- 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_group()
- self.generate_pbx_native_target()
- self.generate_pbx_project()
- self.generate_pbx_shell_build_phase()
- 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):
- self.buildphasemap = {}
- for t in self.build.targets:
- self.buildphasemap[t] = 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_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 s in t.sources:
- 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')
- 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.split(fname)[-1]
- 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 = t.get_filename()
- elif isinstance(t, build.SharedLibrary):
- # OSX has a completely different shared library
- # naming scheme so do this manually.
- typestr = self.get_xcodetype('dummy.dylib')
- path = t.get_osx_filename()
- 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_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()
- 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.indent_level-=1
- self.write_line(');')
- self.write_line('sourceTree = "<group>";')
- 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 = "<group>";')
- 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 = "<group>";')
- 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 = "<group>";')
- 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 = "<group>";')
- 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 = "<group>";')
- 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
- self.write_line('%s /* Sources */,' % self.buildphasemap[tname])
- 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_basename()]
- 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):
- 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')
- test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat')
- cmd = [sys.executable, 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():
- self.write_line('%s /* Sources */ = {' % self.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 = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk";')
- 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_osx_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_name + '.' + dylib_version
- else:
- product_name = target_name
- 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')