#!/bin/sh
# rtool - Mach-O library binary relocation tool.
#
# Copyright (C) 1999-2007 Plumber
# OpenSpecies, The GNU-Darwin Distribution.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
##
# begin Functions
##
#
# boolean is_mach(string $file)
#
function is_mach ()
{
if ! test "$1" = "" ;
then
if file $1 | grep "Mach-O" 1>/dev/null ;
then
return 1;
else
return 0;
fi
fi
return 0;
}
#
# boolean is_link(string $link, string $file)
#
function is_link ()
{
if ! test "$1" = "" && ! test "$2" = "" ;
then
grepLink=`otool -L $2 | grep $1 | cut -d" " -f 1`
if ! test "$grepLink" = "" ;
then
return 1;
else
return 0;
fi
fi
return 0;
}
#
# void link_transform(string $link2search, string $link2replace, string $binary)
#
function link_transform ()
{
s="$1"
r="$2"
x="$3"
is_mach "$x"
if test "$(echo $?)" = "1" ;
then
is_link "$s" "$x"
if test "$(echo $?)" = "1" ;
then
install_name_tool -change $s $r $x
fi
fi
}
#
# void links_exchange(list $search_links,list $replace_links , string $binary)
#
function links_exchange ()
{
s_l="$1"
r_l="$2"
x="$3"
if [ $(echo $s_l | wc -w) = $(echo $r_l | wc -w) ] ;
then
i=1
for s in $s_l;
do
r=$(echo $r_l | cut -d" " -f $i );
link_transform $s $r $x
let i=$i+1
done
fi
}
#
# void relocate_lib(string $id, string $lib)
#
function relocate_lib ()
{
is_mach "$2"
if test "$(echo $?)" = "1" ;
then
install_name_tool -id "${1}" "${2}"
fi
}
#
# void relocate_lib(string $framework_full_root, string $framework_name, string $library)
#
function frameworkize_lib ()
{
relocate_lib "${1}/${2}" "${3}"
}
##
# end Functions
##
##
# begin Lambda
##
#
# lambda &getlib_name ()
#
getlib_name ()
{
lib=$(basename $library)
lib_name=$(echo $lib | sed "s/\.[0-9]//g" | sed "s/.dylib//g")
}
#
# lambda &getlib_version ()
#
getlib_version ()
{
lib_version=$(echo $lib | sed "s/$lib_name\.//g" | sed "s/.dylib//g")
}
#
# lambda &getproj_name ()
#
getproj_name ()
{
proj_name=${framework_name}.frwkproj
}
#
# lambda &lib_id ()
#
getlib_id ()
{
lib_id=$(otool -D $library | grep $lib_name | cut -d: -f 2)
}
##
# end Lambda
##
#
# begin getOpt
#
stderr()
{
echo " "
echo " ****************** "
echo " * $1 "
echo " ****************** "
echo " "
exit 1
}
usage()
{
less -ce <<EOF
Usage: rtool [OPTION]...
Relocate a library as a framework bundle.
Options:
--framework_root framework root (@executable_path/../Frameworks)
--framework_name framework name mynameLib
--framework_version framework version
--library library /some/where/libmyname.dylib
--rlinks_binaries (optional) exchange shared libraries linked
--rlinks_framework (optional) exchange shared libraries linked
--headers (optional list) "/some/where/header_1.h some/where/header_2.h"
--builddir build
--binaries (optional list) "/some/where/bin_1 some/where/bin_2"
--manuals (optional list) "/some/where/manual_1.1 some/where/manual_2.3"
--version displays version
Default:
rtool \\
--framework_root=/library/Frameworks \\
--framework_name=mynameLib \\
--framework_version=A \\
--library=/some/where/libmyname.dylib \\
--builddir=/some/where/build
Examples:
#search list :
\$search=/usr/lib/libMy.dylib \\
/usr/lib/libOther.dylib
#replace list :
\$replace=@executable_path/../Frameworks/My.framework/Versions/A/My \\
@executable_path/../Frameworks/Other.framework/Versions/A/Other
--rlinks_framework="[\$search]:[\$replace]"
\$x=$\{framework_name}.framework/Version/$\{framework_version}/$\{framework_name}
for count \$search ;
do
\$s=\$search[i]
\$r=\$replace[i]
install_name_tool -change \$s \$r \$x
done
--rlinks_binaries="[\$search]:[\$replace]"
for count binaries
\$x=\$binaries[i]
for count \$search ;
do
\$s=\$search[i]
\$r=\$replace[i]
install_name_tool -change \$s \$r \$x
done
done
EOF
exit 1
}
if test $# -eq 0 ; then
usage 1 1>&2
fi
while test $# -gt 0 ; do
case "$1" in
-*=*)
optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'`
;;
*)
optarg=
;;
esac
case $1 in
--framework_root=*)
if ! test "$optarg" = "" ;
then
framework_root=$optarg
framework_root_set=yes
fi
;;
--framework_name=*)
if ! test "$optarg" = "" ;
then
framework_name=$optarg
framework_name_set=yes
fi
;;
--framework_version=*)
if ! test "$optarg" = "" ;
then
framework_version=$optarg
framework_version_set=yes
fi
;;
--library=*)
if ! test "$optarg" = "" ;
then
library=$optarg
library_set=yes
fi
;;
--rlinks_framework=*)
if ! test "$optarg" = "" ;
then
rlinks_framework=$optarg
rlinks_framework_set=yes
fi
;;
--rlinks_binaries=*)
if ! test "$optarg" = "" ;
then
rlinks_binaries=$optarg
rlinks_binaries_set=yes
fi
;;
--builddir=*)
if ! test "$optarg" = "" ;
then
builddir=$optarg
builddir_set=yes
fi
;;
--binaries=*)
if ! test "$optarg" = "" ;
then
binaries=$optarg
binaries_set=yes
fi
;;
--headers=*)
if ! test "$optarg" = "" ;
then
headers=$optarg
headers_set=yes
fi
;;
--manuals=*)
if ! test "$optarg" = "" ;
then
manuals=$optarg
manuals_set=yes
fi
;;
--version)
echo 1.0.0
exit 0
;;
--help)
usage 1 1>&2
;;
*)
stderr "Arguments error : rtool --help"
;;
esac
shift
done
#
# end getOpt
#
#
# begin testOpt
#
if test "$framework_root_set" = "yes" \
&& test "$framework_name_set" = "yes" \
&& test "$library_set" = "yes" \
&& test "$builddir_set" = "yes" ; then
if ! test -f $library ;
then
stderr "Not found : --library=${library}"
fi
getlib_name 1 1>&2
getlib_version 1 1>&2
getproj_name 1 1>&2
getlib_id 1 1>&2
if ! test "$framework_version_set" = "yes" ; then
framework_version=${lib_version}
fi
framework_bundle=${framework_name}.framework/Versions/${framework_version}
framework_full_root=${framework_root}/${framework_bundle}
rm -Rf ${builddir}/$proj_name
framework_resources=${builddir}/$proj_name/${framework_bundle}/Resources
mkdir -p ${framework_resources}
framework_framework=${builddir}/$proj_name/${framework_bundle}
mkdir -p ${framework_framework}
cp -f $library ${framework_framework}/${framework_name}
chmod -f 755 ${framework_framework}/${framework_name}
frameworkize_lib "${framework_full_root}" "${framework_name}" "${builddir}/${proj_name}/${framework_bundle}/${framework_name}"
if test "$rlinks_framework_set" = "yes" ;
then
s=$(echo $rlinks_framework | cut -d: -f 1 | sed "s/\[//g" | sed "s/\]//g")
r=$(echo $rlinks_framework | cut -d: -f 2 | sed "s/\[//g" | sed "s/\]//g")
links_exchange "$s" "$r" "${builddir}/${proj_name}/${framework_bundle}/${framework_name}"
fi
#dev hack
if test "$build_local_support" = "yes" ;
then
#( cd ${framework_framework} \
#&& ln -s ${framework_name} ${lib_name}.dylib \
#&& ln -s ${framework_name} ${lib_name}.dylib.${lib_version} \
#&& ln -s ${framework_name} ${lib_name}.${lib_version}.dylib )
symlinks=$(ls $(dirname $library) | grep ${lib_name}\.*dylib)
#prefix=$(dirname $lib_id | sed "s/\/lib//g")
#mkdir -p ${builddir}/$proj_name${prefix}/{bin,include,lib,share} ;
for symlink in $symlinks; do
( cd ${framework_resources} && ln -fs ../${framework_name} $(basename $symlink) )
done
if test -f $(dirname $library)/${lib_name}.la;
then
cp -f $(dirname $library)/${lib_name}.la ${framework_resources}
fi
if test "$headers_set" = "yes" ;
then
( cd ${framework_resources} && ln -fs ../Headers include )
fi
if test "$binaries_set" = "yes" ;
then
( cd ${framework_resources} && ln -fs Utilities bin )
fi
( cd ${framework_resources} && ln -fs . lib )
fi
if test "$binaries_set" = "yes" ;
then
framework_utilities=${framework_resources}/Utilities
mkdir -p ${framework_utilities}
for bin in $binaries; do
cp $bin ${framework_utilities}/$(basename $bin)
chmod -f 755 ${framework_utilities}/$(basename $bin)
link_transform "${lib_id}" "${framework_full_root}/${framework_name}" "${framework_utilities}/$(basename $bin)"
if test "$rlinks_binaries_set" = "yes" ;
then
s=$(echo $rlinks_binaries | cut -d: -f 1 | sed "s/\[//g" | sed "s/\]//g")
r=$(echo $rlinks_binaries | cut -d: -f 2 | sed "s/\[//g" | sed "s/\]//g")
links_exchange "$s" "$r" "${framework_utilities}/$(basename $bin)"
fi
done
fi
if test "$headers_set" = "yes" ;
then
framework_headers=${builddir}/$proj_name/${framework_bundle}/Headers
mkdir -p ${framework_headers}
for header in $headers; do
cp -PR $header ${framework_headers}/$(basename $header)
if test -d ${framework_headers}/$(basename $header) ;
then
mkdir -p ${framework_headers}/$(basename $header)
chmod -f 755 ${framework_headers}/$(basename $header)
else
chmod -f 644 ${framework_headers}/$(basename $header)
fi
done
fi
if test "$manuals_set" = "yes" ;
then
framework_documentation=${framework_resources}/Documentation
mkdir -p ${framework_documentation}
rm -Rf ${framework_documentation}/*
for manual in $manuals; do
if test -x /usr/X11R6/bin/rman ;
then
/usr/X11R6/bin/rman -f HTML $manual > ${framework_documentation}/$(basename $manual).html 2>/dev/null;
elif test -x rman ;
then
rman -f HTML $manual > ${framework_documentation}/$(basename $manual).html 2>/dev/null;
else
cp $manual ${framework_documentation}/$(basename $manual);
fi
done
chmod -f 644 `find ${framework_documentation} -type file`
fi
###
tolinks=$(ls ${framework_framework})
for tolink in $tolinks; do
if test -d ${framework_framework}/$tolink || test "$tolink" = "$framework_name";
then
( cd ${builddir}/$proj_name/${framework_name}.framework && ln -s Versions/${framework_version}/$(basename $tolink) )
fi
done
( cd ${builddir}/$proj_name/${framework_name}.framework/Versions && ln -s ${framework_version} Current )
###
else
stderr "Arguments error : rtool --help"
fi
#
# end testOpt
#