= Common tasks and useful tips for porting Unix software to OS/2 = [[PageOutline]] This page explains some common code changes often necessary to make Unix software work properly on OS/2. These changes are mainly related to various components shared among Unix programs. These changes are tracked here since we don't normally push upstream and hence we should apply them in each new project that we port and that uses these components. == Common tasks == === Fix POTFILES generation === The fix is applied to `po.m4` that creates rules for `POTFILES` generation. Unfortunately, the upstream version doesn't take DOS drive letters into account and hence creates incorrect relative paths in the generated `POTFILES` file (like `../D:/Coding/myproject/trunk/...`). Here is a typical fix: r1009. When applied, `configure` and friends need to be regenerated in the source tree and then `configure` needs to be re-run to generate proper `Makefile`s. === Fix HAVE_ICONV detection === The fix is applied to `iconv.m4` that detects if the `HAVE_ICONV` config.h macro should be set or not. Here is a typical fix: r1023 (originally this: r934). When applied, `configure` and friends need to be regenerated in the source tree and then `configure` needs to be re-run to generate a proper `config.h`. === Fix EOLs in git-version-gen === Some projects use the `build-aux/git-version-gen` script to define the project version in `configure.ac`. The "stock" version of this script doesn't understand CRLF as line terminators which leads to a corrupt `configure`. The fix is rather simple and can be seen here: r968. === Fix OS/2 DLL name in libtool === When `libtool` is used to generate project DLLs, such a DLL often gets a version number in its name (e.g. `libpixman-1.so.0`, where `pixman-1` is the base DLL name and `0` is the major version number). However, on OS/2 the version information cannot follow the extension and hence it must be put into the name part. But the name part is limited to 8 chars so `libtool` has to cut the base DLL name by default to make the appended major version number fit the limit. In case of the `pixman` this would give us `pixman-0.dll` which looks misleading (the correct name is `pixman10.dll` in this case). A proper solution here is to force `libtool` use a special, short version of the base name for the DLL file (and only for it — all other files, such as the import library name, should carry the original name so that the linker can find it). This is done using the `-shortname` libtool option. Where to add it varies from project to project but the typical place is the _la_LDFLAGS variable in `Makefile.am` for the library. See r1232 for a real-life example. === Have libtool add a buildlevel string to the DLL === With the latest `libtool` it is possible to have a buildlevel string built into a dll. To do so you need to teach the `Makefile` how to handle it. Most likely it is the best practice to change `Makefile.am` and then do a `sh -c "autoreconf -fvi"`. How to adjust a `Makefile.am` can be seen here: r1823 === Increase default stack file for executables === The default stack size in the EMX GCC tool chain is 1 Mbyte. This is not always enough. A clear indication of your program running out of stack is a crash in GCC1.DLL (in a stack checking function `___chkstk_ms` usually located at 0001:00000F4). The stack size can be increased using the `-Zstack` linker option which specifies the stack size in Kbytes. For example, passing `-Zstack 0x2000` to the linker (e.g. via LDFLAGS) will increase the stack size to 8 Mbytes. Read the next section if you want to change the stack size using LDFLAGS in an Autoconf-based project. === Add OS/2 specific build details to Autoconf-based projects === **Method 1**. If `configure.ac` already uses AC_CANONICAL_TARGET or AC_CANONICAL_HOST macros, then you can add the following excerpt to it to do OS/2-specific job (`$target_os` becomes `$host_os` if AC_CANONICAL_HOST is used instead of AC_CANONICAL_TARGET): {{{ case "$host_os" in os2*) # Increase stack size to 8MB export LDFLAGS="$LDFLAGS -Zstack 0x2000" esac }}} **Method 2**. If the above AC_CANONICAL macros are not used, then it will be simpler to use `uname` to do the OS/2-specific job: {{{ case `uname -s 2>/dev/null` in OS/2) # Increase stack size to 8MB export LDFLAGS="$LDFLAGS -Zstack 0x2000" esac }}} Note though that if you need to add such a block more than once, it makes sense to add AC_CANONICAL_TARGET right after AC_INIT to `configure.ac` and go with //Method 1// described above. == Debugging techniques == === Using a logging LIBC DLL === Modern OS/2 programs are built with GCC which uses [http://trac.netlabs.org/libc/ kLIBC] as its POSIX-like C runtime library. This library provides a powerful logging facility where it logs a lot of internal actions as well as entry and exit from each public function it provides. Sometimes, especially when debugging application crashes that can't be caught by other means, it is very handy to get this logging for your application. There are several versions of the LIBC DLL in each release. The normal version, `LIBCxyz.dll`, is an optimized build that doesn't provide any logging or debug info. The logging version is called `LIBCxyz.logchk`. In the RPM environment this DLL lives in the `libc-devel` package. In order to use it in place of the normal version, do the following: 1. Make sure you have `LIBCxyz.logchk` installed and that `xyz` matches the version of LIBC you normally use. 2. Put this fragment to your CONFIG.SYS: {{{ REM // Disable all LIBC logging in the logchk dll by default SET LIBC_LOGGING=-ALL }}} 3. Unlock `LIBCxyz.dll` and rename it to `LIBCxyz.dll.normal`. 4. Rename `LIBCxyz.logchk` to `LIBCxyz.dll`. 5. Reboot. Note that this will cause **all** applications linked against `LIBCxyz.dll` to create a log file named `libc-ABCD.log` in the application's current directory where ABCD is a hex number of a running process. Given that we disabled all logging by `SET LIBC_LOGGING=-ALL` in CONFIG.SYS, these files will only contain a small log header and won't grow at runtime — this is done to avoid excessive logging for unneeded applications and unnecessary slowdown caused by this logging. In order to get anything useful in the log file, you need to enable logging for your application. This is done by overriding the `LIBC_LOGGING` environment variable before starting it. To enable full logging, just do {{{ SET LIBC_LOGGING=+ALL }}} before starting the application. Not that this will produce a huge amount of logs especially if your application starts other processes which will also have all logging enabled. You may fine-tune what to log using log groups as defined in http://svn.netlabs.org/repos/libc/branches/libc-0.6/src/emx/src/lib/sys/logstrict.c (look for `aDefGrps`). For example, in order to enable all but I/O logging, you do {{{ SET LIBC_LOGGING=+ALL-IO }}} If you want to go back to the normal LIBC version, just unlock `LIBCxyz.dll`, rename it back to `LIBCxyz.logchk`, rename `LIBCxyz.dll.normal` to `LIBCxyz.dll` and reboot. Note that while technically you could copy `LIBCxyz.logchk` to a separate directory, rename it to `LIBCxyz.dll` there and then set BEGINLIBPATH= and LIBPATHSTRICT=T in the environment to have this version of LIBC used for your process without rebooting, this will not work well. Doing so will lead to having two **different** LIBC copies in memory which don't cooperate because of the LIBC design that assumes there is only one active LIBC DLL at a time. In particular, having more than one DLL in memory is known to make forked children crash with some weird errors (even if one manages to separate shared structures of different LIBC versions by using unique mutex and shared memory names).