diff --git a/.gitignore b/.gitignore index 0f9ee72a7..2f743fb61 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ polonius_cache/ # Outputs of c2rust-transpile snapshot tests c2rust-transpile/tests/snapshots/**/*.rs + +# Nix output symlinks +result* diff --git a/README.md b/README.md index d87593872..cbb0e277f 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ For example, the official LLVM packages from [apt.llvm.org](https://apt.llvm.org - **NixOS / nix:** ```sh - nix-shell + nix shell github:immunant/c2rust ``` - **macOS:** Xcode command-line tools and recent LLVM (we recommend the Homebrew version) are required. diff --git a/default.nix b/default.nix index cf6bbada8..405c29a50 100644 --- a/default.nix +++ b/default.nix @@ -1,22 +1,14 @@ +final: prev: let - nixpkgs = import { }; - inherit (nixpkgs) pkgs llvmPackages; - stdenv = pkgs.clangStdenv; + # Get rust-overlay from the flake.lock file + rustNodes = (builtins.fromJSON (builtins.readFile ./flake.lock)).nodes.rust-overlay.locked; + rust-overlay = final.fetchFromGitHub { + inherit (rustNodes) owner repo rev; + hash = rustNodes.narHash; + }; + + overlain = final.extend (import rust-overlay); in -stdenv.mkDerivation { - name = "c2rust"; - buildInputs = [ - pkgs.clang - pkgs.cmake - pkgs.llvm - pkgs.libllvm - pkgs.openssl - pkgs.pkgconfig - pkgs.python3 - pkgs.rustup - pkgs.zlib - ]; - LIBCLANG_PATH = "${pkgs.libclang.lib}/lib"; - CMAKE_LLVM_DIR = "${llvmPackages.libllvm.dev}/lib/cmake/llvm"; - CMAKE_CLANG_DIR = "${llvmPackages.libclang.dev}/lib/cmake/clang"; +{ + c2rust = overlain.callPackage ./nix { }; } diff --git a/flake.lock b/flake.lock index e8f193622..36379a967 100644 --- a/flake.lock +++ b/flake.lock @@ -1,34 +1,15 @@ { "nodes": { - "fenix": { - "inputs": { - "nixpkgs": "nixpkgs", - "rust-analyzer-src": "rust-analyzer-src" - }, - "locked": { - "lastModified": 1715581585, - "narHash": "sha256-/JjvIn1NXW3yOaDcD8Me987/QcXjo+rhg+uThasPAnI=", - "owner": "nix-community", - "repo": "fenix", - "rev": "2c4905096782e8e908205e7fa54ef987fba62793", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "fenix", - "type": "github" - } - }, "flake-utils": { "inputs": { "systems": "systems" }, "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -39,96 +20,45 @@ }, "nixpkgs": { "locked": { - "lastModified": 1715534503, - "narHash": "sha256-5ZSVkFadZbFP1THataCaSf0JH2cAH3S29hU9rrxTEqk=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "2057814051972fa1453ddfb0d98badbea9b83c06", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1715542476, - "narHash": "sha256-FF593AtlzQqa8JpzrXyRws4CeKbc5W86o8tHt4nRfIg=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "44072e24566c5bcc0b7aa9178a0104f4cfffab19", - "type": "github" + "lastModified": 1755253863, + "narHash": "sha256-ZFkjmihDaMJRhh7ztPNKdjiXkfWSa0GaiSvf8X0/LZI=", + "rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c", + "type": "tarball", + "url": "https://releases.nixos.org/nixos/unstable/nixos-25.11pre844474.fbcf476f790d/nixexprs.tar.xz?rev=fbcf476f790d8a217c3eab4e12033dc4a0f6d23c" }, "original": { - "owner": "NixOS", - "ref": "nixos-23.11", - "repo": "nixpkgs", - "type": "github" + "type": "tarball", + "url": "https://nixos.org/channels/nixos-unstable/nixexprs.tar.xz" } }, - "nixpkgs_3": { - "locked": { - "lastModified": 1706487304, - "narHash": "sha256-LE8lVX28MV2jWJsidW13D2qrHU/RUUONendL2Q/WlJg=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "90f456026d284c22b3e3497be980b2e47d0b28ac", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" } }, - "oxalica": { + "rust-overlay": { "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs_3" + "nixpkgs": [ + "nixpkgs" + ] }, "locked": { - "lastModified": 1715652909, - "narHash": "sha256-aCLEDvzL1j51Rf2mCFOqK1mieMO3pAn5ItCIdr5h2LA=", + "lastModified": 1719454714, + "narHash": "sha256-MojqG0lyUINkEk0b3kM2drsU5vyaF8DFZe/FAlZVOGs=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "1d8fcbbfcfd3476c2665384a46ee9d07ef2b4dd9", + "rev": "d1c527659cf076ecc4b96a91c702d080b213801e", "type": "github" }, "original": { "owner": "oxalica", + "ref": "snapshot/2024-08-01", "repo": "rust-overlay", "type": "github" } }, - "root": { - "inputs": { - "fenix": "fenix", - "nixpkgs": "nixpkgs_2", - "oxalica": "oxalica", - "utils": "utils" - } - }, - "rust-analyzer-src": { - "flake": false, - "locked": { - "lastModified": 1715255944, - "narHash": "sha256-vLLgYpdtKBaGYTamNLg1rbRo1bPXp4Jgded/gnprPVw=", - "owner": "rust-lang", - "repo": "rust-analyzer", - "rev": "5bf2f85c8054d80424899fa581db1b192230efb5", - "type": "github" - }, - "original": { - "owner": "rust-lang", - "ref": "nightly", - "repo": "rust-analyzer", - "type": "github" - } - }, "systems": { "locked": { "lastModified": 1681028828, @@ -143,39 +73,6 @@ "repo": "default", "type": "github" } - }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "utils": { - "inputs": { - "systems": "systems_2" - }, - "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index f78bdecb7..6df5ff858 100644 --- a/flake.nix +++ b/flake.nix @@ -2,75 +2,46 @@ description = "Flake for c2rust"; inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; - utils.url = "github:numtide/flake-utils"; - fenix = { - url = "github:nix-community/fenix"; - }; - oxalica = { - url = "github:oxalica/rust-overlay"; - }; + nixpkgs.url = "https://nixos.org/channels/nixos-unstable/nixexprs.tar.xz"; + flake-utils.url = "github:numtide/flake-utils"; + rust-overlay.url = "github:oxalica/rust-overlay/snapshot/2024-08-01"; + rust-overlay.inputs.nixpkgs.follows = "nixpkgs"; }; - outputs = inputs@{ self, nixpkgs, utils, fenix, oxalica}: - utils.lib.eachDefaultSystem (system: - let - fenixStable = fenix.packages.${system}.fromToolchainFile { - file = ./rust-toolchain.toml; - sha256 = "sha256-r/8YBFuFa4hpwgE3FnME7nQA2Uc1uqj0eCE1NWmI1u0"; - }; + outputs = + { + self, + nixpkgs, + flake-utils, + rust-overlay, + }: + flake-utils.lib.eachDefaultSystem ( + system: + let pkgs = import nixpkgs { inherit system; overlays = [ - (import oxalica) + (import rust-overlay) + (import self) ]; - config = { - allowUnfree = true; - }; }; - in { - defaultPackage = self.devShell.${system}; - devShell = pkgs.mkShell.override { } { + in + { + packages = { + default = pkgs.c2rust; + unwrapped = pkgs.c2rust.unwrapped; + }; - LIBCLANG_PATH = "${pkgs.llvmPackages_14.libclang.lib}/lib"; - CMAKE_LLVM_DIR = "${pkgs.llvmPackages_14.libllvm.dev}/lib/cmake/llvm"; - CMAKE_CLANG_DIR = "${pkgs.llvmPackages_14.libclang.dev}/lib/cmake/clang"; - shellHook = '' - export CARGO_TARGET_DIR="$(git rev-parse --show-toplevel)/target_dirs/nix_rustc"; - ''; - RUST_SRC_PATH = pkgs.rustPlatform.rustLibSrc; - buildInputs = - with pkgs; [ - clangStdenv.cc - llvmPackages_14.libclang - pkg-config - fenix.packages.${system}.rust-analyzer - llvmPackages_14.clang - cmake - llvmPackages_14.llvm - llvmPackages_14.libllvm - openssl - (python3.withPackages - (python-pkgs: - with python-pkgs; - [ "bencode-python3" - cbor - colorlog - mako - pip - plumbum - psutil - pygments - typing - "scan-build" - pyyaml - toml - ] - ) - ) - zlib - (rust-bin.fromRustupToolchainFile ./rust-toolchain.toml) - ]; - }; - }); + devShells.default = pkgs.callPackage ./shell.nix { }; + + formatter = pkgs.nixfmt-tree; + checks = { + inherit (pkgs) c2rust; + devShell = self.devShells.${system}.default; + }; + } + ) + // { + overlays = import self; + }; } diff --git a/nix/default.nix b/nix/default.nix new file mode 100644 index 000000000..f42d7b8b2 --- /dev/null +++ b/nix/default.nix @@ -0,0 +1,28 @@ +{ + lib, + runCommand, + callPackage, + makeBinaryWrapper, + llvmPackages, +}: +let + c2rust = callPackage ./package.nix { }; +in +runCommand "c2rust-${c2rust.version}" + { + inherit (c2rust) version meta; + nativeBuildInputs = [ + makeBinaryWrapper + ]; + + passthru.unwrapped = c2rust; + } + '' + makeWrapper ${lib.getExe c2rust} "$out/bin/c2rust" \ + --prefix PATH : ${ + lib.makeBinPath [ + c2rust.toolchain + llvmPackages.libllvm + ] + } + '' diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 000000000..6695fdb0a --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,120 @@ +{ + lib, + # Requires rust-overlay for the pinned nightly + # Specifically it requires an old snapshop. + rust-bin, + makeRustPlatform, + rustc, + clangStdenv, + # binaries + llvmPackages, + cmake, + pkg-config, + # libraries + tinycbor, + # Check binaries + python3, +}: +let + # Something changed in nixpkgs since this snapshot, + # so we need to stuff some additional attributes in it. + toolchain = + rust-bin.nightly."2022-08-08".minimal.override + or (throw "Requires the snapshot/2024-08-01 tag of rust-overlay") + { + extensions = [ + "rustc-dev" + "rust-src" + ]; + } + // { + inherit (rustc) targetPlatforms badTargetPlatforms; + }; + + rustPlatform = makeRustPlatform { + stdenv = clangStdenv; + rustc = toolchain; + cargo = toolchain; + }; + + fs = lib.fileset; + + cargoToml = builtins.fromTOML (builtins.readFile ../Cargo.toml); +in +rustPlatform.buildRustPackage (finalAttrs: { + strictDeps = true; + pname = "c2rust"; + inherit (cargoToml.workspace.package) version; + + src = fs.toSource { + root = ../.; + fileset = fs.difference (fs.gitTracked ../.) ( + fs.unions [ + ../.github + ../.gitignore + ../.gitmodules + ../docs + ../examples + ../manual + ../scripts + ../.typos.toml + ../README.md + ../LICENSE + ../book.toml + ../flake.lock + ../flake.nix + ../shell.nix + ] + ); + }; + + patches = [ + ./tinycbor.patch + ]; + + cargoLock.lockFile = ../Cargo.lock; + cargoBuildFlags = [ + "-p" + "c2rust" + ]; + + nativeBuildInputs = [ + rustPlatform.bindgenHook + llvmPackages.libllvm + cmake + pkg-config + ]; + + buildInputs = [ + tinycbor + llvmPackages.libclang + ]; + + env = { + CMAKE_CLANG_DIR = "${llvmPackages.libclang.dev}/lib/cmake/clang"; + RUSTFLAGS = "-L native=${tinycbor}/lib"; + }; + + # FIXME: uhhhhhhhhhhhhhhhhhhhhhhhhhhhh + doCheck = false; + nativeCheckInputs = [ + python3 + ]; + + passthru.toolchain = toolchain; + + meta = { + description = "helper for migrating C99 code to Rust"; + homepage = "https://c2rust.com/"; + changelog = "https://github.com/immunant/c2rust/releases/tag/v${finalAttrs.version}"; + downloadPage = "https://github.com/immunant/c2rust"; + mainProgram = "c2rust"; + license = with lib.licenses; [ + # c2rust + bsd3 + # c2rust/c2rust-ast-pritner + mit + asl20 + ]; + }; +}) diff --git a/nix/tinycbor.patch b/nix/tinycbor.patch new file mode 100644 index 000000000..a527871a4 --- /dev/null +++ b/nix/tinycbor.patch @@ -0,0 +1,51 @@ +In the Nix sandbox, network access is not avaliable. Luckily tinycbor is avaliable with the rev +requested in nixpkgs. So this patch just allows for cmake to grab the pkgconfig module. + +--- a/c2rust-ast-exporter/src/CMakeLists.txt ++++ b/c2rust-ast-exporter/src/CMakeLists.txt +@@ -6,43 +6,8 @@ project(ASTExporter) + # TinyCBOR # + ################################################# + +-set(TINYCBOR_REPO "https://github.com/intel/tinycbor.git" CACHE STRING "tinycbor git repo URL") +- +-# v0.6.3 tag, but using the commit hash instead (of the tarball hash) for integrity checks +-# unlike a .tar.gz MD5 hash, this SHA-1 commit hash should stay stable regardless of compression/archiving +-# (GitHub has changed this), and still retains the integrity check +-set(TINYCBOR_TAG "d393c16f3eb30d0c47e6f9d92db62272f0ec4dc7" CACHE STRING "tinycbor git tag/branch/commit hash") +- +-set(TINYCBOR_PREFIX "${CMAKE_BINARY_DIR}/tinycbor" CACHE STRING "tinycbor install prefix") +- +-if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") +- set(MAKE "gmake") +-else() +- set(MAKE "make") +-endif() +- +-include(ExternalProject) +-ExternalProject_Add(tinycbor_build +- PREFIX ${TINYCBOR_PREFIX} +- INSTALL_DIR ${CMAKE_BINARY_DIR} +- GIT_REPOSITORY ${TINYCBOR_REPO} +- GIT_TAG ${TINYCBOR_TAG} +- # the fd redirection here fails when the build run inside Cargo. +- # patch from upstream: +- # https://github.com/intel/tinycbor/commit/6176e0a28d7c5ef3a5e9cbd02521999c412de72c +- PATCH_COMMAND patch --forward -p1 < ${CMAKE_CURRENT_SOURCE_DIR}/tinycbor_fix_build.patch || true +- CONFIGURE_COMMAND ${MAKE} .config && cat ${CMAKE_CURRENT_SOURCE_DIR}/tinycbor.config >> .config +- BUILD_COMMAND ${MAKE} --quiet prefix= CFLAGS=-fPIC +- INSTALL_COMMAND ${MAKE} --quiet prefix= install +- BUILD_IN_SOURCE 1 +- BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/lib/libtinycbor.a +-) +- +-include_directories(${CMAKE_BINARY_DIR}/include) +- +-add_library(tinycbor STATIC IMPORTED) +-set_target_properties(tinycbor PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/lib/libtinycbor.a) +-add_dependencies(tinycbor tinycbor_build) ++find_package(PkgConfig REQUIRED) ++pkg_check_modules(TINYCBOR REQUIRED tinycbor) + + set(AST_EXPORTER_SRCS + AstExporter.cpp diff --git a/shell.nix b/shell.nix new file mode 100644 index 000000000..3d5ba24c0 --- /dev/null +++ b/shell.nix @@ -0,0 +1,46 @@ +{ + pkgs ? ( + import { + overlays = [ + (import ./.) + ]; + } + ), +}: +pkgs.mkShell.override + { + stdenv = pkgs.clangStdenv; + } + { + name = "c2rust-devshell"; + inputsFrom = [ + pkgs.c2rust.unwrapped + ]; + + packages = [ + (pkgs.c2rust.unwrapped.toolchain.override (old: { + extensions = old.extensions ++ [ + "rustfmt" + "miri" + "rust-analyzer" + ]; + })) + + (pkgs.python3.withPackages (p: [ + p.bencode-py + p.cbor + p.colorlog + p.mako + p.pip + p.plumbum + p.psutil + p.pygments + p.typing + # p.scan-build TODO: Once merged to nixpkgs, add + p.pyyaml + p.toml + ])) + + pkgs.openssl + ]; + }