Bug 28155 - [patch] DESTDIR is used incorrectly in bsd.port.mk
Summary: [patch] DESTDIR is used incorrectly in bsd.port.mk
Status: Closed FIXED
Alias: None
Product: Ports & Packages
Classification: Unclassified
Component: Individual Port(s) (show other bugs)
Version: Latest
Hardware: Any Any
: Normal Affects Only Me
Assignee: Port Management Team
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2001-06-14 22:30 UTC by John E. Hein
Modified: 2006-07-28 22:10 UTC (History)
0 users

See Also:


Attachments
file.diff (4.13 KB, patch)
2001-06-14 22:30 UTC, John E. Hein
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description John E. Hein 2001-06-14 22:30:02 UTC
DESTDIR should not interfere with PREFIX.  PREFIX is really the run-time
location of the port.  DESTDIR is where it gets installed.  These may
not be the same thing.

Unfortunately, bsd.port.mk simply prefixes LOCALBASE, X11BASE & LINUXBASE
with DESTDIR.  If PREFIX is not specified to override these values, PREFIX
will contain DESTDIR.

Not only bsd.port.mk, but many port Makefiles are broken in this regard.
For example, many post-install targets specify something like:

	${INSTALL_PROGRAM} ${WRKSRC}/foo ${PREFIX}/bin

They should probably read:

	${INSTALL_PROGRAM} ${WRKSRC}/foo ${DESTDIR}/${PREFIX}/bin


But, before we fix the ports, we have to fix bsd.port.mk
The included patch does that.
If anyone seriously tries to use DESTDIR for its intended use, many
 ports won't work anyway.

Please commit the patch to bsd.port.mk
Feel free to try it out first.  Send me feedback.  Ask for its
 commit in freebsd-ports.  Pester portmgr@FreeBSD.org
It's a large step in fixing the problem with the ports system's inability
 to install in non-standard paths.  It's time we fixed this.

Fix: First, give a heads up that the following patch will be
 applied in, say, a week or two.
Notify maintainers about it and have them fix their ports
 to handle DESTDIR & PREFIX correctly in preparation for
 this commit.
Then apply the following patch to bsd.port.mk and commit.
Then tell maintainers to commit their fixed ports.


$ cvs diff -u bsd.port.mk
How-To-Repeat: 
Let's suppose you want to install a port for system B on a removable drive
 bay on system A...

sudo mount /dev/da1s1g /mnt_B/usr
sudo mount /dev/da1s1a /mnt_B/root

Now I want to install, say, the glib port to /mnt_B/usr/local.

cd /usr/ports/devel/glib12
sudo make DESTDIR=/mnt_B PKG_DBDIR=/mnt_B/root/var/db/pkg install

umount /mnt_B/root
umount /mnt_B/usr

Now, move the disk to system B and boot it.
Now, run /usr/local/bin/glib-config --cflags and get:

-I/mnt_B/usr/local/include/glib12

That is wrong.  It should read -I/usr/local/include/glib12
Comment 1 Steve Price freebsd_committer freebsd_triage 2001-06-17 19:03:41 UTC
Responsible Changed
From-To: freebsd-ports->portmgr

Over to portmgr for a look see.
Comment 2 John E. Hein 2001-06-20 22:34:00 UTC
The first patch had one small bit missing.  It failed to put DESTDIR
 in the mtree command.  The revised patch below fixes this (in the last
 hunk, #7).

 note: These DESTDIR fixes don't work when PREFIX is relative and DESTDIR
        is empty.  The dest/prefix combos should probably be written:
        ${DESTDIR}${PREFIX} without the intervening /, and leave it up
        to users to append a trailing / to DESTDIR if needed.
       Or we could do something that will add a trailing / to DESTDIR
        if it is non-empty, but I haven't figured out a good way
        to do this in a Makefile yet.

$ cvs diff -u bsd.port.mk
Index: bsd.port.mk
===================================================================
RCS file: /base/FreeBSD-CVS/ports/Mk/bsd.port.mk,v
retrieving revision 1.367
diff -u -r1.367 bsd.port.mk
--- bsd.port.mk	2001/05/23 02:46:52	1.367
+++ bsd.port.mk	2001/06/20 14:37:54
@@ -600,9 +600,22 @@
 .else
 PORTSDIR?=		/usr/ports
 .endif
-LOCALBASE?=		${DESTDIR}/usr/local
-X11BASE?=		${DESTDIR}/usr/X11R6
-LINUXBASE?=		${DESTDIR}/compat/linux
+LOCALBASE?=		/usr/local
+X11BASE?=		/usr/X11R6
+LINUXBASE?=		/compat/linux
+.if defined(DESTDIR)
+.if defined(USE_GMAKE)
+# Tell gmake makefiles to override any local definition of DESTDIR with
+# our definition.
+MAKE_ARGS+=		DESTDIR=${DESTDIR}
+.else
+# FreeBSD's make is not the same as gmake in being able to override VAR=FOO
+# style definitions in the makefile with VAR=SOMETHING_ELSE passed on the
+# command line to make, but we can use -E to get similar behavior.
+MAKE_ARGS+=		-E DESTDIR
+MAKE_ENV+=		DESTDIR=${DESTDIR}
+.endif
+.endif
 DISTDIR?=		${PORTSDIR}/distfiles
 _DISTDIR?=		${DISTDIR}/${DIST_SUBDIR}
 .if defined(USE_BZIP2)
@@ -1064,7 +1077,7 @@
 PKG_DELETE?=	/usr/sbin/pkg_delete
 PKG_INFO?=		/usr/sbin/pkg_info
 .if !defined(PKG_ARGS)
-PKG_ARGS=		-v -c ${COMMENT} -d ${DESCR} -f ${TMPPLIST} -p ${PREFIX} -P "`${MAKE} package-depends | ${GREP} -v -E ${PKG_IGNORE_DEPENDS} | sort -u`" ${EXTRA_PKG_ARGS}
+PKG_ARGS=		-v -c ${COMMENT} -d ${DESCR} -f ${TMPPLIST} -p ${PREFIX} -s ${DESTDIR}/${PREFIX} -P "`${MAKE} package-depends | ${GREP} -v -E ${PKG_IGNORE_DEPENDS} | sort -u`" ${EXTRA_PKG_ARGS}
 .if exists(${PKGINSTALL})
 PKG_ARGS+=		-i ${PKGINSTALL}
 .endif
@@ -1271,7 +1284,8 @@
 		  WRKDIR=${WRKDIR} WRKSRC=${WRKSRC} PATCHDIR=${PATCHDIR} \
 		  SCRIPTDIR=${SCRIPTDIR} FILESDIR=${FILESDIR} \
 		  PORTSDIR=${PORTSDIR} DEPENDS="${DEPENDS}" \
-		  PREFIX=${PREFIX} LOCALBASE=${LOCALBASE} X11BASE=${X11BASE}
+		  PREFIX=${PREFIX} LOCALBASE=${LOCALBASE} X11BASE=${X11BASE} \
+		  DESTDIR=${DESTDIR}
 
 .if defined(BATCH)
 SCRIPTS_ENV+=	BATCH=yes
@@ -1302,7 +1316,7 @@
 		else \
 			{ print "broken"; exit; } \
 	} \
