aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Builtin-options.md8
-rw-r--r--docs/markdown/Users.md3
-rw-r--r--mesonbuild/compilers/cpp.py46
-rw-r--r--mesonbuild/dependencies/base.py92
-rw-r--r--mesonbuild/dependencies/boost.py2
-rw-r--r--mesonbuild/dependencies/data/CMakeListsLLVM.txt95
-rw-r--r--mesonbuild/dependencies/dev.py74
-rw-r--r--mesonbuild/interpreter.py4
-rw-r--r--mesonbuild/msetup.py2
-rw-r--r--setup.py2
-rw-r--r--test cases/common/161 config tool variable/meson.build2
-rw-r--r--test cases/common/91 default options/meson.build11
-rw-r--r--test cases/failing/97 custom target install data/Info.plist.cpp1
-rw-r--r--test cases/failing/97 custom target install data/meson.build11
-rw-r--r--test cases/failing/97 custom target install data/preproc.py13
-rw-r--r--test cases/frameworks/15 llvm/meson.build4
-rw-r--r--test cases/frameworks/2 gtest/meson.build2
-rw-r--r--test cases/frameworks/3 gmock/meson.build2
-rw-r--r--test cases/unit/47 native file binary/meson.build2
19 files changed, 325 insertions, 51 deletions
diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md
index d25d7ab..db3af64 100644
--- a/docs/markdown/Builtin-options.md
+++ b/docs/markdown/Builtin-options.md
@@ -134,7 +134,7 @@ compiler being used:
| cpp_link_args| | free-form comma-separated list | C++ link arguments to use |
| cpp_std | none | none, c++98, c++03, c++11, c++14, c++17, <br/>c++1z, gnu++03, gnu++11, gnu++14, gnu++17, gnu++1z, <br/> vc++14, vc++17, vc++latest | C++ language standard to use |
| cpp_debugstl | false | true, false | C++ STL debug mode |
-| cpp_eh | sc | none, a, s, sc | C++ exception handling type |
+| cpp_eh | default | none, default, a, s, sc | C++ exception handling type |
| cpp_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against |
The default values of `c_winlibs` and `cpp_winlibs` are in compiler-specific
@@ -144,3 +144,9 @@ shell32, ole32, oleaut32, uuid, comdlg32, advapi32.
c_args, cpp_args, c_link_args, and cpp_link_args only affect native builds,
when cross compiling they will not be applied to binaries or libraries
targeting the host system, only those being run on the build system.
+
+When using MSVC, `cpp_eh=none` will result in no exception flags being passed,
+while the `cpp_eh=[value]` will result in `/EH[value]`.
+Since *0.51.0* `cpp_eh=default` will result in `/EHsc` on MSVC. When using
+gcc-style compilers, nothing is passed (allowing exceptions to work), while
+`cpp_eh=none` passes `-fno-exceptions`.
diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md
index c0f82f5..acb5161 100644
--- a/docs/markdown/Users.md
+++ b/docs/markdown/Users.md
@@ -37,6 +37,7 @@ listed in the [`meson` GitHub topic](https://github.com/topics/meson).
- [GNOME Software](https://gitlab.gnome.org/GNOME/gnome-software), an app store for GNOME
- [GNOME Twitch](https://github.com/vinszent/gnome-twitch), an app for viewing Twitch streams on GNOME desktop
- [GNOME Usage](https://gitlab.gnome.org/GNOME/gnome-usage), a GNOME application for visualizing system resources
+ - [GNU FriBidi](https://github.com/fribidi/fribidi), the open source implementation of the Unicode Bidirectional Algorithm
- [Graphene](https://ebassi.github.io/graphene/), a thin type library for graphics
- [Grilo](https://git.gnome.org/browse/grilo) and [Grilo plugins](https://git.gnome.org/browse/grilo-plugins), the Grilo multimedia framework
- [GStreamer](https://cgit.freedesktop.org/gstreamer/gstreamer/), multimedia framework (not the default yet)
@@ -47,6 +48,7 @@ listed in the [`meson` GitHub topic](https://github.com/topics/meson).
- [HexChat](https://github.com/hexchat/hexchat), a cross-platform IRC client in C
- [IGT](https://cgit.freedesktop.org/xorg/app/intel-gpu-tools/), Linux kernel graphics driver test suite
- [iSH](https://github.com/tbodt/ish), Linux shell for iOS
+ - [Janet](https://github.com/janet-lang/janet), a functional and imperative programming language and bytecode interpreter
- [json](https://github.com/nlohmann/json), JSON for Modern C++
- [JsonCpp](https://github.com/open-source-parsers/jsoncpp), a C++ library for interacting with JSON
- [Json-glib](https://gitlab.gnome.org/GNOME/json-glib), GLib-based JSON manipulation library
@@ -65,6 +67,7 @@ listed in the [`meson` GitHub topic](https://github.com/topics/meson).
lookup based on OpenStreetMap data
- [libspng](https://gitlab.com/randy408/libspng), a C library for reading and writing Portable Network Graphics (PNG)
format files
+ - [libui](https://github.com/andlabs/libui), a simple and portable (but not inflexible) GUI library in C that uses the native GUI technologies of each platform it supports
- [Libva](https://github.com/intel/libva), an implementation for the VA (VIdeo Acceleration) API
- [Libzim](https://github.com/openzim/libzim), the reference implementation for the ZIM file format
- [Marker](https://github.com/fabiocolacio/Marker), a GTK-3 markdown editor
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index 910a3e9..12644a2 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -149,7 +149,11 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
def get_options(self):
opts = CPPCompiler.get_options(self)
- opts.update({'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
+ opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh',
+ 'C++ exception handling type.',
+ ['none', 'default'],
+ 'default'),
+ 'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a',
'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'],
'none')})
@@ -160,6 +164,8 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
std = options['cpp_std']
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
+ if options['cpp_eh'].value == 'none':
+ args.append('-fno-exceptions')
return args
def get_option_link_args(self, options):
@@ -181,7 +187,11 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
def get_options(self):
opts = CPPCompiler.get_options(self)
- opts.update({'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
+ opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh',
+ 'C++ exception handling type.',
+ ['none', 'default'],
+ 'default'),
+ 'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17',
'gnu++98', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17'],
'none')})
@@ -192,6 +202,8 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
std = options['cpp_std']
if std.value != 'none':
args.append('-std=' + std.value)
+ if options['cpp_eh'].value == 'none':
+ args.append('-fno-exceptions')
return args
def get_option_link_args(self, options):
@@ -210,7 +222,11 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler):
def get_options(self):
opts = CPPCompiler.get_options(self)
- opts.update({'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
+ opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh',
+ 'C++ exception handling type.',
+ ['none', 'default'],
+ 'default'),
+ 'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a',
'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'],
'none'),
@@ -228,6 +244,8 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler):
std = options['cpp_std']
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
+ if options['cpp_eh'].value == 'none':
+ args.append('-fno-exceptions')
if options['cpp_debugstl'].value:
args.append('-D_GLIBCXX_DEBUG=1')
return args
@@ -258,7 +276,11 @@ class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler):
# It does not support c++/gnu++ 17 and 1z, but still does support 0x, 1y, and gnu++98.
def get_options(self):
opts = CPPCompiler.get_options(self)
- opts.update({'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
+ opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh',
+ 'C++ exception handling type.',
+ ['none', 'default'],
+ 'default'),
+ 'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
['none', 'c++98', 'c++03', 'c++0x', 'c++11', 'c++14', 'c++1y',
'gnu++98', 'gnu++03', 'gnu++0x', 'gnu++11', 'gnu++14', 'gnu++1y'],
'none'),
@@ -304,7 +326,11 @@ class IntelCPPCompiler(IntelCompiler, CPPCompiler):
c_stds += ['c++17']
if version_compare(self.version, '>=17.0.0'):
g_stds += ['gnu++14']
- opts.update({'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
+ opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh',
+ 'C++ exception handling type.',
+ ['none', 'default'],
+ 'default'),
+ 'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
['none'] + c_stds + g_stds,
'none'),
'cpp_debugstl': coredata.UserBooleanOption('cpp_debugstl',
@@ -321,6 +347,8 @@ class IntelCPPCompiler(IntelCompiler, CPPCompiler):
'gnu++03': 'gnu++98'
}
args.append('-std=' + remap_cpp03.get(std.value, std.value))
+ if options['cpp_eh'].value == 'none':
+ args.append('-fno-exceptions')
if options['cpp_debugstl'].value:
args.append('-D_GLIBCXX_DEBUG=1')
return args
@@ -339,8 +367,8 @@ class VisualStudioLikeCPPCompilerMixin:
def _get_options_impl(self, opts, cpp_stds: typing.List[str]):
opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh',
'C++ exception handling type.',
- ['none', 'a', 's', 'sc'],
- 'sc'),
+ ['none', 'a', 's', 'sc', 'default'],
+ 'default'),
'cpp_std': coredata.UserComboOption('cpp_std',
'C++ language standard to use',
cpp_stds,
@@ -354,7 +382,9 @@ class VisualStudioLikeCPPCompilerMixin:
args = []
eh = options['cpp_eh']
- if eh.value != 'none':
+ if eh.value == 'default':
+ args.append('/EHsc')
+ elif eh.value != 'none':
args.append('/EH' + eh.value)
vc_version_map = {
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 9664215..8f38d6c 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -25,6 +25,7 @@ import textwrap
import platform
import itertools
import ctypes
+import typing
from typing import Any, Dict, List, Tuple
from enum import Enum
from pathlib import Path, PurePath
@@ -34,7 +35,7 @@ from .. import mesonlib
from ..compilers import clib_langs
from ..environment import BinaryTable, Environment, MachineInfo
from ..mesonlib import MachineChoice, MesonException, OrderedSet, PerMachine
-from ..mesonlib import Popen_safe, version_compare_many, version_compare, listify
+from ..mesonlib import Popen_safe, version_compare_many, version_compare, listify, stringlistify, extract_as_list
from ..mesonlib import Version, LibType
# These must be defined in this file to avoid cyclical references.
@@ -73,6 +74,8 @@ class Dependency:
@classmethod
def _process_method_kw(cls, kwargs):
method = kwargs.get('method', 'auto')
+ if isinstance(method, DependencyMethods):
+ return method
if method not in [e.value for e in DependencyMethods]:
raise DependencyException('method {!r} is invalid'.format(method))
method = DependencyMethods(method)
@@ -176,6 +179,20 @@ class Dependency:
"""
raise RuntimeError('Unreachable code in partial_dependency called')
+ def _add_sub_dependency(self, dep_type: typing.Type['Dependency'], env: Environment,
+ kwargs: typing.Dict[str, typing.Any], *,
+ method: DependencyMethods = DependencyMethods.AUTO) -> None:
+ """Add an internal dependency of of the given type.
+
+ This method is intended to simplify cases of adding a dependency on
+ another dependency type (such as threads). This will by default set
+ the method back to auto, but the 'method' keyword argument can be
+ used to overwrite this behavior.
+ """
+ kwargs = kwargs.copy()
+ kwargs['method'] = method
+ self.ext_deps.append(dep_type(env, kwargs))
+
class InternalDependency(Dependency):
def __init__(self, version, incdirs, compile_args, link_args, libraries, whole_libraries, sources, ext_deps):
@@ -954,6 +971,24 @@ class CMakeDependency(ExternalDependency):
def _gen_exception(self, msg):
return DependencyException('Dependency {} not found: {}'.format(self.name, msg))
+ def _main_cmake_file(self) -> str:
+ return 'CMakeLists.txt'
+
+ def _extra_cmake_opts(self) -> List[str]:
+ return []
+
+ def _map_module_list(self, modules: List[Tuple[str, bool]]) -> List[Tuple[str, bool]]:
+ # Map the input module list to something else
+ # This function will only be executed AFTER the initial CMake
+ # interpreter pass has completed. Thus variables defined in the
+ # CMakeLists.txt can be accessed here.
+ return modules
+
+ def _original_module_name(self, module: str) -> str:
+ # Reverse the module mapping done by _map_module_list for
+ # one module
+ return module
+
def __init__(self, name: str, environment: Environment, kwargs, language=None):
super().__init__('cmake', environment, language, kwargs)
self.name = name
@@ -973,6 +1008,9 @@ class CMakeDependency(ExternalDependency):
# Where all CMake "build dirs" are located
self.cmake_root_dir = environment.scratch_dir
+ # List of successfully found modules
+ self.found_modules = []
+
# When finding dependencies for cross-compiling, we don't care about
# the 'native' CMake binary
# TODO: Test if this works as expected
@@ -1044,15 +1082,10 @@ class CMakeDependency(ExternalDependency):
if self.cmakeinfo is None:
raise self._gen_exception('Unable to obtain CMake system information')
- modules = kwargs.get('modules', [])
- cm_path = kwargs.get('cmake_module_path', [])
- cm_args = kwargs.get('cmake_args', [])
- if not isinstance(modules, list):
- modules = [modules]
- if not isinstance(cm_path, list):
- cm_path = [cm_path]
- if not isinstance(cm_args, list):
- cm_args = [cm_args]
+ modules = [(x, True) for x in stringlistify(extract_as_list(kwargs, 'modules'))]
+ modules += [(x, False) for x in stringlistify(extract_as_list(kwargs, 'optional_modules'))]
+ cm_path = stringlistify(extract_as_list(kwargs, 'cmake_module_path'))
+ cm_args = stringlistify(extract_as_list(kwargs, 'cmake_args'))
cm_path = [x if os.path.isabs(x) else os.path.join(environment.get_source_dir(), x) for x in cm_path]
if cm_path:
cm_args += ['-DCMAKE_MODULE_PATH={}'.format(';'.join(cm_path))]
@@ -1225,7 +1258,7 @@ class CMakeDependency(ExternalDependency):
return False
- def _detect_dep(self, name: str, modules: List[str], args: List[str]):
+ def _detect_dep(self, name: str, modules: List[Tuple[str, bool]], args: List[str]):
# Detect a dependency with CMake using the '--find-package' mode
# and the trace output (stderr)
#
@@ -1248,11 +1281,12 @@ class CMakeDependency(ExternalDependency):
# Prepare options
cmake_opts = ['--trace-expand', '-DNAME={}'.format(name), '-DARCHS={}'.format(';'.join(self.cmakeinfo['archs']))] + args + ['.']
+ cmake_opts += self._extra_cmake_opts()
if len(i) > 0:
cmake_opts = ['-G', i] + cmake_opts
# Run CMake
- ret1, out1, err1 = self._call_cmake(cmake_opts, 'CMakeLists.txt')
+ ret1, out1, err1 = self._call_cmake(cmake_opts, self._main_cmake_file())
# Current generator was successful
if ret1 == 0:
@@ -1310,6 +1344,11 @@ class CMakeDependency(ExternalDependency):
self.version = vers_raw[0]
self.version.strip('"\' ')
+ # Post-process module list. Used in derived classes to modify the
+ # module list (append prepend a string, etc.).
+ modules = self._map_module_list(modules)
+ autodetected_module_list = False
+
# Try guessing a CMake target if none is provided
if len(modules) == 0:
for i in self.targets:
@@ -1317,17 +1356,19 @@ class CMakeDependency(ExternalDependency):
lname = name.lower()
if '{}::{}'.format(lname, lname) == tg or lname == tg.replace('::', ''):
mlog.debug('Guessed CMake target \'{}\''.format(i))
- modules = [i]
+ modules = [(i, True)]
+ autodetected_module_list = True
break
# Failed to guess a target --> try the old-style method
if len(modules) == 0:
incDirs = self.get_first_cmake_var_of(['PACKAGE_INCLUDE_DIRS'])
+ defs = self.get_first_cmake_var_of(['PACKAGE_DEFINITIONS'])
libs = self.get_first_cmake_var_of(['PACKAGE_LIBRARIES'])
# Try to use old style variables if no module is specified
if len(libs) > 0:
- self.compile_args = list(map(lambda x: '-I{}'.format(x), incDirs))
+ self.compile_args = list(map(lambda x: '-I{}'.format(x), incDirs)) + defs
self.link_args = libs
mlog.debug('using old-style CMake variables for dependency {}'.format(name))
return
@@ -1344,13 +1385,19 @@ class CMakeDependency(ExternalDependency):
compileDefinitions = []
compileOptions = []
libraries = []
- for i in modules:
+ for i, required in modules:
if i not in self.targets:
- raise self._gen_exception('CMake: invalid CMake target {} for {}.\n'
+ if not required:
+ mlog.warning('CMake: Optional module', mlog.bold(self._original_module_name(i)), 'for', mlog.bold(name), 'was not found')
+ continue
+ raise self._gen_exception('CMake: invalid module {} for {}.\n'
'Try to explicitly specify one or more targets with the "modules" property.\n'
- 'Valid targets are:\n{}'.format(i, name, list(self.targets.keys())))
+ 'Valid targets are:\n{}'.format(self._original_module_name(i), name, list(self.targets.keys())))
targets = [i]
+ if not autodetected_module_list:
+ self.found_modules += [i]
+
while len(targets) > 0:
curr = targets.pop(0)
@@ -1415,7 +1462,7 @@ class CMakeDependency(ExternalDependency):
self.compile_args = compileOptions + compileDefinitions + list(map(lambda x: '-I{}'.format(x), incDirs))
self.link_args = libraries
- def get_first_cmake_var_of(self, var_list):
+ def get_first_cmake_var_of(self, var_list: List[str]) -> List[str]:
# Return the first found CMake variable in list var_list
for i in var_list:
if i in self.vars:
@@ -1423,7 +1470,7 @@ class CMakeDependency(ExternalDependency):
return []
- def get_cmake_var(self, var):
+ def get_cmake_var(self, var: str) -> List[str]:
# Return the value of the CMake variable var or an empty list if var does not exist
if var in self.vars:
return self.vars[var]
@@ -1730,6 +1777,13 @@ set(CMAKE_SIZEOF_VOID_P "{}")
def log_tried(self):
return self.type_name
+ def log_details(self) -> str:
+ modules = [self._original_module_name(x) for x in self.found_modules]
+ modules = sorted(set(modules))
+ if modules:
+ return 'modules: ' + ', '.join(modules)
+ return ''
+
class DubDependency(ExternalDependency):
class_dubbin = None
diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py
index f5b95f5..0de1372 100644
--- a/mesonbuild/dependencies/boost.py
+++ b/mesonbuild/dependencies/boost.py
@@ -105,7 +105,7 @@ class BoostDependency(ExternalDependency):
self.requested_modules = self.get_requested(kwargs)
if 'thread' in self.requested_modules:
- self.ext_deps.append(ThreadDependency(environment, kwargs))
+ self._add_sub_dependency(ThreadDependency, environment, kwargs)
self.boost_root = None
self.boost_roots = []
diff --git a/mesonbuild/dependencies/data/CMakeListsLLVM.txt b/mesonbuild/dependencies/data/CMakeListsLLVM.txt
new file mode 100644
index 0000000..9d3e412
--- /dev/null
+++ b/mesonbuild/dependencies/data/CMakeListsLLVM.txt
@@ -0,0 +1,95 @@
+cmake_minimum_required(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} )
+
+set(PACKAGE_FOUND FALSE)
+
+while(TRUE)
+ find_package(LLVM REQUIRED CONFIG QUIET)
+
+ # ARCHS has to be set via the CMD interface
+ if(LLVM_FOUND OR "${ARCHS}" STREQUAL "")
+ break()
+ endif()
+
+ list(GET ARCHS 0 CMAKE_LIBRARY_ARCHITECTURE)
+ list(REMOVE_AT ARCHS 0)
+endwhile()
+
+if(LLVM_FOUND)
+ set(PACKAGE_FOUND TRUE)
+
+ foreach(mod IN LISTS LLVM_MESON_MODULES)
+ # Reset variables
+ set(out_mods)
+ set(real_mods)
+
+ # Generate a lower and upper case version
+ string(TOLOWER "${mod}" mod_L)
+ string(TOUPPER "${mod}" mod_U)
+
+ # Get the mapped components
+ llvm_map_components_to_libnames(out_mods ${mod} ${mod_L} ${mod_U})
+ list(SORT out_mods)
+ list(REMOVE_DUPLICATES out_mods)
+
+ # Make sure that the modules exist
+ foreach(i IN LISTS out_mods)
+ if(TARGET ${i})
+ list(APPEND real_mods ${i})
+ endif()
+ endforeach()
+
+ # Set the output variables
+ set(MESON_LLVM_TARGETS_${mod} ${real_mods})
+ foreach(i IN LISTS real_mods)
+ set(MESON_TARGET_TO_LLVM_${i} ${mod})
+ endforeach()
+ endforeach()
+
+ # Check the following variables:
+ # LLVM_PACKAGE_VERSION
+ # LLVM_VERSION
+ # LLVM_VERSION_STRING
+ if(NOT DEFINED PACKAGE_VERSION)
+ if(DEFINED LLVM_PACKAGE_VERSION)
+ set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
+ elseif(DEFINED LLVM_VERSION)
+ set(PACKAGE_VERSION "${LLVM_VERSION}")
+ elseif(DEFINED LLVM_VERSION_STRING)
+ set(PACKAGE_VERSION "${LLVM_VERSION_STRING}")
+ endif()
+ endif()
+
+ # Check the following variables:
+ # LLVM_LIBRARIES
+ # LLVM_LIBS
+ set(libs)
+ if(DEFINED LLVM_LIBRARIES)
+ set(libs LLVM_LIBRARIES)
+ elseif(DEFINED LLVM_LIBS)
+ set(libs LLVM_LIBS)
+ endif()
+
+ # Check the following variables:
+ # LLVM_INCLUDE_DIRS
+ # LLVM_INCLUDES
+ # LLVM_INCLUDE_DIR
+ set(includes)
+ if(DEFINED LLVM_INCLUDE_DIRS)
+ set(includes LLVM_INCLUDE_DIRS)
+ elseif(DEFINED LLVM_INCLUDES)
+ set(includes LLVM_INCLUDES)
+ elseif(DEFINED LLVM_INCLUDE_DIR)
+ set(includes LLVM_INCLUDE_DIR)
+ endif()
+
+ # Check the following variables:
+ # LLVM_DEFINITIONS
+ set(definitions)
+ if(DEFINED LLVM_DEFINITIONS)
+ set(definitions LLVM_DEFINITIONS)
+ endif()
+
+ set(PACKAGE_INCLUDE_DIRS "${${includes}}")
+ set(PACKAGE_DEFINITIONS "${${definitions}}")
+ set(PACKAGE_LIBRARIES "${${libs}}")
+endif()
diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py
index c911cfa..4d541a3 100644
--- a/mesonbuild/dependencies/dev.py
+++ b/mesonbuild/dependencies/dev.py
@@ -20,14 +20,16 @@ import glob
import os
import re
-from .. import mesonlib
+from .. import mesonlib, mlog
from ..mesonlib import version_compare, stringlistify, extract_as_list, MachineChoice
from .base import (
DependencyException, DependencyMethods, ExternalDependency, PkgConfigDependency,
- strip_system_libdirs, ConfigToolDependency,
+ strip_system_libdirs, ConfigToolDependency, CMakeDependency
)
from .misc import ThreadDependency
+from typing import List, Tuple
+
def get_shared_library_suffix(environment, native):
"""This is only gauranteed to work for languages that compile to machine
@@ -46,7 +48,7 @@ class GTestDependency(ExternalDependency):
self.main = kwargs.get('main', False)
self.src_dirs = ['/usr/src/gtest/src', '/usr/src/googletest/googletest/src']
self.detect()
- self.ext_deps.append(ThreadDependency(environment, kwargs))
+ self._add_sub_dependency(ThreadDependency, environment, kwargs)
def detect(self):
gtest_detect = self.clib_compiler.find_library("gtest", self.env, [])
@@ -117,7 +119,7 @@ class GMockDependency(ExternalDependency):
def __init__(self, environment, kwargs):
super().__init__('gmock', environment, 'cpp', kwargs)
self.main = kwargs.get('main', False)
- self.ext_deps.append(ThreadDependency(environment, kwargs))
+ self._add_sub_dependency(ThreadDependency, environment, kwargs)
# If we are getting main() from GMock, we definitely
# want to avoid linking in main() from GTest
@@ -192,7 +194,7 @@ class GMockDependency(ExternalDependency):
return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM]
-class LLVMDependency(ConfigToolDependency):
+class LLVMDependencyConfigTool(ConfigToolDependency):
"""
LLVM uses a special tool, llvm-config, which has arguments for getting
c args, cxx args, and ldargs as well as version.
@@ -256,7 +258,7 @@ class LLVMDependency(ConfigToolDependency):
self._set_old_link_args()
self.link_args = strip_system_libdirs(environment, self.link_args)
self.link_args = self.__fix_bogus_link_args(self.link_args)
- self.ext_deps.append(ThreadDependency(environment, kwargs))
+ self._add_sub_dependency(ThreadDependency, environment, kwargs)
@staticmethod
def __fix_bogus_link_args(args):
@@ -399,6 +401,66 @@ class LLVMDependency(ConfigToolDependency):
return 'modules: ' + ', '.join(self.module_details)
return ''
+class LLVMDependencyCMake(CMakeDependency):
+ def __init__(self, env, kwargs):
+ self.llvm_modules = stringlistify(extract_as_list(kwargs, 'modules'))
+ self.llvm_opt_modules = stringlistify(extract_as_list(kwargs, 'optional_modules'))
+ super().__init__(name='LLVM', environment=env, language='cpp', kwargs=kwargs)
+
+ # Extract extra include directories and definitions
+ inc_dirs = self.get_cmake_var('PACKAGE_INCLUDE_DIRS')
+ defs = self.get_cmake_var('PACKAGE_DEFINITIONS')
+ temp = ['-I' + x for x in inc_dirs] + defs
+ self.compile_args += [x for x in temp if x not in self.compile_args]
+ self._add_sub_dependency(ThreadDependency, env, kwargs)
+
+ def _main_cmake_file(self) -> str:
+ # Use a custom CMakeLists.txt for LLVM
+ return 'CMakeListsLLVM.txt'
+
+ def _extra_cmake_opts(self) -> List[str]:
+ return ['-DLLVM_MESON_MODULES={}'.format(';'.join(self.llvm_modules + self.llvm_opt_modules))]
+
+ def _map_module_list(self, modules: List[Tuple[str, bool]]) -> List[Tuple[str, bool]]:
+ res = []
+ for mod, required in modules:
+ cm_targets = self.get_cmake_var('MESON_LLVM_TARGETS_{}'.format(mod))
+ if not cm_targets:
+ if required:
+ raise self._gen_exception('LLVM module {} was not found'.format(mod))
+ else:
+ mlog.warning('Optional LLVM module', mlog.bold(mod), 'was not found')
+ continue
+ for i in cm_targets:
+ res += [(i, required)]
+ return res
+
+ def _original_module_name(self, module: str) -> str:
+ orig_name = self.get_cmake_var('MESON_TARGET_TO_LLVM_{}'.format(module))
+ if orig_name:
+ return orig_name[0]
+ return module
+
+class LLVMDependency(ExternalDependency):
+ def __init__(self, env, kwargs):
+ super().__init__('LLVM', env, 'cpp', kwargs)
+
+ @classmethod
+ def _factory(cls, env, kwargs):
+ methods = cls._process_method_kw(kwargs)
+ candidates = []
+
+ if DependencyMethods.CMAKE in methods:
+ candidates.append(functools.partial(LLVMDependencyCMake, env, kwargs))
+
+ if DependencyMethods.CONFIG_TOOL in methods:
+ candidates.append(functools.partial(LLVMDependencyConfigTool, env, kwargs))
+
+ return candidates
+
+ @staticmethod
+ def get_methods():
+ return [DependencyMethods.CMAKE, DependencyMethods.CONFIG_TOOL]
class ValgrindDependency(PkgConfigDependency):
'''
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index ba97083..3f9d464 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -3421,8 +3421,10 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
for s in raw_sources:
if isinstance(s, mesonlib.File):
sources.append(s)
- else:
+ elif isinstance(s, str):
source_strings.append(s)
+ else:
+ raise InvalidArguments('Argument {!r} must be string or file.'.format(s))
sources += self.source_strings_to_files(source_strings)
install_dir = kwargs.get('install_dir', None)
if not isinstance(install_dir, (str, type(None))):
diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py
index 563b811..84bcefb 100644
--- a/mesonbuild/msetup.py
+++ b/mesonbuild/msetup.py
@@ -191,7 +191,7 @@ class MesonApp:
# Print all default option values that don't match the current value
for def_opt_name, def_opt_value, cur_opt_value in intr.get_non_matching_default_options():
mlog.log('Option', mlog.bold(def_opt_name), 'is:',
- mlog.bold(make_lower_case(cur_opt_value.printable_value())),
+ mlog.bold('{}'.format(make_lower_case(cur_opt_value.printable_value()))),
'[default: {}]'.format(make_lower_case(def_opt_value)))
try:
dumpfile = os.path.join(env.get_scratch_dir(), 'build.dat')
diff --git a/setup.py b/setup.py
index 07bd3dd..aab740e 100644
--- a/setup.py
+++ b/setup.py
@@ -35,7 +35,7 @@ packages = ['mesonbuild',
'mesonbuild.modules',
'mesonbuild.scripts',
'mesonbuild.wrap']
-package_data = {'mesonbuild.dependencies': ['data/CMakeLists.txt', 'data/CMakePathInfo.txt']}
+package_data = {'mesonbuild.dependencies': ['data/CMakeLists.txt', 'data/CMakeListsLLVM.txt', 'data/CMakePathInfo.txt']}
data_files = []
if sys.platform != 'win32':
# Only useful on UNIX-like systems
diff --git a/test cases/common/161 config tool variable/meson.build b/test cases/common/161 config tool variable/meson.build
index 0643042..9584117 100644
--- a/test cases/common/161 config tool variable/meson.build
+++ b/test cases/common/161 config tool variable/meson.build
@@ -15,7 +15,7 @@
project('config tool variable', 'cpp')
-dep_llvm = dependency('llvm', required : false)
+dep_llvm = dependency('llvm', method : 'config-tool', required : false)
if not dep_llvm.found()
error('MESON_SKIP_TEST LLVM not installed.')
endif
diff --git a/test cases/common/91 default options/meson.build b/test cases/common/91 default options/meson.build
index c4c72ef..4a9fc2f 100644
--- a/test cases/common/91 default options/meson.build
+++ b/test cases/common/91 default options/meson.build
@@ -8,13 +8,10 @@ project('default options', 'cpp', 'c', default_options : [
assert(get_option('buildtype') == 'debugoptimized', 'Build type default value wrong.')
-if meson.get_compiler('cpp').get_argument_syntax() == 'msvc'
- cpp_eh = get_option('cpp_eh')
- assert(cpp_eh == 'none', 'MSVC eh value is "' + cpp_eh + '" instead of "none"')
-else
- cpp_std = get_option('cpp_std')
- assert(cpp_std == 'c++11', 'C++ std value is "' + cpp_std + '" instead of c++11.')
-endif
+cpp_eh = get_option('cpp_eh')
+assert(cpp_eh == 'none', 'EH value is "' + cpp_eh + '" instead of "none"')
+cpp_std = get_option('cpp_std')
+assert(cpp_std == 'c++11', 'C++ std value is "' + cpp_std + '" instead of c++11.')
w_level = get_option('warning_level')
assert(w_level == '3', 'warning level "' + w_level + '" instead of "3"')
diff --git a/test cases/failing/97 custom target install data/Info.plist.cpp b/test cases/failing/97 custom target install data/Info.plist.cpp
new file mode 100644
index 0000000..9ca2fcb
--- /dev/null
+++ b/test cases/failing/97 custom target install data/Info.plist.cpp
@@ -0,0 +1 @@
+Some data which gets processed before installation
diff --git a/test cases/failing/97 custom target install data/meson.build b/test cases/failing/97 custom target install data/meson.build
new file mode 100644
index 0000000..00d348c
--- /dev/null
+++ b/test cases/failing/97 custom target install data/meson.build
@@ -0,0 +1,11 @@
+project('custom target install data')
+
+preproc = find_program('preproc.py')
+
+t = custom_target('Info.plist',
+ command: [preproc, '@INPUT@', '@OUTPUT@'],
+ input: 'Info.plist.cpp',
+ output: 'Info.plist',
+)
+
+install_data(t)
diff --git a/test cases/failing/97 custom target install data/preproc.py b/test cases/failing/97 custom target install data/preproc.py
new file mode 100644
index 0000000..e6eba4c
--- /dev/null
+++ b/test cases/failing/97 custom target install data/preproc.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+
+import sys
+
+if len(sys.argv) != 3:
+ print(sys.argv[0], '<input>', '<output>')
+
+inf = sys.argv[1]
+outf = sys.argv[2]
+
+with open(outf, 'wb') as o:
+ with open(inf, 'rb') as i:
+ o.write(i.read())
diff --git a/test cases/frameworks/15 llvm/meson.build b/test cases/frameworks/15 llvm/meson.build
index b43bb87..af94dae 100644
--- a/test cases/frameworks/15 llvm/meson.build
+++ b/test cases/frameworks/15 llvm/meson.build
@@ -1,6 +1,6 @@
project('llvmtest', ['c', 'cpp'], default_options : ['c_std=c99'])
-d = dependency('llvm', required : false)
+d = dependency('llvm', required : false, method : 'config-tool')
if not d.found()
d = dependency('llvm', required : false, static : true)
if not d.found()
@@ -35,7 +35,7 @@ foreach static : [true, false]
llvm_dep = dependency(
'llvm',
modules : ['bitwriter', 'asmprinter', 'executionengine', 'target',
- 'mcjit', 'nativecodegen'],
+ 'mcjit', 'nativecodegen', 'amdgpu'],
required : false,
static : static,
)
diff --git a/test cases/frameworks/2 gtest/meson.build b/test cases/frameworks/2 gtest/meson.build
index e5418e9..3f30215 100644
--- a/test cases/frameworks/2 gtest/meson.build
+++ b/test cases/frameworks/2 gtest/meson.build
@@ -4,7 +4,7 @@ gtest = dependency('gtest', main : true, required : false)
if not gtest.found()
error('MESON_SKIP_TEST: gtest not installed.')
endif
-gtest_nomain = dependency('gtest', main : false)
+gtest_nomain = dependency('gtest', main : false, method : 'system')
e = executable('testprog', 'test.cc', dependencies : gtest)
test('gtest test', e)
diff --git a/test cases/frameworks/3 gmock/meson.build b/test cases/frameworks/3 gmock/meson.build
index 516547f..58591ae 100644
--- a/test cases/frameworks/3 gmock/meson.build
+++ b/test cases/frameworks/3 gmock/meson.build
@@ -3,7 +3,7 @@ project('gmock test', 'cpp')
# Using gmock without gtest is a pain so just
# don't support that then.
-gtest = dependency('gtest', main : true, required : false)
+gtest = dependency('gtest', main : true, required : false, method : 'system')
if not gtest.found()
error('MESON_SKIP_TEST: gtest not installed.')
endif
diff --git a/test cases/unit/47 native file binary/meson.build b/test cases/unit/47 native file binary/meson.build
index 4489ac1..c9b6e5d 100644
--- a/test cases/unit/47 native file binary/meson.build
+++ b/test cases/unit/47 native file binary/meson.build
@@ -8,7 +8,7 @@ if case == 'find_program'
assert(result.stdout().strip().endswith('12345'), 'Didn\'t load bash from config file')
elif case == 'config_dep'
add_languages('cpp')
- dep = dependency('llvm')
+ dep = dependency('llvm', method : 'config-tool')
assert(dep.get_configtool_variable('version').endswith('12345'), 'Didn\'t load llvm from config file')
elif case == 'python3'
prog = import('python3').find_python()