From b3362e350ad0c8603966bc485e66af553750c648 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sat, 30 Sep 2017 18:25:33 +0300 Subject: Added release note snippet for prebuilt shared libs. --- docs/markdown/snippets/prebuilt.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 docs/markdown/snippets/prebuilt.md (limited to 'docs') diff --git a/docs/markdown/snippets/prebuilt.md b/docs/markdown/snippets/prebuilt.md new file mode 100644 index 000000000..a51176acc --- /dev/null +++ b/docs/markdown/snippets/prebuilt.md @@ -0,0 +1,15 @@ +# Better support for prebuilt shared libraries + +Meson has had support for prebuilt object files and static libraries. +This release adds feature parity to shared libraries. This means +that e.g. shipping prebuilt libraries as subprojects now can +be as simple as writing a definition file that looks like this. + + project('myprebuiltlibrary', 'c') + + cc = meson.get_compiler('c') + prebuilt = cc.find_library('mylib', dirs : meson.current_source_dir()) + mydep = declare_dependency(include_directories : include_directories('.'), + dependencies : prebuilt) + +Then you can use the dependency object in the same way as any other. -- cgit v1.2.3 From bbdba876afa8adfaf3e1d1985908326443875860 Mon Sep 17 00:00:00 2001 From: Niklas Claesson Date: Wed, 6 Sep 2017 23:54:49 +0200 Subject: Boost: Improve search algorithm The new implementation will correctly pick boost from 3 possible locations on windows and two locations on posix compatible OSs. The new search algorithm also differentiates between debug and release builds of Boost and multi or single threading builds. It was also decided to map "Meson modules" to Boost software libraries and not Boost modules since it there are a lot of options regarding linking. Some modules can even be used either as headers-only or with dynamic linking. This commit also fixes a bug that prevented header-only use on Windows. Fixes: #2274 #2239 #1803 #669 --- .appveyor.yml | 2 - docs/markdown/Dependencies.md | 15 +- .../001-boost-platform-improvement.md | 10 + mesonbuild/dependencies/misc.py | 413 +++++++++++++++------ test cases/frameworks/1 boost/meson.build | 5 +- test cases/frameworks/1 boost/nolinkexe.cc | 12 - tools/boost_names.py | 180 +++++++++ 7 files changed, 502 insertions(+), 135 deletions(-) create mode 100644 docs/markdown/Release-notes-for-0.43.0/001-boost-platform-improvement.md delete mode 100644 test cases/frameworks/1 boost/nolinkexe.cc create mode 100755 tools/boost_names.py (limited to 'docs') diff --git a/.appveyor.yml b/.appveyor.yml index 60a6fd3fd..4dc3f5050 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -59,8 +59,6 @@ init: install: - cmd: set "ORIG_PATH=%PATH%" - # Boost 1.56.0: https://www.appveyor.com/docs/build-environment/#boost - #- cmd: set "BOOST_ROOT=C:\Libraries\boost" # Use a Ninja with QuLogic's patch: https://github.com/ninja-build/ninja/issues/1219 - cmd: set "MESON_FIXED_NINJA=1" - ps: (new-object net.webclient).DownloadFile('http://nirbheek.in/files/binaries/ninja/win32/ninja.exe', 'C:\projects\meson\ninja.exe') diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md index 187c4fe4b..c46334c1e 100644 --- a/docs/markdown/Dependencies.md +++ b/docs/markdown/Dependencies.md @@ -50,8 +50,16 @@ pkg-config files. Meson has autodetection support for some of these. ## Boost ## Boost is not a single dependency but rather a group of different -libraries. To use Boost with Meson, simply list which Boost modules -you would like to use. +libraries. To use Boost headers-only libraries, simply add Boost as a +dependency. + +```meson +boost_dep = dependency('boost') +exe = executable('myprog', 'file.cc', dependencies : boost_dep) +``` + +To link against boost with Meson, simply list which libraries you would like to +use. ```meson boost_dep = dependency('boost', modules : ['thread', 'utility']) @@ -65,6 +73,9 @@ If your boost headers or libraries are in non-standard locations you can set the BOOST_ROOT, BOOST_INCLUDEDIR, and/or BOOST_LIBRARYDIR environment variables. +You can set the argument `threading` to `single` to use boost libraries that +has been compiled for single-threaded use instead. + ## GTest and GMock ## GTest and GMock come as sources that must be compiled as part of your diff --git a/docs/markdown/Release-notes-for-0.43.0/001-boost-platform-improvement.md b/docs/markdown/Release-notes-for-0.43.0/001-boost-platform-improvement.md new file mode 100644 index 000000000..2cd44ce5a --- /dev/null +++ b/docs/markdown/Release-notes-for-0.43.0/001-boost-platform-improvement.md @@ -0,0 +1,10 @@ +## Portability improvements to Boost Dependency + +The Boost dependency has been improved to better detect the various ways to +install boost on multiple platforms. At the same time the `modules` semantics +for the dependency has been changed. Previously it was allowed to specify +header directories as `modules` but it wasn't required. Now, modules are only +used to specify libraries that require linking. + +This is a breaking change and the fix is to remove all modules that aren't +found. diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index 61d0d7708..a0d5e47e9 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -18,7 +18,6 @@ import glob import os import re import shlex -import stat import shutil import sysconfig @@ -30,77 +29,153 @@ from ..environment import detect_cpu_family from .base import DependencyException, DependencyMethods from .base import ExternalDependency, ExternalProgram, ExtraFrameworkDependency, PkgConfigDependency +# On windows 3 directory layouts are supported: +# * The default layout (versioned) installed: +# - $BOOST_ROOT/include/boost-x_x/boost/*.hpp +# - $BOOST_ROOT/lib/*.lib +# * The non-default layout (system) installed: +# - $BOOST_ROOT/include/boost/*.hpp +# - $BOOST_ROOT/lib/*.lib +# * The pre-built binaries from sf.net: +# - $BOOST_ROOT/boost/*.hpp +# - $BOOST_ROOT/lib-/*.lib where arch=32/64 and compiler=msvc-14.1 +# +# Library names supported: +# - libboost_--mt-gd-x_x.lib (static) +# - boost_--mt-gd-x_x.lib|.dll (shared) +# - libboost_.lib (static) +# - boost_.lib|.dll (shared) +# where compiler is vc141 for example. +# +# NOTE: -gb means runtime and build time debugging is on +# -mt means threading=multi +# +# The `modules` argument accept library names. This is because every module that +# has libraries to link against also has multiple options regarding how to +# link. See for example: +# * http://www.boost.org/doc/libs/1_65_1/libs/test/doc/html/boost_test/usage_variants.html +# * http://www.boost.org/doc/libs/1_65_1/doc/html/stacktrace/configuration_and_build.html +# * http://www.boost.org/doc/libs/1_65_1/libs/math/doc/html/math_toolkit/main_tr1.html class BoostDependency(ExternalDependency): - # Some boost libraries have different names for - # their sources and libraries. This dict maps - # between the two. - name2lib = {'test': 'unit_test_framework'} - def __init__(self, environment, kwargs): super().__init__('boost', environment, 'cpp', kwargs) + self.need_static_link = ['boost_exception', 'boost_test_exec_monitor'] + self.is_debug = environment.cmd_line_options.buildtype.startswith('debug') + threading = kwargs.get("threading", "multi") + self.is_multithreading = threading == "multi" + + self.requested_modules = self.get_requested(kwargs) + + self.boost_root = None + self.boost_roots = [] + self.incdir = None self.libdir = None - try: + + if 'BOOST_ROOT' in os.environ: self.boost_root = os.environ['BOOST_ROOT'] + self.boost_roots = [self.boost_root] if not os.path.isabs(self.boost_root): raise DependencyException('BOOST_ROOT must be an absolute path.') - except KeyError: - self.boost_root = None + if 'BOOST_INCLUDEDIR' in os.environ: + self.incdir = os.environ['BOOST_INCLUDEDIR'] + if 'BOOST_LIBRARYDIR' in os.environ: + self.libdir = os.environ['BOOST_LIBRARYDIR'] + + if self.want_cross and self.boost_root is None and self.incdir is None: + raise DependencyException('BOOST_ROOT or BOOST_INCLUDEDIR is needed while cross-compiling') + if self.boost_root is None: - if self.want_cross: - if 'BOOST_INCLUDEDIR' in os.environ: - self.incdir = os.environ['BOOST_INCLUDEDIR'] - else: - raise DependencyException('BOOST_ROOT or BOOST_INCLUDEDIR is needed while cross-compiling') if mesonlib.is_windows(): - self.boost_root = self.detect_win_root() - self.incdir = self.boost_root + self.boost_roots = self.detect_win_roots() else: - if 'BOOST_INCLUDEDIR' in os.environ: - self.incdir = os.environ['BOOST_INCLUDEDIR'] - else: - self.incdir = '/usr/include' + self.boost_roots = self.detect_nix_roots() + + if self.boost_root is None and not self.boost_roots: + self.log_fail() + return + + if self.incdir is None: + if mesonlib.is_windows(): + self.incdir = self.detect_win_incdir() + else: + self.incdir = self.detect_nix_incdir() + + if self.incdir is None: + self.log_fail() + return + + mlog.debug('Boost library root dir is', mlog.bold(self.boost_root)) + mlog.debug('Boost include directory is', mlog.bold(self.incdir)) - if 'BOOST_LIBRARYDIR' in os.environ: - self.libdir = os.environ['BOOST_LIBRARYDIR'] - else: - self.incdir = os.path.join(self.boost_root, 'include') - self.boost_inc_subdir = os.path.join(self.incdir, 'boost') - mlog.debug('Boost library root dir is', self.boost_root) - self.src_modules = {} self.lib_modules = {} - self.lib_modules_mt = {} self.detect_version() - self.requested_modules = self.get_requested(kwargs) - module_str = ', '.join(self.requested_modules) if self.is_found: - self.detect_src_modules() self.detect_lib_modules() + mlog.debug('Boost library directory is', mlog.bold(self.libdir)) self.validate_requested() - if self.boost_root is not None: - info = self.version + ', ' + self.boost_root - else: - info = self.version - mlog.log('Dependency Boost (%s) found:' % module_str, mlog.green('YES'), info) + self.log_success() + else: + self.log_fail() + + def log_fail(self): + module_str = ', '.join(self.requested_modules) + mlog.log("Dependency Boost (%s) found:" % module_str, mlog.red('NO')) + + def log_success(self): + module_str = ', '.join(self.requested_modules) + if self.boost_root: + info = self.version + ', ' + self.boost_root else: - mlog.log("Dependency Boost (%s) found:" % module_str, mlog.red('NO')) + info = self.version + mlog.log('Dependency Boost (%s) found:' % module_str, mlog.green('YES'), info) + + def detect_nix_roots(self): + return ['/usr/local', '/usr'] - def detect_win_root(self): - globtext = 'c:\\local\\boost_*' + def detect_win_roots(self): + res = [] + # Where boost documentation says it should be + globtext = 'C:\\Program Files\\boost\\boost_*' files = glob.glob(globtext) - if len(files) > 0: - return files[0] - return 'C:\\' + res.extend(files) + + # Where boost built from source actually installs it + if os.path.isdir('C:\\Boost'): + res.append('C:\\Boost') + + # Where boost prebuilt binaries are + globtext = 'C:\\local\\boost_*' + files = glob.glob(globtext) + res.extend(files) + return res + + def detect_nix_incdir(self): + for root in self.boost_roots: + incdir = os.path.join(root, 'include', 'boost') + if os.path.isdir(incdir): + return os.path.join(root, 'include') + return None + + # FIXME: Should pick a version that matches the requested version + # Returns the folder that contains the boost folder. + def detect_win_incdir(self): + for root in self.boost_roots: + globtext = os.path.join(root, 'include', 'boost-*') + incdirs = glob.glob(globtext) + if len(incdirs) > 0: + return incdirs[0] + incboostdir = os.path.join(root, 'include', 'boost') + if os.path.isdir(incboostdir): + return os.path.join(root, 'include') + incboostdir = os.path.join(root, 'boost') + if os.path.isdir(incboostdir): + return root + return None def get_compile_args(self): args = [] - if self.boost_root is not None: - if mesonlib.is_windows(): - include_dir = self.boost_root - else: - include_dir = os.path.join(self.boost_root, 'include') - else: - include_dir = self.incdir + include_dir = self.incdir # Use "-isystem" when including boost headers instead of "-I" # to avoid compiler warnings/failures when "-Werror" is used @@ -125,19 +200,23 @@ class BoostDependency(ExternalDependency): for c in candidates: if not isinstance(c, str): raise DependencyException('Boost module argument is not a string.') + if 'boost_' + c not in BOOST_LIBS: + raise DependencyException('Dependency {} not found. It is not a valid boost library.'.format(c)) return candidates def validate_requested(self): for m in self.requested_modules: - if m not in self.src_modules and m not in self.lib_modules and m + '-mt' not in self.lib_modules_mt: - msg = 'Requested Boost module {!r} not found' + if 'boost_' + m not in self.lib_modules: + msg = 'Requested Boost library {!r} not found' raise DependencyException(msg.format(m)) def detect_version(self): try: - ifile = open(os.path.join(self.boost_inc_subdir, 'version.hpp')) + ifile = open(os.path.join(self.incdir, 'boost', 'version.hpp')) except FileNotFoundError: return + except TypeError: + return with ifile: for line in ifile: if line.startswith("#define") and 'BOOST_LIB_VERSION' in line: @@ -147,12 +226,6 @@ class BoostDependency(ExternalDependency): self.is_found = True return - def detect_src_modules(self): - for entry in os.listdir(self.boost_inc_subdir): - entry = os.path.join(self.boost_inc_subdir, entry) - if stat.S_ISDIR(os.stat(entry).st_mode): - self.src_modules[os.path.split(entry)[-1]] = True - def detect_lib_modules(self): if mesonlib.is_windows(): return self.detect_lib_modules_win() @@ -160,32 +233,79 @@ class BoostDependency(ExternalDependency): def detect_lib_modules_win(self): arch = detect_cpu_family(self.env.coredata.compilers) - # Guess the libdir - if arch == 'x86': - gl = 'lib32*' - elif arch == 'x86_64': - gl = 'lib64*' - else: - # Does anyone do Boost cross-compiling to other archs on Windows? - gl = None - # See if the libdir is valid - if gl: - libdir = glob.glob(os.path.join(self.boost_root, gl)) - else: - libdir = [] - # Can't find libdir, bail - if not libdir: + compiler_ts = self.env.detect_cpp_compiler(self.want_cross).get_toolset_version().split('.') + compiler = 'vc{}{}'.format(compiler_ts[0], compiler_ts[1]) + if not self.libdir: + # The libdirs in the distributed binaries + if arch == 'x86': + gl = 'lib32*' + elif arch == 'x86_64': + gl = 'lib64*' + else: + # Does anyone do Boost cross-compiling to other archs on Windows? + gl = None + if self.boost_root: + roots = [self.boost_root] + else: + roots = self.boost_roots + for root in roots: + # The default libdir when building + libdir = os.path.join(root, 'lib') + if os.path.isdir(libdir): + self.libdir = libdir + break + if gl: + tmp = glob.glob(os.path.join(root, gl)) + if len(tmp) > 0: + # FIXME: Should pick the correct version + self.libdir = tmp[0] + break + + if not self.libdir: return - libdir = libdir[0] - # Don't override what was set in the environment - if self.libdir: - self.libdir = libdir - globber = 'libboost_*-gd-*.lib' if self.static else 'boost_*-gd-*.lib' # FIXME - for entry in glob.glob(os.path.join(libdir, globber)): + + for name in self.need_static_link: + libname = "lib{}".format(name) + '-' + compiler + if self.is_multithreading: + libname = libname + '-mt' + if self.is_debug: + libname = libname + '-gd' + libname = libname + "-{}.lib".format(self.version.replace('.', '_')) + if os.path.isfile(os.path.join(self.libdir, libname)): + modname = libname.split('-', 1)[0][3:] + self.lib_modules[modname] = libname + else: + libname = "lib{}.lib".format(name) + if os.path.isfile(os.path.join(self.libdir, libname)): + self.lib_modules[name[3:]] = libname + + # globber1 applies to a layout=system installation + # globber2 applies to a layout=versioned installation + globber1 = 'libboost_*' if self.static else 'boost_*' + globber2 = globber1 + '-' + compiler + if self.is_multithreading: + globber2 = globber2 + '-mt' + if self.is_debug: + globber2 = globber2 + '-gd' + globber2 = globber2 + '-{}'.format(self.version.replace('.', '_')) + globber2_matches = glob.glob(os.path.join(self.libdir, globber2 + '.lib')) + for entry in globber2_matches: (_, fname) = os.path.split(entry) - base = fname.split('_', 1)[1] - modname = base.split('-', 1)[0] - self.lib_modules_mt[modname] = fname + modname = fname.split('-', 1) + if len(modname) > 1: + modname = modname[0] + else: + modname = modname.split('.', 1)[0] + if self.static: + modname = modname[3:] + self.lib_modules[modname] = fname + if len(globber2_matches) == 0: + for entry in glob.glob(os.path.join(self.libdir, globber1 + '.lib')): + (_, fname) = os.path.split(entry) + modname = fname.split('.', 1)[0] + if self.static: + modname = modname[3:] + self.lib_modules[modname] = fname def detect_lib_modules_nix(self): if self.static: @@ -203,25 +323,32 @@ class BoostDependency(ExternalDependency): else: libdirs = [os.path.join(self.boost_root, 'lib')] for libdir in libdirs: + for name in self.need_static_link: + libname = 'lib{}.a'.format(name) + if os.path.isfile(os.path.join(libdir, libname)): + self.lib_modules[name] = libname for entry in glob.glob(os.path.join(libdir, globber)): lib = os.path.basename(entry) - name = lib.split('.')[0].split('_', 1)[-1] + name = lib.split('.')[0][3:] # I'm not 100% sure what to do here. Some distros # have modules such as thread only as -mt versions. - if entry.endswith('-mt.{}'.format(libsuffix)): - self.lib_modules_mt[name] = True - else: - self.lib_modules[name] = True + # On debian all packages are built threading=multi + # but not suffixed with -mt. + # FIXME: implement detect_lib_modules_{debian, redhat, ...} + if self.is_multithreading and mesonlib.is_debianlike(): + self.lib_modules[name] = lib + elif self.is_multithreading and entry.endswith('-mt.{}'.format(libsuffix)): + self.lib_modules[name] = lib + elif not entry.endswith('-mt.{}'.format(libsuffix)): + self.lib_modules[name] = lib def get_win_link_args(self): args = [] # TODO: should this check self.libdir? - if self.boost_root: + if self.libdir: args.append('-L' + self.libdir) - for module in self.requested_modules: - module = BoostDependency.name2lib.get(module, module) - if module in self.lib_modules_mt: - args.append(self.lib_modules_mt[module]) + for lib in self.requested_modules: + args.append(self.lib_modules['boost_' + lib]) return args def get_link_args(self): @@ -232,33 +359,14 @@ class BoostDependency(ExternalDependency): args.append('-L' + os.path.join(self.boost_root, 'lib')) elif self.libdir: args.append('-L' + self.libdir) - for module in self.requested_modules: - module = BoostDependency.name2lib.get(module, module) - libname = 'boost_' + module + for lib in self.requested_modules: # The compiler's library detector is the most reliable so use that first. - default_detect = self.compiler.find_library(libname, self.env, []) + default_detect = self.compiler.find_library('boost_' + lib, self.env, []) if default_detect is not None: - if module == 'unit_testing_framework': - emon_args = self.compiler.find_library('boost_test_exec_monitor') - else: - emon_args = None args += default_detect - if emon_args is not None: - args += emon_args - elif module in self.lib_modules or module in self.lib_modules_mt: - linkcmd = '-l' + libname - args.append(linkcmd) - # FIXME a hack, but Boost's testing framework has a lot of - # different options and it's hard to determine what to do - # without feedback from actual users. Update this - # as we get more bug reports. - if module == 'unit_testing_framework': - args.append('-lboost_test_exec_monitor') - elif module + '-mt' in self.lib_modules_mt: - linkcmd = '-lboost_' + module + '-mt' + elif lib in self.lib_modules: + linkcmd = '-l' + lib args.append(linkcmd) - if module == 'unit_testing_framework': - args.append('-lboost_test_exec_monitor-mt') return args def get_sources(self): @@ -653,3 +761,78 @@ class CupsDependency(ExternalDependency): return [DependencyMethods.PKGCONFIG, DependencyMethods.CUPSCONFIG, DependencyMethods.EXTRAFRAMEWORK] else: return [DependencyMethods.PKGCONFIG, DependencyMethods.CUPSCONFIG] + +# Generated with boost_names.py +BOOST_LIBS = [ + 'boost_atomic', + 'boost_chrono', + 'boost_chrono', + 'boost_container', + 'boost_context', + 'boost_coroutine', + 'boost_date_time', + 'boost_exception', + 'boost_fiber', + 'boost_filesystem', + 'boost_graph', + 'boost_iostreams', + 'boost_locale', + 'boost_log', + 'boost_log_setup', + 'boost_math_tr1', + 'boost_math_tr1f', + 'boost_math_tr1l', + 'boost_math_c99', + 'boost_math_c99f', + 'boost_math_c99l', + 'boost_math_tr1', + 'boost_math_tr1f', + 'boost_math_tr1l', + 'boost_math_c99', + 'boost_math_c99f', + 'boost_math_c99l', + 'boost_math_tr1', + 'boost_math_tr1f', + 'boost_math_tr1l', + 'boost_math_c99', + 'boost_math_c99f', + 'boost_math_c99l', + 'boost_math_tr1', + 'boost_math_tr1f', + 'boost_math_tr1l', + 'boost_math_c99', + 'boost_math_c99f', + 'boost_math_c99l', + 'boost_math_tr1', + 'boost_math_tr1f', + 'boost_math_tr1l', + 'boost_math_c99', + 'boost_math_c99f', + 'boost_math_c99l', + 'boost_math_tr1', + 'boost_math_tr1f', + 'boost_math_tr1l', + 'boost_math_c99', + 'boost_math_c99f', + 'boost_math_c99l', + 'boost_mpi', + 'boost_random', + 'boost_regex', + 'boost_serialization', + 'boost_wserialization', + 'boost_signals', + 'boost_stacktrace_noop', + 'boost_stacktrace_backtrace', + 'boost_stacktrace_addr2line', + 'boost_stacktrace_basic', + 'boost_stacktrace_windbg', + 'boost_stacktrace_windbg_cached', + 'boost_system', + 'boost_prg_exec_monitor', + 'boost_test_exec_monitor', + 'boost_unit_test_framework', + 'boost_thread', + 'boost_timer', + 'boost_type_erasure', + 'boost_wave' +] diff --git a/test cases/frameworks/1 boost/meson.build b/test cases/frameworks/1 boost/meson.build index 6f25f8bb2..b73f93a74 100644 --- a/test cases/frameworks/1 boost/meson.build +++ b/test cases/frameworks/1 boost/meson.build @@ -9,21 +9,18 @@ add_project_arguments(['-DBOOST_LOG_DYN_LINK'], # within one project. The need to be independent of each other. # Use one without a library dependency and one with it. -nolinkdep = dependency('boost', modules: 'utility') linkdep = dependency('boost', modules : ['thread', 'system']) staticdep = dependency('boost', modules : ['thread', 'system'], static : true) -testdep = dependency('boost', modules : 'test') +testdep = dependency('boost', modules : ['unit_test_framework']) nomoddep = dependency('boost') extralibdep = dependency('boost', modules : ['thread', 'system', 'log_setup', 'log']) -nolinkexe = executable('nolinkedexe', 'nolinkexe.cc', dependencies : nolinkdep) linkexe = executable('linkedexe', 'linkexe.cc', dependencies : linkdep) staticexe = executable('staticlinkedexe', 'linkexe.cc', dependencies : staticdep) unitexe = executable('utf', 'unit_test.cpp', dependencies: testdep) nomodexe = executable('nomod', 'nomod.cpp', dependencies : nomoddep) extralibexe = executable('extralibexe', 'extralib.cpp', dependencies : extralibdep) -test('Boost nolinktest', nolinkexe) test('Boost linktest', linkexe) test('Boost statictest', staticexe) test('Boost UTF test', unitexe) diff --git a/test cases/frameworks/1 boost/nolinkexe.cc b/test cases/frameworks/1 boost/nolinkexe.cc deleted file mode 100644 index 7b6c6d92b..000000000 --- a/test cases/frameworks/1 boost/nolinkexe.cc +++ /dev/null @@ -1,12 +0,0 @@ -#include - -class MyClass : boost::noncopyable { -public: - MyClass() {}; - ~MyClass() {}; -}; - -int main(int argc, char **argv) { - MyClass obj; - return 0; -} diff --git a/tools/boost_names.py b/tools/boost_names.py new file mode 100755 index 000000000..9ac16bbc3 --- /dev/null +++ b/tools/boost_names.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python3 + +# Copyright 2017 Niklas Claesson + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""This is two implementations for how to get module names from the boost +sources. One relies on json metadata files in the sources, the other relies on +the folder names. + +Run the tool in the boost directory and append the stdout to the misc.py: + +boost/$ path/to/meson/tools/boost_names.py >> path/to/meson/dependencies/misc.py +""" + +import sys +import os +import collections +import pprint +import json +import re + +Module = collections.namedtuple('Module', ['dirname', 'name', 'libnames']) +Module.__repr__ = lambda self: str((self.dirname, self.name, self.libnames)) + +LIBS = 'libs' + +manual_map = { + 'callable_traits': 'Call Traits', + 'crc': 'CRC', + 'dll': 'DLL', + 'gil': 'GIL', + 'graph_parallel': 'GraphParallel', + 'icl': 'ICL', + 'io': 'IO State Savers', + 'msm': 'Meta State Machine', + 'mpi': 'MPI', + 'mpl': 'MPL', + 'multi_array': 'Multi-Array', + 'multi_index': 'Multi-Index', + 'numeric': 'Numeric Conversion', + 'ptr_container': 'Pointer Container', + 'poly_collection': 'PolyCollection', + 'qvm': 'QVM', + 'throw_exception': 'ThrowException', + 'tti': 'TTI', + 'vmd': 'VMD', +} + +extra = [ + Module('utility', 'Compressed Pair', []), + Module('core', 'Enable If', []), + Module('functional', 'Functional/Factory', []), + Module('functional', 'Functional/Forward', []), + Module('functional', 'Functional/Hash', []), + Module('functional', 'Functional/Overloaded Function', []), + Module('utility', 'Identity Type', []), + Module('utility', 'In Place Factory, Typed In Place Factory', []), + Module('numeric', 'Interval', []), + Module('math', 'Math Common Factor', []), + Module('math', 'Math Octonion', []), + Module('math', 'Math Quaternion', []), + Module('math', 'Math/Special Functions', []), + Module('math', 'Math/Statistical Distributions', []), + Module('bind', 'Member Function', []), + Module('algorithm', 'Min-Max', []), + Module('numeric', 'Odeint', []), + Module('utility', 'Operators', []), + Module('core', 'Ref', []), + Module('utility', 'Result Of', []), + Module('algorithm', 'String Algo', []), + Module('core', 'Swap', []), + Module('', 'Tribool', []), + Module('numeric', 'uBLAS', []), + Module('utility', 'Value Initialized', []), +] + +# Cannot find the following modules in the documentation of boost +not_modules = ['beast', 'logic', 'mp11', 'winapi'] + +def eprint(message): + print(message, file=sys.stderr) + +def get_library_names(jamfile): + libs = [] + with open(jamfile) as jamfh: + jam = jamfh.read() + res = re.finditer(r'^lib[\s]+([A-Za-z0-9_]+)([^;]*);', jam, re.MULTILINE | re.DOTALL) + for matches in res: + if ':' in matches.group(2): + libs.append(matches.group(1)) + return libs + +def exists(modules, module): + return len([x for x in modules if x.dirname == module.dirname]) != 0 + +def get_modules(init=extra): + modules = init + for directory in os.listdir(LIBS): + if not os.path.isdir(os.path.join(LIBS, directory)): + continue + if directory in not_modules: + continue + jamfile = os.path.join(LIBS, directory, 'build', 'Jamfile.v2') + if os.path.isfile(jamfile): + libs = get_library_names(jamfile) + else: + libs = [] + if directory in manual_map.keys(): + modname = manual_map[directory] + else: + modname = directory.replace('_', ' ').title() + modules.append(Module(directory, modname, libs)) + return modules + +def get_modules_2(): + modules = [] + for (root, dirs, files) in os.walk(LIBS): + for f in files: + if f == "libraries.json": + projectdir = os.path.dirname(root) + + jamfile = os.path.join(projectdir, 'build', 'Jamfile.v2') + if os.path.isfile(jamfile): + libs = get_library_names(jamfile) + else: + libs = [] + + # Get metadata for module + jsonfile = os.path.join(root, f) + with open(jsonfile) as jsonfh: + boost_modules = json.loads(jsonfh.read()) + if(isinstance(boost_modules, dict)): + boost_modules = [boost_modules] + for boost_module in boost_modules: + modules.append(Module(boost_module['key'], boost_module['name'], libs)) + + # Some subprojects do not have meta directory with json file. Find those + jsonless_modules = [x for x in get_modules([]) if not exists(modules, x)] + for module in jsonless_modules: + eprint("WARNING: {} does not have meta/libraries.json. Will guess pretty name '{}'".format(module.dirname, module.name)) + modules.extend(jsonless_modules) + + return modules + +def main(args): + if not os.path.isdir(LIBS): + eprint("ERROR: script must be run in boost source directory") + + # It will pick jsonless algorithm if 1 is given as argument + impl = 0 + if len(args) > 1: + if args[1] == '1': + impl = 1 + + if impl == 1: + modules = get_modules() + else: + modules = get_modules_2() + + sorted_modules = sorted(modules, key=lambda module: module.name.lower()) + sorted_modules = [x[2] for x in sorted_modules if x[2]] + sorted_modules = sum(sorted_modules, []) + sorted_modules = [x for x in sorted_modules if x.startswith('boost')] + + pp = pprint.PrettyPrinter() + pp.pprint(sorted_modules) + +if __name__ == '__main__': + main(sys.argv) -- cgit v1.2.3 From a9258923fac2ab145a94f7c72cc5c0127d50bfe2 Mon Sep 17 00:00:00 2001 From: Alexis Jeandet Date: Sun, 1 Oct 2017 16:18:31 +0200 Subject: Added include directory argument for Qt's Moc which is needed to build plugins. Signed-off-by: Alexis Jeandet --- docs/markdown/Qt5-module.md | 8 +++++--- mesonbuild/modules/qt4.py | 10 ++++++---- mesonbuild/modules/qt5.py | 10 ++++++---- test cases/frameworks/4 qt/meson.build | 10 ++++++++++ test cases/frameworks/4 qt/plugin/plugin.cpp | 7 +++++++ test cases/frameworks/4 qt/plugin/plugin.h | 11 +++++++++++ test cases/frameworks/4 qt/plugin/plugin.json | 3 +++ .../frameworks/4 qt/pluginInterface/plugin_if.h | 21 +++++++++++++++++++++ 8 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 test cases/frameworks/4 qt/plugin/plugin.cpp create mode 100644 test cases/frameworks/4 qt/plugin/plugin.h create mode 100644 test cases/frameworks/4 qt/plugin/plugin.json create mode 100644 test cases/frameworks/4 qt/pluginInterface/plugin_if.h (limited to 'docs') diff --git a/docs/markdown/Qt5-module.md b/docs/markdown/Qt5-module.md index 7082309ad..a8ad73d63 100644 --- a/docs/markdown/Qt5-module.md +++ b/docs/markdown/Qt5-module.md @@ -5,17 +5,19 @@ tools and steps required for Qt. The module has one method. ## preprocess -This method takes four keyword arguments, `moc_headers`, +This method takes five keyword arguments, `moc_headers`, `moc_sources`, `ui_files` and `qresources` which define the files that -require preprocessing with `moc`, `uic` and `rcc`. It returns an +require preprocessing with `moc`, `uic` and `rcc` and 'include_directories' which might be needed by moc. It returns an opaque object that should be passed to a main build target. A simple example would look like this: ```meson qt5 = import('qt5') qt5_dep = dependency('qt5', modules: ['Core', 'Gui']) -moc_files = qt5.preprocess(moc_headers : 'myclass.h') +inc = include_directories('includes') +moc_files = qt5.preprocess(moc_headers : 'myclass.h', include_directories: inc) executable('myprog', 'main.cpp', 'myclass.cpp', moc_files, + include_directories: inc, dependencies : qt5_dep) ``` diff --git a/mesonbuild/modules/qt4.py b/mesonbuild/modules/qt4.py index a63aff828..4ab07b9f7 100644 --- a/mesonbuild/modules/qt4.py +++ b/mesonbuild/modules/qt4.py @@ -21,6 +21,7 @@ from . import ExtensionModule import xml.etree.ElementTree as ET from . import ModuleReturnValue from ..interpreterbase import permittedKwargs +from . import get_include_args class Qt4Module(ExtensionModule): tools_detected = False @@ -97,10 +98,10 @@ class Qt4Module(ExtensionModule): except Exception: return [] - @permittedKwargs({'moc_headers', 'moc_sources', 'ui_files', 'qresources', 'method'}) + @permittedKwargs({'moc_headers', 'moc_sources', 'include_directories', 'ui_files', 'qresources', 'method'}) def preprocess(self, state, args, kwargs): - rcc_files, ui_files, moc_headers, moc_sources, sources \ - = extract_as_list(kwargs, 'qresources', 'ui_files', 'moc_headers', 'moc_sources', 'sources', pop = True) + rcc_files, ui_files, moc_headers, moc_sources, sources, include_directories \ + = extract_as_list(kwargs, 'qresources', 'ui_files', 'moc_headers', 'moc_sources', 'sources', 'include_directories', pop = True) sources += args[1:] method = kwargs.get('method', 'auto') self._detect_tools(state.environment, method) @@ -133,9 +134,10 @@ class Qt4Module(ExtensionModule): ui_gen = build.Generator([self.uic], ui_kwargs) ui_output = ui_gen.process_files('Qt4 ui', ui_files, state) sources.append(ui_output) + inc = get_include_args(include_dirs=include_directories) if len(moc_headers) > 0: moc_kwargs = {'output': 'moc_@BASENAME@.cpp', - 'arguments': ['@INPUT@', '-o', '@OUTPUT@']} + 'arguments': inc + ['@INPUT@', '-o', '@OUTPUT@']} moc_gen = build.Generator([self.moc], moc_kwargs) moc_output = moc_gen.process_files('Qt4 moc header', moc_headers, state) sources.append(moc_output) diff --git a/mesonbuild/modules/qt5.py b/mesonbuild/modules/qt5.py index 08ce66213..001caa702 100644 --- a/mesonbuild/modules/qt5.py +++ b/mesonbuild/modules/qt5.py @@ -21,6 +21,7 @@ from . import ExtensionModule import xml.etree.ElementTree as ET from . import ModuleReturnValue from ..interpreterbase import permittedKwargs +from . import get_include_args class Qt5Module(ExtensionModule): tools_detected = False @@ -103,10 +104,10 @@ class Qt5Module(ExtensionModule): except Exception: return [] - @permittedKwargs({'moc_headers', 'moc_sources', 'ui_files', 'qresources', 'method'}) + @permittedKwargs({'moc_headers', 'moc_sources', 'include_directories', 'ui_files', 'qresources', 'method'}) def preprocess(self, state, args, kwargs): - rcc_files, ui_files, moc_headers, moc_sources, sources \ - = extract_as_list(kwargs, 'qresources', 'ui_files', 'moc_headers', 'moc_sources', 'sources', pop = True) + rcc_files, ui_files, moc_headers, moc_sources, sources, include_directories \ + = extract_as_list(kwargs, 'qresources', 'ui_files', 'moc_headers', 'moc_sources', 'sources', 'include_directories', pop = True) sources += args[1:] method = kwargs.get('method', 'auto') self._detect_tools(state.environment, method) @@ -139,9 +140,10 @@ class Qt5Module(ExtensionModule): ui_gen = build.Generator([self.uic], ui_kwargs) ui_output = ui_gen.process_files('Qt5 ui', ui_files, state) sources.append(ui_output) + inc = get_include_args(include_dirs=include_directories) if len(moc_headers) > 0: moc_kwargs = {'output': 'moc_@BASENAME@.cpp', - 'arguments': ['@INPUT@', '-o', '@OUTPUT@']} + 'arguments': inc + ['@INPUT@', '-o', '@OUTPUT@']} moc_gen = build.Generator([self.moc], moc_kwargs) moc_output = moc_gen.process_files('Qt5 moc header', moc_headers, state) sources.append(moc_output) diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build index d9cab6fbe..c6f108bbc 100644 --- a/test cases/frameworks/4 qt/meson.build +++ b/test cases/frameworks/4 qt/meson.build @@ -70,5 +70,15 @@ foreach qt : ['qt4', 'qt5'] dependencies : qtcore) test(qt + 'maninclude', qtmaninclude) + + # building Qt plugins implies to give include path to moc + plugin_includes = include_directories('pluginInterface', 'plugin') + pluginpreprocess = qtmodule.preprocess( + moc_headers : 'plugin/plugin.h', + include_directories : plugin_includes + ) + plugin = library('plugin', 'plugin/plugin.cpp', pluginpreprocess, + include_directories : plugin_includes, + dependencies : qtcore) endif endforeach diff --git a/test cases/frameworks/4 qt/plugin/plugin.cpp b/test cases/frameworks/4 qt/plugin/plugin.cpp new file mode 100644 index 000000000..eeae98db7 --- /dev/null +++ b/test cases/frameworks/4 qt/plugin/plugin.cpp @@ -0,0 +1,7 @@ +#include "plugin.h" +#include + +QString plugin1::getResource() +{ + return "hello world"; +} diff --git a/test cases/frameworks/4 qt/plugin/plugin.h b/test cases/frameworks/4 qt/plugin/plugin.h new file mode 100644 index 000000000..1138f412e --- /dev/null +++ b/test cases/frameworks/4 qt/plugin/plugin.h @@ -0,0 +1,11 @@ +#pragma once +#include + +class plugin1:public QObject,public PluginInterface +{ + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID "demo.PluginInterface" FILE "plugin.json") +public: + QString getResource() override; +}; diff --git a/test cases/frameworks/4 qt/plugin/plugin.json b/test cases/frameworks/4 qt/plugin/plugin.json new file mode 100644 index 000000000..6c6a0116d --- /dev/null +++ b/test cases/frameworks/4 qt/plugin/plugin.json @@ -0,0 +1,3 @@ +{ + "name" : "Plugin1" +} diff --git a/test cases/frameworks/4 qt/pluginInterface/plugin_if.h b/test cases/frameworks/4 qt/pluginInterface/plugin_if.h new file mode 100644 index 000000000..97d2800c3 --- /dev/null +++ b/test cases/frameworks/4 qt/pluginInterface/plugin_if.h @@ -0,0 +1,21 @@ +#ifndef PLUGIN_IF_H +#define PLUGIN_IF_H + +#include +#include + +/** + * @brief Interface for a plugin + */ +class PluginInterface +{ +public: + virtual ~PluginInterface() = default; + + /// Initializes the plugin + virtual QString getResource() = 0; +}; + +Q_DECLARE_INTERFACE(PluginInterface, "demo.PluginInterface") + +#endif -- cgit v1.2.3 From 893d101fff01d72e8df055491d8e609eb0fd8575 Mon Sep 17 00:00:00 2001 From: Patrick Griffis Date: Sun, 13 Aug 2017 12:43:21 -0400 Subject: gnome: Add header kwarg to generate_gir() This is a commonly used flag so lets make it more obvious. --- docs/markdown/Gnome-module.md | 4 ++++ mesonbuild/modules/gnome.py | 8 +++++++- test cases/frameworks/7 gnome/gir/dep1/meson.build | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/markdown/Gnome-module.md b/docs/markdown/Gnome-module.md index 99a9c8e9a..d87e10802 100644 --- a/docs/markdown/Gnome-module.md +++ b/docs/markdown/Gnome-module.md @@ -81,6 +81,10 @@ tool so see its documentation for more information. * `includes`: list of gir names to be included, can also be a GirTarget +* `header`: *(Added 0.43.0)* name of main c header to include for the library, e.g. `glib.h` + +* `dependencies`: deps to use during introspection scanning + * `include_directories`: extra include paths to look for gir files * `install`: if true, install the generated files diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index d1d7013d3..fa2bbb4f1 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -394,7 +394,7 @@ class GnomeModule(ExtensionModule): @permittedKwargs({'sources', 'nsversion', 'namespace', 'symbol_prefix', 'identifier_prefix', 'export_packages', 'includes', 'dependencies', 'link_with', 'include_directories', 'install', 'install_dir_gir', 'install_dir_typelib', 'extra_args', - 'packages', 'build_by_default'}) + 'packages', 'header', 'build_by_default'}) def generate_gir(self, state, args, kwargs): if len(args) != 1: raise MesonException('Gir takes one argument') @@ -429,6 +429,12 @@ class GnomeModule(ExtensionModule): scan_command += ['--no-libtool', '--namespace=' + ns, '--nsversion=' + nsversion, '--warn-all', '--output', '@OUTPUT@'] + header = kwargs.pop('header', None) + if header: + if not isinstance(header, str): + raise MesonException('header must be a string') + scan_command += ['--c-include=' + header] + extra_args = mesonlib.stringlistify(kwargs.pop('extra_args', [])) scan_command += extra_args scan_command += ['-I' + srcdir, diff --git a/test cases/frameworks/7 gnome/gir/dep1/meson.build b/test cases/frameworks/7 gnome/gir/dep1/meson.build index 75dd73166..baa0b1d68 100644 --- a/test cases/frameworks/7 gnome/gir/dep1/meson.build +++ b/test cases/frameworks/7 gnome/gir/dep1/meson.build @@ -19,6 +19,7 @@ dep1gir = gnome.generate_gir( namespace : 'MesonDep1', symbol_prefix : 'meson', identifier_prefix : 'Meson', + header: 'dep1.h', includes : ['GObject-2.0', 'MesonDep2-1.0'], dependencies : [dep2_dep], install : true -- cgit v1.2.3 From ec45c29c9ddd5d848eb1555cdc09246d8900afec Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Mon, 2 Oct 2017 00:56:38 +0300 Subject: Add rpath entries for all found libraries outside of system libraries. --- docs/markdown/snippets/prebuilt.md | 13 +++++++++---- mesonbuild/backend/backends.py | 11 ++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) (limited to 'docs') diff --git a/docs/markdown/snippets/prebuilt.md b/docs/markdown/snippets/prebuilt.md index a51176acc..19741c463 100644 --- a/docs/markdown/snippets/prebuilt.md +++ b/docs/markdown/snippets/prebuilt.md @@ -1,9 +1,14 @@ -# Better support for prebuilt shared libraries +# Better support for shared libraries in non-system paths Meson has had support for prebuilt object files and static libraries. -This release adds feature parity to shared libraries. This means -that e.g. shipping prebuilt libraries as subprojects now can -be as simple as writing a definition file that looks like this. +This release adds feature parity to shared libraries that are either +in non-standard system paths or shipped as part of your project. On +systems that support rpath, Meson automatically adds rpath entries +to built targets using manually found external libraries. + +This means that e.g. supporting prebuilt libraries shipped with your +source or provided by subprojects or wrap definitions by writing a +build file like this: project('myprebuiltlibrary', 'c') diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index c737d491f..e0e2abc2c 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -303,13 +303,16 @@ class Backend: for dep in target.external_deps: if isinstance(dep, dependencies.ExternalLibrary): la = dep.link_args - if len(la) == 1 and la[0].startswith(self.environment.get_source_dir()): + if len(la) == 1 and os.path.isabs(la[0]): # The only link argument is an absolute path to a library file. libpath = la[0] + if libpath.startswith(('/usr/lib', '/lib')): + # No point in adding system paths. + continue if os.path.splitext(libpath)[1] not in ['.dll', '.lib', '.so']: continue absdir = os.path.split(libpath)[0] - rel_to_src = absdir[len(self.environment.get_source_dir())+1:] + rel_to_src = absdir[len(self.environment.get_source_dir()) + 1:] assert(not os.path.isabs(rel_to_src)) paths.append(os.path.join(self.build_to_src, rel_to_src)) return paths @@ -321,7 +324,9 @@ class Backend: prospective = self.get_target_dir(ld) if prospective not in result: result.append(prospective) - result += self.rpaths_for_bundled_shared_libraries(target) + for rp in self.rpaths_for_bundled_shared_libraries(target): + if rp not in result: + result += [rp] return result def object_filename_from_source(self, target, source, is_unity): -- cgit v1.2.3 From 35313c2a850020dc2d98c1aa5b2f4340e49f01d6 Mon Sep 17 00:00:00 2001 From: Mohammed Sadiq Date: Mon, 2 Oct 2017 16:05:10 +0530 Subject: docs: Fix typo Remove the quote before parens --- docs/markdown/Reference-manual.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index f37fb3435..3bdd3c514 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -1614,7 +1614,7 @@ during tests. It should be passed as the `env` keyword argument to tests. It has the following methods. - `append(varname, value)` appends the given value to the old value of - the environment variable, e.g. `env.append'('FOO', 'BAR', separator + the environment variable, e.g. `env.append('FOO', 'BAR', separator : ';')` produces `BOB;BAR` if `FOO` had the value `BOB` and plain `BAR` if the value was not defined. If the separator is not specified explicitly, the default path separator for the host -- cgit v1.2.3 From a28db4577a36bf53f09e439f2032f28eb9cd7079 Mon Sep 17 00:00:00 2001 From: xarkes Date: Mon, 2 Oct 2017 21:18:36 +0200 Subject: Fix typo and clarify library documentation --- docs/markdown/Reference-manual.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 3bdd3c514..86ad15e03 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -820,10 +820,11 @@ static with only one option. The keyword arguments for this are the same as for [`executable`](#executable) with the following additions: -- `name_prefix` the string that will be used as the suffix for the +- `name_suffix` the string that will be used as the suffix for the target by overriding the default (only used for libraries). By default this is `lib` on all platforms and compilers except with - MSVC where it is omitted. + MSVC where it is omitted and set to `a` to avoid potential name clash + with shared libraries (which also generates `lib` files). - `rust_crate_type` specifies the crate type for Rust libraries. Defaults to `dylib` for shared libraries and `rlib` for static libraries. -- cgit v1.2.3 From f10b15930bb40424df0d0254ea5576b24b3c10df Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 3 Oct 2017 05:49:24 +0000 Subject: Update Reference-manual.md Fix documentation breakage from https://github.com/mesonbuild/meson/pull/2415 --- docs/markdown/Reference-manual.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 86ad15e03..0cc6771a7 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -820,11 +820,18 @@ static with only one option. The keyword arguments for this are the same as for [`executable`](#executable) with the following additions: +- `name_prefix` the string that will be used as the prefix for the + target output filename by overriding the default (only used for + libraries). By default this is `lib` on all platforms and compilers + except with MSVC where it is omitted to follow convention. - `name_suffix` the string that will be used as the suffix for the - target by overriding the default (only used for libraries). By - default this is `lib` on all platforms and compilers except with - MSVC where it is omitted and set to `a` to avoid potential name clash - with shared libraries (which also generates `lib` files). + target output filename by overriding the default (see also: + [executable()](#executable)). By default, for shared libraries this + is `dylib` on macOS, `dll` on Windows, and `so` everywhere else. + For static libraries, it is `a` everywhere. By convention MSVC + static libraries use the `lib` suffix, but we use `a` to avoid a + potential name clash with shared libraries which also generate + `xxx.lib` import files. - `rust_crate_type` specifies the crate type for Rust libraries. Defaults to `dylib` for shared libraries and `rlib` for static libraries. -- cgit v1.2.3 From 0c3d58baba4a61558ed9b4905f26155a3e95cf6c Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 3 Oct 2017 06:57:46 +0000 Subject: Update Reference-manual.md --- docs/markdown/Reference-manual.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 0cc6771a7..14097ed18 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -823,7 +823,8 @@ The keyword arguments for this are the same as for [`executable`](#executable) w - `name_prefix` the string that will be used as the prefix for the target output filename by overriding the default (only used for libraries). By default this is `lib` on all platforms and compilers - except with MSVC where it is omitted to follow convention. + except with MSVC shared libraries where it is omitted to follow + convention. - `name_suffix` the string that will be used as the suffix for the target output filename by overriding the default (see also: [executable()](#executable)). By default, for shared libraries this -- cgit v1.2.3