The attached patch (+ two new files) enables cygport to build "relocatable" packages using the framework devised by Bruno Haible -- if the upstream source supports it. Currently, only libiconv and gettext support this feature (coincidentally, the upstream maintainer of both packages is...Bruno Haible).

A relocated package is compiled using a temporary --prefix, like /tmp/libiconv-reloc-912385{/bin,/share,/lib,...} It is then installed into /usr{/bin,/share,/lib,...} -- but internally, all applications and libraries "figure out" where things are by computing relative paths between "where I thought I was going to be" and "where I actually am installed". So, in our case
  (1) cygbuild needs to use ${RELOC}/usr/... not just /usr/...
  (2) cyginstall needs a little tweaking so that things end up in
      ${D}/${RELOC/usr/... and not ${D}/usr/...
  (3) pkg_binpkg needs to cd into ${D}${RELOC}, not ${D} before tar'ing
      things up.
There are other minor tweaks -- but if you don't 'import relocatable', then they are all no-ops (e.g. ${RELOC} is empty). That is, the global variable _ENABLE_RELOCATION (initially empty) acts like the _USE_CVS_FETCH/_USE_SVN_FETCH/_USE_GIT_FETCH variables, in that a cygclass sets it in order to modify the behavior of functions defined in the main cygport script. Don't 'import relocatable' -- and behavior is unchanged from current (except for the added postinstall/preremove features, described next).

Look for my upcoming official releases of libiconv-1.11 and gettext-0.15 soon, for examples of how to (or not) use the relocation feature for these packages.


The attached patch ALSO allows cygports to handle cases where a multi-binpkg project has different postinstall/preinstall scripts for more than one of the subpackages. This also required adding the ability for client cygports to turn off automatic install-info postinstall generation (e.g. in gettext, gettext.info belongs to the gettext-devel subpackage (so gettext.sh can't install it), but libasprintf.info belongs to the gettext subpackage.


Both of these changes were necessary to convert libiconv/gettext over to a cygbuild process.


NEW FILE: bin/prep_relocated_libtool_la.sh
   make sure that .la files don't have references to their
   temporary --prefix.

NEW FILE: lib/relocatable.cygclass
   mainly just "turns on" the relocation support (and "turns off"
   /usr/lib/cygports/bin/<SCRIPTS> that don't have appropriate support.

2006-10-21  Charles Wilson  <...>

        * bin/Makefile.am: add new file prep_relocated_libtool_la.sh
        * bin/prep_relocated_libtool_la.sh: new file
        * lib/Makefile.am: add new file relocatable.cygclass
        * lib/relocatable.cygclass: new file
        * bin/prep_gnu_info.sh: allow cygport client to suppress
        automatic install-info (useful if: subpackages each have own
        explicit postinstall scripts, and each subpackage "owns"
        certain info files.  To activate *suppression*, set
        SUPPRESS_AUTOMATIC_INSTALLINFO to non-empty.  Default behavior
        is unchanged from current.
        * bin/cygport.in (_ENABLE_RELOCATION): new global variable
        (_RELOCDIR): new global variable
        (__init_relocation): new function
        (__check_relocation): new function
        (__maybe_relocate): new function (main hook for relocatation
        support, called by other cygport functions)
        (cygconf): Add support for ${_RELOCDIR} and --enable-relocatable
        (docinto): Add support for ${_RELOCDIR}
        (exeinto): Add support for ${_RELOCDIR}
        (insinto): Add support for ${_RELOCDIR}
        (__prepare_relocation_ins): new function sets up top level of
        ${D} to point to ${D}${_RELOCDIR}
        (cyginstall): Add support for ${_RELOCDIR}.  Optionally call
        __prepare_relocation_ins.
        (__prepetc): allow ${C}/${PN}.postinstall and ${C}/${PN}.sh as
        synonyms for ${C}/postinstall.sh (however, presence of more than
        one of these causes error message).  Allow ${C}/${PN}.preremove
        as synonym for ${C}/preremove.sh (but presence of both causes
        error message).  Allow for ${C}/${pkg_name[${n}]}.postinstall
        and/or ${C}/${pkg_name[${n}]}.preremove [n > 1].
        (__prepstrip): Add support for ${_RELOCDIR}. Also if relocation
        is enabled, call prep_relocated_libtool_la.sh
        (pkg_binpkg): add support for ${_RELOCDIR}
        (pkg_pkgcheck): add support for ${_RELOCDIR}
        (finish): don't forget to clean up /tmp/temporary-prefix
        directory (even though we never actually install anything there;
        instead we install into ${D}/tmp/temporary-prefix)

--
Chuck
Index: bin/Makefile.am
===================================================================
RCS file: /cvsroot/cygwin-ports/cygport/bin/Makefile.am,v
retrieving revision 1.2
diff -u -r1.2 Makefile.am
--- bin/Makefile.am     7 Aug 2006 23:08:43 -0000       1.2
+++ bin/Makefile.am     22 Oct 2006 06:34:07 -0000
@@ -41,6 +41,7 @@
        prep_gnu_info.sh \
        prep_gtk2_modules.sh \
        prep_libtool_modules.sh \
+       prep_relocated_libtool_la.sh \
        prep_scrollkeeper_omf.sh
 
 EXTRA_DIST = cygport.in
Index: bin/cygport.in
===================================================================
RCS file: /cvsroot/cygwin-ports/cygport/bin/cygport.in,v
retrieving revision 1.26
diff -u -r1.26 cygport.in
--- bin/cygport.in      18 Oct 2006 04:27:31 -0000      1.26
+++ bin/cygport.in      22 Oct 2006 06:34:07 -0000
@@ -711,11 +711,47 @@
        done
 }
 
+_ENABLE_RELOCATION=
+_RELOCDIR=
+__init_relocation() {
+       if [ -d ${B} ] ; then
+         if [ -f ${B}/RELOC ] ; then
+           _RELOCDIR=`cat ${B}/RELOC`
+           if [ -z "${_ENABLE_RELOCATION}" ] ; then
+             error "RELOC file exists but relocation is disabled.  Clean build 
dir!"
+           fi
+         else
+          if [ -n "${_ENABLE_RELOCATION}" ] ; then
+            _RELOCDIR=`mktemp -d /tmp/cygport-reloc-XXXXXX`
+            echo -n ${_RELOCDIR} > ${B}/RELOC
+          fi
+         fi
+       else
+         error "cygport internal error: __init_relocation called too early."
+       fi
+}
+
+__check_relocation() {
+       if [ -z "${_ENABLE_RELOCATION}" -a -n "${_RELOCDIR}" ] ; then
+         error "configuration mismatch: relocation disabled but 
_RELOCDIR=${_RELOCDIR}"
+       fi
+       if [ -n "${_ENABLE_RELOCATION}" -a -z "${_RELOCDIR}" ] ; then
+         error "configuration mismatch: relocation enabled but _RELOCDIR not 
set"
+       fi
+}
+__maybe_relocate() {
+       __init_relocation
+       __check_relocation
+}
+
 # standard configure call
 cygconf() {
-       local confargs="--prefix=/usr --exec-prefix=/usr --bindir=/usr/bin \
-               --sbindir=/usr/sbin --libexecdir=/usr/sbin --localstatedir=/var 
\
-               --sysconfdir=/etc"
+       __maybe_relocate
+
+       local confargs="--prefix=${_RELOCDIR}/usr 
--exec-prefix=${_RELOCDIR}/usr \
+               --bindir=${_RELOCDIR}/usr/bin --sbindir=${_RELOCDIR}/usr/sbin \
+               --libexecdir=${_RELOCDIR}/usr/sbin 
--localstatedir=${_RELOCDIR}/var \
+               --sysconfdir=${_RELOCDIR}/etc"
        local confdir;
 
        if [ -n "${CYGCONF_SOURCE}" -a -x ${CYGCONF_SOURCE}/configure ]
@@ -733,14 +769,20 @@
 
        case "x$(grep -m 1 'GNU Autoconf' ${confdir}/configure | cut -d ' ' -f 
6)" in
                x2.60)
-                       confargs+=" --datarootdir=/usr/share 
--docdir=/usr/share/doc/${P}"
+                       confargs+=" --datarootdir=${_RELOCDIR}/usr/share \
+                               --docdir=${_RELOCDIR}/usr/share/doc/${P}"
                        ;;
                *)
-                       confargs+=" --datadir=/usr/share 
--infodir=/usr/share/info \
-                               --mandir=/usr/share/man"
+                       confargs+=" --datadir=${_RELOCDIR}/usr/share \
+                               --infodir=${_RELOCDIR}/usr/share/info \
+                               --mandir=${_RELOCDIR}/usr/share/man"
                        ;;
        esac
 
+        if [ -n "${_ENABLE_RELOCATION}" ] ; then
+                confargs+=" --enable-relocatable"
+        fi
+
        # AC_HAVE_MMAP fails despite a working mmap, so we force this to yes
        # (see http://www.cygwin.com/ml/cygwin/2004-09/msg00741.html
        # and following thread for details)
@@ -835,8 +877,11 @@
                /*) error "docinto argument should be only a subdirectory" ;;
        esac
 
-       dodir /usr/share/doc/${P}/${1};
-       export _docinto_dir=${1};
+       __maybe_relocate
+       dodir ${_RELOCDIR}/usr/share/doc/${P}/${1};
+
+       # ICK!
+       export _docinto_dir=../../../..${_RELOCDIR}/usr/share/doc/${P}/${1};
 }
 
 # set doexe install dir
@@ -846,8 +891,14 @@
                error "exeinto accepts only one argument";
        fi
 
-       dodir ${1};
-       export _exeinto_dir=${1};
+       case ${1} in
+               /*) ;;
+               *) error "exeinto argument must be absolute" ;;
+       esac
+
+       __maybe_relocate
+       dodir ${_RELOCDIR}${1};
+       export _exeinto_dir=${_RELOCDIR}${1};
 }
 
 # set doins install dir
@@ -857,8 +908,14 @@
                error "insinto accepts only one argument";
        fi
 
-       dodir ${1};
-       export _insinto_dir=${1};
+       case ${1} in
+               /*) ;;
+               *) error "insinto argument must be absolute" ;;
+       esac
+
+       __maybe_relocate
+       dodir ${_RELOCDIR}${1};
+       export _insinto_dir=${_RELOCDIR}${1};
 }
 
 # Pre-install steps
@@ -870,25 +927,58 @@
        find ${B} -type f -exec touch -t $(date +%Y%m%d%H%M.%S) '{}' +;
 }
 
+__prepare_relocation_ins() {
+       # This function assumes that __maybe_relocate() has already been
+       # called, AND that _ENABLE_RELOCATION is non-empty.
+
+       # need to set up some symlinks so cygport functions that lack
+       # dir change support will be fooled into putting things into 
${_RELOCDIR}.
+       if [ ! -d ${D}${_RELOCDIR} ]
+       then
+               mkdir -p ${D}${_RELOCDIR}
+       fi
+
+       for d in $@
+       do
+               case ${d} in
+                       /* ) ;;
+                       *)   d=/${d}
+               esac
+               if [ ! -d ${D}${_RELOCDIR}${d} ]
+               then
+                       mkdir -p ${D}${_RELOCDIR}${d}
+               fi
+               if [ ! -e ${D}${d} ] ; then
+                       (cd ${D} && ln -fs ${_RELOCDIR##/}${d} ${d##/})
+               fi
+       done
+}
+
 # run 'make install'
 cyginstall() {
+       __maybe_relocate
+
+       if [ -n "${_ENABLE_RELOCATION}" ] ; then
+         __prepare_relocation_ins etc var usr
+       fi
+
        case ${USE_DESTDIR:-1} in
                1|[Yy]|[Yy][Ee][Ss])
                        make ${MAKEOPTS} install DESTDIR=${D} "[EMAIL 
PROTECTED]" || error "make install DESTDIR failed"
                        ;;
                0|[Nn]|[Nn][Oo])
                        make ${MAKEOPTS} install \
-                               prefix=${D}/usr \
-                               bindir=${D}/usr/bin/ \
-                               includedir=${D}/usr/include \
-                               libdir=${D}/usr/lib \
-                               sbindir=${D}/usr/sbin \
-                               libexecdir=${D}/usr/sbin \
-                               datadir=${D}/usr/share \
-                               infodir=${D}/usr/share/info \
-                               mandir=${D}/usr/share/man \
-                               localstatedir=${D}/var \
-                               sysconfdir=${D}/etc \
+                               prefix=${D}${_RELOCDIR}/usr \
+                               bindir=${D}${_RELOCDIR}/usr/bin/ \
+                               includedir=${D}${_RELOCDIR}/usr/include \
+                               libdir=${D}${_RELOCDIR}/usr/lib \
+                               sbindir=${D}${_RELOCDIR}/usr/sbin \
+                               libexecdir=${D}${_RELOCDIR}/usr/sbin \
+                               datadir=${D}${_RELOCDIR}/usr/share \
+                               infodir=${D}${_RELOCDIR}/usr/share/info \
+                               mandir=${D}${_RELOCDIR}/usr/share/man \
+                               localstatedir=${D}${_RELOCDIR}/var \
+                               sysconfdir=${D}${_RELOCDIR}/etc \
                                [EMAIL PROTECTED] \
                                || error "make install No-DESTDIR failed"
                        ;;
@@ -974,16 +1064,62 @@
 __prepetc() {
        local d;
        local s;
+       local -i n=1
+       local -i count=0
+
+       # handle some conflicts between default behavior...
+       if [ -f ${C}/${PN}.sh          ]; then count+=1 ; fi
+       if [ -f ${C}/postinstall.sh    ]; then count+=1 ; fi
+       if [ -f ${C}/${PN}.postinstall ]; then count+=1 ; fi
+        if (( $count > 1 ))
+       then
+               error "Can have only one of ${PN}.sh, ${PN}.postinstall, and 
postinstall.sh"
+       fi
+
+       count=0
+       if [ -f ${C}/preremove.sh    ]; then count+=1 ; fi
+       if [ -f ${C}/${PN}.preremove ]; then count+=1 ; fi
+       if (( $count > 1 ))
+       then
+               error "Can have only one of ${PN}.preremove, preremove.sh"
+       fi
+
+       # do "main" postinstall if present
+       for f in ${PN}.sh ${PN}.postinstall postinstall.sh
+       do
+               if [ -f ${C}/${f} ]
+               then
+                       dodir /etc/postinstall;
+                       cat >> ${D}/etc/postinstall/${PN}.sh < ${C}/${f}
+                       break
+               fi
+       done
 
-       for s in postinstall preremove
+       # do "main" preremove if present
+       #    look for: ${PN}.preremove, preremove.sh
+       for f in ${PN}.preremove preremove.sh
        do
-               if [ -f ${C}/${s}.sh ]
+               if [ -f ${C}/${f} ]
                then
-                       dodir /etc/${s};
-                       cat >> ${D}/etc/${s}/${PN}.sh < ${C}/${s}.sh;
+                       dodir /etc/preremove;
+                       cat >> ${D}/etc/preremove/${PN}.sh < ${C}/${f};
                fi
        done
 
+       # now do other postinstall/preremove scripts if present
+       while [ -n "${pkg_name[${n}]}" ]
+       do
+               for s in postinstall preremove
+               do
+                       if [ -f ${C}/${pkg_name[${n}]}.${s} ]
+                       then
+                               dodir /etc/${s};
+                               cat >> ${D}/etc/${s}/${pkg_name[${n}]}.sh < 
${C}/${pkg_name[${n}]}.${s}
+                       fi
+               done
+               n+=1
+       done            
+
        if [ -f ${C}/profile.d.sh ]
        then
                exeinto /etc/profile.d;
@@ -1058,7 +1194,8 @@
 
 __prepstrip() {
        local exe;
-
+       __maybe_relocate
+       
        cd ${D};
 
        echo "Stripping executables:";
@@ -1076,6 +1213,12 @@
        done
 
        find * -name '*.la' -exec prep_libtool_modules.sh '{}' + || error 
"Libtool module postinstall failed"
+
+       if [ -n "${_ENABLE_RELOCATION}" ]
+       then
+               find * -name '*.la' -exec prep_relocated_libtool_la.sh 
${_RELOCDIR} '{}' + ||\
+                       error "Relocated libtool postinstall failed"
+       fi
 }
 
 src_postinst() {
@@ -1140,8 +1283,9 @@
 
 pkg_binpkg() {
        local -i n=0;
+       __maybe_relocate
 
-       cd ${D};
+       cd ${D}${_RELOCDIR};
 
        __step "Creating binary package(s)";
 
@@ -1176,7 +1320,8 @@
        local tmp1="${T}/tmptar.log";
        local tmp2="${T}/tmpfind.log";
 
-       cd ${D};
+       __maybe_relocate
+       cd ${D}${_RELOCDIR};
        __step "Checking packages for missing or duplicate files";
 
        rm -f ${tmp1} ${tmp2};
@@ -1418,6 +1563,7 @@
 finish() {
        local -i n=0;
 
+       __maybe_relocate
        cd ${top};
 
        __step "Removing work directory in 5 seconds...";
@@ -1443,6 +1589,16 @@
 
        rmdir ${workdir};
 
+       # in relocation mode, mktemp created an actual directory in /tmp.
+       # nothing was ever installed there, but we should clean it up, too.
+       if [ -n "${_ENABLE_RELOCATION}" ]
+       then
+               if [ -d "${_RELOCDIR}" ]
+               then
+                       rmdir ${_RELOCDIR};
+               fi
+       fi
+               
        __step "Finished.";
 }
 
Index: bin/prep_gnu_info.sh
===================================================================
RCS file: /cvsroot/cygwin-ports/cygport/bin/prep_gnu_info.sh,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 prep_gnu_info.sh
--- bin/prep_gnu_info.sh        14 Jun 2006 01:16:16 -0000      1.1.1.1
+++ bin/prep_gnu_info.sh        22 Oct 2006 06:34:07 -0000
@@ -20,12 +20,16 @@
        gzip -q ${infopage}
 done
 
-dodir /etc/postinstall
-for infopage in $(find ${D}/usr/share/info -type f)
-do
-       cat >> ${D}/etc/postinstall/${PN}.sh <<-_EOF
+if [ -z "${SUPPRESS_AUTOMATIC_INSTALLINFO}" ]
+then
+       dodir /etc/postinstall
+       for infopage in $(find ${D}/usr/share/info -type f)
+       do
+               cat >> ${D}/etc/postinstall/${PN}.sh <<-_EOF
                /usr/bin/install-info --dir-file=/usr/share/info/dir 
--info-file=/usr/share/info/${infopage##*/}
                
                _EOF
-done
-echo >> ${D}/etc/postinstall/${PN}.sh
+       done
+       echo >> ${D}/etc/postinstall/${PN}.sh
+fi
+
Index: lib/Makefile.am
===================================================================
RCS file: /cvsroot/cygwin-ports/cygport/lib/Makefile.am,v
retrieving revision 1.5
diff -u -r1.5 Makefile.am
--- lib/Makefile.am     18 Aug 2006 01:36:10 -0000      1.5
+++ lib/Makefile.am     22 Oct 2006 06:34:07 -0000
@@ -21,6 +21,7 @@
        pygtk.cygclass                          \
        python.cygclass                         \
        qt3.cygclass                            \
+       relocatable.cygclass                    \
        ruby.cygclass                           \
        ruby-gnome2.cygclass            \
        svn.cygclass                            \
#!/bin/bash
################################################################################
#
# prep_relocated_libtool_la.sh - removes ${_RELOCDIR} references from .la files
# Part of cygport - Cygwin packaging application
# Copyright (C) 2006 Charles Wilson
# Distributed under the terms of the GNU General Public License v2
#
# Invoke as:
#   if [ -n "${_ENABLE_RELOCATION}" ]
#   then
#      prep_relocated_libtool_la.sh ${_RELOCDIR} list-of-la-files
#   fi
#
################################################################################
set -e

declare -r ltversion="$(/usr/bin/libtool --version | /bin/grep ltmain.sh)"
_RELOCDIR=$1
shift

if [ -z "${_RELOCDIR}" ]
then
        echo "internal error: bad call to prep_relocated_libtool_la.sh: 
_RELOCDIR empty"
        exit 1
fi
case "${_RELOCDIR}" in
        *.la  )
                echo "internal error: bad call to prep_relocated_libtool_la.sh: 
