mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 14:45:49 +01:00
* feat(linux): add libpath package for finding native library paths
Add a new internal/libpath package that locates shared libraries (.so files)
on Linux systems. Supports multiple distributions and package managers.
Features:
- Multi-tier search: pkg-config -> ldconfig -> filesystem scanning
- Parallel search using goroutines for faster lookups
- Cached dynamic path discovery for Flatpak, Snap, and Nix
- Support for Debian/Ubuntu, Fedora/RHEL, Arch, openSUSE, NixOS
- Context-aware cancellation for graceful shutdown
Performance:
- Library found: ~1.4ms (parallel search)
- Library not found: ~46ms (was 84ms sequential)
- Cached path discovery: 14ns (was 15ms uncached)
* feat(libpath): add multi-library parallel search functions
Add functions to search for multiple library candidates in parallel:
- FindFirstLibrary: Search multiple libs in parallel, return first found
- FindFirstLibraryOrdered: Search in order of preference (for version priority)
- FindAllLibraries: Find all available libraries from a list
Useful when the exact library version is unknown, e.g.:
match, _ := FindFirstLibrary("webkit2gtk-4.1", "webkit2gtk-4.0", "webkit2gtk-6.0")
Also adds findLibraryPathCtx for context-aware searching used by the
multi-library functions.
* refactor(libpath): split into separate files and fix race condition
Split libpath_linux.go into smaller, focused files:
- cache_linux.go: Path cache with thread-safe init/invalidate
- flatpak_linux.go: Flatpak runtime path discovery
- snap_linux.go: Snap package path discovery
- nix_linux.go: Nix/NixOS path discovery
- libpath_linux.go: Core search functions
Fixes:
- Fix data race between init() and invalidate() by holding mutex
during cache writes inside sync.Once.Do (CodeRabbit review)
- Fix FindLibraryPathWithOptions not searching dynamic paths
(Flatpak/Snap/Nix) - now uses GetAllLibPaths() (CodeRabbit review)
79 lines
1.7 KiB
Go
79 lines
1.7 KiB
Go
//go:build linux
|
|
|
|
package libpath
|
|
|
|
import "sync"
|
|
|
|
// pathCache holds cached dynamic library paths to avoid repeated
|
|
// expensive filesystem and subprocess operations.
|
|
type pathCache struct {
|
|
mu sync.RWMutex
|
|
flatpak []string
|
|
snap []string
|
|
nix []string
|
|
initOnce sync.Once
|
|
inited bool
|
|
}
|
|
|
|
var cache pathCache
|
|
|
|
// init populates the cache with dynamic paths from package managers.
|
|
// This is called lazily on first access.
|
|
func (c *pathCache) init() {
|
|
c.initOnce.Do(func() {
|
|
// Discover paths without holding the lock
|
|
flatpak := discoverFlatpakLibPaths()
|
|
snap := discoverSnapLibPaths()
|
|
nix := discoverNixLibPaths()
|
|
|
|
// Hold lock only while updating the cache
|
|
c.mu.Lock()
|
|
c.flatpak = flatpak
|
|
c.snap = snap
|
|
c.nix = nix
|
|
c.inited = true
|
|
c.mu.Unlock()
|
|
})
|
|
}
|
|
|
|
// getFlatpak returns cached Flatpak library paths.
|
|
func (c *pathCache) getFlatpak() []string {
|
|
c.init()
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
return c.flatpak
|
|
}
|
|
|
|
// getSnap returns cached Snap library paths.
|
|
func (c *pathCache) getSnap() []string {
|
|
c.init()
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
return c.snap
|
|
}
|
|
|
|
// getNix returns cached Nix library paths.
|
|
func (c *pathCache) getNix() []string {
|
|
c.init()
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
return c.nix
|
|
}
|
|
|
|
// invalidate clears the cache and forces re-discovery on next access.
|
|
func (c *pathCache) invalidate() {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
c.flatpak = nil
|
|
c.snap = nil
|
|
c.nix = nil
|
|
c.initOnce = sync.Once{} // Reset so init() runs again
|
|
c.inited = false
|
|
}
|
|
|
|
// 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.
|
|
func InvalidateCache() {
|
|
cache.invalidate()
|
|
}
|