将私有函数包括当我编译一个rust项目到WASM?



如果我有一个lib。我在mod.rs文件中使用模块中的函数,该函数在mod.rs文件中使用另一个函数,但未向lib.rs公开。lib.rs.

如果我将我的项目发布到web上会发生什么?哪些文件是公开的?我假设整个mod.rs仍然可以访问,因为网站仍然需要使用mod.rs的功能,或者它只会在mod.rs的公共功能中加载?

注意:我不熟悉发布项目到实际的web。因此,它也在很大程度上导致了人们看不到它是如何运作的。我正在使用WASM(与JS)来编译某些函数。

你的意思不是很清楚,因为这里有两个方面:

  1. 是的,如果您从公共函数访问私有函数(包括通过间接,嵌套调用,模块等),私有函数的代码将包含在最终的可执行文件中。这显然是正确的,因为如果没有私有函数的代码,公共函数根本无法工作…

  2. 不,如果一个符号没有明确标记为pub(或#[used]),并且从crate的顶层可访问,编译器和链接器可以自由地删除该符号,如果他们这样选择的话。这意味着私有函数很可能不是作为可见符号包含在您的最终wasm模块中,并且您不应该假设它们是。由于上述原因,私有函数的代码可能包含在内,但不可能直接从外部调用私有函数。

提前告知编译器和/或链接器是否不将函数作为可见符号包含在中是很重要的。如果您在debug模式下编译,符号可能会包含,这仅仅是因为编译器和/或链接器没有做必要的工作来证明该符号不需要包含。此外,使用链接时间优化可能需要这样做,您可能根本不使用。然而,在任何情况下,除非符号被明确地标记为pub(或#[used;即使这样,链接器也可能会决定反对你,你不能假设这个符号是公开可见的。

例如:

mod r#mod {
#[inline(never)]
fn private(i: i32) -> i32 {
i + 1
}
#[inline(never)]
pub fn public(i: i32) -> i32 {
private(i) + 1
}
}
pub fn public(i: i32) -> i32 {
r#mod::public(i) + 1
}

这里,IR生成三个符号:

; playground::mod::private
define internal fastcc i32 @_ZN10playground3mod7private17h0fb30f481d7b59dcE(i32 %i) unnamed_addr #0 {
start:
%0 = add i32 %i, 1
ret i32 %0
}
; playground::mod::public
define internal fastcc i32 @_ZN10playground3mod6public17h771c0f8fe9a648a0E(i32 %i) unnamed_addr #0 {
start:
; call playground::mod::private
%_2 = tail call fastcc i32 @_ZN10playground3mod7private17h0fb30f481d7b59dcE(i32 %i)
%0 = add i32 %_2, 1
ret i32 %0
}
; playground::public
define i32 @_ZN10playground6public17h7abee63a81dd5c88E(i32 %i) unnamed_addr #1 {
start:
; call playground::mod::public
%_2 = tail call fastcc i32 @_ZN10playground3mod6public17h771c0f8fe9a648a0E(i32 %i)
%0 = add i32 %_2, 1
ret i32 %0
}

正如您所看到的,IR将产生显式标记为internal-mod::privatemod::public的两个符号,即使mod::publicpub,但它在私有模块内!-只有public不是internal,并且会在最终的可执行文件中公开可见。

最新更新