-  }' | ${SED} -e 's \([^/ ][^ ]*\.\(.\)[^. ]*\) $${MAN\2PREFIX}/man/$$$$$$$${__lang}/man\2/\1.gzg' -e 's/ //g' -e 's/MANlPREFIX/MANLPREFIX/g' -e 's/MANnPREFIX/MANNPREFIX/g'
+  }' | ${SED} -e 's \([^/ ][^ ]*\.\(.\)[^. ]*\) ${DESTDIR}/$${MAN\2PREFIX}/man/$$$$$$$${__lang}/man\2/\1.gzg' -e 's/ //g' -e 's/MANlPREFIX/MANLPREFIX/g' -e 's/MANnPREFIX/MANNPREFIX/g'
 .if ${__pmlinks:Mbroken} == "broken"
 .BEGIN:
 	@${ECHO} "${PKGNAME}: Unable to parse MLINKS."
@@ -1322,30 +1336,31 @@
 
 .for sect in 1 2 3 4 5 6 7 8 9
 .if defined(MAN${sect})
-_MANPAGES+=	${MAN${sect}:S%^%${MAN${sect}PREFIX}/man/${lang}/man${sect}/%}
+JUNK=1
+_MANPAGES+=	${MAN${sect}:S%^%${DESTDIR}/${MAN${sect}PREFIX}/man/${lang}/man${sect}/%}
 .endif
 .endfor
 
 .if defined(MANL)
-_MANPAGES+=	${MANL:S%^%${MANLPREFIX}/man/${lang}/manl/%}
+_MANPAGES+=	${MANL:S%^%${DESTDIR}/${MANLPREFIX}/man/${lang}/manl/%}
 .endif
 
 .if defined(MANN)
-_MANPAGES+=	${MANN:S%^%${MANNPREFIX}/man/${lang}/mann/%}
+_MANPAGES+=	${MANN:S%^%${DESTDIR}/${MANNPREFIX}/man/${lang}/mann/%}
 .endif
 
 .endfor
 
 .if defined(_MLINKS) && make(generate-plist)
-_TMLINKS!=	${ECHO} ${_MLINKS} | ${AWK} '{for (i=2; i<=NF; i+=2) print $$i}'
+_TMLINKS!=	${ECHO} ${_MLINKS} | ${AWK} '{for (i=2; i<=NF; i+=2) print $$i}' | ${SED} 's,^${DESTDIR}/,,'
 .else
 _TMLINKS=
 .endif
 
 .if defined(_MANPAGES) && defined(NOMANCOMPRESS)
-__MANPAGES:=	${_MANPAGES:S^${PREFIX}/^^:S/""//:S^//^/^g}
+__MANPAGES:=	${_MANPAGES:S^${DESTDIR}/^^:S^${PREFIX}/^^:S/""//:S^//^/^g}
 .elif defined(_MANPAGES)
-__MANPAGES:=	${_MANPAGES:S^${PREFIX}/^^:S/""//:S^//^/^g:S/$/.gz/}
+__MANPAGES:=	${_MANPAGES:S^${DESTDIR}/^^:S^${PREFIX}/^^:S/""//:S^//^/^g:S/$/.gz/}
 .endif
 
 .if defined(_MANPAGES) && ${MANCOMPRESSED} == "yes"
@@ -1962,10 +1977,10 @@
 .if make(real-install)
 	@${MKDIR} ${PREFIX}
 	@if [ `id -u` != 0 ]; then \
-		if [ -w ${PREFIX}/ ]; then \
+		if [ -w ${DESTDIR}/${PREFIX}/ ]; then \
 			${ECHO_MSG} "Warning: not superuser, you may get some errors during installation."; \
 		else \
-			${ECHO_MSG} "Error: ${PREFIX}/ not writable."; \
+			${ECHO_MSG} "Error: ${DESTDIR}/${PREFIX}/ not writable."; \
 			${FALSE}; \
 		fi; \
 	fi
@@ -1976,7 +1991,7 @@
 			${ECHO} "Copy it from a suitable location (e.g., /usr/src/etc/mtree) and try again."; \
 			exit 1; \
 		else \
-			${MTREE_CMD} ${MTREE_ARGS} ${PREFIX}/ >/dev/null; \
+			${MTREE_CMD} ${MTREE_ARGS} ${DESTDIR}/${PREFIX}/ >/dev/null; \
 		fi; \
 	else \
 		${ECHO_MSG} "Warning: not superuser, can't run mtree."; \
Comment 3 John E. Hein 2001-07-21 00:32:42 UTC
I've updated the patch to
 1) match the latest bsd.port.mk in the repository
 2) change occurrences of ${DESTDIR}/${PREFIX} to the more
      standard ${DESTDIR}${PREFIX}  (see 'note:' in my last
      followup discussing this)

For #2, I also added a check to make sure DESTDIR is an absolute
  path (otherwise, when make is invoked down in work/..., it points
  to the wrong place) and to make sure DESTDIR ends in a / if PREFIX
  doesn't start with a / so the paths don't run together.
  Set IGNORE_ABSPATH_CHECKS=yes to ignore these checks.


Here is the revised patch:

$ cvs diff -u bsd.port.mk
Index: bsd.port.mk
===================================================================
RCS file: /base/FreeBSD-CVS/ports/Mk/bsd.port.mk,v
retrieving revision 1.372
diff -u -r1.372 bsd.port.mk
--- bsd.port.mk	2001/07/10 07:50:17	1.372
+++ bsd.port.mk	2001/07/20 23:12:03
@@ -606,9 +606,41 @@
 .else
 PORTSDIR?=		/usr/ports
 .endif
-LOCALBASE?=		${DESTDIR}/usr/local
-X11BASE?=		${DESTDIR}/usr/X11R6
-LINUXBASE?=		${DESTDIR}/compat/linux
+LOCALBASE?=		/usr/local
+X11BASE?=		/usr/X11R6
+LINUXBASE?=		/compat/linux
+
+IGNORE_ABSPATH_CHECKS?=	no
+.if (${IGNORE_ABSPATH_CHECKS:L} != yes)
+.if defined(DESTDIR)
+.if (${DESTDIR} != "") && (${DESTDIR:C,(^.).*,\1,} != "/")
+.BEGIN:
+	@${ECHO} "DESTDIR must be defined as an absolute path so that when 'make'"
+	@${ECHO} "is invoked in the work area DESTDIR points to the right place."
+	@${FALSE}
+.elif (${DESTDIR} != "") && (${DESTDIR:C,^.*(/)$$,\1,} != "/") \
+	 && (${PREFIX:C,(^.).*,\1,} != "/")
+.BEGIN:
+	@${ECHO} "DESTDIR must be defined with a trailing slash if PREFIX is not\
+				an absolute path."
+	@${FALSE}
+.endif
+.endif
+.endif
+
+.if defined(DESTDIR)
+.if defined(USE_GMAKE)
+# Tell gmake makefiles to override any local definition of DESTDIR with
+# our definition.
+MAKE_ARGS+=		DESTDIR=${DESTDIR}
+.else
+# FreeBSD's make is not the same as gmake in being able to override VAR=FOO
+# style definitions in the makefile with VAR=SOMETHING_ELSE passed on the
+# command line to make, but we can use -E to get similar behavior.
+MAKE_ARGS+=		-E DESTDIR
+MAKE_ENV+=		DESTDIR=${DESTDIR}
+.endif
+.endif
 DISTDIR?=		${PORTSDIR}/distfiles
 _DISTDIR?=		${DISTDIR}/${DIST_SUBDIR}
 .if defined(USE_BZIP2)
@@ -1070,7 +1102,7 @@
 PKG_DELETE?=	/usr/sbin/pkg_delete
 PKG_INFO?=		/usr/sbin/pkg_info
 .if !defined(PKG_ARGS)
-PKG_ARGS=		-v -c ${COMMENT} -d ${DESCR} -f ${TMPPLIST} -p ${PREFIX} -P "`${MAKE} package-depends | ${GREP} -v -E ${PKG_IGNORE_DEPENDS} | sort -u`" ${EXTRA_PKG_ARGS}
+PKG_ARGS=		-v -c ${COMMENT} -d ${DESCR} -f ${TMPPLIST} -p ${PREFIX} -s ${DESTDIR}${PREFIX} -P "`${MAKE} package-depends | ${GREP} -v -E ${PKG_IGNORE_DEPENDS} | sort -u`" ${EXTRA_PKG_ARGS}
 .if exists(${PKGINSTALL})
 PKG_ARGS+=		-i ${PKGINSTALL}
 .endif
@@ -1277,7 +1309,8 @@
 		  WRKDIR=${WRKDIR} WRKSRC=${WRKSRC} PATCHDIR=${PATCHDIR} \
 		  SCRIPTDIR=${SCRIPTDIR} FILESDIR=${FILESDIR} \
 		  PORTSDIR=${PORTSDIR} DEPENDS="${DEPENDS}" \
-		  PREFIX=${PREFIX} LOCALBASE=${LOCALBASE} X11BASE=${X11BASE}
+		  PREFIX=${PREFIX} LOCALBASE=${LOCALBASE} X11BASE=${X11BASE} \
+		  DESTDIR=${DESTDIR}
 
 .if defined(BATCH)
 SCRIPTS_ENV+=	BATCH=yes
@@ -1308,7 +1341,7 @@
 		else \
 			{ print "broken"; exit; } \
 	} \
-  }' | ${SED} -e 's \([^/ ][^ ]*\.\(.\)[^. ]*\) $${MAN\2PREFIX}/man/$$$$$$$${__lang}/man\2/\1.gzg' -e 's/ //g' -e 's/MANlPREFIX/MANLPREFIX/g' -e 's/MANnPREFIX/MANNPREFIX/g'
+  }' | ${SED} -e 's \([^/ ][^ ]*\.\(.\)[^. ]*\) ${DESTDIR}$${MAN\2PREFIX}/man/$$$$$$$${__lang}/man\2/\1.gzg' -e 's/ //g' -e 's/MANlPREFIX/MANLPREFIX/g' -e 's/MANnPREFIX/MANNPREFIX/g'
 .if ${__pmlinks:Mbroken} == "broken"
 .BEGIN:
 	@${ECHO} "${PKGNAME}: Unable to parse MLINKS."
@@ -1328,30 +1361,31 @@
 
 .for sect in 1 2 3 4 5 6 7 8 9
 .if defined(MAN${sect})
