AUTHOR: Alexandru Mihai Buzduc <lalibuzduc@gmail.com>

DATE: 2025-07-09

LICENSE: GNU Free Documentation License v1.2 or later (GFDL-1.2-or-later)
[https://www.linuxfromscratch.org/hints/downloads/files/LICENSES/fdl-1.2.txt]

SYNOPSIS: Package management with Graft

DESCRIPTION:
This hint will provide instructions on how to install and use the Graft package 
manager for symlink style package management on Linux From Scratch. It will also
provide general guidelines for how to make use of Graft system-wide and notes 
for specific packages and files installed in the Building the LFS System section
of the book, such as Glibc and the Texinfo /usr/share/info/dir file.

PREREQUISITES:
This hint requires that you have finished the LFS 12.3 book up to the beginning 
of the Building the LFS System section. It also requires you to have a copy of 
Graft's source code downloaded on the system, preferably in $LFS/sources, via
the following link:
https://github.com/johnsonjh/graft/archive/refs/tags/2.16.tar.gz

HINT:
Notice #########################################################################

While this hint aims to be compatible with all versions of Graft and the LFS 
book, it has been originally tested on and written for LFS 12.3 and Graft 2.16 
in mind. This hint will only be updated when breaking changes for this hint are 
implemented in LFS and/or Graft, or when fixes or improvements for certain parts
of this hint have been found.

Introduction ###################################################################

Graft, like Stow and Depot, provides a mechanism for managing multiple packages 
under a single directory hierarchy, which completely coincides with the symlink
style package management method as specified in the Package Management page at 
the start of the Building the LFS System section of the book. It also aims to 
provide advanced capabilities over Stow and Depot, for example providing the 
ability to prune preexisting packages and to exclude certain files and 
directories when installing packages, which are both very important in resolving 
conflicts.

Installation of graft ##########################################################

1) Prepare Graft for compiling:

make -f Makefile.dist
    
2) Modify some values in the generated makefile via the following sed command:

sed -i \
  -e 's|^PACKAGEDIR[[:space:]]*=.*|PACKAGEDIR = /usr/pkg|' \
  -e 's|^TARGETDIR[[:space:]]*=.*|TARGETDIR = /|' \
  -e 's|^BIN[[:space:]]*=.*|BIN = $(TOP)/usr/bin|' \
  -e 's|^MAN[[:space:]]*=.*|MAN = $(TOP)/usr/share/man|' \
  -e 's|^DOC[[:space:]]*=.*|DOC = $(TOP)/usr/share/doc/graft-2.16|' \
  Makefile

3) Build the package:

make

4) Install graft in the /usr/pkg directory:

make install

5) Remove the .nograft file in the documentation to allow Graft to install it:

rm -v /usr/pkg/graft-2.16/usr/share/doc/graft-2.16/.nograft

6) Create the initial symlinks via Graft itself to start using it:

/usr/pkg/graft-2.16/usr/bin/graft -iV graft-2.16
   
Usage ##########################################################################

This section will point out the base commands to manage packages with Graft,
using an example package named foo-0.1.0.

Install a package:

graft -iV foo-0.1.0

Remove a package:

graft -dV foo-0.1.0

Prune a package:

(i) NOTE: these commands can be used to transition a preexisting package under 
graft control

graft -pV foo-0.1.0 # Nondestructive; renames identical conflicting files
graft -pdV foo-0.1.0 # DESTRUCTIVE; deletes identical conflicting files
   
Caveats ########################################################################

This section of the hint will describe various issues that you may encounter 
when managing with Graft certain LFS packages installed in the Building the LFS
System section, and, if possible, will also provide workarounds on how to fix
these issues.
   
Glibc --------------------------------------------------------------------------

Due to the lack of any modern file replacement technology in Graft, pruning
Glibc while in the system will break every package depending on it (which is to
say all of them), rendering the entire system completely broken and unusable.
Because of this, the safest and only way to properly install it is outside of
the system.

You can do so by exiting the LFS chroot and running the following commands on
the host shell:

$LFS/usr/pkg/graft-2.16/usr/bin/graft -r $LFS -pDV glibc-2.41
$LFS/usr/pkg/graft-2.16/usr/bin/graft -r $LFS -iV glibc-2.41

After this, you can simply chroot back in and proceed with the installation.

Ncurses ------------------------------------------------------------------------

As of the time of writing this, I have not yet figured out a way on how to 
install Ncurses without permanently breaking the ability to chroot back into the
system. If anyone is up to the task of helping me out in fixing this, feel free
to contact me.
    
The /usr/share/info/dir file ---------------------------------------------------

Packages such as Flex and many GNU-related ones install Texinfo documentation 
accessible via the info command, which opens up a small plain text file named 
dir, stored in /usr/share/info, that gets updated every time a package bundled 
with said Texinfo documentation is installed, adding a new entry in it. When 
using a package management technique that involves directly installing packages 
on the root of the system, this isn't an issue, but when dealing with separate 
installation directories for every package on the system, this quickly becomes a
bit of a hassle.
After running the install command for the first ever package on the system that 
contains it, follow the instructions below for how to keep it properly updated,
avoiding any install conflicts for other packages that have it, too:

1) Copy the file in the /usr/share/info directory:

cp -v /usr/pkg/foo-0.1.0/usr/share/info/dir /usr/share/info

2) Write a .graft-exclude file to exclude it, avoiding a conflict:

cat > /usr/pkg/foo-0.1.0/usr/share/info/.graft-exclude << "EOF"
dir
EOF

3) Proceed to install the package:

graft -iV foo-0.1.0

4) Update the dir file to add the new Texinfo documentation in it:

pushd /usr/share/info
  rm -v dir
  for f in *
    do install-info $f dir 2>/dev/null
  done
popd

When installing other packages that include additional documentation, repeat 
steps 2 through 4 to install it and keep dir up to date.

ACKNOWLEDGMENTS:
  * Avery Terrel for helping out with the Glibc entry in Caveats
  
CHANGELOG:
[2025-07-09]
  * Initial hint.
