суббота, 26 сентября 2009 г.

Кросс-компиляция C/C++ программ для Windows в Linux

Кратко расскажу как создать так называемый cross-compile toolchain для компиляции Windows-программ из под Linux. Cross-compile toolchain - это набор средств для создания приложений для целевой платформы не имея собственно самой целевой платформы. Обычно это используется при сборке программ под различные экзотические платформы, в данном случае такой целевой платформой выступает далеко не экзотическая Windows. Термин "целевая платформа" уже прозвучал, помимо него имеется еще термин "хост-платформа" (или "платформа сборки"), думаю их значение пояснять не нужно.
Хватит рассуждать пора делом заниматься, привожу краткую инструкцию в результате которой вы получите готовый инструмент для сборки С/С++ программ для Windows непосредственно в Linux. Используя инструкцию собрал toolchain в ArchLinux и CentOS 5.3, после собрал с помощью него MinGW32 для Windows с последним GCC 4.4.1 с поддержкой C/C++ прямо в Linux. В итоге остался очень доволен и получил ценный опыт, которым собираюсь поделиться с вами.


Перед тем как непосредственно приступить убедитесь что у вас установлены средства разработки, такие как GCC, G++, CVS, Automake, Autoconf, make и т.п. Если что-то не сработает в ходе выполнения инструкции - возможно в системе не хватило каких-то пакетов. Если вы занимаетесь разработкой на C/C++ то скорее всего все эти пакеты в вашей системе уже установлены.


Первым делом получим последние версии MinGW Win32 API и MinGW Win32 Runtime:

export CVSROOT=:pserver:anoncvs@cygwin.com:/cvs/src
cvs login (пароль anoncvs)
cvs -z3 co -d mingwrt src/winsup/mingw
cvs -z3 co -d w32api src/winsup/w32api

Теперь скачаем Binutils, GCC, GCC-G++, GMP и MPFR:
wget http://ftp.gnu.org/gnu/binutils/binutils-2.19.1.tar.bz2
wget http://gcc-uk.internet.bs/releases/gcc-4.4.1/gcc-core-4.4.1.tar.bz2
wget http://gcc-uk.internet.bs/releases/gcc-4.4.1/gcc-g++-4.4.1.tar.bz2
wget ftp://ftp.gnu.org/gnu/gmp/gmp-4.3.1.tar.bz2
wget http://www.mpfr.org/mpfr-current/mpfr-2.4.1.tar.bz2

Распакуем все что скачали:
tar xjf binutils-2.19.1.tar.bz2
tar xjf gcc-core-4.4.1.tar.bz2
tar xjf gcc-g++-4.4.1.tar.bz2
tar xjf gmp-4.3.1.tar.bz2
tar xjf mpfr-2.4.1.tar.bz2

Начнем со сборки и установки Binutils для целевой платформы:
cd binutils-2.19.1
mkdir build && cd build
../configure --target=i686-pc-mingw32 --disable-multilib
make
sudo make install
cd ../..

make install установит собранные бинарники в /usr/local/i686-pc-mingw32
Для дальнейшей сборки надо скопировать заголовочные файлы MinGW в папку куда будут устанавливаться файлы для целевой архитектуры:
sudo cp -r mingwrt/include /usr/local/i686-pc-mingw32
sudo cp -r w32api/include /usr/local/i686-pc-mingw32

Если в переменной окружения PATH у вас отсутствует путь /usr/local/bin - добавте его:
export PATH="/usr/local/bin:$PATH"

Теперь соберем и установим GCC с ключом -gcc (предварительно сделаем ссылки на GMP и MPFR, чтобы они тоже собрались):
cd gcc-4.4.1
ln -s ../gmp-4.3.1 gmp
ln -s ../mpfr-2.4.1 mpfr
mkdir build && cd build
../configure --target=i686-pc-mingw32 --disable-multilib
make all-gcc
sudo make install-gcc
cd ../..

Понадобятся библиотеки из MinGW API:
cd w32api
mkdir build && cd build
../configure --host=i686-pc-mingw32 --prefix=/usr/local/i686-pc-mingw32
make
sudo make install
cd ../..

К сожалению тут идет неприятная часть с кросс-зависимостями между GCC и MinGW Runtime, которая, впрочем, решается довольно просто. Мы повторно собираем GCC но уже с ключом all:
cd gcc-4.4.1/build
make

Сборка завершится с ошибкой, но нам это не важно, главное были собраны необходимые библиотеки, которые понадобятся для сборки MinGW Runtime, скопируем их в папку целевой платформы:
sudo cp i686-pc-mingw32/libgcc/crtbegin.o i686-pc-mingw32/libgcc/crtend.o \
i686-pc-mingw32/libgcc/libgcc_eh.a i686-pc-mingw32/libgcc/libgcc.a \
/usr/local/i686-pc-mingw32/lib/
cd ../..

Теперь можно собрать и установить MinGW Runtime:
cd mingwrt
mkdir build && cd build
../configure --host=i686-pc-mingw32 --prefix=/usr/local/i686-pc-mingw32
make
sudo make install
cd ../..

Возвращаемся к сборке GCC, теперь все должно собраться нормально:
cd gcc-4.4.1/build
make
sudo make install
cd ../..

Ну вот и все, cross-compile toolchain готов, можете приступать к сборке нативных Windows-приложений не выходя из Linux. В качестве компилятора для C используйте i686-pc-mingw32-gcc и для C++ используйте i686-pc-mingw32-g++. Для autoconf скриптов configure достаточно указать опции --host=i686-pc-mingw32 и --target=i686-pc-mingw32, тогда скрипт сам определит нужные программы и по возможности попытается собрать весь проект для запуска на целевой платформе, именно так собирается GCC 4.4.1 для запуска в Windows, но об этом в другой раз. Удачных сборок :)

6 комментариев:

  1. Круто! Ты молодчага.
    Только может я тебя расстрою но на убунте я установил mingw из репозитория и скомпилил командой i586-mingw32msvc-gcc.
    Пойду спать завтра буду дальше разбиратся.

    ОтветитьУдалить
  2. Тем не менее все равно очень полезная статья

    ОтветитьУдалить
  3. Ахринеть...
    wget http://www.mpfr.org/mpfr-current/mpfr-2.4.1.tar.bz2 нот фаунд.
    автор, ищи мне зеркало.. :/

    ОтветитьУдалить
  4. Ложная тревога. Ошибка с инетом.
    зато у меня при выполнении make gcc-all ошибка:
    checking for gmp internal files... configure: error: header files gmp-impl.h and longlong.h not found
    хотя делаю все по инструкции

    ОтветитьУдалить
  5. СУПЕР СТАТЬЯ! Очень помогла мне для сборки GCC для версии 4.5.1. Первый раз собрал за неделю, второй за сутки, третий, вот, за полдня!
    Только мне не понятна зависимость между mingw32 и GCC? В чём причина такой перекрёстной зависимости?

    ОтветитьУдалить
  6. Konstantin:
    Быстрое решение, находясь в каталоге gcc-X.Y.Z/build сделать так:
    cp ../gmp/gmp-impl.h gmp
    cp ../gmp/longlong.h gmp
    И снова набирать make all-gcc

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

    AlexZ:
    А вот не знаю в чем причина, когда готовил инструкцию к публикации то искал ответ, но так и не нашел ничего вразумительного, в итоге предложил самый простой способ обойти проблему.

    ОтветитьУдалить