-_MANPAGES+=	${MAN${sect}:S%^%${MAN${sect}PREFIX}/man/${lang}/man${sect}/%}
+JUNK=1
+_MANPAGES+=	${MAN${sect}:S%^%${DESTDIR}${MAN${sect}PREFIX}/man/${lang}/man${sect}/%}
 .endif
 .endfor
 
 .if defined(MANL)
-_MANPAGES+=	${MANL:S%^%${MANLPREFIX}/man/${lang}/manl/%}
+_MANPAGES+=	${MANL:S%^%${DESTDIR}${MANLPREFIX}/man/${lang}/manl/%}
 .endif
 
 .if defined(MANN)
-_MANPAGES+=	${MANN:S%^%${MANNPREFIX}/man/${lang}/mann/%}
+_MANPAGES+=	${MANN:S%^%${DESTDIR}${MANNPREFIX}/man/${lang}/mann/%}
 .endif
 
 .endfor
 
 .if defined(_MLINKS) && make(generate-plist)
-_TMLINKS!=	${ECHO} ${_MLINKS} | ${AWK} '{for (i=2; i<=NF; i+=2) print $$i}'
+_TMLINKS!=	${ECHO} ${_MLINKS} | ${AWK} '{for (i=2; i<=NF; i+=2) print $$i}' | ${SED} 's,^${DESTDIR},,'
 .else
 _TMLINKS=
 .endif
 
 .if defined(_MANPAGES) && defined(NOMANCOMPRESS)
-__MANPAGES:=	${_MANPAGES:S^${PREFIX}/^^:S/""//:S^//^/^g}
+__MANPAGES:=	${_MANPAGES:S^${DESTDIR}^^:S^${PREFIX}/^^:S/""//:S^//^/^g}
 .elif defined(_MANPAGES)
-__MANPAGES:=	${_MANPAGES:S^${PREFIX}/^^:S/""//:S^//^/^g:S/$/.gz/}
+__MANPAGES:=	${_MANPAGES:S^${DESTDIR}^^:S^${PREFIX}/^^:S/""//:S^//^/^g:S/$/.gz/}
 .endif
 
 .if defined(_MANPAGES) && ${MANCOMPRESSED} == "yes"
@@ -1969,12 +2003,12 @@
 	@cd ${.CURDIR} && ${MAKE} ${__softMAKEFLAGS} run-depends lib-depends
 .endif
 .if make(real-install)
-	@${MKDIR} ${PREFIX}
+	@${MKDIR} ${DESTDIR}${PREFIX}
 	@if [ `id -u` != 0 ]; then \
-		if [ -w ${PREFIX}/ ]; then \
+		if [ -w ${DESTDIR}${PREFIX}/ ]; then \
 			${ECHO_MSG} "Warning: not superuser, you may get some errors during installation."; \
 		else \
-			${ECHO_MSG} "Error: ${PREFIX}/ not writable."; \
+			${ECHO_MSG} "Error: ${DESTDIR}${PREFIX}/ not writable."; \
 			${FALSE}; \
 		fi; \
 	fi
@@ -1985,7 +2019,7 @@
 			${ECHO} "Copy it from a suitable location (e.g., /usr/src/etc/mtree) and try again."; \
 			exit 1; \
 		else \
-			${MTREE_CMD} ${MTREE_ARGS} ${PREFIX}/ >/dev/null; \
+			${MTREE_CMD} ${MTREE_ARGS} ${DESTDIR}${PREFIX}/ >/dev/null; \
 		fi; \
 	else \
 		${ECHO_MSG} "Warning: not superuser, can't run mtree."; \
Comment 4 John E. Hein 2001-07-27 17:47:10 UTC
I've updated the patch to
 1) match the latest bsd.port.mk in the repository (1.373)
 2) check to make sure PREFIX is defined before referencing
      it with :C (:C doesn't like undefined variables)

Here is the revised patch:

$ cvs diff -u bsd.port.mk
Index: bsd.port.mk
===================================================================
RCS file: /base/FreeBSD-CVS/ports/Mk/bsd.port.mk,v
retrieving revision 1.373
diff -u -r1.373 bsd.port.mk
--- bsd.port.mk	2001/07/25 18:10:16	1.373
+++ bsd.port.mk	2001/07/27 16:42:59
@@ -606,9 +606,43 @@
 .else
 PORTSDIR?=		/usr/ports
 .endif
-LOCALBASE?=		${DESTDIR}/usr/local
-X11BASE?=		${DESTDIR}/usr/X11R6
-LINUXBASE?=		${DESTDIR}/compat/linux
+LOCALBASE?=		/usr/local
+X11BASE?=		/usr/X11R6
+LINUXBASE?=		/compat/linux
+
+IGNORE_ABSPATH_CHECKS?=	no
+.if (${IGNORE_ABSPATH_CHECKS:L} != yes)
+.if defined(DESTDIR)
+.if (${DESTDIR} != "") && (${DESTDIR:C,(^.).*,\1,} != "/")
+.BEGIN:
+	@${ECHO} "DESTDIR must be defined as an absolute path so that when 'make'"
+	@${ECHO} "is invoked in the work area DESTDIR points to the right place."
+	@${FALSE}
+.elif defined(PREFIX)
+.if (${DESTDIR} != "") && (${DESTDIR:C,^.*(/)$$,\1,} != "/") \
+	 && (${PREFIX:C,(^.).*,\1,} != "/")
+.BEGIN:
+	@${ECHO} "DESTDIR must be defined with a trailing slash if PREFIX is not\
+				an absolute path."
+	@${FALSE}
+.endif
+.endif
+.endif
+.endif
+
+.if defined(DESTDIR)
+.if defined(USE_GMAKE)
+# Tell gmake makefiles to override any local definition of DESTDIR with
+# our definition.
+MAKE_ARGS+=		DESTDIR=${DESTDIR}
+.else
+# FreeBSD's make is not the same as gmake in being able to override VAR=FOO
+# style definitions in the makefile with VAR=SOMETHING_ELSE passed on the
+# command line to make, but we can use -E to get similar behavior.
+MAKE_ARGS+=		-E DESTDIR
+MAKE_ENV+=		DESTDIR=${DESTDIR}
+.endif
+.endif
 DISTDIR?=		${PORTSDIR}/distfiles
 _DISTDIR?=		${DISTDIR}/${DIST_SUBDIR}
 .if defined(USE_BZIP2)
@@ -1073,7 +1107,7 @@
 PKG_DELETE?=	/usr/sbin/pkg_delete
 PKG_INFO?=		/usr/sbin/pkg_info
 .if !defined(PKG_ARGS)
-PKG_ARGS=		-v -c ${COMMENT} -d ${DESCR} -f ${TMPPLIST} -p ${PREFIX} -P "`${MAKE} package-depends | ${GREP} -v -E ${PKG_IGNORE_DEPENDS} | sort -u`" ${EXTRA_PKG_ARGS}
+PKG_ARGS=		-v -c ${COMMENT} -d ${DESCR} -f ${TMPPLIST} -p ${PREFIX} -s ${DESTDIR}${PREFIX} -P "`${MAKE} package-depends | ${GREP} -v -E ${PKG_IGNORE_DEPENDS} | sort -u`" ${EXTRA_PKG_ARGS}
 .if exists(${PKGINSTALL})
 PKG_ARGS+=		-i ${PKGINSTALL}
 .endif
@@ -1280,7 +1314,8 @@
 		  WRKDIR=${WRKDIR} WRKSRC=${WRKSRC} PATCHDIR=${PATCHDIR} \
 		  SCRIPTDIR=${SCRIPTDIR} FILESDIR=${FILESDIR} \
 		  PORTSDIR=${PORTSDIR} DEPENDS="${DEPENDS}" \
-		  PREFIX=${PREFIX} LOCALBASE=${LOCALBASE} X11BASE=${X11BASE}
+		  PREFIX=${PREFIX} LOCALBASE=${LOCALBASE} X11BASE=${X11BASE} \
+		  DESTDIR=${DESTDIR}
 
 .if defined(BATCH)
 SCRIPTS_ENV+=	BATCH=yes
@@ -1311,7 +1346,7 @@
 		else \
 			{ print "broken"; exit; } \
 	} \
-  }' | ${SED} -e 's \([^/ ][^ ]*\.\(.\)[^. ]*\) $${MAN\2PREFIX}/man/$$$$$$$${__lang}/man\2/\1.gzg' -e 's/ //g' -e 's/MANlPREFIX/MANLPREFIX/g' -e 's/MANnPREFIX/MANNPREFIX/g'
+  }' | ${SED} -e 's \([^/ ][^ ]*\.\(.\)[^. ]*\) ${DESTDIR}$${MAN\2PREFIX}/man/$$$$$$$${__lang}/man\2/\1.gzg' -e 's/ //g' -e 's/MANlPREFIX/MANLPREFIX/g' -e 's/MANnPREFIX/MANNPREFIX/g'
 .if ${__pmlinks:Mbroken} == "broken"
 .BEGIN:
 	@${ECHO} "${PKGNAME}: Unable to parse MLINKS."
