aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Contributing.md13
-rw-r--r--docs/markdown/FAQ.md34
-rw-r--r--mesonbuild/ast/interpreter.py10
-rw-r--r--mesonbuild/ast/introspection.py2
-rw-r--r--mesonbuild/compilers/compilers.py3
-rw-r--r--mesonbuild/compilers/cpp.py34
-rw-r--r--mesonbuild/mconf.py3
-rw-r--r--mesonbuild/mesonlib.py3
-rw-r--r--mesonbuild/modules/pkgconfig.py2
-rwxr-xr-xrun_unittests.py10
-rw-r--r--test cases/unit/55 introspection/meson.build7
11 files changed, 102 insertions, 19 deletions
diff --git a/docs/markdown/Contributing.md b/docs/markdown/Contributing.md
index 2881837..f8f1824 100644
--- a/docs/markdown/Contributing.md
+++ b/docs/markdown/Contributing.md
@@ -291,3 +291,16 @@ Environment variables are like global variables, except that they are
also hidden by default. Envvars should be avoided whenever possible,
all functionality should be exposed in better ways such as command
line switches.
+
+## Random design points that fit nowhere else
+
+- All features should follow the 90/9/1 rule. 90% of all use cases
+ should be easy, 9% should be possible and it is totally fine to not
+ support the final 1% if it would make things too complicated.
+
+- Any build directory will have at most two toolchains: one native and
+ one cross.
+
+- Prefer specific solutions to generic frameworks. Solve the end
+ user's problems rather than providing them tools to do it
+ themselves.
diff --git a/docs/markdown/FAQ.md b/docs/markdown/FAQ.md
index 0208c1a..139e192 100644
--- a/docs/markdown/FAQ.md
+++ b/docs/markdown/FAQ.md
@@ -365,3 +365,37 @@ compiler.
- If the compiler is freely available, consider adding it to the CI
system.
+
+## Why does building my project with MSVC output static libraries called `libfoo.a`?
+
+The naming convention for static libraries on Windows is usually `foo.lib`.
+Unfortunately, import libraries are also called `foo.lib`.
+
+This causes filename collisions with the default library type where we build
+both shared and static libraries, and also causes collisions during
+installation since all libraries are installed to the same directory by default.
+
+To resolve this, we decided to default to creating static libraries of the form
+`libfoo.a` when building with MSVC. This has the following advantages:
+
+1. Filename collisions are completely avoided.
+1. The format for MSVC static libraries is `ar`, which is the same as the GNU
+ static library format, so using this extension is semantically correct.
+1. The static library filename format is now the same on all platforms and with
+ all toolchains.
+1. Both Clang and GNU compilers can search for `libfoo.a` when specifying
+ a library as `-lfoo`. This does not work for alternative naming schemes for
+ static libraries such as `libfoo.lib`.
+1. Since `-lfoo` works out of the box, pkgconfig files will work correctly for
+ projects built with both MSVC, GCC, and Clang on Windows.
+1. MSVC does not have arguments to search for library filenames, and [it does
+ not care what the extension is](https://docs.microsoft.com/en-us/cpp/build/reference/link-input-files?view=vs-2019),
+ so specifying `libfoo.a` instead of `foo.lib` does not change the workflow,
+ and is an improvement since it's less ambiguous.
+
+If, for some reason, you really need your project to output static libraries of
+the form `foo.lib` when building with MSVC, you can set the
+[`name_prefix:`](https://mesonbuild.com/Reference-manual.html#library)
+kwarg to `''` and the [`name_suffix:`](https://mesonbuild.com/Reference-manual.html#library)
+kwarg to `'lib'`. To get the default behaviour for each, you can either not
+specify the kwarg, or pass `[]` (an empty array) to it.
diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py
index eb9cb9f..5354710 100644
--- a/mesonbuild/ast/interpreter.py
+++ b/mesonbuild/ast/interpreter.py
@@ -260,6 +260,12 @@ class AstInterpreter(interpreterbase.InterpreterBase):
id_loop_detect = []
flattend_args = []
+ if isinstance(args, BaseNode):
+ assert(hasattr(args, 'ast_id'))
+ if args.ast_id in id_loop_detect:
+ return [] # Loop detected
+ id_loop_detect += [args.ast_id]
+
if isinstance(args, ArrayNode):
args = [x for x in args.args.arguments]
@@ -301,8 +307,8 @@ class AstInterpreter(interpreterbase.InterpreterBase):
# Resolve the contents of args
for i in args:
- if isinstance(i, IdNode) and i.value not in id_loop_detect:
- flattend_args += self.flatten_args(quick_resolve(i), include_unknown_args, id_loop_detect + [i.value])
+ if isinstance(i, IdNode):
+ flattend_args += self.flatten_args(quick_resolve(i), include_unknown_args, id_loop_detect)
elif isinstance(i, (ArrayNode, ArgumentNode, ArithmeticNode, MethodNode)):
flattend_args += self.flatten_args(i, include_unknown_args, id_loop_detect)
elif isinstance(i, mparser.ElementaryNode):
diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py
index b6ec450..5ac6133 100644
--- a/mesonbuild/ast/introspection.py
+++ b/mesonbuild/ast/introspection.py
@@ -118,7 +118,7 @@ class IntrospectionInterpreter(AstInterpreter):
subproject_dir_abs = os.path.join(self.environment.get_source_dir(), self.subproject_dir)
subpr = os.path.join(subproject_dir_abs, dirname)
try:
- subi = IntrospectionInterpreter(subpr, '', self.backend, cross_file=self.cross_file, subproject=dirname, subproject_dir=self.subproject_dir, env=self.environment)
+ subi = IntrospectionInterpreter(subpr, '', self.backend, cross_file=self.cross_file, subproject=dirname, subproject_dir=self.subproject_dir, env=self.environment, visitors=self.visitors)
subi.analyze()
subi.project_data['name'] = dirname
self.project_data['subprojects'] += [subi.project_data]
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 8c40ced..dacf75d 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -1307,6 +1307,9 @@ class Compiler:
paths = paths + ':' + padding
args.append('-Wl,-rpath,' + paths)
+ if mesonlib.is_sunos():
+ return args
+
if get_compiler_is_linuxlike(self):
# Rpaths to use while linking must be absolute. These are not
# written to the binary. Needed only with GNU ld:
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index c5079cb..9fae22c 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -39,6 +39,13 @@ from .compilers import (
from .c_function_attributes import CXX_FUNC_ATTRIBUTES, C_FUNC_ATTRIBUTES
from .clike import CLikeCompiler
+def non_msvc_eh_options(eh, args):
+ if eh == 'none':
+ args.append('-fno-exceptions')
+ elif eh == 's' or eh == 'c':
+ mlog.warning('non-MSVC compilers do not support ' + eh + ' exception handling.' +
+ 'You may want to set eh to \'default\'.')
+
class CPPCompiler(CLikeCompiler, Compiler):
@classmethod
@@ -153,7 +160,7 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
opts = CPPCompiler.get_options(self)
opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh',
'C++ exception handling type.',
- ['none', 'default'],
+ ['none', 'default', 'a', 's', 'sc'],
'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',
@@ -166,8 +173,9 @@ 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')
+
+ non_msvc_eh_options(options['cpp_eh'].value, args)
+
return args
def get_option_link_args(self, options):
@@ -191,7 +199,7 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
opts = CPPCompiler.get_options(self)
opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh',
'C++ exception handling type.',
- ['none', 'default'],
+ ['none', 'default', 'a', 's', 'sc'],
'default'),
'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17',
@@ -204,8 +212,9 @@ 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')
+
+ non_msvc_eh_options(options['cpp_eh'].value, args)
+
return args
def get_option_link_args(self, options):
@@ -226,7 +235,7 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler):
opts = CPPCompiler.get_options(self)
opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh',
'C++ exception handling type.',
- ['none', 'default'],
+ ['none', 'default', 'a', 's', 'sc'],
'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',
@@ -246,8 +255,9 @@ 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')
+
+ non_msvc_eh_options(options['cpp_eh'].value, args)
+
if options['cpp_debugstl'].value:
args.append('-D_GLIBCXX_DEBUG=1')
return args
@@ -280,7 +290,7 @@ class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler):
opts = CPPCompiler.get_options(self)
opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh',
'C++ exception handling type.',
- ['none', 'default'],
+ ['none', 'default', 'a', 's', 'sc'],
'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',
@@ -330,7 +340,7 @@ class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler):
g_stds += ['gnu++14']
opts.update({'cpp_eh': coredata.UserComboOption('cpp_eh',
'C++ exception handling type.',
- ['none', 'default'],
+ ['none', 'default', 'a', 's', 'sc'],
'default'),
'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
['none'] + c_stds + g_stds,
@@ -379,7 +389,7 @@ 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', 'default'],
+ ['none', 'default', 'a', 's', 'sc'],
'default'),
'cpp_std': coredata.UserComboOption('cpp_std',
'C++ language standard to use',
diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py
index cd9d35a..3b50d55 100644
--- a/mesonbuild/mconf.py
+++ b/mesonbuild/mconf.py
@@ -14,6 +14,7 @@
import os
from . import coredata, environment, mesonlib, build, mintro, mlog
+from .ast import AstIDGenerator
def add_arguments(parser):
coredata.register_builtin_arguments(parser)
@@ -52,7 +53,7 @@ class Conf:
# Make sure that log entries in other parts of meson don't interfere with the JSON output
mlog.disable()
self.source_dir = os.path.abspath(os.path.realpath(self.build_dir))
- intr = mintro.IntrospectionInterpreter(self.source_dir, '', 'ninja')
+ intr = mintro.IntrospectionInterpreter(self.source_dir, '', 'ninja', visitors = [AstIDGenerator()])
intr.analyze()
# Reenable logging just in case
mlog.enable()
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index f78fa35..07beb69 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -344,6 +344,9 @@ class PerMachine(typing.Generic[_T]):
}[machine]
setattr(self, key, val)
+def is_sunos() -> bool:
+ return platform.system().lower() == 'sunos'
+
def is_osx() -> bool:
return platform.system().lower() == 'darwin'
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index 2f8b533..d4d0625 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -267,7 +267,7 @@ class PkgConfigModule(ExtensionModule):
# These always return paths relative to prefix
libdir = PurePath(coredata.get_builtin_option('libdir'))
incdir = PurePath(coredata.get_builtin_option('includedir'))
- with open(fname, 'w') as ofile:
+ with open(fname, 'w', encoding='utf-8') as ofile:
ofile.write('prefix={}\n'.format(self._escape(prefix)))
ofile.write('libdir={}\n'.format(self._escape('${prefix}' / libdir)))
ofile.write('includedir={}\n'.format(self._escape('${prefix}' / incdir)))
diff --git a/run_unittests.py b/run_unittests.py
index 4f27817..f4d969c 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -4250,11 +4250,17 @@ class LinuxlikeTests(BasePlatformTests):
cmd = ['pkg-config', 'requires-test']
out = self._run(cmd + ['--print-requires']).strip().split('\n')
- self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo >= 1.0', 'libhello']))
+ if not is_openbsd():
+ self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo >= 1.0', 'libhello']))
+ else:
+ self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo>=1.0', 'libhello']))
cmd = ['pkg-config', 'requires-private-test']
out = self._run(cmd + ['--print-requires-private']).strip().split('\n')
- self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo >= 1.0', 'libhello']))
+ if not is_openbsd():
+ self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo >= 1.0', 'libhello']))
+ else:
+ self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo>=1.0', 'libhello']))
def test_pkg_unfound(self):
testdir = os.path.join(self.unit_test_dir, '23 unfound pkgconfig')
diff --git a/test cases/unit/55 introspection/meson.build b/test cases/unit/55 introspection/meson.build
index f11d64d..3f013aa 100644
--- a/test cases/unit/55 introspection/meson.build
+++ b/test cases/unit/55 introspection/meson.build
@@ -34,6 +34,13 @@ systype = '@0@, @1@, @2@'.format(systype, host_machine.cpu_family(), host_machin
message(systype)
### END: Test inspired by taisei
+# Minimal code version to produce bug #5376
+# Code inspired by https://github.com/mesa3d/mesa/blob/974c4d679c23373dbed386c696e3e3bc1bfa23ae/meson.build#L1341-L1347
+osmesa_lib_name = 'OSMesa'
+osmesa_bits = '8'
+osmesa_lib_name = osmesa_lib_name + osmesa_bits
+message(osmesa_lib_name) # Infinite recursion gets triggered here when the parameter osmesa_lib_name is resolved
+
test('test case 1', t1)
test('test case 2', t2)
benchmark('benchmark 1', t3)