Libpq и Java
На днях я ввязался в одну авантюру, а она оказалась смоляной ямой. Увяз по самые уши и не знаю, продолжать или бросить. Авантюра, кстати, тоже связана с Postgres.
Я хотел проверить: будет ли драйвер для Postgres быстрее, если переписать его с чистой Джавы на Libpq. Кто не знает, Libpq – это библиотека на Си для работы с базой. Идея в том, чтобы поручить большую часть работы коду на Си, а самому только дергать функции через JNI.
Такую сишную обертку я написал; тесты показали, что Libpq как минимум не хуже, а порой и быстрее Джавы. Взаимодействие Джавы с сишным рантаймом – мутная история, в ней много специфики. Ошибся указателем – Джава вылетает. Но это не идет ни в какое сравнение с тем, где я увяз – сборкой.
Я хотел собрать сишный код под три платформы (винда, мак, линукс) и две архитектуры (x86-64, arm64). Их произведение дает шесть комбинаций. Вопрос: где и как собирать? Допустим, у меня есть Мак на арме; докер на нем дает Линукс на арме. Нужна винда на арме, а где ее взять? То же самое с интелом: у меня есть старый Мак на core i3, но по сегодняшним меркам он такой медленный, что лишний раз трогать его не хочется. Есть игровой комп с Виндой на интеле, но не будешь же носить его с собой? В итоге я поручил сборку Github actions: в нем доступны все шесть видов машин, а сценарий пишется на yaml.
По наивности я думал, что напишу один Makefile, который вызову с разными переменными – и дело в шляпе. Идея провалилась из-за адского разнообразия сред и платформ. Сборка простого кода на C++ отличается даже не в рамках ОС, а дистрибутива. Везде спонтанные отличия, условности, разные названия папок, путей и так далее.
Несколько примеров. На винде x64 компилятор MSYS2 ставится в папку
c:\temp\a\msys64, а на арме – в d:\temp\a\msys64 (другой диск). Почему был
C, а стал D? И почему он ставится не в корень, а куда-то в temp? Уверен, что
есть объяснение, но неудобно.
Мак и его Homebrew тоже хорош. На интеле пакет libpq включает утилиту
pg_config – она показывает, где лежат заголовочные файлы и другое барахло. На
M1 в таком же пакете утилиты нет. Почему?
Плохи дела и на этом вашем Линуксе. В той Убунте, что идет на Гитхабе, пакет
postgres-client – 16 версии, а мне нужна 18. Нужно подключать частный
репозиторий Postgres. У него тоже особенности: на интеле пакет
postgres-client-18 включает заголовочные файлы, а на арме – нет. Нужно качать
dev-барахло.
И таких вещей очень много. Разные пути, переменные среды; здесь есть файл, а тут нет и так далее. Смейтесь или нет, но мне понадобилось 166 (сто шестьдесят шесть) попыток, чтобы прошли все билды. Я убил на это вагон времени, забивая на работу и даже личные обязанности. При этом та удачная 166-я попытка – грубый черновик, который еще доводить и доводить до ума.
Напомню, все это лишь для того, чтобы:
- получить последнюю версию libpq под нужные ОС и архитектуру;
- собрать динамическую библиотеку из кода на C++;
- сохранить libpq и библиотеку в артефакты.
Допускаю, что плохо знаю тонкости кроссплатформенной сборки; возможно, есть инструменты, которые щелкают эту проблему как дважды два. Почему их нет в поисковой выдаче? Я безвылазно сидел в Гугле и StackOverflow, повидал сотню разных ошибок – и ни разу не было ответа, мол, поставь программу X, и она все тебе соберет.
Если такая программа есть или вы решали похожую проблему, расскажите, пожалуйста.
Нашли ошибку? Выделите мышкой и нажмите Ctrl/⌘+Enter