库能否以二进制形式分发,这样最终用户就看不到源代码?

Can libraries be distributed as a binary, so the end user cannot see the source code?

是否可以编译一个 Rust 库 crate,以便用户看不到源代码但仍然可以使用该库?

如果是,是否所有泛型都作为 "Source code" 或某些 IR 提供,或者 Rust 是否以不同于 C++ 模板的方式实现泛型?

每个库 crate 都包含大量元数据,无论是静态链接 (.rlib) 还是动态链接 (.so/.dylib/.dll):

  • 模块结构
  • 已导出 macro_rules 个宏
  • 类型和特征定义
  • 常量及其初始化表达式
  • 所有函数的签名
  • 标记为 #[inline] 或通用的每个函数的整个主体(默认特征方法在 Self 上被认为是通用的)

尽管没有注释或其他空格,但所有这些足以复制一些原始来源(多少取决于泛型的使用)。
函数体在编译器的内部 AST 结构中被序列化——你可以通过 rustc -Z ast-json lib.rs.

看到它的漂亮形式

虽然元数据是二进制的,而不是 JSON,但使用 librustc 从已编译的 crate 中提取所有导出的函数定义,并且漂亮地打印 AST 相当容易。

在未来,可能没有任何 AST 过去的类型检查,因此元数据将编码某种 IR——一种可能性是 CFG,即 "control flow graph",它已经在几个内部使用地点。

然而,这仍然会暴露比 Java 字节码更多的信息,这将是一种优化,您仍然可以近似原始代码(并轻松获得可以编译的东西)。

因此,我只能推荐两个选项:

  1. 暴露一个CAPI;它的优点是作为一个稳定的 ABI,但它非常有限且脆弱;
  2. 仅使用 trait 对象而不是泛型公开 Rust API;这样你就可以保持内存安全并且所有单态函数仍然可以正常工作,但是特征对象(动态调度)不能表达泛型可能的所有模式:特别是,泛型特征方法不能在特征对象上调用(C++ 应该有一个混合 templatevirtual 的类似限制,可能根据具体情况提供解决方法)。