libpath

package
v3.0.0-alpha.57 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 5, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package libpath provides utilities for finding native library paths on Linux.

Overview

This package helps locate shared libraries (.so files) on Linux systems, supporting multiple distributions and package managers. It's particularly useful for applications that need to link against libraries like GTK, WebKit2GTK, or other system libraries at runtime.

Search Strategy

The package uses a multi-tier search strategy, trying each method in order until a library is found:

  1. pkg-config: Queries the pkg-config database for library paths
  2. ldconfig: Searches the dynamic linker cache
  3. Filesystem: Scans common library directories

Supported Distributions

The package includes default search paths for:

  • Debian/Ubuntu (multiarch paths like /usr/lib/x86_64-linux-gnu)
  • Fedora/RHEL/CentOS (/usr/lib64, /usr/lib64/gtk-*)
  • Arch Linux (/usr/lib/webkit2gtk-*, /usr/lib/gtk-*)
  • openSUSE (/usr/lib64/gcc/x86_64-suse-linux)
  • NixOS and Nix package manager

Package Manager Support

Dynamic paths are discovered from:

  • Flatpak: Scans runtime directories via `flatpak --installations`
  • Snap: Globs /snap/*/current/usr/lib* directories
  • Nix: Checks ~/.nix-profile/lib and /run/current-system/sw/lib

Caching

Dynamic path discovery (Flatpak, Snap, Nix) is cached for performance. The cache is populated on first access and persists for the process lifetime. Use InvalidateCache to force re-discovery if packages are installed/removed during runtime.

Security

The current directory (".") is never included in search paths by default, as this is a security risk. Use FindLibraryPathWithOptions with IncludeCurrentDir if you explicitly need this behavior (not recommended for production).

Performance

Typical lookup times (cached):

  • Found via pkg-config: ~2ms (spawns external process)
  • Found via ldconfig: ~1.3ms (spawns external process)
  • Found via filesystem: ~0.1ms (uses cached paths)
  • Not found (worst case): ~20ms (searches all paths)

Example Usage

// Find a library by its pkg-config name
path, err := libpath.FindLibraryPath("webkit2gtk-4.1")
if err != nil {
    log.Fatal("WebKit2GTK not found:", err)
}
fmt.Println("Found at:", path)

// Find a specific .so file
soPath, err := libpath.FindLibraryFile("libgtk-3.so")
if err != nil {
    log.Fatal("GTK3 library file not found:", err)
}
fmt.Println("Library file:", soPath)

// Get all library search paths
for _, p := range libpath.GetAllLibPaths() {
    fmt.Println(p)
}

When you don't know which version of a library is installed, use the multi-library search functions:

// Find any available WebKit2GTK version (first found wins)
match, err := libpath.FindFirstLibrary("webkit2gtk-4.1", "webkit2gtk-4.0", "webkit2gtk-6.0")
if err != nil {
    log.Fatal("No WebKit2GTK found")
}
fmt.Printf("Found %s at %s\n", match.Name, match.Path)

// Prefer newer versions (ordered search)
match, err := libpath.FindFirstLibraryOrdered("gtk4", "gtk+-3.0")

// Discover all available versions
matches := libpath.FindAllLibraries("gtk+-3.0", "gtk4", "webkit2gtk-4.0", "webkit2gtk-4.1")
for _, m := range matches {
    fmt.Printf("Available: %s at %s\n", m.Name, m.Path)
}

On non-Linux platforms, stub implementations are provided that always return LibraryNotFoundError.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FindLibraryFile

func FindLibraryFile(fileName string) (string, error)

FindLibraryFile finds the full path to a specific library file (e.g., "libgtk-3.so").

func FindLibraryPath

func FindLibraryPath(libName string) (string, error)

FindLibraryPath attempts to find the path to a library using multiple methods in parallel. It searches via pkg-config, ldconfig, and filesystem simultaneously, returning as soon as any method finds the library.

The libName should be the pkg-config name (e.g., "gtk+-3.0", "webkit2gtk-4.1"). Returns the library directory path and any error encountered.

func FindLibraryPathSequential

func FindLibraryPathSequential(libName string) (string, error)

FindLibraryPathSequential is the original sequential implementation. Use this if you need deterministic search order (pkg-config → ldconfig → filesystem).

func FindLibraryPathWithOptions

func FindLibraryPathWithOptions(libName string, opts FindOptions) (string, error)

FindLibraryPathWithOptions attempts to find the path to a library with custom options.

func GetAllLibPaths

func GetAllLibPaths() []string

GetAllLibPaths returns all library paths from LD_LIBRARY_PATH, default paths, and dynamically discovered paths from Flatpak, Snap, and Nix. It does NOT include the current directory for security reasons.

func InvalidateCache

func InvalidateCache()

InvalidateCache clears the cached dynamic library paths. Call this if packages are installed or removed during runtime and you need to re-discover library paths.

Types

type FindOptions

type FindOptions struct {
	// IncludeCurrentDir includes "." in the search path.
	// WARNING: This is a security risk and should only be used for development.
	IncludeCurrentDir bool

	// ExtraPaths are additional paths to search before the defaults.
	ExtraPaths []string
}

FindOptions controls library search behavior.

type LibraryMatch

type LibraryMatch struct {
	// Name is the pkg-config name that was searched for.
	Name string
	// Path is the directory containing the library.
	Path string
}

LibraryMatch holds information about a found library.

func FindAllLibraries

func FindAllLibraries(libNames ...string) []LibraryMatch

FindAllLibraries searches for multiple libraries in parallel and returns all that are found. This is useful for discovering which library versions are available on the system.

Example:

matches := FindAllLibraries("gtk+-3.0", "gtk+-4.0", "webkit2gtk-4.0", "webkit2gtk-4.1")
for _, m := range matches {
    fmt.Printf("Found %s at %s\n", m.Name, m.Path)
}

func FindFirstLibrary

func FindFirstLibrary(libNames ...string) (*LibraryMatch, error)

FindFirstLibrary searches for multiple libraries in parallel and returns the first one found. This is useful when you don't know the exact version of a library installed (e.g., gtk+-3.0 vs gtk+-4.0).

The search order among candidates is non-deterministic - whichever is found first wins. If you need a specific preference order, list preferred libraries first and use FindFirstLibraryOrdered instead.

Example:

match, err := FindFirstLibrary("webkit2gtk-4.1", "webkit2gtk-4.0", "webkit2gtk-6.0")
if err != nil {
    log.Fatal("No WebKit2GTK found")
}
fmt.Printf("Found %s at %s\n", match.Name, match.Path)

func FindFirstLibraryOrdered

func FindFirstLibraryOrdered(libNames ...string) (*LibraryMatch, error)

FindFirstLibraryOrdered searches for libraries in order of preference, returning the first one found. Unlike FindFirstLibrary, this respects the order of candidates - earlier entries are preferred.

This is useful when you want to prefer newer library versions:

match, err := FindFirstLibraryOrdered("gtk+-4.0", "gtk+-3.0")
// Will return gtk+-4.0 if available, otherwise gtk+-3.0

type LibraryNotFoundError

type LibraryNotFoundError struct {
	Name string
}

LibraryNotFoundError is returned when a library cannot be found.

func (*LibraryNotFoundError) Error

func (e *LibraryNotFoundError) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL