Rust: Поддержка биткода магазина приложений Apple

Созданный на 24 авг. 2016  ·  89Комментарии  ·  Источник: rust-lang/rust

Биткод — это будущее распространения приложений Apple, и сейчас мы его не поддерживаем. Сделать это сложно, потому что Apple выбирает любую версию LLVM, которую они хотят, и обновляет ее по своему усмотрению. Мы не можем соединить наш LLVM с их LLVM, потому что у нас есть свои собственные потребности, и нас нельзя заставить обновиться, когда Apple решит.

Вот несколько вариантов:

  • Мы поставляем совершенно отдельный набор инструментов для работы с биткодом Apple. Это довольно некрасиво.
  • Мы меняем rustc для динамической загрузки LLVM, создаем пакет rust-llvm и необязательный пакет rust-llvm-apple, а rustc загружает LLVM Apple для работы с их бит-кодом.
  • Мы создаем крейт rustc_llvm_apple и всегда связываем два полных LLVM в rustc. Это, вероятно, не полетит
  • Мы создаем сборку rustc под названием rustc-apple и отправляем ее в дополнительном пакете rustc-apple. Это точно так же, как rustc, за исключением того, что вместо ссылки на rustc_llvm он ссылается на rustc_llvm_apple. Когда rustc получает запрос на передачу битового кода, он просто полностью подчиняется бинарному файлу rustc-apple. Мне на самом деле очень нравится это решение.
  • Мы могли бы изучить дезинфицирующее средство для бит-кода, чтобы преобразовать наш бит-код в их. Я думаю, что вероятность успеха здесь низкая, потому что техническое обслуживание. Я считаю, что RenderScript делает это.

Я думаю, что динамическая загрузка LLVM и решения defer-to-alternate-rustc являются наиболее многообещающими.

копия https://users.rust-lang.org/t/ios-rust-integration/6928/4

копия @bluejekyll

A-LLVM A-rustbuild C-enhancement E-hard O-ios T-compiler T-dev-tools

Самый полезный комментарий

Мне удалось связать статическую библиотеку rustc nightly-2019-09-05 aarch64-apple-ios and rustflags = "-C lto -Z embed-bitcode" с приложением clang-1100.0.33.5 (Xcode 11 beta 7) and -fembed-bitcode . Исходный код https://github.com/saturday06/rust-ios-bitcode-test .

Все 89 Комментарий

Мы меняем rustc для динамической загрузки LLVM, создаем пакет rust-llvm и необязательный пакет rust-llvm-apple, а rustc загружает LLVM Apple для работы с их бит-кодом.

Динамическая загрузка LLVM, конечно, не вариант. API LLVM менее стабилен, чем его битовый код, и, если мы будем собирать LLVM xy, то наличие LLVM xz вместо xy почти наверняка сломает rustc. Просто свяжите LLVM с системой статически (как это уже делает --llvm-root ).

Мы создаем крейт rustc_llvm_apple и всегда связываем два полных LLVM в rustc. Это, вероятно, не полетит

Просто скомпонуйте системный LLVM (статически) для дистрибутивов Apple. По моему опыту, это уже неплохо работает.

Мы могли бы изучить дезинфицирующее средство для бит-кода, чтобы преобразовать наш бит-код в их. Я думаю, что вероятность успеха здесь низкая, потому что техническое обслуживание. Я считаю, что RenderScript делает это.

Хорошо… так что дело в том, что формат битового кода LLVM довольно стабилен между версиями LLVM. Делает ли Apple что-то необычное, чтобы сделать это неправдой, или формат битового кода используется совсем не LLVM (т.е. имеет специфичные для Apple вещи)?


Мне кажется, что я слышал еще в 2013 году, что использование битового кода LLVM в качестве формата распространения глупо. Я, конечно, согласен; распространение нативных бинарных библиотек больше не работает для iOS?

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

Я немного поэкспериментировал с этим, т.е. вывел биткод во время сборки груза, затем попытался создать статическую библиотеку с включенным биткодом. Когда я попытался связать llvm с библиотекой битового кода, я получил несовместимую версию LLVM из битового кода.

У меня нет простого теста, чтобы воспроизвести это, но я предполагаю, что это просто тупая проверка версии, которая отрицает связь между разными версиями LLVM? Или я просто сделал что-то совершенно неправильно. Я постараюсь придумать тестовый пример, когда у меня будет время снова взглянуть на это.

Было бы полезно получить точное сообщение об ошибке из llvm-link.

@bluejekyll LLVM имеет несколько файлов битового кода в своем тестовом каталоге. Тесты на эти файлы битового кода выполняются непрерывно (например, llvm-dis-3.8/opt-3.8 прекрасно понимает файл трехлетнего битового кода из версии 3.2), так что это должно быть что-то из Apple.

Просто скомпонуйте системный LLVM (статически) для дистрибутивов Apple. По моему опыту, это уже неплохо работает.

Это несколько легче сказать, чем сделать — насколько мне известно, единственная благословенная версия apple-llvm для загрузки в App Store — это та, которая поставляется с текущим Xcode. Это также потенциально означает поддержку привязок LLVM для двух версий LLVM (также не обязательно для двух соседних минорных версий). Я не думаю, что можно просто использовать старую версию apple-llvm.

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

Я думаю, что они избегают этого, позволяя только последней версии Xcode отправлять приложения (и я почти уверен, что она записана в выходной образ, какую версию LLVM вы использовали).

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

Я чувствую, что все рекомендуемые решения несколько неприглядны. Наименее беспорядочный способ, который я могу придумать, — это позволить различным целям перегружать поведение кодегена и иметь путь кодегена Apple в динамическом ящике. (Это был бы обычный путь кодегена, скомпилированный с помощью apple-llvm.)

Поскольку в этом баге упоминается App Store, стоит ли здесь рассказывать об истории с обработкой исключений? (т.е. panic=abort в данный момент строго требуется.)

В тестовом каталоге LLVM есть несколько файлов битового кода. Тесты на эти файлы битового кода выполняются непрерывно (например, llvm-dis-3.8/opt-3.8 прекрасно понимает файл трехлетнего битового кода из версии 3.2), так что это должно быть что-то из Apple.

@nagisa, спасибо, что

@ ricky26 хорошие моменты.

насколько мне известно, единственная благословенная версия apple-llvm для загрузки в App Store — это версия, поставляемая с текущим Xcode.

Разве Xcode LLVM на яблоке не то же самое, что системный LLVM? Тогда я имел в виду Xcode LLVM. Мы должны убедиться, что xcode всегда является самой последней версией при отправке поездов rustc.

Конечно, то, как работает Apple, исключает возможность создания корректного биткода Apple со старой версией rustc и, по сути, вынуждает нас отказаться от всех преимуществ, которые предоставляет наша история стабильности, и я не вижу никакого способа исправить это.

Это также потенциально означает сохранение привязок LLVM для двух версий LLVM.

Мы уже поддерживаем¹ поддержку версий LLVM с 3.7 по 3.9 (и, возможно, основной). Пока Xcode LLVM не является какой-то древней версией, я думаю, что у нас все хорошо в этом отношении. Если Xcode LLVM действительно какая-то древняя/пользовательская/и т. д. версия, то я не вижу, чтобы мы вообще могли поддерживать эту функцию. Тем более, что у нас нет возможности отправлять патчи на _этот_ LLVM, чтобы добавить нужные нам функции. Я также не хотел бы заблокировать rustc для поддержки 3.7 навсегда, если Apple решит не обновлять Xcode LLVM до 2038 года.

¹: однако, если rustc был собран для LLVM xy, он должен быть точно связан с LLVM xy.

Динамическая загрузка LLVM, конечно, не вариант. API LLVM менее стабилен, чем его битовый код, и, если мы будем собирать LLVM xy, то наличие LLVM xz вместо xy почти наверняка сломает rustc. Просто свяжите LLVM с системой статически (как это уже делает --llvm-root).

@nagisa API C++ нестабилен, но мы используем C API и добились большого успеха, поддерживая одновременно несколько версий LLVM. Я не вижу разницы в плане поддержки API.

Просто скомпонуйте системный LLVM (статически) для дистрибутивов Apple. По моему опыту, это уже неплохо работает.

Мы могли бы просто поставить LLVM от Apple для всех платформ Apple, но это означает привязку нашего LLVM к Apple даже для генерации машинного кода для настольных компьютеров и исключает возможность поддержки бит-кода iOS на хостах, отличных от Apple.

Хорошо… так что дело в том, что формат битового кода LLVM довольно стабилен между версиями LLVM. Делает ли Apple что-то необычное, чтобы сделать это неправдой, или формат битового кода используется совсем не LLVM (т.е. имеет специфичные для Apple вещи)?

Формат битового кода не является стабильным между версиями.

распространение нативных бинарных библиотек больше не работает для iOS?

Сегодня это работает. Это не предпочтительный метод, и не очевидно, что он будет по-прежнему поддерживаться.

Это также потенциально означает поддержку привязок LLVM для двух версий LLVM (также не обязательно для двух соседних минорных версий). Я не думаю, что можно просто использовать старую версию apple-llvm.

@ ricky26 Мы успешно поддерживаем совместимость между несколькими версиями LLVM. Пока Apple и наша не расходятся слишком далеко друг от друга, это должно быть выполнимо, но всегда есть риск такой большой поломки, что границу нельзя будет пересечь, и я знаю, что грядут серьезные изменения API.

Пока Xcode LLVM не является какой-то древней версией, я думаю, что у нас все хорошо в этом отношении.

С этой страницы https://gist.github.com/yamaya/2924292 :

clang-700.0.72 => LLVM 3.7.0
clang-700.1.76 => LLVM 3.7.0
clang-700.1.81 => LLVM 3.7.0
clang-703.0.29 => LLVM 3.8.0
clang-703.0.31 => LLVM 3.8.0

C++ API нестабилен, но мы используем C API и добились большого успеха, поддерживая одновременно несколько версий LLVM. Я не вижу разницы в плане поддержки API.

Это неправда. У нас есть (довольно большое!) количество привязок к C++ API в виде rustllvm. Есть ряд случаев, когда мы компилируем эту оболочку в зависимости от версии LLVM, с которой компилируется. В случае, если версия LLVM, используемая и скомпилированная, не совпадает, вы получите ошибки динамического компоновщика или, что еще хуже, столкнетесь с проблемами во время выполнения.

исключает возможность поддержки биткода iOS на хостах, отличных от Apple.

Если Apple не хочет использовать битовый код, сгенерированный чем-то другим, кроме их ответвления LLVM, то я не вижу, как мы можем здесь что-то сделать, кроме поддержки аналогичного ответвления и реверс-инжиниринга их внутренних патчей.

Формат битового кода не является стабильным между версиями.

Конечно, но вполне справедливо предположить¹, что битовый код между различными версиями LLVM, известный, например, как 3.7.0, достаточно совместим для целей генерации битового кода для использования другой сборкой LLVM из серии 3.7.0. Это определенно лучше, чем динамическое связывание с libLLVM.

¹: особенно учитывая, что биткод из серии 3.2 по-прежнему совместим с 3.8 LLVM, даже если это очень маленький экземпляр.

Некоторые примечания:

  • Xcode даже не поставляется со связываемой libLLVM (статической или динамической), только libclang.dylib, которая статически связывается с LLVM.
  • Apple отправляет исходный код в свой «clang» (включая LLVM) в разделе «Инструменты разработчика» на https://opensource.apple.com , но этот сайт, как правило, обновляется вечно.
  • История может быть лучше со Swift, у которого есть собственная вилка LLVM с тегами выпуска, но они могут не полностью соответствовать тому, что поставляется с Xcode. (Можно использовать моментальные снимки цепочки инструментов с открытым исходным кодом с Xcode, но проекты, созданные с помощью таких цепочек инструментов, не могут быть отправлены в App Store.)

копия @rust-lang/компилятор

Было бы любопытно услышать, как другие языки программирования планируют справиться с этим. В частности моно и идут.

Ответ Unity на эту проблему — il2cpp — сборка всех своих IL-сборок в код C++.

Соответствующая ошибка golang: https://github.com/golang/go/issues/12682; кажется, что они могли бы использовать цепочку инструментов LLVM go (которая не так хороша, как стандартная цепочка инструментов go).

В общем, история поддержки биткода за пределами Apple оставляет желать лучшего.

Собственно моно идет через Apple LLVM: http://tirania.org/blog/archive/2015/Sep-02.html

