aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml4
-rw-r--r--authors.txt1
-rw-r--r--docs/markdown/Reference-manual.md17
-rw-r--r--mesonbuild/backend/backends.py4
-rw-r--r--mesonbuild/backend/ninjabackend.py12
-rw-r--r--mesonbuild/backend/vs2010backend.py2
-rw-r--r--mesonbuild/build.py43
-rw-r--r--mesonbuild/dependencies.py30
-rw-r--r--mesonbuild/interpreter.py70
-rw-r--r--mesonbuild/mintro.py6
-rw-r--r--setup.py10
-rw-r--r--test cases/common/105 find program path/meson.build9
-rwxr-xr-x[-rw-r--r--]test cases/common/105 find program path/program.py0
-rw-r--r--test cases/frameworks/14 doxygen/installed_files.txt4
-rw-r--r--test cases/frameworks/5 protocol buffers/asubdir/defs.proto3
-rw-r--r--test cases/frameworks/5 protocol buffers/asubdir/main.cpp9
-rw-r--r--test cases/frameworks/5 protocol buffers/asubdir/meson.build8
-rw-r--r--test cases/frameworks/5 protocol buffers/meson.build2
-rw-r--r--test cases/linuxlike/3 linker script/bob.map.in6
-rw-r--r--test cases/linuxlike/3 linker script/copy.py5
-rw-r--r--test cases/linuxlike/3 linker script/meson.build48
-rw-r--r--test cases/linuxlike/3 linker script/sub/foo.map6
-rw-r--r--test cases/linuxlike/3 linker script/sub/meson.build6
23 files changed, 229 insertions, 76 deletions
diff --git a/.travis.yml b/.travis.yml
index fbb11ac..5f4318d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -31,13 +31,13 @@ matrix:
before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install ninja python3; fi
- - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker pull jpakkane/mesonci:yakkety; fi
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker pull jpakkane/mesonci:zesty; fi
# We need to copy the current checkout inside the Docker container,
# because it has the MR id to be tested checked out.
script:
- - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo FROM jpakkane/mesonci:yakkety > Dockerfile; fi
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo FROM jpakkane/mesonci:zesty > Dockerfile; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo ADD . /root >> Dockerfile; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker build -t withgit .; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run withgit /bin/sh -c "cd /root && TRAVIS=true CC=$CC CXX=$CXX OBJC=$CC OBJCXX=$CXX ./run_tests.py -- $MESON_ARGS"; fi
diff --git a/authors.txt b/authors.txt
index 1cfcad7..8a02848 100644
--- a/authors.txt
+++ b/authors.txt
@@ -84,3 +84,4 @@ Michael Olbrich
Ernestas Kulik
Thomas Hindoe Paaboel Andersen
Paolo Borelli
+Mike Gilbert
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 9c4df7e..8d690de 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -233,7 +233,7 @@ Executable supports the following keyword arguments. Note that just like the pos
- `<languagename>_pch` precompiled header file to use for the given language
- `<languagename>_args` compiler flags to use for the given language; eg: `cpp_args` for C++
- `link_args` flags to use during linking. You can use UNIX-style flags here for all platforms.
-- `link_depends` an extra file in the source tree that the link step depends on such as a symbol visibility map. The purpose is to automatically trigger a re-link (but not a re-compile) of the target when this file changes.
+- `link_depends` strings, files, or custom targets the link step depends on such as a symbol visibility map. The purpose is to automatically trigger a re-link (but not a re-compile) of the target when this file changes.
- `include_directories` one or more objects created with the `include_directories` function
- `dependencies` one or more objects created with [`dependency`](#dependency) or [`find_library`](#compiler-object) (for external deps) or [`declare_dependency`](#declare_dependency) (for deps built by the project)
- `gui_app` when set to true flags this target as a GUI application on platforms where this makes a difference (e.g. Windows)
@@ -266,6 +266,16 @@ Meson will also autodetect scripts with a shebang line and run them with the exe
`program_name2` and later positional arguments are used as fallback strings to search for. This is meant to be used for cases where the program may have many alternative names, such as `foo` and `foo.py`. The function will check for the arguments one by one and the first one that is found is returned. Meson versions earlier than 0.37.0 only accept one argument.
+If you need to check for a program in a non-standard location, you can just pass an absolute path to `find_program`, e.g.
+```
+setcap = find_program('setcap', '/usr/sbin/setcap', '/sbin/setcap', required : false)
+```
+
+It is also possible to pass an array to `find_program` in case you need to construct the set of paths to search on the fly:
+```
+setcap = find_program(['setcap', '/usr/sbin/setcap', '/sbin/setcap'], required : false)
+```
+
If none of the programs are found, Meson will abort. You can tell it not to by setting the keyword argument `required` to false, and then use the `.found()` method on the returned object to check whether it was found or not.
The returned object also has methods that are documented in the [object methods section](#external-program-object) below.
@@ -318,6 +328,7 @@ In addition to the above substitutions, the `arguments` keyword argument also ac
- `@OUTPUT@`: the full path to the output file
- `@INPUT@`: the full path to the input file
- `@SOURCE_DIR@`: the full path to the root of the source tree
+- `@CURRENT_SOURCE_DIR@`: this is the directory where the currently processed meson.build is located in
- `@BUILD_DIR@`: the full path to the root of the build dir where the output will be placed
NOTE: Generators should only be used for outputs that will ***only*** be used as inputs for a [build target](#build_target) or a [custom target](#custom_target). When you use the processed output of a generator in multiple targets, the generator will be run multiple times to create outputs for each target. Each output will be created in a target-private directory `@BUILD_DIR@`.
@@ -524,7 +535,9 @@ Project supports the following keyword arguments.
- `subproject_dir` specifies the top level directory name that holds Meson subprojects. This is only meant as a compatibility option for existing code bases that house their embedded source code in a custom directory. All new projects should not set this but instead use the default value. It should be noted that this keyword argument is ignored inside subprojects. There can be only one subproject dir and it is set in the top level Meson file.
- - `meson_version` takes a string describing which Meson version the project requires. Usually something like `>0.28.0`. Similarly you can specify the license(s) the code is under with the `license` keyword argument. Usually this would be something like `license : 'GPL2+'`, but if the code has multiple licenses you can specify them as an array like this: `license : ['proprietary', 'GPL3']`. Note that the text is informal and is only written to the dependency manifest. Meson does not do any license validation, you are responsible for verifying that you abide by all licensing terms.
+ - `meson_version` takes a string describing which Meson version the project requires. Usually something like `>0.28.0`.
+
+ - `license` takes a string or array of strings describing the license(s) the code is under. Usually this would be something like `license : 'GPL2+'`, but if the code has multiple licenses you can specify them as an array like this: `license : ['proprietary', 'GPL3']`. Note that the text is informal and is only written to the dependency manifest. Meson does not do any license validation, you are responsible for verifying that you abide by all licensing terms.
- `default_options` takes an array of strings. The strings are in the form `key=value` and have the same format as options to `mesonconf`. For example to set the default project type you would set this: `default_options : ['buildtype=debugoptimized']`. Note that these settings are only used when running Meson for the first time. Global options such as `buildtype` can only be specified in the master project, settings in subprojects are ignored. Project specific options are used normally even in subprojects.
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 5bb58f5..419d04f 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -149,6 +149,10 @@ class Backend:
dirname = 'meson-out'
return dirname
+ def get_target_source_dir(self, target):
+ dirname = os.path.join(self.build_to_src, self.get_target_dir(target))
+ 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
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index dad752b..bbae408 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1660,6 +1660,7 @@ rule FORTRAN_DEP_HACK
outfilelist = genlist.get_outputs()
base_args = generator.get_arglist()
extra_dependencies = [os.path.join(self.build_to_src, i) for i in genlist.extra_depends]
+ source_target_dir = self.get_target_source_dir(target)
for i in range(len(infilelist)):
if len(generator.outputs) == 1:
sole_output = os.path.join(self.get_target_private_dir(target), outfilelist[i])
@@ -1686,6 +1687,7 @@ rule FORTRAN_DEP_HACK
relout = self.get_target_private_dir(target)
args = [x.replace("@SOURCE_DIR@", self.build_to_src).replace("@BUILD_DIR@", relout)
for x in args]
+ args = [x.replace("@CURRENT_SOURCE_DIR@", source_target_dir) for x in args]
args = [x.replace("@SOURCE_ROOT@", self.build_to_src).replace("@BUILD_ROOT@", '.')
for x in args]
cmdlist = exe_arr + self.replace_extra_args(args, genlist)
@@ -2314,8 +2316,8 @@ rule FORTRAN_DEP_HACK
# current compiler.
commands = commands.to_native()
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]
+ dep_targets.extend([self.get_dependency_filename(t)
+ for t in target.link_depends])
elem = NinjaBuildElement(self.all_outputs, outname, linker_rule, obj_list)
elem.add_dep(dep_targets + custom_target_libraries)
elem.add_item('LINK_ARGS', commands)
@@ -2333,6 +2335,12 @@ rule FORTRAN_DEP_HACK
def get_dependency_filename(self, t):
if isinstance(t, build.SharedLibrary):
return os.path.join(self.get_target_private_dir(t), self.get_target_filename(t) + '.symbols')
+ elif isinstance(t, mesonlib.File):
+ if t.is_built:
+ return t.relative_name()
+ else:
+ return t.absolute_path(self.environment.get_source_dir(),
+ self.environment.get_build_dir())
return self.get_target_filename(t)
def generate_shlib_aliases(self, target, outdir):
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index e910a03..533edf0 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -120,6 +120,7 @@ class Vs2010Backend(backends.Backend):
custom_target_include_dirs = []
custom_target_output_files = []
target_private_dir = self.relpath(self.get_target_private_dir(target), self.get_target_dir(target))
+ source_target_dir = self.get_target_source_dir(target)
down = self.target_to_build_root(target)
for genlist in target.get_generated_sources():
if isinstance(genlist, build.CustomTarget):
@@ -154,6 +155,7 @@ class Vs2010Backend(backends.Backend):
args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir())
.replace("@BUILD_DIR@", target_private_dir)
for x in args]
+ args = [x.replace("@CURRENT_SOURCE_DIR@", source_target_dir) for x in args]
args = [x.replace("@SOURCE_ROOT@", self.environment.get_source_dir())
.replace("@BUILD_ROOT@", self.environment.get_build_dir())
for x in args]
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 06e6156..0d58394 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -42,6 +42,7 @@ known_basic_kwargs = {'install': True,
'dependencies': True,
'install_dir': True,
'main_class': True,
+ 'name_suffix': True,
'gui_app': True,
'extra_files': True,
'install_rpath': True,
@@ -62,7 +63,6 @@ known_lib_kwargs = known_basic_kwargs.copy()
known_lib_kwargs.update({'version': True, # Only for shared libs
'soversion': True, # Only for shared libs
'name_prefix': True,
- 'name_suffix': True,
'vs_module_defs': True, # Only for shared libs
'vala_header': True,
'vala_vapi': True,
@@ -503,6 +503,34 @@ class BuildTarget(Target):
assert(len(self.compilers) == 1)
return
+ def process_link_depends(self, sources, environment):
+ """Process the link_depends keyword argument.
+
+ This is designed to handle strings, Files, and the output of Custom
+ Targets. Notably it doesn't handle generator() returned objects, since
+ adding them as a link depends would inherently cause them to be
+ generated twice, since the output needs to be passed to the ld_args and
+ link_depends.
+ """
+ if not isinstance(sources, list):
+ sources = [sources]
+ for s in sources:
+ if hasattr(s, 'held_object'):
+ s = s.held_object
+
+ if isinstance(s, File):
+ self.link_depends.append(s)
+ elif isinstance(s, str):
+ self.link_depends.append(
+ File.from_source_file(environment.source_dir, self.subdir, s))
+ elif hasattr(s, 'get_outputs'):
+ self.link_depends.extend(
+ [File.from_built_file(s.subdir, p) for p in s.get_outputs()])
+ else:
+ raise InvalidArguments(
+ 'Link_depends arguments must be strings, Files, '
+ 'or a Custom Target, or lists thereof.')
+
def get_original_kwargs(self):
return self.kwargs
@@ -616,12 +644,7 @@ class BuildTarget(Target):
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.')
+ self.process_link_depends(kwargs.get('link_depends', []), environment)
# Target-specific include dirs must be added BEFORE include dirs from
# internal deps (added inside self.add_deps()) to override them.
inclist = kwargs.get('include_directories', [])
@@ -1264,13 +1287,11 @@ class SharedLibrary(BuildTarget):
self.vs_module_defs = File.from_absolute_file(path)
else:
self.vs_module_defs = File.from_source_file(environment.source_dir, self.subdir, path)
- # link_depends can be an absolute path or relative to self.subdir
- self.link_depends.append(path)
+ self.link_depends.append(self.vs_module_defs)
elif isinstance(path, File):
# When passing a generated file.
self.vs_module_defs = path
- # link_depends can be an absolute path or relative to self.subdir
- self.link_depends.append(path.absolute_path(environment.source_dir, environment.build_dir))
+ self.link_depends.append(path)
else:
raise InvalidArguments(
'Shared library vs_module_defs must be either a string, '
diff --git a/mesonbuild/dependencies.py b/mesonbuild/dependencies.py
index f6ca8c3..18d418e 100644
--- a/mesonbuild/dependencies.py
+++ b/mesonbuild/dependencies.py
@@ -465,8 +465,9 @@ class ExternalProgram:
@staticmethod
def _shebang_to_cmd(script):
"""
- Windows does not understand shebangs, so we check if the file has a
- shebang and manually parse it to figure out the interpreter to use
+ Check if the file has a shebang and manually parse it to figure out
+ the interpreter to use. This is useful if the script is not executable
+ or if we're on Windows (which does not understand shebangs).
"""
try:
with open(script) as f:
@@ -504,15 +505,17 @@ class ExternalProgram:
if os.path.exists(trial):
if self._is_executable(trial):
return [trial]
+ # Now getting desperate. Maybe it is a script file that is
+ # a) not chmodded executable, or
+ # b) we are on windows so they can't be directly executed.
+ return self._shebang_to_cmd(trial)
else:
- for ext in self.windows_exts:
- trial_ext = '{}.{}'.format(trial, ext)
- if os.path.exists(trial_ext):
- return [trial_ext]
- return False
- # Now getting desperate. Maybe it is a script file that is a) not chmodded
- # executable or b) we are on windows so they can't be directly executed.
- return self._shebang_to_cmd(trial)
+ if mesonlib.is_windows():
+ for ext in self.windows_exts:
+ trial_ext = '{}.{}'.format(trial, ext)
+ if os.path.exists(trial_ext):
+ return [trial_ext]
+ return False
def _search(self, name, search_dir):
'''
@@ -525,7 +528,8 @@ class ExternalProgram:
# Do a standard search in PATH
command = shutil.which(name)
if not mesonlib.is_windows():
- # On UNIX-like platforms, the standard PATH search is enough
+ # On UNIX-like platforms, shutil.which() is enough to find
+ # all executables whether in PATH or with an absolute path
return [command]
# HERE BEGINS THE TERROR OF WINDOWS
if command:
@@ -567,9 +571,9 @@ class ExternalProgram:
return self.command[:]
def get_path(self):
- # Assume that the last element is the full path to the script
- # If it's not a script, this will be an array of length 1
if self.found():
+ # Assume that the last element is the full path to the script or
+ # binary being run
return self.command[-1]
return None
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 0e3f039..80d482e 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -23,7 +23,7 @@ from . import compilers
from .wrap import wrap, WrapMode
from . import mesonlib
from .mesonlib import FileMode, Popen_safe, get_meson_script
-from .dependencies import InternalDependency, Dependency
+from .dependencies import InternalDependency, Dependency, ExternalProgram
from .interpreterbase import InterpreterBase
from .interpreterbase import check_stringlist, noPosargs, noKwargs, stringArgs
from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode
@@ -72,17 +72,19 @@ class TryRunResultHolder(InterpreterObject):
class RunProcess(InterpreterObject):
- def __init__(self, command_array, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False):
+ def __init__(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False):
super().__init__()
- pc, self.stdout, self.stderr = self.run_command(command_array, source_dir, build_dir, subdir, mesonintrospect, in_builddir)
+ if not isinstance(cmd, ExternalProgram):
+ raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
+ pc, self.stdout, self.stderr = self.run_command(cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir)
self.returncode = pc.returncode
self.methods.update({'returncode': self.returncode_method,
'stdout': self.stdout_method,
'stderr': self.stderr_method,
})
- def run_command(self, command_array, source_dir, build_dir, subdir, mesonintrospect, in_builddir):
- cmd_name = command_array[0]
+ def run_command(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir):
+ command_array = cmd.get_command() + args
env = {'MESON_SOURCE_ROOT': source_dir,
'MESON_BUILD_ROOT': build_dir,
'MESON_SUBDIR': subdir,
@@ -97,18 +99,6 @@ class RunProcess(InterpreterObject):
try:
return Popen_safe(command_array, 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 Popen_safe(command_array, 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 Popen_safe(command_array, env=child_env, cwd=cwd)
- except FileNotFoundError:
raise InterpreterException('Could not execute command "%s".' % cmd_name)
def returncode_method(self, args, kwargs):
@@ -250,7 +240,6 @@ class DependencyHolder(InterpreterObject):
def found_method(self, args, kwargs):
if self.held_object.type_name == 'internal':
return True
-
return self.held_object.found()
def version_method(self, args, kwargs):
@@ -1105,7 +1094,8 @@ class MesonMain(InterpreterObject):
if found.found():
self._found_source_scripts[key] = found
else:
- raise InterpreterException('Script {!r} not found'.format(name))
+ m = 'Script or command {!r} not found or not executable'
+ raise InterpreterException(m.format(name))
return build.RunScript(found.get_command(), args)
def add_install_script_method(self, args, kwargs):
@@ -1469,28 +1459,38 @@ class Interpreter(InterpreterBase):
raise InterpreterException('Not enough arguments')
cmd = args[0]
cargs = args[1:]
+ srcdir = self.environment.get_source_dir()
+ builddir = self.environment.get_build_dir()
+ m = 'must be a string, or the output of find_program(), files(), or ' \
+ 'configure_file(); not {!r}'
if isinstance(cmd, ExternalProgramHolder):
- cmd = cmd.get_command()
- elif isinstance(cmd, str):
- cmd = [cmd]
+ cmd = cmd.held_object
else:
- raise InterpreterException('First argument should be find_program() '
- 'or string, not {!r}'.format(cmd))
+ if isinstance(cmd, mesonlib.File):
+ cmd = cmd.absolute_path(srcdir, builddir)
+ elif not isinstance(cmd, str):
+ raise InterpreterException('First argument ' + m.format(cmd))
+ # Prefer scripts in the current source directory
+ search_dir = os.path.join(srcdir, self.subdir)
+ prog = ExternalProgram(cmd, silent=True, search_dir=search_dir)
+ if not prog.found():
+ raise InterpreterException('Program or command {!r} not found'
+ 'or not executable'.format(cmd))
+ cmd = prog
expanded_args = []
for a in mesonlib.flatten(cargs):
if isinstance(a, str):
expanded_args.append(a)
elif isinstance(a, mesonlib.File):
- if a.is_built:
- raise InterpreterException('Can not use generated files in run_command.')
- expanded_args.append(os.path.join(self.environment.get_source_dir(), str(a)))
+ expanded_args.append(a.absolute_path(srcdir, builddir))
+ elif isinstance(a, ExternalProgramHolder):
+ expanded_args.append(a.held_object.get_path())
else:
- raise InterpreterException('Run_command arguments must be strings or the output of files().')
- args = cmd + expanded_args
+ raise InterpreterException('Arguments ' + m.format(a))
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,
+ return RunProcess(cmd, expanded_args, srcdir, builddir, self.subdir,
get_meson_script(self.environment, 'mesonintrospect'), in_builddir)
@stringArgs
@@ -1846,7 +1846,7 @@ class Interpreter(InterpreterBase):
if progobj.found():
return progobj
if required and not progobj.found():
- raise InvalidArguments('Program "%s" not found.' % exename)
+ raise InvalidArguments('Program "%s" not found or not executable' % exename)
return progobj
def func_find_library(self, node, args, kwargs):
@@ -2217,10 +2217,12 @@ class Interpreter(InterpreterBase):
subdir = os.path.join(prev_subdir, args[0])
if os.path.isabs(subdir):
raise InvalidArguments('Subdir argument must be a relative path.')
- if subdir in self.visited_subdirs:
+ absdir = os.path.join(self.environment.get_source_dir(), subdir)
+ symlinkless_dir = os.path.realpath(absdir)
+ if symlinkless_dir in self.visited_subdirs:
raise InvalidArguments('Tried to enter directory "%s", which has already been visited.'
% subdir)
- self.visited_subdirs[subdir] = True
+ self.visited_subdirs[symlinkless_dir] = True
self.subdir = subdir
os.makedirs(os.path.join(self.environment.build_dir, subdir), exist_ok=True)
buildfilename = os.path.join(self.subdir, environment.build_filename)
@@ -2424,7 +2426,7 @@ different subdirectory.
exe_wrapper.append(i)
elif isinstance(i, dependencies.ExternalProgram):
if not i.found():
- raise InterpreterException('Tried to use non-found external executable.')
+ raise InterpreterException('Tried to use non-found executable.')
exe_wrapper += i.get_command()
else:
raise InterpreterException('Exe wrapper can only contain strings or external binaries.')
diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py
index 6eab76e..c12c4dd 100644
--- a/mesonbuild/mintro.py
+++ b/mesonbuild/mintro.py
@@ -65,8 +65,14 @@ def determine_installed_path(target, installdata):
def list_installed(installdata):
res = {}
if installdata is not None:
+ for path, installdir, aliases, unknown1, unknown2 in installdata.targets:
+ res[os.path.join(installdata.build_dir, path)] = os.path.join(installdata.prefix, installdir, os.path.basename(path))
for path, installpath, unused_prefix in installdata.data:
res[path] = os.path.join(installdata.prefix, installpath)
+ for path, installdir in installdata.headers:
+ res[path] = os.path.join(installdata.prefix, installdir, os.path.basename(path))
+ for path, installpath in installdata.man:
+ res[path] = os.path.join(installdata.prefix, installpath)
print(json.dumps(res))
diff --git a/setup.py b/setup.py
index 300ddf1..8996772 100644
--- a/setup.py
+++ b/setup.py
@@ -16,8 +16,6 @@
import os
import sys
-from distutils.dir_util import mkpath
-from distutils.file_util import copy_file
from mesonbuild.coredata import version
@@ -41,16 +39,20 @@ class install_scripts(orig):
super().run()
return
+ if not self.skip_build:
+ self.run_command('build_scripts')
self.outfiles = []
if not self.dry_run:
- mkpath(self.install_dir)
+ self.mkpath(self.install_dir)
# We want the files to be installed without a suffix on Unix
for infile in self.get_inputs():
+ infile = os.path.basename(infile)
+ in_built = os.path.join(self.build_dir, infile)
in_stripped = infile[:-3] if infile.endswith('.py') else infile
outfile = os.path.join(self.install_dir, in_stripped)
# NOTE: Mode is preserved by default
- copy_file(infile, outfile, dry_run=self.dry_run)
+ self.copy_file(in_built, outfile)
self.outfiles.append(outfile)
setup(name='meson',
diff --git a/test cases/common/105 find program path/meson.build b/test cases/common/105 find program path/meson.build
index e1e6d2e..0a81249 100644
--- a/test cases/common/105 find program path/meson.build
+++ b/test cases/common/105 find program path/meson.build
@@ -1,9 +1,6 @@
project('find program', 'c')
-python = find_program('python3', required : false)
-if not python.found()
- python = find_program('python')
-endif
+python = import('python3').find_python()
# Source file via string
prog = find_program('program.py')
@@ -14,8 +11,8 @@ py = configure_file(input : 'program.py',
output : 'builtprogram.py',
configuration : configuration_data())
-foreach f : [prog, find_program(py), find_program(progf)]
- ret = run_command(python, f.path())
+foreach f : [prog, progf, py, find_program(py), find_program(progf)]
+ ret = run_command(python, f)
assert(ret.returncode() == 0, 'can\'t manually run @0@'.format(prog.path()))
assert(ret.stdout().strip() == 'Found', 'wrong output from manually-run @0@'.format(prog.path()))
diff --git a/test cases/common/105 find program path/program.py b/test cases/common/105 find program path/program.py
index 2ebc564..2ebc564 100644..100755
--- a/test cases/common/105 find program path/program.py
+++ b/test cases/common/105 find program path/program.py
diff --git a/test cases/frameworks/14 doxygen/installed_files.txt b/test cases/frameworks/14 doxygen/installed_files.txt
index 72afb2e..e4f70e3 100644
--- a/test cases/frameworks/14 doxygen/installed_files.txt
+++ b/test cases/frameworks/14 doxygen/installed_files.txt
@@ -1,6 +1,4 @@
usr/share/doc/spede/html/annotated.html
-usr/share/doc/spede/html/arrowdown.png
-usr/share/doc/spede/html/arrowright.png
usr/share/doc/spede/html/bc_s.png
usr/share/doc/spede/html/bdwn.png
usr/share/doc/spede/html/classComedy_1_1Comedian.html
@@ -29,6 +27,8 @@ usr/share/doc/spede/html/functions_func.html
usr/share/doc/spede/html/hierarchy.html
usr/share/doc/spede/html/index.html
usr/share/doc/spede/html/jquery.js
+usr/share/doc/spede/html/menu.js
+usr/share/doc/spede/html/menudata.js
usr/share/doc/spede/html/namespaceComedy.html
usr/share/doc/spede/html/namespacemembers.html
usr/share/doc/spede/html/namespacemembers_func.html
diff --git a/test cases/frameworks/5 protocol buffers/asubdir/defs.proto b/test cases/frameworks/5 protocol buffers/asubdir/defs.proto
new file mode 100644
index 0000000..f795651
--- /dev/null
+++ b/test cases/frameworks/5 protocol buffers/asubdir/defs.proto
@@ -0,0 +1,3 @@
+message Dummy {
+ required string text = 1;
+}
diff --git a/test cases/frameworks/5 protocol buffers/asubdir/main.cpp b/test cases/frameworks/5 protocol buffers/asubdir/main.cpp
new file mode 100644
index 0000000..f6566d5
--- /dev/null
+++ b/test cases/frameworks/5 protocol buffers/asubdir/main.cpp
@@ -0,0 +1,9 @@
+#include "defs.pb.h"
+
+int main(int argc, char **argv) {
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+ Dummy *d = new Dummy;
+ delete d;
+ google::protobuf::ShutdownProtobufLibrary();
+ return 0;
+}
diff --git a/test cases/frameworks/5 protocol buffers/asubdir/meson.build b/test cases/frameworks/5 protocol buffers/asubdir/meson.build
new file mode 100644
index 0000000..9727165
--- /dev/null
+++ b/test cases/frameworks/5 protocol buffers/asubdir/meson.build
@@ -0,0 +1,8 @@
+subdirgen = generator(protoc, \
+ output : ['@BASENAME@.pb.cc', '@BASENAME@.pb.h'],
+ arguments : ['--proto_path=@CURRENT_SOURCE_DIR@', '--cpp_out=@BUILD_DIR@', '@INPUT@'])
+
+generated = subdirgen.process('defs.proto')
+e = executable('subdir-prog', 'main.cpp', generated,
+ dependencies : dep)
+test('subdir-prototest', e)
diff --git a/test cases/frameworks/5 protocol buffers/meson.build b/test cases/frameworks/5 protocol buffers/meson.build
index c99e0a8..58666f9 100644
--- a/test cases/frameworks/5 protocol buffers/meson.build
+++ b/test cases/frameworks/5 protocol buffers/meson.build
@@ -16,3 +16,5 @@ generated = gen.process('defs.proto')
e = executable('prog', 'main.cpp', generated,
dependencies : dep)
test('prototest', e)
+
+subdir('asubdir')
diff --git a/test cases/linuxlike/3 linker script/bob.map.in b/test cases/linuxlike/3 linker script/bob.map.in
new file mode 100644
index 0000000..f695e4a
--- /dev/null
+++ b/test cases/linuxlike/3 linker script/bob.map.in
@@ -0,0 +1,6 @@
+V1_0_0 {
+ global:
+ "@in@";
+ local:
+ *;
+};
diff --git a/test cases/linuxlike/3 linker script/copy.py b/test cases/linuxlike/3 linker script/copy.py
new file mode 100644
index 0000000..49e7a85
--- /dev/null
+++ b/test cases/linuxlike/3 linker script/copy.py
@@ -0,0 +1,5 @@
+import shutil
+import sys
+
+if __name__ == '__main__':
+ shutil.copy(sys.argv[1], sys.argv[2])
diff --git a/test cases/linuxlike/3 linker script/meson.build b/test cases/linuxlike/3 linker script/meson.build
index 30761c6..63765e7 100644
--- a/test cases/linuxlike/3 linker script/meson.build
+++ b/test cases/linuxlike/3 linker script/meson.build
@@ -1,8 +1,56 @@
project('linker script', 'c')
+# Static map file
mapfile = 'bob.map'
vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile)
l = shared_library('bob', 'bob.c', link_args : vflag, link_depends : mapfile)
e = executable('prog', 'prog.c', link_with : l)
test('core', e)
+
+# configure_file
+conf = configuration_data()
+conf.set('in', 'bobMcBob')
+m = configure_file(
+ input : 'bob.map.in',
+ output : 'bob-conf.map',
+ configuration : conf,
+)
+vflag = '-Wl,--version-script,@0@'.format(m)
+
+l = shared_library('bob-conf', 'bob.c', link_args : vflag, link_depends : m)
+e = executable('prog-conf', 'prog.c', link_with : l)
+test('core', e)
+
+# custom_target
+python = find_program('python3')
+m = custom_target(
+ 'bob-ct.map',
+ command : [python, '@INPUT0@', '@INPUT1@', 'bob-ct.map'],
+ input : ['copy.py', 'bob.map'],
+ output : 'bob-ct.map',
+ depend_files : 'bob.map',
+)
+vflag = '-Wl,--version-script,@0@'.format(m.full_path())
+
+l = shared_library('bob-ct', ['bob.c', m], link_args : vflag, link_depends : m)
+e = executable('prog-ct', 'prog.c', link_with : l)
+test('core', e)
+
+# File
+mapfile = files('bob.map')
+vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile[0])
+
+l = shared_library('bob-files', 'bob.c', link_args : vflag, link_depends : mapfile)
+e = executable('prog-files', 'prog.c', link_with : l)
+test('core', e)
+
+subdir('sub')
+
+# With map file in subdir
+mapfile = 'sub/foo.map'
+vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile)
+
+l = shared_library('bar', 'bob.c', link_args : vflag, link_depends : mapfile)
+e = executable('prog-bar', 'prog.c', link_with : l)
+test('core', e)
diff --git a/test cases/linuxlike/3 linker script/sub/foo.map b/test cases/linuxlike/3 linker script/sub/foo.map
new file mode 100644
index 0000000..e07a780
--- /dev/null
+++ b/test cases/linuxlike/3 linker script/sub/foo.map
@@ -0,0 +1,6 @@
+V1_0_0 {
+ global:
+ "bobMcBob";
+ local:
+ *;
+};
diff --git a/test cases/linuxlike/3 linker script/sub/meson.build b/test cases/linuxlike/3 linker script/sub/meson.build
new file mode 100644
index 0000000..93199f3
--- /dev/null
+++ b/test cases/linuxlike/3 linker script/sub/meson.build
@@ -0,0 +1,6 @@
+mapfile = 'foo.map'
+vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile)
+
+l = shared_library('foo', '../bob.c', link_args : vflag, link_depends : mapfile)
+e = executable('prog-foo', '../prog.c', link_with : l)
+test('core', e)