Because most of the caveats listed below are strongly linked to the specific implementation of a given application, I'll break things down along those lines, going from the easiest to port to the hardest to port.
Platform-independent applications are authored in such a way that they can run on more than one platform with little or no modification. Most programs written in Perl, PHP, Ruby, Python or Java, for instance, can be run quite transparently on any platform, because the interpreter or runtime environment will handle the vast majority of platform-dependent features.
Platform-specific issues usually come down to things like where files are written to or read from, where profile/locale information is stored or obtained from and so on. These aspects vary from program to program depending on what the application is doing, but most applications that use standard I/O mechanisms (for instance, a CGI gateway in a Web server) would need little or no reconfiguring to work correctly. There's a strong incentive to write platform-independent
Platform-specific implementations of applications
Platform-specific implementations exist in multiple editions for different platforms. One good example of this would be the database application MySQL, which is available in both Linux and Windows versions. If you had a MySQL database running on a Windows server and wanted to move it to a corresponding Linux server, the process would involve little more than exporting the database on one machine and importing it on another. Because the program recognizes the same data format on both platforms, the process of moving the data is trivial.
What may not be trivial is dealing with any differences in implementation of the application on the other platform. This might be something like a bug that shows up in Windows but not in Linux (don't forget to read the release notes!) or a feature that is implemented on one platform but not the other. These need to be understood and put to rest before the application goes live.
Another issue that comes up, although it may be manageable by the application itself, is differences in the platforms that affect how the programs act. The biggest issue of this kind that comes to mind is case-sensitivity. Windows is not inherently case-sensitive, down to the file system, but Linux is case-sensitive throughout its infrastructure. If, for instance, a database contained a stored procedure that assumed case-sensitivity, that procedure might need to be changed to have the case-sensitive operation made explicit.
Source-ported applications are those that need to be recompiled to binaries on the target platform from their source code. This is the trickiest and most difficult way to go from platform to platform, because you're dealing directly with all of the differences inherent in each platform, from case sensitivity to where files need to go. One subset of this is applications that run as managed code, such as .NET, which inherits numerous behaviors of the host operating system, such as case-sensitivity. Unless your application specifically addresses this problem it may not work as intended. Windows languages contain many functions with options to address case-sensitivity (such as the string-matching features in .NET).
Thankfully, you'll find a breadth of tools available for porting applications between Linux and Windows that are broad and robustly supported. Cygwin (available under the GPL license) is one commonly used toolset for bringing Linux applications to Windows. For those who don't want to operate under the GPL license, there's MinGW, which has been explicitly released into the public domain (although it does use some of Cygwin's tools where needed). The MKS Tookit is a commercial package of tools that allow scripts, source code (including API support) and working environments to be ported from Linux to Windows; it supports both 32- and 64-bit Windows, and a free evaluation version is available for download. (I should also make mention of Services for Unix, which is made by Microsoft and provides a number of Cygwin-like tools but does not work in Windows 9x or Windows XP Home Edition and is closed-source.)
All of the above, however, assume that you have the source code for the applications in question. If you don't, the only way to get a binary application to move from one platform to another is to use some variety of emulation. For running Windows binaries in Linux, Wine is a remarkably successful project that has reverse-engineered many of the native Windows APIs to allow binary Windows applications to run in Linux. (The Wine libraries also allow a Windows application to be ported to and recompiled in Linux.)
Another porting method is Alky, a tool for converting existing binaries without requiring source access. For Linux-under-Windows, assuming source code is not available or cannot be ported easily, one possible solution is using machine emulation, or running the app in an emulated Linux installation. The coLinux project uses an approach like this.
The breadth of programming and support tools in both Windows and Linux makes it possible to move applications in either direction, although the amount of work involved will vary enormously. The easiest applications to move will be those not dependent on a given platform, of course. If you're faced with the task of moving from one platform to another, focus on the hardest-to-move items first (such as binary applications that need recompiling), because those will typically take up the bulk of your time anyway. And save the easiest for last.
This was first published in July 2006