This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] cygport


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} "${@}" || 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 \
 				${@} \
 				|| 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 "${@}"
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/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]