diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 80a1c5642..59f94b1b4 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1651,7 +1651,10 @@ class NinjaBackend(backends.Backend): args += compilers.get_base_compile_args(base_proxy, rustc) self.generate_generator_list_rules(target) - orderdeps = [os.path.join(t.subdir, t.get_filename()) for t in target.link_targets] + # dependencies need to cause a relink, they're not just for odering + deps = [os.path.join(t.subdir, t.get_filename()) for t in target.link_targets] + + orderdeps: T.List[str] = [] main_rust_file = None for i in target.get_sources(): @@ -1772,6 +1775,8 @@ class NinjaBackend(backends.Backend): element = NinjaBuildElement(self.all_outputs, target_name, compiler_name, main_rust_file) if orderdeps: element.add_orderdep(orderdeps) + if deps: + element.add_dep(deps) element.add_item('ARGS', args) element.add_item('targetdep', depfile) element.add_item('cratetype', cratetype) diff --git a/test cases/unit/100 rlib linkage/lib2.rs b/test cases/unit/100 rlib linkage/lib2.rs new file mode 100644 index 000000000..3487bc5a9 --- /dev/null +++ b/test cases/unit/100 rlib linkage/lib2.rs @@ -0,0 +1,5 @@ +use lib; + +pub fn fun() { + lib::fun(); +} diff --git a/test cases/unit/100 rlib linkage/main.rs b/test cases/unit/100 rlib linkage/main.rs new file mode 100644 index 000000000..d0f82e4e1 --- /dev/null +++ b/test cases/unit/100 rlib linkage/main.rs @@ -0,0 +1,5 @@ +use lib2::fun; + +fn main() { + fun(); +} diff --git a/test cases/unit/100 rlib linkage/meson.build b/test cases/unit/100 rlib linkage/meson.build new file mode 100644 index 000000000..2d15b2a14 --- /dev/null +++ b/test cases/unit/100 rlib linkage/meson.build @@ -0,0 +1,22 @@ +project('rlib linkage', 'rust', default_options : ['rust_std=2018']) + +lib = static_library( + 'lib', + 'lib.rs', + rust_crate_type : 'rlib', +) + +lib2 = static_library( + 'lib2', + 'lib2.rs', + rust_crate_type : 'rlib', + link_with : lib, +) + +exe = executable( + 'exe', + 'main.rs', + link_with : lib2, +) + +test('main', exe) diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index b8cdfb6a8..5ae33fef3 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +from mesonbuild.mesonlib.universal import windows_proof_rm import subprocess import re import json @@ -4062,6 +4063,37 @@ class AllPlatformTests(BasePlatformTests): self.build() self.assertIn('error: use of a blacklisted/placeholder name `foo`', cm.exception.stdout) + @skip_if_not_language('rust') + def test_rust_rlib_linkage(self) -> None: + if self.backend is not Backend.ninja: + raise unittest.SkipTest('Rust is only supported with ninja currently') + template = textwrap.dedent('''\ + use std::process::exit; + + pub fn fun() {{ + exit({}); + }} + ''') + + testdir = os.path.join(self.unit_test_dir, '100 rlib linkage') + gen_file = os.path.join(testdir, 'lib.rs') + with open(gen_file, 'w') as f: + f.write(template.format(0)) + self.addCleanup(windows_proof_rm, gen_file) + + self.init(testdir) + self.build() + self.run_tests() + + with open(gen_file, 'w') as f: + f.write(template.format(39)) + + self.build() + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.run_tests() + self.assertEqual(cm.exception.returncode, 1) + self.assertIn('exit status 39', cm.exception.stdout) + def test_custom_target_name(self): testdir = os.path.join(self.unit_test_dir, '99 custom target name') self.init(testdir)