WxWindows application compile (for Linux) and cross-compile (for Windows) under Linux/Eclipse/CDT

From WxWiki
Jump to: navigation, search

NOTE: This text is published as-is for now, as mini how-to, to conserve and spread results of my development. I hope to get back later to make it nice with all that wiki formating.


INTRODUCTION

I am currently able to compile and cross-compile GUI applications for (native) GNU/Linux (Debian Etch (stable)) platform as well as for MS Windows platform (tested against Microsoft Windows XP Professional Version 2002 Service Pack 1 as well as Linux wine). I am even able to produce Windows versions with shared .DLL libraries of wxWidgets.

To achieve this, I had to put some effort in web search survey, investigation of some missing information, development of several tricks and putting it all together. As I value this time and the community spirit of Linux platform, I wish to share the results by this minihowto. Be warned, it is almost sure neither perfect nor complete guide, but I hope it will help anyway.

PLATFORM

This is the actual list of components involved:

  • AMD 32 bit / 1G RAM - processor and memory
  • Debian Etch (stable) - operating system
  • Eclipse platform 3.3.1.1 - universal platform for various IDE environments
  • Eclipse CDT 4.0.1.200709241202 - IDE for compiler-independent C++ development
  • gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) - Linux C++ (cross-)compiler
  • MinGW 3.4.5.20060117.1.dfsg-2 (Debian stable package) - Linux to Windows cross-compile library platform
  • wxWidgets 2.8.7 (z wxGTK) - GUI development library
  • Microsoft Windows XP Professional Verze 2002 Service Pack 1 - for testing purposes only


HOW TO ...

This is description of my installation in brief. I will supply links to other how-tos I have used and reduce my text to only comments on the linked texts, where there is some undocumented information or workaround needed.

1) Eclipse platform

Installation is quite straightforward, just unzip and run. I have myself read little bit more around and installed as shared version, so that I installed as root and now I am installing any add-ons and upgrading as root, while developing can perform any user from his own account. I did not experience any troubles with this (this is the option ad 3) in the Multi-user install how-to).

I have downloaded the C/C++ development IDE from here http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/20071103/eclipse-cpp-europa-fall2-linux-gtk.tar.gz, then upgraded the IDE from inside the platform and installed two add-ons (plug-in development add-on, what I need just for my experimenting with Eclipse itself and the Sublipse, Subversion(see next paragraph) plug-in for Eclipse, what I recommend for any seriously meant production development.)

For some reason (I did not investigate) I was before unable to make Eclipse run properly from the "complete" package eclipse-platform-SDK-3.3-linux-gtk.tar.gz, so beware. However I noticed there is newer version available, http://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops/R-3.3.1.1-200710231652/eclipse-SDK-3.3.1.1-linux-gtk.tar.gz. I have no experience with it and will be grateful for any feedback on it regarding new installations.

1a) Option: Subclipse

You can read more on Subversion here: http://subversion.tigris.org/, Subclipse homepage is here: http://subclipse.tigris.org/ and how-to regarding installation from inside the Eclipse you can find here: http://subclipse.tigris.org/install.html.

2) Gcc

I have used the standard Debian package "gcc" for Debian Etch (stable), just apt-get it (or use whatever GUI your desktop platform offers) and you are good to go. (It may install several dependency chains as well). Home page for gcc project is http://gcc.gnu.org/

3) MinGW

The same goes for MinGW. The package name is "mingw32" and it will install dependencies mingw32-binutils and mingw32-runtime automatically. You can read more e.g. here: http://www.mingw.org/wiki/Getting_Started.

4) wxWidgets themselves

Do not worry about wxWidgets! They seems to be tough to install as there are many variants available and no pre-compiled packages, but after a week of reading and try and fail attempts you will learn easy way how to install them (well, I did it for you already ;-) ).

Homepage of wxWidgets can be found here: https://www.wxwidgets.org/, while downloads are here https://www.wxwidgets.org/downloads/. I am using GTK version, what should support both major Linux desktop environments, KDE and Gnome. The important think is you DO NOT need wxALl or wxMSW versions, if you plan to cross-compile in Linux for Windows target. You will be (see below) able to compile wxGTK sources into wxMSW cross-libraries, so everything you need is wxGTK (or your platform eventually - if someone is trying to adapt e.g. for Mac).

Now, you will compile the downloaded sources (at least) twice to generate (at least) two different libraries - one for the Linux applications and one for Windows cross-applications. To get general overview of the process, you should read Compiling and getting started, do not worry if you do not get all details, I will explain important ones further.

Even for one platform you can build more than one library, each one to be used to build applications with different requirements. E.g. if plain-text or Unicode is to be used for strings or if ODBC or JPEG format support is to be included. To ease this, there is the tool (shell script) ./configure. The concept is such, that you make ONE EMPTY directory for each library to be compiled (generally elsewhere) and run configure script from it, passing the parameters customizing the nature of the final library. The script runs for a while, checking parameters and your system and platform capabilities and finally it builds the make file in your directory and several other files and sub-trees needed for the compilation. Still there is NO OBJECT FILE OR LIBRARY yet.

The "(general elsewhere)" means, that the command need not be literary ./configure --<parameter> -- <parameter>, but e.g. in my case ../../configure --<parameter> -- <parameter>., as I use the tree

wxGTK-2.8.10 + wxGTK + Unicode
             |       |
             |       \plaintex 
             |
             + wxMSW + Unicode
                     |
                     \ Unicode-ODBC 

etc. above the folder, where I unpacked the source. It could even be /home/userx/Project/wxWidgets/source/configure --<parameter> -- <parameter>, if your library configuration would be in different subtree than source files. Just think carefully about your own tree to be able to maintain it well-arranged for a long. You can read Build System Management now to get other ideas and more process overview.

The "--prefix=..." stands for the important parameter of the ./configure script. This parameter gives builder the path, where the library built (several library files in most case plus some more stuff) will be stored. The folder need not exist and is created in the process if it does not. This way you can make the well-arranged tree of wxWidgets libraries for various purposes, independent (and independently recompilable, e.g. with new wxWidgets releases) on each other.

Other parameters of ./configure are in general the build modifying ones (like --host= and --target= which allows for fine tuning on what platform and for what platform you are compiling), --with-<something>/--without-<something> (including/excluding some modules from the final library) and --enable-<something>/--disable-<something> (modifying features of the basic library). I will support basic parameters for Linux and Windows builds later. You can anyway list all available parameters by ./configure --help and, as this is quite lenghty list filter the searched for word by ./configure --help | grep <something>.

When ./configure finishes, it presents overview table of options. You should check this one (I myself found sometimes that it is not what I want due for e.g. misspell in parameters) an if OK, continue with make. If there is some mistake, you can simply rerun ./configure with corrected parameters again.

Make is as simple as writing command "make", as all other prerequisities are already generated by ./configure. If you find some mistakes during make process, check carefully gcc and MinGW instalations. If installed properly and enough recent versions (and enough disk space etc.), there should be no problem in compilation or link.

If you did not read it yet, please read Compiling and getting started, part "Reminder:" now. Notice, that you can (and need) to run "make distclean" if you want to redo "./configure" with different parameters in the particular folder once "make" was already inited. However you can continue "make" if you just need to continue the interrupted run or use "make clean" to just rerun make with the previously ./configured parameters. Notice several hints on various error messages workarounds as well.

4a) Tested ./configure paramer sets

To build Unicode library of wxWdgets for Linux native (GTK+) applications and using shared (.so) libraries I have used:

../../configure --prefix=/usr/local/wxWidgets/wxGTK/Unicode/ --enable-unicode

The same library for cross-compilation under Windows:

../../configure --prefix=/usr/local/wxWidgets/wxMSW/Unicode/ --host=i586-mingw32msvc --enable-unicode --with-msw --without-subdirs

For comments on shared libraries in cross-compiled versions read 4b) below.

The same library for cross-compilation under Windows but with statically linked wxWidgets library:

../../configure --prefix=/usr/local/wxWidgets/wxMSW/Unicode/ --host=i586-mingw32msvc --enable-unicode --with-msw --without-subdirs --disable-shared

(Just --disable-shared parameter added).

4b) Staticaly link or use shared libraries

There is plenty of pages out there stating, that shared cross-compiled library does not work. The same seemed for me for a long. Later I have found, that I am receiving exactly the same errors even with statically linked library, what went into development of hints under 6) below. Furthermore you have to understand .DLL concepts and locations in MS Windows instalation folders (described ad 8) ). Othervise I did not mention any troubles with shared libraries so far, so I expect, that the abovementioned warnings results just from these reasons if not from some troubles in older versions of wxWidgets. However the total size of just the shared .DLLs is about 10MB while simple statically linked application takes only 2,4MB what can be further compressed to some 750 kB using UPX (http://upx.sourceforge.net/ - I did not mention any trouble using it so far), so it is wise to use staticaly linked of library if you plan to deploy just one application, while using shared libraries where many wxWidgets applications are intended to be run on the same machine.

5) Post-make actions as root

After make command finished without errors, you have to do two final instalation steps. You must be loghed in as the superuser (root) to run them:

  1. make install
  2. ldconfig

5a) make install

This is as simple as command

sudo make install

This command installs the previously compiled libraries to the /usr/local/... path.

5b) ldconfig

What I learned so far about the "ldconfig" command, this command is intended to create symbolic links in various library folders, that links the newly created libraries, named with the version numbers as the filenema extensions (dot separated numbers) at the name's end to the "default" named link (without version numbers), to allow to use this standard name regardless of the further upgrades and recompilations. Why is this important for you? In the case of "native" platform library, this should make links needed to simply use wx-config (see ad 6a) below) in default path and with lastly built default version of wxWidgets library. I am not sure, if it is needed when you use custom paths to individual libraries, however to ensure no problems I have included that the paths to every library folder were included in the ldconfig configuration file (see below) and that ldconfig was run after each make install.

General configuration file for ldconfig is /etc/ld.so.conf. In my case it containedjust one line: include /etc/ld.so.conf.d/*.conf What I interpreted so, that every file in /etc/ld.so.conf.d/ folder will be interpreted cumulatively. Indeed there existed folder /etc/ld.so.conf.d/ on my filesystem and it contained (among others) wx.conf file, what contained two lines (as the result of previous attempts with wxWidgets Debian package):

# Local libraries support - introduced for wx-wwidgets
/usr/local/lib obsoleted by definitive tree structure

I have changed this file to contain the following, what works fine for me:

sudoedit /etc/ld.so.conf.d/wx.conf
# Local libraries support - introduced for wx-wwidgets
#/usr/local/wxWidgets/wxGTK/Unicode/lib
#/usr/local/wxWidgets/wxMSW/Unicode/lib
#/usr/local/wxWidgets/wxMSW/Unicode-static/lib

Uncomment the lines pointing to the path of the previously installed libraries, and after run

 sudo ldconfig

6) Building application with Eclipse

The following are minimal requirements to build simple C++ application using wxWidgets in the Eclipse/CDT environment. I will neither go into details of Eclipse nor into details of general structure of the wxWidgets application skeleton. Please use Google and documentation of relevant components. Just one remark - there is NO predefined template for wxWidgets application in the Eclipse so far. It is announced that new versions of Eclipse will contain means to define application (project in the Eclipse terms) skeleton template. Until that you have to build from scratch (wxApp documentation is good startpoint) or to copy some old application sources and strip all the "flesh".

Start your project standartly, via File->New->C++ project and place all header and source files in the src folder. One remark: if you need to use some externally generated files (like wxFormBuilder generated files), the option Link to file in filesystem (under File->New->General->File->Advanced) does NOT work properly as for header files compiler returns with error "Is not file or directory" and source files are not compiled at all. You have to use File->Import to create a local copy of the respective files.

6a) Concept of wx-config

To understand the following settings description, you have to understand the concept of wx-config shell. There is link to this shell generated under each <base_path_to_library>/bin folder (e.g. /usr/local/wxWidgets/wxGTK/Unicode/bin) and it writes various command line components (e.g. compile parameters) to the standart output, depending on the parameters used. These parameters are addapted to fit the particular library variant case. You can use the shell feature, that text written in reverse-apostrophes in the command line is interpeted as if standard output of the corresponding command would be written there. This way you need not to take care about compilaion and link command line parameters and paths yourself and can let the generated wx-command to fill them for you.

In theory one wx-config can serve several variants of libraries. If you followed the above process, generating each library variant into separate base folder, you need not to bother with that parameters, as each individual wx-config link serves exactly one library variant, so you have just to state proper path to choose it. You can get brief description of all possible parameters by wx-config --help.

We will need just following variants anyway: wx-config --cxx -> this generates command to invoke C++ compiler (the same as linker), (e.g. g++) wx-config --cxxflags -> this generates parameters for the C++ compiler (including all the include paths etc.) wx-config --libs -> this generates parameters for linkage (including paths to library files etc.) You can check what each of them means exactly for your library variant by simple running it in the terminal command line and watching output.

6b) Compile/linkage parameters

To compile and link application using wxWidgets library, you have to add or change the following locations in the generated project properties:

  • select your project in the Project explorer window
  • from main menu choose Project->Properties
  • select C/C++ Build->Settings

Each project starts with two default build targets, "Debug" and "Release". So now you can choose the one you wish to build or even make target of your choose by pushing "Manage configurations" button and selecting "New...". In the following dialog you can select new name (e.g. Windows) and target, which settings will be copied into new one. In the following I expect, you started project based on default Release settings.

  • to the left of the "Settings" window there is tree of options. It starts with the GCC C++ Compiler root.
  • select GCC C++ Compiler (root itself) and to the right place `wx-config --cxx` to the Command edit box context. Do not forget back-apostrophes around and use wx-config on the proper path (e.g. `/usr/local/wxWidgets/wxMSW/Unicode/bin/wx-config --cxx`).
  • you can check overall options to the compiler in the "All options" window, but you CAN NOT change them here. Instead do the following:
  • select GCC C++ Compiler -> Miscelaneous and prepend `wx-config --cxxflags` before the original text of the "Other flags" edit box. Again use back-apostrophes and proper path. The resulting text should read " `/usr/local/wxWidgets/wxMSW/Unicode/bin/wx-config --cxxflags` -c -fmessage-length=0". Do not get confused, if the textbox is so width, that you have to scroll right. The corresponding scroll bar is all the height down, just above the buttons.
  • if you plan to compile just C++, you do not need to change anything below GCC C Compiler.
  • The next root you have to change is GCC C++ Linker:
  • Place `wx-config --cxx` into GCC C++ Linker's Command textbox (back-apostrophes, path).
  • Place `wx-config --libs` into GCC C++ Linker->Miscelaneous, Linker flags textbox.

This is all of standart configuration, but do not close the window yet, we will do several more tricks.

6c) Command line components order

This was the trickiest part to find out, as it looked like normal linker related errors, but they were caused by something else. Even worse, the default order is somehow fine for "native" GTK application build, but not for the Windows cross-compiled one. However the cure is easy, once you find it: In the

GCC C++ Linker root 

there is

"Command line pattern:" 

textbox. It is pre-filled by reasonable defaults for newly created build targets, however for cross-compilation they need to adjust. Generally, it declares order, in which various command line components (linker command, flags, library paths, parameters, input/output file names etc. appear in the final command).

The trick is, that default order places library to be linked with BEFORE object files to be linked names.

In cross-compilation link this leads to many undefined references related to wxWidgets components.

So I have changed the order (quite intuitively) and voila, build run with no problems.

Default order is:

${COMMAND} ${FLAGS} ${OUTPUT_FLAG}${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}

while order to be used for cross-compilation linker is:

${COMMAND} ${INPUTS} ${FLAGS} ${OUTPUT_FLAG}${OUTPUT_PREFIX}${OUTPUT}

6d) Sidenote

You could see some warning about strict rules violation during "native" GTK compilations. This should be fully ignorable and is described on many places, just use Google. Easy workaround is to lower optimization level to just -O1. This does not happen for Windows build, even with -O3.

So now close window with OK button and you should be good to go. Go, try to build your application.

7) Testing with wine

I experienced following behaviour, when testing cross-compiled application under wine on Linux:

  • clicking statically-linked application under KDE Konqueror does not work, even if it correctly identifies binary as Windows executable
  • typing "wine <app-name>" from terminal works normally
  • running of shared library application under wine does never work for me (I am pretty sure, that further research on proper place for shared libraries should make it work, but did not have enough time and motivation to do it so far)

8) (option) Using shared libraries under MS Windows

When you compile wxWidgets themself with --with-msw and --enable-shared (or no --disable-shared as shared is default), there will be generated two kinds of files into <base-path>/lib folder:

  • .dll - these are shared libraries to be used during runtime in MS Windows
  • .dll.a - libraries to be linked with application during linkage in Linux

Do not care about the .dll.a extensions, they ARE OK and linker automatically use them if no extension is given to library name on the command line (as wx-config does).

To be able to run shared application, you must place all the *.dll libraries in the proper path on MS Windows. I tested either to put them all to the same folder as the application or to the C:\WINDOWS\system32, both works.

Details can be quite easy Googled from the Microsoft web pages; there should be even third path possible, but I did not further investigate. Pitty, that C:\WINDOWS\system32 subdirectories are NOT searched through, so it is NOT POSSIBLE to use something like C:\WINDOWS\system32\wxWidgets.

9) Multiple thread support

To run application which use (or does not disable) multiple thread support, you need one more library, the mingwm10.dll. You DO need this one even if you use static build of wxWidgets. The rules where to place it are the same as the *.dlls in ad 8). It is luckily just 16kB in size and I downloaded it for free here: http://www.dll-files.com/dllindex/dll-files.shtml?mingwm10