diff options
37 files changed, 290 insertions, 113 deletions
diff --git a/cross/ownstdlib.txt b/cross/ownstdlib.txt index 46e99f7..bdff6f4 100644 --- a/cross/ownstdlib.txt +++ b/cross/ownstdlib.txt @@ -10,4 +10,4 @@ endian = 'little' [properties] -c_stdlib = ['mylibc', 'mylibc_dep'] # Subproject name, dependency name +c_stdlib = 'mylibc' # Subproject name diff --git a/docs/markdown/Cross-compilation.md b/docs/markdown/Cross-compilation.md index d86d417..c8cd728 100644 --- a/docs/markdown/Cross-compilation.md +++ b/docs/markdown/Cross-compilation.md @@ -268,7 +268,7 @@ invocation to use in your cross file is the following: ```ini [properties] -c_stdlib = ['mylibc', 'mylibc_dep'] # Subproject name, dependency name +c_stdlib = ['mylibc', 'mylibc_dep'] # Subproject name, variable name ``` This specifies that C standard library is provided in the Meson @@ -277,6 +277,18 @@ is used on every cross built C target in the entire source tree (including subprojects) and the standard library is disabled. The build definitions of these targets do not need any modification. +Note that it is supported for any language, not only `c`, using `<lang>_stdlib` +property. + +Since *0.56.0* the variable name parameter is no longer required as long as the +subproject calls `meson.override_dependency('c_stdlib', mylibc_dep)`. +The above example becomes: + +```ini +[properties] +c_stdlib = 'mylibc' +``` + ## Changing cross file settings Cross file settings are only read when the build directory is set up diff --git a/docs/markdown/IDE-integration.md b/docs/markdown/IDE-integration.md index ee51b64..816225f 100644 --- a/docs/markdown/IDE-integration.md +++ b/docs/markdown/IDE-integration.md @@ -335,3 +335,4 @@ removal of a key) are unlikely and will be announced in the release notes. - [Meson Cmake Wrapper](https://github.com/prozum/meson-cmake-wrapper) (for cmake IDEs) (currently unmaintained !!) - [Meson-UI](https://github.com/michaelbadcrumble/meson-ui) (Meson build GUI) - [Meson Syntax Highlighter](https://plugins.jetbrains.com/plugin/13269-meson-syntax-highlighter) plugin for JetBrains IDEs. +- [asabil.meson](https://open-vsx.org/extension/asabil/meson) extension for VS Code/Codium diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index 3be129f..55c1a99 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -25,6 +25,7 @@ These are return values of the `get_id` (Compiler family) and | mono | Xamarin C# compiler | | | msvc | Microsoft Visual Studio | msvc | | nagfor | The NAG Fortran compiler | | +| nvidia_hpc| NVidia HPC SDK compilers | | | open64 | The Open64 Fortran Compiler | | | pathscale | The Pathscale Fortran compiler | | | pgi | Portland PGI C/C++/Fortran compilers | | diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index dbacc6e..307aef7 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -88,6 +88,7 @@ lookup based on OpenStreetMap data 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 + - [Libvirt](https://libvirt.org), a toolkit to manage virtualization platforms - [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 - [Mesa](https://gitlab.freedesktop.org/mesa/mesa/), an open source graphics driver project @@ -117,6 +118,7 @@ format files - [Polari](https://gitlab.gnome.org/GNOME/polari), an IRC client - [qboot](https://github.com/bonzini/qboot), a minimal x86 firmware for booting Linux kernels - [radare2](https://github.com/radare/radare2), unix-like reverse engineering framework and commandline tools (not the default) + - [QEMU](https://qemu.org), a processor emulator and virtualizer - [RxDock](https://gitlab.com/rxdock/rxdock), a protein-ligand docking software designed for high throughput virtual screening (fork of rDock) - [scrcpy](https://github.com/Genymobile/scrcpy), a cross platform application that provides display and control of Android devices connected on USB or over TCP/IP - [Sequeler](https://github.com/Alecaddd/sequeler), a friendly SQL client for Linux, built with Vala and Gtk diff --git a/docs/markdown/snippets/add_nvidia_hpc_sdk_compilers.md b/docs/markdown/snippets/add_nvidia_hpc_sdk_compilers.md new file mode 100644 index 0000000..1d9acf9 --- /dev/null +++ b/docs/markdown/snippets/add_nvidia_hpc_sdk_compilers.md @@ -0,0 +1,3 @@ +## Added NVidia HPC SDK compilers + +Added support for `nvidia_hpc` NVidia HPC SDK compilers, which are currently in public beta testing. diff --git a/docs/markdown/snippets/stdlib.md b/docs/markdown/snippets/stdlib.md new file mode 100644 index 0000000..5e80dd5 --- /dev/null +++ b/docs/markdown/snippets/stdlib.md @@ -0,0 +1,6 @@ +## Custom standard library + +- It is not limited to cross builds any more, `<lang>_stdlib` property can be + set in native files. +- The variable name parameter is no longer required as long as the subproject + calls `meson.override_dependency('c_stdlib', mylibc_dep)`. diff --git a/mesonbuild/arglist.py b/mesonbuild/arglist.py index fd4de96..4ab7d09 100644 --- a/mesonbuild/arglist.py +++ b/mesonbuild/arglist.py @@ -119,7 +119,7 @@ class CompilerArgs(collections.abc.MutableSequence): # This correctly deduplicates the entries after _can_dedup definition # Note: This function is designed to work without delete operations, as deletions are worsening the performance a lot. def flush_pre_post(self) -> None: - pre_flush = collections.deque() # type: T.Deque[str] + new = list() # type: T.List[str] pre_flush_set = set() # type: T.Set[str] post_flush = collections.deque() # type: T.Deque[str] post_flush_set = set() # type: T.Set[str] @@ -128,7 +128,7 @@ class CompilerArgs(collections.abc.MutableSequence): for a in self.pre: dedup = self._can_dedup(a) if a not in pre_flush_set: - pre_flush.append(a) + new.append(a) if dedup is Dedup.OVERRIDEN: pre_flush_set.add(a) for a in reversed(self.post): @@ -140,12 +140,15 @@ class CompilerArgs(collections.abc.MutableSequence): #pre and post will overwrite every element that is in the container #only copy over args that are in _container but not in the post flush or pre flush set + if pre_flush_set or post_flush_set: + for a in self._container: + if a not in post_flush_set and a not in pre_flush_set: + new.append(a) + else: + new.extend(self._container) + new.extend(post_flush) - for a in self._container: - if a not in post_flush_set and a not in pre_flush_set: - pre_flush.append(a) - - self._container = list(pre_flush) + list(post_flush) + self._container = new self.pre.clear() self.post.clear() diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index c84bb75..c6a48d3 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -657,7 +657,7 @@ class Backend: # First, the trivial ones that are impossible to override. # # Add -nostdinc/-nostdinc++ if needed; can't be overridden - commands += self.get_cross_stdlib_args(target, compiler) + commands += self.get_no_stdlib_args(target, compiler) # Add things like /NOLOGO or -pipe; usually can't be overridden commands += compiler.get_always_args() # Only add warning-flags by default if the buildtype enables it, and if diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index b4ebdc3..24cfe26 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -114,13 +114,17 @@ rsp_threshold = get_rsp_threshold() # from, etc.), so it must not be shell quoted. raw_names = {'DEPFILE_UNQUOTED', 'DESC', 'pool', 'description', 'targetdep'} +NINJA_QUOTE_BUILD_PAT = re.compile(r"[$ :\n]") +NINJA_QUOTE_VAR_PAT = re.compile(r"[$ \n]") + def ninja_quote(text, is_build_line=False): if is_build_line: - qcs = ('$', ' ', ':') + quote_re = NINJA_QUOTE_BUILD_PAT else: - qcs = ('$', ' ') - for char in qcs: - text = text.replace(char, '$' + char) + quote_re = NINJA_QUOTE_VAR_PAT + # Fast path for when no quoting is necessary + if not quote_re.search(text): + return text if '\n' in text: errmsg = '''Ninja does not support newlines in rules. The content was: @@ -128,7 +132,7 @@ def ninja_quote(text, is_build_line=False): Please report this error with a test case to the Meson bug tracker.'''.format(text) raise MesonException(errmsg) - return text + return quote_re.sub(r'$\g<0>', text) @unique class Quoting(Enum): @@ -261,18 +265,20 @@ class NinjaRule: # expand variables in command command = ' '.join([self._quoter(x) for x in self.command + self.args]) - expanded_command = '' - for m in re.finditer(r'(\${\w*})|(\$\w*)|([^$]*)', command): - chunk = m.group() - if chunk.startswith('$'): - chunk = chunk[1:] - chunk = re.sub(r'{(.*)}', r'\1', chunk) - chunk = ninja_vars.get(chunk, []) # undefined ninja variables are empty - chunk = ' '.join(chunk) - expanded_command += chunk + estimate = len(command) + for m in re.finditer(r'(\${\w*}|\$\w*)?[^$]*', command): + if m.start(1) != -1: + estimate -= m.end(1) - m.start(1) + 1 + chunk = m.group(1) + if chunk[1] == '{': + chunk = chunk[2:-1] + else: + chunk = chunk[1:] + chunk = ninja_vars.get(chunk, []) # undefined ninja variables are empty + estimate += len(' '.join(chunk)) # determine command length - return len(expanded_command) + return estimate class NinjaBuildElement: def __init__(self, all_outputs, outfilenames, rulename, infilenames, implicit_outs=None): @@ -380,10 +386,9 @@ class NinjaBuildElement: newelems = [] for i in elems: if not should_quote or i == '&&': # Hackety hack hack - quoter = ninja_quote + newelems.append(ninja_quote(i)) else: - quoter = lambda x: ninja_quote(qf(x)) - newelems.append(quoter(i)) + newelems.append(ninja_quote(qf(i))) line += ' '.join(newelems) line += '\n' outfile.write(line) @@ -2088,12 +2093,15 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) mod_files = _scan_fortran_file_deps(src, srcdir, dirname, tdeps, compiler) return mod_files - def get_cross_stdlib_args(self, target, compiler): - if self.environment.machines.matches_build_machine(target.for_machine): - return [] - if not self.environment.properties.host.has_stdlib(compiler.language): - return [] - return compiler.get_no_stdinc_args() + def get_no_stdlib_args(self, target, compiler): + if compiler.language in self.build.stdlibs[target.for_machine]: + return compiler.get_no_stdinc_args() + return [] + + def get_no_stdlib_link_args(self, target, linker): + if hasattr(linker, 'language') and linker.language in self.build.stdlibs[target.for_machine]: + return linker.get_no_stdlib_link_args() + return [] def get_compile_debugfile_args(self, compiler, target, objfile): # The way MSVC uses PDB files is documented exactly nowhere so @@ -2520,14 +2528,6 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) elem.add_item('CROSS', '--cross-host=' + self.environment.machines[target.for_machine].system) self.add_build(elem) - def get_cross_stdlib_link_args(self, target, linker): - if isinstance(target, build.StaticLibrary) or \ - self.environment.machines.matches_build_machine(target.for_machine): - return [] - if not self.environment.properties.host.has_stdlib(linker.language): - return [] - return linker.get_no_stdlib_link_args() - def get_import_filename(self, target): return os.path.join(self.get_target_dir(target), target.import_filename) @@ -2689,7 +2689,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) linker, isinstance(target, build.SharedModule)) # Add -nostdlib if needed; can't be overridden - commands += self.get_cross_stdlib_link_args(target, linker) + commands += self.get_no_stdlib_link_args(target, linker) # Add things like /NOLOGO; usually can't be overridden commands += linker.get_linker_always_args() # Add buildtype linker args: optimization level, etc. diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 5e6db73..edd1506 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -774,6 +774,7 @@ class BuildTarget(Target): def extract_objects(self, srclist): obj_src = [] + sources_set = set(self.sources) for src in srclist: if isinstance(src, str): src = File(False, self.subdir, src) @@ -782,7 +783,7 @@ class BuildTarget(Target): else: raise MesonException('Object extraction arguments must be strings or Files.') # FIXME: It could be a generated source - if src not in self.sources: + if src not in sources_set: raise MesonException('Tried to extract unknown source {}.'.format(src)) obj_src.append(src) return ExtractedObjects(self, obj_src) diff --git a/mesonbuild/cmake/executor.py b/mesonbuild/cmake/executor.py index e29e67a..2226c02 100644 --- a/mesonbuild/cmake/executor.py +++ b/mesonbuild/cmake/executor.py @@ -29,13 +29,18 @@ from .. import mlog, mesonlib from ..mesonlib import PerMachine, Popen_safe, version_compare, MachineChoice from ..environment import Environment from ..envconfig import get_env_var +from ..compilers import ( + AppleClangCCompiler, AppleClangCPPCompiler, AppleClangObjCCompiler, + AppleClangObjCPPCompiler +) if T.TYPE_CHECKING: from ..dependencies.base import ExternalProgram + from ..compilers import Compiler TYPE_result = T.Tuple[int, T.Optional[str], T.Optional[str]] -MESON_TO_CMAKE_MAPPING = { +_MESON_TO_CMAKE_MAPPING = { 'arm': 'ARMCC', 'armclang': 'ARMClang', 'clang': 'Clang', @@ -51,13 +56,21 @@ MESON_TO_CMAKE_MAPPING = { 'sun': 'SunPro', } -def meson_compiler_to_cmake_id(cobj): - # cland and apple clang both map to 'clang' in meson, so we need to look at - # the linker that's being used - if cobj.linker.get_id() == 'ld64': +def meson_compiler_to_cmake_id(cobj: 'Compiler') -> str: + """Translate meson compiler's into CMAKE compiler ID's. + + Most of these can be handled by a simple table lookup, with a few + exceptions. + + Clang and Apple's Clang are both identified as "clang" by meson. To make + things more complicated gcc and vanilla clang both use Apple's ld64 on + macOS. The only way to know for sure is to do an isinstance() check. + """ + if isinstance(cobj, (AppleClangCCompiler, AppleClangCPPCompiler, + AppleClangObjCCompiler, AppleClangObjCPPCompiler)): return 'AppleClang' # If no mapping, try GNU and hope that the build files don't care - return MESON_TO_CMAKE_MAPPING.get(cobj.get_id(), 'GNU') + return _MESON_TO_CMAKE_MAPPING.get(cobj.get_id(), 'GNU') class CMakeExecutor: diff --git a/mesonbuild/compilers/__init__.py b/mesonbuild/compilers/__init__.py index fd47545..b8d8678 100644 --- a/mesonbuild/compilers/__init__.py +++ b/mesonbuild/compilers/__init__.py @@ -36,6 +36,8 @@ __all__ = [ 'AppleClangCCompiler', 'AppleClangCPPCompiler', + 'AppleClangObjCCompiler', + 'AppleClangObjCPPCompiler', 'ArmCCompiler', 'ArmCPPCompiler', 'ArmclangCCompiler', @@ -85,6 +87,9 @@ __all__ = [ 'ObjCPPCompiler', 'Open64FortranCompiler', 'PathScaleFortranCompiler', + 'NvidiaHPC_CCompiler', + 'NvidiaHPC_CPPCompiler', + 'NvidiaHPC_FortranCompiler', 'PGICCompiler', 'PGICPPCompiler', 'PGIFortranCompiler', @@ -135,6 +140,7 @@ from .c import ( EmscriptenCCompiler, IntelCCompiler, IntelClCCompiler, + NvidiaHPC_CCompiler, PGICCompiler, CcrxCCompiler, Xc16CCompiler, @@ -153,6 +159,7 @@ from .cpp import ( EmscriptenCPPCompiler, IntelCPPCompiler, IntelClCPPCompiler, + NvidiaHPC_CPPCompiler, PGICPPCompiler, CcrxCPPCompiler, C2000CPPCompiler, @@ -177,17 +184,20 @@ from .fortran import ( NAGFortranCompiler, Open64FortranCompiler, PathScaleFortranCompiler, + NvidiaHPC_FortranCompiler, PGIFortranCompiler, SunFortranCompiler, ) from .java import JavaCompiler from .objc import ( ObjCCompiler, + AppleClangObjCCompiler, ClangObjCCompiler, GnuObjCCompiler, ) from .objcpp import ( ObjCPPCompiler, + AppleClangObjCPPCompiler, ClangObjCPPCompiler, GnuObjCPPCompiler, ) diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index d600ac4..13ca1d4 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -266,6 +266,15 @@ class PGICCompiler(PGICompiler, CCompiler): PGICompiler.__init__(self) +class NvidiaHPC_CCompiler(PGICompiler, CCompiler): + def __init__(self, exelist, version, for_machine: MachineChoice, + is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, + info, exe_wrapper, **kwargs) + PGICompiler.__init__(self) + self.id = 'nvidia_hpc' + + class ElbrusCCompiler(GnuCCompiler, ElbrusCompiler): def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, info: 'MachineInfo', exe_wrapper=None, diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index f5b0c05..698c71a 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -156,7 +156,7 @@ class CPPCompiler(CLikeCompiler, Compiler): class ClangCPPCompiler(ClangCompiler, CPPCompiler): def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, info: 'MachineInfo', exe_wrapper=None, - defines : T.Optional[T.List[str]] = None, **kwargs): + defines: T.Optional[T.List[str]] = None, **kwargs): CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs) ClangCompiler.__init__(self, defines) @@ -240,8 +240,8 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler): def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): CPPCompiler.__init__(self, exelist=exelist, version=version, - for_machine=for_machine, is_cross=is_cross, - info=info, exe_wrapper=exe_wrapper, **kwargs) + for_machine=for_machine, is_cross=is_cross, + info=info, exe_wrapper=exe_wrapper, **kwargs) ArmclangCompiler.__init__(self) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'0': [], @@ -305,7 +305,7 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler): 'std': coredata.UserComboOption( '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'], + 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'], 'none', ), 'debugstl': coredata.UserBooleanOption( @@ -356,6 +356,15 @@ class PGICPPCompiler(PGICompiler, CPPCompiler): PGICompiler.__init__(self) +class NvidiaHPC_CPPCompiler(PGICompiler, CPPCompiler): + def __init__(self, exelist, version, for_machine: MachineChoice, + is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs) + PGICompiler.__init__(self) + + self.id = 'nvidia_hpc' + + class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler): def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, info: 'MachineInfo', exe_wrapper=None, @@ -365,9 +374,20 @@ class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler): **kwargs) ElbrusCompiler.__init__(self) - # 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) + + cpp_stds = [ + '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', + ] + + if version_compare(self.version, '>=1.24.00'): + cpp_stds += [ 'c++1z', 'c++17', 'gnu++1z', 'gnu++17' ] + + if version_compare(self.version, '>=1.25.00'): + cpp_stds += [ 'c++2a', 'gnu++2a' ] + opts.update({ 'eh': coredata.UserComboOption( 'C++ exception handling type.', @@ -376,10 +396,7 @@ class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler): ), 'std': coredata.UserComboOption( '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', - ], + cpp_stds, 'none', ), 'debugstl': coredata.UserBooleanOption( diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index af83c0e56..7ca3073 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -418,6 +418,23 @@ class PGIFortranCompiler(PGICompiler, FortranCompiler): return ['-lpgf90rtl', '-lpgf90', '-lpgf90_rpm1', '-lpgf902', '-lpgf90rtl', '-lpgftnrtl', '-lrt'] + +class NvidiaHPC_FortranCompiler(PGICompiler, FortranCompiler): + def __init__(self, exelist, version, for_machine: MachineChoice, + is_cross, info: 'MachineInfo', exe_wrapper=None, + **kwargs): + FortranCompiler.__init__(self, exelist, version, for_machine, + is_cross, info, exe_wrapper, **kwargs) + PGICompiler.__init__(self) + + self.id = 'nvidia_hpc' + default_warn_args = ['-Minform=inform'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args, + '3': default_warn_args + ['-Mdclchk']} + + class FlangFortranCompiler(ClangCompiler, FortranCompiler): def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, info: 'MachineInfo', exe_wrapper=None, diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 95b9592..4311fa5 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -40,7 +40,9 @@ from .visualstudio import VisualStudioLikeCompiler if T.TYPE_CHECKING: from ...environment import Environment -SOREGEX = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$') +GROUP_FLAGS = re.compile(r'''\.so (?:\.[0-9]+)? (?:\.[0-9]+)? (?:\.[0-9]+)?$ | + ^(?:-Wl,)?-l | + \.a$''', re.X) class CLikeCompilerArgs(arglist.CompilerArgs): prepend_prefixes = ('-I', '-L') @@ -69,8 +71,7 @@ class CLikeCompilerArgs(arglist.CompilerArgs): group_start = -1 group_end = -1 for i, each in enumerate(new): - if not each.startswith(('-Wl,-l', '-l')) and not each.endswith('.a') and \ - not SOREGEX.match(each): + if not GROUP_FLAGS.search(each): continue group_end = i if group_start < 0: @@ -85,6 +86,9 @@ class CLikeCompilerArgs(arglist.CompilerArgs): default_dirs = self.compiler.get_default_include_dirs() bad_idx_list = [] # type: T.List[int] for i, each in enumerate(new): + if not each.startswith('-isystem'): + continue + # Remove the -isystem and the path if the path is a default path if (each == '-isystem' and i < (len(new) - 1) and @@ -92,7 +96,7 @@ class CLikeCompilerArgs(arglist.CompilerArgs): bad_idx_list += [i, i + 1] elif each.startswith('-isystem=') and each[9:] in default_dirs: bad_idx_list += [i] - elif each.startswith('-isystem') and each[8:] in default_dirs: + elif each[8:] in default_dirs: bad_idx_list += [i] for i in reversed(bad_idx_list): new.pop(i) diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py index d351c88..254a609 100644 --- a/mesonbuild/compilers/objc.py +++ b/mesonbuild/compilers/objc.py @@ -92,3 +92,8 @@ class ClangObjCCompiler(ClangCompiler, ObjCCompiler): '1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} + + +class AppleClangObjCCompiler(ClangObjCCompiler): + + """Handle the differences between Apple's clang and vanilla clang.""" diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py index 10555b4..3197abc 100644 --- a/mesonbuild/compilers/objcpp.py +++ b/mesonbuild/compilers/objcpp.py @@ -90,3 +90,9 @@ class ClangObjCPPCompiler(ClangCompiler, ObjCPPCompiler): '1': default_warn_args, '2': default_warn_args + ['-Wextra'], '3': default_warn_args + ['-Wextra', '-Wpedantic']} + + + +class AppleClangObjCPPCompiler(ClangObjCPPCompiler): + + """Handle the differences between Apple's clang and vanilla clang.""" diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 368a4bc..f581c06 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -2301,7 +2301,7 @@ def get_dep_identifier(name, kwargs) -> T.Tuple: # 'required' is irrelevant for caching; the caller handles it separately # 'fallback' subprojects cannot be cached -- they must be initialized # 'default_options' is only used in fallback case - if key in ('version', 'native', 'required', 'fallback', 'default_options'): + if key in ('version', 'native', 'required', 'fallback', 'default_options', 'force_fallback'): continue # All keyword arguments are strings, ints, or lists (or lists of lists) if isinstance(value, list): diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 8571202..eee336e 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -58,6 +58,8 @@ from .linkers import ( QualcommLLVMDynamicLinker, MSVCDynamicLinker, OptlinkDynamicLinker, + NvidiaHPC_DynamicLinker, + NvidiaHPC_StaticLinker, PGIDynamicLinker, PGIStaticLinker, SolarisDynamicLinker, @@ -74,6 +76,8 @@ from .compilers import ( ArmclangCPPCompiler, AppleClangCCompiler, AppleClangCPPCompiler, + AppleClangObjCCompiler, + AppleClangObjCPPCompiler, ClangCCompiler, ClangCPPCompiler, ClangObjCCompiler, @@ -105,6 +109,9 @@ from .compilers import ( NAGFortranCompiler, Open64FortranCompiler, PathScaleFortranCompiler, + NvidiaHPC_CCompiler, + NvidiaHPC_CPPCompiler, + NvidiaHPC_FortranCompiler, PGICCompiler, PGICPPCompiler, PGIFortranCompiler, @@ -769,11 +776,11 @@ class Environment: self.default_objc = [] self.default_objcpp = [] else: - self.default_c = ['cc', 'gcc', 'clang', 'pgcc', 'icc'] - self.default_cpp = ['c++', 'g++', 'clang++', 'pgc++', 'icpc'] + self.default_c = ['cc', 'gcc', 'clang', 'nvc', 'pgcc', 'icc'] + self.default_cpp = ['c++', 'g++', 'clang++', 'nvc++', 'pgc++', 'icpc'] self.default_objc = ['cc', 'gcc', 'clang'] self.default_objcpp = ['c++', 'g++', 'clang++'] - self.default_fortran = ['gfortran', 'flang', 'pgfortran', 'ifort', 'g95'] + self.default_fortran = ['gfortran', 'flang', 'nvfortran', 'pgfortran', 'ifort', 'g95'] self.default_cs = ['mcs', 'csc'] self.default_d = ['ldc2', 'ldc', 'gdc', 'dmd'] self.default_java = ['javac'] @@ -1304,6 +1311,13 @@ class Environment: return cls( ccache + compiler, version, for_machine, is_cross, info, exe_wrap, linker=linker) + if 'NVIDIA Compilers and Tools' in out: + cls = NvidiaHPC_CCompiler if lang == 'c' else NvidiaHPC_CPPCompiler + self.coredata.add_lang_args(cls.language, cls, for_machine, self) + linker = NvidiaHPC_DynamicLinker(compiler, for_machine, cls.LINKER_PREFIX, [], version=version) + return cls( + ccache + compiler, version, for_machine, is_cross, + info, exe_wrap, linker=linker) if '(ICC)' in out: cls = IntelCCompiler if lang == 'c' else IntelCPPCompiler l = self._guess_nix_linker(compiler, cls, for_machine) @@ -1475,6 +1489,15 @@ class Environment: compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) + if 'NVIDIA Compilers and Tools' in out: + cls = NvidiaHPC_FortranCompiler + self.coredata.add_lang_args(cls.language, cls, for_machine, self) + linker = PGIDynamicLinker(compiler, for_machine, + cls.LINKER_PREFIX, [], version=version) + return cls( + compiler, version, for_machine, is_cross, info, exe_wrap, + full_version=full_version, linker=linker) + if 'flang' in out or 'clang' in out: linker = self._guess_nix_linker( compiler, FlangFortranCompiler, for_machine) @@ -1507,7 +1530,7 @@ class Environment: def detect_objcpp_compiler(self, for_machine: MachineInfo) -> 'Compiler': return self._detect_objc_or_objcpp_compiler(for_machine, False) - def _detect_objc_or_objcpp_compiler(self, for_machine: MachineInfo, objc: bool) -> 'Compiler': + def _detect_objc_or_objcpp_compiler(self, for_machine: MachineChoice, objc: bool) -> 'Compiler': popen_exceptions = {} compilers, ccache, exe_wrap = self._get_compilers('objc' if objc else 'objcpp', for_machine) is_cross = self.is_cross_build(for_machine) @@ -1536,7 +1559,10 @@ class Environment: exe_wrap, defines, linker=linker) if 'clang' in out: linker = None - comp = ClangObjCCompiler if objc else ClangObjCPPCompiler + if 'Apple' in out: + comp = AppleClangObjCCompiler if objc else AppleClangObjCPPCompiler + else: + comp = ClangObjCCompiler if objc else ClangObjCPPCompiler if 'windows' in out or self.machines[for_machine].is_windows(): # If we're in a MINGW context this actually will use a gnu style ld try: diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index b547bbf..2924172 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -2572,21 +2572,25 @@ class Interpreter(InterpreterBase): return self.variables def check_stdlibs(self): - for for_machine in MachineChoice: + machine_choices = [MachineChoice.HOST] + if self.coredata.is_cross_build(): + machine_choices.append(MachineChoice.BUILD) + for for_machine in machine_choices: props = self.build.environment.properties[for_machine] for l in self.coredata.compilers[for_machine].keys(): try: di = mesonlib.stringlistify(props.get_stdlib(l)) - if len(di) != 2: - raise InterpreterException('Stdlib definition for %s should have exactly two elements.' - % l) - projname, depname = di - subproj = self.do_subproject(projname, 'meson', {}) - self.build.stdlibs.host[l] = subproj.get_variable_method([depname], {}) except KeyError: - pass - except InvalidArguments: - pass + continue + if len(di) == 1: + FeatureNew.single_use('stdlib without variable name', '0.56.0', self.subproject) + kwargs = {'fallback': di, + 'native': for_machine is MachineChoice.BUILD, + 'force_fallback': True, + } + name = display_name = l + '_stdlib' + dep = self.dependency_impl(name, display_name, kwargs) + self.build.stdlibs[for_machine][l] = dep def import_module(self, modname): if modname in self.modules: @@ -2788,6 +2792,12 @@ external dependencies (including libraries) must go to "dependencies".''') self.subprojects[dirname] = sub return sub + def get_subproject(self, dirname): + sub = self.subprojects.get(dirname) + if sub and sub.found(): + return sub + return None + def do_subproject(self, dirname: str, method: str, kwargs): disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) if disabled: @@ -3514,7 +3524,7 @@ external dependencies (including libraries) must go to "dependencies".''') return DependencyHolder(NotFoundDependency(self.environment), self.subproject) def verify_fallback_consistency(self, dirname, varname, cached_dep): - subi = self.subprojects.get(dirname) + subi = self.get_subproject(dirname) if not cached_dep or not varname or not subi or not cached_dep.found(): return dep = subi.get_variable_method([varname], {}) @@ -3646,7 +3656,7 @@ external dependencies (including libraries) must go to "dependencies".''') # even if the dependency is not required. provider = self.environment.wrap_resolver.find_dep_provider(name) dirname = mesonlib.listify(provider)[0] - if provider and (required or dirname in self.subprojects): + if provider and (required or self.get_subproject(dirname)): kwargs['fallback'] = provider has_fallback = True @@ -3676,15 +3686,16 @@ external dependencies (including libraries) must go to "dependencies".''') # a higher level project, try to use it first. if has_fallback: dirname, varname = self.get_subproject_infos(kwargs) - sub = self.subprojects.get(dirname) - if sub and sub.found(): + if self.get_subproject(dirname): return self.get_subproject_dep(name, display_name, dirname, varname, kwargs) wrap_mode = self.coredata.get_builtin_option('wrap_mode') force_fallback_for = self.coredata.get_builtin_option('force_fallback_for') + force_fallback = kwargs.get('force_fallback', False) forcefallback = has_fallback and (wrap_mode == WrapMode.forcefallback or \ name in force_fallback_for or \ - dirname in force_fallback_for) + dirname in force_fallback_for or \ + force_fallback) if name != '' and not forcefallback: self._handle_featurenew_dependencies(name) kwargs['required'] = required and not has_fallback @@ -4362,8 +4373,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self if len(inputs_abs) != 1: raise InterpreterException('Exactly one input file must be given in copy mode') os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True) - shutil.copyfile(inputs_abs[0], ofile_abs) - shutil.copystat(inputs_abs[0], ofile_abs) + shutil.copy2(inputs_abs[0], ofile_abs) else: # Not reachable raise AssertionError @@ -4786,8 +4796,7 @@ Try setting b_lundef to false instead.'''.format(self.coredata.base_options['b_s target = targetclass(name, self.subdir, self.subproject, for_machine, sources, objs, self.environment, kwargs) target.project_version = self.project_version - if not self.environment.machines.matches_build_machine(for_machine): - self.add_cross_stdlib_info(target) + self.add_stdlib_info(target) l = targetholder(target, self) self.add_target(name, l.held_object) self.project_args_frozen = True @@ -4811,23 +4820,19 @@ This will become a hard error in the future.''', location=self.current_node) kwargs['d_import_dirs'] = cleaned_items def get_used_languages(self, target): - result = {} + result = set() for i in target.sources: - # TODO other platforms - for lang, c in self.coredata.compilers.host.items(): + for lang, c in self.coredata.compilers[target.for_machine].items(): if c.can_compile(i): - result[lang] = True + result.add(lang) break return result - def add_cross_stdlib_info(self, target): - if target.for_machine != MachineChoice.HOST: - return + def add_stdlib_info(self, target): for l in self.get_used_languages(target): - props = self.environment.properties.host - if props.has_stdlib(l) \ - and self.subproject != props.get_stdlib(l)[0]: - target.add_deps(self.build.stdlibs.host[l]) + dep = self.build.stdlibs[target.for_machine].get(l, None) + if dep: + target.add_deps(dep) def check_sources_exist(self, subdir, sources): for s in sources: diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py index 822167c..6c4f273 100644 --- a/mesonbuild/interpreterbase.py +++ b/mesonbuild/interpreterbase.py @@ -810,9 +810,7 @@ The result of this is undefined and will become a hard error in a future Meson r assert(isinstance(node, mparser.PlusAssignmentNode)) varname = node.var_name addition = self.evaluate_statement(node.value) - if is_disabler(addition): - self.set_variable(varname, addition) - return + # Remember that all variables are immutable. We must always create a # full new variable and then assign it. old_variable = self.get_variable(varname) @@ -836,7 +834,7 @@ The result of this is undefined and will become a hard error in a future Meson r new_value = {**old_variable, **addition} # Add other data types here. else: - raise InvalidArguments('The += operator currently only works with arrays, dicts, strings or ints ') + raise InvalidArguments('The += operator currently only works with arrays, dicts, strings or ints') self.set_variable(varname, new_value) def evaluate_indexing(self, node: mparser.IndexNode) -> TYPE_var: diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py index 3ce7111..505aef6 100644 --- a/mesonbuild/linkers.py +++ b/mesonbuild/linkers.py @@ -712,7 +712,7 @@ class GnuDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, Dynam """Representation of GNU ld.bfd and ld.gold.""" def get_accepts_rsp(self) -> bool: - return True; + return True class GnuGoldDynamicLinker(GnuDynamicLinker): @@ -964,6 +964,8 @@ class PGIDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): return (['-R' + os.path.join(build_dir, p) for p in rpath_paths], set()) return ([], set()) +NvidiaHPC_DynamicLinker = PGIDynamicLinker + class PGIStaticLinker(StaticLinker): def __init__(self, exelist: T.List[str]): @@ -977,6 +979,8 @@ class PGIStaticLinker(StaticLinker): def get_output_args(self, target: str) -> T.List[str]: return [target] +NvidiaHPC_StaticLinker = PGIStaticLinker + class VisualStudioLikeLinkerMixin: diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index 4b8cce8..760b235 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -242,6 +242,7 @@ class File: self.is_built = is_built self.subdir = subdir self.fname = fname + self.hash = hash((is_built, subdir, fname)) def __str__(self) -> str: return self.relative_name() @@ -291,10 +292,12 @@ class File: def __eq__(self, other) -> bool: if not isinstance(other, File): return NotImplemented + if self.hash != other.hash: + return False return (self.fname, self.subdir, self.is_built) == (other.fname, other.subdir, other.is_built) def __hash__(self) -> int: - return hash((self.fname, self.subdir, self.is_built)) + return self.hash @lru_cache(maxsize=None) def relative_name(self) -> str: diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py index 0be01fe..e6e973a 100644 --- a/mesonbuild/minstall.py +++ b/mesonbuild/minstall.py @@ -270,11 +270,9 @@ class Installer: # Remove this entire branch when changing the behaviour to duplicate # symlinks rather than copying what they point to. print(symlink_warning) - shutil.copyfile(from_file, to_file) - shutil.copystat(from_file, to_file) + shutil.copy2(from_file, to_file) else: - shutil.copyfile(from_file, to_file) - shutil.copystat(from_file, to_file) + shutil.copy2(from_file, to_file) selinux_updates.append(to_file) append_to_log(self.lf, to_file) return True diff --git a/mesonbuild/scripts/gettext.py b/mesonbuild/scripts/gettext.py index f5c0421..7042863 100644 --- a/mesonbuild/scripts/gettext.py +++ b/mesonbuild/scripts/gettext.py @@ -83,8 +83,7 @@ def do_install(src_sub, bld_sub, dest, pkgname, langs): pkgname + '.mo') tempfile = outfile + '.tmp' os.makedirs(os.path.dirname(outfile), exist_ok=True) - shutil.copyfile(srcfile, tempfile) - shutil.copystat(srcfile, tempfile) + shutil.copy2(srcfile, tempfile) os.replace(tempfile, outfile) print('Installing %s to %s' % (srcfile, outfile)) return 0 diff --git a/mesonbuild/scripts/yelphelper.py b/mesonbuild/scripts/yelphelper.py index 95c8c9c..6bf0673 100644 --- a/mesonbuild/scripts/yelphelper.py +++ b/mesonbuild/scripts/yelphelper.py @@ -68,8 +68,7 @@ def install_help(srcdir, blddir, sources, media, langs, install_dir, destdir, pr infile = os.path.join(srcdir if lang == 'C' else blddir, lang, source) outfile = os.path.join(indir, source) mlog.log('Installing %s to %s' % (infile, outfile)) - shutil.copyfile(infile, outfile) - shutil.copystat(infile, outfile) + shutil.copy2(infile, outfile) for m in media: infile = os.path.join(srcdir, lang, m) outfile = os.path.join(indir, m) diff --git a/run_unittests.py b/run_unittests.py index 95a6089..2012542 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -5054,6 +5054,29 @@ recommended as it is not supported on some platforms''') self.build() self.run_tests() + @unittest.skipUnless(is_linux() and (re.search('^i.86$|^x86$|^x64$|^x86_64$|^amd64$', platform.processor()) is not None), + 'Requires ASM compiler for x86 or x86_64 platform currently only available on Linux CI runners') + def test_nostdlib(self): + testdir = os.path.join(self.unit_test_dir, '79 nostdlib') + machinefile = os.path.join(self.builddir, 'machine.txt') + with open(machinefile, 'w') as f: + f.write(textwrap.dedent(''' + [properties] + c_stdlib = 'mylibc' + ''')) + + # Test native C stdlib + self.meson_native_file = machinefile + self.init(testdir) + self.build() + + # Test cross C stdlib + self.new_builddir() + self.meson_native_file = None + self.meson_cross_file = machinefile + self.init(testdir) + self.build() + class FailureTests(BasePlatformTests): ''' Tests that test failure conditions. Build files here should be dynamically diff --git a/test cases/common/235 disabler array addition/meson.build b/test cases/common/235 disabler array addition/meson.build new file mode 100644 index 0000000..231f76a --- /dev/null +++ b/test cases/common/235 disabler array addition/meson.build @@ -0,0 +1,9 @@ +project('disabler_inside_array', 'c') + +exes = [] + +exes += library('a', 'test.c') + +exes += library('b', 'test.c', dependencies : disabler()) + +exes += library('c', 'test.c') diff --git a/test cases/common/235 disabler array addition/test.c b/test cases/common/235 disabler array addition/test.c new file mode 100644 index 0000000..e9a7aac --- /dev/null +++ b/test cases/common/235 disabler array addition/test.c @@ -0,0 +1 @@ +int stub(void) { return 0; } diff --git a/manual tests/9 nostdlib/meson.build b/test cases/unit/79 nostdlib/meson.build index 9c5f949..9c5f949 100644 --- a/manual tests/9 nostdlib/meson.build +++ b/test cases/unit/79 nostdlib/meson.build diff --git a/manual tests/9 nostdlib/prog.c b/test cases/unit/79 nostdlib/prog.c index b9216ee..b9216ee 100644 --- a/manual tests/9 nostdlib/prog.c +++ b/test cases/unit/79 nostdlib/prog.c diff --git a/manual tests/9 nostdlib/subprojects/mylibc/libc.c b/test cases/unit/79 nostdlib/subprojects/mylibc/libc.c index 67261cb..67261cb 100644 --- a/manual tests/9 nostdlib/subprojects/mylibc/libc.c +++ b/test cases/unit/79 nostdlib/subprojects/mylibc/libc.c diff --git a/manual tests/9 nostdlib/subprojects/mylibc/meson.build b/test cases/unit/79 nostdlib/subprojects/mylibc/meson.build index aa0184e..ff4bdb2 100644 --- a/manual tests/9 nostdlib/subprojects/mylibc/meson.build +++ b/test cases/unit/79 nostdlib/subprojects/mylibc/meson.build @@ -9,3 +9,5 @@ libc = static_library('c', 'libc.c', 'stubstart.s') mylibc_dep = declare_dependency(link_with : libc, include_directories : include_directories('.') ) + +meson.override_dependency('c_stdlib', mylibc_dep) diff --git a/manual tests/9 nostdlib/subprojects/mylibc/stdio.h b/test cases/unit/79 nostdlib/subprojects/mylibc/stdio.h index c3f8f56..c3f8f56 100644 --- a/manual tests/9 nostdlib/subprojects/mylibc/stdio.h +++ b/test cases/unit/79 nostdlib/subprojects/mylibc/stdio.h diff --git a/manual tests/9 nostdlib/subprojects/mylibc/stubstart.s b/test cases/unit/79 nostdlib/subprojects/mylibc/stubstart.s index 0a6d972..0a6d972 100644 --- a/manual tests/9 nostdlib/subprojects/mylibc/stubstart.s +++ b/test cases/unit/79 nostdlib/subprojects/mylibc/stubstart.s |