# Installing ports to alternate root



## babel17 (May 28, 2010)

I'm trying to figure out the best way to install ports to an alternate root as part of creating a custom FreeBSD distribution that includes certain ports.  I can use

`make install PREFIX=/altroot/usr/local`

but I am worried that some ports may be internally using PREFIX, or setting LOCALBASE to something other than "/usr/local" and my setting prefix from the command line will break that.

Should I instead be using?

`make install LOCALBASE=/altroot/usr/local`

Or is there some better way?

Also, I would like to disable ldconfig running when I do this as I do not want anything under /altroot being used by the current operating system.  The only way I can see to do this is to set USE_LDCONFIG to an existing directory that already in my hints file.  There appears to be no way to just turn it off.


----------



## jgh@ (May 28, 2010)

I've used alternative PREFIX for ports I've made, but never used it on ports that are in the ports tree, and it works fine. Not sure of the implications outside of this structure.


----------



## Carpetsmoker (May 29, 2010)

> I'm trying to figure out the best way to install ports to an alternate root as part of creating a custom FreeBSD distribution that includes certain ports.



Use DESTDIR for this purpose. See /usr/ports/Mk/bsd.destdir.mk
Builds are chrooted, so you'll need to use mount_nullfs or mount_nfs to mount some stuff.

Setting PREFIX will not work: Dependencies are checked against LOCALBASE, and libraries are checked with ldconfig.
So you only end up with the target port: And not all of the dependencies.

Some time ago I made a cleaned up/better version of tinybsd (/usr/src/tools/tools/tinybsd), here is the port installation function to give you an example/idea of how it works.

```
install_ports()
{
	if [ ! -d "${WORKDIR}/usr/ports" ]; then
		mkdir -p "${WORKDIR}/usr/ports"
	fi

	for p in $(grep -v '^#' ${CURRENTDIR}/conf/${CONF}/${PORTSFILE}) ; do
		portname=$(echo ${p} | cut -s -f 1 -d ':')
		options=$(echo ${p} | cut -s -f 2 -d ':')
		if [ -z "${portname}" ]; then
			portname=${p}
		fi

		mounts="/lib /usr/bin /usr/sbin /usr/ports /usr/share /usr/libexec /usr/lib /usr/include"

		for m in ${mounts}; do
			mount_nullfs ${m} ${WORKDIR}/${m}
		done
		
		echo "${TS} Building ${portname}."
		cd ${PORTSDIR}/${portname} && \
			make -DBATCH DESTDIR_ENV_LIST="PATH" DESTDIR="${WORKDIR}" \
				${options} fetch-recursive install clean
		
		for m in ${mounts}; do
			umount ${WORKDIR}/${m}
		done
	done
}
```

Good luck


----------



## jgh@ (May 29, 2010)

Carpetsmoker said:
			
		

> Use DESTDIR for this purpose. See /usr/ports/Mk/bsd.destdir.mk
> Builds are chrooted, so you'll need to use mount_nullfs or mount_nfs to mount some stuff.
> 
> Setting PREFIX will not work: Dependencies are checked against LOCALBASE, and libraries are checked with ldconfig.
> ...



In using PREFIX, and not DESTDIR, I have all dependencies correctly registered and have had no issues when it comes to libraries, as well. I've built all of these ports in Tinderbox and have no major design issue with them. That being said, I am curious how using DESTDIR will differ, and may try that.


----------



## Carpetsmoker (May 29, 2010)

> In using PREFIX, and not DESTDIR, I have all dependencies correctly registered and have had no issues when it comes to libraries, as well.



The ports system will check dependencies relative to LOCALBASE, or use ldconfig or other tools in the current installation (Scuh as pkg-config).

It _might_ happen to work if you have a system without any ports installed though. But it is not designed for it.

Settings DESTDIR will start a chroot build in DESTDIR.


----------



## babel17 (May 31, 2010)

Muchas Gracias Carpetsmoker.

I will try DESTDIR and see how that works.  Certainly both PREFIX and LOCALBASE do not do what I what I want.


----------



## babel17 (Jun 2, 2010)

Well, it mostly works.  Trouble is it looks like many of the ports themselves are broken.  they have a bug in the path for install.sh

for instance, bison, ipmitool, gsed, ...


```
make  install-recursive
test no != no || /bin/sh /usr/ports/devel/bison/work/bison-2.4.1/build-aux/install-sh -d /usr/local/lib
/usr/ports/devel/bison/work/bison-2.4.1/build-aux/install-sh: Can't open /usr/ports/devel/bison/work/bison-2.4.1/build-aux/install-sh: No such file or directory
*** Error code 2

Stop in /tmp/mountpoint.uXo3ph/devel/bison/work/bison-2.4.1/lib.
*** Error code 1
```

It shouldn't be looking in /usr/ports/devel/bison/..., it should be looking in /tmp/mountpoint.uXo3ph/devel/bison/...

By contrast, the port for coreutils works correctly because it uses a relative path:


```
test -z "/usr/local/lib/coreutils" || ../build-aux/install-sh -c -d "/usr/local/lib/coreutils"
  ./ginstall libstdbuf.so '/usr/local/lib/coreutils/./glibstdbuf.so'
```


Oh well, back to the drawing board


----------



## OH (Jun 3, 2010)

I always build packages on the preparing system, move those packages to a directory in the custom distribution, chroot into the custom distribution (run ldconfig start) and then pkg_add those packages.


----------



## Carpetsmoker (Jun 3, 2010)

> It shouldn't be looking in /usr/ports/devel/bison/..., it should be looking in /tmp/mountpoint.uXo3ph/devel/bison/...



Almost all (if not all) ports respect PORTSDIR.

I don't know what commands exactly you issued and what exactly went wrong, but why "should" /tmp/mountpoint.uXo3ph/devel/bison/ be used and not /usr/ports/?


----------



## babel17 (Jun 3, 2010)

Re: why?

Well, to be honest, my understanding may be incorrect.  But...

I don't think I should have to do the loopback mount of /usr/ports to $DESTDIR/usr/ports.  $DESTDIR/usr/ports already exists, and my work dir - at least as evidenced by the log file - ends up under some temp directory.  There is no $PORTSDIR/path_to_port/work directory there is only a $TMPDIR/path_to_port/work.   I don't know why this happens this way, I just know that it does.

Having said that, since it's more important to me (right now) to make it work than it is to understand exactly how it works,  I went ahead and did the loopback mount (mount_nullfs /usr/ports $DESTDIR/usr/ports)  and that solved the problem.  Had I never built the ports without using DESTDIR, I'm not sure if it would have though.


Re: build packages instead

Yeah that was gonna be my next step.


----------



## Carpetsmoker (Jun 4, 2010)

> I don't think I should have to do the loopback mount of /usr/ports to $DESTDIR/usr/ports. $DESTDIR/usr/ports already exists



As I understand it, as long as ${DESTDIR}/usr/ports is a valid port directory you're fine, it doesn't matter if you use mount_nullfs or if it's a "real" directory.
You can define WITH_DESTDIR_DEBUG to display some extra messages which may explain the issue.

In any case, as I understand it, it works as expected?


----------



## babel17 (Jun 4, 2010)

Carpetsmoker said:
			
		

> In any case, as I understand it, it works as expected?



As expected? Not the terminology I would have chosen, but yeah, it now does what I want, if not quite the way I expected.  Unfortunately I'm on the clock, so I don't really have the time to delve into it further to see if it's my error or something in some of the ports.


----------



## Carpetsmoker (Jun 5, 2010)

I had to do some stuff with DESTDIR today, much to my confusion I encountered an error similar to yours (While it "used to work fine")!
The problem? I had built the port earlier in my normal FreeBSD environment, and the work directory still remained. This caused the errors.
A make clean solved the problem.
Just FYI or for other people reading ...

Today I also noticed that using DESTDIR has the disadvantage that it pulls in some potentially unwanted and unneeded dependencies, for example one port I added had a build (But not runtime) dependency on all sorts of stuff: perl, ruby, autoconf, m4, gnu make, etc.
The result: My lean 15MB FreeBSD image got slightly larger 

I'll post my automatic build-package-install script once it's ready.


----------



## jgh@ (Jun 8, 2010)

I have written tons of internal ports and have not once used the $DESTDIR directive. Although, none of my ports are being installed to /usr/local/ hierarchy, and I am not installing any libraries to $LOCALBASE.

That being said, I am using Tinderbox that takes care of my chroot'ed environment, and I have not had to worry about $DESTDIR (didn't even know it was a factor) because all testing has proven that the system works without that for the purposes I am using it for.

I have setup Tinderbox with my Operating System Sources, and imported /usr/ports and injected my local ports tree with no issue for several builds.

If I have an issue at some point, I will remember to post to this thread.


----------



## Carpetsmoker (Jun 8, 2010)

I think you are confused about the difference between PREFIX and DESTDIR, they are something quite different.

PREFIX installs port to a different PREFIX, normally this is /usr/local/, but you can also set it to /var/ or /home/ or /whatever. PREFIX installs ports in the current installation.
All that setting up PREFIX does is change the configure's --prefix argument or equivalent for each port.

DESTDIR is used for installing ports to a _different_ FreeBSD installation and not the _current_ installation. It will chroot to DESTDIR, the current installation is _completely_ unaffected.


----------

