diff --git a/Configs/.local/bin/hyde-shell b/Configs/.local/bin/hyde-shell index aaf5c19cc0..72e6d28675 100755 --- a/Configs/.local/bin/hyde-shell +++ b/Configs/.local/bin/hyde-shell @@ -532,8 +532,18 @@ export BIN_DIR LIB_DIR SHARE_DIR PATH HYDE_SCRIPTS_PATH #*-------------------------------------------------------------------------------- +if [[ -z "${XDG_RUNTIME_DIR:-}" ]]; then + if [[ "$(uname -s)" == "FreeBSD" ]]; then + export XDG_RUNTIME_DIR="/tmp/runtime-$(id -u)" + else + export XDG_RUNTIME_DIR="/run/user/$(id -u)" + fi +fi +[[ -d "${XDG_RUNTIME_DIR}" ]] || mkdir -p "${XDG_RUNTIME_DIR}" +chmod 700 "${XDG_RUNTIME_DIR}" 2>/dev/null || true + # Prepare runtime directory for hyde -[[ -d "${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/hyde" ]] || mkdir -p "${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/hyde" +[[ -d "${XDG_RUNTIME_DIR}/hyde" ]] || mkdir -p "${XDG_RUNTIME_DIR}/hyde" # Priority commands case "$1" in diff --git a/Configs/.local/lib/hyde/globalcontrol.sh b/Configs/.local/lib/hyde/globalcontrol.sh index 59c5e638f3..8ec4a80e6a 100755 --- a/Configs/.local/lib/hyde/globalcontrol.sh +++ b/Configs/.local/lib/hyde/globalcontrol.sh @@ -3,7 +3,15 @@ export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}" export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}" export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" -export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" +if [[ -z "${XDG_RUNTIME_DIR:-}" ]]; then + if [[ "$(uname -s)" == "FreeBSD" ]]; then + export XDG_RUNTIME_DIR="/tmp/runtime-$(id -u)" + else + export XDG_RUNTIME_DIR="/run/user/$(id -u)" + fi +fi +[[ -d "${XDG_RUNTIME_DIR}" ]] || mkdir -p "${XDG_RUNTIME_DIR}" +chmod 700 "${XDG_RUNTIME_DIR}" 2>/dev/null || true export HYDE_CONFIG_HOME="$XDG_CONFIG_HOME/hyde" export HYDE_DATA_HOME="$XDG_DATA_HOME/hyde" export HYDE_CACHE_HOME="$XDG_CACHE_HOME/hyde" @@ -178,6 +186,7 @@ get_themes() { unset thmSort unset thmList unset thmWall + [ -d "$HYDE_CONFIG_HOME/themes" ] || return 0 while read -r thmDir; do local realWallPath realWallPath="$(readlink "$thmDir/wall.set")" @@ -215,7 +224,7 @@ case "$enableWallDcol" in esac if [ -z "$HYDE_THEME" ] || [ ! -d "$HYDE_CONFIG_HOME/themes/$HYDE_THEME" ]; then get_themes - HYDE_THEME="${thmList[0]}" + [ "${#thmList[@]}" -gt 0 ] && HYDE_THEME="${thmList[0]}" fi HYDE_THEME_DIR="$HYDE_CONFIG_HOME/themes/$HYDE_THEME" WALLBASH_DIRS=( diff --git a/Configs/.local/lib/hyde/pm.sh b/Configs/.local/lib/hyde/pm.sh index 75ddc2145e..2ea285c61e 100755 --- a/Configs/.local/lib/hyde/pm.sh +++ b/Configs/.local/lib/hyde/pm.sh @@ -207,7 +207,7 @@ skip_table_header() { xargs_self() { xargs -r sh -c '"$0" "$@" /dev/null || pkg search -x "$1" +} +pkg_list_all() { + pkg rquery '%n %v' +} +pkg_list_installed() { + pkg query '%n %v' +} +pkg_format_all() { + awk "{ print $FMT_NAME \$1 $FMT_VERSION \$2 $FMT_RESET }" +} +pkg_format_installed() { + awk "{ print $FMT_NAME \$1 $FMT_VERSION \$2 $FMT_RESET }" +} +pkg_is_installed() { + pkg info -e "$1" > /dev/null 2>&1 && echo "Installed" || { + echo "Not installed" && return 1 + } +} +pkg_file_query() { + pkg which "$1" +} AUR_HELPERS="paru paru-bin yay yay-bin" aur_helpers_contain() { for NAME in $AUR_HELPERS; do diff --git a/Configs/.local/lib/hyde/pyutils/pip_env.py b/Configs/.local/lib/hyde/pyutils/pip_env.py index 2562e248af..cf8c645a6a 100644 --- a/Configs/.local/lib/hyde/pyutils/pip_env.py +++ b/Configs/.local/lib/hyde/pyutils/pip_env.py @@ -20,7 +20,7 @@ def is_venv_valid(venv_path): """Returns whether the venv is valid or not - + Args: venv_path: Path to the virtual environment to validate """ @@ -32,8 +32,8 @@ def is_venv_valid(venv_path): # 1.- Must have its own python file and it must be executable if not (os.path.isfile(python_exe) and os.access(python_exe, os.X_OK)): return False - - # 2.- Python inside venv must be able to import pip + + # 2.- Python inside venv must be able to import pip try: res = subprocess.run( [python_exe, "-c", "import pip"], @@ -45,7 +45,7 @@ def is_venv_valid(venv_path): return False except Exception: return False - + # 3.- Python version used to create the venv must match current one if os.path.exists(pyvenv_cfg): try: @@ -345,9 +345,12 @@ def main(args): args = parser.parse_args(args) venv_path = get_venv_path() - requirements_file = os.path.join( - xdg_base_dirs.user_lib_dir(), "hyde", "pyutils", "requirements.txt" - ) + requirements_dir = os.path.join(xdg_base_dirs.user_lib_dir(), "hyde", "pyutils") + requirements_file = os.path.join(requirements_dir, "requirements.txt") + if sys.platform.startswith("freebsd"): + freebsd_requirements = os.path.join(requirements_dir, "requirements-freebsd.txt") + if os.path.exists(freebsd_requirements): + requirements_file = freebsd_requirements if args.command == "create": args.func(venv_path, requirements_file) diff --git a/Configs/.local/lib/hyde/pyutils/requirements-freebsd.txt b/Configs/.local/lib/hyde/pyutils/requirements-freebsd.txt new file mode 100644 index 0000000000..521d7770dd --- /dev/null +++ b/Configs/.local/lib/hyde/pyutils/requirements-freebsd.txt @@ -0,0 +1,4 @@ +loguru==0.7.3 +pulsectl==24.12.0 +requests==2.32.4 +PyGObject diff --git a/Configs/.local/lib/hyde/resetxdgportal.sh b/Configs/.local/lib/hyde/resetxdgportal.sh index a955a2fa91..6e9e6c8b9a 100755 --- a/Configs/.local/lib/hyde/resetxdgportal.sh +++ b/Configs/.local/lib/hyde/resetxdgportal.sh @@ -6,6 +6,8 @@ killall -e xdg-desktop-portal sleep 1 if [ -d /run/current-system/sw/libexec ]; then libDir=/run/current-system/sw/libexec +elif [ -d /usr/local/libexec ]; then + libDir=/usr/local/libexec else libDir=/usr/lib fi diff --git a/Configs/.local/lib/hyde/theme.switch.sh b/Configs/.local/lib/hyde/theme.switch.sh index c652124351..c7e91239a2 100755 --- a/Configs/.local/lib/hyde/theme.switch.sh +++ b/Configs/.local/lib/hyde/theme.switch.sh @@ -3,6 +3,13 @@ [ -z "$HYDE_THEME" ] && echo "ERROR: unable to detect theme" && exit 1 get_themes confDir="${XDG_CONFIG_HOME:-$HOME/.config}" +sed_in_place() { + if sed --version >/dev/null 2>&1; then + sed -i "$@" + else + sed -i '' "$@" + fi +} Theme_Change() { local x_switch=$1 for i in "${!thmList[@]}"; do @@ -85,7 +92,7 @@ sanitize_hypr_theme() { dirty_regex+=("${HYPR_CONFIG_SANITIZE[@]}") for pattern in "${dirty_regex[@]}"; do grep -E "$pattern" "$buffer_file" | while read -r line; do - sed -i "\|$line|d" "$buffer_file" + sed_in_place "\|$line|d" "$buffer_file" print_log -sec "theme" -warn "sanitize" "$line" done done @@ -130,8 +137,12 @@ if [[ -r $HYPRLAND_CONFIG ]]; then load_hypr_variables "${XDG_STATE_DIR:-$HOME/.local/state}/hyde/hyprland.conf" fi show_theme_status -if ! dconf write /org/gnome/desktop/interface/icon-theme "'$ICON_THEME'"; then - print_log -sec "theme" -warn "dconf" "failed to set icon theme" +if command -v dconf >/dev/null 2>&1 && { [[ -n "${DBUS_SESSION_BUS_ADDRESS:-}" ]] || [[ -n "${DISPLAY:-}" ]]; }; then + if ! dconf write /org/gnome/desktop/interface/icon-theme "'$ICON_THEME'"; then + print_log -sec "theme" -warn "dconf" "failed to set icon theme" + fi +else + print_log -sec "theme" -warn "dconf" "no active DBus session; skipping icon theme write" fi if [ -d /run/current-system/sw/share/themes ]; then export themesDir=/run/current-system/sw/share/themes @@ -159,10 +170,10 @@ toml_write "$confDir/kdeglobals" "UiSettings" "ColorScheme" "colors" toml_write "$confDir/kdeglobals" "KDE" "widgetStyle" "kvantum" toml_write "$XDG_DATA_HOME/icons/default/index.theme" "Icon Theme" "Inherits" "$CURSOR_THEME" toml_write "$HOME/.icons/default/index.theme" "Icon Theme" "Inherits" "$CURSOR_THEME" -sed -i -e "/^gtk-theme-name=/c\gtk-theme-name=\"$GTK_THEME\"" \ - -e "/^include /c\include \"$HOME/.gtkrc-2.0.mime\"" \ - -e "/^gtk-cursor-theme-name=/c\gtk-cursor-theme-name=\"$CURSOR_THEME\"" \ - -e "/^gtk-icon-theme-name=/c\gtk-icon-theme-name=\"$ICON_THEME\"" "$HOME/.gtkrc-2.0" +sed_in_place -e "s|^gtk-theme-name=.*$|gtk-theme-name=\"$GTK_THEME\"|" \ + -e "s|^include .*$|include \"$HOME/.gtkrc-2.0.mime\"|" \ + -e "s|^gtk-cursor-theme-name=.*$|gtk-cursor-theme-name=\"$CURSOR_THEME\"|" \ + -e "s|^gtk-icon-theme-name=.*$|gtk-icon-theme-name=\"$ICON_THEME\"|" "$HOME/.gtkrc-2.0" GTK3_FONT="${GTK3_FONT:-$FONT}" GTK3_FONT_SIZE="${GTK3_FONT_SIZE:-$FONT_SIZE}" toml_write "$confDir/gtk-3.0/settings.ini" "Settings" "gtk-theme-name" "$GTK_THEME" @@ -193,10 +204,10 @@ if pkg_installed flatpak; then --env=ICON_THEME="$ICON_THEME" flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo & fi -sed -i -e "/^Net\/ThemeName /c\Net\/ThemeName \"$GTK_THEME\"" \ - -e "/^Net\/IconThemeName /c\Net\/IconThemeName \"$ICON_THEME\"" \ - -e "/^Gtk\/CursorThemeName /c\Gtk\/CursorThemeName \"$CURSOR_THEME\"" \ - -e "/^Gtk\/CursorThemeSize /c\Gtk\/CursorThemeSize $CURSOR_SIZE" \ +sed_in_place -e "s|^Net/ThemeName .*$|Net/ThemeName \"$GTK_THEME\"|" \ + -e "s|^Net/IconThemeName .*$|Net/IconThemeName \"$ICON_THEME\"|" \ + -e "s|^Gtk/CursorThemeName .*$|Gtk/CursorThemeName \"$CURSOR_THEME\"|" \ + -e "s|^Gtk/CursorThemeSize .*$|Gtk/CursorThemeSize $CURSOR_SIZE|" \ "$confDir/xsettingsd/xsettingsd.conf" if [ ! -L "$HOME/.themes/$GTK_THEME" ] && [ -d "$themesDir/$GTK_THEME" ]; then print_log -sec "theme" -warn "linking" "$GTK_THEME to ~/.themes to fix GTK4 not following xdg" @@ -205,8 +216,8 @@ if [ ! -L "$HOME/.themes/$GTK_THEME" ] && [ -d "$themesDir/$GTK_THEME" ]; then ln -snf "$themesDir/$GTK_THEME" "$HOME/.themes/" fi if [ -f "$HOME/.Xresources" ]; then - sed -i -e "/^Xcursor\.theme:/c\Xcursor.theme: $CURSOR_THEME" \ - -e "/^Xcursor\.size:/c\Xcursor.size: $CURSOR_SIZE" "$HOME/.Xresources" + sed_in_place -e "s|^Xcursor\.theme:.*$|Xcursor.theme: $CURSOR_THEME|" \ + -e "s|^Xcursor\.size:.*$|Xcursor.size: $CURSOR_SIZE|" "$HOME/.Xresources" grep -q "^Xcursor\.theme:" "$HOME/.Xresources" || echo "Xcursor.theme: $CURSOR_THEME" >>"$HOME/.Xresources" grep -q "^Xcursor\.size:" "$HOME/.Xresources" || echo "Xcursor.size: 30" >>"$HOME/.Xresources" else @@ -216,8 +227,8 @@ Xcursor.size: $CURSOR_SIZE EOF fi if [ -f "$HOME/.Xdefaults" ]; then - sed -i -e "/^Xcursor\.theme:/c\Xcursor.theme: $CURSOR_THEME" \ - -e "/^Xcursor\.size:/c\Xcursor.size: $CURSOR_SIZE" "$HOME/.Xdefaults" + sed_in_place -e "s|^Xcursor\.theme:.*$|Xcursor.theme: $CURSOR_THEME|" \ + -e "s|^Xcursor\.size:.*$|Xcursor.size: $CURSOR_SIZE|" "$HOME/.Xdefaults" grep -q "^Xcursor\.theme:" "$HOME/.Xdefaults" || echo "Xcursor.theme: $CURSOR_THEME" >>"$HOME/.Xdefaults" grep -q "^Xcursor\.size:" "$HOME/.Xdefaults" || echo "Xcursor.size: 30" >>"$HOME/.Xdefaults" fi diff --git a/Configs/.local/lib/hyde/waybar.py b/Configs/.local/lib/hyde/waybar.py index 8cc598226b..50e03981a6 100755 --- a/Configs/.local/lib/hyde/waybar.py +++ b/Configs/.local/lib/hyde/waybar.py @@ -68,6 +68,7 @@ STATE_FILE = Path(os.path.join(str(xdg_state_home()), "hyde", "staterc")) HYDE_CONFIG = Path(os.path.join(str(xdg_state_home()), "hyde", "config")) UNIT_NAME = f"hyde-{os.environ.get('XDG_SESSION_DESKTOP', 'unknown')}-bar.service" +HAS_SYSTEMCTL = shutil.which("systemctl") is not None def source_env_file(filepath): @@ -500,6 +501,10 @@ def signal_handler(sig, frame): def is_waybar_running_for_current_user(): """Check if Waybar or Waybar-wrapped is running for the current user only.""" + if not HAS_SYSTEMCTL: + result = subprocess.run(["pgrep", "-x", "waybar"], capture_output=True, text=True) + return result.returncode == 0 + check_cmd = ["systemctl", "--user", "is-active", UNIT_NAME] try: result = subprocess.run(check_cmd, capture_output=True, text=True) @@ -514,6 +519,14 @@ def is_waybar_running_for_current_user(): def run_waybar(): """Run Waybar using hyde-shell app with systemd unit, let systemd handle logging.""" + if not HAS_SYSTEMCTL: + if not is_waybar_running_for_current_user(): + subprocess.Popen(["waybar"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + logger.debug("Waybar launched directly (no systemctl available)") + else: + logger.debug("Waybar already running (direct mode)") + return + # check_cmd = ["systemctl", "--user", "is-active", "--quiet", UNIT_NAME] run_cmd = ["hyde-shell", "app", "-u", UNIT_NAME, "-t", "service", "--", "waybar"] # Check if the unit is active @@ -528,6 +541,11 @@ def run_waybar(): def kill_waybar(): """Kill only the current user's Waybar process.""" """Stop Waybar systemd unit for current session desktop.""" + if not HAS_SYSTEMCTL: + subprocess.run(["pkill", "-x", "waybar"]) + logger.debug("Stopped Waybar process directly (no systemctl available)") + return + subprocess.run(["systemctl", "--user", "stop", UNIT_NAME]) logger.debug(f"Stopped Waybar systemd unit: {UNIT_NAME}") @@ -544,6 +562,9 @@ def kill_waybar_and_watcher(): kill_waybar() logger.debug("Killed Waybar processes for current user.") + if not HAS_SYSTEMCTL: + return + try: watcher_unit = f"hyde-{os.getenv('XDG_SESSION_DESKTOP')}-waybar-watcher.service" result = subprocess.run( @@ -1441,8 +1462,12 @@ def main(): if args.hide: # Send SIGUSR1 to Waybar systemd unit - cmd = ["systemctl", "--user", "kill", "-s", "SIGUSR1", UNIT_NAME] - logger.info(f"Sending SIGUSR1 to {UNIT_NAME} via systemctl") + if HAS_SYSTEMCTL: + cmd = ["systemctl", "--user", "kill", "-s", "SIGUSR1", UNIT_NAME] + logger.info(f"Sending SIGUSR1 to {UNIT_NAME} via systemctl") + else: + cmd = ["pkill", "-USR1", "-x", "waybar"] + logger.info("Sending SIGUSR1 to waybar directly (no systemctl)") subprocess.run(cmd) sys.exit(0) diff --git a/README.md b/README.md index ac7be2fd14..0620590eca 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ Multi-language README support EndeavourOS Garuda NixOS + FreeBSD @@ -73,6 +74,8 @@ While installing HyDE alongside another [DE](https://wiki.archlinux.org/title/De For NixOS support there is a separate project being maintained @ [Hydenix](https://github.com/richen604/hydenix/tree/main) +[FreeBSD](https://www.freebsd.org) is supported via HydeBSD. Due to differences in bootloader, kernel, userspace, and package availability, not all features of HyDE may be present. + > [!IMPORTANT] > The install script will auto-detect an NVIDIA card and install nvidia-open-dkms drivers for your kernel. > For legacy cards [check this first](./Scripts/nvidia-db/) diff --git a/Scripts/global_fn.sh b/Scripts/global_fn.sh index 922b729497..461935a22d 100755 --- a/Scripts/global_fn.sh +++ b/Scripts/global_fn.sh @@ -23,8 +23,19 @@ export shlList pkg_installed() { local PkgIn=$1 + local PkgResolved - if pacman -Q "${PkgIn}" &>/dev/null; then + case "${PkgIn}" in + kvantum) PkgResolved="Kvantum" ;; + imagemagick) PkgResolved="ImageMagick7" ;; + *) PkgResolved="${PkgIn}" ;; + esac + + if [[ "${PkgIn}" == "zsh-theme-powerlevel10k" ]] && [[ -d "${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k" ]]; then + return 0 + fi + + if "${pacmanCmd}" query "${PkgResolved}" &>/dev/null; then return 0 else return 1 diff --git a/Scripts/hydevm/README.md b/Scripts/hydevm/README.md index 8b34c504ae..7491a920c8 100644 --- a/Scripts/hydevm/README.md +++ b/Scripts/hydevm/README.md @@ -4,10 +4,12 @@ HydeVM is a streamlined development tool that automatically sets up HyDE in a vi - [HydeVM - Simplified VM Tool for HyDE Contributors](#hydevm---simplified-vm-tool-for-hyde-contributors) - [Hardware Requirements](#hardware-requirements) + - [Hardware Requirements - FreeBSD](#hardware-requirements---freebsd) - [Features](#features) - [Quick Start](#quick-start) - [Arch Linux](#arch-linux) - [NixOS](#nixos) + - [FreeBSD](#freebsd) - [First-Time Setup](#first-time-setup) - [Usage](#usage) - [Basic Commands](#basic-commands) @@ -28,9 +30,9 @@ HydeVM is a streamlined development tool that automatically sets up HyDE in a vi - [Verification Steps](#verification-steps) - [Troubleshooting Hyprland in VM](#troubleshooting-hyprland-in-vm) -**Supported Host Operating Systems:** Arch Linux, NixOS +**Supported Host Operating Systems:** Arch Linux, NixOS, FreeBSD, macOS Silicon -## Hardware Requirements +## Hardware Requirements (non macOS) **CPU:** x86_64 with virtualization support (Intel VT-x or AMD-V, enabled in BIOS) **Memory:** 4GB+ RAM (VM uses 4GB by default) @@ -43,6 +45,22 @@ HydeVM is a streamlined development tool that automatically sets up HyDE in a vi **OpenGL:** 3.3+ support required for Hyprland **Note:** Tested on AMD GPU + Intel CPU. Hyprland VM support is experimental. +### Hardware Requirements - FreeBSD + +**CPU:** `x86_64/amd64` machines require `EPT` if *Intel* or `RVI/NPT` if AMD + +**GPU & OpenGL Support:** From [Chapter 5.2. Graphics Drivers - FreeBSD Handbook](https://docs.freebsd.org/en/books/handbook/x11/#x-graphic-card-drivers) + +| *Type* | *License* | *Module* | *Port* | +|-----------------------------|--------------|------------------------------------|-----------------------------------------------| +| Intel® | Open Source | `i915kms` | `graphics/drm-kmod` | +| AMD® | Open Source | `amdgpu` / `radeonkms` | `graphics/drm-kmod` | +| NVIDIA® | Proprietary | `nvidia-drm` / `nvidia-modeset` / `nvidia` | `graphics/nvidia-drm-kmod`, `x11/nvidia-driver` | +| System Console Framebuffer | Open Source | `scfb` | `x11-drivers`/`xf86-video-scfb` | +| VESA BIOS Extension | Open Source | `vesa` | `x11-drivers`/`xf86-video-vesa` | +| VirtualBox® | Open Source | `vboxvideo` | `emulators`/`virtualbox-ose-additions` | +| VMware® | Open Source | `vmwgfx` | `x11-drivers`/`xf86-video-vmware` | + ## Features - **Zero Configuration**: Automatically downloads Arch Linux base image and sets up HyDE @@ -53,7 +71,7 @@ HydeVM is a streamlined development tool that automatically sets up HyDE in a vi ## Quick Start -### Arch Linux +### Arch Linux, FreeBSD, and macOS Silicon ```bash # Download and run (will auto-detect missing packages) @@ -77,7 +95,7 @@ nix run When you run a new branch/commit for the first time, hydevm will: 1. **OS Detection**: Automatically detects your OS and checks dependencies -2. **Dependency Installation**: (Arch only) Prompts to install missing packages +2. **Dependency Installation**: (Arch & FreeBSD only) Prompts to install missing packages 3. **VM Setup**: Shows a VM window with setup instructions 4. **HyDE Installation**: You'll need to: - Login as `arch` / `arch` @@ -116,7 +134,7 @@ hydevm --clean # Check dependencies hydevm --check-deps -# Install dependencies (Arch only) +# Install dependencies (Arch & FreeBSD only) hydevm --install-deps ``` @@ -154,10 +172,53 @@ sudo usermod -a -G kvm $USER virtualisation.libvirtd.enable = true; ``` +### FreeBSD - command not found: qemu +> [!NOTE] +> Adopted from [Chapter 24.6. Virtualization with QEMU on FreeBSD](https://docs.freebsd.org/en/books/handbook/virtualization/#qemu-virtualization-host-guest) by @MFarabi619 + +```bash +# modified to not override pre-existing ones, and restore broken setups to a working default from handbook as of March 21, 2026, 1:34 PM +sudo pkg install qemu + +# checks if symlink doesn't exist or points to the wrong location +if [ "$(readlink /usr/local/bin/qemu)" != "/usr/local/bin/qemu-system-x86_64" ]; then + sudo ln -sf /usr/local/bin/qemu-system-x86_64 /usr/local/bin/qemu +fi + +sudo sysctl net.link.tap.user_open=1 +sudo grep -qxF "net.link.tap.user_open=1" /etc/sysctl.conf || \ +echo 'net.link.tap.user_open=1' | sudo tee -a /etc/sysctl.conf +sudo grep -qxF "add path 'tap*' mode 0660 group operator" /etc/devfs.rules || \ +printf "add path 'tap*' mode 0660 group operator\n" | sudo tee -a /etc/devfs.rules + +# should show window saying boot failed .... no bootable device, proves that qemu is working as intended +qemu +``` + +#### FreeBSD - [Bhyve](https://bhyve.org) +> [!NOTE] +> Adopted from [Chapter 24.6. Virtualization with QEMU on FreeBSD](https://docs.freebsd.org/en/books/handbook/virtualization/#virtualization-host-bhyve) by @MFarabi619 + +```bash +sudo kldload vmm + +sudo ifconfig tap0 create +sudo sysctl net.link.tap.up_on_open=1 +sudo grep -qxF "net.link.tap.up_on_open=1" /etc/sysctl.conf || \ +echo 'net.link.tap.up_on_open=1' | sudo tee -a /etc/sysctl.conf +sudo grep -qxF "add path 'tap*' mode 0660 group operator" /etc/devfs.rules || \ +printf "add path 'tap*' mode 0660 group operator\n" | sudo tee -a /etc/devfs.rules + +sudo ifconfig bridge0 create +sudo ifconfig bridge0 addm igb0 addm tap0 +sudo ifconfig bridge0 up +``` + ### Missing Dependencies - **Arch**: Script will prompt to install missing packages - **NixOS**: Nix will automatically install missing packages +- **FreeBSD**: Script will prompt to install missing packages ### Clean Start @@ -213,6 +274,7 @@ nixGL nix run github:HyDE-Project/HyDE **Packages (Arch):** `qemu-desktop mesa` **Packages (NixOS):** `qemu mesa` +**Packages (FreeBSD):** `qemu drm-kmod` **NixOS Configuration:** @@ -241,6 +303,7 @@ hydevm **Packages (Arch):** `qemu-desktop mesa intel-media-driver` **Packages (NixOS):** `qemu mesa intel-media-driver` +**Packages (FreeBSD):** `qemu drm-kmod` **NixOS Configuration:** @@ -265,6 +328,12 @@ lsmod | grep virtio hydevm ``` +**FreeBSD Configuration:** + +```bash +sudo pkg install qemu drm-kmod +``` + ### NVIDIA GPU + Any CPU ⚠️ Option 1: Proprietary Drivers (May have issues) @@ -311,6 +380,9 @@ glxinfo | grep "OpenGL renderer" hydevm ``` +#### FreeBSD (WIP) +TODO: cover various NVIDIA installation paths and common problems + Option 3: Software Rendering (Fallback) ```bash diff --git a/Scripts/hydevm/hydevm.sh b/Scripts/hydevm/hydevm.sh index c2ea3386dd..cbf3660ceb 100755 --- a/Scripts/hydevm/hydevm.sh +++ b/Scripts/hydevm/hydevm.sh @@ -1,7 +1,7 @@ -#!/bin/bash +#!/usr/bin/env bash # HydeVM - Simplified VM tool for HyDE contributors -# Works on both Arch Linux and NixOS with automatic OS detection +# Works on Arch Linux, NixOS, and FreeBSD with automatic OS detection set -e @@ -10,12 +10,21 @@ CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/hydevm" BASE_IMAGE="$CACHE_DIR/archbase.qcow2" SNAPSHOTS_DIR="$CACHE_DIR/snapshots" HYDE_REPO="https://github.com/HyDE-Project/HyDE.git" + +COMMON_PACKAGES=( + "curl" "python" "git" +) + # Required packages for Arch Linux ARCH_PACKAGES=( "qemu-desktop" - "curl" - "python" - "git" + "${COMMON_PACKAGES[@]}" +) + +# Required packages for FreeBSD +FREEBSD_PACKAGES=( + "qemu" + "${COMMON_PACKAGES[@]}" ) # Create cache directories @@ -29,6 +38,8 @@ function detect_os() { echo "nixos" elif [[ "$ID" == "arch" ]]; then echo "arch" + elif [[ "$ID" == "freebsd" ]]; then + echo "freebsd" else echo "unknown" fi @@ -36,6 +47,10 @@ function detect_os() { echo "nixos" elif command -v pacman >/dev/null 2>&1; then echo "arch" + elif [[ "$(uname -s)" == "FreeBSD" ]]; then + echo "freebsd" + elif [[ "$(uname -s)" == "Darwin" ]]; then + echo "darwin" else echo "unknown" fi @@ -43,7 +58,7 @@ function detect_os() { function print_usage() { echo "HydeVM - Simplified VM tool for HyDE contributors" - echo "Supports: Arch Linux, NixOS" + echo "Supports: Arch Linux, NixOS, FreeBSD, and Darwin" echo "" echo "Usage: hydevm [OPTIONS] [BRANCH/COMMIT]" echo "" @@ -54,7 +69,7 @@ function print_usage() { echo " --persist Make VM changes persistent" echo " --list List available snapshots" echo " --clean Clean all cached data" - echo " --install-deps Install required dependencies (Arch only)" + echo " --install-deps Install required dependencies (Arch, FreeBSD, Darwin)" echo " --check-deps Check if dependencies are installed" echo " --help Show this help" echo "" @@ -71,9 +86,11 @@ function print_usage() { echo " hydevm abc123 # Run specific commit" echo " hydevm --persist dev # Run dev branch with persistence" echo "" - echo "OS-specific notes:" - echo " Arch Linux: Missing packages will be auto-detected and offered for install" - echo " NixOS: automatically installs dependencies" + echo "Auto-detected OS-specific install notes:" + echo " Arch Linux: Missing packages will be offered for installation via 'pacman'" + echo " NixOS: Missing packages will be installed via 'nix shell'" + echo " FreeBSD: Missing packages will be installed via 'pkg'" + echo " Darwin : Missing packages can be installed via 'nix shell', 'brew', or direct download" } function check_root() { @@ -99,8 +116,14 @@ function check_dependencies() { "arch") check_arch_dependencies ;; + "freebsd") + check_freebsd_dependencies + ;; + "darwin") + check_darwin_dependencies + ;; *) - echo "⚠️ Unsupported OS. This script supports Arch Linux and NixOS." + echo "⚠️ Unsupported OS. This script supports Arch Linux, NixOS, and FreeBSD." echo " Please ensure qemu, curl, python, and git are installed." return 0 ;; @@ -169,6 +192,255 @@ function check_arch_dependencies() { return 0 } +function check_freebsd_dependencies() { + local missing_packages=() + + for package in "${FREEBSD_PACKAGES[@]}"; do + if ! pkg info -e "$package" > /dev/null 2>&1; then + missing_packages+=("$package") + fi + done + + if [ ${#missing_packages[@]} -gt 0 ]; then + echo "❌ Missing required packages: ${missing_packages[*]}" + echo "" + read -p "Would you like to install them now? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + install_freebsd_packages "${missing_packages[@]}" + else + echo " You can install them manually with: sudo pkg install ${missing_packages[*]}" + return 1 + fi + fi + + # Check if qemu is available; if not, prompt for QEMU or bhyve setup + if ! command -v qemu >/dev/null 2>&1; then + cat <<'EOF' +⚠️ Additional system setup is required (not applied automatically). +❌ QEMU not available. + You can use either QEMU or bhyve on FreeBSD. + + 1) QEMU + 2) bhyve + +EOF + read -p "Choose a virtualization backend to set up (1/2, or anything else to skip): " -r + + if [[ $REPLY == "1" ]]; then + cat <<'EOF' +Adopted from [Chapter 24.6. Virtualization with QEMU on FreeBSD](https://docs.freebsd.org/en/books/handbook/virtualization/#qemu-virtualization-host-guest) by @MFarabi619 + To set up QEMU, run: + sudo pkg install qemu + + # Fix missing or broken qemu symlink + if [ "$(readlink /usr/local/bin/qemu)" != "/usr/local/bin/qemu-system-x86_64" ]; then + sudo ln -sf /usr/local/bin/qemu-system-x86_64 /usr/local/bin/qemu + fi + + sudo sysctl net.link.tap.user_open=1 + sudo grep -qxF "net.link.tap.user_open=1" /etc/sysctl.conf || \ + echo 'net.link.tap.user_open=1' | sudo tee -a /etc/sysctl.conf + sudo grep -qxF "add path 'tap*' mode 0660 group operator" /etc/devfs.rules || \ + printf "add path 'tap*' mode 0660 group operator\n" | sudo tee -a /etc/devfs.rules + + Then test with: + qemu +EOF + elif [[ $REPLY == "2" ]]; then + cat <<'EOF' +Adopted from [Chapter 24.6. Virtualization with bhyve on FreeBSD](https://docs.freebsd.org/en/books/handbook/virtualization/#virtualization-host-bhyve) by @MFarabi619 + To set up bhyve, run: + sudo kldload vmm + + sudo ifconfig tap0 create + sudo sysctl net.link.tap.up_on_open=1 + sudo grep -qxF "net.link.tap.up_on_open=1" /etc/sysctl.conf || \ + echo 'net.link.tap.up_on_open=1' | sudo tee -a /etc/sysctl.conf + sudo grep -qxF "add path 'tap*' mode 0660 group operator" /etc/devfs.rules || \ + printf "add path 'tap*' mode 0660 group operator\n" | sudo tee -a /etc/devfs.rules + + sudo ifconfig bridge0 create + sudo ifconfig bridge0 addm igb0 addm tap0 + sudo ifconfig bridge0 up +EOF + else + echo " Skipping virtualization backend setup." + fi + fi + + # Check if /dev/vmm exists for bhyve acceleration +if ! kldstat -q -m vmm; then + cat <<'EOF' +⚠️ bhyve/VMM not available. Native FreeBSD virtualization may not work. + Make sure the vmm module is loaded: sudo kldload vmm +EOF +fi + + # Check if tap access is likely unavailable for non-root users + if ! sysctl -n net.link.tap.user_open >/dev/null 2>&1 || [ "$(sysctl -n net.link.tap.user_open 2>/dev/null)" != "1" ]; then + cat <<'EOF' +⚠️ Non-root tap access is not enabled. + To enable it, run: sudo sysctl net.link.tap.user_open=1 + Then persist it in /etc/sysctl.conf. +EOF + fi + + return 0 +} + +check_darwin_dependencies() { + if [[ "$(uname -p 2>/dev/null || true)" != "arm" && "$(uname -p 2>/dev/null || true)" != "arm64" ]]; then + echo "❌ x86_64-darwin is not supported" + exit 1 + fi + + # NOTE: temporary UTM-first workflow for Darwin. Later we should simplify + # this by removing UTM and driving qemu directly. + if command -v utmctl >/dev/null 2>&1; then + echo "UTM version $(utmctl version) is installed" + + if [[ "${HYDEVM_CHECK_DEPS_ONLY:-0}" == "1" ]]; then + echo "Supported VM guests on macOS Host: NixOS, FreeBSD" + return 0 + fi + + echo "Supported VM guests on macOS Host: NixOS, FreeBSD" + echo "" + echo "Choose a VM target OS:" + echo " 1) NixOS" + echo " 2) FreeBSD" + read -r -p "Select target OS (1/2): " reply + + if [[ "$reply" == "1" ]]; then + HYDEVM_DARWIN_TARGET="nixos" + export HYDEVM_DARWIN_TARGET + echo "Selected target: NixOS" + exit 0 + elif [[ "$reply" == "2" ]]; then + HYDEVM_DARWIN_TARGET="freebsd" + export HYDEVM_DARWIN_TARGET + echo "Selected target: FreeBSD" + exit 0 + fi + + echo "❌ Invalid selection. Please choose 1 for NixOS or 2 for FreeBSD." + return 1 + fi + + if command -v nix >/dev/null 2>&1; then + cat <<'EOF' +❌ UTM is not installed. + +You can set it up with nix using: + nix shell nixpkgs#utm + +Or manually: +1. Install UTM via https://mac.getutm.app. +2. Install UTM via brew (requires brew): brew install --cask utm +3. Install UTM via Determinate Nix (if needed): + curl -fsSL https://install.determinate.systems/nix | sh -s -- install + Then use a nix shell, home manager, or nix-darwin. + +For nix-darwin, ensure Homebrew paths are available when using Homebrew-managed UTM: +environment.systemPath = [ + "/usr/local/bin" + "/opt/homebrew/bin" +]; + +More info: https://nix-darwin.github.io/nix-darwin/manual/index.html#opt-homebrew.enable +EOF + return 1 + fi + + if command -v brew >/dev/null 2>&1; then + cat <<'EOF' +❌ UTM is not installed. + +Homebrew is available. Install UTM with: + brew install --cask utm + +Or manually: +1. Install UTM via https://mac.getutm.app. +2. Install UTM via Determinate Nix: + curl -fsSL https://install.determinate.systems/nix | sh -s -- install + Then use a nix shell, home manager, or nix-darwin. + +For nix-darwin, ensure Homebrew paths are available when using Homebrew-managed UTM: +environment.systemPath = [ + "/usr/local/bin" + "/opt/homebrew/bin" +]; + +More info: https://nix-darwin.github.io/nix-darwin/manual/index.html#opt-homebrew.enable +EOF + return 1 + fi + + cat <<'EOF' +UTM is required on macOS for the current HyDE VM flow. + +You can set it up manually in one of these ways: +1. Install UTM via https://mac.getutm.app. +2. Install UTM via brew, requires installing brew. +3. Install UTM via Determinate Nix, requires installing Determinate nix with: + curl -fsSL https://install.determinate.systems/nix | sh -s -- install + Then use a nix shell, home manager, or nix-darwin. +EOF + + return 1 +} + +function install_darwin_dependencies() { + if [[ "$(uname -p 2>/dev/null || true)" != "arm" && "$(uname -p 2>/dev/null || true)" != "arm64" ]]; then + echo "❌ x86_64-darwin is not supported" + exit 1 + fi + + if command -v utmctl >/dev/null 2>&1; then + echo "✅ UTM is already installed: $(utmctl version)" + return 0 + fi + + echo "📦 UTM is required on macOS for the current HyDE VM flow." + + if command -v brew >/dev/null 2>&1; then + read -r -p "Install UTM with Homebrew now? (y/N): " reply + if [[ "$reply" =~ ^[Yy]$ ]]; then + brew install --cask utm + return 0 + fi + fi + + if command -v nix >/dev/null 2>&1; then + read -r -p "Open nix shell with UTM now (nix shell nixpkgs#utm)? (y/N): " reply + if [[ "$reply" =~ ^[Yy]$ ]]; then + nix shell nixpkgs#utm + echo "Re-run hydevm after entering the nix shell." + return 1 + fi + fi + + cat <<'EOF' +Install UTM manually with one of these options: +1. Install UTM via https://mac.getutm.app. +2. Install UTM via brew, requires installing brew. +3. Install UTM via Determinate Nix, requires installing Determinate nix with: + curl -fsSL https://install.determinate.systems/nix | sh -s -- install + Then use a nix shell, home manager, or nix-darwin. + +For nix-darwin, ensure Homebrew paths are available when using Homebrew-managed UTM: +environment.systemPath = [ + "/usr/local/bin" + "/opt/homebrew/bin" +]; + +More info: https://nix-darwin.github.io/nix-darwin/manual/index.html#opt-homebrew.enable +EOF + + return 1 +} + function install_arch_packages() { local packages=("$@") @@ -192,36 +464,94 @@ function install_arch_packages() { echo "✅ Packages installed successfully" } -function install_all_arch_dependencies() { +function install_freebsd_packages() { + local packages=("$@") + + echo "📦 Installing missing packages: ${packages[*]}" + + # Update package database + echo "🔄 Updating package database..." + sudo pkg update + + # Install required packages + echo "📥 Installing packages..." + sudo pkg install -y "${packages[@]}" + + echo "✅ Packages installed successfully" +} + +function install_all_dependencies() { local os os=$(detect_os) - if [[ "$os" != "arch" ]]; then - echo "❌ --install-deps is only supported on Arch Linux" + if [[ "$os" != "arch" && "$os" != "freebsd" && "$os" != "darwin" ]]; then + echo "❌ --install-deps is only supported on Arch Linux, FreeBSD, and Darwin" echo " Current OS: $os" exit 1 fi echo "📦 Installing all HydeVM dependencies..." - install_arch_packages "${ARCH_PACKAGES[@]}" + + if [[ "$os" == "arch" ]]; then + install_arch_packages "${ARCH_PACKAGES[@]}" echo "💡 You may need to reboot or logout/login for all changes to take effect" + elif [[ "$os" == "freebsd" ]]; then + install_freebsd_packages "${FREEBSD_PACKAGES[@]}" + elif [[ "$os" == "darwin" ]]; then + install_darwin_dependencies + fi } function check_deps_only() { local os + local memory + local accel_available + local accel_label + local cpu_cores + os=$(detect_os) echo "🔍 Checking HydeVM dependencies..." echo " Detected OS: $os" + HYDEVM_CHECK_DEPS_ONLY=1 + export HYDEVM_CHECK_DEPS_ONLY if check_dependencies; then + unset HYDEVM_CHECK_DEPS_ONLY echo "✅ All dependencies are installed" # Check additional system info echo "" echo "📊 System Information:" - echo " CPU cores: $(nproc)" - echo " Memory: $(free -h | awk '/^Mem:/ {print $2}' 2>/dev/null || echo "Unknown")" - echo " KVM available: $([ -r /dev/kvm ] && echo "Yes" || echo "No")" + cpu_cores="$(nproc 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null || echo "Unknown")" + + case "$os" in + freebsd) + memory="$(sysctl -n hw.physmem 2>/dev/null | awk '{printf "%.1fGiB", $1/1024/1024/1024}' || echo "Unknown")" + accel_available="$(kldstat -q -m vmm && echo "Yes" || echo "No")" + accel_label="BSD Hypervisor (bhyve)" + ;; + darwin) + memory="$(sysctl -n hw.memsize 2>/dev/null | awk '{printf "%.1fGiB", $1/1024/1024/1024}' || echo "Unknown")" + + if command -v qemu-system-aarch64 >/dev/null 2>&1 && \ + qemu-system-aarch64 -accel help 2>/dev/null | grep -q hvf; then + accel_available="Yes" + else + accel_available="No" + fi + + accel_label="Apple HVF" + ;; + *) + memory="$(free -h 2>/dev/null | awk '/^Mem:/ {print $2}' || echo "Unknown")" + accel_available="$([ -r /dev/kvm ] && echo "Yes" || echo "No")" + accel_label="KVM" + ;; + esac + + echo " CPU cores: $cpu_cores" + echo " Memory: $memory" + echo " $accel_label: $accel_available" if command -v qemu-system-x86_64 >/dev/null 2>&1; then echo " QEMU version: $(qemu-system-x86_64 --version | head -1)" @@ -229,6 +559,7 @@ function check_deps_only() { return 0 else + unset HYDEVM_CHECK_DEPS_ONLY return 1 fi } @@ -321,6 +652,22 @@ function download_archbox() { fi } +function get_latest_freebsd_image_url() { +# https://download.freebsd.org/releases/ISO-IMAGES/15.0/FreeBSD-15.0-RELEASE-amd64-dvd1.iso +# https://download.freebsd.org/releases/ISO-IMAGES/15.0/FreeBSD-15.0-RELEASE-arm64-aarch64-dvd1.iso + echo "https://download.freebsd.org/releases/VM-IMAGES/15.0-RELEASE/amd64/Latest/FreeBSD-15.0-RELEASE-amd64-ufs.qcow2.xz" +} + +function download_freebsdbox() { + if [ ! -f "$BASE_IMAGE" ]; then + echo "📦 Downloading FreeBSD base image..." + local latest_url + latest_url=$(get_latest_freebsd_image_url) + curl -L "$latest_url" -o "$BASE_IMAGE" + echo "✅ Base image downloaded successfully" + fi +} + function get_snapshot_name() { local ref="$1" if [ -z "$ref" ]; then @@ -532,6 +879,20 @@ check_root persistent="false" ref="master" +original_argc=$# + +if [ "$original_argc" -eq 0 ]; then + os=$(detect_os) + case "$os" in + arch|nixos|freebsd|darwin) ;; + *) + print_usage + echo "" + echo "❌ Unsupported OS: $os" + exit 1 + ;; + esac +fi # Parse arguments while [ $# -gt 0 ]; do @@ -549,7 +910,7 @@ while [ $# -gt 0 ]; do exit 0 ;; --install-deps) - install_all_arch_dependencies + install_all_dependencies exit 0 ;; --check-deps) diff --git a/Scripts/install.sh b/Scripts/install.sh index 0b7620cc4b..c92462d427 100755 --- a/Scripts/install.sh +++ b/Scripts/install.sh @@ -23,6 +23,11 @@ EOF # import variables and functions # #--------------------------------# scrDir="$(dirname "$(realpath "$0")")" + +if [[ "$(uname -s)" == "FreeBSD" ]]; then + exec "${scrDir}/install_freebsd.sh" "$@" +fi + # shellcheck disable=SC1091 if ! source "${scrDir}/global_fn.sh"; then echo "Error: unable to source global_fn.sh..." diff --git a/Scripts/install_freebsd.sh b/Scripts/install_freebsd.sh new file mode 100755 index 0000000000..ce6d1c93da --- /dev/null +++ b/Scripts/install_freebsd.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2154 + +cat <<"EOF" + +------------------------------------------------- + _ _ _ ____ ____ ____ +| | | |_ _ __| | ___| __ ) ___|| _ \ +| |_| | | | |/ _` |/ _ \ _ \___ \| | | | +| _ | |_| | (_| | __/ |_) |__) | |_| | +|_| |_|\__, |\__,_|\___|____/____/|____/ + |___/ +------------------------------------------------- + +EOF + +scrDir="$(dirname "$(realpath "$0")")" +# shellcheck disable=SC1091 +if ! source "${scrDir}/global_fn.sh"; then + echo "Error: unable to source global_fn.sh..." + exit 1 +fi + +if [[ "$(uname -s)" != "FreeBSD" ]]; then + print_log -crit "unsupported" "install_freebsd.sh must be run on FreeBSD." + exit 1 +fi + +flg_Install=0 +flg_Restore=0 +flg_DryRun=0 +flg_ThemeInstall=1 + +while getopts idrtmh RunStep; do + case $RunStep in + i) flg_Install=1 ;; + d) + flg_Install=1 + export use_default="--noconfirm" + ;; + r) flg_Restore=1 ;; + t) flg_DryRun=1 ;; + m) flg_ThemeInstall=0 ;; + *) + cat <>"${scrDir}/install_pkg.lst" + if [ -f "${custom_pkg}" ] && [ -n "${custom_pkg}" ]; then + cat "${custom_pkg}" >>"${scrDir}/install_pkg.lst" + fi + + echo "" + if ! chk_list "myShell" "${shlList[@]}"; then + print_log -c "Shell :: " + for i in "${!shlList[@]}"; do + print_log -sec "$((i + 1))" " ${shlList[$i]} " + done + prompt_timer 120 "Enter option number [default: zsh] | q to quit " + + case "${PROMPT_INPUT}" in + 1) export myShell="zsh" ;; + 2) export myShell="fish" ;; + q) + print_log -sec "shell" -crit "Quit" "Exiting..." + exit 1 + ;; + *) + print_log -sec "shell" -warn "Defaulting to zsh" + export myShell="zsh" + ;; + esac + print_log -sec "shell" -stat "Added as shell" "${myShell}" + echo "${myShell}" >>"${scrDir}/install_pkg.lst" + fi + + if ! grep -q "^#user packages" "${scrDir}/install_pkg.lst"; then + print_log -sec "pkg" -crit "No user packages found..." "Log file at ${cacheDir}/logs/${HYDE_LOG}/install_freebsd.sh" + exit 1 + fi + + "${scrDir}/install_pkg.sh" "${scrDir}/install_pkg.lst" +fi + +if [ ${flg_Restore} -eq 1 ]; then + cat <<"EOF" + + _ _ + ___ ___ ___| |_ ___ ___|_|___ ___ +| _| -_|_ -| _| . | _| | | . | +|_| |___|___|_| |___|_| |_|_|_|_ | + |___| + +EOF + + if [ "${flg_DryRun}" -ne 1 ] && [ -n "${HYPRLAND_INSTANCE_SIGNATURE}" ]; then + hyprctl keyword misc:disable_autoreload 1 -q + fi + + "${scrDir}/restore_fnt.sh" + "${scrDir}/restore_cfg.sh" + "${scrDir}/restore_thm.sh" + "${scrDir}/restore_shl.sh" + print_log -g "[generate] " "cache ::" "Wallpapers..." + if [ "${flg_DryRun}" -ne 1 ]; then + export PATH="$HOME/.local/lib/hyde:$HOME/.local/bin:${PATH}" + "$HOME/.local/lib/hyde/swwwallcache.sh" -t "" + "$HOME/.local/lib/hyde/theme.switch.sh" -q || true + "$HOME/.local/lib/hyde/waybar.py" --update || true + echo "[install] reload :: Hyprland" + fi +fi + +if [ $flg_Install -eq 1 ]; then + echo "" + print_log -g "Installation" " :: " "COMPLETED!" +fi +print_log -b "Log" " :: " -y "View logs at ${cacheDir}/logs/${HYDE_LOG}" +print_log -warn "Reboot" "Please reboot the system to apply all changes." diff --git a/Scripts/install_pkg.sh b/Scripts/install_pkg.sh index 62e5770be9..ad0efad6f5 100755 --- a/Scripts/install_pkg.sh +++ b/Scripts/install_pkg.sh @@ -14,9 +14,12 @@ fi flg_DryRun=${flg_DryRun:-0} export log_section="package" +currentPm="$(${pacmanCmd} which)" -"${scrDir}/install_aur.sh" "${getAur}" 2>&1 -chk_list "aurhlpr" "${aurList[@]}" +if [[ "${currentPm}" == "pacman" || "${currentPm}" == "yay" || "${currentPm}" == "paru" ]]; then + "${scrDir}/install_aur.sh" "${getAur}" 2>&1 + chk_list "aurhlpr" "${aurList[@]}" +fi listPkg="${1:-"${scrDir}/pkg_core.lst"}" archPkg=() aurhPkg=() @@ -58,11 +61,15 @@ while read -r pkg deps; do if pkg_installed "${pkg}"; then print_log -y "[skip] " "${pkg}" - elif pkg_available "${pkg}"; then - repo=$(pacman -Si "${pkg}" | awk -F ': ' '/Repository / {print $2}' | tr '\n' ' ') + elif "${pacmanCmd}" info "${pkg}" &>/dev/null; then + if [[ "${currentPm}" == "pacman" || "${currentPm}" == "yay" || "${currentPm}" == "paru" ]]; then + repo=$(pacman -Si "${pkg}" | awk -F ': ' '/Repository / {print $2}' | tr '\n' ' ') + else + repo="${currentPm}" + fi print_log -b "[queue] " "${pkg}" -b " :: " -g "${repo}" archPkg+=("${pkg}") - elif aur_available "${pkg}"; then + elif [[ "${currentPm}" == "pacman" || "${currentPm}" == "yay" || "${currentPm}" == "paru" ]] && aur_available "${pkg}"; then print_log -b "[queue] " "${pkg}" -b " :: " -g "aur" aurhPkg+=("${pkg}") else @@ -84,12 +91,20 @@ install_packages() { print_log -b "[pkg] " "${pkg}" done else - $install_cmd ${use_default:+"$use_default"} -S "${pkg_array[@]}" + if [[ "${currentPm}" == "pacman" || "${currentPm}" == "yay" || "${currentPm}" == "paru" ]]; then + $install_cmd ${use_default:+"$use_default"} -S "${pkg_array[@]}" + else + $install_cmd install "${pkg_array[@]}" + fi fi fi } echo "" -install_packages archPkg "arch" "sudo pacman" -echo "" -install_packages aurhPkg "aur" "${aurhlpr}" +if [[ "${currentPm}" == "pacman" || "${currentPm}" == "yay" || "${currentPm}" == "paru" ]]; then + install_packages archPkg "arch" "sudo pacman" + echo "" + install_packages aurhPkg "aur" "${aurhlpr}" +else + install_packages archPkg "${currentPm}" "${pacmanCmd}" +fi diff --git a/Scripts/pkg_core_freebsd.lst b/Scripts/pkg_core_freebsd.lst new file mode 100644 index 0000000000..ce4f4ebc67 --- /dev/null +++ b/Scripts/pkg_core_freebsd.lst @@ -0,0 +1,102 @@ +# --------------------------------------------------- // System +# uwsm # A standalone Wayland session manager +pipewire # audio/video server +# pipewire-module-xrdp-0.1 PipeWire module which enables xrdp to use audio redirection +# pipewire-spa-oss-g20251117_1 PipeWire SPA plugin implementing a FreeBSD OSS backend +# plasma6-kpipewire-6.5.5 Components relating to Flatpak 'pipewire' use in Plasma + +# pipewire-alsa # pipewire alsa client +# pipewire-audio # pipewire audio client +# pipewire-jack # pipewire jack client +# pipewire-pulse # pipewire pulseaudio client +# gst-plugin-pipewire # pipewire gstreamer client +wireplumber # pipewire session manager +pavucontrol # pulseaudio volume control +pamixer # pulseaudio cli mixer +# networkmanager # network manager +# network-manager-applet # network manager system tray utility +# bluez # bluetooth protocol stack +bluez-firmware +# bluez-utils # bluetooth utility cli +# blueman # bluetooth manager gui +FreeBSD-bluetooth +# use `backlight` instead. https://docs.freebsd.org/en/books/handbook/config/index.html#acpi-config +# brightnessctl # screen brightness control +playerctl # media controls +# udiskie # manage removable media +dconf +dconf-editor + +# --------------------------------------------------- // Display Manager +sddm # display manager for KDE plasma +qt5-quickcontrols # for sddm theme ui elements +qt5-quickcontrols2 # for sddm theme ui elements +qt5-graphicaleffects # for sddm theme effects + +# --------------------------------------------------- // Window Manager +hyprland # wlroots-based wayland compositor +dunst # notification daemon +rofi # application launcher +waybar # system bar +swww # wallpaper +hyprlock # lock screen +wlogout # logout menu +grim # screenshot tool +hyprpicker # color picker +slurp # region select for screenshot/screenshare +satty # Modern Screenshot Annotation +cliphist # clipboard manager +wl-clipboard +# wl-clip-persist # Keep Wayland clipboard even after programs close (avoids crashes) +hyprsunset # blue light filter + +# --------------------------------------------------- // Dependencies +polkit-gnome # authentication agent +xdg-desktop-portal-hyprland # xdg desktop portal for hyprland +xdg-desktop-portal-gtk # file picker and dbus integration +xdg-user-dirs # Manage user directories like ~/Desktop and ~/Music +# pacman-contrib # for system update check +parallel # for parallel processing +jq # for json processing +ImageMagick7 # for image processing +qt5-imageformats # for dolphin image thumbnails +ffmpeg +ffmpegthumbnailer +# ffmpegthumbs # for dolphin video thumbnails +# kde-cli-tools # for dolphin file type defaults +plasma6-kde-cli-tools +libnotify # for notifications +# noto-fonts-emoji # emoji font +noto-emoji + +# --------------------------------------------------- // Theming +nwg-look # gtk configuration tool +qt5ct # qt5 configuration tool +qt6ct # qt6 configuration tool +Kvantum +# kvantum # svg based qt6 theme engine +# kvantum-qt5 # svg based qt5 theme engine +qt5-wayland # wayland support in qt5 +qt6-wayland # wayland support in qt6 + +# --------------------------------------------------- // Applications +firefox # browser +kitty # terminal +dolphin # kde file manager +ark # kde file archiver +unzip # extracting zip files +vim # terminal text editor +# code # ide text editor +# nwg-displays # monitor management utility +py311-nwg-displays +fzf # Command-line fuzzy finder + +# --------------------------------------------------- // Shell +starship|zsh # customizable shell prompt written in Rust +# starship-git # The cross-shell prompt for astronauts +starship|fish # customizable shell prompt + +fastfetch # system information fetch tool + +# --------------------------------------------------- // HyDE +hypridle # idle daemon diff --git a/Scripts/restore_cfg.sh b/Scripts/restore_cfg.sh index a5aed3615d..c5122cf7df 100755 --- a/Scripts/restore_cfg.sh +++ b/Scripts/restore_cfg.sh @@ -193,6 +193,10 @@ deploy_psv() { } hyprland_hook() { + if [[ "$(uname -s)" == "FreeBSD" ]]; then + print_log -y "[hook] " -b "hyprland :: " "Skipping hyq marker validation on FreeBSD." + return 0 + fi local hyde_config="${cloneDir}/Configs/.config/hypr/hyprland.conf" local hyprland_default_config="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/hyprland.conf" @@ -267,10 +271,18 @@ echo "" hyprland_hook print_log -g "[python env]" -b " :: " "Rebuilding HyDE Python environment..." -if command -v hyde-shell >/dev/null 2>&1; then - hyde-shell pyinit +if [[ "$(uname -s)" == "FreeBSD" ]]; then + if command -v hyde-shell >/dev/null 2>&1; then + hyde-shell pyinit || print_log -warn "python env" "Failed to rebuild Python environment on FreeBSD (non-fatal)." + else + "${HOME}/.local/bin/hyde-shell" pyinit || print_log -warn "python env" "Failed to rebuild Python environment on FreeBSD (non-fatal)." + fi else - "${HOME}/.local/bin/hyde-shell" pyinit + if command -v hyde-shell >/dev/null 2>&1; then + hyde-shell pyinit + else + "${HOME}/.local/bin/hyde-shell" pyinit + fi fi print_log -g "[version]" -b " :: " "saving version info..." diff --git a/Scripts/restore_shl.sh b/Scripts/restore_shl.sh index 8102e65ed5..2e6cb25168 100755 --- a/Scripts/restore_shl.sh +++ b/Scripts/restore_shl.sh @@ -54,7 +54,8 @@ if pkg_installed zsh; then Zsh_rc="${ZDOTDIR:-$HOME}/.zshenv" Zsh_Path="${Zsh_Path:-$HOME/.oh-my-zsh}" Zsh_Plugins="$Zsh_Path/custom/plugins" - Fix_Completion="" + Add_Completion=0 + [ -f "${Zsh_rc}" ] || touch "${Zsh_rc}" # generate plugins from list while read -r r_plugin; do @@ -67,7 +68,7 @@ if pkg_installed zsh; then fi fi if [ "${z_plugin}" == "zsh-completions" ] && [ "$(grep -c 'fpath+=.*plugins/zsh-completions/src' "${Zsh_rc}")" -eq 0 ]; then - Fix_Completion='\nfpath+=${ZSH_CUSTOM:-${ZSH:-/usr/share/oh-my-zsh}/custom}/plugins/zsh-completions/src' + Add_Completion=1 else [ -z "${z_plugin}" ] || w_plugin+=" ${z_plugin}" fi @@ -75,7 +76,31 @@ if pkg_installed zsh; then # update plugin array in zshrc print_log -sec "SHELL" -stat "installing" "plugins (${w_plugin} )" - sed -i "/^hyde_plugins=/c\hyde_plugins=(${w_plugin} )${Fix_Completion}" "${Zsh_rc}" + plugin_line="hyde_plugins=(${w_plugin} )" + completion_line='fpath+=${ZSH_CUSTOM:-${ZSH:-/usr/share/oh-my-zsh}/custom}/plugins/zsh-completions/src' + + if grep -q '^hyde_plugins=' "${Zsh_rc}"; then + awk -v repl="${plugin_line}" ' + BEGIN { done = 0 } + /^hyde_plugins=/ { + if (!done) { + print repl + done = 1 + } + next + } + { print } + END { + if (!done) print repl + } + ' "${Zsh_rc}" >"${Zsh_rc}.tmp" && mv "${Zsh_rc}.tmp" "${Zsh_rc}" + else + printf '%s\n' "${plugin_line}" >>"${Zsh_rc}" + fi + + if [ "${Add_Completion}" -eq 1 ] && ! grep -q 'plugins/zsh-completions/src' "${Zsh_rc}"; then + printf '%s\n' "${completion_line}" >>"${Zsh_rc}" + fi else if [ "${flg_DryRun}" -eq "1" ]; then while read -r r_plugin; do diff --git a/Scripts/themepatcher.sh b/Scripts/themepatcher.sh index f6336aa9b6..e582e30073 100755 --- a/Scripts/themepatcher.sh +++ b/Scripts/themepatcher.sh @@ -160,7 +160,7 @@ Fav_Theme_Dir="${Theme_Dir}/Configs/.config/hyde/themes/${Fav_Theme}" [ ! -d "${Fav_Theme_Dir}" ] && print_prompt -r "[ERROR] " "'${Fav_Theme_Dir}'" -y " Do not Exist" && exit 1 # config=$(find "${dcolDir}" -type f -name "*.dcol" | awk -v favTheme="${Fav_Theme}" -F 'theme/' '{gsub(/\.dcol$/, ".theme"); print ".config/hyde/themes/" favTheme "/" $2}') -config=$(find "${wallbashDirs[@]}" -type f -path "*/theme*" -name "*.dcol" 2>/dev/null | awk '!seen[substr($0, match($0, /[^/]+$/))]++' | awk -v favTheme="${Fav_Theme}" -F 'theme/' '{gsub(/\.dcol$/, ".theme"); print ".config/hyde/themes/" favTheme "/" $2}') +config=$(find "${wallbashDirs[@]}" -type f -path "*/theme*" -name "*.dcol" 2>/dev/null | awk -F/ '{print $NF "|" $0}' | awk -F'|' '!seen[$1]++ {print $2}' | awk -v favTheme="${Fav_Theme}" -F 'theme/' '{gsub(/\.dcol$/, ".theme"); print ".config/hyde/themes/" favTheme "/" $2}') restore_list="" while IFS= read -r fileCheck; do diff --git a/Source/assets/freebsd.png b/Source/assets/freebsd.png new file mode 100644 index 0000000000..2a5ccb1417 Binary files /dev/null and b/Source/assets/freebsd.png differ diff --git a/flake.nix b/flake.nix index 3391b620d6..46c63e4eea 100644 --- a/flake.nix +++ b/flake.nix @@ -13,6 +13,7 @@ "aarch64-linux" "x86_64-darwin" "aarch64-darwin" + # "x86_64-freebsd" # TODO: evaluate stability, broken as of March 20th, 2026 ]; forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system); in