Although there is a native Win32 port of make , this is a small part of the Windows portability problem, because the shell this native port uses is cmd.exe (or command.exe ). This, along with the absence of most of the Unix tools, makes cross-platform portability a daunting task. Fortunately, the Cygwin project (http://www.cygwin.com) has built a Linux-compatible library for Windows to which many programs [1] have been ported. For Windows developers who want Linux compatibility or access to GNU tools, I don't believe there is a better tool to be found. [1] My Cygwin /bin directory currently contains 1343 executables. I have used Cygwin for over 10 years on a variety of projects from a combined C++/Lisp CAD application to a pure Java workflow management system. The Cygwin tool set includes compilers and interpreters for many programming languages. However, Cygwin can be used profitably even when the applications themselves are implemented using non-Cygwin compilers and interpreters. The Cygwin tool set can be used solely as an aid to coordinating the development and build process. In other words, it is not necessary to write a "Cygwin" application or use Cygwin language tools to reap the benefits of the Cygwin environment. Nevertheless, Linux is not Windows (thank goodness!) and there are issues involved when applying Cygwin tools to native Windows applications. Almost all of these issues revolve around the line endings used in files and the form of paths passed between Cygwin and Windows. 7.2.1 Line Termination Windows filesystems use a two-character sequence carriage return followed by line feed (or CRLF) to terminate each line of a text file. POSIX systems use a single character, a line feed (LF or newline ). Occasionally this difference can cause the unwary some confusion as programs report syntax errors or seek to the wrong location in a data file. However, the Cygwin library does a very good job of working through these issues. When Cygwin is installed (or alternatively when the mount command is used), you can choose whether Cygwin should translate files with CRLF endings. If a DOS file format is selected, Cygwin will translate CRLF to LF when reading and the reverse when writing text files so that Unix-based programs can properly handle DOS text files. If you plan to use native language tools such as Visual C++ or Sun's Java SDK, choose the DOS file format. If you are going to use Cygwin compilers, choose Unix. (Your choice can be changed at any time.) In addition, Cygwin comes with tools to translate files explicitly. The utilities dos2unix and unix2dos transform the line endings of a file, if necessary. 7.2.2 Filesystem Cygwin provides a POSIX view of the Windows filesystem. The root directory of a POSIX filesystem is / , which maps to the directory in which Cygwin is installed. Windows drives are accessible through the pseudo-directory /cygdrive/ letter . So, if Cygwin is installed in C:\usr\cygwin (my preferred location), the directory mappings shown in Table 7-1 would hold. Table 7-1. Default Cygwin directory mapping Native Windows path | Cygwin path | Alternate Cygwin path | c:\usr\cygwin | / | /cygdrive/c/usr/cygwin | c:\Program Files | /cygdrive/c/Program Files | | c:\usr\cygwin\bin | /bin | /cygdrive/c/usr/cygwin/bin | This can be a little confusing at first, but doesn't pose any problems to tools. Cygwin also includes a mount command that allows users to access files and directories more conveniently. One option to mount , ”change-cygdrive-prefix , allows you to change the prefix. I find that changing the prefix to simply / is particularly useful because drive letters can be accessed more naturally: $ mount --change-cygdrive-prefix / $ ls /c AUTOEXEC.BAT Home Program Files hp BOOT.INI I386 RECYCLER ntldr CD IO.SYS System Volume Information pagefile.sys CONFIG.SYS MSDOS.SYS Temp tmp C_DILLA NTDETECT.COM WINDOWS usr Documents and Settings PERSIST WUTemp work Once this change is made, our previous directory mapping would change to those shown in Table 7-2. Table 7-2. Modified Cygwin directory mapping Native Windows path | Cygwin path | Alternate Cygwin path | c:\usr\cygwin | / | /c/usr/cygwin | c:\Program Files | /c/Program Files | | c:\usr\cygwin\bin | /bin | /c/usr/cygwin/bin | If you need to pass a filename to a Windows program, such as the Visual C++ compiler, you can usually just pass the relative path to the file using POSIX-style forward slashes. The Win32 API does not distinguish between forward and backward slashes. Unfortunately, some utilities that perform their own command-line argument parsing treat all forward slashes as command options. One such utility is the DOS print command; another is the net command. If absolute paths are used, the drive letter syntax is always a problem. Although Windows programs are usually happy with forward slashes, they are completely unable to fathom the /c syntax. The drive letter must always be tranformed back into c: . To accomplish this and the forward/backslash conversion, Cygwin provides the cygpath utility to translate between POSIX paths and Windows paths. $ cygpath --windows /c/work/src/lib/foo.c c:\work\src\lib\foo.c $ cygpath --mixed /c/work/src/lib/foo.c c:/work/src/lib/foo.c $ cygpath --mixed --path "/c/work/src:/c/work/include" c:/work/src;c:/work/include The ”windows option translates the POSIX path given on the command line into a Windows path (or vice versa with the proper argument). I prefer to use the ”mixed option that produces a Windows path, but with forward slashes instead of backslashes (when the Windows utility accepts it). This plays much better with the Cygwin shell because the backslash is the escape character. The cygpath utility has many options, some of which provide portable access to important Windows paths: $ cygpath --desktop /c/Documents and Settings/Owner/Desktop $ cygpath --homeroot /c/Documents and Settings $ cygpath --smprograms /c/Documents and Settings/Owner/Start Menu/Programs $ cygpath --sysdir /c/WINDOWS/SYSTEM32 $ cygpath --windir /c/WINDOWS If you're using cygpath in a mixed Windows/Unix environment, you'll want to wrap these calls in a portable function: ifdef COMSPEC cygpath-mixed = $(shell cygpath -m "") cygpath-unix = $(shell cygpath -u "") drive-letter-to-slash = /$(subst :,,) else cygpath-mixed = cygpath-unix = drive-letter-to-slash = endif If all you need to do is map the c: drive letter syntax to the POSIX form, the drive-letter-to-slash function is faster than running the cygpath program. Finally, Cygwin cannot hide all the quirks of Windows. Filenames that are invalid in Windows are also invalid in Cygwin. Thus, names such as aux.h , com1 , and prn cannot be used in a POSIX path, even with an extension. 7.2.3 Program Conflicts Several Windows programs have the same names as Unix programs. Of course, the Windows programs do not accept the same command-line arguments or behave in compatible ways with the Unix programs. If you accidentally invoke the Windows versions, the usual result is serious confusion. The most troublesome ones seem to be find , sort , ftp , and telnet . For maximum portability, you should be sure to provide full paths to these programs when porting between Unix, Windows, and Cygwin. If your commitment to Cygwin is strong and you do not need to build using native Windows support tools, you can safely place the Cygwin /bin directory at the front of your Windows path. This will guarantee access to Cygwin tools over Windows versions. If your makefile is working with Java tools, be aware that Cygwin includes the GNU jar program that is incompatible with the standard Sun jar file format. Therefore, the Java jdk bin directory should be placed before the Cygwin /bin directory in your Path variable to avoid using Cygwin's jar program. |