Skip to content

Commit 0730422

Browse files
tamirdojeda
authored andcommitted
rust: use host dylib naming convention to support macOS
Because the `macros` crate exposes procedural macros, it must be compiled as a dynamic library (so it can be loaded by the compiler at compile-time). Before this change the resulting artifact was always named `libmacros.so`, which works on hosts where this matches the naming convention for dynamic libraries. However the proper name on macOS would be `libmacros.dylib`. This turns out to matter even when the dependency is passed with a path (`--extern macros=path/to/libmacros.so` rather than `--extern macros`) because rustc uses the file name to infer the type of the library (see link). This is because there's no way to specify both the path to and the type of the external library via CLI flags. The compiler could speculatively parse the file to determine its type, but it does not do so today. This means that libraries that match neither rustc's naming convention for static libraries nor the platform's naming convention for dynamic libraries are *rejected*. The only solution I've found is to follow the host platform's naming convention. This patch does that by querying the compiler to determine the appropriate name for the artifact. This allows the kernel to build with CONFIG_RUST=y on macOS. Link: https://github.com/rust-lang/rust/blob/d829780/compiler/rustc_metadata/src/locator.rs#L728-L752 Tested-by: Daniel Gomez <[email protected]> Co-developed-by: Fiona Behrens <[email protected]> Signed-off-by: Fiona Behrens <[email protected]> Signed-off-by: Tamir Duberstein <[email protected]> Tested-by: Andreas Hindborg <[email protected]> Link: https://lore.kernel.org/r/[email protected] [ Added `MAKEFLAGS=`s to avoid jobserver warnings. Removed space. Reworded title. - Miguel ] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent 4401565 commit 0730422

File tree

4 files changed

+25
-15
lines changed

4 files changed

+25
-15
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
*.dtb.S
2323
*.dtbo.S
2424
*.dwo
25+
*.dylib
2526
*.elf
2627
*.gcno
2728
*.gcda

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1571,7 +1571,7 @@ MRPROPER_FILES += include/config include/generated \
15711571
certs/x509.genkey \
15721572
vmlinux-gdb.py \
15731573
rpmbuild \
1574-
rust/libmacros.so
1574+
rust/libmacros.so rust/libmacros.dylib
15751575

15761576
# clean - Delete most, but leave enough to build external modules
15771577
#

rust/Makefile

+12-10
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ always-$(CONFIG_RUST) += exports_core_generated.h
1111
obj-$(CONFIG_RUST) += helpers/helpers.o
1212
CFLAGS_REMOVE_helpers/helpers.o = -Wmissing-prototypes -Wmissing-declarations
1313

14-
always-$(CONFIG_RUST) += libmacros.so
15-
no-clean-files += libmacros.so
16-
1714
always-$(CONFIG_RUST) += bindings/bindings_generated.rs bindings/bindings_helpers_generated.rs
1815
obj-$(CONFIG_RUST) += bindings.o kernel.o
1916
always-$(CONFIG_RUST) += exports_helpers_generated.h \
@@ -38,9 +35,14 @@ obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.o
3835

3936
always-$(subst y,$(CONFIG_RUST),$(CONFIG_JUMP_LABEL)) += kernel/generated_arch_static_branch_asm.rs
4037

41-
# Avoids running `$(RUSTC)` for the sysroot when it may not be available.
38+
# Avoids running `$(RUSTC)` when it may not be available.
4239
ifdef CONFIG_RUST
4340

41+
libmacros_name := $(shell MAKEFLAGS= $(RUSTC) --print file-names --crate-name macros --crate-type proc-macro - </dev/null)
42+
libmacros_extension := $(patsubst libmacros.%,%,$(libmacros_name))
43+
44+
always-$(CONFIG_RUST) += $(libmacros_name)
45+
4446
# `$(rust_flags)` is passed in case the user added `--sysroot`.
4547
rustc_sysroot := $(shell MAKEFLAGS= $(RUSTC) $(rust_flags) --print sysroot)
4648
rustc_host_target := $(shell $(RUSTC) --version --verbose | grep -F 'host: ' | cut -d' ' -f2)
@@ -109,10 +111,10 @@ rustdoc-ffi: $(src)/ffi.rs rustdoc-core FORCE
109111
+$(call if_changed,rustdoc)
110112

111113
rustdoc-kernel: private rustc_target_flags = --extern ffi \
112-
--extern build_error --extern macros=$(objtree)/$(obj)/libmacros.so \
114+
--extern build_error --extern macros \
113115
--extern bindings --extern uapi
114116
rustdoc-kernel: $(src)/kernel/lib.rs rustdoc-core rustdoc-ffi rustdoc-macros \
115-
rustdoc-compiler_builtins $(obj)/libmacros.so \
117+
rustdoc-compiler_builtins $(obj)/$(libmacros_name) \
116118
$(obj)/bindings.o FORCE
117119
+$(call if_changed,rustdoc)
118120

@@ -362,10 +364,10 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
362364
-Clink-args='$(call escsq,$(KBUILD_HOSTLDFLAGS))' \
363365
--emit=dep-info=$(depfile) --emit=link=$@ --extern proc_macro \
364366
--crate-type proc-macro \
365-
--crate-name $(patsubst lib%.so,%,$(notdir $@)) $<
367+
--crate-name $(patsubst lib%.$(libmacros_extension),%,$(notdir $@)) $<
366368

367369
# Procedural macros can only be used with the `rustc` that compiled it.
368-
$(obj)/libmacros.so: $(src)/macros/lib.rs FORCE
370+
$(obj)/$(libmacros_name): $(src)/macros/lib.rs FORCE
369371
+$(call if_changed_dep,rustc_procmacro)
370372

371373
quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L $@
@@ -382,7 +384,7 @@ quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L
382384
$(cmd_objtool)
383385

384386
rust-analyzer:
385-
$(Q)$(srctree)/scripts/generate_rust_analyzer.py \
387+
$(Q)MAKEFLAGS= $(srctree)/scripts/generate_rust_analyzer.py \
386388
--cfgs='core=$(core-cfgs)' \
387389
$(realpath $(srctree)) $(realpath $(objtree)) \
388390
$(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \
@@ -443,7 +445,7 @@ $(obj)/uapi.o: $(src)/uapi/lib.rs \
443445
$(obj)/kernel.o: private rustc_target_flags = --extern ffi \
444446
--extern build_error --extern macros --extern bindings --extern uapi
445447
$(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/build_error.o \
446-
$(obj)/libmacros.so $(obj)/bindings.o $(obj)/uapi.o FORCE
448+
$(obj)/$(libmacros_name) $(obj)/bindings.o $(obj)/uapi.o FORCE
447449
+$(call if_changed_rule,rustc_library)
448450

449451
ifdef CONFIG_JUMP_LABEL

scripts/generate_rust_analyzer.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import logging
99
import os
1010
import pathlib
11+
import subprocess
1112
import sys
1213

1314
def args_crates_cfgs(cfgs):
@@ -35,8 +36,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
3536
crates_cfgs = args_crates_cfgs(cfgs)
3637

3738
def append_crate(display_name, root_module, deps, cfg=[], is_workspace_member=True, is_proc_macro=False):
38-
crates_indexes[display_name] = len(crates)
39-
crates.append({
39+
crate = {
4040
"display_name": display_name,
4141
"root_module": str(root_module),
4242
"is_workspace_member": is_workspace_member,
@@ -47,7 +47,15 @@ def append_crate(display_name, root_module, deps, cfg=[], is_workspace_member=Tr
4747
"env": {
4848
"RUST_MODFILE": "This is only for rust-analyzer"
4949
}
50-
})
50+
}
51+
if is_proc_macro:
52+
proc_macro_dylib_name = subprocess.check_output(
53+
[os.environ["RUSTC"], "--print", "file-names", "--crate-name", display_name, "--crate-type", "proc-macro", "-"],
54+
stdin=subprocess.DEVNULL,
55+
).decode('utf-8').strip()
56+
crate["proc_macro_dylib_path"] = f"{objtree}/rust/{proc_macro_dylib_name}"
57+
crates_indexes[display_name] = len(crates)
58+
crates.append(crate)
5159

5260
# First, the ones in `rust/` since they are a bit special.
5361
append_crate(
@@ -70,7 +78,6 @@ def append_crate(display_name, root_module, deps, cfg=[], is_workspace_member=Tr
7078
[],
7179
is_proc_macro=True,
7280
)
73-
crates[-1]["proc_macro_dylib_path"] = f"{objtree}/rust/libmacros.so"
7481

7582
append_crate(
7683
"build_error",

0 commit comments

Comments
 (0)