diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2017-06-22 06:12:27 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-22 06:12:27 -0400 |
commit | 65d5ec5f18f645a7b4d10de10b63a329718a7939 (patch) | |
tree | b63b5c11125d08b35ceae512d9582962f90f10e3 | |
parent | 185808bf167fb7477211c7b624cd7a3ba3c4ce77 (diff) | |
parent | 6165612f6bb06c0f41422a9768caf2eba03849a9 (diff) | |
download | meson-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.md | 5 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 36 | ||||
-rw-r--r-- | mesonbuild/build.py | 45 | ||||
-rw-r--r-- | mesonbuild/compilers.py | 12 | ||||
-rw-r--r-- | test cases/failing/55 wrong shared crate type/foo.rs | 0 | ||||
-rw-r--r-- | test cases/failing/55 wrong shared crate type/meson.build | 3 | ||||
-rw-r--r-- | test cases/failing/56 wrong static crate type/foo.rs | 0 | ||||
-rw-r--r-- | test cases/failing/56 wrong static crate type/meson.build | 3 | ||||
-rw-r--r-- | test cases/rust/2 sharedlib/installed_files.txt | 2 | ||||
-rw-r--r-- | test cases/rust/4 polyglot/installed_files.txt | 2 | ||||
-rw-r--r-- | test cases/rust/4 polyglot/meson.build | 5 | ||||
-rw-r--r-- | test cases/rust/4 polyglot/prog.c | 8 | ||||
-rw-r--r-- | test cases/rust/4 polyglot/stuff.rs | 6 | ||||
-rw-r--r-- | test cases/rust/5 polyglot static/installed_files.txt | 2 | ||||
-rw-r--r-- | test cases/rust/5 polyglot static/meson.build | 10 | ||||
-rw-r--r-- | test cases/rust/5 polyglot static/prog.c | 8 | ||||
-rw-r--r-- | test cases/rust/5 polyglot static/stuff.rs | 6 |
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!"); +} |