mixing binary packages and compiled ports - keeping it up to date

Setting:
  • FreeBSD 11.0 RELEASE
  • I have binary packages installed using pkg. Works great and fine in itself.
  • I have installed from source some ports as the options used in the binary version was not what I needed. Works great and fine in itself.

Mixing both as such works as advertised, but I'm not sure how to keep it up to date in a safe manner so that the vital compile time options remain set on those ports that need it.

I know I can prevent pkg upgrade from upgrading an installed from source package to a binary one by locking it with pkg lock <name>. That works fine.

But that also means that portmaster <name> doesn't want to update it either anymore, giving a long error message. I can go in the appropriate /usr/ports/... directory and do a manual make reinstall, which does work, but then the lock seems to be gone all of a sudden, risking that pkg upgrade would start to put its binary version out there.

Question is hence simple:
How do I set it up so that:
  • The binary installed packages keep getting binary upgrades
  • The packages compiled from source with a different set of options can be upgraded with a simple command that doesn't require a truckload of additional software to be installed
  • Keep that going forward so that the compile time option I need are never going to be overwritten by a binary version that has other options.

E.g. of a package I need to make from source: nginx ...
 
I wrote a shell script for exactly the situation which you described. It works well on 6 FreeBSD machines.

You would need to inform the ports which you want to have built from sources at the top of the script. Be careful when editing the portslist, leaving a blank before each \. If you happen to built phpXY from the ports, then you need to add all the needed phpXY-modules as well to said list like I did in my script.

Code:
#!/bin/sh

### the list of the ports that shall be updated from sources
portslist="\
devel/apr1 \
devel/subversion \
lang/php71 \
www/mod_php71 \
\
archivers/php71-phar \
archivers/php71-zlib \
converters/php71-iconv \
converters/php71-mbstring \
databases/php71-mysqli \
databases/php71-pgsql \
devel/php71-json \
devel/php71-tokenizer \
security/php71-filter \
security/php71-hash \
sysutils/php71-posix \
textproc/php71-ctype \
textproc/php71-dom \
textproc/php71-simplexml \
textproc/php71-xml \
textproc/php71-xmlreader \
textproc/php71-xmlwriter \
www/php71-opcache \
www/php71-session"

### fetching FreeBSD system updates
/usr/bin/printf "Fetching FreeBSD system updates...\n"
PAGER=/bin/cat
/usr/sbin/freebsd-update fetch

### fetching updates of the FreeBSD ports tree
/usr/bin/printf "\nFetching updates of the FreeBSD ports tree...\n"
/usr/sbin/portsnap fetch update
/usr/sbin/pkg version -v
/usr/sbin/pkg updating -d `date -v-2w +%Y%m%d`

### ask and in case of y|Y run the updating processes
/usr/bin/printf "\nDo you want to continue (y/n)? "
save_stty_state=$(stty -g); stty raw -echo; answer=$(head -c 1); stty $save_stty_state
if echo "$answer" | grep -iq "^y" ; then
   /usr/bin/printf "\n\n"
   /usr/sbin/pkg update

   portmake=""
   pkgslist=`/usr/sbin/pkg version -o | /usr/bin/cut -f1 -w`
   for port in $portslist ; do
      for pkg in $pkgslist ; do
         if [ "$pkg" == "$port" ] ; then
            continue 2
         fi
      done

      portmake="$portmake $port"
   done

   pkgslist=""
   outdated=`/usr/sbin/pkg version -ol\< | /usr/bin/cut -f1 -w`
   for outd in $outdated ; do
      for port in $portslist ; do
         if [ "$port" == "$outd" ] ; then
            portmake="$portmake $port"
            continue 2
         fi
      done

      pkgslist="$pkgslist $outd"        
   done

   pkgupgrd=""
   outdated=`/usr/sbin/pkg version -RU -ol\< | /usr/bin/cut -f1 -w`
   for outd in $outdated ; do
      for pkg in $pkgslist ; do
         if [ "$pkg" == "$outd" ] ; then
            pkgupgrd="$pkgupgrd $pkg"
            continue 2
         fi
      done
   done

   /usr/bin/printf "\nUpdating binary packages...\n"
   if [ "$pkgupgrd" != "" ] ; then
      /usr/sbin/pkg upgrade -U $pkgupgrd
   else
      echo "All installed packages are up-to-date."
   fi

   /usr/bin/printf "\nUpdating ports...\n"
   if [ "$portmake" != "" ] ; then
      cwd=$PWD

      for port in $portmake ; do
         cd /usr/ports/$port
         /usr/bin/make deinstall distclean
         /usr/bin/make install clean
      done

      cd "$cwd"
   else
      echo "All installed ports are up-to-date."
   fi

   /usr/bin/printf "\nCleaning up...\n"
   /usr/sbin/pkg clean -y

else

   /usr/bin/printf "\n\n"

fi
You also want to configure pkg(8) to pick packages from the latest repository instead of the quarterly one. For this, place the following content into the file /usr/local/etc/pkg/repos/FreeBSD.conf:
Code:
FreeBSD: {
  url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest",
}
 
Ideally the way you should do this is to use a package builder such as poudriere or synth and use them to build your local packages from a list. Keep your local ports tree at the same revision as the FreeBSD package repository was built from and then install the packages from each repository as required. pkg will automatically record which repository the packages came from and update from each as needed.

If you don't keep the source tree revisions identical then you run the risk of installing a package which depends on a package that doesn't exist.
 
If you don't keep the source tree revisions identical then you run the risk of installing a package which depends on a package that doesn't exist.
It doesn't matter what /usr/ports contains if you install packages (using pkg-install(8)). It can even be completely empty.
 
Setting:
  • FreeBSD 11.0 RELEASE
  • I have binary packages installed using pkg. Works great and fine in itself.
  • I have installed from source some ports as the options used in the binary version was not what I needed. Works great and fine in itself.

Mixing both as such works as advertised...

It's recommended not to mix ports and packages. Stick with one or the other and you'll find peace within.
 
Nothing wrong with mixing ports and packages. After all the only thing installing a port does is creates a package which is installed using pkg. What isn't recommended, and what I mentioned above, is mixing two different versions of the ports tree. As you might install a port that's linked against say OpenSSL 1.0.1 but the package repository wants to install a package that's linked against OpenSSL 1.0.2. Then hassle ensues.

That's why I said the best option is to keep your ports tree in sync against the package repository and use something like poudriere to create your own second repository.
 
Back
Top