@@ -1331,30 +1366,31 @@
 
 .for sect in 1 2 3 4 5 6 7 8 9
 .if defined(MAN${sect})
-_MANPAGES+=	${MAN${sect}:S%^%${MAN${sect}PREFIX}/man/${lang}/man${sect}/%}
+JUNK=1
+_MANPAGES+=	${MAN${sect}:S%^%${DESTDIR}${MAN${sect}PREFIX}/man/${lang}/man${sect}/%}
 .endif
 .endfor
 
 .if defined(MANL)
-_MANPAGES+=	${MANL:S%^%${MANLPREFIX}/man/${lang}/manl/%}
+_MANPAGES+=	${MANL:S%^%${DESTDIR}${MANLPREFIX}/man/${lang}/manl/%}
 .endif
 
 .if defined(MANN)
-_MANPAGES+=	${MANN:S%^%${MANNPREFIX}/man/${lang}/mann/%}
+_MANPAGES+=	${MANN:S%^%${DESTDIR}${MANNPREFIX}/man/${lang}/mann/%}
 .endif
 
 .endfor
 
 .if defined(_MLINKS) && make(generate-plist)
-_TMLINKS!=	${ECHO} ${_MLINKS} | ${AWK} '{for (i=2; i<=NF; i+=2) print $$i}'
+_TMLINKS!=	${ECHO} ${_MLINKS} | ${AWK} '{for (i=2; i<=NF; i+=2) print $$i}' | ${SED} 's,^${DESTDIR},,'
 .else
 _TMLINKS=
 .endif
 
 .if defined(_MANPAGES) && defined(NOMANCOMPRESS)
-__MANPAGES:=	${_MANPAGES:S^${PREFIX}/^^:S/""//:S^//^/^g}
+__MANPAGES:=	${_MANPAGES:S^${DESTDIR}^^:S^${PREFIX}/^^:S/""//:S^//^/^g}
 .elif defined(_MANPAGES)
-__MANPAGES:=	${_MANPAGES:S^${PREFIX}/^^:S/""//:S^//^/^g:S/$/.gz/}
+__MANPAGES:=	${_MANPAGES:S^${DESTDIR}^^:S^${PREFIX}/^^:S/""//:S^//^/^g:S/$/.gz/}
 .endif
 
 .if defined(_MANPAGES) && ${MANCOMPRESSED} == "yes"
@@ -1972,12 +2008,12 @@
 	@cd ${.CURDIR} && ${MAKE} ${__softMAKEFLAGS} run-depends lib-depends
 .endif
 .if make(real-install)
-	@${MKDIR} ${PREFIX}
+	@${MKDIR} ${DESTDIR}${PREFIX}
 	@if [ `id -u` != 0 ]; then \
-		if [ -w ${PREFIX}/ ]; then \
+		if [ -w ${DESTDIR}${PREFIX}/ ]; then \
 			${ECHO_MSG} "Warning: not superuser, you may get some errors during installation."; \
 		else \
-			${ECHO_MSG} "Error: ${PREFIX}/ not writable."; \
+			${ECHO_MSG} "Error: ${DESTDIR}${PREFIX}/ not writable."; \
 			${FALSE}; \
 		fi; \
 	fi
@@ -1988,7 +2024,7 @@
 			${ECHO} "Copy it from a suitable location (e.g., /usr/src/etc/mtree) and try again."; \
 			exit 1; \
 		else \
-			${MTREE_CMD} ${MTREE_ARGS} ${PREFIX}/ >/dev/null; \
+			${MTREE_CMD} ${MTREE_ARGS} ${DESTDIR}${PREFIX}/ >/dev/null; \
 		fi; \
 	else \
 		${ECHO_MSG} "Warning: not superuser, can't run mtree."; \
Comment 5 John E. Hein 2001-09-26 00:31:51 UTC
 I've updated the patch to
  1) match the latest bsd.port.mk in the repository (1.381, 20010923)
  2) move the DESTDIR fixes to the "post-makefile" section so we define
      the right MAKE_ARGS based on whether USE_GMAKE is set or not.
      In some ports (e.g., math/fftw), USE_GMAKE isn't set until after
      bsd.port.pre.mk is included.

Here is the revised patch:

$ cvs diff -u bsd.port.mk
Index: bsd.port.mk
===================================================================
RCS file: /base/FreeBSD-CVS/ports/Mk/bsd.port.mk,v
retrieving revision 1.381
diff -u -r1.381 bsd.port.mk
--- bsd.port.mk	2001/09/23 00:35:08	1.381
+++ bsd.port.mk	2001/09/25 23:23:19
@@ -608,9 +608,9 @@
 .else
 PORTSDIR?=		/usr/ports
 .endif
-LOCALBASE?=		${DESTDIR}/usr/local
-X11BASE?=		${DESTDIR}/usr/X11R6
-LINUXBASE?=		${DESTDIR}/compat/linux
+LOCALBASE?=		/usr/local
+X11BASE?=		/usr/X11R6
+LINUXBASE?=		/compat/linux
 DISTDIR?=		${PORTSDIR}/distfiles
 _DISTDIR?=		${DISTDIR}/${DIST_SUBDIR}
 .if defined(USE_BZIP2)
@@ -735,6 +735,42 @@
 
 _POSTMKINCLUDED=	yes
 
+IGNORE_ABSPATH_CHECKS?=	no
+.if (${IGNORE_ABSPATH_CHECKS:L} != yes)
+.if defined(DESTDIR)
+
+.if (${DESTDIR} != "") && (${DESTDIR:C,(^.).*,\1,} != "/")
+.BEGIN:
+	@${ECHO} "DESTDIR must be defined as an absolute path so that when 'make'"
+	@${ECHO} "is invoked in the work area DESTDIR points to the right place."
+	@${FALSE}
+.elif defined(PREFIX)
+.if (${DESTDIR} != "") && (${DESTDIR:C,^.*(/)$$,\1,} != "/") \
+	&& (${PREFIX:C,(^.).*,\1,} != "/")
+.BEGIN:
+	@${ECHO} "DESTDIR must be defined with a trailing slash if PREFIX is not\
+				an absolute path."
+	@${FALSE}
+.endif
+.endif
+
+.endif
+.endif	# IGNORE_ABSPATH_CHECKS != yes
+
+.if defined(DESTDIR)
+.if defined(USE_GMAKE)
+# Tell gmake makefiles to override any local definition of DESTDIR with
+# our definition.
+MAKE_ARGS+=		DESTDIR=${DESTDIR}
+.else
+# FreeBSD's make is not the same as gmake in being able to override VAR=FOO
+# style definitions in the makefile with VAR=SOMETHING_ELSE passed on the
+# command line to make, but we can use -E to get similar behavior.
+MAKE_ARGS+=		-E DESTDIR
+MAKE_ENV+=		DESTDIR=${DESTDIR}
+.endif
+.endif
+
 WRKDIR?=		${WRKDIRPREFIX}${.CURDIR}/work
 .if defined(NO_WRKSUBDIR)
 WRKSRC?=		${WRKDIR}
@@ -1081,7 +1117,7 @@
 PKG_DELETE?=	/usr/sbin/pkg_delete
 PKG_INFO?=		/usr/sbin/pkg_info
 .if !defined(PKG_ARGS)
-PKG_ARGS=		-v -c ${COMMENT} -d ${DESCR} -f ${TMPPLIST} -p ${PREFIX} -P "`${MAKE} package-depends | ${GREP} -v -E ${PKG_IGNORE_DEPENDS} | sort -u`" ${EXTRA_PKG_ARGS}
+PKG_ARGS=		-v -c ${COMMENT} -d ${DESCR} -f ${TMPPLIST} -p ${PREFIX} -s ${DESTDIR}${PREFIX} -P "`${MAKE} package-depends | ${GREP} -v -E ${PKG_IGNORE_DEPENDS} | sort -u`" ${EXTRA_PKG_ARGS}
 .if exists(${PKGINSTALL})
 PKG_ARGS+=		-i ${PKGINSTALL}
 .endif
@@ -1288,7 +1324,8 @@
 		  WRKDIR=${WRKDIR} WRKSRC=${WRKSRC} PATCHDIR=${PATCHDIR} \
 		  SCRIPTDIR=${SCRIPTDIR} FILESDIR=${FILESDIR} \
 		  PORTSDIR=${PORTSDIR} DEPENDS="${DEPENDS}" \
-		  PREFIX=${PREFIX} LOCALBASE=${LOCALBASE} X11BASE=${X11BASE}
+		  PREFIX=${PREFIX} LOCALBASE=${LOCALBASE} X11BASE=${X11BASE} \
+		  DESTDIR=${DESTDIR}
 
 .if defined(BATCH)
 SCRIPTS_ENV+=	BATCH=yes
@@ -1319,7 +1356,7 @@
 		else \
 			{ print "broken"; exit; } \
 	} \
-  }' | ${SED} -e 's \([^/ ][^ ]*\.\(.\)[^. ]*\) $${MAN\2PREFIX}/man/$$$$$$$${__lang}/man\2/\1.gzg' -e 's/ //g' -e 's/MANlPREFIX/MANLPREFIX/g' -e 's/MANnPREFIX/MANNPREFIX/g'
+  }' | ${SED} -e 's \([^/ ][^ ]*\.\(.\)[^. ]*\) ${DESTDIR}$${MAN\2PREFIX}/man/$$$$$$$${__lang}/man\2/\1.gzg' -e 's/ //g' -e 's/MANlPREFIX/MANLPREFIX/g' -e 's/MANnPREFIX/MANNPREFIX/g'
 .if ${__pmlinks:Mbroken} == "broken"
 .BEGIN:
 	@${ECHO} "${PKGNAME}: Unable to parse MLINKS."
