воскресенье, 1 апреля 2012 г.

Кросс-компиляция с MinGW


Задача
Собрать готовый проект Visual Studio С++ на Linux с использованием компилятора MinGW.


Инструменты

Для сборки проекта в системе должны быть установлены следующие пакеты (названия в дистрибутиве Ubuntu 11.04):

1. wine
2. mingw32
3. mingw32-binutils
Названия пакетов даны для дистрибутива Ubuntu 11.04. В других дистрибутивах эти названия могут отличаться.


Реализация
Для простоты рассмотрим сборку уже готового проекта.
Например воспользуемся этим проектом:
http://www.codeproject.com/KB/directx/basicdd.aspx

Его же можно взять из каталога vs-source репозитория:
http://github.com/ellysh/ddraw-mingw.git


Из всего этого проекта нам понадобятся следующие файлы:
BasicDD.cpp
cSurface.cpp
cSurface.h
resource.h
resource.rc
bmp_bigcar_green.bmp
Из файлов BasicDD.cpp и cSurface.cpp удалим строчку:
#include "stdafx.h"
Создадим Makefile.mingw такого содержания:
MINGW=i586-pc-mingw32
MINGWLIB=/usr/$(MINGW)/sys-root/mingw/lib
CC=$(MINGW)-gcc
LD=$(MINGW)-ld
CXX=$(MINGW)-g++
STRIP=$(MINGW)-strip
WINDRES=$(MINGW)-windres -v
RANLIB=$(MINGW)-ranlib
AR=$(MINGW)-ar
RELFLAGS=-D_FORTIFY_SOURCE=2 -O2
CFLAGS=-Wall -Wno-pointer-sign $(RELFLAGS)
CXXFLAGS=-Wall $(RELFLAGS)
LDADD=-static-libgcc
.SUFFIXES: .rc .res .res.o
%.o: %.c
        $(CC) $(CFLAGS) $(ONLYCFLAGS) -c $< -o $@
%.o: %.cpp
        $(CXX) $(CXXFLAGS) -c $< -o $@
.rc.res.o:
        $(WINDRES) $^ $@
Это универсальный makefile для проектов на C и C++, собираемых компилятором 
MinGW.


Кроме этого, сделаем Makefile с конкретными целями сборки: 
include Makefile.mingw
CXXFLAGS+=-Wall -I/usr/include/wine/windowsLDADD+=-lgdi32 -luser32 -lddraw /usr/lib/wine/libuuid.a
OBJECTS=BasicDD.o cSurface.oRES=resource.rc
all: test.exe
test.exe: $(OBJECTS) $(RES).res.o
        $(CXX) $^ -o $@ $(LDADD)
$(RES).res.o: $(RES)
        $(WINDRES) $^ $@
clean:
       rm -f $(OBJECTS) $(RES).res.o test.exe
Если все это у вас соберется после команды
make
считайте что вам повезло.


При сборке с версией 1.3.6 оригинального Wine при линковке возникала следующая ошибка:
i586-pc-mingw32-g++ BasicDD.o cSurface.o resource.rc.res.o -o test.exe -static-libgcc -lgdi32 -luser32 -lddraw
BasicDD.o:BasicDD.cpp:(.text+0xa7): undefined reference to `_IID_IDirectDraw7'collect2: ld returned 1 exit status
make: *** [test.exe] Ошибка 1 
Проблема связана с тем, что в libuuid.a отсутствует идентификатор (UIID) интерфейса IDirectDraw7.


Для решения этой проблемы необходимо собрать свою библиотеку libuuid.a, включающую необходимый UIID.

1. Клонируем репозиторий оригинального wine
$ git clone http://source.winehq.org/git/wine.git
2. В файл dlls/uuid/uuid.c добавляем заголовочный файл с нужным UUID:
#include "ddraw.h"
3. Собираем libuuid


После сборки получим 2 файла: 

libuuid.cross.a
libuuid.a
Нам нужен libuuid.cross.a, т.к. он имеет формат статической библиотеки Windows и линкуется с объектным кодом, сгенерированным MinGW.

Копируем этот файл в каталог собираемого проекта.


Исправляем строчку с LDADD в Makefile:
LDADD+=-lgdi32 -luser32 -lddraw libuuid.cross.a
После этого сборка должна работать.

Замечания

1. В новых версиях Wine каталог dlls/uuid может переехать в другое место.
2. На самом деле картинка bmp_bigcar_green.bmp для сборки не нужна.
Все собирается и работает без нее, т.к. картинка уже содержится в resource.rc. Но если возникнет необходимость изменить выводимое изображение, необходимо отредактировать этот bmp файл и добавить его в resource.rc.

Ссылки

http://freesource.info/wiki/RuslanHihin/gitusermanual – руководство по использованию git
http://git.etersoft.ru/people/shpigor/packages/ddraw-test.git – репозиторий готового проекта
http://www.winehq.org – сайт разработчиков оригинального Wine
http://www.codeproject.com – хороший сайт с примерами кода на разных языках

Комментариев нет:

Отправить комментарий