|
This happened in July - one rainy day I (Stauff) was going to my work and suddenly remembered that Andy, whom I knew from university, is working just near my work - in the next building. It is a great thing for OS/2 users to talk to each other, since there are few of us today (sigh) so we talked a lot about OS/2 news, my new job, Linux and GNU and suddenly I remembered one thing that had been on my porting schedule for a long long time. "Andy - QT-3 (Qt (http://www.trolltech.com/) is a C++ framework/GUI toolkit for X and Windows) - requires GCC 3.0 and I can't build it with your PGCC, can you give it a look?" - I asked. "No problem" - was his answer. However we soon faced tons of problems. QT3 refused to build, had problem during linkage, the generated code was bad etc. etc. At some stage we asked the Mozilla developers to test the new compiler to ensure everything was ok. Only now after weeks and months during which Andrew debugged and fixed and again fixed (as GCC was also moving) you can see GCC 3.0.2 in the shape we want it to be. I do hope OS/2 developers will have as much fun and make as many interesting discoveries as we have during work on GCC. Good Luck!
Get GCC 3.0.2 from Netlabs Server
All the GCC packages have a common directory structure that will help you keep the old EMX GCC alongside the new one. All the binaries are installed under emx/bin.new/ and do not overwrite anything in emx/bin/. The following compilers are available:
Unpack the compiler packages in the emx directory. For C/C++ development you must install both the C and C++ compilers. Please ensure that you have the 'emx/dll/' directory in your LIBPATH.
Move the file /emx/bin.new/newgcc.cmd into /emx/bin; change it to suit all your needs, all instructions are inside newgcc.cmd. To switch to the new gcc just execute newgcc.cmd. To switch back, exit from your shell. To completely replace gcc 2.8.x with the new version you should merge all the files from /emx/bin.new with the files in /emx/bin, overwriting any existing files with the same name in /emx/bin. Then remove the bin.new subdirectory.
Now we will do the EMX update and libs creation. Switch to the new GCC with newgcc.cmd (please make sure to adjust it with your own preferences) and check that the basic compilers work. Type gcc -v and g++ -v to see the compilers' versions. You should see 3.0.2 as the GCC version in both cases. By launching the compilers we also check everything is O.K., so if you had any troubles, errors or even core-dumps during launch, it is time to return and re-read the installation instructions.
Since EMX 0.9 was written, IBM has added to OS/2 several useful API's, one of which is the Unicode API. To allow usage of the Unicode API's in EMX programs (programs linked with libstdc++ will need them) we had to write the missing API definitions (.h and import definitions.) Now to add the missing functions to os2.a and os2.lib (the libraries defining all OS/2 system-specific functions) you must go to /emx/lib and type 'make'. This will rebuild os2.a so that it contains all the functions defined in unicode.imp, then it will re-convert all outdated OMF libraries (.lib) from their a.out counterparts (.a).
Also you must go to the /emx/lib/gcc-lib/i386-pc-os2_emx/3.0.2/ directory and type 'make' there as well for the same reason (to convert supplied a.out libraries into OMF format in the case you will use the -Zomf switch).
#include <iostream.h> using namespace std; int main() { cout<<"Hello World"<<endl; return 0; }
Now let's compile this by launching g++ test.cpp. No problems, but we get an a.out object file in this example. Let's use OMF.
g++ test.cpp -Zomf
You will get a lot of linking errors, for example:
X:\......\gcc-lib\i386-pc-os2_emx\3.0.2\st\stdcxx.lib(functexcept.obj):
error L2025: _ZTSSt9exception : symbol defined more than once
Bad indeed. This happens because linking with the libstdc++ library requires special handling when using OMF format. Erase weaksyms.omf from the current directory. Go to emx\lib\gcc-lib\i386-pc-os2_emx\3.0.2\ and copy weak symbols list file from there (weaksyms.omf) to your directory. Issue the compilation command once again. It should work as expected this time.
Here is how it works. As many people know, gcc never generates OMF files directly. Instead, it generates a.out files which then are run through emxomf in order to convert them from a.out to OMF. Finally, in the link stage, LINK386 or ILINK is run. Now, the weak symbol attribute has an effect at the link stage. Having a symbol marked as weak means that if there is another symbol with the same name and also marked as weak, a duplicate symbol error is not generated. Instead, the linker randomly chooses one of them (usually the first one encountered.) (In fact, the "real" weak attribute also means that if somebody refers to a weak external symbol, and that symbol is not found anywhere, it is resolved to NULL. But this syntax of weak symbols is supported only in the a.out format, not OMF.) The only way to do it for OMF is to keep a list of weak symbols of your project in a external file, which is not lost between numerous runs of emxomf. Suppose emxomf converts an a.out file to OMF and finds a weak symbol. Now it looks into that table: have we encountered this weak symbol already, or is this the first time? If we encountered it already, the symbol is converted to a non-exported local symbol (so that LINK386 won't barf about duplicate symbols.) If not, the symbol is marked as a normal symbol, and it is added to that external table, along with the object file name where it was encountered for the first time. The file name is needed so that when the same file is re-compiled (for example after you modify the source) emxomf should detect that this symbol should be declared as external and not as a local non-exported symbol, even though it is mentioned in the weak symbol table. This file is called weaksyms.omf. If you see such a file in your project's directory, it means your project uses weak symbols. Don't delete it, after some time it will cease to grow and it will contain a complete list of weak symbols of your project. If your project uses multiple directories, and your makefile changes the current directory then emxomf can miss the weaksyms.omf file and start the list from scratch. In this case you can get duplicate symbols error. The solution is to maintain one unique weak symbol list by setting the GCC_WEAKSYMS environment variable which points to some file where all your weak symbols will be collected:
SET GCC_WEAKSYMS=d:/myproject/weaksyms.omf
The libstdc++ contains a lot of weak symbols, and if your application
uses libstdc++, emxomf should know in advance about them. For this reason, before
starting the compilation of your project, you must copy the weaksyms.omf
file supplied with gcc (the file name is lib/gcc-lib/i386-pc-os2_emx/x.x.x/weaksyms.omf)
to your project's directory.
Q)Compiling speed is slow.
Q)Fork does not work anymore in GCC 3.0.2. Why?
Q)I can't allocate more than 32 Mb of memory. What to do?
Q)What OS/2 specific macro symbols does GCC 3.0.2 define?
Q)GDB does not find my function names!
Q)-mcpu=pentiumpro does not accelerate my app. OS/2 bug?
Q)Executable size is sooooo huge. How to reduce it?
Q)Can I mix object files from old and new GCC?
Platon Fomichev (mailto:pfomiche@w-trade.spb.ru) aka Stauff is a long time OS/2 user and developer,
and a porter of a wide range of UNIX software to OS/2 VIO and XFree86/2.
This article is courtesy of www.os2ezine.com. You can view
it online at http://www.os2ezine.com/20011216/page_4.html.
Frequently Asked Questions
A)Use SET GCCLOAD=x, where x is a number of minutes to keep GCC pre-loaded
in memory. Also use -pipe switch while compiling, or SET GCCOPT=-pipe.
A)Not exactly. It does not work when using the -Zcrtdll switch.
This happens because EMX's fork() black magic gets confused by the new
gcc302*.dll. If you add the "-lgcc" switch after -Zcrtdll, your application
won't be linked against gcc302*.dll, and fork() will work.
A)That's an EMX feature. Usually EMX applications are limited to
using a 32MB heap because the fork() logic expects the heap to be allocated in one
big segment. If you don't use fork(), you can use the _uflags() function
to tell the EMX runtime that you don't want your heap to be contiguous.
A)You can see these by running gcc -v on a .c or .cpp file. The
OS/2-specific symbol is __OS2__, also __EMX__ is defined; other symbols
like __i386__ are defined depending on CPU type.
A)g++ 3.0 and later has a new name mangler. This means that gdb
and other old apps cannot demangle the mangled C++ names correctly.
There is nothing you can do about it other than trying to port a newer
gdb (:-).
A)The speed increase is marginal and can give significant
increases only for computational algorithms. Normal programs are
limited by lots of other factors, thus pure execution speed is not
a requirement for most programs. In fact, I'd recommend everyone
compiles using the -O2 -march=i386 switches, because these two switches
favour small code size over speed, and you won't observe any differences
anyway.
A)You can try to use the -Zcrtdll switch. Also if your project is
written in C++ and you don't use exceptions, you should use the -fno-exceptions
switch: this will reduce your executable size a lot. Also -fno-rtti could
give a small gain. Finally, try -Os switch which tells gcc to optimize
by favouring smaller code over faster but larger code.
A)Only for plain C. As I mentioned above, the C++ mangler has
changed in gcc 3.x, thus you will get linking errors when linking with old
C++ object files and libraries.
Technical hints and tips
Andrew Zabolotny (mailto:zap@cobra.ru) is a long time OS/2 user and developer, the maintainer
of the OS/2 port of Pentium GCC (http://www.goof.com/pcg/os2/) and now the GCC compiler suite.