@@ -1339,30 +1376,31 @@
 
 .for sect in 1 2 3 4 5 6 7 8 9
 .if defined(MAN${sect})
-_MANPAGES+=	${MAN${sect}:S%^%${MAN${sect}PREFIX}/man/${lang}/man${sect}/%}
+JUNK=1
+_MANPAGES+=	${MAN${sect}:S%^%${DESTDIR}${MAN${sect}PREFIX}/man/${lang}/man${sect}/%}
 .endif
 .endfor
 
 .if defined(MANL)
-_MANPAGES+=	${MANL:S%^%${MANLPREFIX}/man/${lang}/manl/%}
+_MANPAGES+=	${MANL:S%^%${DESTDIR}${MANLPREFIX}/man/${lang}/manl/%}
 .endif
 
 .if defined(MANN)
-_MANPAGES+=	${MANN:S%^%${MANNPREFIX}/man/${lang}/mann/%}
+_MANPAGES+=	${MANN:S%^%${DESTDIR}${MANNPREFIX}/man/${lang}/mann/%}
 .endif
 
 .endfor
 
 .if defined(_MLINKS) && make(generate-plist)
-_TMLINKS!=	${ECHO} ${_MLINKS} | ${AWK} '{for (i=2; i<=NF; i+=2) print $$i}'
+_TMLINKS!=	${ECHO} ${_MLINKS} | ${AWK} '{for (i=2; i<=NF; i+=2) print $$i}' | ${SED} 's,^${DESTDIR},,'
 .else
 _TMLINKS=
 .endif
 
 .if defined(_MANPAGES) && defined(NOMANCOMPRESS)
