aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2017-06-22 06:12:27 -0400
committerGitHub <noreply@github.com>2017-06-22 06:12:27 -0400
commit65d5ec5f18f645a7b4d10de10b63a329718a7939 (patch)
treeb63b5c11125d08b35ceae512d9582962f90f10e3
parent185808bf167fb7477211c7b624cd7a3ba3c4ce77 (diff)
parent6165612f6bb06c0f41422a9768caf2eba03849a9 (diff)
downloadmeson-65d5ec5f18f645a7b4d10de10b63a329718a7939.zip
meson-65d5ec5f18f645a7b4d10de10b63a329718a7939.tar.gz
meson-65d5ec5f18f645a7b4d10de10b63a329718a7939.tar.bz2
Merge pull request #1922 from acfoltzer/rust-improvements
Enhance Rust support
-rw-r--r--docs/markdown/Reference-manual.md5
-rw-r--r--mesonbuild/backend/ninjabackend.py36
-rw-r--r--mesonbuild/build.py45
-rw-r--r--mesonbuild/compilers.py12
-rw-r--r--test cases/failing/55 wrong shared crate type/foo.rs0
-rw-r--r--test cases/failing/55 wrong shared crate type/meson.build3
-rw-r--r--test cases/failing/56 wrong static crate type/foo.rs0
-rw-r--r--test cases/failing/56 wrong static crate type/meson.build3
-rw-r--r--test cases/rust/2 sharedlib/installed_files.txt2
-rw-r--r--test cases/rust/4 polyglot/installed_files.txt2
-rw-r--r--test cases/rust/4 polyglot/meson.build5
-rw-r--r--test cases/rust/4 polyglot/prog.c8
-rw-r--r--test cases/rust/4 polyglot/stuff.rs6
-rw-r--r--test cases/rust/5 polyglot static/installed_files.txt2
-rw-r--r--test cases/rust/5 polyglot static/meson.build10
-rw-r--r--test cases/rust/5 polyglot static/prog.c8
-rw-r--r--test cases/rust/5 polyglot static/stuff.rs6
17 files changed, 139 insertions, 14 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 492666b..dd77d6d 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -510,11 +510,12 @@ Joins the given strings into a file system path segment. For example `join_paths
Builds a library that is either static or shared depending on the value of `default_library` user option. You should use this instead of [`shared_library`](#shared_library) or [`static_library`](#static_library) most of the time. This allows you to toggle your entire project (including subprojects) from shared to static with only one option.
-The keyword arguments for this are the same as for [`executable`](#executable) with the following addition:
+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 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.
+- `rust_crate_type` specifies the crate type for Rust libraries. Defaults to `dylib` for shared libraries and `rlib` for static libraries.
-`static_library` and `shared_library` also accept this keyword argument.
+`static_library` and `shared_library` also accept these keyword arguments.
### message()
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 415b554..761d508 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1165,8 +1165,10 @@ int dummy;
args = ['--crate-type']
if isinstance(target, build.Executable):
cratetype = 'bin'
+ elif hasattr(target, 'rust_crate_type'):
+ cratetype = target.rust_crate_type
elif isinstance(target, build.SharedLibrary):
- cratetype = 'rlib'
+ cratetype = 'dylib'
elif isinstance(target, build.StaticLibrary):
cratetype = 'rlib'
else:
@@ -1185,6 +1187,36 @@ int dummy;
if d == '':
d = '.'
args += ['-L', d]
+ has_shared_deps = False
+ for dep in target.get_dependencies():
+ if isinstance(dep, build.SharedLibrary):
+ has_shared_deps = True
+ if isinstance(target, build.SharedLibrary) or has_shared_deps:
+ # add prefer-dynamic if any of the Rust libraries we link
+ # against are dynamic, otherwise we'll end up with
+ # multiple implementations of crates
+ args += ['-C', 'prefer-dynamic']
+
+ # build the usual rpath arguments as well...
+
+ # Set runtime-paths so we can run executables without needing to set
+ # LD_LIBRARY_PATH, etc in the environment. Doesn't work on Windows.
+ if '/' in target.name or '\\' in target.name:
+ # Target names really should not have slashes in them, but
+ # unfortunately we did not check for that and some downstream projects
+ # now have them. Once slashes are forbidden, remove this bit.
+ target_slashname_workaround_dir = os.path.join(os.path.split(target.name)[0],
+ self.get_target_dir(target))
+ else:
+ target_slashname_workaround_dir = self.get_target_dir(target)
+ rpath_args = rustc.build_rpath_args(self.environment.get_build_dir(),
+ target_slashname_workaround_dir,
+ self.determine_rpath_dirs(target),
+ target.install_rpath)
+ # ... but then add rustc's sysroot to account for rustup
+ # installations
+ for rpath_arg in rpath_args:
+ args += ['-C', 'link-arg=' + rpath_arg + ':' + os.path.join(rustc.get_sysroot(), 'lib')]
element = NinjaBuildElement(self.all_outputs, target_name, 'rust_COMPILER', relsrc)
if len(orderdeps) > 0:
element.add_orderdep(orderdeps)
@@ -1192,6 +1224,8 @@ int dummy;
element.add_item('targetdep', depfile)
element.add_item('cratetype', cratetype)
element.write(outfile)
+ if isinstance(target, build.SharedLibrary):
+ self.generate_shsym(outfile, target)
def swift_module_file_name(self, target):
return os.path.join(self.get_target_private_dir(target),
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index ba30fec..c73ba3a 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -71,6 +71,7 @@ known_lib_kwargs.update({'version': True, # Only for shared libs
'vala_vapi': True,
'vala_gir': True,
'pic': True, # Only for static libs
+ 'rust_crate_type': True, # Only for Rust libs
})
@@ -1123,6 +1124,14 @@ class StaticLibrary(BuildTarget):
super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs)
if 'cs' in self.compilers:
raise InvalidArguments('Static libraries not supported for C#.')
+ if 'rust' in self.compilers:
+ # If no crate type is specified, or it's the generic lib type, use rlib
+ if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'lib':
+ mlog.debug('Defaulting Rust static library target crate type to rlib')
+ self.rust_crate_type = 'rlib'
+ # Don't let configuration proceed with a non-static crate type
+ elif self.rust_crate_type not in ['rlib', 'staticlib']:
+ raise InvalidArguments('Crate type "{0}" invalid for static libraries; must be "rlib" or "staticlib"'.format(self.rust_crate_type))
# By default a static library is named libfoo.a even on Windows because
# MSVC does not have a consistent convention for what static libraries
# are called. The MSVC CRT uses libfoo.lib syntax but nothing else uses
@@ -1133,9 +1142,12 @@ class StaticLibrary(BuildTarget):
if not hasattr(self, 'prefix'):
self.prefix = 'lib'
if not hasattr(self, 'suffix'):
- # Rust static library crates have .rlib suffix
if 'rust' in self.compilers:
- self.suffix = 'rlib'
+ if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'rlib':
+ # default Rust static library suffix
+ self.suffix = 'rlib'
+ elif self.rust_crate_type == 'staticlib':
+ self.suffix = 'a'
else:
self.suffix = 'a'
self.filename = self.prefix + self.name + '.' + self.suffix
@@ -1147,6 +1159,15 @@ class StaticLibrary(BuildTarget):
def check_unknown_kwargs(self, kwargs):
self.check_unknown_kwargs_int(kwargs, known_lib_kwargs)
+ def process_kwargs(self, kwargs, environment):
+ super().process_kwargs(kwargs, environment)
+ if 'rust_crate_type' in kwargs:
+ rust_crate_type = kwargs['rust_crate_type']
+ if isinstance(rust_crate_type, str):
+ self.rust_crate_type = rust_crate_type
+ else:
+ raise InvalidArguments('Invalid rust_crate_type "{0}": must be a string.'.format(rust_crate_type))
+
class SharedLibrary(BuildTarget):
def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
self.soversion = None
@@ -1159,6 +1180,14 @@ class SharedLibrary(BuildTarget):
# The import library that GCC would generate (and prefer)
self.gcc_import_filename = None
super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs)
+ if 'rust' in self.compilers:
+ # If no crate type is specified, or it's the generic lib type, use dylib
+ if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'lib':
+ mlog.debug('Defaulting Rust dynamic library target crate type to "dylib"')
+ self.rust_crate_type = 'dylib'
+ # Don't let configuration proceed with a non-dynamic crate type
+ elif self.rust_crate_type not in ['dylib', 'cdylib']:
+ raise InvalidArguments('Crate type "{0}" invalid for dynamic libraries; must be "dylib" or "cdylib"'.format(self.rust_crate_type))
if not hasattr(self, 'prefix'):
self.prefix = None
if not hasattr(self, 'suffix'):
@@ -1200,12 +1229,6 @@ class SharedLibrary(BuildTarget):
prefix = ''
suffix = 'dll'
self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
- # Rust
- elif 'rust' in self.compilers:
- # Currently, we always build --crate-type=rlib
- prefix = 'lib'
- suffix = 'rlib'
- self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
# C, C++, Swift, Vala
# Only Windows uses a separate import library for linking
# For all other targets/platforms import_filename stays None
@@ -1315,6 +1338,12 @@ class SharedLibrary(BuildTarget):
raise InvalidArguments(
'Shared library vs_module_defs must be either a string, '
'a file object or a Custom Target')
+ if 'rust_crate_type' in kwargs:
+ rust_crate_type = kwargs['rust_crate_type']
+ if isinstance(rust_crate_type, str):
+ self.rust_crate_type = rust_crate_type
+ else:
+ raise InvalidArguments('Invalid rust_crate_type "{0}": must be a string.'.format(rust_crate_type))
def check_unknown_kwargs(self, kwargs):
self.check_unknown_kwargs_int(kwargs, known_lib_kwargs)
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
index 3b9972f..979a5ac 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -1570,7 +1570,7 @@ class MonoCompiler(Compiler):
def split_shlib_to_parts(self, fname):
return None, fname
- def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
+ def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
return []
def get_dependency_gen_args(self, outtarget, outfile):
@@ -1651,7 +1651,7 @@ class JavaCompiler(Compiler):
def split_shlib_to_parts(self, fname):
return None, fname
- def build_rpath_args(self, build_dir, rpath_paths, install_rpath):
+ def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
return []
def get_dependency_gen_args(self, outtarget, outfile):
@@ -1833,6 +1833,14 @@ class RustCompiler(Compiler):
def get_buildtype_args(self, buildtype):
return rust_buildtype_args[buildtype]
+ def build_rpath_args(self, build_dir, from_dir, rpath_paths, install_rpath):
+ return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, install_rpath)
+
+ def get_sysroot(self):
+ cmd = self.exelist + ['--print', 'sysroot']
+ p, stdo, stde = Popen_safe(cmd)
+ return stdo.split('\n')[0]
+
class SwiftCompiler(Compiler):
def __init__(self, exelist, version):
self.language = 'swift'
diff --git a/test cases/failing/55 wrong shared crate type/foo.rs b/test cases/failing/55 wrong shared crate type/foo.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test cases/failing/55 wrong shared crate type/foo.rs
diff --git a/test cases/failing/55 wrong shared crate type/meson.build b/test cases/failing/55 wrong shared crate type/meson.build
new file mode 100644
index 0000000..69ac3da
--- /dev/null
+++ b/test cases/failing/55 wrong shared crate type/meson.build
@@ -0,0 +1,3 @@
+project('test', 'rust')
+
+shared_library('test', 'foo.rs', rust_crate_type : 'staticlib')
diff --git a/test cases/failing/56 wrong static crate type/foo.rs b/test cases/failing/56 wrong static crate type/foo.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test cases/failing/56 wrong static crate type/foo.rs
diff --git a/test cases/failing/56 wrong static crate type/meson.build b/test cases/failing/56 wrong static crate type/meson.build
new file mode 100644
index 0000000..c094613
--- /dev/null
+++ b/test cases/failing/56 wrong static crate type/meson.build
@@ -0,0 +1,3 @@
+project('test', 'rust')
+
+static_library('test', 'foo.rs', rust_crate_type : 'cdylib')
diff --git a/test cases/rust/2 sharedlib/installed_files.txt b/test cases/rust/2 sharedlib/installed_files.txt
index 85acff2..680343d 100644
--- a/test cases/rust/2 sharedlib/installed_files.txt
+++ b/test cases/rust/2 sharedlib/installed_files.txt
@@ -1,2 +1,2 @@
usr/bin/prog?exe
-usr/lib/libstuff.rlib
+usr/lib/libstuff.so
diff --git a/test cases/rust/4 polyglot/installed_files.txt b/test cases/rust/4 polyglot/installed_files.txt
new file mode 100644
index 0000000..680343d
--- /dev/null
+++ b/test cases/rust/4 polyglot/installed_files.txt
@@ -0,0 +1,2 @@
+usr/bin/prog?exe
+usr/lib/libstuff.so
diff --git a/test cases/rust/4 polyglot/meson.build b/test cases/rust/4 polyglot/meson.build
new file mode 100644
index 0000000..a20d766
--- /dev/null
+++ b/test cases/rust/4 polyglot/meson.build
@@ -0,0 +1,5 @@
+project('rust and c polyglot executable', 'c', 'rust')
+
+l = library('stuff', 'stuff.rs', install : true)
+e = executable('prog', 'prog.c', link_with : l, install : true)
+test('polyglottest', e)
diff --git a/test cases/rust/4 polyglot/prog.c b/test cases/rust/4 polyglot/prog.c
new file mode 100644
index 0000000..18f2c36
--- /dev/null
+++ b/test cases/rust/4 polyglot/prog.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+void f();
+
+int main() {
+ printf("Hello from C!\n");
+ f();
+}
diff --git a/test cases/rust/4 polyglot/stuff.rs b/test cases/rust/4 polyglot/stuff.rs
new file mode 100644
index 0000000..ecf623c
--- /dev/null
+++ b/test cases/rust/4 polyglot/stuff.rs
@@ -0,0 +1,6 @@
+#![crate_name = "stuff"]
+
+#[no_mangle]
+pub extern fn f() {
+ println!("Hello from Rust!");
+}
diff --git a/test cases/rust/5 polyglot static/installed_files.txt b/test cases/rust/5 polyglot static/installed_files.txt
new file mode 100644
index 0000000..2f7a397
--- /dev/null
+++ b/test cases/rust/5 polyglot static/installed_files.txt
@@ -0,0 +1,2 @@
+usr/bin/prog?exe
+usr/lib/libstuff.a
diff --git a/test cases/rust/5 polyglot static/meson.build b/test cases/rust/5 polyglot static/meson.build
new file mode 100644
index 0000000..76dc790
--- /dev/null
+++ b/test cases/rust/5 polyglot static/meson.build
@@ -0,0 +1,10 @@
+project('static rust and c polyglot executable', 'c', 'rust')
+
+deps = [
+ meson.get_compiler('c').find_library('dl'),
+ dependency('threads'),
+]
+
+l = static_library('stuff', 'stuff.rs', rust_crate_type : 'staticlib', install : true)
+e = executable('prog', 'prog.c', dependencies: deps, link_with : l, install : true)
+test('polyglottest', e)
diff --git a/test cases/rust/5 polyglot static/prog.c b/test cases/rust/5 polyglot static/prog.c
new file mode 100644
index 0000000..18f2c36
--- /dev/null
+++ b/test cases/rust/5 polyglot static/prog.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+void f();
+
+int main() {
+ printf("Hello from C!\n");
+ f();
+}
diff --git a/test cases/rust/5 polyglot static/stuff.rs b/test cases/rust/5 polyglot static/stuff.rs
new file mode 100644
index 0000000..ecf623c
--- /dev/null
+++ b/test cases/rust/5 polyglot static/stuff.rs
@@ -0,0 +1,6 @@
+#![crate_name = "stuff"]
+
+#[no_mangle]
+pub extern fn f() {
+ println!("Hello from Rust!");
+}