Cross compiling for Win32 under Linux/ru

From Lazarus wiki
Jump to navigationJump to search

English (en) français (fr) magyar (hu) italiano (it) русский (ru) 中文(中国大陆) (zh_CN)

Заметки по кросс-компиляции исполняемых файлов Win32 из Linux

Начиная с 0.9.10 существует rpm 'fpc-crosswin32', который устанавливает необходимые утилиты binutils (например кросс ассемблер, кросс линкер), fpc .ppu файлы скомпилированные для win32 и вносит изменения в /etc/fpc.cfg.

Он не включает кросс-скомпилированные LCL .ppu файлы. Вам нужно скомпилировать их самостоятельно после установки, fpc-crosswin32.


Также существует быстрый способ описанный тут: http://wiki.lazarus.freepascal.org/Cross_compiling/ru

Lazarus и Free Pascal Compiler

О кросс-компиляции - понимайте то что вы делаете

Это короткое введение для новичков. В последующих разделах описывается как настроить систему для кросс-компиляции, имеется ввиду работая под linux создавать исполняемые файлы win32 (или freebsd, или dawin, или...) Почему кросс-компиляция: FreePascal это компилятор, преобразующий исходный код в исполняемые файлы (на машинном языке). Эти исполняемые файлы, кроме всего прочего, содержат информацию о том как операционная система запускает их на выполнение. Поэтому исполняемые файлы являются платформенно-зависимыми. Сам FreePascal не требует различных дистрибутивов. Он может создавать исполняемые файлы для многих платформ. Просто укажите ему это. Но компилятор - это только одна часть. Существует ещё ассемблер и линкер. И эти утилиты не способны создавать кроссплатформенный код. Поэтому были созданы специальные утилиты линкер 'ld' и ассемблер 'as' для каждой целевой платформы. Это binutils. После создания кроссплатформенных утилит все модули fpc pascal будут кросс-компилированы. Например, для каждой из целевых платформ существует отдельный файл system.ppu. Затем ваш конфигурационный файл fpc.cfg будет перенастроен, таким образом кросс-компиляция станет настолько лёгкой, что вы сможете забыть обо всех мелочах. То же самое нужно проделать и с LCL - lazarus component library. И после этого вы сможете кросс-компилировать программы на паскале для win32. Затем проверить их при помощи wine или скопировать на машину с Windows и протестировать на ней.

Почему из *nix в windows а не по-другому.

Основная причина - генерирование unix-бинарников на другой платформе (другой unix или Linux) более сложно. Более сложное статическое связывание, не говоря уж об остальном.

Придется использовать библиотеки из целевой платформы (gtk, glib, libc и т.д.), и множество дополнительных настроек для ld. (пути к библиотекам, путь к линкеру и т.д.)

Это было частично сделано (в статическом случае), но это сложно т.к. требует внесения изменений в файлы линкера и командную строку линкера, а также глубокого понимания о сборке бинарников Unix.

Скачивание исходных кодов FPC

Исполняемых файлов недостаточно, вам потребуются все исходники fpc. Обратитесь к www.freepascal.org. Вы можете использовать SVN или ежедневные сборки. Для следующих примеров исходники fpc были скачены в папку ~/sources/fpc.

Скачивание gnu binutils.

Например, binutils-2.18.tar.gz скачайте в ~/download/binutils-2.18.tar.gz.

Кроссплатформенная сборка binutils

В репозитории fpcbuild существует скрипт для сборки binutils для всех поддерживаемых целевых платформ: install/cross/buildcrossbinutils

Скачиваем инсталлятор fpcbuild:

 []$ cd ~
 []$ svn co http://svn.freepascal.org/svn/fpcbuild/branches/fixes_2_4/install install

Создаём копию скрипта:

 []$ cd ~/install/cross/
 []$ cp buildcrossbinutils buildcrossbinutils.sh

Правим переменные в начале нового скрипта.

Переменная BASE указывает на директорию сборки и установки. Директория должна быть пустой. Например:

 BASE=~/cross_fpc

Теперь разберёмся со скачанным файлом binutils. Если путь к скачанному файлу ~/download/binutils-2.18.tar.gz то укажем

 BINUTILSPATH=~/download/
 BINUTILSBASE=binutils
 BINUTILSVERSION=2.18
 BINUTILS_GZIP=yes

Скрипт будет автоматически соберёт это в ~/download/binutils-2.18.tar.gz. Остальные переменные определяют какие целевые платформы мы имеем. По умолчанию их довольно много, поэтому компиляция может занять много времени (часы на слабых машинах). Для кросс-компиляции для Windows вам потребуется только

 TARGETS_WIN="mingw32"
 

и закомментировать все остальные:

 #BSD="freebsd netbsd openbsd"
 #TARGETS_WIN="cygwin mingw32 msdosdjgpp"
 #TARGETS_I386="${BSD} linux solaris darwin"
 #TARGETS_POWERPC="${BSD} linux darwin"
 #TARGETS_SPARC="${BSD} linux solaris"
 #TARGETS_M68k=


Затем запустите скрипт:

 []$ sh buildcrossbinutils.sh

Скрипт создаст поддиректорию 'logs' с соответствующим содержимым. В случае чего, начните поиски оттуда.

Заметьте что для некоторых платформ (Linux,FreeBSD, win32) утилиты доступны в скомпилированном виде. Смотрите ftp://freepascal.stack.nl/pub/fpc/contrib/cross/

Кроссплатформенная сборка FPC

В рекозитории fpcbuild существует скрипт для сборки fpc под все поддерживаемые целевые платформы: install/cross/buildcrosssnapshot Создайте копию скрипта

 []$ cd ~/install/cross/
 []$ cp buildcrosssnapshot buildcrosssnapshot.sh

Исправьте переменные в начале нового скрипта.

Вам потребуется изменить всего лишь CROSSTOOLSROOT, FPCCVS, DESTDIR, TARGETS_OS и TARGETS_CPU. Например:

 CROSSTOOLSROOT=~/cross_fpc/cross
 FPCCVS=~/sources/fpc
 TARGETS_OS="win32"
 TARGETS_CPU="i386"
 DESTDIR=~/cross_fpc/
 

Затем запустите скрипт:

 []$ sh buildcrosssnapshot.sh

После этого вы получите кросс-компилированные модули в ~/cross_fpc/

Конфигурирование вашего fpc.cfg

Откройте с правами рута /etc/fpc.cfg или создайте копию /etc/fpc.cfg to ~/fpc.cfg и отредактируйте этот файл. Найдите в файле пути поиска модулей.

Примечание: В более старых версиях FPC вместо $fpcversion и $fpctarget использовались $version и $target.

-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget
-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/*
-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/rtl

Замените их специальными путями для других платформ. Например, для linux и кросс-компилированной win32:

#IFDEF win32
-Fu~/cross_fpc/lib/fpc/$fpcversion/cross/units/i386-win32/
-Fu~/cross_fpc/lib/fpc/$fpcversion/cross/units/i386-win32/*
-Fu~/cross_fpc/lib/fpc/$fpcversion/cross/units/i386-win32/rtl
-XPi686-mingw32-
-FD~/cross_fpc/cross/bin
#ELSE linux
-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget
-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/*
-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/rtl
#-Fu~/fpc/packages/*;~/fpc/rtl/linux
#ENDIF

Выполните: тестирование и устранение неполадок.

Кросс-компиляция LCL и компонентов lazarus

В коммандной строке:

cd lazarus; make clean all OS_TARGET=win32
cd lazarus/lcl; make clean all 

Таким образом всё скомпилируется для win32 (включая IDE, что необязательно, но это сокращает объём манипуляций).

Или в IDE Сервис->Параметры сборки: отметим LCL, Synedit, Codetools, Регистрация пакетов и Интерфейс IDE как Очистить+Собрать, установми в поле Библиотека виджетов LCL значение win32/win64, а Целевая ОС - win32. Затем нажмём 'Собрать'. Ваши файлы .ppu/.o скомпилированные для linux не будут перезаписаны и вам не нужно будет перекомпилировать их каждый раз, т.к. в рабочей папке будут созданы специальные директории для других целевых систем.

Коросс-компиляция проекта

Выберите Проект->Параметры проекта->Параметры компилятора->Генерация кода Целевая ОС='win32' и Проект->Параметры проекта->Параметры компилятора->Пути Библиотека виджетов LCL='win32'. Вот и всё. При следующей компиляции будет создан исполняемый файл win32. IDE произведёт поиск утилит win32, поэтому компилятор будет работать с rtl для win32 вместо rtl для linux. Когда вы откроете другой проект или закроете текущий и откроете его вновь IDE автоматически установит настройки.

Подсказки по кросс-компиляции и Lazarus

Если вы создаете приложение/пакет для различных целевых ОС, вам необходимо действовать следующим образом: устранить баги, скомпилировать и протестировать приложение под linux, затем скомпилировать и протестировать его под win32, .. . Потому что обычно вы перезаписываете ваши .ppu файлы, и вам придётся перекомпилировать всё, каждый раз когда вы переключаете захотите изменить целевую ОС. Но это не обязательно. Lazarus поддреживает макросы.

Пример 1: Кросс-компиляция проекта для linux и win32.

Установите значение Проект-> Параметры компилятора->Пути->Каталог вывода модулей = $(TargetOS). Этот макрос будет заменён названием целевой ОС в нижнем регистре (например 'linux' для Linux, 'win32' для Win32). Каталог вывода модулей находится в директории вашего проекта (директории где расположен файл .lpi). Создайте директории с именами 'linux' и 'win32' в директории вашего проекта. Когда вы кликните на кнопке 'Показать параметры' в самом низу окна Параметры проекта, вы увидите -FElinux/ или -FEwin32/. Эта опция сообщает компилятору куда записать создаваемые файлы (файлы .ppu/.o).

Пример 2: Кросс-компиляция проекта для различных платформ и наборов виджетов.

Укажите Каталог вывода модулей следующим образом $(TargetCPU)/$(TargetOS)/$(LCLWidgetType) и создайте поддиректории для всех целей. Этот путь также используется LCL.

То же самое можно проделать и для пакетов.

Кросс-компиляция и пакеты Lazarus

Пакеты Lazarus не ограничены библиотеками. Они могут быть использованы для компиляции практически чего угодно. И IDE автоматически перекомпилирует их при необходимости. Пакеты могут наследовать опции компилятора. Например: проект, использующий пакет, наследует каталог вывода пакета. Другими словами: каталог вывода пакета добавляется в пути поиска модулей проекта. Посмотрите в IDE: Проект->Параметры проекта->Параметры компилятора->Унаследованные.

Наследование срабатывает единажды. Но существуют исключения: Целевая платформа (ОС и CPU) проекта переопределяет цель для всех используемых пакетов. Это значит, если вы укажете Целевую ОС в проекте = 'win32' и скомпилируете проект, IDE выполнит проверку на предмет необходимости перекомпиляции пакетов для Целевой ОС.

Пример:

Пакет А имеет директорию вывода: lib/$(TargetOS) Проект использует А.

  1. Проект собирается для linux. IDE компилирует А для linux в <PackageDirOfA>/lib/linux/, затем компилирует проект для linux.
  2. Проект собирается для win32. IDE компилирует А для win32 в <PackageDirOfA>/lib/win32/, затем компилирует проект для win32.
  3. Проект снова собирается для linux. IDE проверяет, существует ли А для linux. Затем компилирует проект для linux.

Таким образом, использование макросов экономит много времени.

Для Unix (в общих чертах)

Опция -XLA используется для изменения зависимостей библиотек определённых в модулях. Формат -XLAold=new изменяет link-опцию ld -l<old> на -l<new>.

Опция -XR<sysroot> (recent trunk) может быть использована для указания корня Целевой ОС. Она используется для:

  • добавления префикса к указанным по-умолчанию путям библиотек, в прошлом вы использовали -Xd и эти пути вручную. Например для i386-linux

вместо следования в /lib, /usr/lib, и /usr/X11R6/lib к ld, будет следовать в <sysroot>/lib, <sysroot>/usr/lib, и <sysroot>/usr/X11R6/lib к ld.

  • определение местоположения библиотек С (linux-версий): glibc или uclibc. Например для uclibc будет принята попытка поиска по пути '<sysroot>/lib/ld-uClibc.so.0'

Для Linux под Win32

Это просто, есть некоторая информация в buildfaq

FreeBSD для sparc

Я пытался кросс-компилировать из х86 для Sparc Solaris 9. Несмотря на то что результат не работал должным образом привожу мою командную строку:

в компилятор / выполнить:

 gmake cycle CPU_TARGET=sparc OS_TARGET=solaris CROSSBINUTILPREFIX=solaris-sparc- CROSSOPT='-Xd -Fl~/src/sollib'

~/src/sollib директория которая содержит:

  • набор файлов .o из /usr/local/gcc-3.3-32bit/lib/gcc-lib/sparc-sun-solaris/3.3
  • libgcc.a из /usr/local/gcc-3.3-32bit/lib/gcc-lib/sparc-sun-solaris/3.3
  • набор файлов lib*.so из /usr/lib: libaio.so libmd5.so libc.so libelf.so librt.so libdl.so libm.so

Иллюстрация проблемы при компиляции:

 Free Pascal Compiler version 2.1.1 [2006/03/17] for sparc
 Copyright (c) 1993-2005 by Florian Klaempfl
 Target OS: Solaris for SPARC
 Compiling system.pp
 system.pp(15,1) Fatal: Syntax error, "BEGIN" expected but "identifier UNIT" found

Я подозреваю что ошибся с выбранными .o файлами.

Для Mac OS X

Посмотрите этот пост.


Авторы

Эта страница была конвертирована из epikwiki version.