mirror of
https://github.com/celesrenata/end-4-flakes.git
synced 2026-06-05 18:29:26 -05:00
fix: add wayland dev headers and scanner for pywayland build on NixOS
This commit is contained in:
@@ -0,0 +1,268 @@
|
||||
# Python Virtual Environment for dots-hyprland
|
||||
# This replicates the installer's Python setup exactly
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.dots-hyprland.python;
|
||||
mainCfg = config.programs.dots-hyprland;
|
||||
|
||||
# Virtual environment setup script that replicates installer behavior
|
||||
setupVenvScript = pkgs.writeShellScript "setup-dots-hyprland-venv" ''
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
VENV_PATH="$HOME/.local/state/quickshell/.venv"
|
||||
|
||||
echo "🐍 Setting up dots-hyprland Python virtual environment..."
|
||||
echo "📁 Target: $VENV_PATH"
|
||||
|
||||
# Create directory structure
|
||||
mkdir -p "$(dirname "$VENV_PATH")"
|
||||
|
||||
# Only create venv if it doesn't exist
|
||||
if [[ ! -d "$VENV_PATH" ]]; then
|
||||
echo "🏗️ Creating Python 3.12 virtual environment..."
|
||||
${pkgs.python312}/bin/python -m venv "$VENV_PATH" --prompt .venv
|
||||
else
|
||||
echo "✅ Virtual environment already exists at $VENV_PATH"
|
||||
fi
|
||||
|
||||
# Set up proper library path for Python packages (64-bit only)
|
||||
export LD_LIBRARY_PATH="${lib.makeLibraryPath (with pkgs; [
|
||||
stdenv.cc.cc.lib # provides libstdc++.so.6
|
||||
gcc-unwrapped.lib
|
||||
glibc
|
||||
zlib
|
||||
libffi
|
||||
openssl
|
||||
bzip2
|
||||
xz.out
|
||||
ncurses
|
||||
readline
|
||||
sqlite
|
||||
])}"
|
||||
|
||||
# Clear Python path to avoid conflicts
|
||||
export PYTHONPATH=""
|
||||
export PYTHONDONTWRITEBYTECODE=1
|
||||
|
||||
echo "📚 Library path: $LD_LIBRARY_PATH"
|
||||
|
||||
# Activate and install exact requirements from installer
|
||||
echo "📦 Installing Python packages with proper library linking..."
|
||||
source "$VENV_PATH/bin/activate"
|
||||
|
||||
# Add build tools to PATH for building Python packages
|
||||
export PATH="${pkgs.cmake}/bin:${pkgs.pkg-config}/bin:${pkgs.gcc}/bin:${pkgs.gnumake}/bin:$PATH"
|
||||
export CMAKE_GENERATOR="Unix Makefiles"
|
||||
export CMAKE_MAKE_PROGRAM="${pkgs.gnumake}/bin/make"
|
||||
export CC="${pkgs.gcc}/bin/gcc"
|
||||
export CXX="${pkgs.gcc}/bin/g++"
|
||||
|
||||
# Set wayland protocol path for pywayland
|
||||
export PKG_CONFIG_PATH="${pkgs.wayland.dev}/lib/pkgconfig:${pkgs.wayland-protocols}/share/pkgconfig:${pkgs.wayland-scanner.dev}/lib/pkgconfig"
|
||||
export WAYLAND_PROTOCOLS_DIR="${pkgs.wayland-scanner}/share/wayland"
|
||||
export C_INCLUDE_PATH="${pkgs.wayland.dev}/include:${C_INCLUDE_PATH:-}"
|
||||
export PATH="${pkgs.wayland-scanner}/bin:$PATH"
|
||||
|
||||
# Upgrade pip first
|
||||
pip install --upgrade pip
|
||||
|
||||
# Install exact versions from scriptdata/requirements.txt
|
||||
pip install --no-cache-dir --force-reinstall \
|
||||
build==1.2.2.post1 \
|
||||
cffi==1.17.1 \
|
||||
libsass==0.23.0 \
|
||||
material-color-utilities==0.2.1 \
|
||||
materialyoucolor==2.0.10 \
|
||||
numpy==2.2.2 \
|
||||
packaging==24.2 \
|
||||
pillow==11.1.0 \
|
||||
psutil==6.1.1 \
|
||||
pycparser==2.22 \
|
||||
pyproject-hooks==1.2.0 \
|
||||
setproctitle==1.3.4 \
|
||||
setuptools==80.9.0 \
|
||||
setuptools-scm==8.1.0 \
|
||||
wheel==0.45.1 \
|
||||
pywayland==0.4.18
|
||||
|
||||
# Test critical imports
|
||||
echo "🧪 Testing critical package imports..."
|
||||
python -c "
|
||||
import sys
|
||||
print(f'Python: {sys.version}')
|
||||
|
||||
tests = [
|
||||
('materialyoucolor', 'materialyoucolor'),
|
||||
('material_color_utilities', 'material_color_utilities'),
|
||||
('sass', 'sass'),
|
||||
('numpy', 'numpy'),
|
||||
('PIL', 'PIL'),
|
||||
('pywayland.client', 'pywayland.client'),
|
||||
('psutil', 'psutil'),
|
||||
('setproctitle', 'setproctitle')
|
||||
]
|
||||
|
||||
working = 0
|
||||
for name, module in tests:
|
||||
try:
|
||||
__import__(module)
|
||||
print(f'✅ {name}')
|
||||
working += 1
|
||||
except Exception as e:
|
||||
print(f'❌ {name}: {e}')
|
||||
|
||||
print(f'📊 {working}/{len(tests)} packages working')
|
||||
if working == len(tests):
|
||||
print('🎉 All critical packages imported successfully!')
|
||||
else:
|
||||
print('⚠️ Some packages failed - may need additional system libraries')
|
||||
"
|
||||
|
||||
deactivate
|
||||
|
||||
echo "✅ Python virtual environment setup complete!"
|
||||
echo "🔗 Environment variable: ILLOGICAL_IMPULSE_VIRTUAL_ENV=$VENV_PATH"
|
||||
echo "📚 Library path configured for NixOS compatibility"
|
||||
'';
|
||||
|
||||
# Test script to verify the Python environment works
|
||||
testVenvScript = pkgs.writeShellScript "test-dots-hyprland-venv" ''
|
||||
#!/usr/bin/env bash
|
||||
|
||||
VENV_PATH="$HOME/.local/state/quickshell/.venv"
|
||||
|
||||
echo "🧪 Testing dots-hyprland Python virtual environment..."
|
||||
|
||||
if [[ ! -d "$VENV_PATH" ]]; then
|
||||
echo "❌ Virtual environment not found at $VENV_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$VENV_PATH/bin/activate"
|
||||
|
||||
# Test critical packages
|
||||
echo "📦 Testing Python packages..."
|
||||
python -c "import material_color_utilities; print('✅ material-color-utilities')" || echo "❌ material-color-utilities"
|
||||
python -c "import materialyoucolor; print('✅ materialyoucolor')" || echo "❌ materialyoucolor"
|
||||
python -c "import pywayland; print('✅ pywayland')" || echo "❌ pywayland"
|
||||
python -c "import PIL; print('✅ pillow')" || echo "❌ pillow"
|
||||
python -c "import numpy; print('✅ numpy')" || echo "❌ numpy"
|
||||
python -c "import psutil; print('✅ psutil')" || echo "❌ psutil"
|
||||
|
||||
deactivate
|
||||
|
||||
echo "🎉 Python environment test complete!"
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.programs.dots-hyprland.python = {
|
||||
enable = mkEnableOption "Python virtual environment for dots-hyprland";
|
||||
|
||||
venvPath = mkOption {
|
||||
type = types.str;
|
||||
default = "$HOME/.local/state/quickshell/.venv";
|
||||
description = "Path to Python virtual environment";
|
||||
};
|
||||
|
||||
autoSetup = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Automatically set up virtual environment on activation";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Install system Python and required build dependencies + test script
|
||||
home.packages = with pkgs; [
|
||||
python312
|
||||
python312Packages.pip
|
||||
python312Packages.virtualenv
|
||||
|
||||
# System dependencies for Python packages (from illogical-impulse-python PKGBUILD)
|
||||
clang
|
||||
gtk4
|
||||
libadwaita
|
||||
libsoup_3
|
||||
libportal-gtk4
|
||||
gobject-introspection
|
||||
sassc
|
||||
opencv4
|
||||
|
||||
# Critical system libraries for Python packages (64-bit)
|
||||
gcc-unwrapped.lib # Provides proper libstdc++.so.6
|
||||
glibc
|
||||
zlib
|
||||
libffi
|
||||
openssl
|
||||
|
||||
# Additional libraries that might be needed
|
||||
bzip2
|
||||
xz
|
||||
ncurses
|
||||
readline
|
||||
sqlite
|
||||
|
||||
# Development tools
|
||||
pkg-config
|
||||
cairo
|
||||
gdk-pixbuf
|
||||
glib
|
||||
|
||||
# Test script
|
||||
(writeShellScriptBin "test-dots-hyprland-venv" ''
|
||||
${testVenvScript}
|
||||
'')
|
||||
];
|
||||
|
||||
# Set up virtual environment on Home Manager activation
|
||||
# Only rebuilds if packages change
|
||||
home.activation.setupDotsHyprlandVenv = mkIf cfg.autoSetup (
|
||||
lib.hm.dag.entryAfter ["writeBoundary"] ''
|
||||
VENV_PATH="${cfg.venvPath}"
|
||||
MARKER_FILE="$VENV_PATH/.nix-built"
|
||||
EXPECTED_HASH="${builtins.hashString "sha256" (builtins.readFile setupVenvScript)}"
|
||||
|
||||
# Only rebuild if venv doesn't exist or script changed
|
||||
if [[ ! -f "$MARKER_FILE" ]] || [[ "$(cat "$MARKER_FILE" 2>/dev/null)" != "$EXPECTED_HASH" ]]; then
|
||||
echo "🐍 Building Python venv (this takes ~10 minutes on first run)..."
|
||||
$DRY_RUN_CMD ${setupVenvScript}
|
||||
$DRY_RUN_CMD echo "$EXPECTED_HASH" > "$MARKER_FILE"
|
||||
else
|
||||
echo "✅ Python venv already up to date"
|
||||
fi
|
||||
''
|
||||
);
|
||||
|
||||
# Set critical environment variable and library paths
|
||||
home.sessionVariables = {
|
||||
ILLOGICAL_IMPULSE_VIRTUAL_ENV = cfg.venvPath;
|
||||
# Ensure Python packages can find system libraries (64-bit only)
|
||||
LD_LIBRARY_PATH = lib.makeLibraryPath (with pkgs; [
|
||||
gcc-unwrapped.lib
|
||||
glibc
|
||||
zlib
|
||||
libffi
|
||||
openssl
|
||||
bzip2
|
||||
xz.out
|
||||
ncurses
|
||||
readline
|
||||
sqlite
|
||||
]);
|
||||
# Additional environment variables for Python
|
||||
PYTHONPATH = ""; # Clear to avoid conflicts
|
||||
PYTHONDONTWRITEBYTECODE = "1"; # Prevent .pyc files
|
||||
|
||||
# QML import paths for quickshell
|
||||
QML2_IMPORT_PATH = lib.concatStringsSep ":" (with pkgs; [
|
||||
"${kdePackages.qt5compat}/lib/qt-6/qml"
|
||||
"${kdePackages.qtdeclarative}/lib/qt-6/qml"
|
||||
"${kdePackages.qtwayland}/lib/qt-6/qml"
|
||||
]);
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user