Porting Enterprise Apps from UNIX to Linux
By Martyn Honeyford2005-04-17
Get the Build System Working
Products that support multiple platforms typically require code that is specific to the particular operating system on which the product is running. This common code is typically held in a separate code component within the source directory structure.
For example the OS-specific code layout could look something like this:
src/operating_system_specific_code_component/aix (for AIX).
src/operating_system_specific_code_component/solaris (for Solaris).
src/operating_system_specific_code_component/UNIX (for other flavors of Unix).
The following figure presents a more "graphic" view of the OS-specific code layout.
Figure 1. Code organization layout
1.
Make a Linux build system
For the first step, you'll create a directory for Linux-specific code and populate it with files from one of the platforms. When you introduce a new directory for Linux, the layout might look like this:
src/operating_system_specific_code_component/linux (for Linux).
This in turn would give us a new code layout that would look like the following.
Figure 2. New code organization layout
2.
Normally, much of the application code is common across all Unix flavors and will work on Linux, too. For Linux-specific code, experience shows that picking Solaris-specific files as an initial drop minimizes the effort to port the platform-specific code to Linux.
Next, change the makefiles and introduce Linux-specific items:
• Definitions for the compilers to use
• Library path
• Thread library path
• Compiler flag
• Include file path
• Preprocessor flags
• Whatever else you need
Many changes in the source files are related to changing the include file paths. For example, for the variable errno, <sys/errno.h> needs to be specifically included.
Care must be taken whereever possible that you don't directly include architecture-specific include files, but do include the recommended files. For example, as mentioned in <bits/dlfcn.h>:
#ifndef _DLFCN_HYou should use the directive -Dlinux or word "linux" carefully. The preprocessor on Linux translates the word "linux" to the numeral 1. For example, if there is a path in the file like /home/linux and the file is preprocessed using cpp, the path in the output file will look like /home/1. To avoid this substitution, the preprocessor directive could look like this: /lib/cpp -traditional -Ulinux <file_name>.
# error "Never use <bits/dlfcn.h> directly; include <dlfcn.h> instead."
#endif
Common compilation commands
The compiler that programmers normally use is gcc. A typical compile line might look like this: gcc -fPIC -D_GNU_SOURCE -ansi -O2 -c <file_name.c> -I<include_path>. -fPIC helps generate position-independent code and is equivalent to -KPIC on Solaris. -ansi is equivalent to -Xa on Solaris.
For shared objects, a typical link time directive could be gcc -fPIC -shared -o <shared_object> <object_file> -L<library_search_path> -l<library_name>. -shared is equivalent to -G on Solaris.
For relocatable objects with entry points, a typical directive might be gcc -fPIC -shared -o <name> <object_file> -e entry_point -L<library_search_path> -l<library_name>.
Before moving on to choosing the best operating environment, I'll examine the issues surrounding compiling the code on other architectures.
Compiling on other architectures
Another important consideration is that the programmer should be able to get the code to compile on other architectures as easily as possible. The build system should have separate definition files for each architecture involved. For example, the compiler directive for an x86 architecture could have a flag -DCMP_x86 with a directive like -DCMP_PSERIES for some code specific to Linux on pSeries servers. The compile lines in the specific build-definition files will look like this for compiling on an x86-architecture system:
gcc -fPIC -D_GNU_SOURCE -ansi -O2 -c <file_name.c> -I<include_path> -DCMP_x86
and this for compiling on the pSeries architecture:
gcc -fPIC -D_GNU_SOURCE -ansi -O2 -c <file_name.c> -I<include_path> -DCMP_PSERIES.
Both -CMP_x86 and -CMP_PSERIES are user-defined flags and should be used wherever the program is going to have architecture-specific code within Linux-specific code. My experience has been that most of the application code for Linux is architecture-independent, and the architecture-specific code comes into play in areas in which assembly code needs to be written. For example, architecture-specific code will be used if you're going to exploit locks using an implementation of compare and swap instructions.
Code should be arranged so that there are no architecture-specific subdirectories within the Linux-specific directory in the code layout. Why? Because Linux already does a great job of segregating the architecture specifics and an application programmer typically should not have to care about which architectures the application is going to be compiled on. The aim should be to have the program written for a particular architecture to compile on another architecture with minimal effort and minimum changes to the code, the code layout, and the makefiles. By avoiding architecture-specific subdirectories within the linux directory, makefiles are greatly simplified.
Source files in the linux subdirectory could have a code layout with preprocessor directives as follows:
#ifdef CMP_x86
<x86 specific code>
#elif CMP_PSERIES
<p-series specific code>
#else
#error No code for this architecture in __FILE__
#endif
Tutorial Pages:
» A Practical Checklist, Tips, and Insight Drawn from Experience
» Get the Build System Working
» Decide on a Viable Operating Environment
» Architecture-Specific Changes
» Choose an IPC Mechanism
» Select the Threading Model
» File System, Usage Parameters, Stacks
» Memory Maps and Using Shared Memory Segments
» Signaling
» Configure Kernel Karameters
» Parser Tools like lex/yacc
» Globalization Issues
» Security Concerns
» Locating Installed Packages and Variable Data
» Testing
» There's a Port in Every Storm
» Resources
First published by IBM DeveloperWorks
| Related Tutorials: » How to Install PHP 5 on Linux » How to Install Apache 2 on Linux » How to Install MySQL 5.0 on Linux » SMB Caching » Mound --Bind » Tar Wild Card Interpretation |
