rust: add start-group/end-group arguments for libraries

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
pull/14026/head
Paolo Bonzini 3 months ago
parent a9432f1202
commit ad185307e3
  1. 38
      mesonbuild/compilers/rust.py
  2. 11
      test cases/rust/27 staticlib group/lib1.c
  3. 4
      test cases/rust/27 staticlib group/lib1.h
  4. 8
      test cases/rust/27 staticlib group/lib2.c
  5. 3
      test cases/rust/27 staticlib group/lib2.h
  6. 6
      test cases/rust/27 staticlib group/main.c
  7. 9
      test cases/rust/27 staticlib group/main.rs
  8. 13
      test cases/rust/27 staticlib group/meson.build

@ -9,10 +9,13 @@ import textwrap
import re
import typing as T
from .. import arglist
from .. import options
from ..linkers.linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker
from ..mesonlib import EnvironmentException, MesonException, Popen_safe_logged
from ..options import OptionKey
from .compilers import Compiler, clike_debug_args
from .mixins.clike import GROUP_FLAGS
if T.TYPE_CHECKING:
from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType
@ -62,6 +65,37 @@ def get_rustup_run_and_args(exelist: T.List[str]) -> T.Optional[T.Tuple[T.List[s
except StopIteration:
return None
class RustcCompilerArgs(arglist.CompilerArgs):
def to_native_inplace(self) -> None:
assert isinstance(self.compiler, RustCompiler), 'How did you get here'
# Check if we need to add --start/end-group for circular dependencies
# between static libraries, and for recursively searching for symbols
# needed by static libraries that are provided by object files or
# shared libraries.
# This covers all ld.bfd, ld.gold, ld.gold, and xild on Linux, which
# all act like (or are) gnu ld
if isinstance(self.compiler.linker, (GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker)):
group_start = -1
group_end = -1
last_rustc_arg = -1
for i, each in enumerate(self):
if each in {'--emit', '-o', '--extern'}:
last_rustc_arg = i
if last_rustc_arg == i - 1 or not GROUP_FLAGS.search(each):
continue
group_end = i
if group_start < 0:
# First occurrence of a library
group_start = i
# Only add groups if there are multiple libraries.
if group_end > group_start >= 0:
# Last occurrence of a library
self.insert(group_end + 1, '-Clink-arg=-Wl,--end-group')
self.insert(group_start, '-Clink-arg=-Wl,--start-group')
class RustCompiler(Compiler):
# rustc doesn't invoke the compiler itself, it doesn't need a LINKER_PREFIX
@ -100,6 +134,10 @@ class RustCompiler(Compiler):
self.base_options.add(OptionKey('b_vscrt'))
self.native_static_libs: T.List[str] = []
def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> RustcCompilerArgs:
# This is correct, mypy just doesn't understand co-operative inheritance
return RustcCompilerArgs(self, args)
def needs_static_linker(self) -> bool:
return False

@ -0,0 +1,11 @@
#include <stdio.h>
#include "lib1.h"
#include "lib2.h"
void from_lib2(void) {
printf("hello world");
}
void c_func(void) {
from_lib1();
}

@ -0,0 +1,4 @@
#pragma once
void from_lib2(void);
void c_func(void);

@ -0,0 +1,8 @@
#include <stdio.h>
#include "lib1.h"
#include "lib2.h"
void from_lib1(void)
{
from_lib2();
}

@ -0,0 +1,3 @@
#pragma once
void from_lib1(void);

@ -0,0 +1,6 @@
#include "lib1.h"
#include "lib2.h"
void main() {
c_func();
}

@ -0,0 +1,9 @@
extern "C" {
fn c_func();
}
fn main() {
unsafe {
c_func();
}
}

@ -0,0 +1,13 @@
project('staticlib group', 'c', 'rust')
ld_bfd = find_program('ld.bfd')
if not ld_bfd.found()
error('MESON_SKIP_TEST ld.bfd not found')
endif
lib1 = static_library('lib1', 'lib1.c')
lib2 = static_library('lib2', 'lib2.c')
executable('lib1first', 'main.rs', link_with : [lib1, lib2],
rust_args: ['-C', 'lto=n', '-C', 'linker-plugin-lto=n', '-Clink-arg=-fuse-ld=bfd'])
executable('lib2first', 'main.rs', link_with : [lib2, lib1],
rust_args: ['-C', 'lto=n', '-C', 'linker-plugin-lto=n', '-Clink-arg=-fuse-ld=bfd'])
Loading…
Cancel
Save