Windows-Friendly Cygwin Paths

On July 9, 2010, in Uncategorized, by derekgreer

Not too long ago, I ventured into using Rake for my .Net project builds.  Given that my shell preference on Windows is Cygwin’s bash port (via the excellent mintty terminal), I tend to prefer installing the Cygwin ruby package rather than using the RubyInstaller for Windows.

One issue I ran into, however, was that the absolute paths generated under rake resolve to /cygdrive/c/ by default.  This isn’t an issue when calling applications compiled for Cygwin, but they pose a problem if you need to pass an absolute path as a parameter to commands like MSBuild.  One way to resolve this problem is to create an NTFS mount point which mirrors a path that Windows executables can resolve.  Here’s how:

Open up the file /etc/fstab which configures the mount table under Cygwin.  Add a line similar to the following:

C:/projects /projects ntfs binary,posix=0,user 0 0

This mounts the C:/projects folder (where I do all of my project development) as /projects.  Note that the mount point must be named the same as the actual physical NTFS path.  After restarting the shell, the new mount point will be available.  This can be verified by issuing the mount command:

> mount
C:/cygwin/bin on /usr/bin type ntfs (binary,auto)
C:/cygwin/lib on /usr/lib type ntfs (binary,auto)
C:/projects on /projects type ntfs (binary,posix=0,user)
C:/cygwin on / type ntfs (binary,auto)
C: on /cygdrive/c type ntfs (binary,posix=0,user,noumount,auto)
D: on /cygdrive/d type iso9660 (binary,posix=0,user,noumount,auto)
F: on /cygdrive/f type iso9660 (binary,posix=0,user,noumount,auto)
G: on /cygdrive/g type ntfs (binary,posix=0,user,noumount,auto)
H: on /cygdrive/h type ntfs (binary,posix=0,user,noumount,auto)
I: on /cygdrive/i type vfat (binary,posix=0,user,noumount,auto)

Since Windows accepts the forward slash as a directory delimiter and considers drive letters to be optional, expanding a relative path under the NTFS mount point will render a path that can be correctly interpreted by Windows executables.

Tagged with:  

Getting Started With Cygwin

On April 8, 2010, in Uncategorized, by derekgreer

With the increasing popularity of the Git version control system, many .Net developers are being introduced for the first time to Unix-like tools for Windows by way of two popular Git client platforms: msysgit and Cygwin. The more substantial of the two, Cygwin is a Linux-like environment for Windows and provides a wide range of useful utilities. The following is a guide for helping newcomers quickly get up and going with the Cygwin environment.

Installation

The first step is to obtain the installer from the Cygwin home page. Upon running the installer, you’ll be presented with a wizard which guides you through the installation process:

 

Upon arriving at the “Select Packages” dialog, you’ll be presented with all the packages available from the selected mirror site(s):

 

The installer allows you to install selected packages, or install by category:

 

At the package level, the rotating arrow icon allows you to cycle through the choices of installing one of the package versions available, skipping the package, or in the event the package is already installed, keeping, reinstalling, uninstalling, or obtaining the source code for the package. At the category level, the rotating arrow icon allows you to cycle through the choices of Default, Install, Reinstall, or Uninstall.

It’s best to only select the packages you really think you’ll want to use or immediately explore. There’s quite a bit of applications available and choosing everything would result in quite a large installation time. The installer can always be run at a later time to pickup up additional packages you want to explore.

By default, Cygwin selects the Base category packages as well as a few other odds & ends. Among the packages skipped by default, you may consider also installing the following:

Category Package Description
Admin cygrunsrv Utility for easily working with Windows services (adding/removing/starting/stopping).  This is beneficial if you’d like to run git daemon or sshd as a windows service for anonymous or authenticated access.
Archive zip, unzip PKZip compatible zip capabilities.
Editors vim An enhanced VI editor.
Net openssh Secure shell client and server programs.
Utils ncurses Terminal utilities (has a clear command for clearing the screen).
Web curl Multi-protocol file transfer tool.  This tool is useful for scripting HTTP interaction.

 

In addition, I personally always install the X11 category packages. While this adds a bit to the download size, it gives you the ability to run your preferred shell (e.g. bash) in an xterm as opposed to the standard terminal window. I’ll cover a bit of X11 installation and customization later in this guide.

When you’re done selecting your packages, click “Next” and the install will begin:

 

 

Once complete, click the Finish button and you’re done with the install.

Bash Shell Customization

If you selected the “Add icon to Start Menu” option during the install then you should have a new shortcut entitled “Cygwin Bash Shell” which will start the bash shell as an interactive login shell (i.e. bash –login -i). If not, you can browse to cygwin.bat file located within the chosen installation folder.

When bash runs for the first time, it checks to see if the home directory (denoted in the /etc/passwd file) exists for your account. If not, it creates the directory and copies over some default config files for your shell:

 

The .bash_profile is used for login shells while the .bashrc file is used for interactive, non-login shells. The default .bash_profile configuration sources the .bashrc file if it exists, so both are sourced for interactive login shells. This effectively allows the .bashrc to serve as the core configuration for both login and non-login shells. The .inputrc file is used to set custom key mappings. Of the three, the .bashrc file will generally be the one you’ll deal with most often.

Go ahead and open up the .bashrc file. (Note: Microsoft Notepad does not display Unix-style line endings correctly. If using a Windows editor, use Wordpad.) After opening the file, you’ll notice that most of the configuration is commented out. The only active configuration are commands to unset the Windows TMP and TEMP variables. You can keep this if you like, but I prefer to keep things a bit more tidy and only have the configuration I actually use. If you want to view the default contents of this file, it can always be viewed from its original source in /etc/skel. The following is a more minimal configuration you might wish to start with:

unset TMP
unset TEMP

PATH=.:~/bin:${PATH}
PATH=${PATH}:c:/Windows/Microsoft.Net/Framework/v3.5/
PATH=${PATH}:c:/Program  Files/Reflector/
PATH=${PATH}:c:/Program Files/Microsoft  SDKs/Windows/v6.1/Bin/

. ~/.alias
. ~/.functions

In this configuration, several folders have been added to the PATH environment variable. The first places a ~/bin folder before the PATH. This ensures any custom scripts found in the users bin folder occur first in the path allowing commands to be overridden. The remaining three lines are example folders you might want to set if you are doing .Net development related tasks at the bash command line.

The remaining two lines assume the existence of two new files, .alias and .functions. I find storing aliases and functions separately to be a bit more tidy, as well as making it easier to share with others.

Now, let’s take a look at the .bash_profile configuration. By default, the only configuration that exists is the sourcing of the .bashrc file. Again, normally the .bashrc file is only sourced for non-login shells, so this ensures the .bashrc settings are picked up for login shells as well.

In this file, let’s replace the contents with the following:

#  source the system wide bashrc if it exists
if [ -e /etc/bash.bashrc ]  ; then
source /etc/bash.bashrc
fi

# source the users  bashrc if it exists
if [ -e "${HOME}/.bashrc" ] ; then
source  "${HOME}/.bashrc"
fi

PS1='[h]: ${PWD##*/} > '
set -o vi
export  DISPLAY=127.0.0.1:0.0

In addition to the existing configuration, we’ve added three additional settings. The first customizes how the prompt appears at the command line by setting the PS1 variable. This prompt is a bit plain, but you can spruce it up with a bit of color by replacing it with the following:

PS1=’\[\033]0;\w\007\033[32m\][\h]: \[\033[33m ${PWD##*/}\033[0m\] > ‘

Next, I’ve issued: “set -o vi”. This tells bash to use a vi-style command line editing interface which let’s you more efficiently issue and edit commands at the command line. You can delete this if you don’t ever plan on learning vi.

Next, I’ve set an X environment variable named “DISPLAY” to my localhost. This tells the xterm and other X applications where to attempt to display. You can delete this if you don’t plan on running an xterm, but leaving it certainly won’t hurt.

This should get you started. Your config files will likely evolve from here if you find yourself working at the command line often.

Aliases

The next step you may want to take is to define some command aliases. The bash alias command allows you to set up aliases for verbose or otherwise undesirable commands. As indicated, I store all of my aliases in a .alias file in my home directory to segregate them away from the rest of my .bashrc configuration. Here is a subset of my current list of aliases you might find useful:

alias programfiles="cd  /cygdrive/c/Program Files"
alias projects="cd /cygdrive/c/projects"
alias  spikes="cd /cygdrive/c/projects/spikes"
alias vs='cmd /c *.sln'
alias  vs9='/cygdrive/c/Program Files/Microsoft Visual Studio  9.0/Common7/IDE/devenv.exe *.sln&'
alias  wordpad='/cygdrive/c//Program Files/Windows  NT/Accessories/wordpad.exe'
alias config='cd  /cygdrive/c/Windows/Microsoft.NET/Framework/v2.0.50727/CONFIG'
alias  mydocs='cd /cygdrive/c/Users/${USER}/Documents'
alias myhome='cd  /cygdrive/c/Documents and Settings/${USER}/'
alias  fusion='fuslogvw.exe'

You’ll be surprised at how fast you’ll start zipping around the system once you’ve got some good navigation aliases in place.

Functions

I don’t tend to write a lot of bash functions, but I’m including this section here for completeness. Like the aliases, I like to segregate any functions I do write away from my main config file to make things a bit cleaner. As an example of what you can do, here is the contents of an example .functions file which allows you to tweet from the command line:

tweet()
{
read -s -p "Password:" password
curl -u  derekgreer:$password -d status="$1"  http://twitter.com/statuses/update.xml
}
Note: If you want to actually use this function then you’ll need to have downloaded the curl package and will need to modify the Twitter id.

Basic Commands

If you’re completely new to the Unix shells, the following are some common commands to get you started with navigating around, creating folders, deleting files, etc.:

Command Description
cd Change to home directory
cd [directory name] Change to a specified directory
cd – Change to the last directory
ls List the contents of the current folder (like dir)
ls -la List the contents of the current folder in long format including all hidden files
cat [filename] Print the context of a file (like DOS type)
![command prefix] Run the last command starting with the specified prefix.
mkdir [directory name] Make a new directory
mkdir -p [directory hierarchy] Make a all directories listed (e.g. mkdir -p a/b/c/d)
rm [filename] Remove a file
rm -rf [filename] Remove recursively with force
find [start folder] -name [regex] -print Starting at the start folder, find a file matching the given regular expression.
grep [regex] [filename] Display all lines matching the regular expression from the given file.

Scripts

Once you start getting comfortable with the available commands, you may wish to start writing your own scripts to help with various everyday tasks. While covering the basics of bash shell scripting is beyond the intended scope of this article, you can obtain an archive of some scripts I’ve written for my own purposes from here. Here’s a list of the contained scripts along with a brief description:

Script Description
clean Cleans up common temp/generated Visual Studio files.
detachfromcvs Removes CVS folders.
detachfromtfs Removes TFS bindings from source files.
diff Overrides the diff command to call WinMerge
git-diff-wrapper.sh Diff wrapper for use with Git.
replaceinfile Replaces string patterns in a file.
replaceinfiles Wrapper for calling replaceinfile for files matching a given pattern.
rgrep Recursive grep (Also greps from .Net assemblies)
unix2dosall Recursive unix2dos

X11 – Using an XTerm

The final portion of this guide is intended for those who would like to explore the X Windows system provided by Cygwin. One of the benefits of running an XServer on Windows is the ability to use an XTerm over the standard terminal provided by DOS. XTerm provides more flexibility over the fonts, colors used, and buffers used, provides dynamic resizing, and provides much more intuitive cut-n-paste capabilities (highlight = cut, middle mouse button = paste). It also displays buffered text which comes in handy when you want to use the tail -f command to follow a log file and queue up a bunch of spaces to visually separate new entries.

Assuming you’ve already installed the X11 packages, locate the Cygwin-X folder in your start menu and execute the “XWin Server” shortcut. By default, the XServer starts a plain white terminal:

 

Since this isn’t likely the style of terminal you’ll want to work with, you can prevent XServer from starting this default xterm by creating an empty .startxwinrc file in your home directory. You can do this by using the touch command:

touch ~/.startxwinrc

Next, you can modify the XTerm shortcut that was created in your start menu’s Cygwin-X folder to start a new xterm with no menu, a custom font, colors, a scrollbar, etc. using the following Target value:

C:Cygwinbinrun.exe -p /usr/X11R6/bin xterm -display 127.0.0.1:0.0 -ls -vb -fn 10×20 +tb -bg gray14 -fg ivory -sb -rightbar -sl 400

This command will launch an xterm similar to the following:

 

From here, you may consider adding the XWin Server shortcut to your startup.

That concludes my guide. Enjoy!

Tagged with: