52

I have used Ubuntu/Fedora/Red Hat/Suse but haven't used OS X at all. If I have to start using OS X regularly, what are the things I should look out for?

Tools I use are GNU tool chain, C++/Boost, etc.

2
  • Are you going to be developing more conventional Unix/Linux apps, or Mac OSX apps? Aug 24, 2010 at 21:39
  • 1
    At least at first more conventional Unix/Linux apps, I just use the OS X PC as a workstation.
    – grokus
    Aug 25, 2010 at 0:03

7 Answers 7

54

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 @loader_path/../lib/libfoo.dylib instead.

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/lib or /usr/local/lib. When you run into this, a good fix for the problem is to add lines like the following to your .bash_profile:

    # Tell the dynamic linker (dyld) where to find MacPorts package libs
    export DYLD_LIBRARY_PATH=/opt/local/lib:$DYLD_LIBRARY_PATH

    # Add MacPorts header file install dirs to your gcc and g++ include paths
    export C_INCLUDE_PATH=/opt/local/include:$C_INCLUDE_PATH
    export CPLUS_INCLUDE_PATH=/opt/local/include:$CPLUS_INCLUDE_PATH
  • 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 lib directory.

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'

Add -arch ppc -arch ppc64 to the CFLAGS and 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.

4
  • 2
    +1: specifically for mentioning dynamic linkage. I got caught out thinking it would be very similar. The joy of install_name and how the OSX dynamic link editor, dyld, resolves depdendencies!
    – Troubadour
    Aug 19, 2010 at 14:53
  • About keeping old versions of MacOS: I use Parallel to keep separated VMs with a given OS X version if I want to test backward compatibility. I recommend this or a similar tool for app testing.
    – ogerard
    Apr 30, 2011 at 13:59
  • For old versions of the developer tools, check out connect.apple.com. I just checked, and the first download listed in the Developer Tools section is Xcode 1.0 from 27 Oct 2004 for OS X 10.3+. No ProjectBuilder, but SOP for Mac projects is to support only the current and previous major releases, so 10.3+ is more than enough. Jun 8, 2011 at 17:05
  • @Jeremy: Updated. I don't want to assure people they always will be downloadable, since they haven't always been in the past. Jun 8, 2011 at 19:45
30

HUGE GOTCHA -- Mac OS filesystem is NOT case sensitive.

4
  • 9
    Just to be clear, they are case-preserving and not case-sensitive by default. So the case of your filename will be preserved, but you can access it through any variation of case. This can be changed to be case-sensitive when the filesystem is created.
    – KeithB
    Aug 18, 2010 at 20:38
  • 9
    @KeithB: However, many mainstream Mac apps will not run on a case-sensitive filesystem, eg Adobe CS refuses even to install, and World of Warcraft won't run. I got burned by this and the only way to recover was to back up and restore my system onto a reformatted disk. Sep 10, 2010 at 21:42
  • 1
    This is mostly a gotcha when dealing with version control, and working on a project in a multiplatform team.
    – Arafangion
    Oct 5, 2010 at 14:23
  • I created a case-sensitive sparsebundle to workaround this. Thankfully, I have an unused partition on this SSD.
    – dhchdhd
    Apr 24, 2012 at 3:33
9

Although Fink and MacPorts are the traditional means of getting unix packages on OS X, I'd recommend checking out a newer tool called brew that has worked better for me and messed less with my system, and is much easier to use. It basically just downloads tarballs and installs to /usr/local, but it automates the whole process very nicely.

Link

1
  • 1
    Agreed; Homebrew has been working a lot smoother for me than MacPorts did.
    – Jonik
    Jul 9, 2013 at 8:24
4

HUGE GOTCHA -- Mac OS filesystem is NOT case sensitive.

You may create a case sensitive disk image on Mac OS X which can be mounted as a normal hard drive volume.

# cf. http://codesnippets.joyent.com/posts/show/8617
IMAGE="${HOME}/Desktop/Case Sensitive Test.dmg"
VOLNAME="Case Sensitive Test"

hdiutil create "${IMAGE}" -size 10m -fs HFSX -volname "${VOLNAME}" -layout NONE

hdiutil attach "${IMAGE}"

cd "/Volumes/${VOLNAME}"
touch foo.txt Foo.txt
open .
ls -l [Ff]oo.txt
stat -f "inode: %i  --  name: %N" [Ff]oo.txt

cd ~
hdiutil detach "/Volumes/${VOLNAME}"
3

Here's a good source of selected dev articles, the Cocoa Literature List:

http://osx.hyperjeff.net/Reference/CocoaArticles

(This may be especially useful if one day you want to make use of Mac OS X specific goodies.)

3

When porting a network stack from Solaris, BSD, Linux, and Windows to OSX the only main point that garners attention is that much like FreeBSD the entire tool chain is pretty old.

Apple are speeding with with OSX Lion but Leopard, Snow Leopard are pretty behind modern Linux distributions and many standards are not supported. In my case I am hit with lack of RFC 3678 (Socket Interface Extensions for Multicast Source Filters) being quite inconvenient.

On OSX server I installed a case-sensitive file system as it recommends to do so for HTTP serving.

  • Old GCC
  • Old Autoconf, Automake, libtool
  • No Pthread spinlocks, OSX provides native alternatives.
  • Not many re-rentrant NSS APIs.
  • Not overly useful /proc file system.
  • No /dev/rtc, /dev/hpet, and RDTSC seems to be gimped. OSX provides native alternatives.
  • No epoll, but you have poll and kqueue
1

OS X supports pthread_cond_timedwait but it uses absolute calendar time and there is no way to use a monotonically increasing time.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .