diff options
| -rw-r--r-- | README.md | 124 | ||||
| -rw-r--r-- | flake.nix | 34 | ||||
| -rw-r--r-- | hm-module.nix | 86 | ||||
| -rw-r--r-- | package.nix | 113 |
4 files changed, 357 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..ae322a6 --- /dev/null +++ b/README.md @@ -0,0 +1,124 @@ +# open-bamboo-networking (Nix/home-manager) + +Nix packaging of [open-bamboo-networking](https://github.com/ClusterM/open-bamboo-networking), +an open-source drop-in replacement for the proprietary `bambu_networking` +plugin. + +The proprietary plugin (which OrcaSlicer will try to download) is not +compatible with NixOS unless you go through the effort of (at the very least) +relinking the shared objects (`libBambuSource.so` + +`libbambu_networking_xx.xx.xx.xx.so`) downloaded to the plugins directory +(`~/.config/OrcaSlicer/plugins`). The open plugin, on the other hand, can be +easily built with Nix and the binaries can be dropped into the plugins +directory to replace the proprietary ones. + +The flake includes also a home-manager module which installs the plugin for +OrcaSlicer decoratively. One caveat is that `OrcaSlicer.conf` will need to be +patched in order for it to recognize the plugin when it is (as in this case) +installed manually (see instructions below). Correctly done, the user will not +be notified of a missing plugin on launch. + +## Usage + +```nix +{ + inputs.open-bamboo-networking.url = "github:you/open-bamboo-networking"; + + # in your home-manager config: + imports = [ inputs.open-bamboo-networking.homeManagerModules.default ]; + + programs.openBambooNetworking = { + enable = true; + orcaSlicer = { + enable = true; # default + }; + }; +} +``` + +### Options + +| option | default | description | +|---|---|---| +| `programs.openBambooNetworking.enable` | `false` | enable the module | +| `programs.openBambooNetworking.orcaSlicer.enable` | `true` | build and link the plugin for OrcaSlicer / a compatible fork | +| `programs.openBambooNetworking.orcaSlicer.obnVersion` | `"02.03.00.99"` | ABI version baked into the built filename | +| `programs.openBambooNetworking.orcaSlicer.configDir` | `${config.xdg.configHome}/OrcaSlicer` | where `OrcaSlicer.conf` and `plugins/` live - override for forks, nightlies, or Flatpak installs | + +`orcaSlicer.enable` only links the shared objects declaratively into +`<configDir>/plugins` - it does **not** touch `OrcaSlicer.conf`. That file +is mutable app state the slicer reads and rewrites on its own, so patching +it is left as a manual step (below) rather than something +`home-manager switch` does for you. + +## Patching OrcaSlicer.conf + +After `home-manager switch`, and after launching the slicer at least once +so `<configDir>/OrcaSlicer.conf` exists, run: + +```bash +# Ensure correct $ver +cat <<< $(jq --arg ver "02.03.00.99" ' + .app.installed_networking = "true" + | .app.network_plugin_version = $ver + | .app.network_plugin_remind_later = "true" +' ~/.config/OrcaSlicer/OrcaSlicer.conf) > ~/.config/OrcaSlicer/OrcaSlicer.conf +``` + +Use the same `$ver` as `orcaSlicer.obnVersion`. Restart the slicer. Re-run +this whenever you change `obnVersion`, or if the app ever resets +`network_plugin_version` on its own. + +### Automating it with home.activationScripts + +If you'd rather this happen automatically on every `home-manager switch` +instead of by hand, add this alongside the module import. It reads +`obnVersion`/`configDir` straight from `programs.openBambooNetworking.orcaSlicer`, +so it can't drift out of sync with what the module actually built and +linked: + +```nix +{ config, lib, pkgs, ... }: +let + cfg = config.programs.openBambooNetworking.orcaSlicer; +in +{ + home.activationScripts.openBambooNetworkingOrcaConf = '' + CONF="${cfg.configDir}/OrcaSlicer.conf" + + if [ ! -e "$CONF" ]; then + echo "open-bamboo-networking: $CONF doesn't exist yet, skipping" \ + "(launch OrcaSlicer once first)" + else + NEEDS_PATCH=$(${pkgs.jq}/bin/jq -r --arg ver "${cfg.obnVersion}" ' + (.app.installed_networking != "true") + or (.app.network_plugin_version != $ver) + ' "$CONF") + + if [ "$NEEDS_PATCH" = "true" ]; then + if [ -n "''${DRY_RUN_CMD:-}" ]; then + echo "open-bamboo-networking: would patch $CONF (dry run)" + else + cp -f "$CONF" "$CONF.bak" + TMP=$(mktemp) + ${pkgs.jq}/bin/jq --arg ver "${cfg.obnVersion}" ' + .app.installed_networking = "true" + | .app.network_plugin_version = $ver + | .app.network_plugin_remind_later = "true" + ' "$CONF" > "$TMP" + cat "$TMP" > "$CONF" + rm -f "$TMP" + echo "open-bamboo-networking: patched $CONF (backup: $CONF.bak)" + fi + fi + fi + ''; +} +``` + +## AI disclosure + +The Nix packaging in this repo was written with substantial AI assistance. It +hasn't been reviewed by anyone but the repo maintainer's own testing - treat it +accordingly and read through `package.nix`/`hm-module.nix` yourself before +trusting it with your setup. diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..f138bc6 --- /dev/null +++ b/flake.nix @@ -0,0 +1,34 @@ +{ + description = "open-bamboo-networking: an open-source replacement for Bambu Lab slicers' proprietary network plugin, packaged for Nix + home-manager"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = + { self, nixpkgs }: + let + forAllSystems = nixpkgs.lib.genAttrs [ + "x86_64-linux" + "aarch64-linux" + ]; + in + { + packages = forAllSystems ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + { + # clientType defaults to "orca_slicer" - the only target this + # flake's home-manager module currently wires up - but the + # package itself takes clientType as a parameter for other + # slicers upstream supports. + default = pkgs.callPackage ./package.nix { }; + } + ); + + homeManagerModules.default = import ./hm-module.nix self; + homeManagerModules.openBambooNetworking = self.homeManagerModules.default; + }; +} diff --git a/hm-module.nix b/hm-module.nix new file mode 100644 index 0000000..d3fa652 --- /dev/null +++ b/hm-module.nix @@ -0,0 +1,86 @@ +self: +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.programs.openBambooNetworking; + + mkClientPlugin = + clientType: obnVersion: pkgs.callPackage (self + "/package.nix") { inherit clientType obnVersion; }; + + # home.file targets are relative to $HOME; configDir is given as an + # absolute path (so it composes naturally whether it comes from + # config.xdg.configHome, a Flatpak path, or something else entirely). + relToHome = + path: + if lib.hasPrefix (config.home.homeDirectory + "/") path then + lib.removePrefix (config.home.homeDirectory + "/") path + else + throw "programs.openBambooNetworking: configDir (${path}) must be under $HOME (${config.home.homeDirectory})"; + + orcaPlugin = mkClientPlugin "orca_slicer" cfg.orcaSlicer.obnVersion; +in +{ + options.programs.openBambooNetworking = { + enable = mkEnableOption '' + open-bamboo-networking (https://github.com/ClusterM/open-bamboo-networking), + an open-source replacement for Bambu Lab slicers' proprietary network + plugin, built from source + ''; + + # Each supported client gets its own nested option group. Only + # orcaSlicer is wired up today; add siblings here (e.g. bambuStudio) + # as upstream support for them matures. + orcaSlicer = { + enable = mkOption { + type = types.bool; + default = true; + description = "Build and link the plugin for OrcaSlicer (or a compatible fork)."; + }; + + obnVersion = mkOption { + type = types.str; + default = "02.03.00.99"; + description = '' + Plugin ABI version baked into the built filename. Must match what + the slicer expects: check with + jq -r '.app.network_plugin_version // "not set"' <configDir>/OrcaSlicer.conf + First three components should match what the app reports; the + last component should stay .99 (see README). + ''; + }; + + configDir = mkOption { + type = types.str; + default = "${config.xdg.configHome}/OrcaSlicer"; + defaultText = literalExpression ''"''${config.xdg.configHome}/OrcaSlicer"''; + description = '' + Directory containing OrcaSlicer.conf and its plugins/ subfolder. + Override this if you're on a fork with a different config + directory (e.g. ~/.config/BambuStudio, ~/.config/OrcaSlicer-Nightly), + or a Flatpak install (e.g. ~/.var/app/io.github.softfever.OrcaSlicer/config/OrcaSlicer). + Must be a path under $HOME. + ''; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + (mkIf cfg.orcaSlicer.enable { + home.packages = [ orcaPlugin ]; + + home.file = { + "${relToHome cfg.orcaSlicer.configDir}/plugins/libbambu_networking_${cfg.orcaSlicer.obnVersion}.so".source = + "${orcaPlugin}/plugins/libbambu_networking_${cfg.orcaSlicer.obnVersion}.so"; + "${relToHome cfg.orcaSlicer.configDir}/plugins/libBambuSource.so".source = + "${orcaPlugin}/plugins/libBambuSource.so"; + }; + }) + ]); +} diff --git a/package.nix b/package.nix new file mode 100644 index 0000000..7363fbb --- /dev/null +++ b/package.nix @@ -0,0 +1,113 @@ +{ + lib, + stdenv, + fetchFromGitHub, + cmake, + pkg-config, + openssl, + zlib, + curl, + # Which slicer this build targets. Determines the OBN_CLIENT_TYPE CMake + # passes through, which in turn determines the expected filename/version + # scheme for the built plugin. Currently "orca_slicer" is the only target + # exercised by this flake's home-manager module, but the upstream project + # also builds for e.g. "bambu_studio" - see its CMakeLists.txt/Clients.cmake + # for the full list. + clientType ? "orca_slicer", + # The plugin ABI is versioned into the .so filename the slicer expects + # (libbambu_networking_<version>.so). Check yours with: + # jq -r '.app.network_plugin_version // "not set"' ~/.config/OrcaSlicer/OrcaSlicer.conf + # and pass that here (with .99 as the 4th component - see README) if it differs. + obnVersion ? "02.03.00.99", +}: + +let + # Vendored deps the upstream CMakeLists normally fetches over the network + # at configure time via FetchContent. We pre-fetch them as normal Nix + # sources and hand CMake writable copies instead (see preConfigure), + # so the build stays sandboxed. + mosquittoSrc = fetchFromGitHub { + owner = "eclipse"; + repo = "mosquitto"; + rev = "v2.1.2"; # must match OBN_MOSQUITTO_GIT_TAG in CMakeLists.txt + hash = "sha256-Zl55yjuzQY2fyaKs/zLaJ7a3OONKTDQPaT+DpPURdZI="; + }; + + cjsonSrc = fetchFromGitHub { + owner = "DaveGamble"; + repo = "cJSON"; + rev = "v1.7.18"; # must match OBN_CJSON_GIT_TAG in CMakeLists.txt + hash = "sha256-UgUWc/+Zie2QNijxKK5GFe4Ypk97EidG8nTiiHhn5Ys="; + }; +in +stdenv.mkDerivation { + pname = "open-bamboo-networking-${clientType}"; + version = "1.1.0"; + + src = fetchFromGitHub { + owner = "ClusterM"; + repo = "open-bamboo-networking"; + rev = "v1.1.0"; + hash = "sha256-bxkOwCnlKu2fA3cEiTZq15anSwLkuJIyko19wqul6Fw="; + }; + + nativeBuildInputs = [ + cmake + pkg-config + ]; + buildInputs = [ + openssl + zlib + curl + ]; + + cmakeFlags = [ + "-DOBN_CLIENT_TYPE=${clientType}" + "-DOBN_VERSION=${obnVersion}" + "-DOBN_BUILD_TESTS=OFF" + # This build never touches $HOME - see README.md for install steps. + "-DOBN_PATCH_CLIENT_CONF=OFF" + "-DFETCHCONTENT_FULLY_DISCONNECTED=ON" + ]; + + # The build patches the vendored mosquitto/cJSON sources in place + # (VendorMosquittoEmbedPatch.cmake writes into libcommon/CMakeLists.txt + # etc.), so FETCHCONTENT_SOURCE_DIR_* can't point directly at the + # read-only fetchFromGitHub store paths. Copy them into a writable + # scratch dir first and point CMake there instead. + preConfigure = '' + mkdir -p _vendor/mosquitto _vendor/cjson + cp -r --no-preserve=mode,ownership ${mosquittoSrc}/. _vendor/mosquitto + cp -r --no-preserve=mode,ownership ${cjsonSrc}/. _vendor/cjson + chmod -R u+w _vendor + cmakeFlagsArray+=( + "-DFETCHCONTENT_SOURCE_DIR_ECLIPSE_MOSQUITTO=$(pwd)/_vendor/mosquitto" + "-DFETCHCONTENT_SOURCE_DIR_CJSON=$(pwd)/_vendor/cjson" + ) + ''; + + # `cmake --install` (run automatically by the stdenv cmake hook) produces, + # under $out/plugins/: + # libbambu_networking_<obnVersion>.so - LAN discovery/print/MQTT + # libBambuSource.so - camera/live-view tunnel + # liblive555.so - OTA-banner-check stub only, + # see README before installing + postInstall = '' + mkdir -p $out/lib + ln -s $out/plugins/libbambu_networking_${obnVersion}.so \ + $out/lib/libbambu_networking_${obnVersion}.so + ''; + + # Read this back from downstream (README examples, activation scripts) + # instead of repeating the version string everywhere. + passthru = { + inherit obnVersion clientType; + }; + + meta = with lib; { + description = "Open-source drop-in replacement for Bambu Lab slicers' proprietary bambu_networking plugin (client: ${clientType})"; + homepage = "https://github.com/ClusterM/open-bamboo-networking"; + license = licenses.agpl3Plus; + platforms = platforms.linux; + }; +} |
