Skip to content

ROS Diamondback on OS X 10.6 using Macports

wjwwood edited this page Oct 9, 2011 · 1 revision

ROS on OS X 10.6.x Snow Leopard

Information about how to install ROS Diamonback on OS X are available here also: http://www.ros.org/wiki/diamondback/Installation/OSX

This guide is step by step method for building ROS i386 only on OS X with macports. This allows us to use rviz (and other tools) in OS X successfully until the wx dependency is solved or removed.

Not every fix here is ideal and recommendations/edits are welcome. [email protected]

RViz on OS X

NOTICE: This document was written for Diamondback on OS X around the date June 16th, 2011. It is important to note that things change quickly in the ROS environment and while we will try to keep the page uptodate sometimes searching on answers.ros.org or the mailing list.

ANOTHER NOTICE: Lion will kill all of this. Possibly hold off on upgrading if you are interested in having RVIZ working.

Start over with macports

We would suggest starting over with macports just so you can be sure that you have all your ports built correctly. If you don't want to do this, then you just need to make sure that all your ports are built universal (that support it) and that you are using only one version of Python (here we use 2.6.x).

Setting up a Fresh Macports

To preserve your old macports while working with a new one, a few things need to happen:

  1. Move /opt to something like /old_opt: sudo mv /opt /old_opt

  2. Make sure all entries relating to macports, previous ROS installs, or specific Python PATH settings in your ~/.profile, ~/.bash_profile, and ~/.bashrc files have been removed or commented out.

  3. Restart your shell to ensure these changes have taken place.

  4. Reinstall macports

  • (~mc: Tested with 1.9.2 DMG)

Setting up global macports variants

This is done for two reasons... First, the +universal variant will build all packages as fat (i386 and x86_64) binaries if supported, this allows 32-bit programs/libraries to use your macports stuff as well as 64-bit. Secondly, restricting to one version of Python prevents confusion when building ROS libraries which might cross-compile with a different version because cmake's FindPython.cmake in /opt/local/share/cmake-2.8/Modules/ is not affected by python-select... this causes libraries, specifically tf, to compile against a different python than what you are using. You can modify FindPython.cmake to force using that python you want, but just having one version is easier. There is probably a better solution here and it is greatly welcome.

Append these changes with your editor of choice and elevated (sudo) privileges in the /opt/local/etc/macports/variants.conf file:

+universal
-python27
+python26

Note: Add the line -atlas if you want to avoid building atlas for numpy.

Note: There is some discussion here and here about doing +no_x11 +quartz in the variants.conf to help fix some python/gtk/cairo issues that you will encounter when trying to run rxgraph, rxbag, others... This hasn't been tested yet.

Macports bash variables

Now we need to set some variables so that ROS and other libraries can find all of Macports stuff properly:

if [ "$UNAME" = Darwin ]; then
    test -x /opt/local -a ! -L /opt/local && {
        PORTS=/opt/local
        
        PATH="$PORTS/bin:$PORTS/sbin:$PATH"
        MANPATH="$PORTS/share/man:$MANPATH"
        
        export CPATH=$PORTS/include
        export LIBRARY_PATH=$PORTS/lib
        export LD_LIBRARY_PATH=$PORTS/lib
        export DYLD_FALLBACK_LIBRARY_PATH=$DYLD_FALLBACK_LIBRARY_PATH:$PORTS/lib
    }   
fi

Credit Indirectly: Michael Carroll [email protected]

Installing required packages from Macports

Finally you are ready to start installing necessary requirements for ROS.

sudo port install wget cmake python_select subversion git-core mercurial py26-yaml py26-setuptools boost py26-numpy py26-paramiko log4cxx

Now, you should go get coffee, make a sandwich, take a vacation... w/e. This is going to take a long time if you are building from scratch because you have to build boost, gcc, and atlas (if you pull numpy)...

Now make sure you are using the macports python26:

sudo port select --set python python26

Installing rosinstall

Just to be sure to use macports Python: export PATH=/opt/local/Library/Frameworks/Python.framework/Versions/2.6/bin:$PATH

sudo easy_install pip

sudo pip install rosinstall

which rosinstall should now return: /opt/local/Library/Frameworks/Python.framework/Versions/2.6/bin/rosinstall

Installing ROS

I recommend, as with macports, starting a new ros install from source. I use the command from the OS X installation page on ros.org's wiki for desktop-full on Diamondback:

LANG=en_US.utf-8 rosinstall ~/devel/ros/diamondback "http://packages.ros.org/cgi-bin/gen_rosinstall.py?rosdistro=diamondback&variant=desktop-full&overlay=no"

Don't forget to prepend rosintall with LANG=en_US.utf-8 in order to avoid problems with locale. More explanations here: https://code.ros.org/lurker/message/20110207.221305.26a5169b.en.html Ticket here: https://code.ros.org/trac/ros/ticket/3305

Note: I use ~/devel/ros/diamondback as my install location, change this to what ever you want for your install location.

Setup your bash variables

echo "source ~/ros/setup.bash" >> ~/.bashrc
. ~/.bashrc

Building rViz

Next, you will inevitably (for the moment) have failures during the ROS installation. You will need to look in the Troubleshooting section of this page and the ROS related elements to try and fix each problem as you run into it. Each time you fix on rospkg you will need to rerun the rosinstall command until it succeeds.

Once you have successfully rosinstalled the base of ros, you will want to attempt to build tools like rViz:

CMAKE_OSX_ARCHITECTURES="i386" rosmake --rosdep-install rviz

Note: Sometimes you need to add the --pre-clean flag to rosmake if you change the architecture.

The CMAKE_OSX_ARCHITECTURES="i386" is required to make 32-bit binaries for OS X. Anything built with cmake will adhere to this, others will still break (things that use Make only). Again, you will want to consult the troubleshooting section of this wiki to find solutions to specific failures.

Troubleshooting

ROS: rosrecord

Failure:

Linking CXX executable ../bin/rosplay
Undefined symbols:
"boost::filesystem3::path::extension() const", referenced from:
    ros::record::Player::open(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, ros::Time, bool)in rosplay.o
"boost::filesystem3::path::wchar_t_codecvt_facet()", referenced from:
    ros::record::Player::open(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, ros::Time, bool)in rosplay.o
ld: symbol(s) not found

Ticket:

https://code.ros.org/trac/ros-pkg/ticket/4923

Solution:

I applied the patch:

Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 13886)
+++ CMakeLists.txt	(working copy)
@@ -19,7 +19,7 @@
 rosbuild_link_boost(rosrecord iostreams)
 
 rosbuild_add_executable(rosplay src/rosplay/rosplay.cpp src/rosplay/time_publisher.cpp)
-rosbuild_link_boost(rosplay iostreams system)
+rosbuild_link_boost(rosplay iostreams system filesystem)
 
 #INSTALL(TARGETS rosrecord rosplay
 #        RUNTIME DESTINATION $ENV{ROS_ROOT}/bin)

ROS: rViz rosdep py26-wxpython

Failure:

Error: Cannot install py26-wxpython for the arch(s) 'i386 x86_64' because
Error: its dependency wxWidgets-python does not build for the required arch(s) by default
Error: and does not have a universal variant.
Error: Unable to execute port: architecture mismatch

Solution:

Build py26-wxpython as non-universal, non-gtk, and +carbon.

sudo port clean py26-wxpython
sudo port install py26-wxpython +carbon

This will force it to build i386 for carbon and ignore the +universal and +gtk variants.

ROS: wxpropgrid

Failure:

ld: warning: in propgridsample_minimal.o, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in propgridsample_propgridsample.o, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in propgridsample_sampleprops.o, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in propgridsample_tests.o, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in propgridsample_xh_propgrid.o, file was built for unsupported file format which is not the architecture being linked (i386)
Undefined symbols:
  "_main", referenced from:
      start in crt1.10.6.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
make[1]: *** [samples/propgridsample] Error 1

Ticket:

https://code.ros.org/trac/ros-pkg/ticket/4788#comment:8

Solution:

Use the patch in the comment linked above:

--- visualization/wxpropgrid/Makefile	(revision 36357)
+++ visualization/wxpropgrid/Makefile	(working copy)
@@ -14,8 +14,8 @@

 installed: $(SOURCE_DIR)/unpacked
 	cd $(SOURCE_DIR) && \
-		export CFLAGS='-g -D__NOTWXPYTHON__ -g' && \
-		export CXXFLAGS='-g -D__NOTWXPYTHON__ -g' && \
+		export CFLAGS='-g -D__NOTWXPYTHON__ -g -arch i386' && \
+		export CXXFLAGS='-g -D__NOTWXPYTHON__ -g -arch i386' && \
 		./configure --prefix=$(WXPROPGRID_ROOT)/propgrid_install && \
 		make && \
 		make install

ROS: pluginlib

Failure:

/Users/william/devel/ros/diamondback/common/pluginlib/src/boost_fs_wrapper.cpp: In function ‘std::string pluginlib::getPackageFromLibraryPath(const std::string&)’:
/Users/william/devel/ros/diamondback/common/pluginlib/src/boost_fs_wrapper.cpp:58: error: conversion from ‘boost::filesystem3::path’ to non-scalar type ‘std::basic_string<char, std::char_traits<char>, std::allocator<char> >’ requested

Ticket:

https://code.ros.org/trac/ros-pkg/ticket/4976

Solution:

Apply the patch from the ticket.

Index: src/boost_fs_wrapper.cpp
===================================================================
--- src/boost_fs_wrapper.cpp	(revision 36933)
+++ src/boost_fs_wrapper.cpp	(working copy)
@@ -55,7 +55,7 @@
   {
     if (boost::filesystem::exists(parent / "manifest.xml"))
     {
-      std::string package = parent.filename();
+      std::string package = parent.filename().string();
       std::string package_path = ros::package::getPath(package);
       if (path.find(package_path) == 0)
       {

ROS: ogre_tools

Failure (Look at the top):

Linking CXX shared library ../lib/libogre_tools.dylib
ld: warning: in /Users/william/devel/ros/diamondback/visualization_common/ogre/ogre/lib/Ogre.framework/Ogre, file was built for i386 which is not the architecture being linked (x86_64)

Ticket:

https://code.ros.org/trac/ros-pkg/ticket/4788#comment:8

Solution:

roscd ogre_tools
make clean
CMAKE_OSX_ARCHITECTURES="i386" rosmake ogre_tools

ROS: rxtools

Failure:

Linking CXX shared library ../lib/librxtools.dylib
ld: warning: in /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks//QuickTime.framework/QuickTime, missing required architecture x86_64 in file
ld: warning: in /opt/local/lib/libwx_macu-2.8.dylib, file was built for i386 which is not the architecture being linked (x86_64)

Ticket:

https://code.ros.org/trac/ros-pkg/ticket/4788#comment:8

Solution:

roscd rxtools
make clean
CMAKE_OSX_ARCHITECTURES="i386" rosmake rxtools

ROS: rViz

Failure:

Linking CXX shared library ../../../lib/librviz.dylib
ld: warning: in /Users/william/devel/ros/diamondback/common/yaml_cpp/yaml-cpp/lib/libyaml-cpp.dylib, file was built for unsupported file format which is not the architecture being linked (i386)

Ticket:

https://code.ros.org/trac/ros-pkg/ticket/4788#comment:8

Solution:

roscd yaml_cpp
make clean

Patch the Makefile with this:

Index: Makefile
===================================================================
--- Makefile	(revision 37210)
+++ Makefile	(working copy)
@@ -12,7 +12,7 @@


 yaml-cpp: wiped $(SOURCE_DIR)/unpacked
-	cd build && cmake -DCMAKE_INSTALL_PREFIX=../yaml-cpp yaml-cpp-0.2.5
+	cd build && cmake -DCMAKE_INSTALL_PREFIX=../yaml-cpp yaml-cpp-0.2.5 -DCMAKE_OSX_ARCHITECTURES="i386"
 	cd build && make && make install
 	if [ `uname` = Darwin ]; then \
 		install_name_tool -id `rospack find yaml_cpp`/yaml-cpp/lib/libyaml-cpp.0.2.dylib yaml-cpp/lib/libyaml-cpp.0.2.dylib; \

Note: not sure why you have to add the CMAKE_OSX... in the Makefile on this one..._

Then rebuild it:

make

Then rebuild rviz:

roscd rviz
make clean
CMAKE_OSX_ARCHITECTURES="i386" rosmake rviz

ROS: running rviz

Failure:

If you run rosrun rviz rviz and get:

dyld: Library not loaded: libassimp.1.dylib
  Referenced from: /Users/william/devel/ros/diamondback/visualization/rviz/bin/rviz
  Reason: image not found
Trace/BPT trap

Ticket:

https://code.ros.org/trac/ros-pkg/ticket/4788#comment:8

Solution:

roscd assimp && install_name_tool -id $(rospack find assimp)/lib/libassimp.1.dylib lib/libassimp.1.dylib
roscd rviz
make clean
CMAKE_OSX_ARCHITECTURES="i386" rosmake rviz

ROS: opende

Failure:

Undefined symbols:
  "_XGetImage", referenced from:
      processDrawFrame(int*, dsFunctions*)  in libdrawstuff.a(x11.o)
  "_XInternAtom", referenced from:
      createMainWindow(int, int)in libdrawstuff.a(x11.o)
      createMainWindow(int, int)in libdrawstuff.a(x11.o)
  "_XLookupString", referenced from:
      handleEvent(_XEvent&, dsFunctions*)      in libdrawstuff.a(x11.o)
  "_XDestroyWindow", referenced from:
      dsPlatformSimLoop(int, int, dsFunctions*, int)in libdrawstuff.a(x11.o)
  "_XSetWMName", referenced from:
      createMainWindow(int, int)in libdrawstuff.a(x11.o)
  "_XPending", referenced from:
      dsPlatformSimLoop(int, int, dsFunctions*, int)in libdrawstuff.a(x11.o)
  "_XSetWMProtocols", referenced from:
      createMainWindow(int, int)in libdrawstuff.a(x11.o)
  "_XNextEvent", referenced from:
      dsPlatformSimLoop(int, int, dsFunctions*, int)in libdrawstuff.a(x11.o)
  "_XOpenDisplay", referenced from:
      createMainWindow(int, int)in libdrawstuff.a(x11.o)
  "_XCreateWindow", referenced from:
      createMainWindow(int, int)in libdrawstuff.a(x11.o)
  "_XCloseDisplay", referenced from:
      dsPlatformSimLoop(int, int, dsFunctions*, int)in libdrawstuff.a(x11.o)
  "_XSync", referenced from:
      processDrawFrame(int*, dsFunctions*)  in libdrawstuff.a(x11.o)
      createMainWindow(int, int)in libdrawstuff.a(x11.o)
      dsPlatformSimLoop(int, int, dsFunctions*, int)in libdrawstuff.a(x11.o)
  "_XQueryPointer", referenced from:
      handleEvent(_XEvent&, dsFunctions*)      in libdrawstuff.a(x11.o)
  "_XCreateColormap", referenced from:
      createMainWindow(int, int)in libdrawstuff.a(x11.o)
  "_XMapWindow", referenced from:
      createMainWindow(int, int)in libdrawstuff.a(x11.o)
ld: symbol(s) not found
collect2: ld returned 1 exit status

Solution:

Apply this patch:

Index: Makefile.ode.tarball
===================================================================
--- Makefile.ode.tarball	(revision 37210)
+++ Makefile.ode.tarball	(working copy)
@@ -3,8 +3,14 @@
 
 CFG_OPTIONS = --with-libccd=cyl-cyl --with-trimesh=opcode --enable-new-trimesh --enable-demos --enable-shared --with-arch=nocona --enable-release --enable-malloc --enable-ou --disable-asserts --with-pic --enable-double-precision

-ifeq ($(WITH_DRAWSTUFF), yes)
-CFG_OPTIONS += --with-drawstuff=X11
+UNAME := $(shell uname)
+
+ifeq ($(WITH_DRAWSTUFF), yes) 
+	ifeq ($(UNAME), Darwin)
+		CFG_OPTIONS += --with-drawstuff=OSX
+	else
+		CFG_OPTIONS += --with-drawstuff=X11
+	endif
 endif

 all: threadpool installed

Python Problems:

  • Depending on how your building things, some libraries for ros might end up being 32-bit. If you want the ros extensions to python to build and work properly then you'll need to make sure to run python in 32-bit mode.

  • To force python to run as a 32-bit binary you can do: arch -i386 /opt/local/Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python

I use the following script to start a python instance:

#!/usr/bin/env bash
arch -i386 /opt/local/Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python "$@"
  • If your numpy is not building as a 32-bit extension with macports, dont worry your not alone. The macports py26-numpy seemed to ignore all of the flags I gave it and only build as a 64-bit extension. In the end, I ended up manually building numpy. To build it, download the source from http://sourceforge.net/projects/numpy/files/NumPy/1.6.0/numpy-1.6.0.tar.gz/download which is the current release. On OS X 10.6+ to build an extension as a universal binary or to specify the architecture you need to set the ARCHFLAGS. env ARCHFLAGS="-arch i386 -arch x86_64" python setup.py build and sudo env ARCHFLAGS="-arch i386 -arch x86_64" python setup.py install should build and install the extension as a universal binary. If you only want the 32-bit extension then simply do use ARCHFLAGS="-arch i386".

Misc. Notes

  • To run any universal binary in a specific architecture, simply do arch -i386 /path/to/binary and it will force an architecture. Valid architectures are ppc, i386, ppc64, and x86_64.