Одним камнем преткновения будет то, что вы не можете использовать встроенный ассемблер в биткоде :(

Что касается истории моно, у меня был быстрый обмен мнениями с Мигелем де Икаса о том, что моно делает для любопытных: https://twitter.com/mitsuhiko/status/769458873237434368

@mitsuhiko У вас _может_ быть встроенная сборка в биткоде на iOS и tvOS, но по какой-то причине нет watchOS.

Любое движение по этому поводу? Мне совсем не нравится использовать Rust на iOS без плана поддержки биткода. У Apple есть история того, что необязательные вещи, такие как эта, становятся необязательными довольно внезапно, и действительно, биткод уже требуется в watchOS и tvOS.

Я чувствую, что все рекомендуемые решения несколько неприглядны. Наименее беспорядочный способ, который я могу придумать, — это позволить различным целям перегружать поведение кодегена и иметь путь кодегена Apple в динамическом ящике. (Это был бы обычный путь кодегена, скомпилированный с помощью apple-llvm.)

Этот подход (автор @ricky26) кажется мне, как пользователю rustc, наиболее естественным.

Я не верю, что что-то изменилось в этом в последнее время, по крайней мере, насколько мне известно. С недавним объявлением LLVM о версиях они указали, что битовый код должен (я думаю) всегда загружаться будущими версиями LLVM. Это может означать, что эта проблема «решена» на фундаментальном уровне, но все равно потребуется более эргономичный интерфейс для извлечения всего битового кода.

Есть ли обновления по этому поводу?

Этот комментатор на HackerNews преуспел в использовании биткода, сгенерированного из Rust, на macOS и iOS. В этой ветке есть подробная информация о том, как включить биткод для двоичных файлов ржавчины, что звучит как отличная новость!

https://news.ycombinator.com/item?id=14305084

Как комментатор, о котором идет речь, быстрые заметки:

  • Я использовал -C lto --emit llvm-bc чтобы заставить rustc создать один файл .bc, содержащий текущий крейт и все зависимости. Это работает, но по сути это хак; в частности, он не работает для зависимостей C, включая jemalloc (хотя в iOS он все равно не используется). Было бы лучше, если бы rustc правильно поддерживал передачу Mach-O со «встроенным биткодом»; вы можете посмотреть на источник clang, чтобы увидеть, как это делается.

  • Если вы хотите попробовать это и не возражаете против взлома, кажется, что это «просто работает», за исключением проблемы с версией:

  • Основное практическое препятствие заключается в том, что Rust синхронизируется с транком LLVM чаще, чем Xcode, который делает это только раз в год. Более новые версии LLVM могут загружать старый биткод, но не наоборот, поэтому вам придется либо использовать старую версию rustc, либо собрать последнюю версию на основе старого LLVM. (На самом деле, rustc 1.17, кажется, все еще работает с Xcode 8.x, но не каждую ночь после обновления LLVM 4.0; хотя это просто совпадение.)

  • В идеале Rust должен поставлять официальные бинарные файлы, созданные для подходящей версии LLVM. На практике можно использовать правильную версию стандартного LLVM, но если вы хотите использовать форк Apple:

    • Как я сказал в предыдущем комментарии, Xcode не поставляет бинарные файлы LLVM в какой-либо форме, которую можно связать, даже динамически; только clang и libclang.dylib (который экспортирует Clang API, но не LLVM).
    • Но, как я уже сказал, исходный код обычно размещается на opensource.apple.com (в разделе Инструменты разработчика -> clang; архив включает в себя весь LLVM), просто несколько непоследовательно/с задержкой. Однако, особенно учитывая расширенные гарантии обратной совместимости, отмеченные @alexcrichton , не всегда быть в курсе

(В качестве теста я только что попытался скомпилировать Rust с Xcode 8.2.1 Clang. rustllvm не удалось собрать, потому что в нем есть множество условных выражений #if LLVM_VERSION_GE(..) , которые предназначены для компиляции с обоими более старый и более новый LLVM, путается в этой ветке, которая утверждает, что это LLVM 3.9svn, но с точки зрения API находится где-то между 3,8 и 3,9 Вероятно, не стоит исправлять, так как Xcode в любом случае почти готов к следующему ежегодному обновлению.)

Был ли достигнут прогресс на этом фронте? В качестве альтернативы вы (основная команда) рассматриваете это испытание как проблему с надежным постоянным исправлением в поле зрения, или вы ожидаете, что эта штука со скачком версии останется в обозримом будущем?

Я рассматриваю возможность реализации части iOS-приложения на Rust из-за его превосходной системы типов и низкоуровневой семантики, и я бы предпочел не зацикливаться на не-биткоде или регулярных взломах/задержках всякий раз, когда есть обновление для Xcode или rustc.

@regexident

Я думаю, что мы собираемся реализовать сменные версии LLVM по другим причинам. Если это будет реализовано, у нас не должно возникнуть проблем с поставкой отдельных трансов для Apple, wasm и всего остального.

копия № 45684

Разве биткод Apple по-прежнему действительно опасен, аля https://medium.com/@FredericJacobs/why -im-not-enabling-bitcode-f35cd8fbfcc5 Невозможно проверить сборки. Вопросы по криптографии. и Т. Д.

@burdges Для некоторых приложений это абсолютно проблема.

Но для watchOS и tvOS Apple действительно требует Bitcode для отправки в App Store. У тебя нет выбора. Кроме «не делайте криптографию или важные вещи на этих платформах». Также следует опасаться, что Apple в какой-то момент в будущем применит Bitcode для iOS. Я бы предпочел не иметь кирпичный продукт в этот момент.

Я попытался выполнить сборку на Rust 1.24.0 для iOS, используя прием -C lto --emit=llvm-bc , но компоновщик выдал следующие ошибки:

Undefined symbols for architecture x86_64:
  "_backtrace_create_state", referenced from:
      std::sys_common::gnu::libbacktrace::init_state::h686c3e443c712b0f in Logger(x86_64.o)
  "_backtrace_syminfo", referenced from:
      std::panicking::default_hook::_$u7b$$u7b$closure$u7d$$u7d$::h598a932d5bb0d80b in Logger(x86_64.o)
      core::iter::iterator::Iterator::position::_$u7b$$u7b$closure$u7d$$u7d$::hbf03153d55553502 in Logger(x86_64.o)
  "_backtrace_pcinfo", referenced from:
      std::panicking::default_hook::_$u7b$$u7b$closure$u7d$$u7d$::h598a932d5bb0d80b in Logger(x86_64.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Есть идеи, в чем может быть проблема?

Изменить: кажется, что я могу по крайней мере подавить эту проблему, обернув весь код в каждом общедоступном внешнем fn с помощью AssertUnwindSafe

libbacktrace — это библиотека C, включенная в исходное дерево Rust:

https://github.com/rust-lang/rust/tree/master/src/libbacktrace

Вам придется каким-то образом скомпилировать это как биткод.

Я в замешательстве, потому что я могу найти только libbacktrace, созданный для моего ноутбука, но не для ОС телефона. Как Rust вставляет эти символы в stdlib? Есть ли более простой способ сделать это, каким-то образом отключив функцию обратной трассировки? Я удалил переменную окружения RUST_BACKTRACE, но это не помогло. Я читал, что вы можете скомпилировать rustc без обратных следов, но я надеялся на что-то более простое, например, в файле cargo.toml моего проекта.

По сути, вы хотите построить исходное дерево rustc, сообщая ему о передаче -fembed-bitcode компилятору C. В идеале вы могли бы просто добавить его в CFLAGS ; к сожалению, я только что попробовал это, и это не сработало должным образом из-за двух проблем с gcc-rs (используется системой сборки rustc для сборки зависимостей C). Тем не менее, я заставил его работать с немного хакерской процедурой:

cd /tmp/build
cat >ccwrap.py <<END

#!/usr/bin/env python
import os, sys
os.execv('/usr/bin/xcrun', ['clang', '-fembed-bitcode'] + [arg for arg in sys.argv[1:] if arg not in {'-ffunction-sections', '-fdata-sections'}])

END

chmod 755 ccwrap.py
ln -s /usr/bin/ar ar
export CC_aarch64_apple_ios=`pwd`/ccwrap.py
/usr/src/rust/configure --target=aarch64-apple-ios
make

Это должно дать вам libbacktrace.a./build/aarch64-apple-ios/native/libbacktrace/.libs/ ) со встроенным биткодом. __LLVM,__bitcode того, что в противном случае является нативными библиотеками, так же, как это делает clang: тогда не было бы необходимости вручную компилировать и связывать файлы .bc.

(На самом деле, поскольку приведенная вами ошибка выглядит как обычная ошибка компоновщика, я думаю, что вы могли бы обойти ее, просто связав обычную, не встроенную в битовый код libbacktrace.a . Но в лучшем случае это приведет к выходному файлу со сломанным встроенным биткодом.)

Вышеупомянутые проблемы:

  • gcc-rs пропускает -ffunction-sections и -fdata-sections без возможности отключить их; clang жалуется на это в сочетании с -fembed-bitcode (даже если -fno-function-sections передается позже).

Я подал отчет о

  • gcc-rs пытается найти ar в том же каталоге, что и CC_aarch64_apple_ios (!?); ручная установка AR_aarch64_apple_ios не дала результата

Я не смог воспроизвести это с последней версией cc-rs (переименованной из gcc-rs ), поэтому я не зарегистрировал проблему. В качестве обходного пути описанная выше процедура создает символические ссылки ar в тот же каталог.

Спасибо за предложения! На самом деле мне просто нужен был биткод для моего собственного кода, а не для трассировки, поэтому я просто использовал скомпилированную libbacktrace без встраивания биткода.

С помощью взлома, который я попытался, я столкнулся с другой проблемой: dsymutil segfaults, когда я пытаюсь создать для него dSYM. Обычное выполнение без dSYM работает нормально, но создание dSYM по какой-то причине прерывается. Я удалил свой libbacktrace.a, заменил его пустыми функциями-заполнителями, и все заработало нормально, так что, похоже, возникла проблема с моей библиотекой ржавчины.

Это похоже на ошибку в dsymutil, о которой следует сообщить вышестоящему LLVM. Можете ли вы попробовать запустить dsymutil под LLDB и опубликовать отслеживание сбоя? Или, чтобы получить лучшую отладочную информацию, вы можете попробовать собрать LLVM в режиме отладки и воспроизвести его с этим.

(Обратите внимание, что двоичный файл в стандартной установке LLVM называется llvm-dsymutil , но в наши дни dsymutil Xcode — это просто символическая ссылка на llvm-dsymutil . Раньше dsymutil отдельная утилита с закрытым исходным кодом, но в течение нескольких лет эта версия поставлялась как dsymutil-classic и не использовалась по умолчанию.)

@comex из любопытства, должен ли ящик cc компилировать все с помощью -fembed-bitcode ? Или, если мы используем «официальный» clang, можно ли избежать встраивания битового кода?

(извините, я не очень хорошо знаком с лучшими практиками ios!)

Что касается самого кода Rust, было бы лучше, если бы мы просто генерировали байт-код вместо объектных файлов? Это то, что Clang/компоновщик может понять?

@алекскрайтон

должен ли ящик cc компилировать все с -fembed-bitcode ? Или, если мы используем «официальный» clang, можно ли избежать встраивания битового кода?

Использование официального clang не избавляет от необходимости встроенного битового кода. Скорее битовый код включается — в дополнение к собственному коду — в архив приложения, загружаемый в Apple, а затем Apple может перекомпилировать его на стороне сервера, например, для оптимизации для различных микроархитектур.

Вероятно, имеет смысл передать -fembed-bitcode по умолчанию на iOS/watchOS/tvOS. Если да, то при сборке в режиме отладки надо передать -fembed-bitcode-marker (вместо или в дополнение, не имеет значения); это говорит clang включать только фиктивный раздел битового кода, а не какой-либо фактический битовый код, поскольку встроенный битовый код необходим только для окончательных архивов приложений, и это немного ускоряет компиляцию, чтобы исключить его. На самом деле, Xcode передает -fembed-bitcode-marker для всего, кроме создания окончательного архива приложения, даже для разрабатываемых сборок, которые имеют оптимизацию, но поскольку cc не имеет отдельной концепции «действительно окончательного выпуска». mode", вероятно, следует просто передать его в режиме отладки. Обратите внимание, что встраивать биткод безопасно, даже если окончательная сборка не требует этого.

Что касается самого кода Rust, было бы лучше, если бы мы просто генерировали байт-код вместо объектных файлов? Это то, что Clang/компоновщик может понять?

И clang, и ld поддерживают необработанные файлы битового кода, передаваемые в качестве входных данных; это обычно используется, когда LTO включен ( -flto ), и в этом случае файлы .o, которые генерирует clang, на самом деле представляют собой необработанный битовый код, а не Mach-O. (Они все еще могут быть сформированы в статические библиотеки с помощью обычной команды lipo.) Однако это отличается от формата «встроенного битового кода», который состоит из Mach-O с битовым кодом, помещенным в раздел __LLVM,__bitcode в дополнение к нативному коду в обычных разделах. Этот формат используется в объектных файлах, когда LTO отключен, а также в окончательно связанных исполняемых файлах или динамических библиотеках независимо от настройки LTO. (Если LTO включен, компоновщик отвечает за создание этого раздела; если LTO выключен, компоновщик просто объединяет разделы __LLVM,__bitcode из каждого объектного файла, как и для любого другого раздела, вместо того, чтобы создавать единый объединенный раздел. модуль биткода. ) РЕДАКТИРОВАТЬ: на самом деле он делает что-то более сложное , создавая xar-архив разделов биткода и помещая их в раздел с именем __LLVM,__bundle ; в любом случае, это не то, о чем мы должны заботиться.

Я думаю, что в идеале rustc должен создавать «встроенный биткод» по умолчанию на iOS, а не необработанный биткод. Это не так уж сложно сделать, и это позволяет избежать нарушения инкрементной компиляции, особенно в режиме отладки, где вы можете просто создать фиктивный раздел битового кода, например -fembed-bitcode-marker , но потенциально и в режиме выпуска, поскольку компоновщик просто заполняет объекты ' разделы битового кода вместе, вместо того, чтобы делать что-либо дорогостоящее во время компоновки.

Вот как clang генерирует встроенный биткод:

https://github.com/llvm-mirror/clang/blob/master/lib/CodeGen/BackendUtil.cpp#L1242

Относительно просто — перед вызовом бэкенда он выгружает текущий модуль LLVM в виде битового кода, а затем
помещает это как двоичные данные в новую глобальную переменную (в том же модуле!), помещенную в секцию __LLVM,__bitcode . Это похоже на хакерский дизайн (почему интерфейс должен делать это вручную?), но это не должно быть слишком сложно воспроизвести в rustc.

@comex такой подход имеет смысл, хотя я думаю, что есть причины (см. # 48833, который я только что сделал) для использования Apple clang в качестве бэкэнда, пока мы думаем о подобных изменениях. Кроме того, насколько легко скомпилировать себя из встроенного битового кода?

@michaeleiselsc Извините, я не понимаю, что вы подразумеваете под «скомпилировать себя из встроенного битового кода».

Например, вместо того, чтобы просто предоставить двоичный код в App Store со встроенным бит-кодом, есть также преимущества в том, чтобы взять бит-код и создать его самостоятельно, используя Apple clang. Два преимущества, которые меня интересуют, — это последующие исправления, которые есть у Apple clang, и возможность использовать дезинфицирующие средства clang, например дезинфицирующее средство покрытия.

@comex хорошо, немного достаточно проста (относительно), но у меня есть несколько вопросов:

  • Почему -fembed-bitcode-marker вещь? Используя clang локально, он просто выдает пустой статический сигнал в раздел. Означает ли это, что само наличие раздела что-то значит? Не ломается ли какой-нибудь инструмент по дороге в iOS, если раздела нет? (но на самом деле он не заглядывает внутрь раздела, потому что он пуст?
  • Знаете ли вы, нужен ли раздел __cmdline ? Похоже, что -fembed-bitcode также встраивает некоторую форму командной строки в двоичный файл. Я не совсем уверен, что бы мы поместили здесь, так как это, вероятно, не командная строка rustc, но смотрит ли это какой-либо инструмент? Прерывается ли компиляция, если -fembed-bitcode=bitcode используется с iOS?
  • И, наконец, есть ли причина когда-либо хотеть отключить это? Или мы должны просто безоговорочно включить это для целей iOS и двигаться дальше?

Почему -fembed-bitcode-marker вещь?

Я думаю, что он используется xcode, чтобы указать, что что-то должно использовать бит-код, но бит-код на самом деле не был скомпилирован. Если вы попытаетесь заархивировать такой проект позже, ld завершится с ошибкой.

На вопрос о том, хотим ли мы всегда включать это, определенно есть некоторые случаи, с которыми мы хотели бы быть осторожными. Например, если кто-то отправит его на платформу распространения бета-приложений, такую ​​​​как HockeyApp, удалит ли HockeyApp этот раздел битового кода или бета-тестерам придется загружать двоичный файл гораздо большего размера, чем им нужно?

@mitsuhiko Да, идея в том, что компоновщик может проверить, правильно ли настроена сборка для бит-кода, даже если вы в настоящее время тестируете сборки, которым на самом деле не нужен бит-код.

Например, если вы скомпилируете файл C без упоминания биткода, а затем попытаетесь скомпоновать его с помощью -fembed-bitcode-marker , вы получите:

$ clang -c -o test.o test.c
$ clang -dynamiclib -o test.dylib test.o -fembed-bitcode-marker
ld: warning: all bitcode will be dropped because 'test.o' was built
without bitcode. You must rebuild it with bitcode enabled (Xcode
setting ENABLE_BITCODE), obtain an updated library from the vendor,
or disable bitcode for this target.

Предупреждение исчезнет, ​​если вы также передадите -fembed-bitcode-marker в первой строке.

@alexcrichton Что касается __cmdline … хм… похоже, компоновщик требует, чтобы он присутствовал (ищите «Создать биткод»):

https://opensource.apple.com/source/ld64/ld64-274.2/src/ld/parsers/macho_relocatable_file.cpp.auto.html

Но я не вижу ничего, что заботилось бы о фактической стоимости. Вероятно, лучше всего указать там фиктивное значение.

Была ли эта проблема решена путем слияния # 48896?

Я играл с этим в ночных сборках, и он отлично работает, пока вы не попытаетесь заархивировать с помощью Xcode. Похоже, он добавляет маркер fembed-bitcode-marker, но не febed-bitcode в вывод статической библиотеки Rust. Он скомпилирован с помощью cargo lipo --release с:

$ cargo --version
cargo 1.27.0-nightly (af3f1cd29 2018-05-03)
$ cargo lipo --version
cargo-lipo 2.0.0-beta-2
$ rustc --version
rustc 1.27.0-nightly (565235ee7 2018-05-07)
ld: '/Users/chrisbal/Documents/Beach/rust-universal-template/target/universal/release/libexample.a(example_generic-be72fb1769c1779b.example_generic6-152d14edfb6970f54250733c74e59b7.rs.rcgu.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Когда я запускаю otool -arch arm64 -l /Users/chrisbal/Documents/Beach/rust-universal-template/target/universal/release/libexample.a | grep bitcode я получаю много sectname __bitcode , но я не знаю, как проверить, является ли это фактическим биткодом, а не просто маркерами.

Я использую вложенные ящики, так что, может быть, внутренний «общий» ящик не получает флаги битового кода?

редактировать: вот наше репо, демонстрирующее проблему https://github.com/Raizlabs/rust-universal-template/tree/879e7412d729e8963586c5b083d51b09733aec32

@chrisballinger работает с дополнительным флагом, см.
RUSTFLAGS="-Z embed-bitcode" cargo lipo --release

$ cargo --version
cargo 1.28.0-nightly (f352115d5 2018-05-15)
$ cargo lipo --version
cargo-lipo 2.0.0-beta-2
$ rustc --version
rustc 1.28.0-nightly (952f344cd 2018-05-18)

Но у меня другая ошибка компиляции только для арки arm7:

.rs.rcgu.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture armv7

Кто-нибудь знает, как исправить arm7 arch ?

К сожалению, он тоже не работает, получая ту же ошибку, что и @chrisballinger :

ld: '/sandbox/target/universal/release/librgame.a(std-da6dba40351cda22.std3-d36cd881bae00a8b5fc36289b5737f78.rs.rcgu.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Я попытался скомпилировать его с RUSTFLAGS="-Z embed-bitcode" cargo lipo --release и установить в .cargo/config . Однако он добавляет флаг:

` Executing: "cargo" "build" "--target" "x86_64-apple-ios" "--lib" "--features" "" "--color" "auto" "--release" "--verbose" Compiling libc v0.2.42 Compiling rand_core v0.2.1 Running `rustc --crate-name libc /Users/aleksandrivanov/.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.42/src/lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 --cfg 'feature="default"' --cfg 'feature="use_std"' -C metadata=dce309634355ac97 -C extra-filename=-dce309634355ac97 --out-dir /Users/aleksandrivanov/Sandbox/Projects/tetris/rgame/target/x86_64-apple-ios/release/deps --target x86_64-apple-ios -L dependency=/Users/aleksandrivanov/Sandbox/Projects/tetris/rgame/target/x86_64-apple-ios/release/deps -L dependency=/Users/aleksandrivanov/Sandbox/Projects/tetris/rgame/target/release/deps --cap-lints allow -Zembed-bitcode` ...

Какие-нибудь обновления здесь? Вероятным вариантом является серьезное рассмотрение общей базовой библиотеки для нашего приложения и без этого фиксированного C++.

@chrisballinger , может ли это быть связано с https://github.com/rust-lang/rust/issues/52686?

@volodg Нет, эта проблема возникла недавно.

Слияние # 48896 должно работать из коробки?

Я на 1.29.1, и объекты по-прежнему не имеют встроенного битового кода по умолчанию. Как упоминалось ранее @volodg , вы можете получить ржавчину, чтобы встроить их, используя RUSTFLAGS="-Z embed-bitcode" . Но из того, что я испытал, вы сталкиваетесь с проблемой, когда собственные библиотеки Rust (compiler_builtins, std) не компилируются с embed-bitcode. Возможно, сработает перестроение целей iOS с помощью xargo с embed-bitcode, но я не пробовал.

Я попытался использовать xargo как вы предложили, но проблема, похоже, все еще здесь :(

Используя этот Xargo.toml

[dependencies]
std = {}
[target]
features = ["jemalloc"]

Также добавив это к Cargo.toml :

[profile.release]
panic = "abort"

Я скомпилировал, используя xargo build --release --target $TARGET для всех этих целей:

  • aarch64-яблоко-дарвин
  • armv7-яблоко-дарвин
  • armv7s-яблоко-дарвин
  • i386-яблоко-дарвин
  • x86_84-яблоко-дарвин

Затем я использовал lipo для создания одной статической библиотеки.

У меня все еще есть ошибка компоновщика:

ld: '../../cargo/target/universal/libgreetings.a(greetings-ceeec73d35f7dbe0.greetings.9kcaav8v-cgu.2.rcgu.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Продвинулись немного дальше с путем xargo.

Мои Xargo.toml

[dependencies]
std = {}

Мои Cargo.toml

[profile.release]
panic = "abort"

Я не знаю, требуется ли это, но из документа xargo вам нужно явно использовать extern crate compiler_builtins , который я добавил в свой lib.rs.

Затем я скомпилировал с помощью: RUSTFLAGS="-Z embed-bitcode" xargo build --target $TARGET --release для компиляции. Убедитесь, что он собирает core/std/compiler_bultins. xargo clean не очищает предыдущие сборки правильно от того, что я испытал, поэтому rm -rf ~/.xargo был необходим для перекомпиляции std, когда я пробовал разные настройки Xargo.toml .

Но затем, архивируя в Xcode 10, я получаю (при ссылке armv7 ):

Intrinsic has incorrect argument type!
void (i8*, i8, i32, i1)* @llvm.memset.p0i8.i32
Intrinsic has incorrect argument type!
void (i8*, i8*, i32, i1)* @llvm.memcpy.p0i8.p0i8.i32
Intrinsic has incorrect argument type!
...
(lots of it)
...
LLVM ERROR: Broken module found, compilation aborted!
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Означает ли это, что ошибка связана со стороной LLVM?

РЕДАКТИРОВАТЬ : Как мы могли бы помочь продвинуться в этом вопросе?

Кто-нибудь пробовал это недавно? Похоже, что самая большая проблема — это armv7?

Всем привет. Я уже некоторое время слежу за этой веткой, и я очень рад видеть, что биткод Apple поддерживается Rust. Кто-нибудь смог сделать эту работу? Чего сейчас не хватает и как мы можем помочь?
Спасибо!

После нескольких часов поиска этой проблемы я нашел причину, по которой встраивание битового кода Rust не работает в Xcode. Короткий ответ заключается в том, что версия Xcode LLVM ожидает биткод LLVM 6.0 , в то время как Rust в июле 2018 года перешел на LLVM 7.0.

А теперь длинный ответ...

Как мы можем видеть в журнале изменений LLVM 7.0, они изменили подписи для @llvm.memcpy , @llvm.memmove и @llvm.memset , а ошибка сборки Xcode была ясной из-за неправильного типа аргумента, как видно в моем предыдущем комментарии .

Кстати, Kotlin Native добавил поддержку embed-bitcode в октябре 2018 года и, судя по всему, отлично работает в Xcode . Причина в том, что Kotlin до сих пор использует LLVM 6.0 .

Увидев это, я попытался скомпилировать старую версию Rust до перехода на 7.0. Я пробовал с nightly-2018-06-01-x86_64-apple-darwin , и успешно, он компилируется!

Я также безуспешно пытался скомпилировать без использования Xargo. Все зависимости должны быть скомпилированы с встраиванием биткода.

Итак, если Apple не улучшит свою версию LLVM, я не думаю, что мы увидим поддержку встроенного битового кода в ближайшее время... Если только кто-то не найдет умный способ преобразовать встроенный битовый код в битовый код 6.0...

@appaquet Спасибо, что

Спасибо @appaquet за четкий ответ. Теперь, я думаю, нам просто нужно полагаться на то, что Apple поступит правильно.

Взгляд человека, который интересуется мультиплатформой для мобильных устройств и сравнил большинство многообещающих решений (React Native, Flutter, Kotlin/Native, Rust)

Реагировать нативно. Поддерживает биткод с самого начала, потому что по сути мост написан на C++ и просто интерпретирует код JS во время выполнения.

Флаттер. Биткод пока не поддерживает - https://github.com/flutter/flutter/issues/15288

Котлин/Родной. JetBrains рассматривает мобильные платформы в качестве приоритета, и хотя это заняло некоторое время, и это только маркеры битового кода (еще не полный биткод), этого достаточно, чтобы начать работать с ним — см. https://github.com/JetBrains/kotlin-native/ pull/1564 и https://github.com/JetBrains/kotlin-native/issues/1202#issuecomment-444022513

Ржавчина. Поддерживает биткод для LLVM 7, тогда как Apple использует версию 6.

Если я хочу иметь и бизнес-логику, и кроссплатформенный пользовательский интерфейс, я бы выбрал React Native или Flutter. Но для многих серьезных приложений этот путь слишком рискован. React Native недостаточно производительен, а стабильность API и зависимостей является проблемой (выйдет ли когда-нибудь версия 1.0?). Флаттер немного незрелый, но, кажется, набирает все большую популярность.

Теперь, если я хочу поделиться только бизнес-логикой в ​​каких-то модулях (как это делали более ранние большие приложения с C++ и JNI/Obj-C++), а затем создать поверх нативный пользовательский интерфейс, вначале у меня есть выбор между всеми четырьмя. Затем я вычеркиваю React Native, потому что использование полноценного JavaScriptCore и моста для запуска бизнес-логики между JS <-> Native кажется немного чрезмерным (инициализация этого моста тоже довольно дорогая). Потенциально Flutter можно использовать, но он не предназначен для этого , поэтому я снова использую UI-фреймворк для запуска бизнес-логики. Плюс он не поддерживает биткод.
Rust и Kotlin/Native нацелены на эту нишу, имеют приличный инструментарий, создают собственный бинарный файл (производительность и занимаемая площадь!). Биткод — большая проблема для тех, кто хочет использовать Rust в качестве языка для создания мультиплатформенных модулей на мобильных платформах. И теперь у Kotlin/Native есть преимущество.

Подводя итог, почему биткод очень важен для разработчиков iOS. Ничего не могу написать на tvOS или watchOS. Многие сторонние фреймворки, которые распространяются в виде двоичных файлов, имеют биткод (десятки примеров, из моей головы Google IMA - самая популярная видеореклама). Некоторые аудиты безопасности требуют этого. И, наконец, всякий раз, когда Apple говорит, что «со следующего года мы больше не принимаем приложения без полностью встроенного битового кода», все получают тикающий таймер.

Теперь, я думаю, нам просто нужно полагаться на то, что Apple поступит правильно.

Да, именно этим Apple и славится ;)
Я не знаю, что было бы лучшим решением (временный даунгрейд до LLVM 6 не вариант, верно?), но Rust полностью теряет iOS и мобильных кроссплатформенных разработчиков.

Большое спасибо за это подробное объяснение @oleksandr-yefremov. Я немного читал на эту тему и нашел этот интересный комментарий: https://gist.github.com/yamaya/2924292#gistcomment -2738480

Версия LLVM привязана к версии Swift, используемой в XCode. До сих пор применялась следующая поддержка:

Xcode 8.3  --> swift 3.1 --> llvm 4.0.0
Xcode 9.0  --> swift 4.0 --> llvm 4.0.0
Xcode 9.3  --> swift 4.1 --> llvm 5.0.2
Xcode 10.0 --> swift 4.2 --> llvm 6.0.1

Глядя на swift-5.0-branch , я заметил, что в нем заявлена ​​версия LLVM 7.0.0 : https://github.com/apple/swift-llvm/blob/swift-5.0-branch/ CMakeLists.txt#L25 -L33

Я не знаю, есть ли здесь другие блокираторы, но мне кажется, что мы могли бы использовать Rust для вывода двоичных файлов Bitcode 🎉

Похоже, что Xcode 10.2 будет включать Swift 5.0 и действительно должен быть выпущен довольно скоро. Но с другой стороны, LLVM 8.0 планируется выпустить на следующей неделе. Rust, скорее всего, обновится до того, как Apple начнет его использовать.

Чтобы Rust правильно поддерживал биткод, нам понадобятся сборки Rust для архитектур Apple ARM, чтобы использовать закрепленную версию LLVM (возможно, из репозитория https://github.com/apple/swift-llvm — Apple, похоже, не использует выпущенный пакет LLVM, но свои собственные ветки). Эта версия LLVM будет обновлена ​​только тогда, когда Apple выпустит новую окончательную версию Xcode с другой версией LLVM.

Кстати, кажется, что последнюю версию Rust можно собрать с помощью LLVM 6, так что это определенно кажется выполнимым: https://github.com/rust-lang/rust/blob/master/src/bootstrap/native.rs#L282.
Вам определенно нужно, чтобы люди вмешивались, когда возникает проблема, чтобы обновить требуемую версию LLVM (та, что для LLVM 6: https://github.com/rust-lang/rust/issues/55842).

@vincentisambart Rust уже использует LLVM 8 для ночных сборок в течение 5 месяцев IIRC.
LLVM 6 — это минимально поддерживаемая версия, если вы хотите собрать ее самостоятельно, и она протестирована на CI: https://github.com/rust-lang/rust/blob/706e67b0a0143d651eb03f2fa2c30645899e81ff/src/ci/docker/x86_64-gnu-llvm-6.0. /Докерфайл

Теперь, я думаю, нам просто нужно полагаться на то, что Apple поступит правильно.

Я некоторое время гонялся за чем-то в этом направлении (и теперь вышел), и я предполагаю, что с точки зрения платформы Apple не имеет смысла делать это, потому что:

  • Swift хочет быть Rust во многих отношениях (см. манифест прав собственности на один из них), но сильно отстает.
  • Apple нуждается в том, чтобы Swift был и оставался их основным языком платформы, поэтому для них не имеет смысла ни поддерживать еще один большой язык на своей платформе, ни продвигать Swift в другие среды.

Rust уже использует LLVM 8 для ночных сборок в течение 5 месяцев IIRC.

Тогда, даже если Apple начнет поддерживать битовый код LLVM 7, битовый код, сгенерированный последними официальными сборками Rust, может не работать. Даже если это произойдет, он может сломаться при следующем переходе Rust на версию LLVM с несовместимым изменением в сгенерированном битовом коде.

LLVM 6 — это минимальная поддерживаемая версия, если вы хотите собрать ее самостоятельно, и она протестирована на CI.

Затем официальные сборки Rust за *-apple-ios будут собраны с помощью LLVM 6 (или лучше что-то вроде https://github.com/apple/swift-llvm/releases/tag/swift-4.2.2-RELEASE — если это работает) может исправить проблемы с биткодом.

Я думаю, что Rust в настоящее время поставляется с двумя бэкендами LLVM (Emscripten и стандартный) после слияния https://github.com/rust-lang/rust/issues/46819.
Хотя # 46819 упоминает бэкэнд ios LLVM для битового кода, он не реализован.

Не для того, чтобы полностью сорвать это, но не будет ли в целом более разумным попытаться разрешить транспиляцию на C для таких случаев? Маловероятно, что Rust сможет идти в ногу с требованиями Apple по биткоду.

Даже если действительно есть потенциальные источники несовместимости, это открывает двери для тестов, в которых мы могли бы попытаться скомпилировать совместимую старую версию Rust, которая включает правильную версию LLVM для Apple.

В полном кросс-платформенном подходе это все еще довольно блокирует, поскольку нам нужно будет иметь возможность компилировать один и тот же исходный код как из последней версии Rust, чтобы воспользоваться последними улучшениями, так и иметь возможность компилировать из более старой версии. версии Rust, специально для вывода двоичных файлов, совместимых с бит-кодом, для экосистемы Apple. Это выполнимо, но не подходит.

Я все еще очень рад видеть, как это происходит, поскольку это, по крайней мере, откроет двери для большего количества людей, чтобы протестировать это и подтолкнуть нас всех вперед в правильном направлении.

Говоря как человек, который сейчас пытается определиться с подходом к написанию кроссплатформенного мобильного кода для довольно большой команды, мы буквально не можем использовать Rust, если не можем генерировать биткод. Одно из наших приложений использует битовый код, чтобы иметь возможность генерировать достаточно небольшой двоичный файл для загрузки по сотовым сетям, и у нас есть несколько крупных клиентов, которые настаивают на этом.

Основываясь на всем, что я вижу о Rust, я думаю, что у него самый долгосрочный потенциал из всех возможностей, которые я вижу (мультиплатформенность Kotlin, кросс-компиляция Swift, Mono, Dart, C++, React Native), но ему определенно нужен биткод. быть полностью поддерживаемым, даже если это означает, что вы не сможете идти в ногу с последними выпусками Rust.

Даже если бы биткод работал, Rust все равно не может работать с watchOS или tvOS, не так ли?

Маловероятно, что Rust сможет идти в ногу с требованиями Apple по биткоду.

Проблема здесь в том, что LLVM для Rust слишком новый , а не в том, что он слишком старый . Я согласен, что у нас должна быть лучшая история совместимости здесь.

Насколько реально rustc поддерживать несколько LLVM?

Связанный: Поддержка целей tvOS и watchOS (и симулятора)

Он уже использует несколько LLVM. Для целей emscripten используется форк LLVM от emscripten, работающий на LLVM 6 atm.

Проблема здесь в том, что LLVM Rust _слишком новый_, а не то, что он _слишком старый_. Я согласен, что у нас должна быть лучшая история совместимости здесь.

Проблема не в том, что он слишком старый или слишком новый, а в том, что даже если ржавчина соответствует версии LLVM, в любом выпуске iOS она может снова сломаться. Apple (насколько мне известно) никоим образом не гарантирует стабильности в отношении биткода.

Проблема не в том, что он слишком старый или слишком новый, а в том, что даже если ржавчина соответствует версии LLVM, в любом выпуске iOS она может снова сломаться. Apple (насколько мне известно) никоим образом не гарантирует стабильности в отношении биткода.

На практике мы видим крупные обновления Xcode раз в год, когда выходят новые версии iOS. Когда такое случается, разработчики довольно ясно понимают, что им нужно начинать отправлять приложения с более новой версией Xcode, так что это редко кого удивляет. Я бы не сказал, что это особенно сложно спланировать.

Я бы не сказал, что это особенно сложно спланировать.

Поскольку нет абсолютно никаких гарантий относительно бит-кода, это может превратиться в нечто очень сложное для планирования. Представьте, что они будут решать от одного выпуска к другому использовать свой собственный формат битового кода, который не попадет в выпуск LLVM с открытым исходным кодом.

Поскольку нет абсолютно никаких гарантий относительно бит-кода, это может превратиться в нечто очень сложное для планирования. Представьте, что они будут решать от одного выпуска к другому использовать свой собственный формат битового кода, который не попадет в выпуск LLVM с открытым исходным кодом.

Если мы просто предположим, что Apple собирается внести критические изменения без оглядки на кого-либо еще, конечно. Наличие более четкой документации по их планам относительно Bitcode не сильно улучшит ситуацию, если мы предположим, что они злонамеренные или им просто все равно.

Но они явно сделали Swift важной частью своей платформы, и от него зависят многие тысячи разработчиков, включая их собственные команды и некоторых из их наиболее важных партнеров. Swift основан на LLVM с полностью открытым исходным кодом и сам разрабатывается полностью под открытым небом, включая цепочку инструментов, которую Xcode использует для генерации битового кода, который принимает Apple.

Таким образом, для того, чтобы они просто внезапно изменили этот формат, чтобы никто не заметил или не позаботился, им потребовалось бы сделать свои репозитории Swift и LLVM закрытыми, верно? Это, конечно, возможно, но мне это не кажется сверхвероятным.

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

Поскольку нет абсолютно никаких гарантий относительно бит-кода, это может превратиться в нечто очень сложное для планирования. Представьте, что они будут решать от одного выпуска к другому использовать свой собственный формат битового кода, который не попадет в выпуск LLVM с открытым исходным кодом.

Apple выпускает бета-версию Xcode примерно в начале июня, а окончательную версию — в сентябре. Через 6-9 месяцев он перестает принимать сборки приложений со старыми версиями Xcode в Appstore.

Я думаю, что за это время достаточно времени, чтобы подготовить изменения биткода.

Только что протестировано с Xcode 10.2 beta 3 (которая включает Swift 5 с LLVM 7), и я мог связать последнюю ночь с Rust со встроенным биткодом. Очевидно, что это работает только с таргетами iOS, поскольку в Rust нет таргетов watchOS/tvOS .

Я также согласен с тем, что Rust должен иметь возможность использовать форк Apple LLVM для всех целей, связанных с Apple, чтобы поддерживать совместимость битового кода.

Да, окно выпуска бета-версии звучит разумно. Я думаю, что идея о том, что Apple собирается закрыть исходный код LLVM или их формат битового кода, очень маловероятна, но Apple, требующая битового кода в будущих выпусках iOS, определенно звучит так, как будто это произойдет. И кто знает, может быть, они даже начнут требовать биткод для приложений Mac App Store с проектом Marzipan.

Предлагаемый негарантированный способ решения проблемы совместимости, по общему признанию, неприятен, но я думаю, что мобильные платформы в конечном итоге должны стать платформами уровня 1 , особенно в тех случаях, когда в противном случае вы бы использовали C++, например, для разработки видеоигр. Кроме того, вы также можете разрабатывать игры на Rust для Apple TV.

Я надеюсь, что официально санкционированный подход команды компилятора побудит кого-то поработать над этим, но я думаю, что более ранний комментарий @brson резюмирует колебания:

Мы успешно поддерживаем совместимость между несколькими версиями LLVM. Пока компании Apple и наши не расходятся слишком далеко друг от друга, это должно быть выполнимо, но всегда существует риск такой большой поломки, что границу нельзя будет пересечь.

Или, может быть, в будущем биткод стабилизируется, и мы все забудем об этих спорах 🙏

Я сейчас съем свою шляпу 😞

В котором я сказал:

идея о том, что Apple собирается закрыть исходный код LLVM или их формат битового кода, очень маловероятна.

В основном это было ответом на недоверие, выраженное @mitsuhiko :

Представьте, что они будут решать от одного выпуска к другому использовать свой собственный формат битового кода, который не попадет в выпуск LLVM с открытым исходным кодом.

Но если посмотреть на issue #48833 , прецедент точно есть. Как ранее писал @comex :

были случаи, когда функции отображались в LLVM Xcode до магистрали LLVM — например, весь порт arm64, когда он был первоначально разработан, потому что Apple хотела сохранить в секрете, что они планировали поставлять устройства arm64.

И история @michaeleiselsc из того же номера:

приложение, над которым я работал, сильно пострадало от случайных перезапусков в декабре 2016 года, и это было вызвано конкретной проблемой, которую LLVM с открытым исходным кодом исправила только в декабре 2017 года. Когда мы перешли с LLVM с открытым исходным кодом на LLVM от Apple в декабре 2016 года, проблема было исправлено

Учитывая, что идея заключается в использовании LLVM от Apple с Rust, это звучит не так уж плохо, но определенно существует риск случайной неприятной ошибки из-за расходящихся реализаций 😢. Это не тот риск, который могут взять на себя все проекты. Транспиляция звучит как лучший вариант на данный момент, но пока это не кажется таким уж возможным .

Я все еще думаю, что использование LLVM от Apple должно поддерживаться, но в документации должны быть четкие предупреждения, объясняющие, что нет никаких гарантий, что все будет работать (уровень 1.5 или что-то в этом роде).

Котлин/Родной. JetBrains рассматривает мобильные платформы в качестве приоритета, и хотя это заняло некоторое время, и это только маркеры битового кода (еще не полный биткод), он достаточно хорош для начала работы — см. JetBrains/kotlin-native#1564 и JetBrains/kotlin-native# 1202 (комментарий)

Спасибо, что указали на это, @oleksandr-yefremov! Я копнул немного дальше и смог воспроизвести подход kotlin/native в golang . Я считаю, что вы, ребята, должны иметь возможность сделать то же самое, что позволит использовать ржавчину в приложениях iOS/tvOS/watchOS с поддержкой битового кода без обязательной генерации битового кода.

Работает ли биткод сейчас? Кто-нибудь пробовал?

@volodg Я новичок в ржавчине. Тем не менее, я прошел этот урок с последней версией ржавчины каждую ночь (на момент написания rustc 1.37.0-nightly (088b98730 2019-07-03) ), и это НЕ сработало.

Маркеры вроде есть..

$ otool -arch arm64 -l librust.a  | grep bitcode
  sectname __bitcode
...

Но я получаю следующую ошибку при сборке для устройства iOS (работает симулятор):

ld: '/Users/amrox/Documents/Projects/rust-ios-example/hello-rust/libs/librust.a(rust-e6011ffb55678675.rust.8yq9vjk7-cgu.3.rcgu.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Это то, что я получил.

Мне удалось связать статическую библиотеку rustc nightly-2019-09-05 aarch64-apple-ios and rustflags = "-C lto -Z embed-bitcode" с приложением clang-1100.0.33.5 (Xcode 11 beta 7) and -fembed-bitcode . Исходный код https://github.com/saturday06/rust-ios-bitcode-test .

  • Знаете ли вы, необходим ли раздел __cmdline ?

Два года спустя я могу ответить: для развертывания на физических устройствах или создания архивов Xcode пустая командная строка подходит, однако для отправки в App Store Apple выполняет проверку командной строки clang. В этом PR я разместил более подробное описание, которое включает хакерский патч, чтобы заставить его работать: https://github.com/getditto/rust-bitcode/pull/7.

Я хотел бы как-то воспитать это, но варианты не привлекательны. Придумываем ли мы какие-то параметры clang при нацеливании на iOS? Предоставляем ли мы envvar, чтобы выбрать, как именно лгать, если Apple изменит свои правила проверки? Я был бы рад внести изменения, если бы здесь был разумный выбор.

-Cembed-bitcode=no не работает для цели ios. в файле .a все еще есть раздел битового кода
как собрать без биткода?

Была ли эта страница полезной?
0 / 5 - 0 рейтинги