Кросс-компиляция cygwin → mingw

Некоторое время назад я начал свой кроссплатформенный проект. Поскольку сижу я в основном за Windows, то для компиляции обычно использую cygwin, а для сборки билдов для тестеров под cygwin живет i686-w64-mingw. Все было хорошо, но вот пришла пора, и для вывода пары фраз текста я решил подключить к проекту libfreetype. При компиляции на cygwin проблем нет — ведь в репозитории есть соответствующий пакет, ну а для mingw, естественно, придется собирать либу самому.

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

Для начала немного теории. В любом проекте на autotools кросс-компиляция легко реализуется с помощью двух основных параметров:

  • --build — указывает имя среды, в которой мы компилируем
  • --host — указывает имя среды, в которой результат будет запускаться

Важно не путать эти ключи, устанавливать оба в mingw32 — тоже не лучший вариант (ведь он и правда поверит, что вы работаете в MSYS).

В итоге, строка конфигурации будет выглядеть следующим образом:

Но не спешите ее выполнять.

freetype имеет 2 зависимости: libz и libbz2, — их статические версии для mingw мы уже как бы собрали ранее. И если сейчас попытаться скомпилировать freetype, libtool на них ругнется: мол, мы тут динамические библиотеки компилирует, нефиг тут статику мне совать. В чем то он прав, но нам все же придется как-то обойти это ограничение. Самое простое решение — передать ключи библиотек напрямую линкеру:

Запускаем сборку — все прекрасно! Только… почему-то в экспорте dll не только freetype, но и libz и libbz2! С чего бы это?

Причина кроется в ключе -no-undefined. Есть два способа добавить функции на экспорт: специальные атрибуты у нужных функций и ключ -no-undefined, тогда все функции будут в экспорте. Как с этим бороться? На помощь приходит -export-symbols, чтобы его активировать, выполним:

Если сейчас запустить сборку libtool ругнется что win32 не может иметь неопределенные символы в экспорте и соберет статическую либу. Чтобы отключить такое поведение нужен еще один патч:

Но сборка все еще не работает. Все из-за того, что, повторюсь, win32 не может иметь неопределенные символы в экспорте. Он просто ругнется на несколько функций, которых у нас нет. А именно, относящиеся к Mac. Все, что надо сделать, удалить ненужный header:

Последний штрих (активация улучшенных алгоритмов):

Теперь все легко соберется!

Полный скрипт:

В конце можно стрипнуть либу (лежит в /usr/local/freetype/bin), сжать upx, обрубить с помощью rebuildpe, обновить скрипты pkg-config и aclocal и радоваться жизни! Надеюсь вы не будете наступать на мои грабли.

Удачи!

VP