-__MANPAGES:=	${_MANPAGES:S^${PREFIX}/^^:S/""//:S^//^/^g}
+__MANPAGES:=	${_MANPAGES:S^${DESTDIR}^^:S^${PREFIX}/^^:S/""//:S^//^/^g}
 .elif defined(_MANPAGES)
-__MANPAGES:=	${_MANPAGES:S^${PREFIX}/^^:S/""//:S^//^/^g:S/$/.gz/}
+__MANPAGES:=	${_MANPAGES:S^${DESTDIR}^^:S^${PREFIX}/^^:S/""//:S^//^/^g:S/$/.gz/}
 .endif
 
 .if defined(_MANPAGES) && ${MANCOMPRESSED} == "yes"
@@ -1980,12 +2018,12 @@
 	@cd ${.CURDIR} && ${MAKE} ${__softMAKEFLAGS} run-depends lib-depends
 .endif
 .if make(real-install)
-	@${MKDIR} ${PREFIX}
+	@${MKDIR} ${DESTDIR}${PREFIX}
 	@if [ `id -u` != 0 ]; then \
-		if [ -w ${PREFIX}/ ]; then \
+		if [ -w ${DESTDIR}${PREFIX}/ ]; then \
 			${ECHO_MSG} "Warning: not superuser, you may get some errors during installation."; \
 		else \
-			${ECHO_MSG} "Error: ${PREFIX}/ not writable."; \
+			${ECHO_MSG} "Error: ${DESTDIR}${PREFIX}/ not writable."; \
 			${FALSE}; \
 		fi; \
 	fi
@@ -1996,7 +2034,7 @@
 			${ECHO} "Copy it from a suitable location (e.g., /usr/src/etc/mtree) and try again."; \
 			exit 1; \
 		else \
-			${MTREE_CMD} ${MTREE_ARGS} ${PREFIX}/ >/dev/null; \
+			${MTREE_CMD} ${MTREE_ARGS} ${DESTDIR}${PREFIX}/ >/dev/null; \
 		fi; \
 	else \
 		${ECHO_MSG} "Warning: not superuser, can't run mtree."; \
Comment 6 Will Andrews freebsd_committer freebsd_triage 2004-06-04 01:31:18 UTC
State Changed
From-To: open->feedback

This seems like a good idea.  I agree that your interpretation of 
DESTDIR is correct.  However, your current patch no longer applies, 
for obvious reasons.  Sorry that nobody looked at your PR before, but 
I was wondering if you might have maintained this patch over the last 
(nearly) 3 years.  Thanks!
Comment 7 John E. Hein 2004-06-04 16:32:04 UTC
Will Andrews wrote at 17:34 -0700 on Jun  3, 2004:
 > Synopsis: [patch] DESTDIR is used incorrectly in bsd.port.mk
 > 
 > State-Changed-From-To: open->feedback
 > State-Changed-By: will
 > State-Changed-When: Thu Jun 3 17:31:18 PDT 2004
 > State-Changed-Why: 
 > This seems like a good idea.  I agree that your interpretation of
 > DESTDIR is correct.  However, your current patch no longer applies,
 > for obvious reasons.  Sorry that nobody looked at your PR before, but
 > I was wondering if you might have maintained this patch over the last
 > (nearly) 3 years.  Thanks!
 > 
 > http://www.freebsd.org/cgi/query-pr.cgi?pr=28155

Thanks for the response.  It's been a while on this one.

I have maintained it some (basically every so often when I merge my
Mk/bsd.port.mk with the latest version in CVS).  But I had given up on
anyone at FreeBSD working it in officially.  The most enthusiastic
response (prior to this one) I got from anyone who mattered was "Yes,
it's wrong, but it's too much work to fix it."

Indeed, port maintainers would need a heads up for such a change.
There are LOTS of ports (picking one simple one at random:
databases/gdbm) that have custom *-install targets that install to
${PREFIX} or ${X11BASE} or ${LOCALBASE} instead of
${DESTDIR}${PREFIX}.  Then there are some %%PREFIX%% substitutions
that may need fixing with respect to DESTDIR.

Some ports don't even work for an alternate definition of PREFIX.
But that'd be a different bug.

There was so much breakage, that I pretty much gave up trying to do
consistent builds (i.e., for a commercial product) outside a chroot.

And even in the chroot case, there's a pervasive problem with
pkg-plist's and absolute sym links in ports when using pkg_add -p.  I
had to pull teeth to fix just one of them (see
http://www.freebsd.org/cgi/query-pr.cgi?pr=56621).  There are other
examples (emulators/mtools & lang/perl5.8 to name a couple).
Basically anything that has an 'ln' in pkg-plist and uses %D as the
link target.

One way to address the widespread breakage might be just broadcasting
a message to maintainers regarding the impending paradigm correction.
It would probably be useful to also add a test to the bento builds to
verify things are installed to the right place.

It's a hard problem to fix that was broken by an unfortunate
implementation of DESTDIR a LONG time ago and is now widespread.

But, on the other hand, breaking the current DESTDIR is not such a bad
thing since no one can possibly be using it successfully (at least not
in any way that couldn't just as easily, and in most cases, more
successfully be done using PREFIX).  I bet a poll would indicate that
no one uses DESTDIR (whether or not the reason for not using DESTDIR
is that it's broken).

So I'd guess that just fixing it in Mk/* will probably have little
impact (and probably no negative impact).

Note that there seems to be very little maintainer consideration
regarding building/installing to some place other than /usr/local or
/usr/X11R6.  That may be because the .mk infrastructure makes it too
hard.  Some ports are better than others, but often only because the
underlying package supports it correctly (usually via autoconf
generated Makefiles) and the actual port Makefile doesn't do anything
to break that.

Sorry for the lengthy reply.

If you're still reading, I'd be willing to update the patch and write
the rudiments of a test that could be used for automated DESTDIR
verification if someone at portmgr@ is willing to see this through.
Let me know.
Comment 8 Gabor Kovesdan freebsd_committer freebsd_triage 2006-07-28 11:34:00 UTC
This PR is superseded by ports/100555, so it should be closed now. The 
new patchset is currently being tested on the package building cluster.

-- 
Cheers,

Gabor
Comment 9 Mark Linimon freebsd_committer freebsd_triage 2006-07-28 20:24:30 UTC
State Changed
From-To: feedback->closed

After many long years of neglect, one of our Summer Of Code (SoC) students 
has picked up this idea and is currently trying to implement it (see the 
patch in ports/100555, which is currently being tested on the cluster). 

As will not surprise you, many ports are non-conformant, and we are having 
to do multiple regression runs to minimize the impact. 

2005 and 2006 are the first years in a long time where we've actually 
started to make progress on the portmgr PR backlog, due to the fact that 
a) we have a much larger number of i386 machines available to us now; 
b) we have more portmgr members willing and able to do the regression 
tests, and c) we have finally gotten buy-in that we need more time with 
the ports tree unlocked to make progress (effectively, infrastructure work 
is mutually exclusive with ports tree locks).  I am hopeful that we are 
able to continue to make progress in the last half of this year so that 
situations like this, which must have been extremely frustrating to the 
submitter, are less likely to occur in the future.
Comment 10 John E. Hein 2006-07-28 22:04:56 UTC
Mark Linimon wrote at 19:30 GMT on Jul 28, 2006:
 > After many long years of neglect, one of our Summer Of Code (SoC) stud=
ents
 > has picked up this idea and is currently trying to implement it (see t=
he
 > patch in ports/100555, which is currently being tested on the cluster)=
=2E

Yes... thanks for picking this up, G=E1bor.
I'll look over 100555 and post any comments to that patch there.


 > As will not surprise you, many ports are non-conformant, and we are ha=
ving
 > to do multiple regression runs to minimize the impact.
 > =

 > 2005 and 2006 are the first years in a long time where we've actually
 > started to make progress on the portmgr PR backlog, due to the fact th=
at
 > a) we have a much larger number of i386 machines available to us now;
 > b) we have more portmgr members willing and able to do the regression
 > tests, and c) we have finally gotten buy-in that we need more time wit=
h
 > the ports tree unlocked to make progress (effectively, infrastructure =
work
 > is mutually exclusive with ports tree locks).  I am hopeful that we ar=
e
 > able to continue to make progress in the last half of this year so tha=
t
 > situations like this, which must have been extremely frustrating to th=
e
 > submitter, are less likely to occur in the future.

Nice to see the progress.  It stopped being frustrating long ago... I
just gave up and lived with local patches.  I'd guess this is a fairly
typical response for patch submitters, but that's the nature of the
project.

I figured that this change was too big to handle with the regression
infrastructure we had back then.  The response was fairly lukewarm,
too, but that was probably because of the daunting testing for this
change.

Of course, it would have been a bit easier back then from a volume
standpoint with half as many ports ;)