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.
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityI 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.
I made the same move years ago. Here are the things I've run into:
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.
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.
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.
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
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.)
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.
dyld
, resolves depdendencies!
Aug 19, 2010 at 14:53
HUGE GOTCHA -- Mac OS filesystem is NOT case sensitive.
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.
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}"
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.)
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.
/proc
file system./dev/rtc
, /dev/hpet
, and RDTSC
seems to be gimped. OSX provides native alternatives.epoll
, but you have poll
and kqueueOS X supports pthread_cond_timedwait
but it uses absolute calendar time and there is no way to use a monotonically increasing time.