- Compile windows app on linux
- 1. Getting mingw , the cross-compiler tools
- 2. Hello_World.exe
- 3. Simple SCons build system
- Кросс-компиляция и отладка C++ Windows-приложения под Linux
- Wine, не юникодное приложение, английский интерфейс Ubuntu и русский язык
- Настройка IDE Code::Blocks для кросс-компиляции и отладки
- Линкование статической библиотеки boost’а
- Compile Windows C console applications in Linux
Compile windows app on linux
This article explains how to cross-compile a 64-bit windows application from linux. This means that you don’t need to have a windows build-machine, and you can use all linux based development tools. This is great for developers who feel more comfortable in linux. For some time, I knew that this was technically possible, but always assumed it would be either too difficult, or otherwise buggy and cumbersome. That I would eventually give up, and porting the compilation to windows, using a build machine running windows. After two days of working at this problem, I’m eager to explain and share my experience with it. I’ll try to do so in two parts:
- Install the mingw cross-compilation tools.
- Compile hello_world.exe .
- A SCons based build system, that will be used in part 2.
- Cross-compile SDL . Cross-compile a program that links to, and initializes SDL .
- Repeat the process for similar libraries:
- SDL_image , together with libjpg and libpng .
- SDL_mixer , with libogg and libvorbis
- SDL_ttf , with libfreetype
- GLEW
1. Getting mingw , the cross-compiler tools
To cross-compile, I’ll use the mingw -project, in partuclar, the 64 bit gcc -like build tools. On ubuntu, I installed these with
If you’re relying on c++11 features, you might want to verify that the mingw-g++ compiler is version 4.7 or newer. To check out which version you have:
2. Hello_World.exe
In order to cross-compile a hello world program, all you need to do is:
It works fine. The —static makes sure all necessary libraries get packed into the exe . Without it, you’ll get an error message.
3. Simple SCons build system
Since a project usually consists of more than a main.cpp , you want an exensible build system. Preferably, one with the ability to easy switch between target platforms, and manage the differences between them.
I’ll be using SCons . It is based on python , and easy to understand and customize. In fact, I don’t think you need to know anything about SCons or python to make sense of the scripts (which rarely is the case for make and cmake )
To follow along, grab a copy of the repo (and check out the «basic» branch)
The SCons «Makefile», aka SConsctruct
This sets it up so we can use —win64 flag to specify that we want a windows build. With this enabled, x86_64-w64-mingw32-g++ is used as the compiler, instead of g++ .
Additionally, the SConstruct script asks SCons to put all files created by the build in ./build/linux/ or ./build/windows/ . This keeps things tidy, and we also don’t need to rebuild everything when alternating building for the two platforms.
Lastly, is does whatherver the SCons build script src/SConscript (together with the environment we set up) tells it to do. But, before I show that, I want to show the two python scripts that will be used to differentiate the details between the target platforms:
The SCons build script, src/SConscript
Using the SCons setup, we can build a linux executable ( ./bin/main ) with:
Table of Contents
License
About
Roald Fernandez
Norwegian software developer
Thinks alpacas are underratedКросс-компиляция и отладка C++ Windows-приложения под Linux
Показали мне недавно интересное приложение, под которое можно разрабатывать плагины. Приложение оказалось очень полезным для научной работы, но вот незадача — приложение разработано под Windows, у меня стоит Ubuntu. Windows для разработки под это приложение от лаборатории получить пока не удалось. Чтобы не тратить время, решил освоить кросс-компиляцию и отладку этого приложения.
Итого, имеется:
Ubuntu 12.10 x64
Не-юникодное приложение Мастерская Граф-Моделей (МГМ) (В командах консоли будет называться gmw.exe)Нужно:
Разрабатывать и отлаживать плагины (dll-библиотеки), не устанавливая Windows.И тут нам помогут Wine, Code::Blocks, портированное GDB, и boost.
Wine, не юникодное приложение, английский интерфейс Ubuntu и русский язык
получаются зюки следующего вида:
На эту проблему интернет очень быстро дает следующую подсказку:
LC_ALL=ru_RU.UTF-8 wine gmw.exe
В моём случае, данный подход не улучшил ситуацию ни на йоту.
Как выяснилось, русских локалей в системе не было добавлено (тыц).sudo echo "ru_RU.UTF-8 UTF-8" >> /var/lib/locales/supported.d/ru sudo locale-gen ru
LC_ALL=ru_RU.UTF-8 wine gmw.exe
И, вуаля, запускается приложение с читаемым русским текстом:
Настройка IDE Code::Blocks для кросс-компиляции и отладки
Установка Code::Blocks
В дальнейшем для отладки нам потребуется менять код плагина отладки поэтому лучше сразу взять версию Code::Blocks из под svn.
Устанавливаем svn:sudo apt-get install subversion
С помощью svn получаем код C::B, для этого переходим в папку, в которую хотим сохранить код C::B, где и набираем:
svn checkout svn://svn.berlios.de/codeblocks/trunk
Переходим в полученную папку ‘trunk’.
Компиляция C::B происходит с помощью g++, autotools, automake и некоторых других утилит, которые необходимо установить:
sudo apt-get install libtool autotools-dev automake autoconf g++ libhunspell-dev libgtk2.0-dev libgamin-dev libboost-dev
sudo apt-get install libwxgtk2.8-dev
И дальше, устанавливаем сам codeblocks (ключ —prefix можно упустить для использования настроек по-умолчанию):
sudo ./configure --prefix= --with-contrib-plugins=all sudo make sudo make install
Более подробно можно посмотреть по ссылке.
Настройка компиляции и линковки
Выполняем пункты с 1 по 5 с форума Code::Blocks. После этого компиляция программ должна работать, если не используется линковка к платформо-зависмым библиотекам (линковка с boost::regexp будет рассмотрена позже).
(*) В новом Code::Blocks немного изменилось меню по сравнению с инструкцией. Настройки искать нужно в ‘Settings->Compiler. ‘. Для старого Code::Blocks (10.05) пункт 5 нужно выполнить полностью, для нового же (12.11) настройку касающуюся gdb в 5 пункте пока трогать не будем.Если используется boost его лучше положить отдельно от /usr/include, т.к. по этому адресу лежит много linux-специфичных заголовочных файлов, которые мы не хотим включать в проект при компиляции под Windows.
UPD: При настройке линковки в поле «Other Linker Options» имеет смысл добавить опцию «-Wl,—subsystem,windows,—kill-at», которая помечает, что это реально Windows DLL, и, что самое главное, запрещает использовать декорирование символов (—kill-at) при экспорте функций с соглашением вызова __stdcall. Подрбнее здесь и здесь.
Начиная с пункта 7 по ссылке выше, описывается кросс-отладка, но, к сожалению, insight.exe, упоминающийся в инструкциях, найти не удается. Поэтому пойдем своим путем.
Кросс-отладка в Code::Blocks & MingW32 gdb для Windows
gdb, который является родным для линукса частично умеет отлаживать Windows приложения, правда, умеет он только останавливаться на исключениях и почти всегда игнорирует точки останова. Чтобы справиться с этими проблемами скачиваем gdb в пакете mingw32 под Windows. Для этого скачиваем и затем распаковываем и переходим в подпапку ‘bin’. Устанавливаем gdb под Windows:
wine mingw-get.exe install gdb
Теперь в этой же папке bin появился файл gdb.exe, он-то нам и нужен.
Создаем скрипт для имитации обычного gdb для этого в файл /usr/bin/i586-mingw32msvc-gdb
sudo gedit /usr/bin/i586-mingw32msvc-gdb
Для старого C::B все уже настроенно, для нового же отладчик нужно настроить дополнительно. В пункте ‘Settings->Debugger’ кликаем по ‘GDB/CDB debugger’ затем по ‘Create Config’. В новом конфиге меняем команду запуска отладчика на ‘/usr/bin/i586-mingw32msvc-gdb’, остальные настройки по желанию. После этого идем в ‘Settings->Compiler. «, в пункте ‘Selected Compiler’ выбираем тот компилятор, который настраивали до этого и затем на вкладке ‘Toolchain executables’ меняем ‘Debugger’ на наш свежесозданный конфиг. Теперь отладчик будет останавливаться на точках останова, хотя и остановить программу в произволльный момент не сможет (данная проблема пока еще не решена). Правда при попытке отладить,C::B выдает следующую ошибку:
The program has stopped on a breakpoint but the breakpoint format is not recognized: 0x1A0x1AZ:/SamplePlugin.cpp:48:948:beg:0x68087599
Эта ошибка говорит о том, что плагин отладчика в C::B не понимает выдачу отладчика gdb.exe. Как выяснилось при ближайшем рассмотрении плагин отладчика имеет платформо-зависимый код, и вот тут-то и нужно вспомнить что у нас есть исходники C::B. Мы сейчас слегка подкоррекируем код этого плагина. Нужно будет поменять код только одного файла ‘/src/plugins/debuggergdb/gdb_driver.cpp’
Для этого нужно перейти в корень проекта C::B (откуда запускалась команды ./bootstrap), по умолчанию это папка ‘trunk’. И накактить патч:patch --unified --strip=0 --forward --input=gdb_driver.cpp.patch
sudo ./configure --prefix= --with-contrib-plugins=all sudo make sudo make install
И почти все готово, остается только создать проект. Шаги 12-13 по ссылке. Если же вы хотите создать проект dll-библиотеки, то указывайти создание динамической библиотеки в мастере и переименовывайте разширение в dll.
Проверям, что в настройках проекта стоит выбранная нами цепь компилятор-линкер-отладчик. ‘-Build Options. ‘ пункт ‘Selected compiler’, и можно радоваться и отлаживаться. Напомню, что по какой-то причине отладчик не может быть прерван во время исполнения, т.е. все отладочные действия могут буть применены только во время останова программы. В частности нельзя поставить новую точку останова, если программа не стоит на какой-либо другой точке останова…Линкование статической библиотеки boost’а
Библиотека boost в основном является набором заголовочных файлов, и потому никаких проблем с линковкой обычно не возникает. Но для некоторых частей boost’а необходимо линковаться к статической библиотеке, например, boost::regex. Пробуем собрать проект и получаем:
/boost/regex/v4/cpp_regex_traits.hpp|1059|undefined reference to `boost::scoped_static_mutex_lock::scoped_static_mutex_lock(boost::static_mutex&, bool)'
Ошибка возникает из-за того, что мы пытаемся прилинковаться к linux билиотеке, для того чтобы построить windows-приложение.
Чтобы слинковаться нужно скомпилировать boost::regex с помощью MingW32 (про кросс-компиляцию). Скачиваем boost, распаковываем и переходим в папку с распаковынным boost’ом. Создаем файл user-config.jam в корне домашней директории:using gcc : : i586-mingw32msvc-g++ ;
sudo ./bootstrap.sh --with-libraries=regex --without-icu sudo ./b2
После выполнения последней команды у меня были ошибки «failed updating 1 target», что, правда, не мешает собираться программам.
В результате, у нас есть полностью подготовленная среда для написания, сборки и отладки Windows-приложений или Windows-библиотек из под Linux. Теперь можно приступать к работе…
Compile Windows C console applications in Linux
Best answer so far, and yes, there was a dupe 😀 Also nice to post the needed packages. Straight answer, to the punch.
Thanks for the answer. Also sorry for the duplicate question, I didn’t spot it. 🙂 Keep up the good work! Thanks again.
On Fedora, we also have resources for learning about compiling for win32 using mingw, an irc channel, the mingw32 utilities and a bunch of pre-built libraries for windows — for more info, see: fedoraproject.org/wiki/SIGs/MinGW .
You can if it’s standard C, and doesn’t use Windows libraries.
C code itself is very portable, and the standard C libraries (libc) are available pretty much everywhere. If your code does printf() and sscanf() and fopen() and so on, then it will just compile and run on another platform. Windows, Linux, BSD, etc.
It’s the libraries other than libc that introduce portability challenges.
Anything that links with Windows-specific platform libraries is trouble. Kernel32.lib, user32.lib, etc etc.
There are third-party libs, too, that, if written in C, should be available across Linux and Windows. PCRE is a good example here — it’s a Regular Expression library written in C, and it’s available on Windows as well as on Linux. there are literally hundreds of libraries in this set.
If you confine yourself to libc and library calls into portable libs, then you will have a portable C application.