{ description = "GKleen's flakey openwrt setup"; inputs = { openwrt = { type = "github"; owner = "openwrt"; repo = "openwrt"; ref = "master"; flake = false; }; flake-utils = { type = "github"; owner = "numtide"; repo = "flake-utils"; ref = "master"; }; nixpkgs = { type = "github"; owner = "NixOS"; repo = "nixpkgs"; ref = "master"; }; openwrt-packages = { url = "git+https://git.openwrt.org/feed/packages.git"; flake = false; }; openwrt-luci = { url = "git+https://git.openwrt.org/project/luci.git"; flake = false; }; openwrt-routing = { url = "git+https://git.openwrt.org/feed/routing.git"; flake = false; }; openwrt-telephony = { url = "git+https://git.openwrt.org/feed/telephony.git"; flake = false; }; sunwait = { type = "github"; owner = "risacher"; repo = "sunwait"; ref = "master"; flake = false; }; }; outputs = { self, openwrt, nixpkgs, flake-utils, ... }@inputs: flake-utils.lib.eachDefaultSystem (system: let pkgs = nixpkgs.legacyPackages.${system}; fixWrapper = pkgs.runCommand "fix-wrapper" {} '' mkdir -p $out/bin for i in ${pkgs.gcc.cc}/bin/*-gnu-gcc*; do ln -s ${pkgs.gcc}/bin/gcc $out/bin/$(basename "$i") done for i in ${pkgs.gcc.cc}/bin/*-gnu-{g++,c++}*; do ln -s ${pkgs.gcc}/bin/g++ $out/bin/$(basename "$i") done ''; fhs = extraAttrs: pkgs.buildFHSUserEnvBubblewrap ({ name = "openwrt-env"; multiPkgs = null; inherit targetPkgs; extraOutputsToInstall = [ "dev" ]; profile = '' export NIX_HARDENING_ENABLE= ''; } // extraAttrs); targetPkgs = pkgs: with pkgs; [ binutils file fixWrapper gcc getopt gettext git gnumake openssl patch perl python2 python3 rsync subversion systemd unzip wget which ncurses zlib # zlib.static # glibc.static pkgconfig ubnt-mkfwimage gnused ]; openwrtWithPackages = pkgs.stdenv.mkDerivation { name = "openwrt-with-packages"; src = openwrt; phases = [ "unpackPhase" "patchPhase" "buildPhase" "installPhase" ]; patchPhase = let sunwaitRepo = pkgs.runCommand "openwrt-sunwait" {} '' mkdir -p $out/utils/sunwait cp ${pkgs.writeText "Makefile" '' include $(TOPDIR)/rules.mk PKG_NAME:=sunwait PKG_VERSION:=${inputs.sunwait.rev} PKG_RELEASE:=1 include $(INCLUDE_DIR)/package.mk define Package/sunwait SECTION:=util CATEGORY:=Utilities TITLE:=Sunwait URL:=https://github.com/risacher/sunwait DEPENDS:=+libstdcpp +libc endef define Package/sunwait/description Wait until the specified solar event endef define Build/Prepare cp -t $(PKG_BUILD_DIR) -r ${inputs.sunwait}/. endef define Build/Compile $(TARGET_CC) $(TARGET_CPPFLAGS) -o $(PKG_BUILD_DIR)/sunwait.o -c $(PKG_BUILD_DIR)/sunwait.cpp $(TARGET_CC) $(TARGET_CPPFLAGS) -o $(PKG_BUILD_DIR)/sunriset.o -c $(PKG_BUILD_DIR)/sunriset.cpp $(TARGET_CC) $(TARGET_CPPFLAGS) -o $(PKG_BUILD_DIR)/print.o -c $(PKG_BUILD_DIR)/print.cpp $(TARGET_CC) $(TARGET_LDFLAGS) -o $(PKG_BUILD_DIR)/$1 $(PKG_BUILD_DIR)/sunwait.o $(PKG_BUILD_DIR)/sunriset.o $(PKG_BUILD_DIR)/print.o -lm -lstdc++ endef define Package/sunwait/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/sunwait $(1)/usr/bin/ endef $(eval $(call BuildPackage,sunwait)) ''} $out/utils/sunwait/Makefile ''; feedsConf = pkgs.writeText "feeds.conf" '' src-cpy packages ${inputs.openwrt-packages} src-cpy luci ${inputs.openwrt-luci} src-cpy routing ${inputs.openwrt-routing} src-cpy telephony ${inputs.openwrt-telephony} src-cpy sunwait ${sunwaitRepo} ''; in '' rm feeds.conf.default cp ${feedsConf} feeds.conf ''; buildPhase = '' ${let runScript = pkgs.writeShellScript "build" '' ./scripts/feeds update -a ./scripts/feeds install -a ''; in fhs { inherit runScript; }}/bin/openwrt-env ''; installPhase = '' cp -r . $out ''; }; ubnt-mkfwimage = pkgs.stdenv.mkDerivation rec { pname = "ubnt-mkfwimage"; version = "70594ca"; src = pkgs.fetchFromGitHub { owner = "aliosa27"; repo = "ubnt-mkfwimage"; rev = version; hash = "sha256-NTOSQzRYO/3N2sNLBUa6uzA8LZSshL8W36kW2ociqrA="; }; buildInputs = with pkgs; [ gcc zlib ]; phases = [ "unpackPhase" "buildPhase" "installPhase" ]; sourceRoot = "source/src"; buildPhase = '' gcc -lz -o ubnt-mkfwimage ubnt-mkfwimage.c gcc -lz -o ubnt-fwsplit fwsplit.c ''; installPhase = '' mkdir -p $out/bin install -m 0555 -t $out/bin ubnt-mkfwimage ubnt-fwsplit ''; }; unpackWrt = pkgs.writeShellScript "unpack" '' ${pkgs.rsync}/bin/rsync --chmod=u+wX -rlptD --exclude /tmp --exclude /build_dir --exclude /bin --exclude /staging_dir ${openwrtWithPackages}/. ${./files}/. ./. patchDir=$(mktemp -d -t patches.XXXXXXXXXX) ${pkgs.rsync}/bin/rsync --chmod=u+wX -rlptD ${./patches}/. "''${patchDir}/." while IFS= read -r -d $'\0' sopsFile; do ${pkgs.sops}/bin/sops --output="''${sopsFile%.sops}" --decrypt "''${sopsFile}" rm "''${sopsFile}" done < <(find . "$patchDir" -not \( \( -path ./tmp -o -path ./build_dir -o -path ./bin -o -path ./staging_dir \) -a -prune \) -a \( -type f -a -name '*.sops' -a -print0 \)) while IFS= read -r -d $'\0' patchFile; do if [[ "''${patchFile##*.}" = "patch" ]]; then patch -p1 --batch <$patchFile else . $patchFile fi done < <(find "$patchDir" -type f -print0) ''; buildWrt = pkgs.writeShellScript "build" "make -j V=sc"; buildWrtApp = { type = "app"; program = toString (pkgs.writers.writePython3 "build" {} '' from tempfile import TemporaryDirectory import os import subprocess import argparse from pathlib import Path parser = argparse.ArgumentParser(prog="build", formatter_class=argparse.ArgumentDefaultsHelpFormatter # noqa: E501 ) parser.add_argument('-C', '--directory', dest='dir', metavar='DIRECTORY', type=Path, default=Path('./result'), help='Change to this directory before doing anything' ) parser.add_argument('--copy-to', dest='copyTo', metavar='FILE', type=Path, default='/srv/tftp/' + Path.cwd().name + '.bin', help='Copy result image here' ) parser.add_argument('--copy-to-no-sudo', dest='copyToSudo', action='store_false', help='Use sudo to copy result image' ) parser.add_argument('--copy-image', dest='image', default='bin/targets/ath79/generic/openwrt-ath79-generic-ubnt_unifiac-pro-initramfs-kernel.bin', # noqa: E501 help='Which file to copy' ) args = parser.parse_args() if not args.dir: args.dir = Path() if not args.copyTo: args.copyTo = None args.dir.mkdir(parents=True, exist_ok=True) os.chdir(args.dir) with TemporaryDirectory() as tmpdir: os.environ["TMPDIR"] = f"{tmpdir}" subprocess.check_call('${fhs { runScript = pkgs.writeShellScript "build" '' set +x set -e ${unpackWrt} ${buildWrt} ''; }}/bin/openwrt-env') if args.copyTo: command = ['cp', args.image, args.copyTo] if args.copyToSudo: command = ['sudo', '--', *command] subprocess.check_call(command) ''); }; in rec { devShell = pkgs.mkShell { name = "openwrt"; shellHook = let setup = pkgs.writeText "setup" '' set -ex function unpackPhase() { ${unpackWrt} } function buildPhase() { ${buildWrt} } set +ex ''; in "exec -- ${fhs { runScript = "bash --init-file ${setup}"; }}/bin/openwrt-env"; }; packages = { inherit openwrtWithPackages ubnt-mkfwimage; }; apps = { inherit buildWrtApp; }; defaultApp = apps.buildWrtApp; }); }