rec { description = "C++ Brainfuck Interpreter"; inputs = { nixpkgs.url = "nixpkgs"; # Use nixpkgs from system registry flake-utils.url = "github:numtide/flake-utils"; rust-overlay.url = "github:oxalica/rust-overlay"; rust-overlay.inputs.nixpkgs.follows = "nixpkgs"; }; outputs = { self, nixpkgs, flake-utils, rust-overlay, }: # Create a shell (and possibly package) for each possible system, not only x86_64-linux flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; config.allowUnfree = true; overlays = [ rust-overlay.overlays.default ]; }; inherit (pkgs) lib stdenv; python = pkgs.python313.withPackages (p: with p; [ pyside6 ffmpeg-python matplotlib numpy ]); rust = pkgs.rust-bin.stable.latest.default.override { extensions = ["rust-src"]; # Include the Rust stdlib source (for IntelliJ) }; # 64 bit C/C++ compilers that don't collide (use the same libc) bintools = pkgs.wrapBintoolsWith { bintools = pkgs.bintools.bintools; # Unwrapped bintools libc = pkgs.glibc; }; gcc = pkgs.hiPrio (pkgs.wrapCCWith { cc = pkgs.gcc.cc; # Unwrapped gcc libc = pkgs.glibc; bintools = bintools; }); clang = pkgs.wrapCCWith { cc = pkgs.clang.cc; # Unwrapped clang libc = pkgs.glibc; bintools = bintools; }; # Multilib C/C++ compilers that don't collide (use the same libc) bintools_multilib = pkgs.wrapBintoolsWith { bintools = pkgs.bintools.bintools; # Unwrapped bintools libc = pkgs.glibc_multi; }; gcc_multilib = pkgs.hiPrio (pkgs.wrapCCWith { cc = pkgs.gcc.cc; # Unwrapped gcc libc = pkgs.glibc_multi; bintools = bintools_multilib; }); clang_multilib = pkgs.wrapCCWith { cc = pkgs.clang.cc; # Unwrapped clang libc = pkgs.glibc_multi; bintools = bintools_multilib; }; # Stuff ran at build-time (e.g. cmake, autoPatchelfHook). # Architecture will be the build/target platform (relevant for e.g. cross-compilation). # Packages will be added to $PATH. nativeBuildInputs = with pkgs; []; # Stuff that's linked against. # Architecture will be the host platform. # Packages will be added to $PATH unless "strictDeps = true;". buildInputs = with pkgs; [ # Languages: # python # rust bintools gcc clang # bintools_multilib # gcc_multilib # clang_multilib # C/C++: gdb valgrind gnumake cmake # boost # sfml # Qt: # qt6.qtbase # qt6.full # qt6.wrapQtAppsHook # For the shellHook ]; in { # TODO: Add default packages for different languages # TODO: check nixpkgs docs for buildPythonApplication # packages.${system}.default = pkgs.buildPythonApplication { # pname = "pyside6_image_viewer"; # version = "0.1.0"; # }; packages.${system}.default = stdenv.mkDerivation { pname = "bfuck"; version = "1.0.0"; src = ./.; inherit nativeBuildInputs buildInputs; }; devShell = pkgs.mkShell { name = description; # Comments on buildInputs, nativeBuildInputs, buildPackages: # https://discourse.nixos.org/t/use-buildinputs-or-nativebuildinputs-for-nix-shell/8464 # For our "nix develop" shell, buildInputs can be used for everything. inherit nativeBuildInputs buildInputs; # Rust stdlib source: # RUST_SRC_PATH = "${rust}/lib/rustlib/src/rust/library"; # Custom dynamic libraries: # LD_LIBRARY_PATH = builtins.concatStringsSep ":" [ # # Rust Bevy GUI app # "${pkgs.xorg.libX11}/lib" # "${pkgs.xorg.libXcursor}/lib" # "${pkgs.xorg.libXrandr}/lib" # "${pkgs.xorg.libXi}/lib" # "${pkgs.libGL}/lib" # ]; # Dynamic libraries from buildinputs: # LD_LIBRARY_PATH = nixpkgs.lib.makeLibraryPath buildInputs; # Setup the shell when entering the "nix develop" environment (bash script). shellHook = let mkCmakeScript = type: let typeLower = lib.toLower type; in pkgs.writers.writeFish "cmake-${typeLower}.fish" '' cd $FLAKE_PROJECT_ROOT echo "Removing build directory ./cmake-build-${typeLower}/" rm -rf ./cmake-build-${typeLower} echo "Creating build directory" mkdir cmake-build-${typeLower} cd cmake-build-${typeLower} echo "Running cmake" cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE="${type}" -DCMAKE_EXPORT_COMPILE_COMMANDS="On" .. echo "Linking compile_commands.json" cd .. ln -sf ./cmake-build-${typeLower}/compile_commands.json ./compile_commands.json ''; cmakeDebug = mkCmakeScript "Debug"; cmakeRelease = mkCmakeScript "Release"; mkBuildScript = type: let typeLower = lib.toLower type; in pkgs.writers.writeFish "cmake-build.fish" '' cd $FLAKE_PROJECT_ROOT/cmake-build-${typeLower} echo "Running cmake" cmake --build . ''; buildDebug = mkBuildScript "Debug"; buildRelease = mkBuildScript "Release"; # Use this to specify commands that should be ran after entering fish shell initProjectShell = pkgs.writers.writeFish "init-shell.fish" '' echo "Entering \"${description}\" environment..." # Determine the project root, used e.g. in cmake scripts set -g -x FLAKE_PROJECT_ROOT (git rev-parse --show-toplevel) # Add shell abbreviations specific to this build environment # Rust Bevy: # abbr -a build-release-windows "CARGO_FEATURE_PURE=1 cargo xwin build --release --target x86_64-pc-windows-msvc" # C/C++: abbr -a cmake-debug "${cmakeDebug}" abbr -a cmake-release "${cmakeRelease}" abbr -a build-debug "${buildDebug}" abbr -a build-release "${buildRelease}" ''; in builtins.concatStringsSep "\n" [ # Launch into pure fish shell '' exec "$(type -p fish)" -C "source ${initProjectShell} && abbr -a menu '${pkgs.bat}/bin/bat "${initProjectShell}"'" '' # Qt: Launch into wrapped fish shell # '' # fishdir=$(mktemp -d) # makeWrapper "$(type -p fish)" "$fishdir/fish" "''${qtWrapperArgs[@]}" # exec "$fishdir/fish" -C "source ${initProjectShell} && abbr -a menu '${pkgs.bat}/bin/bat "${initProjectShell}"'" # '' ]; }; }); }