Подтвердить что ты не робот

Могут ли библиотеки быть распределены как двоичные, поэтому конечный пользователь не может видеть исходный код?

Можно ли скомпилировать ящик библиотеки Rust, чтобы пользователь не мог видеть исходный код, но все еще может использовать библиотеку?

Если это так, все ли генерики предоставляются как "Исходный код" или какой-либо ИК-порт, или же Rust реализует дженерики по-разному от шаблонов С++?

4b9b3361

Ответ 1

В каждый библиотечный ящик входит множество метаданных, статически связанных (.rlib) или динамически связанных (.so/.dylib/.dll):

  • Структура модуля
  • экспортированные макросы macro_rules
  • определения типов и признаков
  • константы с их выражениями инициализации
  • подписи для всех функций
  • весь элемент каждой функции, который помечен как #[inline] или является общим (методы определения по умолчанию считаются общими по Self)

Все это достаточно, чтобы воспроизвести часть исходного источника (насколько это зависит от использования дженериков), хотя и без комментариев или других пробелов. Тело функции сериализуется во внутренней структуре АСТ-структуры компилятора - вы можете видеть ее симпатичную форму с помощью rustc -Z ast-json lib.rs.

В то время как метаданные являются двоичными, а не JSON, используя librustc для извлечения всех экспортированных определений функций из скомпилированного ящика, а довольно-печатная версия АСТ довольно проста.

В будущем может не быть какой-либо проверки прошлого типа AST, поэтому метаданные будут кодировать IR-сортировки - одна из возможностей - CFG, то есть "график потока управления", который уже используется внутри пары мест.

Однако это все равно будет содержать больше информации, чем байт-код Java, это будет оптимизация, вы все равно можете приблизиться к исходному коду (и легко получить то, что компилируется).

Таким образом, я могу рекомендовать только два варианта:

  • открыть API C; он имеет то преимущество, что является стабильным ABI, но он довольно ограниченный и хрупкий;
  • выставлять API-интерфейс Rust с использованием только объектов-признаков, а не generics; таким образом, вы можете сохранить безопасность памяти, и все мономорфные функции будут работать нормально, но объекты-объекты (динамическая отправка) не могут выразить все шаблоны, которые могут возникнуть с помощью дженериков: в частности, общие методы признаков не подлежат вызову на объекты-объекты (С++ должен иметь аналогичное ограничение для смешивания template и virtual, с обходными способами, потенциально доступными в каждом конкретном случае).