Как мы добавляли поддержку Apple Silicon в анализатор (arm64)

С выходом PVS-Studio 7.34 стали доступны нативные сборки анализатора для macOS на архитектуре Apple Silicon (ARM). В этой заметке мы хотели бы подробнее рассказать о проделанной работе, а также предложить советы по портированию кроссплатформенных инструментов на новую перспективную архитектуру.

e905f5d47365dc5bcfe507e46ebbff88.png

Коротко о главном

Как уже было сказано выше, начиная с версии 7.34 PVS-Studio предоставляет поддержку macOS на архитектуре Apple Silicon (arm64). Пакеты для архитектуры Intel (x86_64) продолжат выходить, как и раньше.

Минимальные поддерживаемые версии macOS:

К релизу подготовлены следующие компоненты:

  • анализаторы: С, С++, C#, Java;

  • плагины: CLion, IDEA, Rider, VS Code и Qt Creator (начиная с 14.0);

  • утилиты: blame-notifier (оповещение разработчиков о проблемах), plog-converter (конвертер отчётов).

Всё это уже можно скачать по ссылке, установить и использовать. Будем рады вашим отзывам :)

Что насчёт Windows ARM?

Поддержка Windows ARM существует в PVS-Studio начиная с версии 7.28.

А как дела с Linux ARM?

Запросов на поддержку этой платформы и архитектуры пока не поступало, поэтому и планов на эту версию пока что нет.

Нюансы поддержки новой архитектуры

Фух, с официальной частью закончили, можно переходить к самому интересному :)

Итак, PVS-Studio — это набор компонентов, утилит и плагинов, написанных на языках С и С++, C# и Java. Просто взглянув на список языков, попробуйте угадать, какой из них доставил больше всего проблем…

f8bd54cf40c38f6389c451c2fe4913da.png

Если вы подумали про С и С++, то, увы, должен вас огорчить — больше всего проблем оказалось при портировании именно Java анализатора. Хотя… Здесь нужно сделать оговорку, что проблема была вызвана не самим языком, а крайне специфичными взаимоотношениями между общими компонентами С++ и Java анализаторов. Пожалуй, об этих нюансах как-нибудь отдельно расскажет наша Java-команда. Не буду спойлерить интересный материал :)

Что ж, если не Java, то тогда точно С++? Да, теперь в точку. И позвольте сократить вам пару часов времени на исследование.

На самом деле, если ваш проект уже собирается под macOS, то особых проблем с портированием вы не встретите. При использовании сборочной системы CMake достаточно просто добавить пару записей в ваш CMakeLists.txt и уже можно начинать тестовую сборку:

set(CMAKE_OSX_ARCHITECTURES "arm64")  # целевая архитектура
set(CMAKE_OSX_DEPLOYMENT_TARGET 11.0) # целевая версия SDK
set(CMAKE_OSX_SYSROOT "/path/to/sdk") # путь до SDK указанной версии

Примечание: SDK версии 11.0 указан потому, что это минимальная версия, которая поддерживает архитектуру Apple Silicon. Кстати, если вам необходимы пакеты SDK для развертывания на CI/CD серверах и вы по какой-то причине не можете установить SDK с помощью XCode, то их можно взять в этом репозитории GitHub.

Интересным моментом также является возможность сборки так называемых Universal Binary, которые могут работать одновременно как на Intel (x86_64), так и на Apple Silicon (arm64). Для этого достаточно модифицировать указанную выше переменную:

set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")

Проверить полученный результат можно с помощью команды file. В случае успеха вывод будет содержать информацию сразу о двух архитектурах:

>> file hello_world
hello_world: Mach-O universal binary with 2 architectures: 
[x86_64:Mach-O 64-bit executable x86_64] [arm64:Mach-O 64-bit executable arm64]
hello_world (for architecture x86_64): Mach-O 64-bit executable x86_64
hello_world (for architecture arm64):  Mach-O 64-bit executable arm64

Продолжаем погружение

Выше я упоминал, что если ваше приложение уже было портировано на macOS, то особых проблем быть не должно. «Подержи моё пиво» — сказал Clang.

Представляю вашему вниманию D138307 в LLVM или, как его ещё называют, «Remove default definition of std: char_traits». Суть его в том, что разработчики решили удалить из libc++ специализации std::char_traits, которые не упоминаются в стандарте С++. Наше удивление после отказа компилятора собирать код с std::basic_string было сложно описать словами.

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

However, since we’re aware of some users of char_traits for unsigned char and signed char, we’re keeping those two specializations around for two releases to give people some time to migrate.

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

Если у вас появился вопрос: «а зачем вам такая специализация std::basic_string?», то ответ на него — наследие библиотеки OpenC++, на основе которой сделан C и C++ анализатор. Код библиотеки за это время претерпел значительные изменения, однако кое-где остались такие забавные места. Когда-нибудь мы избавимся и от них :)

Сторонние компоненты

Портирование приложения на новую архитектуру — это не только адаптация собственного кода, но и чаще всего работа со сторонними библиотеками. Если они не поддерживают целевую платформу и архитектуру, у вас есть три пути: ждать обновлений, адаптировать код самостоятельно или искать альтернативные решения.

Мы же столкнулись с отсутствием поддержки архитектуры ARM (а точнее Windows ARM) в популярной C++ библиотеке для сбора stack trace при аварийном завершении программы — backward-cpp. После изучения документации и анализа кода мы подготовили pull request с исправлениями для улучшения поддержки ARM. Надеемся, что это небольшое улучшение окажется полезным и для других разработчиков, которые занимаются портированием своих приложений на ARM:)

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

А как же Java и C#?

К счастью, там рассказывать особо и нечего. По сути, все проблемы разрешились сменой целевой архитектуры в файлах проекта и «отколачиванием» захардкоженных путей и значений :)

Заключение

Надеемся, вам было интересно почитать немного историй про портирование анализатора на новую архитектуру. Возможно, у вас даже появится желание портировать и свой софт. После исправления ошибок компиляции и запуска приложения вы можете столкнуться с некоторыми багами, это вполне нормальный этап в процессе портирования. Чтобы сократить их количество и облегчить этот процесс, вам на помощь придут статические анализаторы, такие как PVS-Studio, готовые выявить ошибки в вашем коде. Можно попробовать (в том числе на macOS Apple Silicon), скачав анализатор по ссылке.

Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Mikhail Gelvikh. How we added Apple Silicon support to analyzer (arm64).

© Habrahabr.ru