I made the same move years ago. Here are the things I've run into:
Your average desktop Linux has a richer userland than that of OS X.
You'll probably miss different tools than I did, so no sense getting specific about recommendations for replacements.
Instead, just install Fink, MacPorts, or Homebrew first thing. These systems provide a package management system typical of Linux or the BSDs. Each has its own flavor and package set, so the right choice will be based on your tastes and needs.
You may find that no one package system will have every program you need. Some programs have yet to be ported to OS X, so they won't appear in any package system. Nevertheless, these systems do greatly extend what ships with OS X, and will ease your transition from Linux.
OS X command line compilers now build 64-bit executables by default.
In Leopard and earlier, the compilers built 32-bit executables by default instead. This can cause problems in several ways: maybe you have old 32-bit libraries you can't rebuild but have to link to, maybe you're still running your system in 32-bit mode, etc.
One way to force a 32-bit build is to override
gcc defaults in build systems with
gcc-4.0, that being the old 32-bits-by-default Leopard compiler. (
gcc is a symlink to the 64-bits-by-default
gcc-4.2 on Snow Leopard.) With autoconf based build systems, this works:
$ ./configure CC=gcc-4.0 CXX=g++-4.0
(You only need the
CXX bit if the program contains C++ components.)
Another way is to pass
-m32 to the compiler and linker:
$ ./configure CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32
It's more typing, but it lets you get 32-bit builds out of the newer GCC.
Dynamic linkage is vastly different.
If you're the sort to write your
ld commands by hand, it's time to break that habit. You should instead be linking programs and libraries through the compiler, or using an intermediary like
libtool. These take care of the niggly platform-specific link scheme differences, so you can save the brain power for learning programs you can't abstract away with portable mechanisms.
For instance, you'll need to update your muscle memory so you type
otool -L someprogram instead of
ldd someprogram to figure out what libraries
someprogram is linked to.
Another difference in dynamic linkage that will twist your brain at first is that on OS X, the install location for a library is recorded in the library itself, and the linker copies that into the executable at link time. This means that if you link to a library that got installed in
/usr/local/lib but you want to ship it to your users in the same directory as the executable, you need to say something like this as part of your install process:
$ cp /usr/local/lib/libfoo.dylib .
$ install_name_tool -id @loader_path/libfoo.dylib libfoo.dylib
$ make LDFLAGS=-L. relink
Now, much of the above is likely to vary for your build system, so just take it as an example, rather than a recipe. What this does is makes a private copy of a library we link to, changes its shared library identifier from an absolute path to a relative one meaning "in the same directory as the executable", then forces a rebuild of the executable against this modified copy of the library.
install_name_tool is the core command here. If instead you wanted to install the library in a
../lib directory relative to the executable, the
-id argument would need to be
Joe Di Pol wrote a good article on this, with a lot more detail.
Dynamic linkage + third party packages can cause headaches early on.
You are likely to run into dynamic linkage issues early on, as soon as you start trying to use libraries from third-party packages that don't install the libraries into standard locations. MacPorts does this, for example, installing libraries into
/opt/local/lib, rather than
/usr/local/lib. When you run into this, a good fix for the problem is to add lines like the following to your
# Tell the dynamic linker (dyld) where to find MacPorts package libs
# Add MacPorts header file install dirs to your gcc and g++ include paths
OS X handles the CPU compatibility issue differently than Linux.
On a 64-bit Linux where you have to also support 32-bit for whatever reason, you end up with two copies of things like libraries that need to be in both formats, with the 64-bit versions off in a
lib64 directory parallel to the traditional
OS X solves this problem differently, with the Universal binary concept, which lets you put multiple binaries into a single file. You can currently have executables that support up to 4 CPU types: 32- and 64-bit PowerPC, plus 32- and 64-bit Intel.
It's easy to build Universal binaries with Xcode, but a bit of a pain with command line tools. This gets you a Universal Intel-only build with Autoconf-based build systems:
$ ./configure --disable-dependency-tracking CFLAGS='-arch i386 -arch x86_64' \
LDFLAGS='-arch i386 -arch x86_64'
-arch ppc -arch ppc64 to the
LDFLAGS if you need PowerPC support.
If you don't disable dependency tracking, you end up building only for one platform, since the presence of newly-built
.o files for the first platform convinces
make(1) that it doesn't need to build for the second platform, too. Everything has to be built twice in the above example; four times for a fully-Universal binary, if you still need PowerPC support.
(More info in Apple Technical Note TN2137.)
The developer tools aren't installed on OS X by default.
Before Lion, the most reliable place to get the right dev tools for your system was on the OS discs. They're an optional install.
The nice thing about installing the dev tools from the OS discs is that you know the tools will work with the OS. Apple being Apple, you have to have a recent version of the OS to run the latest compilers, and they haven't always made downloads of old tools available, so the OS discs are often the easiest way to find the right tools for a given dev or test box.
With Lion, they're trying to do away with install media, so unless you buy the expensive USB key version, you'll have to download Xcode from the App Store.
I recommend you keep at least a few versions of any Xcode DMGs you download. When Lion's successor comes out a year or three hence, you might find yourself without a way to install a contemporaneous version of Xcode on a Lion test VM. Plan ahead in case the availability problems and lack of OS media make old versions of Xcode otherwise unobtainable.