The pkgsrc wrapper framework
Jörg Sonnenberger
Motivation
- Reliable packages
- Reproducable builds
- Inconsistent command lines of compilers
- Inconsistencies between Operating Systems
The buildlink framework
- buildlink3.mk files provide dependency information
- buildlink3.mk files provide the visibility tree
- Shadow tree in the work area:
- .buildlink subdirectory with symlinks to /usr/pkg
- .x11-buildlink subdirectory with symlinks to /usr/X11R6
The buildlink framework
- File list based on package content
- Header files, libraries, pkg-config files per default
- Wrappers to redirect to the shadow tree
Transformations for GCC-like frontends (I)
- Multiple transformation phases:
- Normalization
- First cleanup
- Generic option transformation
- Reordering
- Compiler-specific option transformation
- Second cleanup
Transformations for GCC-like frontends (II)
- Each phase can add, change or drop options
- Input: GCC-like command line
- Output: native compiler command line
Phase 1: Normalization (I)
- Transform options to canonical form
- "-Dmacro" vs "-D macro", "-Idir" vs "-I dir", "-Ldir" vs "-L dir"
- Linker options can be concatenated ("-Wl,-L,dir")
- "-Ldir" vs "-Wl,-Ldir"
Phase 1: Normalization (II)
- "-R" vs "-Wl,-R" vs "-Wl,-rpath" vs "-Wl,--rpath"
- "-Wl,-rpath,dir1:dir2" vs "-Wl,-rpath,dir1 -Wl,rpath,dir2"
- Same for "-Wl,-rpath-link"
- "/usr/pkg/lib/libgtk2.so" vs "-L/usr/pkg/lib -lgtk2"
Phases 2 & 6: Cleanup
- Drop redundant arguments:
- Simplifies following phases
- Helps platforms with small argument limit
- Duplicate "-I", "-L", "-Wl,-rpath" and "-Wl,-rpath-link"
- Old wrappers: Drop duplicate "-D" options
- Drop "-Wl,-rpath" options with relative paths
- Unify consecutive library options
Phase 3: Generic option processing (I)
- Implements the shadow tree redirection
- Supports dropping or transforming flags:
- Optimizer flags that crash the compiler
- Unsupportable warning flags ("-Werror")
- Old wrapper: wildcard matches
Phase 3: Generic option processing (II)
- Absolute path names for "-I", "-Wl,-rpath" and "-L" are matched
- Per type src:dst rules
- Replace src part with dst, drops option if dst is empty
- No match: option is dropped
Phase 4: Reordering
- Helps with stricter library ordering rules:
- Mach-O, XCOFF
- Static linkage
- foo:bar moves all instances of foo after first instance of bar
- Old wrappers: Move all "-l" options after all "-L" arguments
- Old wrappers: Glue for "-Wl,-Bdynamic" and "-Wl,-Bstatic"
Phase 5: Platform specific processing
- Transforms GCC options to native compiler options
- Platform specific linker options
- Example AIX: emulation of "-Wl,-rpath" using "-blibpath"
- Table driven transformation of fixed strings or prefix matches
Dealing with libtool
- Compiler wrapper to abstract shared library issues
- Need to deal with full path to libtool archives (*.la)
- Relinking on installation
- Leaking references to .buildlink inside libtool archives
- Wrap libtool itself for pre and post processing
Libtool: Full path to libtool archives
- Path is in the work area: leave it
- Transform it to "-L" + "-l" argument pair
Libtool: Relinking
- Need to be able to link against to-be-installed libraries
- Need to be able to link against unshadowed libraries
- Solution: add .libs subdirectory of depending libtool archives via "-L"
- Problem: all libtool archives must be requested by path
- Solution: scan "-l" options and replace them if needed
Libtool: .buildlink leakage
- libtool includes "-L" options for linkage in libtool archives
- libtool sees only the buildlink shadow tree
- Unwrap the dependency_libs line by replacing .buildlink references back
- Only relevant for .lai files (to-be-installed version of .la)
The new wrappers
- Compiled C code
- Configuration file for each wrapper
- Most errors are fatal: no silent problems
- Stricter validation: less cross-platform issues
The new wrappers: code overview (I)
- Independent loops over all arguments for each phase
- Arguments as (mostly) immutable strings: copy-on-change
- Hash tables for the cleanup phase
- Perfect hashing for compiler transformation
The new wrappers: code overview (II)
- Forking only if needed (libtool)
- No low level optimisations yet
- NetBSD/gcc: 64KB or 2600 lines of code
Performance (I)
Performance (II)
Performance (III)
Conclusions
- Little to no overhead
- Small code base
- Straight forward logic (except libtool)
- Separation of code and configuration
- More work to finish before merge