Saturday, June 20, 2009

Changing the RPATH of a binary

Suppose that you have two different versions of a library installed on /usr/lib and /usr/local/lib. Further suppose that for most software you run you will want to use the standard one in /usr/lib, but for a specific program you're compiling you need to make it use /usr/local/lib. The problem is that GCC builds in a search path used at runtime where /usr/lib is always before /usr/local/lib. This means that the binary will always find the wrong library in /usr/lib before it finds the library in /usr/local/lib. You can use ldd and "ldd -s" to check which libraries the binary uses.

Because I don't have a good solution I do this: Use elfedit to edit the binary to change the search path.

Step 1.
Get the current search path. (-r means read-only so you will only display the current one)
# elfedit -r -e 'dyn:runpath' file
index tag value
[31] RUNPATH 0x494b /usr/ccs/lib:/lib:/usr/lib:/usr/sfw/lib:/usr/local/lib
[32] RPATH 0x494b /usr/ccs/lib:/lib:/usr/lib:/usr/sfw/lib:/usr/local/lib

See how /usr/lib is before /usr/local/lib? That is my problem here.

Step 2.
Change the path so that /usr/local/lib is before /usr/lib.
# elfedit -e 'dyn:runpath /usr/ccs/lib:/lib:/usr/local/lib:/usr/lib:/usr/sfw/lib' file

Step 3.
Verify that it has changed.
# elfedit -r -e 'dyn:runpath' file
index tag value
[31] RUNPATH 0x4982 /usr/ccs/lib:/lib:/usr/local/lib:/usr/lib:/usr/sfw/lib
[32] RPATH 0x4982 /usr/ccs/lib:/lib:/usr/local/lib:/usr/lib:/usr/sfw/lib

This is the problem I

Wednesday, June 10, 2009

Build awesome 3.2.1 on OpenSolaris 2009.06

There are a number of prerequisites that need to be built before building awesome and a number of them that can be easily installed via IPS.

Getting awesome
Download awesome 3.2.1 from awesome's main site.

Needed IPS packages
You need to install these packages (by "pfexec pkg install SUNWxxx"):
  • SUNWcmake
  • SUNWgnu-gperf (needed by ?)
  • SUNWgmake
  • SUNWgnome-common-devel (for pkg-config)
  • SUNWxwinc (for pthread-stubs and xau, required by libxcb)
  • SUNWgm4 (for xcb-util)
  • SUNWlua (for awesome itself)

Prerequisites
The XCB library and utilities must be installed. I used the following versions:
and they are to be built in that order. Before building "libxcb", set the PKG_CONFIG_PATH environment variable to include "/usr/local/lib/pkgconfig". In bash:
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig

These are compiled by running "./configure", "gmake", "pfexec gmake install". This will by default build them to be placed under "/usr/local".
If, when you do "./configure" on libxcb get something like the following:
checking for XCBPROTO... configure: error: Package requirements (xcb-proto >= 1.1) were not met:

No package 'xcb-proto' found

Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
then that means you haven't set the PKG_CONFIG_PATH to "/usr/local/lib/pkgconfig".

Building cairo, pango and imlib2
Get cairo 1.8.6 here.
Get pango 1.24.2 here.
Get imlib2 here.
For cairo, use these configure flags to enable xcb and disable xlib.
./configure --enable-xcb --disable-xlib
Also here, run "gmake" and "pfexec gmake install".

For pango, use these configure flags to disable xlib.
./configure --without-x
And then "gmake", "pfexec gmake install".
For some versions of pango there is a bug in which pango tries to include "cairo-xlib.h" even when using the "--without-x" configure flag. In that case, go here
and get the patch (the .diff file) and apply it to pango using (assuming you save the patch file as pango_cairo_xlib.diff):

patch -p0 < pango_cairo_xlib.diff
and recompile.

Build imlib2 using "./configure", "gmake", "pfexec gmake install".

Building readline and libev
The readline main site is here.
Get libev from here.
Compile both using "./configure", "gmake", "pfexec gmake install".

Compiling awesome
There are a few things that need to be adjusted in awesome's build scripts to make it link cleanly. No changes should have to be made to the actual code.

The following patch adds libsocket to required libraries.
--- awesomeConfig.cmake.orig 2009-06-11 20:27:17.136714602 +0200
+++ awesomeConfig.cmake 2009-06-11 20:26:31.525618560 +0200
@@ -163,6 +163,7 @@
# Check for readline, ncurse and libev
a_find_library(LIB_READLINE readline)
a_find_library(LIB_EV ev)
+a_find_library(LIB_SOCKET socket)

# Error check
if(NOT LUA51_FOUND AND NOT LUA50_FOUND) # This is a workaround to a cmake bug
@@ -173,6 +174,7 @@
${AWESOME_COMMON_REQUIRED_LIBRARIES}
${AWESOME_REQUIRED_LIBRARIES}
${LIB_EV}
+ ${LIB_SOCKET}
${LUA_LIBRARIES})

set(AWESOME_REQUIRED_INCLUDE_DIRS
@@ -184,6 +186,7 @@
${AWESOME_COMMON_REQUIRED_LIBRARIES}
${LIB_READLINE}
${LIB_XCB}
+ ${LIB_SOCKET}
${CURSES_LIBRARIES})

set(AWESOMECLIENT_REQUIRED_INCLUDE_DIRS

The following patch fixes an unexpected link flag.

--- CMakeLists.txt.orig 2009-06-11 20:28:37.049608031 +0200
+++ CMakeLists.txt 2009-06-11 20:28:21.726953876 +0200
@@ -100,7 +100,7 @@

set_target_properties(${PROJECT_AWE_NAME}
PROPERTIES
- LINK_FLAGS -export-dynamic)
+ LINK_FLAGS --export-dynamic)

target_link_libraries(${PROJECT_AWE_NAME}
${AWESOME_COMMON_REQUIRED_LIBRARIES}


To compile, run "gmake".

Awesome actually compiles at this point, but I had problems with it finding the incompatible versions of cairo already installed in /usr/lib by default in OpenSolaris. To fix that I had to edit the binary with elfedit and set a different runpath on the awesome binary itself, but I'll leave that for an edit of this post.