From 21650fe751b22191345be15d727ed7d1ea107f8a Mon Sep 17 00:00:00 2001 From: Samuel Grayson Date: Tue, 15 Oct 2024 00:18:52 -0500 Subject: [PATCH 1/9] fix-install --- probe_src/frontend/frontend.nix | 2 + probe_src/tests/docker_os_matrix.py | 162 ++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 probe_src/tests/docker_os_matrix.py diff --git a/probe_src/frontend/frontend.nix b/probe_src/frontend/frontend.nix index 4a82270f..c2d1cc87 100644 --- a/probe_src/frontend/frontend.nix +++ b/probe_src/frontend/frontend.nix @@ -109,7 +109,9 @@ python.pkgs.flit-core ]; unpackPhase = '' + mkdir /build cp --recursive ${probe-py-generated-src}/* /build + cd /build ''; pythonImportsCheck = [pname]; }; diff --git a/probe_src/tests/docker_os_matrix.py b/probe_src/tests/docker_os_matrix.py new file mode 100644 index 00000000..0f1f9964 --- /dev/null +++ b/probe_src/tests/docker_os_matrix.py @@ -0,0 +1,162 @@ +import io +import typing +import tempfile +import sys +import collections.abc +import subprocess +import shlex +import pathlib +import asyncio + + +project_root = pathlib.Path(__file__).resolve().parent.parent.parent + + +_T = typing.TypeVar("_T") + + +def as_completed_with_concurrency( + n: int, + coros: typing.Iterable[collections.abc.Awaitable[_T]], +) -> typing.Iterator[asyncio.Future[_T]]: + semaphore = asyncio.Semaphore(n) + async def sem_coro(coro: collections.abc.Awaitable[_T]) -> _T: + async with semaphore: + return await coro + return asyncio.as_completed([sem_coro(c) for c in coros]) + + +async def run_in_docker( + name: str, + image: str, + tag: str, + script: list[list[list[str]]], + test: list[list[str]], + capture_output: bool, + clean: bool, +) -> tuple[str, bool, bytes, bytes]: + dockerfile = "\n".join([ + f"FROM {image}:{tag}", + *[ + "RUN " + " && ".join( + shlex.join(line).replace("double-pipe", "||") + for line in group + ) + for group in script + ], + ]) + temp_dir = pathlib.Path(tempfile.mkdtemp()) + (temp_dir / "Dockerfile").write_text(dockerfile) + proc = await asyncio.create_subprocess_exec( + *["podman", "build", "--tag", name, str(temp_dir)], + stdout=subprocess.PIPE if capture_output else None, + stderr=subprocess.PIPE if capture_output else None, + ) + if capture_output: + stdout, stderr = await proc.communicate() + else: + stdout, stderr = b"", b"" + + await proc.wait() + + if proc.returncode != 0: + return name, False, stdout, stderr + + test_str = " && ".join( + shlex.join(line) + for line in test + ) + args = ["podman", "run", "--rm", "--volume", f"{project_root}:{project_root}:ro", name, "bash", "-c", test_str] + proc = await asyncio.create_subprocess_exec( + *args, + stdin=None, + stdout=subprocess.PIPE if capture_output else None, + stderr=subprocess.PIPE if capture_output else None, + ) + if capture_output: + result = await proc.communicate() + else: + result = b"", b"" + + stdout += result[0] + stderr += result[1] + + await proc.wait() + + return name, not proc.returncode, stdout, stderr + + +images = [ + ("ubuntu", ["24.04"], [[ + ["apt-get", "update"], + ["DEBIAN_FRONTEND=noninteractive", "apt-get", "install", "-y", "curl"], + ["rm", "--recursive", "--force", "/var/lib/apt/lists/*"] + ]]), + # ("debian", ["8.0", "unstable-slim"], [[ + # ["apt-get", "update"], + # ["DEBIAN_FRONTEND=noninteractive", "apt-get", "install", "-y", "curl"], + # ["rm", "--recursive", "--force", "/var/lib/apt/lists/*"] + # ]]), + # ("fedora-slim", ["23", "41"], []), + # Alpine uses musl c, which should be interesting + # ("alpine", ["2.6", "3.20"], []), +] + + +script = [ + # shlex.quote("|") -> "'|'", which is wrong, so instead we will write the word pipe. + [ + ["curl", "--proto", "=https", "--tlsv1.2", "-sSf", "-o", "nix-installer", "-L", "https://install.determinate.systems/nix"], + ["sh", "nix-installer", "install", "linux", "--no-confirm", "--init", "none"], + ], + [ + [".", "/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh"], + ["export", "USER=root"], + ["nix", "profile", "install", "--accept-flake-config", "nixpkgs#cachix"], + ["cachix", "use", "charmonium"], + ], + [ + ["export", "USER=root"], + [".", "/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh"], + ["nix", "build", "-L", "github:charmoniumQ/PROBE#probe-bundled", "double-pipe", "true"], + ], +] + +test = [ + ["export", "USER=root"], + [".", "/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh"], + ["nix", "profile", "install", "-L", f"{project_root}#probe-bundled"], + ["probe", "record", "-f", "stat", "."] +] + + +async def main(max_concurrency: int, capture_output: bool) -> bool: + results = as_completed_with_concurrency(max_concurrency, [ + run_in_docker( + f"probe-{image}-{tag}", + image, + tag, + pre_script + script, + test, + capture_output, + clean=False, + ) + for image, tags, pre_script in images + for tag in tags + ]) + any_failed = False + for result in results: + image, success, stdout, stderr = await result + if not success: + print(image, "failed") + sys.stdout.buffer.write(stdout) + sys.stderr.buffer.write(stderr) + print("\n") + any_failed = True + return any_failed + +if asyncio.run(main( + max_concurrency=1, + capture_output=False, +)): + sys.exit(1) From 1e99a02adc7210ad060c1b5aa72e3b4abaabab75 Mon Sep 17 00:00:00 2001 From: Samuel Grayson Date: Tue, 15 Oct 2024 10:05:46 -0500 Subject: [PATCH 2/9] Fix stuff --- .github/workflows/ci.yml | 21 +++++++++++++-- Justfile | 12 ++++++--- flake.nix | 1 + probe_src/frontend/frontend.nix | 47 ++++++++++++++------------------- 4 files changed, 49 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7507bb96..c0d947f0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,11 @@ on: jobs: build: - runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-22.04, ubuntu-20.04] + + runs-on: ${{ matrix.os }} steps: - name: Checkout repository @@ -21,5 +25,18 @@ jobs: extra_nix_config: | experimental-features = nix-command flakes - - name: Run Just in development shell + - name: Test existence of Cachix signing key + run: echo ${{ secrets.CACHIX_SIGNING_KEY }} | wc -c + + - uses: cachix/cachix-action@v15 + with: + name: charmonium + signingKey: ${{ secrets.CACHIX_SIGNING_KEY }} + + - name: Build devshell + # I think we need to "build" the devshell so it gets cached by Cachix + # It has to be built anyway, to actually run + run: nix build .#devshell + + - name: Run Just on-push stuff in development shell run: nix develop --command just on-push diff --git a/Justfile b/Justfile index f7631f65..2428c28b 100644 --- a/Justfile +++ b/Justfile @@ -49,6 +49,12 @@ test-dev: compile-lib check-flake: nix flake check --all-systems -pre-commit: fix-format-nix fix-ruff fix-format-rust fix-clippy compile check-mypy test-dev - -on-push: check-format-nix check-ruff check-format-rust check-clippy compile check-mypy check-flake test-ci +user-facing-build: + # `just compile` is great, but it's the _dev-facing_ build. + # Users will build PROBE following the `README.md` + # which says `nix profile install github:charmoniumQ/PROBE#probe-bundled` + # Which should be equivalent to this: + nix build .#probe-bundled + +pre-commit: fix-format-nix fix-ruff fix-format-rust fix-clippy compile check-mypy test-dev +on-push: check-format-nix check-ruff check-format-rust check-clippy compile check-mypy test-ci check-flake user-facing-build diff --git a/flake.nix b/flake.nix index 32bf451d..569765a5 100644 --- a/flake.nix +++ b/flake.nix @@ -52,6 +52,7 @@ in { packages = rec { + devshell = self.packages.${system}.devShells.default; probe-bundled = let # libprobe is a "private" package # It is only used in probe-bundled diff --git a/probe_src/frontend/frontend.nix b/probe_src/frontend/frontend.nix index c2d1cc87..33144a0c 100644 --- a/probe_src/frontend/frontend.nix +++ b/probe_src/frontend/frontend.nix @@ -79,40 +79,33 @@ # TODO: Simplify this # Perhaps by folding the substituteAllFiles into probe-py-generated (upstream) or probe-py-frontend (downstream) # Could we combine all the packages? - probe-py-generated-src = pkgs.substituteAllFiles rec { - name = "probe-py-${version}"; - src = probe-frontend; - files = [ - "./pyproject.toml" - "./LICENSE" - "./probe_py/generated/__init__.py" - "./probe_py/generated/ops.py" - "./probe_py/generated/parser.py" - ]; - - authors = builtins.concatStringsSep "" (builtins.map (match: let - name = builtins.elemAt match 0; - email = builtins.elemAt match 1; - in "\n {name = \"${name}\", email = \"${email}\"},") ( - builtins.map - (author-str: builtins.match "(.+) <(.+)>" author-str) - (workspace.package.authors) - )); - version = workspace.package.version; - }; in python.pkgs.buildPythonPackage rec { + src = pkgs.substituteAllFiles rec { + src = probe-frontend; + files = [ + "./pyproject.toml" + "./LICENSE" + "./probe_py/generated/__init__.py" + "./probe_py/generated/ops.py" + "./probe_py/generated/parser.py" + ]; + authors = builtins.concatStringsSep "" (builtins.map (match: let + name = builtins.elemAt match 0; + email = builtins.elemAt match 1; + in "\n {name = \"${name}\", email = \"${email}\"},") ( + builtins.map + (author-str: builtins.match "(.+) <(.+)>" author-str) + (workspace.package.authors) + )); + version = workspace.package.version; + }; pname = "probe_py.generated"; - version = probe-py-generated-src.version; + version = workspace.package.version; pyproject = true; build-system = [ python.pkgs.flit-core ]; - unpackPhase = '' - mkdir /build - cp --recursive ${probe-py-generated-src}/* /build - cd /build - ''; pythonImportsCheck = [pname]; }; probe-cli = craneLib.buildPackage (individualCrateArgs From dc3e3508affb9672e9ffe8ee965400f05dd45da6 Mon Sep 17 00:00:00 2001 From: Samuel Grayson Date: Tue, 15 Oct 2024 10:55:06 -0500 Subject: [PATCH 3/9] Fix Nix stuff --- Justfile | 4 +- flake.nix | 119 +++++++++++------- probe_src/frontend/frontend.nix | 60 +++------ probe_src/frontend/lib/src/transcribe.rs | 15 ++- .../frontend/python/probe_py/generated/ops.py | 2 + probe_src/tests/docker_os_matrix.py | 1 - 6 files changed, 108 insertions(+), 93 deletions(-) diff --git a/Justfile b/Justfile index 2428c28b..5e69c148 100644 --- a/Justfile +++ b/Justfile @@ -40,10 +40,10 @@ compile-tests: compile: compile-lib compile-cli compile-tests -test-ci: compile-lib +test-ci: compile pytest probe_src -test-dev: compile-lib +test-dev: compile pytest probe_src --failed-first --maxfail=1 check-flake: diff --git a/flake.nix b/flake.nix index 569765a5..b222657a 100644 --- a/flake.nix +++ b/flake.nix @@ -28,48 +28,60 @@ nixpkgs, flake-utils, rust-overlay, + crane, + advisory-db, ... } @ inputs: let - supported-systems = [ - "x86_64-linux" - "i686-linux" - "aarch64-linux" - "armv7l-linux" - ]; - in - flake-utils.lib.eachSystem + supported-systems = { + # "nix system" = "rust target"; + "x86_64-linux" = "x86_64-unknown-linux-musl"; # Even with Nextflow (requires OpenJDK) removed, # i686-linux still doesn't build. # Only the wind and water know why. Us mere mortals never will. - (nixpkgs.lib.lists.remove "i686-linux" supported-systems) + #"i686-linux" = "i686-unknown-linux-musl"; + "aarch64-linux" = "aarch64-unknown-linux-musl"; + "armv7l-linux" = "armv7-unknown-linux-musleabi"; + }; + in + flake-utils.lib.eachSystem + (builtins.attrNames supported-systems) (system: let pkgs = import nixpkgs { inherit system; overlays = [(import rust-overlay)]; }; + lib = nixpkgs.lib; python = pkgs.python312; - frontend = (import ./probe_src/frontend/frontend.nix) ({inherit system pkgs python;} // inputs); - in { - packages = - rec { - devshell = self.packages.${system}.devShells.default; - probe-bundled = let - # libprobe is a "private" package - # It is only used in probe-bundled - # TODO: The only public package should probably be probe-bundled and probe-py. - libprobe = pkgs.stdenv.mkDerivation rec { - pname = "libprobe"; - version = "0.1.0"; - src = ./probe_src/libprobe; - makeFlags = ["INSTALL_PREFIX=$(out)" "SOURCE_VERSION=${version}"]; - buildInputs = [ - (pkgs.python312.withPackages (pypkgs: [ - pypkgs.pycparser - ])) - ]; - }; - in - pkgs.stdenv.mkDerivation rec { + rust-target = supported-systems.${system}; + craneLib = (crane.mkLib pkgs).overrideToolchain (p: + p.rust-bin.stable.latest.default.override { + targets = [rust-target]; + }); + frontend = (import ./probe_src/frontend/frontend.nix) { + inherit + system + pkgs + python + rust-target + craneLib + lib + advisory-db + ; + }; + in rec { + packages = rec { + libprobe = pkgs.stdenv.mkDerivation rec { + pname = "libprobe"; + version = "0.1.0"; + src = ./probe_src/libprobe; + makeFlags = ["INSTALL_PREFIX=$(out)" "SOURCE_VERSION=${version}"]; + buildInputs = [ + (pkgs.python312.withPackages (pypkgs: [ + pypkgs.pycparser + ])) + ]; + }; + probe-bundled = pkgs.stdenv.mkDerivation rec { pname = "probe-bundled"; version = "0.1.0"; dontUnpack = true; @@ -78,7 +90,7 @@ installPhase = '' mkdir $out $out/bin makeWrapper \ - ${self.packages.${system}.probe-cli}/bin/probe \ + ${frontend.packages.probe-cli}/bin/probe \ $out/bin/probe \ --set __PROBE_LIB ${libprobe}/lib \ --prefix PATH : ${probe-py}/bin @@ -93,7 +105,7 @@ ]; src = ./probe_src/python; propagatedBuildInputs = [ - self.packages.${system}.probe-py-generated + frontend.packages.probe-py-generated python.pkgs.networkx python.pkgs.pygraphviz python.pkgs.pydot @@ -102,22 +114,41 @@ ]; pythonImportsCheck = [pname]; }; - probe-py = python.withPackages (pypkgs: [probe-py-manual]); + probe-py = python.withPackages (pypkgs: [frontend.packages.probe-py-manual]); default = probe-bundled; - } - // frontend.packages; - # TODO: Run pytest tests in Nix checks - checks = self.packages.${system} // frontend.checks; + }; + checks = { + inherit (frontend.checks) + probe-workspace-clippy + probe-workspace-doc + probe-workspace-fmt + probe-workspace-audit + probe-workspace-deny + probe-workspace-nextest + ; + # The python import checks are so fast, we will incorporate those tests into the package. + # TODO: Add integration PROBE tests (already have in pytest). + }; devShells = { - default = frontend.devShells.default.overrideAttrs (oldAttrs: rec { + default = craneLib.devShell { shellHook = '' pushd $(git rev-parse --show-toplevel) source ./setup_devshell.sh popd ''; - buildInputs = - oldAttrs.buildInputs - ++ [ + inputsFrom = [ + frontend.packages.probe-frontend + frontend.packages.probe-cli + frontend.packages.probe-macros + ]; + packages = [ + pkgs.cargo-audit + pkgs.cargo-expand + pkgs.cargo-flamegraph + pkgs.cargo-watch + pkgs.gdb + pkgs.rust-analyzer + (python.withPackages (pypkgs: [ # probe_py.manual runtime requirements pypkgs.networkx @@ -135,7 +166,9 @@ # libprobe build time requirement pypkgs.pycparser ])) + # (export-and-rename python312-debug [["bin/python" "bin/python-dbg"]]) + pkgs.which pkgs.gnumake pkgs.gcc @@ -153,7 +186,7 @@ ++ pkgs.lib.lists.optional (system != "aarch64-darwin") pkgs.gdb # while xdot isn't marked as linux only, it has a dependency (xvfb-run) that is ++ pkgs.lib.lists.optional (builtins.elem system pkgs.lib.platforms.linux) pkgs.xdot; - }); + }; }; } ); diff --git a/probe_src/frontend/frontend.nix b/probe_src/frontend/frontend.nix index 33144a0c..18abc8b0 100644 --- a/probe_src/frontend/frontend.nix +++ b/probe_src/frontend/frontend.nix @@ -1,25 +1,19 @@ { - self, pkgs, - crane, + craneLib, + rust-target, advisory-db, system, python, - ... -}: let - systems = { - # "nix system" = "rust target"; - "x86_64-linux" = "x86_64-unknown-linux-musl"; - "i686-linux" = "i686-unknown-linux-musl"; - "aarch64-linux" = "aarch64-unknown-linux-musl"; - "armv7l-linux" = "armv7-unknown-linux-musleabi"; - }; - craneLib = (crane.mkLib pkgs).overrideToolchain (p: - p.rust-bin.stable.latest.default.override { - targets = [systems.${system}]; - }); + lib, +}: rec { - src = ./.; + src = lib.cleanSource ./.; + filter = name: type: + !(builtins.any (x: x) [ + (lib.hasSuffix ".nix" name) + (lib.hasPrefix "." (builtins.baseNameOf name)) + ]); # Common arguments can be set here to avoid repeating them later commonArgs = { @@ -40,7 +34,7 @@ export PYGEN_OUTFILE="$(realpath ./python/probe_py/generated/ops.py)" ''; - CARGO_BUILD_TARGET = systems.${system}; + CARGO_BUILD_TARGET = rust-target; CARGO_BUILD_RUSTFLAGS = "-C target-feature=+crt-static"; CPATH = ../libprobe/include; }; @@ -60,6 +54,7 @@ doCheck = false; }; + packages = rec { # Build the top-level crates of the workspace as individual derivations. # This allows consumers to only depend on (and build) only what they need. # Though it is possible to build the entire workspace as a single derivation, @@ -108,6 +103,7 @@ ]; pythonImportsCheck = [pname]; }; + probe-cli = craneLib.buildPackage (individualCrateArgs // { pname = "probe-cli"; @@ -118,17 +114,10 @@ pname = "probe-macros"; cargoExtraArgs = "-p probe_macros"; }); -in { + + }; checks = { - # Build the crates as part of `nix flake check` for convenience - inherit probe-frontend probe-py-generated probe-cli probe-macros; - - # Run clippy (and deny all warnings) on the workspace source, - # again, reusing the dependency artifacts from above. - # - # Note that this is done as a separate derivation so that - # we can block the CI if there are issues here, but not - # prevent downstream consumers from building our crate by itself. + probe-workspace-clippy = craneLib.cargoClippy (commonArgs // { inherit cargoArtifacts; @@ -166,21 +155,4 @@ in { }); }; - packages = { - inherit probe-cli probe-py-generated probe-frontend probe-macros; - }; - - devShells.default = craneLib.devShell { - # Inherit inputs from checks. - checks = self.checks.${system}; - - packages = [ - pkgs.cargo-audit - pkgs.cargo-expand - pkgs.cargo-flamegraph - pkgs.cargo-watch - pkgs.gdb - pkgs.rust-analyzer - ]; - }; } diff --git a/probe_src/frontend/lib/src/transcribe.rs b/probe_src/frontend/lib/src/transcribe.rs index 28247b21..b10ac882 100644 --- a/probe_src/frontend/lib/src/transcribe.rs +++ b/probe_src/frontend/lib/src/transcribe.rs @@ -317,7 +317,12 @@ impl<'a> OpsArena<'a> { .wrap_err("Failed to create ArenaHeader for OpsArena")?; if ((header.used - size_of::()) % size_of::()) != 0 { - return Err(ArenaError::Misaligned { size: header.used }.into()); + return Err(ArenaError::Misaligned { + size: header.used, + header_size: size_of::(), + op_size: size_of::(), + } + .into()); } let count = (header.used - size_of::()) / size_of::(); @@ -424,8 +429,12 @@ pub enum ArenaError { /// Returned if an [`OpsArena`]'s size isn't isn't `HEADER_SIZE + (N * OP_SIZE)` when `N` is /// some integer. - #[error("Arena alignment error: arena size ({size}) minus header isn't a multiple of op size")] - Misaligned { size: usize }, + #[error("Arena alignment error: arena size ({size}) minus header ({header_size}) isn't a multiple of op size ({op_size})")] + Misaligned { + size: usize, + header_size: usize, + op_size: usize, + }, /// Returned if the instantiation in a [`ArenaHeader`] doesn't match the indicated one #[error("Header contained Instantiation ID {header}, but {passed} was indicated")] diff --git a/probe_src/frontend/python/probe_py/generated/ops.py b/probe_src/frontend/python/probe_py/generated/ops.py index 9595a055..caa9b9aa 100644 --- a/probe_src/frontend/python/probe_py/generated/ops.py +++ b/probe_src/frontend/python/probe_py/generated/ops.py @@ -40,6 +40,8 @@ class Statx: dev_major: int dev_minor: int mnt_id: int + dio_mem_align: int + dio_offset_align: int @dataclass(init=True, frozen=True) diff --git a/probe_src/tests/docker_os_matrix.py b/probe_src/tests/docker_os_matrix.py index 0f1f9964..24f9edb4 100644 --- a/probe_src/tests/docker_os_matrix.py +++ b/probe_src/tests/docker_os_matrix.py @@ -1,4 +1,3 @@ -import io import typing import tempfile import sys From a3e00fe9d1a025ad91d264a4bfeabbd3566794cd Mon Sep 17 00:00:00 2001 From: Samuel Grayson Date: Tue, 15 Oct 2024 11:24:54 -0500 Subject: [PATCH 4/9] Fix just tests --- Justfile | 1 + probe_src/tests/A.txt | 1 + probe_src/tests/B.txt | 1 + .../probe_py/manual => tests}/test_probe.py | 50 +++++++------------ 4 files changed, 20 insertions(+), 33 deletions(-) create mode 100644 probe_src/tests/A.txt create mode 100644 probe_src/tests/B.txt rename probe_src/{python/probe_py/manual => tests}/test_probe.py (91%) diff --git a/Justfile b/Justfile index 5e69c148..8adcbe7a 100644 --- a/Justfile +++ b/Justfile @@ -22,6 +22,7 @@ check-clippy: env --chdir probe_src/frontend cargo clippy fix-clippy: + git add -A env --chdir probe_src/frontend cargo clippy --fix --allow-staged check-mypy: diff --git a/probe_src/tests/A.txt b/probe_src/tests/A.txt new file mode 100644 index 00000000..248434cf --- /dev/null +++ b/probe_src/tests/A.txt @@ -0,0 +1 @@ +This is A.txt \ No newline at end of file diff --git a/probe_src/tests/B.txt b/probe_src/tests/B.txt new file mode 100644 index 00000000..248434cf --- /dev/null +++ b/probe_src/tests/B.txt @@ -0,0 +1 @@ +This is A.txt \ No newline at end of file diff --git a/probe_src/python/probe_py/manual/test_probe.py b/probe_src/tests/test_probe.py similarity index 91% rename from probe_src/python/probe_py/manual/test_probe.py rename to probe_src/tests/test_probe.py index d751bf50..bf1aa8c5 100644 --- a/probe_src/python/probe_py/manual/test_probe.py +++ b/probe_src/tests/test_probe.py @@ -1,9 +1,9 @@ +import pytest import typing from probe_py.generated.parser import ProvLog, parse_probe_log from probe_py.generated.ops import OpenOp, CloneOp, ExecOp, InitProcessOp, InitExecEpochOp, CloseOp, WaitOp, Op -from probe_py.manual.analysis import FileNode, ProcessNode, InodeOnDevice +from probe_py.manual.analysis import FileNode, ProcessNode, InodeOnDevice, provlog_to_digraph, validate_hb_graph from probe_py.manual.workflows import NextflowGenerator -from . import analysis import pathlib import networkx as nx # type: ignore import subprocess @@ -15,15 +15,15 @@ REMAKE_LIBPROBE = False -project_root = pathlib.Path(__file__).resolve().parent.parent.parent.parent.parent +project_root = pathlib.Path(__file__).resolve().parent.parent.parent def test_diff_cmd() -> None: paths = [str(project_root / "flake.nix"), str(project_root / "flake.lock")] command = ['diff', *paths] process_tree_prov_log = execute_command(command, 1) - process_graph = analysis.provlog_to_digraph(process_tree_prov_log) - assert not analysis.validate_hb_graph(process_tree_prov_log, process_graph) + process_graph = provlog_to_digraph(process_tree_prov_log) + assert not validate_hb_graph(process_tree_prov_log, process_graph) path_bytes = [path.encode() for path in paths] dfs_edges = list(nx.dfs_edges(process_graph)) match_open_and_close_fd(dfs_edges, process_tree_prov_log, path_bytes) @@ -32,8 +32,8 @@ def test_diff_cmd() -> None: def test_bash_in_bash() -> None: command = ["bash", "-c", f"head {project_root}/flake.nix ; head {project_root}/flake.lock"] process_tree_prov_log = execute_command(command) - process_graph = analysis.provlog_to_digraph(process_tree_prov_log) - assert not analysis.validate_hb_graph(process_tree_prov_log, process_graph) + process_graph = provlog_to_digraph(process_tree_prov_log) + assert not validate_hb_graph(process_tree_prov_log, process_graph) paths = [f'{project_root}/flake.nix'.encode(), f'{project_root}/flake.lock'.encode()] process_file_map = {} start_node = [node for node, degree in process_graph.in_degree() if degree == 0][0] @@ -46,8 +46,8 @@ def test_bash_in_bash() -> None: def test_bash_in_bash_pipe() -> None: command = ["bash", "-c", f"head {project_root}/flake.nix | tail"] process_tree_prov_log = execute_command(command) - process_graph = analysis.provlog_to_digraph(process_tree_prov_log) - assert not analysis.validate_hb_graph(process_tree_prov_log, process_graph) + process_graph = provlog_to_digraph(process_tree_prov_log) + assert not validate_hb_graph(process_tree_prov_log, process_graph) paths = [f'{project_root}/flake.nix'.encode(), b'stdout'] start_node = [node for node, degree in process_graph.in_degree() if degree == 0][0] dfs_edges = list(nx.dfs_edges(process_graph,source=start_node)) @@ -56,8 +56,8 @@ def test_bash_in_bash_pipe() -> None: def test_pthreads() -> None: process_tree_prov_log = execute_command([f"{project_root}/probe_src/tests/c/createFile.exe"]) - process_graph = analysis.provlog_to_digraph(process_tree_prov_log) - assert not analysis.validate_hb_graph(process_tree_prov_log, process_graph) + process_graph = provlog_to_digraph(process_tree_prov_log) + assert not validate_hb_graph(process_tree_prov_log, process_graph) root_node = [n for n in process_graph.nodes() if process_graph.out_degree(n) > 0 and process_graph.in_degree(n) == 0][0] bfs_nodes = [node for layer in nx.bfs_layers(process_graph, root_node) for node in layer] root_node = [n for n in process_graph.nodes() if process_graph.out_degree(n) > 0 and process_graph.in_degree(n) == 0][0] @@ -282,29 +282,13 @@ def get_op_from_provlog( return process_tree_prov_log.processes[pid].exec_epochs[exec_epoch_id].threads[tid].ops[op_idx] +@pytest.mark.xfail def test_dataflow_graph_to_nextflow_script() -> None: - #current_path = 'probe_src/python/probe_py/manual/test_probe.py' + a_file_path = project_root / "probe_src" / "tests" / "A.txt" + b_file_path = project_root / "probe_src" / "tests" / "B.txt" - # Get the directory containing the script - script_dir = os.path.dirname(os.path.realpath(__file__)) - - # Get the path to the folder before 'probe_src' - parent_of_probe_src = os.path.join(os.path.dirname(script_dir), "..", "..", "..") - - # Resolve the absolute path to the folder before 'probe_src' - parent_of_probe_src = os.path.abspath(parent_of_probe_src) - - # Define the file paths - a_file_path = os.path.join(parent_of_probe_src, "A.txt") - b_file_path = os.path.join(parent_of_probe_src, "B.txt") - - # Create and write to A.txt - with open(a_file_path, 'w') as a_file: - a_file.write("This is A.txt") - - # Create and write to B.txt - with open(b_file_path, 'w') as b_file: - b_file.write("This is B.txt") + a_file_path.write_text("This is A.txt") + b_file_path.write_text("This is A.txt") dataflow_graph = nx.DiGraph() A = FileNode(InodeOnDevice(0,0,0), 0, "A.txt") @@ -437,4 +421,4 @@ def test_dataflow_graph_to_nextflow_script() -> None: assert script == expected_script os.remove(a_file_path) - os.remove(b_file_path) \ No newline at end of file + os.remove(b_file_path) From a3fa41ea21c12fb625bbddcfbd4a9c0045eea65a Mon Sep 17 00:00:00 2001 From: Samuel Grayson Date: Tue, 15 Oct 2024 11:27:56 -0500 Subject: [PATCH 5/9] Fix GitHub CI --- .github/workflows/ci.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0d947f0..687e7a50 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,10 +33,5 @@ jobs: name: charmonium signingKey: ${{ secrets.CACHIX_SIGNING_KEY }} - - name: Build devshell - # I think we need to "build" the devshell so it gets cached by Cachix - # It has to be built anyway, to actually run - run: nix build .#devshell - - name: Run Just on-push stuff in development shell run: nix develop --command just on-push From 6724c556014d0acd9b2b677eb1967c4675fcc465 Mon Sep 17 00:00:00 2001 From: Samuel Grayson Date: Tue, 15 Oct 2024 11:49:35 -0500 Subject: [PATCH 6/9] Fix nix stuff --- Justfile | 4 +- benchmark/flake.nix | 226 +++++++++-------- docs/flake.nix | 422 ++++++++++++++++---------------- docs/lit_review/flake.nix | 20 +- flake.nix | 73 +++--- probe_src/frontend/frontend.nix | 111 ++++----- 6 files changed, 447 insertions(+), 409 deletions(-) diff --git a/Justfile b/Justfile index 8adcbe7a..c998cad7 100644 --- a/Justfile +++ b/Justfile @@ -1,8 +1,8 @@ fix-format-nix: - #alejandra . + alejandra . check-format-nix: - #alejandra --check . # TODO: uncomment + alejandra --check . fix-ruff: #ruff format probe_src # TODO: uncomment diff --git a/benchmark/flake.nix b/benchmark/flake.nix index 9c5b2e10..c8fcef15 100644 --- a/benchmark/flake.nix +++ b/benchmark/flake.nix @@ -3,9 +3,14 @@ # Use newer Nix to apply this bugfix # https://github.com/NixOS/nix/pull/10467 inputs.new-nixos.url = "github:NixOS/nixpkgs"; - outputs = { self, nixpkgs, flake-utils, ... }@inputs: - flake-utils.lib.eachDefaultSystem (system: - let + outputs = { + self, + nixpkgs, + flake-utils, + ... + } @ inputs: + flake-utils.lib.eachDefaultSystem ( + system: let pkgs = nixpkgs.legacyPackages.${system}; python = pkgs.python310.override { packageOverrides = self: super: { @@ -13,16 +18,23 @@ debugpy = noPytest super.debugpy; }; }; - noPytest = pypkg: pypkg.overrideAttrs (self: super: { - pytestCheckPhase = ''true''; - }); - removePackage = drv: pkgsToRemove: drv.override (builtins.listToAttrs (builtins.map (pkgToRemove: {name = pkgToRemove; value = null;}) pkgsToRemove)); - renameInDrv = drv: oldFile: newFile: pkgs.runCommand "${drv.name}-renamed" {} '' - mkdir $out - cp --recursive ${drv}/* $out - chmod +w $out/${oldFile} $(dirname $out/${newFile}) - mv $out/${oldFile} $out/${newFile} - ''; + noPytest = pypkg: + pypkg.overrideAttrs (self: super: { + pytestCheckPhase = ''true''; + }); + removePackage = drv: pkgsToRemove: + drv.override (builtins.listToAttrs (builtins.map (pkgToRemove: { + name = pkgToRemove; + value = null; + }) + pkgsToRemove)); + renameInDrv = drv: oldFile: newFile: + pkgs.runCommand "${drv.name}-renamed" {} '' + mkdir $out + cp --recursive ${drv}/* $out + chmod +w $out/${oldFile} $(dirname $out/${newFile}) + mv $out/${oldFile} $out/${newFile} + ''; in { packages = rec { nix = inputs.new-nixos.legacyPackages.${system}.nix; @@ -65,7 +77,13 @@ pkgs.bash pkgs.coreutils (pkgs.gnutar.overrideAttrs (super: { - patches = (if (super ? patches) then super.patches else []) ++ [ ./tar.patch ]; + patches = + ( + if (super ? patches) + then super.patches + else [] + ) + ++ [./tar.patch]; })) pkgs.gzip pkgs.pigz @@ -202,9 +220,9 @@ rev = "master"; hash = "sha256-HFgqYEHanlwA0FA/7kOSsmcPzcb8BLJ3lG74DV5RtBA="; }; - a="hi"; - patches = [ ./splash-3.diff ]; - nativeBuildInputs = [ pkgs.m4 pkgs.binutils ]; + a = "hi"; + patches = [./splash-3.diff]; + nativeBuildInputs = [pkgs.m4 pkgs.binutils]; sourceRoot = "source/codes"; buildPhase = '' ${pkgs.gnused}/bin/sed --in-place s=inputs/car.geo=$out/inputs/raytrace/car.geo=g apps/raytrace/inputs/car.env @@ -246,7 +264,7 @@ rev = "darshan-${version}"; hash = "sha256-hNuLGKxJjpVogqoXMtUSMIgZlOQyA3nCM1s7ia2Y8kM="; }; - buildInputs = [ pkgs.zlib pkgs.autoconf pkgs.automake pkgs.libtool ]; + buildInputs = [pkgs.zlib pkgs.autoconf pkgs.automake pkgs.libtool]; configurePhase = '' ./prepare.sh cd darshan-runtime/ @@ -269,7 +287,7 @@ version = darshan-runtime.version; src = darshan-runtime.src; buildInputs = darshan-runtime.buildInputs; - propagatedBuildInputs = [ pkgs.perl pkgs.gnuplot pkgs.python3 pkgs.bash ]; + propagatedBuildInputs = [pkgs.perl pkgs.gnuplot pkgs.python3 pkgs.bash]; configurePhase = '' ./prepare.sh cd darshan-util/ @@ -278,35 +296,36 @@ }; spade = ( let - mainSrc = (pkgs.fetchFromGitHub { + mainSrc = pkgs.fetchFromGitHub { owner = "ashish-gehani"; repo = "SPADE"; rev = "master"; hash = "sha256-5Cvx9Z1Jn30wEqP+X+/rPviZZKiEOjRGvd1KJfg5Www="; name = "main"; - }); + }; neo4j = pkgs.fetchurl { url = https://neo4j.com/artifact.php?name=neo4j-community-4.1.1-unix.tar.gz; hash = "sha256-T2Y6UgvsQN/QsZcv6zz5OvMhwjC0SK223JF3F+Z6EnE="; }; jdk = pkgs.jdk11; jre = pkgs.jdk11; - scriptDeps = [ pkgs.ps jre ]; - in pkgs.stdenv.mkDerivation { - pname = "SPADE"; - version = "2.0.0"; - buildInputs = [ jdk pkgs.uthash pkgs.fuse ]; - nativeBuildInputs = [ pkgs.makeWrapper pkgs.pkg-config ]; - patches = [ ./spade.diff ]; - srcs = [ mainSrc neo4j ]; - sourceRoot = mainSrc.name; - postUnpack = "mv neo4j-community-4.1.1 ${mainSrc.name}/lib/"; - preBuild = "patchShebangs --build bin/*"; - postInstall = '' - wrapProgram $out/bin/spade --prefix PATH : ${pkgs.lib.makeBinPath scriptDeps} - ''; - PKG_CONFIG_PATH = "${pkgs.fuse}/lib/pkgconfig"; - } + scriptDeps = [pkgs.ps jre]; + in + pkgs.stdenv.mkDerivation { + pname = "SPADE"; + version = "2.0.0"; + buildInputs = [jdk pkgs.uthash pkgs.fuse]; + nativeBuildInputs = [pkgs.makeWrapper pkgs.pkg-config]; + patches = [./spade.diff]; + srcs = [mainSrc neo4j]; + sourceRoot = mainSrc.name; + postUnpack = "mv neo4j-community-4.1.1 ${mainSrc.name}/lib/"; + preBuild = "patchShebangs --build bin/*"; + postInstall = '' + wrapProgram $out/bin/spade --prefix PATH : ${pkgs.lib.makeBinPath scriptDeps} + ''; + PKG_CONFIG_PATH = "${pkgs.fuse}/lib/pkgconfig"; + } ); benchexec = python.pkgs.buildPythonPackage rec { pname = "BenchExec"; @@ -315,11 +334,11 @@ inherit pname version; sha256 = "e796e8636772825aa7c72aa3aaf0793522e3d0d55eb9220f7706421d4d3f38a9"; }; - propagatedBuildInputs = [ python.pkgs.pyyaml python.pkgs.pystemd python.pkgs.lxml ]; + propagatedBuildInputs = [python.pkgs.pyyaml python.pkgs.pystemd python.pkgs.lxml]; # checkInputs = [ python.pkgs.nose pkgs.busybox python.pkgs.lxml ]; # Check tries to manipulate cgroups and /sys which will not work inside the Nix sandbox doCheck = false; - pythonImportsCheck = [ "benchexec" ]; + pythonImportsCheck = ["benchexec"]; }; charmonium-time-block = python.pkgs.buildPythonPackage rec { pname = "charmonium.time_block"; @@ -330,11 +349,11 @@ inherit version; sha256 = "5cbde16fdfc927393a473297690138c2db169e51cdfff13accbbf6ec44486968"; }; - nativeBuildInputs = [ python.pkgs.poetry-core ]; - propagatedBuildInputs = [ python.pkgs.psutil ]; - checkInputs = [ python.pkgs.pytest ]; - pythonImportsCheck = [ "charmonium.time_block" ]; - nativeCheckInputs = [ python.pkgs.pytestCheckHook ]; + nativeBuildInputs = [python.pkgs.poetry-core]; + propagatedBuildInputs = [python.pkgs.psutil]; + checkInputs = [python.pkgs.pytest]; + pythonImportsCheck = ["charmonium.time_block"]; + nativeCheckInputs = [python.pkgs.pytestCheckHook]; }; rpaths = python.pkgs.buildPythonPackage rec { pname = "rpaths"; @@ -343,7 +362,7 @@ inherit pname version; sha256 = "dd7418b2c837e1b4eb5c5490465d5f282645143e4638c809ddd250dc33395641"; }; - pythonImportsCheck = [ pname ]; + pythonImportsCheck = [pname]; }; distro = python.pkgs.buildPythonPackage rec { pname = "distro"; @@ -353,8 +372,8 @@ inherit pname version; sha256 = "02e111d1dc6a50abb8eed6bf31c3e48ed8b0830d1ea2a1b78c61765c2513fdd8"; }; - buildInputs = [ python.pkgs.setuptools ]; - pythonImportsCheck = [ pname ]; + buildInputs = [python.pkgs.setuptools]; + pythonImportsCheck = [pname]; }; usagestats = python.pkgs.buildPythonPackage rec { pname = "usagestats"; @@ -363,9 +382,9 @@ inherit pname version; sha256 = "d8887aa0f65769b1423b784e626ec6fb6ba6ed1432667e10d6115b783571be6d"; }; - buildInputs = [ python.pkgs.pip ]; - propagatedBuildInputs = [ distro python.pkgs.requests ]; - pythonImportsCheck = [ pname ]; + buildInputs = [python.pkgs.pip]; + propagatedBuildInputs = [distro python.pkgs.requests]; + pythonImportsCheck = [pname]; # Check tries to upload usage statistics to localhost over TCP which will not work in the Nix sandbox doCheck = false; }; @@ -376,8 +395,8 @@ inherit pname version; sha256 = "a98b7f04c52c60072e3c42da21997d3ad41161ff6cb1139e18cda8d3012120f9"; }; - checkInputs = [ python.pkgs.pip ]; - buildInputs = [ pkgs.sqlite ]; + checkInputs = [python.pkgs.pip]; + buildInputs = [pkgs.sqlite]; propagatedBuildInputs = [ rpaths usagestats @@ -386,7 +405,7 @@ pkgs.dpkg python.pkgs.setuptools ]; - pythonImportsCheck = [ pname ]; + pythonImportsCheck = [pname]; }; reprounzip = python.pkgs.buildPythonPackage rec { pname = "reprounzip"; @@ -395,9 +414,9 @@ inherit pname version; sha256 = "3f0b6b4dcde9dbcde9d283dfdf154c223b3972d5aff41a1b049224468bba3496"; }; - checkInputs = [ python.pkgs.pip ]; - propagatedBuildInputs = [ python.pkgs.pyyaml rpaths usagestats python.pkgs.requests distro python.pkgs.pyelftools ]; - pythonImportsCheck = [ pname ]; + checkInputs = [python.pkgs.pip]; + propagatedBuildInputs = [python.pkgs.pyyaml rpaths usagestats python.pkgs.requests distro python.pkgs.pyelftools]; + pythonImportsCheck = [pname]; }; reprounzip-docker = python.pkgs.buildPythonPackage rec { pname = "reprounzip-docker"; @@ -406,10 +425,10 @@ inherit pname version; sha256 = "ccde16c7502072693afd7ab9d8b58f478e575efe3806ec4951659869a571fa2f"; }; - checkInputs = [ python.pkgs.pip ]; + checkInputs = [python.pkgs.pip]; doCheck = false; - propagatedBuildInputs = [ rpaths reprounzip ]; - pythonImportsCheck = [ "reprounzip.unpackers.docker" ]; + propagatedBuildInputs = [rpaths reprounzip]; + pythonImportsCheck = ["reprounzip.unpackers.docker"]; }; provenance-to-use = pkgs.stdenv.mkDerivation rec { pname = "provenance-to-use"; @@ -424,13 +443,13 @@ "-DBUILD_TESTING=OFF" "-DCMAKE_BUILD_TYPE=Release" ]; - patches = [ ./provenance-to-use.patch ]; - nativeBuildInputs = [ pkgs.cmake pkgs.makeWrapper ]; - buildInputs = [ pkgs.coreutils ]; + patches = [./provenance-to-use.patch]; + nativeBuildInputs = [pkgs.cmake pkgs.makeWrapper]; + buildInputs = [pkgs.coreutils]; installPhase = '' install -d $out/bin install -t $out/bin ptu - wrapProgram $out/bin/ptu --prefix PATH : ${pkgs.lib.strings.makeBinPath [ pkgs.coreutils ]} + wrapProgram $out/bin/ptu --prefix PATH : ${pkgs.lib.strings.makeBinPath [pkgs.coreutils]} ''; }; sciunit-dedup = pkgs.stdenv.mkDerivation rec { @@ -443,7 +462,7 @@ rev = "7400941338892fef17791dd6dc3465cd280d99b2"; hash = "sha256-eRtaYjIJHZi/ZEXj7Jd1g7kzDvafxWQzV45okoQmRik="; }; - nativeBuildInputs = [ pkgs.cmake ]; + nativeBuildInputs = [pkgs.cmake]; patches = [ ./sciunit-dedup.patch # https://github.com/depaul-dice/sciunit/blob/4c8011ddbf4f8ca7da6b987572d6de56d70661dc/CMakeLists.txt @@ -462,7 +481,7 @@ rev = "master"; hash = "sha256-Z80106btm0MKf2IUuolJK5kJG0FCWBi3zBu0AN9eNRI="; }; - nativeBuildInputs = [ pkgs.cmake ]; + nativeBuildInputs = [pkgs.cmake]; installPhase = '' install -d $out/bin install -t $out/bin scripter @@ -475,7 +494,7 @@ inherit pname version; sha256 = "4d4631f6062e658e9007ab3149a9b914f3548cb38bfb021c64f39a025ce578ae"; }; - pythonImportsCheck = [ pname ]; + pythonImportsCheck = [pname]; }; utcdatetime = python.pkgs.buildPythonPackage rec { pname = "utcdatetime"; @@ -484,14 +503,14 @@ inherit pname version; sha256 = "806d96da79fd129efade31e8e917a19ea602b047e5b6c3db12c0d69828a779f4"; }; - pythonImportsCheck = [ pname ]; + pythonImportsCheck = [pname]; nativeCheckInputs = [ python.pkgs.nose - (python.pkgs.strict-rfc3339.overrideAttrs (_: { doCheck = false; })) + (python.pkgs.strict-rfc3339.overrideAttrs (_: {doCheck = false;})) python.pkgs.freezegun python.pkgs.pytz ]; - patches = [ ./utcdatetime.patch ]; + patches = [./utcdatetime.patch]; }; hs_restclient = python.pkgs.buildPythonPackage rec { pname = "hs_restclient"; @@ -506,12 +525,12 @@ python.pkgs.oauthlib python.pkgs.requests_oauthlib ]; - pythonImportsCheck = [ pname ]; + pythonImportsCheck = [pname]; }; sciunit2 = python.pkgs.buildPythonApplication rec { pname = "sciunit2"; version = "0.4.post82.dev130189670"; - patches = [ ./sciunit2.patch ]; + patches = [./sciunit2.patch]; src = pkgs.fetchPypi { inherit pname version; sha256 = "a1ab36634ab7a1abe46f478b90643eb128ace56f85bda007dfe95525392fc876"; @@ -523,9 +542,9 @@ rm sciunit2-*/sciunit2/libexec/{ptu,scripter,vv} ''; postFixup = '' - wrapProgram $out/bin/sciunit --prefix PATH : ${(pkgs.lib.strings.makeBinPath [ pkgs.gnutar ])} + wrapProgram $out/bin/sciunit --prefix PATH : ${(pkgs.lib.strings.makeBinPath [pkgs.gnutar])} ''; - pythonImportsCheck = [ pname ]; + pythonImportsCheck = [pname]; propagatedBuildInputs = [ # https://github.com/depaul-dice/sciunit/blob/4c8011ddbf4f8ca7da6b987572d6de56d70661dc/CMakeLists.txt provenance-to-use @@ -544,7 +563,7 @@ hs_restclient pkgs.gnutar ]; - nativeBuildInputs = [ python.pkgs.pip pkgs.makeWrapper ]; + nativeBuildInputs = [python.pkgs.pip pkgs.makeWrapper]; nativeCheckInputs = [ python.pkgs.nose python.pkgs.nose-exclude @@ -580,19 +599,23 @@ # So I will do that manually here. # [1]: https://github.com/ipython-contrib/jupyter_contrib_nbextensions/issues/1647 # [2]: https://github.com/NixOS/nixpkgs/commit/ba873b2be6252a5144c9f37fae1341973ac155ae - meta = { broken = false; }; - patches = (({ patches = []; } // super).patches) ++ [ - (pkgs.fetchpatch { - name = "notebook-v7-compat.patch"; - url = "https://github.com/ipython-contrib/jupyter_contrib_nbextensions/commit/181e5f38f8c7e70a2e54a692f49564997f21a231.patch"; - hash = "sha256-WrC9npEUAk3Hou8Tp8kK+Nw+H0bEEjR3GIoUTxrZxak="; - }) - ]; + meta = {broken = false;}; + patches = + (({patches = [];} // super).patches) + ++ [ + (pkgs.fetchpatch { + name = "notebook-v7-compat.patch"; + url = "https://github.com/ipython-contrib/jupyter_contrib_nbextensions/commit/181e5f38f8c7e70a2e54a692f49564997f21a231.patch"; + hash = "sha256-WrC9npEUAk3Hou8Tp8kK+Nw+H0bEEjR3GIoUTxrZxak="; + }) + ]; }); pcre2-dev = pkgs.pcre2.dev.overrideAttrs (super: { - postFixup = super.postFixup + '' - ${pkgs.gnused}/bin/sed --in-place s=/bin/sh=${pkgs.bash}/bin/bash=g $dev/bin/pcre2-config - ''; + postFixup = + super.postFixup + + '' + ${pkgs.gnused}/bin/sed --in-place s=/bin/sh=${pkgs.bash}/bin/bash=g $dev/bin/pcre2-config + ''; }); pyTimecard = python.pkgs.buildPythonPackage rec { pname = "Timecard"; @@ -645,8 +668,8 @@ cp --recursive proftpd-mod_vroot proftpd/contrib/mod_vroot cd proftpd ''; - buildInputs = [ pkgs.libxcrypt ]; - configureFlags = [ "--with-modules=mod_vroot" ]; + buildInputs = [pkgs.libxcrypt]; + configureFlags = ["--with-modules=mod_vroot"]; installPhase = '' install --directory $out/bin install --target-directory $out/bin proftpd ftpcount ftpdctl ftpscrub ftpshut ftptop ftpwho contrib/ftpasswd contrib/ftpquota contrib/ftpmail @@ -662,8 +685,8 @@ hash = "sha256-kg9pxlPl7nU3ayUEmmimrgHg1uVd2mMB2Fo8fW65TiQ="; }; # buildInputs = [ pkgs.glib.dev pkgs.gnulib.out ]; - nativeBuildInputs = [ pkgs.autoconf pkgs.automake pkgs.glib.dev pkgs.gnulib.out pkgs.pkg-config pkgs.m4 pkgs.libtool pkgs.texinfo ]; - buildInputs = [ pkgs.libssh ]; + nativeBuildInputs = [pkgs.autoconf pkgs.automake pkgs.glib.dev pkgs.gnulib.out pkgs.pkg-config pkgs.m4 pkgs.libtool pkgs.texinfo]; + buildInputs = [pkgs.libssh]; configurePhase = '' glib-gettextize -f -c @@ -688,7 +711,7 @@ name = "lmbench"; }; sourceRoot = "lmbench"; - buildInputs = [ pkgs.libtirpc.dev pkgs.coreutils pkgs.findutils ]; + buildInputs = [pkgs.libtirpc.dev pkgs.coreutils pkgs.findutils]; patchPhase = '' sed -i 's=/bin/rm=rm=g' src/Makefile Makefile sed -i 's/CFLAGS=-O/CFLAGS="$(CFLAGS)"/g' src/Makefile @@ -726,10 +749,10 @@ ''; }); ltrace = pkgs.ltrace.overrideAttrs (super: { - patches = super.patches ++ [ ./ltrace.patch ]; + patches = super.patches ++ [./ltrace.patch]; }); cde = pkgs.cde.overrideAttrs (super: { - patches = [ ./cde.patch ]; + patches = [./cde.patch]; }); care = pkgs.stdenv.mkDerivation rec { pname = "care"; @@ -746,17 +769,17 @@ # our cross machinery defines $CC and co just right sed -i /CROSS_COMPILE/d src/GNUmakefile ''; - buildInputs = [ pkgs.ncurses pkgs.talloc pkgs.uthash pkgs.libarchive ]; - nativeBuildInputs = [ pkgs.pkg-config pkgs.docutils pkgs.makeWrapper ]; - makeFlags = [ "-C src" "care"]; + buildInputs = [pkgs.ncurses pkgs.talloc pkgs.uthash pkgs.libarchive]; + nativeBuildInputs = [pkgs.pkg-config pkgs.docutils pkgs.makeWrapper]; + makeFlags = ["-C src" "care"]; postBuild = '' make -C doc care/man.1 ''; - installFlags = [ "PREFIX=${placeholder "out"}" ]; + installFlags = ["PREFIX=${placeholder "out"}"]; installTargets = "install-care"; postInstall = '' install -Dm644 doc/care/man.1 $out/share/man/man1/care.1 - wrapProgram $out/bin/care --prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.lzop ]} + wrapProgram $out/bin/care --prefix PATH : ${pkgs.lib.makeBinPath [pkgs.lzop]} ''; # proot provides tests with `make -C test` however they do not run in the sandbox doCheck = false; @@ -766,9 +789,9 @@ libseccomp = pkgs.libseccomp.lib; env-image = pkgs.dockerTools.buildImage { name = "prov-tracer-benchmark-env"; - copyToRoot = [ env ]; + copyToRoot = [env]; config = { - Cmd = [ "${env}/bin/bash" ]; + Cmd = ["${env}/bin/bash"]; }; }; env = pkgs.symlinkJoin { @@ -809,10 +832,8 @@ }; }; } - ) - ; + ); } - /* (progn (remhash 'pyls lsp-clients) @@ -835,3 +856,4 @@ (ein:jupyter-server-stop) */ + diff --git a/docs/flake.nix b/docs/flake.nix index 41942f0f..f60ebbf7 100644 --- a/docs/flake.nix +++ b/docs/flake.nix @@ -10,212 +10,222 @@ url = "github:charmoniumQ/nix-documents"; }; }; - outputs = { self, nixpkgs, flake-utils, nix-utils, nix-documents }: + outputs = { + self, + nixpkgs, + flake-utils, + nix-utils, + nix-documents, + }: flake-utils.lib.eachDefaultSystem - (system: - let - pkgs = nixpkgs.legacyPackages.${system}; - nix-lib = nixpkgs.lib; - nix-utils-lib = nix-utils.lib.${system}; - nix-documents-lib = nix-documents.lib.${system}; - svg2pdf = dstName: srcName: pkgs.runCommand dstName {} "${pkgs.librsvg}/bin/rsvg-convert --output=$out --format=pdf ${srcName}"; - texlivePackages = { - inherit (pkgs.texlive) - # See sec 2.1 here https://ctan.math.illinois.edu/macros/latex/contrib/acmart/acmguide.pdf - # Also see \usepackage's in acm-template.tex - acmart - amscls - amsfonts - amsmath - babel - bibcop - biblatex - biblatex-trad - kastrup # \usepackage{binhex} - bookmark - booktabs - caption - catchfile - cleveref - cm-super - cmap - collection-luatex - comment - doclicense - draftwatermark - enumitem - environ - etoolbox - fancyhdr - fancyvrb - float - fontaxes - fontspec - geometry - graphics - hyperref - hyperxmp - ifmtarg - iftex - inconsolata - lacheck - latexmk - libertine - mdwtools - microtype - mmap - ms - mweights - nag - natbib - ncctools # \usepackage{manyfoot,nccfoots} - newtx - oberdiek - parskip - pbalance - physics - # pdftex-def - preprint - printlen - refcount - scheme-small - selnolig - setspace - soul - subfig - supertabular - svg - textcase - tools - totpages - transparent - trimspaces - ulem - upquote - xcolor - xkeyval - xstring - xurl - zref - ; - }; - in - { - packages = { - test = (pkgs.texlive.combine texlivePackages); - default = self.packages."${system}".acm-rep; - acm-rep = nix-utils-lib.mergeDerivations { - packageSet = nix-utils-lib.packageSetRec - (self: [ - (pkgs.stdenvNoCC.mkDerivation rec { - src = nix-utils-lib.mergeDerivations { - packageSet = { - "." = ./benchmark_suite; - "zotero.bib" = ./zotero.bib; - "reed.bib" = ./reed.bib; - "supplemental.bib" = ./supplemental.bib; - "acm-template.tex" = ./acm-template.tex; - "citations-to-latex.lua" = ./citations-to-latex.lua; - } - // nix-utils-lib.packageSet [ - self."app-lvl-prov.pdf" - self."wf-lvl-prov.pdf" - self."sys-lvl-prov.pdf" - self."sys-lvl-log.pdf" - self."prov-example.pdf" - ]; - }; - mainSrc = "README.md"; - latexStem = "main"; - latexTemplate = "acm-template.tex"; - name = "benchmark_suite"; - date = 1707292740; - latexmkFlagForEngine = "-pdf"; - pandocFlagForEngine = "latexmk"; # pdfLaTeX vs LuaLaTeX vs XeLaTeX - FONTCONFIG_FILE = pkgs.makeFontsConf { fontDirectories = [ ]; }; - buildInputs = [ - (pkgs.texlive.combine texlivePackages) - pkgs.pandoc + (system: let + pkgs = nixpkgs.legacyPackages.${system}; + nix-lib = nixpkgs.lib; + nix-utils-lib = nix-utils.lib.${system}; + nix-documents-lib = nix-documents.lib.${system}; + svg2pdf = dstName: srcName: pkgs.runCommand dstName {} "${pkgs.librsvg}/bin/rsvg-convert --output=$out --format=pdf ${srcName}"; + texlivePackages = { + inherit + (pkgs.texlive) + # See sec 2.1 here https://ctan.math.illinois.edu/macros/latex/contrib/acmart/acmguide.pdf + + # Also see \usepackage's in acm-template.tex + + acmart + amscls + amsfonts + amsmath + babel + bibcop + biblatex + biblatex-trad + kastrup # \usepackage{binhex} + bookmark + booktabs + caption + catchfile + cleveref + cm-super + cmap + collection-luatex + comment + doclicense + draftwatermark + enumitem + environ + etoolbox + fancyhdr + fancyvrb + float + fontaxes + fontspec + geometry + graphics + hyperref + hyperxmp + ifmtarg + iftex + inconsolata + lacheck + latexmk + libertine + mdwtools + microtype + mmap + ms + mweights + nag + natbib + ncctools # \usepackage{manyfoot,nccfoots} + newtx + oberdiek + parskip + pbalance + physics + # pdftex-def + + preprint + printlen + refcount + scheme-small + selnolig + setspace + soul + subfig + supertabular + svg + textcase + tools + totpages + transparent + trimspaces + ulem + upquote + xcolor + xkeyval + xstring + xurl + zref + ; + }; + in { + packages = { + test = pkgs.texlive.combine texlivePackages; + default = self.packages."${system}".acm-rep; + acm-rep = nix-utils-lib.mergeDerivations { + packageSet = + nix-utils-lib.packageSetRec + (self: [ + (pkgs.stdenvNoCC.mkDerivation rec { + src = nix-utils-lib.mergeDerivations { + packageSet = + { + "." = ./benchmark_suite; + "zotero.bib" = ./zotero.bib; + "reed.bib" = ./reed.bib; + "supplemental.bib" = ./supplemental.bib; + "acm-template.tex" = ./acm-template.tex; + "citations-to-latex.lua" = ./citations-to-latex.lua; + } + // nix-utils-lib.packageSet [ + self."app-lvl-prov.pdf" + self."wf-lvl-prov.pdf" + self."sys-lvl-prov.pdf" + self."sys-lvl-log.pdf" + self."prov-example.pdf" ]; - buildPhase = '' - tmp=$(mktemp --directory) - HOME=$(mktemp --directory) - export SOURCE_DATE_EPOCH=${builtins.toString date} - ${pkgs.pandoc}/bin/pandoc \ - --output=${latexStem}-plain.tex \ - --lua-filter=citations-to-latex.lua \ - --pdf-engine=${pandocFlagForEngine} \ - --template=${latexTemplate} \ - --metadata-file=<(echo {"styles": {"removed": "removed", "added": "default", "only-in-new": "default", "only-in-old": "removed", "only-in-trans": "removed"}}) \ - ${mainSrc} - ${pkgs.pandoc}/bin/pandoc \ - --output=${latexStem}.tex \ - --lua-filter=citations-to-latex.lua \ - --pdf-engine=${pandocFlagForEngine} \ - --template=${latexTemplate} \ - --metadata-file=<(echo {"styles": {"removed": "red", "added": "green", "only-in-new": "default", "only-in-old": "removed", "only-in-trans": "default"}}) \ - ${mainSrc} - # lacheck ${latexStem}.tex - set +e - latexmk ${latexmkFlagForEngine} -shell-escape -emulate-aux-dir -auxdir=$tmp -Werror ${latexStem} - ls -ahlt - latexmk ${latexmkFlagForEngine} -shell-escape -emulate-aux-dir -auxdir=$tmp -Werror ${latexStem}-plain - ls -ahlt - latexmk_status=$? - set -e - ${pkgs.pdftk}/bin/pdftk ${latexStem}.pdf ${latexStem}-plain.pdf cat output ${latexStem}-full.pdf - mkdir $out/ - cp *.{svg,pdf,bbl,tex,docx} $out/ - set -x - archive=acmrep24-11 - mkdir $archive - mkdir $archive/pdf $archive/Source - cp main.pdf $archive/pdf/main.pdf - cp *.{pdf,svg,bbl,bib,tex} $archive/Source/ - cp --recursive generated $archive/Source - # Remove specific files that TAPS doesn't like - rm $archive/Source/{main*.pdf,README.pdf,acm-template.tex,main.tex} - env --chdir $archive ${pkgs.zip}/bin/zip -r $out/$archive.zip ./ - if [ $latexmk_status -ne 0 ]; then - cp $tmp/${latexStem}.log $out - echo "Aborting: Latexmk failed" - cat $tmp/${latexStem}.log - # exit $latexmk_status - fi - ''; - phases = [ "unpackPhase" "buildPhase" ]; - }) - (nix-documents-lib.graphvizFigure { - src = ./benchmark_suite; - main = "app-lvl-prov.dot"; - name = "app-lvl-prov.pdf"; - outputFormat = "pdf"; - layoutEngine = "dot"; - }) - (nix-documents-lib.graphvizFigure { - src = ./benchmark_suite; - main = "wf-lvl-prov.dot"; - name = "wf-lvl-prov.pdf"; - outputFormat = "pdf"; - layoutEngine = "dot"; - }) - (nix-documents-lib.graphvizFigure { - src = ./benchmark_suite; - main = "sys-lvl-prov.dot"; - name = "sys-lvl-prov.pdf"; - outputFormat = "pdf"; - layoutEngine = "dot"; - }) - (nix-documents-lib.graphvizFigure { - src = ./benchmark_suite; - main = "prov-example.dot"; - name = "prov-example.pdf"; - outputFormat = "pdf"; - layoutEngine = "dot"; - }) - (svg2pdf "sys-lvl-log.pdf" ./benchmark_suite/sys-lvl-log.svg) - ]); - }; - }; - }); + }; + mainSrc = "README.md"; + latexStem = "main"; + latexTemplate = "acm-template.tex"; + name = "benchmark_suite"; + date = 1707292740; + latexmkFlagForEngine = "-pdf"; + pandocFlagForEngine = "latexmk"; # pdfLaTeX vs LuaLaTeX vs XeLaTeX + FONTCONFIG_FILE = pkgs.makeFontsConf {fontDirectories = [];}; + buildInputs = [ + (pkgs.texlive.combine texlivePackages) + pkgs.pandoc + ]; + buildPhase = '' + tmp=$(mktemp --directory) + HOME=$(mktemp --directory) + export SOURCE_DATE_EPOCH=${builtins.toString date} + ${pkgs.pandoc}/bin/pandoc \ + --output=${latexStem}-plain.tex \ + --lua-filter=citations-to-latex.lua \ + --pdf-engine=${pandocFlagForEngine} \ + --template=${latexTemplate} \ + --metadata-file=<(echo {"styles": {"removed": "removed", "added": "default", "only-in-new": "default", "only-in-old": "removed", "only-in-trans": "removed"}}) \ + ${mainSrc} + ${pkgs.pandoc}/bin/pandoc \ + --output=${latexStem}.tex \ + --lua-filter=citations-to-latex.lua \ + --pdf-engine=${pandocFlagForEngine} \ + --template=${latexTemplate} \ + --metadata-file=<(echo {"styles": {"removed": "red", "added": "green", "only-in-new": "default", "only-in-old": "removed", "only-in-trans": "default"}}) \ + ${mainSrc} + # lacheck ${latexStem}.tex + set +e + latexmk ${latexmkFlagForEngine} -shell-escape -emulate-aux-dir -auxdir=$tmp -Werror ${latexStem} + ls -ahlt + latexmk ${latexmkFlagForEngine} -shell-escape -emulate-aux-dir -auxdir=$tmp -Werror ${latexStem}-plain + ls -ahlt + latexmk_status=$? + set -e + ${pkgs.pdftk}/bin/pdftk ${latexStem}.pdf ${latexStem}-plain.pdf cat output ${latexStem}-full.pdf + mkdir $out/ + cp *.{svg,pdf,bbl,tex,docx} $out/ + set -x + archive=acmrep24-11 + mkdir $archive + mkdir $archive/pdf $archive/Source + cp main.pdf $archive/pdf/main.pdf + cp *.{pdf,svg,bbl,bib,tex} $archive/Source/ + cp --recursive generated $archive/Source + # Remove specific files that TAPS doesn't like + rm $archive/Source/{main*.pdf,README.pdf,acm-template.tex,main.tex} + env --chdir $archive ${pkgs.zip}/bin/zip -r $out/$archive.zip ./ + if [ $latexmk_status -ne 0 ]; then + cp $tmp/${latexStem}.log $out + echo "Aborting: Latexmk failed" + cat $tmp/${latexStem}.log + # exit $latexmk_status + fi + ''; + phases = ["unpackPhase" "buildPhase"]; + }) + (nix-documents-lib.graphvizFigure { + src = ./benchmark_suite; + main = "app-lvl-prov.dot"; + name = "app-lvl-prov.pdf"; + outputFormat = "pdf"; + layoutEngine = "dot"; + }) + (nix-documents-lib.graphvizFigure { + src = ./benchmark_suite; + main = "wf-lvl-prov.dot"; + name = "wf-lvl-prov.pdf"; + outputFormat = "pdf"; + layoutEngine = "dot"; + }) + (nix-documents-lib.graphvizFigure { + src = ./benchmark_suite; + main = "sys-lvl-prov.dot"; + name = "sys-lvl-prov.pdf"; + outputFormat = "pdf"; + layoutEngine = "dot"; + }) + (nix-documents-lib.graphvizFigure { + src = ./benchmark_suite; + main = "prov-example.dot"; + name = "prov-example.pdf"; + outputFormat = "pdf"; + layoutEngine = "dot"; + }) + (svg2pdf "sys-lvl-log.pdf" ./benchmark_suite/sys-lvl-log.svg) + ]); + }; + }; + }); } diff --git a/docs/lit_review/flake.nix b/docs/lit_review/flake.nix index 153dd3ff..86ddc25d 100644 --- a/docs/lit_review/flake.nix +++ b/docs/lit_review/flake.nix @@ -6,12 +6,17 @@ inputs.nix-documents.inputs.nixpkgs.follows = "nixpkgs"; inputs.nix-utils.url = "github:charmoniumQ/nix-utils"; inputs.nix-documents.inputs.nix-utils.follows = "nix-utils"; - outputs = { self, nixpkgs, flake-utils, nix-documents, nix-utils }: - flake-utils.lib.eachDefaultSystem (system: - let + outputs = { + self, + nixpkgs, + flake-utils, + nix-documents, + nix-utils, + }: + flake-utils.lib.eachDefaultSystem ( + system: let pkgs = nixpkgs.legacyPackages.${system}; - in - { + in { packages = rec { application-level = nix-documents.lib.${system}.graphvizFigure { src = nix-utils.lib.${system}.mergeDerivations { @@ -50,14 +55,15 @@ }; }; texlivePackages = { - inherit (pkgs.texlive) + inherit + (pkgs.texlive) geometry hyperref cleveref booktabs graphics caption - ; + ; }; }; all-figs = nix-utils.lib.${system}.mergeDerivations { diff --git a/flake.nix b/flake.nix index b222657a..92006ca8 100644 --- a/flake.nix +++ b/flake.nix @@ -44,8 +44,9 @@ }; in flake-utils.lib.eachSystem - (builtins.attrNames supported-systems) - (system: let + (builtins.attrNames supported-systems) + ( + system: let pkgs = import nixpkgs { inherit system; overlays = [(import rust-overlay)]; @@ -66,36 +67,37 @@ craneLib lib advisory-db - ; + ; }; in rec { packages = rec { - libprobe = pkgs.stdenv.mkDerivation rec { - pname = "libprobe"; - version = "0.1.0"; - src = ./probe_src/libprobe; - makeFlags = ["INSTALL_PREFIX=$(out)" "SOURCE_VERSION=${version}"]; - buildInputs = [ - (pkgs.python312.withPackages (pypkgs: [ - pypkgs.pycparser - ])) - ]; - }; - probe-bundled = pkgs.stdenv.mkDerivation rec { - pname = "probe-bundled"; - version = "0.1.0"; - dontUnpack = true; - dontBuild = true; - nativeBuildInputs = [pkgs.makeWrapper]; - installPhase = '' - mkdir $out $out/bin - makeWrapper \ - ${frontend.packages.probe-cli}/bin/probe \ - $out/bin/probe \ - --set __PROBE_LIB ${libprobe}/lib \ - --prefix PATH : ${probe-py}/bin - ''; - }; + libprobe = pkgs.stdenv.mkDerivation rec { + pname = "libprobe"; + version = "0.1.0"; + src = ./probe_src/libprobe; + makeFlags = ["INSTALL_PREFIX=$(out)" "SOURCE_VERSION=${version}"]; + buildInputs = [ + (pkgs.python312.withPackages (pypkgs: [ + pypkgs.pycparser + ])) + ]; + }; + probe-bundled = pkgs.stdenv.mkDerivation rec { + pname = "probe-bundled"; + version = "0.1.0"; + dontUnpack = true; + dontBuild = true; + nativeBuildInputs = [pkgs.makeWrapper]; + installPhase = '' + mkdir $out $out/bin + makeWrapper \ + ${frontend.packages.probe-cli}/bin/probe \ + $out/bin/probe \ + --set __PROBE_LIB ${libprobe}/lib \ + --prefix PATH : ${probe-py}/bin + ''; + }; + probe-py = let probe-py-manual = python.pkgs.buildPythonPackage rec { pname = "probe_py.manual"; version = "0.1.0"; @@ -114,18 +116,20 @@ ]; pythonImportsCheck = [pname]; }; - probe-py = python.withPackages (pypkgs: [frontend.packages.probe-py-manual]); - default = probe-bundled; + in + python.withPackages (pypkgs: [probe-py-manual]); + default = probe-bundled; }; checks = { - inherit (frontend.checks) + inherit + (frontend.checks) probe-workspace-clippy probe-workspace-doc probe-workspace-fmt probe-workspace-audit probe-workspace-deny probe-workspace-nextest - ; + ; # The python import checks are so fast, we will incorporate those tests into the package. # TODO: Add integration PROBE tests (already have in pytest). }; @@ -141,7 +145,8 @@ frontend.packages.probe-cli frontend.packages.probe-macros ]; - packages = [ + packages = + [ pkgs.cargo-audit pkgs.cargo-expand pkgs.cargo-flamegraph diff --git a/probe_src/frontend/frontend.nix b/probe_src/frontend/frontend.nix index 18abc8b0..88029136 100644 --- a/probe_src/frontend/frontend.nix +++ b/probe_src/frontend/frontend.nix @@ -7,7 +7,6 @@ python, lib, }: rec { - src = lib.cleanSource ./.; filter = name: type: !(builtins.any (x: x) [ @@ -55,69 +54,66 @@ }; packages = rec { - # Build the top-level crates of the workspace as individual derivations. - # This allows consumers to only depend on (and build) only what they need. - # Though it is possible to build the entire workspace as a single derivation, - # so this is left up to you on how to organize things - probe-frontend = craneLib.buildPackage (individualCrateArgs - // { - pname = "probe-frontend"; - cargoExtraArgs = "-p probe_frontend"; - installPhase = '' - cp -r ./python/ $out - cp ./LICENSE $out/LICENSE - ''; - }); - probe-py-generated = let - workspace = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).workspace; - - # TODO: Simplify this - # Perhaps by folding the substituteAllFiles into probe-py-generated (upstream) or probe-py-frontend (downstream) - # Could we combine all the packages? - in - python.pkgs.buildPythonPackage rec { - src = pkgs.substituteAllFiles rec { - src = probe-frontend; - files = [ - "./pyproject.toml" - "./LICENSE" - "./probe_py/generated/__init__.py" - "./probe_py/generated/ops.py" - "./probe_py/generated/parser.py" - ]; - authors = builtins.concatStringsSep "" (builtins.map (match: let - name = builtins.elemAt match 0; - email = builtins.elemAt match 1; - in "\n {name = \"${name}\", email = \"${email}\"},") ( - builtins.map + # Build the top-level crates of the workspace as individual derivations. + # This allows consumers to only depend on (and build) only what they need. + # Though it is possible to build the entire workspace as a single derivation, + # so this is left up to you on how to organize things + probe-frontend = craneLib.buildPackage (individualCrateArgs + // { + pname = "probe-frontend"; + cargoExtraArgs = "-p probe_frontend"; + installPhase = '' + cp -r ./python/ $out + cp ./LICENSE $out/LICENSE + ''; + }); + probe-py-generated = let + workspace = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).workspace; + # TODO: Simplify this + # Perhaps by folding the substituteAllFiles into probe-py-generated (upstream) or probe-py-frontend (downstream) + # Could we combine all the packages? + in + python.pkgs.buildPythonPackage rec { + src = pkgs.substituteAllFiles rec { + src = probe-frontend; + files = [ + "./pyproject.toml" + "./LICENSE" + "./probe_py/generated/__init__.py" + "./probe_py/generated/ops.py" + "./probe_py/generated/parser.py" + ]; + authors = builtins.concatStringsSep "" (builtins.map (match: let + name = builtins.elemAt match 0; + email = builtins.elemAt match 1; + in "\n {name = \"${name}\", email = \"${email}\"},") ( + builtins.map (author-str: builtins.match "(.+) <(.+)>" author-str) (workspace.package.authors) - )); + )); + version = workspace.package.version; + }; + pname = "probe_py.generated"; version = workspace.package.version; + pyproject = true; + build-system = [ + python.pkgs.flit-core + ]; + pythonImportsCheck = [pname]; }; - pname = "probe_py.generated"; - version = workspace.package.version; - pyproject = true; - build-system = [ - python.pkgs.flit-core - ]; - pythonImportsCheck = [pname]; - }; - - probe-cli = craneLib.buildPackage (individualCrateArgs - // { - pname = "probe-cli"; - cargoExtraArgs = "-p probe_cli"; - }); - probe-macros = craneLib.buildPackage (individualCrateArgs - // { - pname = "probe-macros"; - cargoExtraArgs = "-p probe_macros"; - }); + probe-cli = craneLib.buildPackage (individualCrateArgs + // { + pname = "probe-cli"; + cargoExtraArgs = "-p probe_cli"; + }); + probe-macros = craneLib.buildPackage (individualCrateArgs + // { + pname = "probe-macros"; + cargoExtraArgs = "-p probe_macros"; + }); }; checks = { - probe-workspace-clippy = craneLib.cargoClippy (commonArgs // { inherit cargoArtifacts; @@ -154,5 +150,4 @@ partitionType = "count"; }); }; - } From 015c5af27129ba946ae66d17f694318cbc580653 Mon Sep 17 00:00:00 2001 From: Samuel Grayson Date: Tue, 15 Oct 2024 12:02:50 -0500 Subject: [PATCH 7/9] Reduce GitHub Actions matrix --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 687e7a50..7108b631 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,13 @@ jobs: strategy: matrix: - os: [ubuntu-22.04, ubuntu-20.04] + os: + - ubuntu-20.04 + #- ubuntu-22.04 + # We can test on a Matrix of Ubuntu versions + # But Nix does get us pretty good reproducibility + # So we will test just one in CI. + # More full tests can be run by docker_os_matrix.py runs-on: ${{ matrix.os }} From 6659ed0d980b9d9c86c7363d34c3c9b19ca180ef Mon Sep 17 00:00:00 2001 From: Samuel Grayson Date: Tue, 15 Oct 2024 12:47:32 -0500 Subject: [PATCH 8/9] Fix Cachix --- .github/workflows/ci.yml | 8 +++++--- Justfile | 12 ++++++++++-- flake.nix | 4 +++- probe_src/frontend/frontend.nix | 18 +++++++++--------- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7108b631..6b360f7a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,13 +31,15 @@ jobs: extra_nix_config: | experimental-features = nix-command flakes - - name: Test existence of Cachix signing key - run: echo ${{ secrets.CACHIX_SIGNING_KEY }} | wc -c + - name: Test existence of secrets + run: | + echo -e 'CACHIX_AUTH_TOKEN length: ' + echo ${{ secrets.CACHIX_AUTH_TOKEN }} | wc -c - uses: cachix/cachix-action@v15 with: name: charmonium - signingKey: ${{ secrets.CACHIX_SIGNING_KEY }} + authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - name: Run Just on-push stuff in development shell run: nix develop --command just on-push diff --git a/Justfile b/Justfile index c998cad7..c48e0e94 100644 --- a/Justfile +++ b/Justfile @@ -50,12 +50,20 @@ test-dev: compile check-flake: nix flake check --all-systems -user-facing-build: +user-facing-build: check-flake # `just compile` is great, but it's the _dev-facing_ build. # Users will build PROBE following the `README.md` # which says `nix profile install github:charmoniumQ/PROBE#probe-bundled` # Which should be equivalent to this: - nix build .#probe-bundled + nix build .#probe-bundled .#probe-py + +upload-cachix: user-facing-build + #!/usr/bin/env bash + if [ -z "$CACHIX_AUTH_TOKEN" ]; then + echo "CACHIX_AUTH_TOKEN not set" + exit 1 + fi + nix-store -qR --include-outputs $(nix-store -qd $(nix build --print-out-paths --no-link .#probe-bundled .#probe-py)) | grep -v '\.drv$' | cachix push charmonium pre-commit: fix-format-nix fix-ruff fix-format-rust fix-clippy compile check-mypy test-dev on-push: check-format-nix check-ruff check-format-rust check-clippy compile check-mypy test-ci check-flake user-facing-build diff --git a/flake.nix b/flake.nix index 92006ca8..3808af34 100644 --- a/flake.nix +++ b/flake.nix @@ -71,6 +71,7 @@ }; in rec { packages = rec { + inherit (frontend.packages) cargoArtifacts; libprobe = pkgs.stdenv.mkDerivation rec { pname = "libprobe"; version = "0.1.0"; @@ -182,8 +183,9 @@ pkgs.alejandra pkgs.hyperfine pkgs.just - pkgs.black pkgs.ruff + pkgs.cachix + pkgs.jq # to make cachix work ] # gdb broken on i686 ++ pkgs.lib.lists.optional (system != "i686-linux") pkgs.nextflow diff --git a/probe_src/frontend/frontend.nix b/probe_src/frontend/frontend.nix index 88029136..54f17c5f 100644 --- a/probe_src/frontend/frontend.nix +++ b/probe_src/frontend/frontend.nix @@ -38,12 +38,6 @@ CPATH = ../libprobe/include; }; - # Build *just* the cargo dependencies (of the entire workspace), - # so we can reuse all of that work (e.g. via cachix) when running in CI - # It is *highly* recommended to use something like cargo-hakari to avoid - # cache misses when building individual top-level-crates - cargoArtifacts = craneLib.buildDepsOnly commonArgs; - individualCrateArgs = commonArgs // { @@ -54,6 +48,12 @@ }; packages = rec { + # Build *just* the cargo dependencies (of the entire workspace), + # so we can reuse all of that work (e.g. via cachix) when running in CI + # It is *highly* recommended to use something like cargo-hakari to avoid + # cache misses when building individual top-level-crates + cargoArtifacts = craneLib.buildDepsOnly commonArgs; + # Build the top-level crates of the workspace as individual derivations. # This allows consumers to only depend on (and build) only what they need. # Though it is possible to build the entire workspace as a single derivation, @@ -116,13 +116,13 @@ checks = { probe-workspace-clippy = craneLib.cargoClippy (commonArgs // { - inherit cargoArtifacts; + inherit (packages) cargoArtifacts; cargoClippyExtraArgs = "--all-targets -- --deny warnings"; }); probe-workspace-doc = craneLib.cargoDoc (commonArgs // { - inherit cargoArtifacts; + inherit (packages) cargoArtifacts; }); # Check formatting @@ -145,7 +145,7 @@ # run the tests twice. probe-workspace-nextest = craneLib.cargoNextest (commonArgs // { - inherit cargoArtifacts; + inherit (packages) cargoArtifacts; partitions = 1; partitionType = "count"; }); From f39d4f0a0b06d1d5704e24a7bcafb350045d30d5 Mon Sep 17 00:00:00 2001 From: Samuel Grayson Date: Tue, 15 Oct 2024 12:59:26 -0500 Subject: [PATCH 9/9] Update documentation to refer to cachix --- README.md | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 40993872..6fdc2150 100644 --- a/README.md +++ b/README.md @@ -8,16 +8,6 @@ The provenance graph tells us where a particular file came from. The provenance graph can help us re-execute the program, containerize the program, turn it into a workflow, or tell us which version of the data did this program use. -## Reading list - -- [_Provenance for Computational Tasks: A Survey_ by Freire, et al. in CiSE 2008](https://sci.utah.edu/~csilva/papers/cise2008a.pdf) for an overview of provenance in general. -- [_Transparent Result Caching_ by Vahdat and Anderson in USENIX ATC 1998](https://www.usenix.org/legacy/publications/library/proceedings/usenix98/full_papers/vahdat/vahdat.pdf) for an early system-level provenance tracer in Solaris using the `/proc` fs. Linux's `/proc` fs doesn't have the same functionality. However, this paper discusses two interesting application of provenance: unmake (query lineage information) and transparent Make (more generally, incremental computation). -- [_CDE: Using System Call Interposition to Automatically Create Portable Software Packages_ by Guo and Engler in USENIX ATC 2011](https://www.usenix.org/legacy/events/atc11/tech/final_files/GuoEngler.pdf) for an early system-level provenance tracer. Their only application is software execution replay, but replay is quite an important application. -- [_Techniques for Preserving Scientific Software Executions: Preserve the Mess or Encourage Cleanliness?_ by Thain, Meng, and Ivie in 2015 ](https://curate.nd.edu/articles/journal_contribution/Techniques_for_Preserving_Scientific_Software_Executions_Preserve_the_Mess_or_Encourage_Cleanliness_/24824439?file=43664937) discusses whether enabling automatic-replay is actually a good idea. A cursory glance makes PROBE seem more like "preserving the mess", but I think, with some care in the design choices, it actually can be more like "encouraging cleanliness", for example, by having heuristics that help cull/simplify provenance and generating human readable/editable package-manager recipes. -- [_SoK: History is a Vast Early Warning System: Auditing the Provenance of System Intrusions_ by Inam et al. in IEEE Symposium on Security and Privacy 2023](https://adambates.org/documents/Inam_Oakland23.pdf) see specifically Inam's survey of different possibilities for the "Capture layer", "Reduction layer", and "Infrastructure layer". Although provenance-for-security has different constraints than provenacne for other purposes, the taxonomy that Inam lays out is still useful. PROBE operates by intercepting libc calls, which is essentially a "middleware" in Table I (platform modification, no program modification, no config change, incomplete mediation, not tamperproof, inter-process tracing, etc.). -- [_System-Level Provenance Tracers_ by me et al. in ACM REP 2023](./docs/acm-rep-pres.pdf) for a motivation of this work. It surveys prior work, identifies potential gaps, and explains why I think library interposition is a promising path for future research. -- [_Computational Experiment Comprehension using Provenance Summarization_ by Bufford et al. in ACM REP 2023](https://dl.acm.org/doi/pdf/10.1145/3641525.3663617) discusses how to implement an interface for querying provenance information. They compare classical graph-based visualization with an interactive LLM in a user-study. - ## Installing PROBE 1. Install Nix with flakes. This can be done on any Linux (including Ubuntu, RedHat, Arch Linux, not just NixOS), MacOS X, or even Windows Subsystem for Linux. @@ -32,13 +22,22 @@ The provenance graph can help us re-execute the program, containerize the progra - If you already have Nix and are running NixOS, enable flakes with by adding `nix.settings.experimental-features = [ "nix-command" "flakes" ];` to your configuration. -2. Run `nix env -i github:charmoniumQ/PROBE#probe-bundled`. +2. If you want to avoid a time-consuming build, add our public cache. + + ```bash + nix profile install --accept-flake-config nixpkgs#cachix + cachix use charmonium + ``` + + If you want to build from source (e.g., for security reasons), skip this step. -3. Now you should be able to run `probe record [-f] [-o probe_log] `, e.g., `probe record ./script.py --foo bar.txt`. See below for more details. +3. Run `nix env -i github:charmoniumQ/PROBE#probe-bundled`. -4. To view the provenance, run `probe dump [-i probe_log]`. See below for more details. +4. Now you should be able to run `probe record [-f] [-o probe_log] `, e.g., `probe record ./script.py --foo bar.txt`. See below for more details. -5. Run `probe --help` for more details. +5. To view the provenance, run `probe dump [-i probe_log]`. See below for more details. + +6. Run `probe --help` for more details. ## What does `probe record` do? @@ -109,6 +108,22 @@ nix shell nixpkgs#graphviz github:charmoniumQ/PROBE#probe-py-manual \ 7. **Before submitting a PR**, run `just pre-commit` which will run pre-commit checks. +## Resarch reading list + +- [_Provenance for Computational Tasks: A Survey_ by Freire, et al. in CiSE 2008](https://sci.utah.edu/~csilva/papers/cise2008a.pdf) for an overview of provenance in general. + +- [_Transparent Result Caching_ by Vahdat and Anderson in USENIX ATC 1998](https://www.usenix.org/legacy/publications/library/proceedings/usenix98/full_papers/vahdat/vahdat.pdf) for an early system-level provenance tracer in Solaris using the `/proc` fs. Linux's `/proc` fs doesn't have the same functionality. However, this paper discusses two interesting application of provenance: unmake (query lineage information) and transparent Make (more generally, incremental computation). + +- [_CDE: Using System Call Interposition to Automatically Create Portable Software Packages_ by Guo and Engler in USENIX ATC 2011](https://www.usenix.org/legacy/events/atc11/tech/final_files/GuoEngler.pdf) for an early system-level provenance tracer. Their only application is software execution replay, but replay is quite an important application. + +- [_Techniques for Preserving Scientific Software Executions: Preserve the Mess or Encourage Cleanliness?_ by Thain, Meng, and Ivie in 2015 ](https://curate.nd.edu/articles/journal_contribution/Techniques_for_Preserving_Scientific_Software_Executions_Preserve_the_Mess_or_Encourage_Cleanliness_/24824439?file=43664937) discusses whether enabling automatic-replay is actually a good idea. A cursory glance makes PROBE seem more like "preserving the mess", but I think, with some care in the design choices, it actually can be more like "encouraging cleanliness", for example, by having heuristics that help cull/simplify provenance and generating human readable/editable package-manager recipes. + +- [_SoK: History is a Vast Early Warning System: Auditing the Provenance of System Intrusions_ by Inam et al. in IEEE Symposium on Security and Privacy 2023](https://adambates.org/documents/Inam_Oakland23.pdf) see specifically Inam's survey of different possibilities for the "Capture layer", "Reduction layer", and "Infrastructure layer". Although provenance-for-security has different constraints than provenacne for other purposes, the taxonomy that Inam lays out is still useful. PROBE operates by intercepting libc calls, which is essentially a "middleware" in Table I (platform modification, no program modification, no config change, incomplete mediation, not tamperproof, inter-process tracing, etc.). + +- [_System-Level Provenance Tracers_ by me et al. in ACM REP 2023](./docs/acm-rep-pres.pdf) for a motivation of this work. It surveys prior work, identifies potential gaps, and explains why I think library interposition is a promising path for future research. + +- [_Computational Experiment Comprehension using Provenance Summarization_ by Bufford et al. in ACM REP 2023](https://dl.acm.org/doi/pdf/10.1145/3641525.3663617) discusses how to implement an interface for querying provenance information. They compare classical graph-based visualization with an interactive LLM in a user-study. + ## Prior art - [RR-debugger](https://github.com/rr-debugger/rr) which is much slower, but features more complete capturing, lets you replay but doesn't let you do any other analysis.