This document describes how to cross-compile Windows CE applications using the tools provided by the CeGCC project. Part of this document is dependent on the host environment, another part is generic.
What does that sentence mean ? The host environment is the environment in which you compile your sources to produce an executable that can run on Windows CE. The CeGCC project actively supports two such environments :
In this chapter, we'll show how to compile a very simple source.
You can type or copy-and-paste this source :
#include <windows.h> int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { MessageBoxW(0, L"HELLO!", L"H3LLO!", 0); }
We've created a file named dialog.c that contains this code. To compile it, run this command :
arm-wince-cegcc-gcc -o dialog.exe dialog.c
Beware - you'll need to have the CeGCC DLLs installed on your PDA if you want to run this application. Read about that in the DLL document.
All the cross-commands have the names that are formed by using their target platform as a prefix, and the tool name as a suffix. For our case, the target platform is called arm-wince-cegcc which means we're building for an ARM processor, running the wince operating system, and producing pe executable files to be linked with the CEGCC library. An example : the C compiler is called arm-wince-cegcc-gcc .
PE stands for Portable Executable file format, and it's Microsoft's implementation of COFF (the Common Object File Format). ARM is a RISC processor family which is found in many embedded systems, also implemented by Intel as their Xscale processor line. Wince is shorthand for the Windows CE operating system. Windows CE is the technology base for environments such as PocketPC, Smartphone, and Windows Mobile.
In an apparent attempt to complicate matters, we implement not only the arm-wince-cegcc target (see above), but also the arm-wince-mingw32ce target. MinGW is a free software project implementing a Minimalist GNU for Windows. We're using this target to build applications that merely use the Windows CE API, not our CeGCC (newlib based) library. (Note that this is neither a full nor an official port of MinGW.)
We used to have a target called arm-wince-pe but renamed that to arm-wince-cegcc for consistency.
arm-wince-cegcc-addr2line | arm-wince-mingw32ce-addr2line | Convert addresses into source program file/line number |
arm-wince-cegcc-ar | arm-wince-mingw32ce-ar | archive library management tool |
arm-wince-cegcc-as | arm-wince-mingw32ce-as | the GNU assembler |
arm-wince-cegcc-c++ | arm-wince-mingw32ce-c++ | the C++ compiler |
arm-wince-cegcc-c++filt | arm-wince-mingw32ce-c++filt | C++ name demangler |
arm-wince-cegcc-cpp | arm-wince-mingw32ce-cpp | the C preprocessor |
arm-wince-cegcc-dlltool | arm-wince-mingw32ce-dlltool | a tool to create DLLs |
arm-wince-cegcc-gcc | arm-wince-mingw32ce-gcc | the C compiler |
arm-wince-cegcc-gccbug | arm-wince-mingw32ce-gccbug | Bug reporting script for the C compiler |
arm-wince-cegcc-gcov | arm-wince-mingw32ce-gcov | Test coverage analysis tool |
arm-wince-cegcc-gdb | arm-wince-mingw32ce-gdb | GNU Debugger |
arm-wince-cegcc-gdbtui | arm-wince-mingw32ce-gdbtui | GNU Debugger |
arm-wince-cegcc-gprof | arm-wince-mingw32ce-gprof | Profiling analysis tool |
arm-wince-cegcc-g++ | arm-wince-mingw32ce-g++ | the C++ compiler |
arm-wince-cegcc-ld | arm-wince-mingw32ce-ld | the GNU linker |
arm-wince-cegcc-nm | arm-wince-mingw32ce-nm | the tool to inspect symbols in load modules |
arm-wince-cegcc-objcopy | arm-wince-mingw32ce-objcopy | Copy and manipulate object files |
arm-wince-cegcc-objdump | arm-wince-mingw32ce-objdump | a tool to print data about object files |
arm-wince-cegcc-ranlib | arm-wince-mingw32ce-ranlib | tool to add or refresh the library directory |
arm-wince-cegcc-readelf | arm-wince-mingw32ce-readelf | Not very useful, we don't produce ELF files |
arm-wince-cegcc-size | arm-wince-mingw32ce-size | Print the size of executable contents |
arm-wince-cegcc-strings | arm-wince-mingw32ce-strings | Print a list of strings in an executable |
arm-wince-cegcc-strip | arm-wince-mingw32ce-strip | Strip debugging symbols and name tables from an executable |
arm-wince-cegcc-windres | arm-wince-mingw32ce-windres | Windows resource compiler |
A Makefile is a description of how to build something that depends on other sources. We're using it for building executables from program sources, which is its most common use.
ARCH= arm-wince-cegcc CC= ${ARCH}-gcc ${CFLAGS} WINDRES= ${ARCH}-windres CFLAGS= -g -D_WIN32_IE=0x0400 menu-resource.exe: menu-resource.o menu-resource.rsc ${CC} -o $@ menu-resource.o menu-resource.rsc -lcommctrl menu-resource.o: menu-resource.c ${CC} -c $? menu-resource.rsc: menu-resource.rc menu-resource.h ${WINDRES} $? $@ clean: -rm -f *.o *.exe *.rsc
To give you something to play with, all of the files for this example have been put online :
The executable should work on any suitable PDA. With the menu, you should be able to create a simple line drawing and quit the application.
Well, we're not going to explain how Make works, you can read stuff like this make tutorial for that. In your Makefile, you'll have to specify that the arm-wince-cegcc tools need to be used. Mixing your host platform's tools with these ones will have surprising results, you'll need to make sure that you cover all the tools required. For instance, that's the reason why I've overriden the CC variable: all calls to the C compiler will be dealt with in this way. An obvious hole is that any C++ source would trigger the C++ compiler, which is probably still g++, not arm-wince-cegcc-g++, because we've not specified
CXX= ${ARCH}-g++
Failure to do so could produce this :
dannypc: {136} make t.exe g++ -O -c -o t.o t.C arm-wince-cegcc-gcc -g -D_WIN32_IE=0x0400 -o t.exe t.o t.o: file not recognized: File format not recognized collect2: ld returned 1 exit status gmake: *** [t.exe] Error 1 rm t.o
That's because this generated a t.o file meant for (in my case) a Linux Pentium system, and the arm-wince-cegcc linker can't cope with that.
An important thing to know about Windows is that applications consist of program sources (in languages such as C or C++), but also of resource files. The traditional linker command line for UNIX and its lookalikes would only gather a bunch of .o files and libraries to combine them into an executable file. On Windows, there's a binary form of resource files that needs to be put in the exe files in the same way as the .o files. As you can see in the sample Makefile,
The actual run of a make command might look like this :
% make menu-resource.exe arm-wince-cegcc-gcc -D_WIN32_IE=0x0400 -c menu-resource.c arm-wince-cegcc-windres menu-resource.rc menu-resource.rsc arm-wince-cegcc-gcc -D_WIN32_IE=0x0400 -o menu-resource.exe menu-resource.o menu-resource.rsc -lcommctrl %
The only difference with all the above is the name of all the tools. You can still call e.g. the compiler in the same way, it just has a slightly different name. The Makefile that you can download (see above) is actually slightly larger than described here. Issuing a simple make command will also run compile commands such as :
arm-wince-mingw32ce-gcc -o hello-small.exe hello-dialog.cwhich creates an executable which only calls Windows CE's coredll, not the CeGCC DLL (cegcc.dll).
This needs to be expanded, please provide feedback with your experience so this chapter grows. The address for feedback is our mailing list : cegcc-devel@lists.sourceforge.net .
An important warning : the locale definition is not the same on all systems. If you write applications that cooperate with each other across system boundaries, be sure to exchange data only in formats that are truly portable. An example : the wide character encoding on my PDA has two bytes per character, on my Linux system it has four. GDB (actually the arm-wince-cegcc-gdb cross-debugger) and its stub are each working on one of those systems, and they're exchanging data as wide characters. That's rather silly off course, the multibyte encoding is better at exchanging data. For the tools to work together, it was necessary to create special functions that convert strings to and from the PDA format. This was not necessary for the same to work between the PDA and Cygwin (I'm guessing that desktop Windows uses the same format as Windows CE).
However, some of the XCE functions in our newlib library do support such functionality. (Only in the arm-wince-cegcc target.) The startup code (see src/newlib/newlib/libc/sys/wince/startup.c) sets up an environment variable PWD which it presets to either the current directory from the parent process, or the path extracted from the executable file we're running. Similarly a PATH variable is also put in the environment.
More information about this is in The unix-like layer provided by CeGCC.
In the MinGW environment (our arm-wince-mingw32ce target), some include files are meant to be missing. That's because the environment mimics the Windows CE platform as closely as possible. This can lead to unexpected situations, because standard C include files (some that are part of the ISO C Standard) will appear not to work.
An example of this is <errno.h> : this include file is part of several well document standards, see e.g. this description by the Open Group. This functionality is not part of Windows CE, so a development environment that closely mimics the platform API should not contain this include file or implement its contents.
One way to implement this is to leave <errno.h> out of our mingw implementation. This is not what we did. We do have this file, but it contains a construction which will make its use always fail. This is because the <errno.h> contains this
#ifdef __COREDLL__ #include_next <errno.h> #else /* __COREDLL__ */ ..
When you try to compile a source which includes this file, it'll fail.
Pedro says he has virtually deleted these files : they're there but you can't use them any more. The reason for this approach is that this type of approach might allow us to keep our sources in sync with the maintainers (of MinGW, in this case).
Note that the arm-wince-cegcc target has different characteristics than arm-wince-mingw32ce target. The <errno.h> file is an example of such a difference : it does exist, and works, in arm-wince-cegcc.
When you're using the arm-wince-cegcc tools, the unix-like layer kicks in : the cegcc.dll library provides you with all of newlib, a library originally written to offer a cheap C library for embedded environments.
Newlib comes with its own implementation of stdio, functions like fopen, fprintf, fclose, scanf, printf, and many more.
The trouble is that coredll.dll, Windows CE's runtime library, also comes with these functions, and the two libraries are incompatible with each other.
Getting in trouble with this is not all that easy, so we hope you don't go down this road. Should you ever find yourself in a position where you find that stdio functions mysteriously fail on you, then think about this. The way to figure out which functions your application is using is to use the arm-wince-cegcc-objdump utility. It'll tell you from which library each function is obtained. All of stdio should come from the same library.
Information |
Support |