_RELOCDIR=${_RELOCDIR}"
                exit 1
                ;;
        /* ) ;;
        *  )
                echo "internal error: _RELOCDIR must be an absolute path: 
_RELOCDIR=${_RELOCDIR}"
                exit 1
                ;;
esac

echo "Fixing relocated libtool modules:"

for lib_la in "[EMAIL PROTECTED]"
do
        if [ ! -f ${lib_la} ]
        then
                error "file ${lib_la} does not exist!"
        fi

        if ! grep -q "libtool library file" ${lib_la}
        then
                continue    # go to next iteration of for loop
        fi

        echo "        ${lib_la}"
        new_lib_la=${lib_la}.new
        cat ${lib_la} | sed -e "/^dependency_libs=/s,${_RELOCDIR},,g" \
                -e "/^libdir=/s,${_RELOCDIR},,g" > ${new_lib_la}
        mv ${new_lib_la} ${lib_la}
        

done

################################################################################
#
# relocatable.cygclass - functions for building packages that use Bruno Haible's
#                        relocation framework (e.g. libiconv and gettext, with
#                        --enable-relocatable)
#
# Copyright (C) 2006 Charles Wilson
# Distributed under the terms of the GNU General Public License v2
#
################################################################################

_ENABLE_RELOCATION=1
relocatable_conf() {
        cygconf
}

relocatable_install() {
        cyginstall
}

### the following do not have support for dir changes, disallow

dolib()   { error "/usr/lib/cygport/bin/dolib needs dir change support." ; }
dobin()   { error "/usr/lib/cygport/bin/dobin needs dir change support." ; }
doman()   { error "/usr/lib/cygport/bin/doman needs dir change support." ; }
dosbin()  { error "/usr/lib/cygport/bin/dosbin needs dir change support." ; }
doicon()  { error "/usr/lib/cygport/bin/doicon needs dir change support." ; }
domenu()  { error "/usr/lib/cygport/bin/domenu needs dir change support." ; }
newbin()  { error "/usr/lib/cygport/bin/newbin needs dir change support." ; }
newman()  { error "/usr/lib/cygport/bin/newman needs dir change support." ; }
newicon() { error "/usr/lib/cygport/bin/newicon needs dir change support." ; }
newmenu() { error "/usr/lib/cygport/bin/newmenu needs dir change support." ; }

### use dosym with care: both arguments must be specified with ${RELOCDIR}
### ditto for dodir: argument must be specified with ${RELOCDIR}


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Reply via email to