nip/src/nimpak/variant_mappings.nim

233 lines
6.7 KiB
Nim

# SPDX-License-Identifier: LSL-1.0
# Copyright (c) 2026 Markus Maiwald
# Stewardship: Self Sovereign Society Foundation
#
# This file is part of the Nexus Sovereign Core.
# See legal/LICENSE_SOVEREIGN.md for license terms.
## variant_mappings.nim
## Maps NIP variant domains to package manager specific flags
## Each package can have custom mappings, with fallback to generic mappings
import std/[tables, strutils, json, os]
type
PackageManagerFlag* = object
nix*: string # Nix override attribute
pkgsrc*: string # PKGSRC PKG_OPTIONS flag
gentoo*: string # Gentoo USE flag
description*: string
VariantMapping* = object
domain*: string
value*: string
flags*: PackageManagerFlag
# Generic variant mappings (work for most packages)
const GenericMappings* = {
# Graphics domain
("graphics", "wayland"): PackageManagerFlag(
nix: "waylandSupport = true",
pkgsrc: "wayland",
gentoo: "wayland",
description: "Wayland display server support"
),
("graphics", "X"): PackageManagerFlag(
nix: "x11Support = true",
pkgsrc: "x11",
gentoo: "X",
description: "X11 display server support"
),
("graphics", "vulkan"): PackageManagerFlag(
nix: "vulkanSupport = true",
pkgsrc: "vulkan",
gentoo: "vulkan",
description: "Vulkan graphics API"
),
# Audio domain
("audio", "pipewire"): PackageManagerFlag(
nix: "pipewireSupport = true",
pkgsrc: "pipewire",
gentoo: "pipewire",
description: "PipeWire audio server"
),
("audio", "pulseaudio"): PackageManagerFlag(
nix: "pulseaudioSupport = true",
pkgsrc: "pulseaudio",
gentoo: "pulseaudio",
description: "PulseAudio sound server"
),
("audio", "alsa"): PackageManagerFlag(
nix: "alsaSupport = true",
pkgsrc: "alsa",
gentoo: "alsa",
description: "ALSA audio support"
),
# Optimization domain
("optimization", "lto"): PackageManagerFlag(
nix: "enableLTO = true",
pkgsrc: "-flto",
gentoo: "lto",
description: "Link-time optimization"
),
("optimization", "pgo"): PackageManagerFlag(
nix: "enablePGO = true",
pkgsrc: "-fprofile-generate",
gentoo: "pgo",
description: "Profile-guided optimization"
),
# Security domain
("security", "pie"): PackageManagerFlag(
nix: "hardeningEnable = [\"pie\"]",
pkgsrc: "-fPIE",
gentoo: "pie",
description: "Position independent executable"
),
("security", "hardened"): PackageManagerFlag(
nix: "hardeningEnable = [\"all\"]",
pkgsrc: "hardened",
gentoo: "hardened",
description: "Full hardening"
)
}.toTable
# Package-specific mappings (override generic for specific packages)
const PackageSpecificMappings* = {
# Firefox specific
("firefox", "graphics", "wayland"): PackageManagerFlag(
nix: "waylandSupport = true",
pkgsrc: "wayland",
gentoo: "wayland",
description: "Firefox Wayland support"
),
("firefox", "audio", "pipewire"): PackageManagerFlag(
nix: "pipewireSupport = true",
pkgsrc: "pulseaudio", # PKGSRC firefox uses pulseaudio flag
gentoo: "pipewire",
description: "Firefox audio via PipeWire"
),
# Chromium specific
("chromium", "graphics", "wayland"): PackageManagerFlag(
nix: "enableWayland = true",
pkgsrc: "wayland",
gentoo: "wayland",
description: "Chromium Wayland support"
),
# NGINX specific
("nginx", "network", "ipv6"): PackageManagerFlag(
nix: "withIPv6 = true",
pkgsrc: "inet6",
gentoo: "ipv6",
description: "IPv6 support"
)
}.toTable
proc getVariantMapping*(packageName: string, domain: string, value: string): PackageManagerFlag =
## Get the package manager flags for a variant
## Checks package-specific mappings first, then falls back to generic
# Check package-specific mapping
let specificKey = (packageName.toLower(), domain, value)
if PackageSpecificMappings.hasKey(specificKey):
return PackageSpecificMappings[specificKey]
# Fall back to generic mapping
let genericKey = (domain, value)
if GenericMappings.hasKey(genericKey):
return GenericMappings[genericKey]
# Return empty if not found
result = PackageManagerFlag(
nix: "",
pkgsrc: "",
gentoo: "",
description: "Unknown variant"
)
proc loadCustomMappings*(mappingFile: string): Table[(string, string, string), PackageManagerFlag] =
## Load custom variant mappings from a JSON file
## Format: { "package": { "domain": { "value": { "nix": "...", "pkgsrc": "...", "gentoo": "..." } } } }
result = initTable[(string, string, string), PackageManagerFlag]()
if not fileExists(mappingFile):
return
try:
let content = readFile(mappingFile)
let json = parseJson(content)
for packageName, packageData in json.pairs:
for domain, domainData in packageData.pairs:
for value, flagData in domainData.pairs:
let flags = PackageManagerFlag(
nix: flagData{"nix"}.getStr(""),
pkgsrc: flagData{"pkgsrc"}.getStr(""),
gentoo: flagData{"gentoo"}.getStr(""),
description: flagData{"description"}.getStr("")
)
result[(packageName, domain, value)] = flags
except:
discard
proc showVariantMappings*(packageName: string = "", domain: string = "") =
## Show available variant mappings
echo "🗺️ Variant Mappings"
echo ""
if packageName != "":
echo "Package-specific mappings for: " & packageName
echo ""
for key, flags in PackageSpecificMappings:
let (pkg, dom, val) = key
if pkg == packageName.toLower():
echo " " & dom & "=" & val
echo " Nix: " & flags.nix
echo " PKGSRC: " & flags.pkgsrc
echo " Gentoo: " & flags.gentoo
echo ""
else:
echo "Generic mappings:"
echo ""
for key, flags in GenericMappings:
let (dom, val) = key
if domain == "" or dom == domain:
echo " " & dom & "=" & val
echo " Nix: " & flags.nix
echo " PKGSRC: " & flags.pkgsrc
echo " Gentoo: " & flags.gentoo
echo " " & flags.description
echo ""
proc generateMappingTemplate*(outputFile: string) =
## Generate a template JSON file for custom mappings
let mappingTemplate = %*{
"firefox": {
"graphics": {
"wayland": {
"nix": "waylandSupport = true",
"pkgsrc": "wayland",
"gentoo": "wayland",
"description": "Wayland support"
}
}
},
"nginx": {
"network": {
"ipv6": {
"nix": "withIPv6 = true",
"pkgsrc": "inet6",
"gentoo": "ipv6",
"description": "IPv6 support"
}
}
}
}
writeFile(outputFile, mappingTemplate.pretty())
echo "✅ Generated mapping template: " & outputFile