From 735a9104d0e9995a7257d71f5a24dcbafdd1b141 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sun, 12 Nov 2017 20:49:08 +0530 Subject: [PATCH 1/5] custom target: Serialize env vars that are set on the target This is not exposed to build files and should not be. However, it is useful for modules that want to run external commands that only take certain inputs via environment variables. --- mesonbuild/backend/ninjabackend.py | 28 ++++++++++++++++++++-------- mesonbuild/backend/vs2010backend.py | 1 + mesonbuild/build.py | 1 + 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 1057892c668a..8fd5f2d39f4a 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -491,7 +491,7 @@ def generate_custom_target(self, target, outfile): (srcs, ofilenames, cmd) = self.eval_custom_target_command(target) deps = self.unwrap_dep_list(target) deps += self.get_custom_target_depend_files(target) - desc = 'Generating {0} with a {1} command.' + desc = 'Generating custom target {!r} with {}' if target.build_always: deps.append('PHONY') if target.depfile is None: @@ -506,11 +506,22 @@ def generate_custom_target(self, target, outfile): elem.add_dep(os.path.join(self.get_target_dir(d), output)) serialize = False extra_paths = [] + exe = target.command[0] + # Get the command's basename for printing when the target is run + if isinstance(exe, (dependencies.ExternalProgram, + build.BuildTarget, build.CustomTarget)): + basename = exe.name + else: + basename = os.path.basename(exe) # If the target requires capturing stdout, then use the serialized # executable wrapper to capture that output and save it to a file. - if target.capture: + if target.capture or target.envvars: + serialize = True + # If the target requires environment variables set, we need the wrapper + # to set those vars for us. + if target.envvars: serialize = True - # If the command line requires a newline, also use the wrapper, as + # If the command line requires a newline, also use the wrapper as # ninja does not support them in its build rule syntax. if any('\n' in c for c in cmd): serialize = True @@ -520,19 +531,20 @@ def generate_custom_target(self, target, outfile): # CustomTarget command needs extra paths first. if mesonlib.is_windows() or mesonlib.is_cygwin(): extra_bdeps = target.get_transitive_build_target_deps() - extra_paths = self.determine_windows_extra_paths(target.command[0], extra_bdeps) + extra_paths = self.determine_windows_extra_paths(exe, extra_bdeps) if extra_paths: serialize = True if serialize: - exe_data = self.serialize_executable(target.command[0], cmd[1:], + exe_data = self.serialize_executable(exe, cmd[1:], # All targets are built from the build dir self.environment.get_build_dir(), extra_paths=extra_paths, + env=target.envvars, capture=ofilenames[0] if target.capture else None) + cmd_str = '{!r} using the meson_exe.py wrapper'.format(basename) cmd = self.environment.get_build_command() + ['--internal', 'exe', exe_data] - cmd_type = 'meson_exe.py custom' else: - cmd_type = 'custom' + cmd_str = '{!r}'.format(basename) if target.depfile is not None: rel_dfile = os.path.join(self.get_target_dir(target), target.depfile) abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) @@ -540,7 +552,7 @@ def generate_custom_target(self, target, outfile): elem.add_item('DEPFILE', rel_dfile) cmd = self.replace_paths(target, cmd) elem.add_item('COMMAND', cmd) - elem.add_item('description', desc.format(target.name, cmd_type)) + elem.add_item('description', desc.format(target.name, cmd_str)) elem.write(outfile) self.processed_targets[target.get_id()] = True diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index e872a0474c5c..6d9de57abedf 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -434,6 +434,7 @@ def gen_custom_target_vcxproj(self, target, ofname, guid): exe_data = self.serialize_executable(target.command[0], cmd[1:], # All targets run from the target dir tdir_abs, + env=target.envvars, extra_paths=extra_paths, capture=ofilenames[0] if target.capture else None) wrapper_cmd = self.environment.get_build_command() + ['--internal', 'exe', exe_data] diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 7757300c5e03..b12ae3a72480 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1517,6 +1517,7 @@ def __init__(self, name, subdir, subproject, kwargs, absolute_paths=False): self.extra_depends = [] self.depend_files = [] # Files that this target depends on but are not on the command line. self.depfile = None + self.envvars = {} self.process_kwargs(kwargs) self.extra_files = [] # Whether to use absolute paths for all files on the commandline From 6bc497c9333c5270beef8c23d6e1f44fe5cd2290 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sun, 12 Nov 2017 20:50:56 +0530 Subject: [PATCH 2/5] meson_exe.py: Don't capture stdout unless requested It is better to send it to stdout so that the user sees progress on long-running commands. It also gives better feedback to users, f.ex. when a command requires capture: true and the user forgets to pass it. --- mesonbuild/scripts/meson_exe.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mesonbuild/scripts/meson_exe.py b/mesonbuild/scripts/meson_exe.py index 643e1af7b6d3..550d69236e20 100644 --- a/mesonbuild/scripts/meson_exe.py +++ b/mesonbuild/scripts/meson_exe.py @@ -17,6 +17,7 @@ import argparse import pickle import platform +import subprocess from ..mesonlib import Popen_safe @@ -56,7 +57,12 @@ def run_exe(exe): if len(exe.extra_paths) > 0: child_env['PATH'] = (os.pathsep.join(exe.extra_paths + ['']) + child_env['PATH']) - p, stdout, stderr = Popen_safe(cmd + exe.cmd_args, env=child_env, cwd=exe.workdir) + # By default, don't capture output + stderr = None + if exe.capture: + stderr = subprocess.PIPE + p, stdout, stderr = Popen_safe(cmd + exe.cmd_args, env=child_env, + cwd=exe.workdir, stderr=stderr) if exe.capture and p.returncode == 0: with open(exe.capture, 'w') as output: output.write(stdout) From 7c15837bd25d37672bfddcb6ef9402792b3d3c23 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sun, 12 Nov 2017 20:52:48 +0530 Subject: [PATCH 3/5] custom target: Allow fetching outputs from built subdirs Change the check for `/` to checking for `..` to prevent custom targets from fetching outputs from outside the target directory, but allow fetching outputs from arbitrarily-nested subdirs. Also disallow absolute paths for outputs for similar reasons. --- mesonbuild/build.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index b12ae3a72480..1802a4eac94e 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -13,6 +13,7 @@ # limitations under the License. import copy, os, re +from pathlib import PurePath from collections import OrderedDict import itertools @@ -1602,10 +1603,13 @@ def process_kwargs(self, kwargs): inputs = get_sources_string_names(self.sources) values = get_filenames_templates_dict(inputs, []) for i in self.outputs: - if not(isinstance(i, str)): + if not isinstance(i, str): raise InvalidArguments('Output argument not a string.') - if '/' in i: - raise InvalidArguments('Output must not contain a path segment.') + ipath = PurePath(i) + if ipath.is_absolute(): + raise InvalidArguments('Output must not be an absolute path') + if '..' in ipath.parts: + raise InvalidArguments('Output path must not contain ".."') if '@INPUT@' in i or '@INPUT0@' in i: m = 'Output cannot contain @INPUT@ or @INPUT0@, did you ' \ 'mean @PLAINNAME@ or @BASENAME@?' @@ -1626,8 +1630,11 @@ def process_kwargs(self, kwargs): depfile = kwargs['depfile'] if not isinstance(depfile, str): raise InvalidArguments('Depfile must be a string.') - if os.path.split(depfile)[1] != depfile: - raise InvalidArguments('Depfile must be a plain filename without a subdirectory.') + deppath = PurePath(depfile) + if deppath.is_absolute(): + raise InvalidArguments('Depfile must not be an absolute path') + if '..' in deppath.parts: + raise InvalidArguments('Depfile must not contain ".."') self.depfile = depfile self.command = self.flatten_command(kwargs['command']) if self.capture: From b3b3a7d9331589d69afc4b8eb7f9fbef96b8cf67 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sun, 12 Nov 2017 20:57:53 +0530 Subject: [PATCH 4/5] custom targets: Allow setting the ninja pool for commands Long-running commands such as `cargo build` would show no output at all without this. This feature is precisely for this use-case, so expose it. Of course, build files do not have access to this yet. --- mesonbuild/backend/ninjabackend.py | 2 ++ mesonbuild/build.py | 1 + 2 files changed, 3 insertions(+) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 8fd5f2d39f4a..dbaf6359831b 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -550,6 +550,8 @@ def generate_custom_target(self, target, outfile): abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) os.makedirs(abs_pdir, exist_ok=True) elem.add_item('DEPFILE', rel_dfile) + if target.ninja_pool is not None: + elem.add_item('pool', target.ninja_pool) cmd = self.replace_paths(target, cmd) elem.add_item('COMMAND', cmd) elem.add_item('description', desc.format(target.name, cmd_str)) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 1802a4eac94e..65d7f3dd26c3 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1519,6 +1519,7 @@ def __init__(self, name, subdir, subproject, kwargs, absolute_paths=False): self.depend_files = [] # Files that this target depends on but are not on the command line. self.depfile = None self.envvars = {} + self.ninja_pool = None self.process_kwargs(kwargs) self.extra_files = [] # Whether to use absolute paths for all files on the commandline From 580c8512c17154a7a18bb1e3853f4c9e9171490e Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sun, 12 Nov 2017 22:32:33 +0530 Subject: [PATCH 5/5] WIP: Add an unstable module for Rust Cargo support Currently only supports building staticlib libraries and binaries with Cargo. All configuration must be in the Cargo.toml file. You should use cargo 0.23 because it fixes a bug in emitting dep-info FIXMEs: * Cross compilation is broken. We do not pass the `--target TRIPLE` flag to cargo, so it always builds targetting the build machine. * tests and benches are currently not supported, but can be added * cdylibs are not supported because it is not clear if anyone uses them and if they even work properly in Rust * `ninja dist` does not yet run `cargo vendor` to add crate sources * `cargo clean` is not called on `ninja clean` * We cannot handle adding system libraries that are needed by the staticlib while linking because it's outputted at build time by `cargo build`. You must handle that yourself. * We do not pass on RUSTFLAGS from the env during configure to cargo build. --- mesonbuild/mesonlib.py | 2 + mesonbuild/modules/unstable_cargo.py | 307 ++++++++++++++++++ test cases/rust/7 cargo module/.gitignore | 1 + .../rust/7 cargo module/bins/Cargo.toml | 6 + .../rust/7 cargo module/bins/meson.build | 5 + .../rust/7 cargo module/bins/src/main.rs | 3 + .../rust/7 cargo module/bothlibs/Cargo.toml | 9 + .../rust/7 cargo module/bothlibs/meson.build | 3 + .../rust/7 cargo module/bothlibs/src/lib.rs | 7 + .../rust/7 cargo module/installed_files.txt | 5 + test cases/rust/7 cargo module/meson.build | 7 + .../rust/7 cargo module/staticlib/Cargo.toml | 9 + .../rust/7 cargo module/staticlib/meson.build | 3 + .../rust/7 cargo module/staticlib/src/lib.rs | 7 + 14 files changed, 374 insertions(+) create mode 100644 mesonbuild/modules/unstable_cargo.py create mode 100644 test cases/rust/7 cargo module/.gitignore create mode 100644 test cases/rust/7 cargo module/bins/Cargo.toml create mode 100644 test cases/rust/7 cargo module/bins/meson.build create mode 100644 test cases/rust/7 cargo module/bins/src/main.rs create mode 100644 test cases/rust/7 cargo module/bothlibs/Cargo.toml create mode 100644 test cases/rust/7 cargo module/bothlibs/meson.build create mode 100644 test cases/rust/7 cargo module/bothlibs/src/lib.rs create mode 100644 test cases/rust/7 cargo module/installed_files.txt create mode 100644 test cases/rust/7 cargo module/meson.build create mode 100644 test cases/rust/7 cargo module/staticlib/Cargo.toml create mode 100644 test cases/rust/7 cargo module/staticlib/meson.build create mode 100644 test cases/rust/7 cargo module/staticlib/src/lib.rs diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index 9ad0668214d4..cb8ad873471d 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -661,6 +661,8 @@ def expand_arguments(args): return None return expended_args +Popen_safe_errors = (FileNotFoundError, PermissionError, subprocess.CalledProcessError) + def Popen_safe(args, write=None, stderr=subprocess.PIPE, **kwargs): if sys.version_info < (3, 6) or not sys.stdout.encoding: return Popen_safe_legacy(args, write=write, stderr=stderr, **kwargs) diff --git a/mesonbuild/modules/unstable_cargo.py b/mesonbuild/modules/unstable_cargo.py new file mode 100644 index 000000000000..096efcb7bf9e --- /dev/null +++ b/mesonbuild/modules/unstable_cargo.py @@ -0,0 +1,307 @@ +# Copyright 2017 The Meson development team + +# 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. + +import os +import json + +from .. import mlog +from ..mesonlib import Popen_safe, Popen_safe_errors +from ..mesonlib import extract_as_list, version_compare, MesonException, File +from ..environment import for_windows, for_cygwin, for_darwin +from ..interpreterbase import noKwargs, permittedKwargs +from ..dependencies import InternalDependency +from ..build import CustomTarget + +from . import ExtensionModule, ModuleReturnValue, permittedSnippetKwargs + +target_kwargs = {'toml', 'sources', 'install', 'install_dir'} + + +class CargoModule(ExtensionModule): + cargo = ['cargo'] + cargo_build = ['cargo', 'build', '-v', '--color=always'] + cargo_version = None + + def __init__(self): + super().__init__() + try: + self._get_version() + except Popen_safe_errors: + raise MesonException('Cargo was not found') + self.snippets.add('test') + self.snippets.add('benchmark') + + def _get_cargo_build(self, toml): + # FIXME: must use target-triple to set the host system, currently it + # always builds for the build machine. + return self.cargo_build + ['--manifest-path', toml] + + def _is_release(self, env): + buildtype = env.coredata.get_builtin_option('buildtype') + return not buildtype.startswith('debug') + + def _get_crate_name(self, name, crate_type, env): + ''' + We have no control over what filenames cargo uses for its output, so we + have to figure it out ourselves. + ''' + if for_cygwin(env.is_cross_build(), env): + raise MesonException('Cygwin cargo support is TODO') + prefix = 'lib' + if crate_type == 'staticlib': + suffix = 'a' + if for_windows(env.is_cross_build(), env): + prefix = '' + suffix = 'lib' + elif crate_type == 'cdylib': + if for_windows(env.is_cross_build(), env): + prefix = '' + suffix = 'dll' + elif for_darwin(env.is_cross_build(), env): + suffix = 'dylib' + else: + suffix = 'so' + elif crate_type == 'bin': + prefix = '' + suffix = '' + if for_windows(env.is_cross_build(), env): + suffix = 'exe' + if suffix: + fname = prefix + name + '.' + suffix + else: + fname = prefix + name + if self._is_release(env): + return os.path.join('release', fname) + else: + return os.path.join('debug', fname) + + def _read_metadata(self, toml): + cmd = self.cargo + ['metadata', '--format-version=1', '--no-deps', + '--manifest-path', toml] + out = Popen_safe(cmd)[1] + try: + encoded = json.loads(out) + except json.decoder.JSONDecodeError: + print(cmd, out) + raise + return encoded['packages'][0] + + def _source_strings_to_files(self, source_dir, subdir, sources): + results = [] + for s in sources: + if isinstance(s, File): + pass + elif isinstance(s, str): + s = File.from_source_file(source_dir, subdir, s) + else: + raise MesonException('Source item is {!r} instead of ' + 'string or files() object'.format(s)) + results.append(s) + return results + + def _get_sources(self, state, kwargs): + # 'sources' kwargs is optional; we have a depfile with dependency + # information and ninja will use that to determine when to rebuild. + sources = extract_as_list(kwargs, 'sources') + return self._source_strings_to_files(state.environment.source_dir, + state.subdir, sources) + + def _get_cargo_test_outputs(self, name, metadata, env): + args = [] + outputs = [] + depfile = None + for t in metadata['targets']: + if t['name'] != name: + continue + # Filter out crate types we don't want + # a test target will only have one output + if t['crate_types'] != ['bin']: + continue + # Filter out the target `kind`s that we don't want + if t['kind'] != ['test']: + continue + outputs.append(self._get_crate_name(name, 'bin', env)) + args = ['--test', name] + break + if outputs: + depfile = os.path.splitext(outputs[0])[0] + '.d' + else: + toml = metadata['manifest_path'] + raise MesonException('no test called {!r} found in {!r}' + ''.format(name, toml)) + return outputs, depfile, args + + def _get_cargo_executable_outputs(self, name, metadata, env): + args = [] + outputs = [] + depfile = None + for t in metadata['targets']: + if t['name'] != name: + continue + # Filter out crate types we don't want + # an executable target will only have one output + if t['crate_types'] != ['bin']: + continue + # Filter out the target `kind`s that we don't want + if t['kind'] not in [['example'], ['bin']]: + continue + outputs.append(self._get_crate_name(name, 'bin', env)) + if t['kind'][0] == 'example': + args = ['--example', name] + else: + args = ['--bin', name] + break + if outputs: + depfile = os.path.splitext(outputs[0])[0] + '.d' + else: + toml = metadata['manifest_path'] + raise MesonException('no bin called {!r} found in {!r}' + ''.format(name, toml)) + return outputs, depfile, args + + def _get_cargo_static_library_outputs(self, name, metadata, env): + args = [] + outputs = [] + depfile = None + for t in metadata['targets']: + if t['name'] != name: + continue + # Filter out the target `kind`s that we don't want + # a library target can have multiple outputs + if 'staticlib' not in t['kind'] and \ + 'example' not in t['kind']: + continue + for ct in t['crate_types']: + if ct == 'staticlib': + outputs.append(self._get_crate_name(name, ct, env)) + if t['kind'][0] == 'example': + # If the library is an example, it must be built by name + args = ['--example', name] + else: + # Library is the crate itself, no name needed + args = ['--lib'] + break + if outputs: + depfile = os.path.splitext(outputs[0])[0] + '.d' + else: + toml = metadata['manifest_path'] + raise MesonException('no staticlib called {!r} found ' + 'in {!r}'.format(name, toml)) + return outputs, depfile, args + + def _get_cargo_outputs(self, name, metadata, env, cargo_target_type): + # FIXME: track which outputs have already been fetched from + # a toml file and disallow duplicates. + fn = getattr(self, '_get_cargo_{}_outputs'.format(cargo_target_type)) + return fn(name, metadata, env) + + def _check_cargo_dep_info_bug(self, metadata): + if version_compare(self.cargo_version, '>0.22.0'): + return + for t in metadata['targets']: + if t['kind'] == ['custom-build']: + m = 'Crate {!r} contains a custom build script {!r} which ' \ + 'will cause dep-info to not being emitted due to a ' \ + 'bug in Cargo. Please upgrade to Cargo 0.23 or newer.' \ + ''.format(metadata['name'], os.path.basename(t['src_path'])) + mlog.warning(m) + return + + def _cargo_target(self, state, args, kwargs, cargo_target_type): + ctkwargs = {} + env = state.environment + if len(args) != 1: + raise MesonException('{0}() requires exactly one positional ' + 'argument: the name of the {0}' + ''.format(cargo_target_type)) + name = args[0] + if 'toml' not in kwargs: + raise MesonException('"toml" kwarg is required') + toml = File.from_source_file(env.get_source_dir(), state.subdir, + kwargs['toml']) + # Get the Cargo.toml file as a JSON encoded object + md = self._read_metadata(toml.absolute_path(env.source_dir, None)) + # Warn about the cargo dep-info bug if needed + self._check_cargo_dep_info_bug(md) + # Get the list of outputs that cargo will create matching the specified name + ctkwargs['output'], ctkwargs['depfile'], cargo_args = \ + self._get_cargo_outputs(name, md, env, cargo_target_type) + # Set the files that will trigger a rebuild + ctkwargs['depend_files'] = [toml] + self._get_sources(state, kwargs) + # Cargo command that will build the output library/libraries/bins + cmd = self._get_cargo_build(toml) + cargo_args + if self._is_release(env): + cmd.append('--release') + ctkwargs['command'] = cmd + if 'install' in kwargs: + ctkwargs['install'] = kwargs['install'] + if 'install_dir' in kwargs: + ctkwargs['install_dir'] = kwargs['install_dir'] + elif 'install' in kwargs: + # People should be able to set `install: true` and get a good + # default for `install_dir` + if cargo_target_type == 'static_library': + ctkwargs['install_dir'] = env.coredata.get_builtin_option('libdir') + elif cargo_target_type == 'executable': + ctkwargs['install_dir'] = env.coredata.get_builtin_option('bindir') + ct = CustomTarget(name, state.subdir, state.subproject, ctkwargs) + # Ninja buffers all cargo output so we get no status updates + ct.ninja_pool = 'console' + # Force it to output in the current directory + ct.envvars['CARGO_TARGET_DIR'] = state.subdir + # XXX: we need to call `cargo clean` on `ninja clean`. + return md, ct + + @permittedKwargs(target_kwargs) + def static_library(self, state, args, kwargs): + md, ct = self._cargo_target(state, args, kwargs, 'static_library') + # XXX: Cargo build outputs a list of system libraries that are needed + # by this (possibly) static library, but we have no way of accessing it + # during configure. So we require developers to manage that themselves. + # XXX: We add the output file into `sources`, but that creates + # a compile-time dependency instead of a link-time dependency and + # reduces parallelism. + d = InternalDependency(md['version'], [], [], [], [], [ct], []) + return ModuleReturnValue(d, [d]) + + @permittedKwargs(target_kwargs) + def executable(self, state, args, kwargs): + md, ct = self._cargo_target(state, args, kwargs, 'executable') + # XXX: We return a custom target, which means this may not be usable + # everywhere that an executable build target can be. + return ModuleReturnValue(ct, [ct]) + + @permittedSnippetKwargs(target_kwargs) + def test(self, interpreter, state, args, kwargs): + # This would map to cargo tests + raise MesonException('Not implemented') + + @permittedSnippetKwargs(target_kwargs) + def benchmark(self, interpreter, state, args, kwargs): + # This would map to cargo benches + raise MesonException('Not implemented') + + def _get_version(self): + if self.cargo_version is None: + out = Popen_safe(self.cargo + ['--version'])[1] + self.cargo_version = out.strip().split('cargo ')[1] + return self.cargo_version + + @noKwargs + def version(self, state, args, kwargs): + return ModuleReturnValue(self._get_version(), []) + + +def initialize(): + return CargoModule() diff --git a/test cases/rust/7 cargo module/.gitignore b/test cases/rust/7 cargo module/.gitignore new file mode 100644 index 000000000000..03314f77b5aa --- /dev/null +++ b/test cases/rust/7 cargo module/.gitignore @@ -0,0 +1 @@ +Cargo.lock diff --git a/test cases/rust/7 cargo module/bins/Cargo.toml b/test cases/rust/7 cargo module/bins/Cargo.toml new file mode 100644 index 000000000000..f3745cdbc797 --- /dev/null +++ b/test cases/rust/7 cargo module/bins/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "mesonbin" +version = "0.1.0" +authors = ["Nirbheek Chauhan "] + +[dependencies] diff --git a/test cases/rust/7 cargo module/bins/meson.build b/test cases/rust/7 cargo module/bins/meson.build new file mode 100644 index 000000000000..b2b9efcdd385 --- /dev/null +++ b/test cases/rust/7 cargo module/bins/meson.build @@ -0,0 +1,5 @@ +cargo.executable('mesonbin', + toml : 'Cargo.toml', + # This is optional, since ninja keeps track of dependencies on source files. + sources : ['src/main.rs'], + install : true) diff --git a/test cases/rust/7 cargo module/bins/src/main.rs b/test cases/rust/7 cargo module/bins/src/main.rs new file mode 100644 index 000000000000..e7a11a969c03 --- /dev/null +++ b/test cases/rust/7 cargo module/bins/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/test cases/rust/7 cargo module/bothlibs/Cargo.toml b/test cases/rust/7 cargo module/bothlibs/Cargo.toml new file mode 100644 index 000000000000..d35932e2245d --- /dev/null +++ b/test cases/rust/7 cargo module/bothlibs/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "mesonbothlib" +version = "0.1.0" +authors = ["Nirbheek Chauhan "] + +[dependencies] + +[lib] +crate-type = ['staticlib', 'cdylib'] diff --git a/test cases/rust/7 cargo module/bothlibs/meson.build b/test cases/rust/7 cargo module/bothlibs/meson.build new file mode 100644 index 000000000000..4627a3d5628f --- /dev/null +++ b/test cases/rust/7 cargo module/bothlibs/meson.build @@ -0,0 +1,3 @@ +cargo.static_library('mesonbothlib', + toml : 'Cargo.toml', + install : true) diff --git a/test cases/rust/7 cargo module/bothlibs/src/lib.rs b/test cases/rust/7 cargo module/bothlibs/src/lib.rs new file mode 100644 index 000000000000..31e1bb209f98 --- /dev/null +++ b/test cases/rust/7 cargo module/bothlibs/src/lib.rs @@ -0,0 +1,7 @@ +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} diff --git a/test cases/rust/7 cargo module/installed_files.txt b/test cases/rust/7 cargo module/installed_files.txt new file mode 100644 index 000000000000..117efb430283 --- /dev/null +++ b/test cases/rust/7 cargo module/installed_files.txt @@ -0,0 +1,5 @@ +?gcc:usr/lib/libmesonstatic.a +?gcc:usr/lib/libmesonbothlib.a +?msvc:usr/lib/mesonstatic.lib +?msvc:usr/lib/mesonbothlib.lib +usr/bin/mesonbin?exe diff --git a/test cases/rust/7 cargo module/meson.build b/test cases/rust/7 cargo module/meson.build new file mode 100644 index 000000000000..dd92bd5ba4b4 --- /dev/null +++ b/test cases/rust/7 cargo module/meson.build @@ -0,0 +1,7 @@ +project('cargo module', 'c', 'rust') + +cargo = import('unstable-cargo') + +subdir('staticlib') +subdir('bothlibs') +subdir('bins') diff --git a/test cases/rust/7 cargo module/staticlib/Cargo.toml b/test cases/rust/7 cargo module/staticlib/Cargo.toml new file mode 100644 index 000000000000..4e1bfb794b5e --- /dev/null +++ b/test cases/rust/7 cargo module/staticlib/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "mesonstatic" +version = "0.1.0" +authors = ["Nirbheek Chauhan "] + +[dependencies] + +[lib] +crate-type = ['staticlib'] diff --git a/test cases/rust/7 cargo module/staticlib/meson.build b/test cases/rust/7 cargo module/staticlib/meson.build new file mode 100644 index 000000000000..b2d0f31ae573 --- /dev/null +++ b/test cases/rust/7 cargo module/staticlib/meson.build @@ -0,0 +1,3 @@ +cargo.static_library('mesonstatic', + toml : 'Cargo.toml', + install : true) diff --git a/test cases/rust/7 cargo module/staticlib/src/lib.rs b/test cases/rust/7 cargo module/staticlib/src/lib.rs new file mode 100644 index 000000000000..31e1bb209f98 --- /dev/null +++ b/test cases/rust/7 cargo module/staticlib/src/lib.rs @@ -0,0 +1,7 @@ +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +}