Visual Studio Android встраивает файлы сборки в приложение
У нас есть решение Visual Studio Android с (среди прочего) проектом статической библиотеки, которая содержит функциональные возможности, реализованные в сборке. Подобно:
my.S -> libMine.a -> libMyApp.so
Некоторые обручи (ниже) уже были перепрыгнуты, чтобы получить его для компиляции. Затем происходит сбой связывания проекта общей библиотеки приложения (на обеих архитектурах, которые нас интересуют - x64 и arm64), с неопределенными ссылками на функции, которые реализованы в [the] assembly [file].
Похоже, что Visual Studio (или ее подключаемый модуль Cross Platform Mobile Dev / Android) не обрабатывает элементы проекта файла сборки достаточно корректно - рассматривается как файлы компилятора C/C++, он выдает ошибку в первом символе точки (т.е. в .text
); и Microsoft Macro Assembler "не поддерживается на этой платформе". Поэтому я посмотрел на настройку пользовательского шага сборки с помощью следующей команды:
$(ClangToolExe) %(FullPath) --target=$(ClangTarget) -g -o $(IntDir)%(FileName).o
Это будет предварительной обработкой, компиляцией и связыванием, но с неправильным компоновщиком: вместо того, что используется для конкретного набора инструментов Android, он пойдет для того, что в моей установке MinGW, который не распознает режим эмуляции - в любом случае, это не расположение моего набора инструментов NDK.
Мы можем пока пропустить связывание объекта (добавить -c
на вышеуказанную команду). К нашему большому разочарованию, результирующий объектный файл все еще не добавляется в статическую библиотеку, что подтверждается {Rest of the toolchain path}ar t libMine.a
, И действительно, библиотека будет иметь неопределенные символы для наших функций, как показано {Rest of the toolchain path}objdump -t libMine.a
,
Давайте добавим объектный файл в результирующую библиотеку вручную, в качестве шага после сборки. Команда:
$(ToolChainPrebuiltPath){Rest of the toolchain path}ar.exe ru $(TargetPath) $(IntDir)my.o
objdump -t libMine.a
теперь покажет, что у нас есть символы. Однако существует также определенная пара *UND*.
Перемотка вперед:
- Добавление
my.o
сar rub otherObjectThatReferencesMyFunctions.o libMine.a
, чтобы хорошие символы отображались до того, как неопределенные не будут иметь значения. - Связывание моего скомпилированного файла сборки со вторым пользовательским шагом сборки,
$(ToolChainPrebuiltPath){Rest of the toolchain path}ld.exe $(IntDir)%(FileName).o -o $(IntDir)%(FileName).o
не имеет существенного значения. - Повторный запуск компоновщика в статической библиотеке, как второй шаг после сборки
$(ToolChainPrebuiltPath){Rest of the toolchain path}ld.exe $(TargetPath)
не имеет существенного значения. - Последние два шага приводят к предупреждению о пропущенном символе _start (точка входа?). Я предполагаю, что это связано со связыванием исполняемого файла, который нам не нужен.
Что я делаю неправильно? Как я могу разрешить эти неопределенные ссылки?
1 ответ
То, что, кажется, сработало, было:
1, убедитесь, что расширение файла сборки .S
, т. е. заглавная S. Это один из немногих случаев, которые я обнаружил, когда регистр имени файла имеет значение для Windows.
2. Настройте проект так, чтобы файл сборки был создан с clang.exe {full/path/to/assembly.S, i.e. %(FullPath)} -c --target=$(ClangTarget) -g -o $(IntDir)%(FileName).o
, В случае VS Android, мы должны указать выходные данные сборки отдельно, то есть $(IntDir)%(FileName).o
расстаться снова и снова.
3, запустить ar
как команда пост-сборки: {correct toolchain}/ar.exe rus $(TargetPath) {output from assembly compilation}
, для каждого файла сборки.
Единственное, чего не хватает этому решению, - это обнаружению [отсутствия] изменений, что означает, что файл сборки будет перестраиваться при каждой компиляции, а также все, что от него зависит.