;; src/ contains no dune-related files
;; kimchi-stubs-vendors contains the vendors for Kimchi stubs

(data_only_dirs src kimchi-stubs-vendors)

;; Ignore target if it exists locally

(dirs :standard .cargo \ target)

;;
;; Rules to set the optimisation flags for the rust compiler.
;;
;; By default, we compile with optimisations enabled. The instructions that
;; these generate may not be available on all CPU architectures; to build a
;; slower version that does not use these instructions, set the environment
;; variable `RUST_TARGET_FEATURE_OPTIMISATIONS=n`.
;;

(rule
 (enabled_if
  (<> %{env:RUST_TARGET_FEATURE_OPTIMISATIONS=y} n))
 (targets rustflags.sexp)
 (action
  (with-stdout-to
   rustflags.sexp
   (echo "-C target-feature=+bmi2,+adx"))))

(rule
 (enabled_if
  (= %{env:RUST_TARGET_FEATURE_OPTIMISATIONS=y} n))
 (targets rustflags.sexp)
 (action
  (with-stdout-to
   rustflags.sexp
   (echo "-C target-feature=-bmi2,-adx"))))

;;
;; rules to build the static library for kimchi
;;

;; note: to build Mina, nix will set `KIMCHI_STUBS` and ignore this rule

(rule
 (enabled_if
  (= %{env:KIMCHI_STUBS=n} n))
 (targets libkimchi_stubs.a)
 (deps
  Cargo.toml
  rust-toolchain.toml
  (source_tree src)
  (source_tree kimchi-stubs-vendors)
  (source_tree .cargo)
  (source_tree ../../proof-systems)
  (env_var KIMCHI_STUBS))
 (locks /cargo-lock) ;; lock for rustup
 (action
  (progn
   (setenv
    RUSTFLAGS
    %{read:rustflags.sexp}
    (run
     cargo
     build
     -p
     kimchi-stubs
     --release
     --target-dir
     %{read:../dune-build-root}/cargo_kimchi_stubs
     --offline))
   (run
    cp
    %{read:../dune-build-root}/cargo_kimchi_stubs/release/libkimchi_stubs.a
    .))))

;; this is used by nix

(rule
 (enabled_if
  (<> %{env:KIMCHI_STUBS_STATIC_LIB=n} n))
 (targets libkimchi_stubs.a)
 (deps
  (env_var KIMCHI_STUBS_STATIC_LIB))
 (action
  (progn
   (copy
    %{env:KIMCHI_STUBS_STATIC_LIB=n}/lib/libkimchi_stubs.a
    libkimchi_stubs.a))))

;;
;; declare the libraries we're going to generate to match the bindings
;;

(library
 (public_name kimchi_types)
 (name kimchi_types)
 (modules kimchi_types)
 (instrumentation
  (backend bisect_ppx))
 (libraries mina_stdlib)
 (inline_tests
  (flags -verbose -show-counts))
 (preprocess
  (pps ppx_version ppx_inline_test)))

(library
 (public_name pasta_bindings)
 (name pasta_bindings)
 (modules pasta_bindings)
 (libraries kimchi_types mina_stdlib pasta_bindings.backend)
 (instrumentation
  (backend bisect_ppx))
 (inline_tests
  (flags -verbose -show-counts))
 (preprocess
  (pps ppx_version ppx_inline_test)))

(library
 (public_name kimchi_bindings)
 (name kimchi_bindings)
 (modules kimchi_bindings)
 (libraries pasta_bindings kimchi_types mina_stdlib)
 (instrumentation
  (backend bisect_ppx))
 (inline_tests
  (flags -verbose -show-counts))
 (preprocess
  (pps ppx_version ppx_inline_test)))

(library
 (public_name pasta_bindings.backend.native)
 (name pasta_bindings_backend_native)
 (modules pasta_bindings_backend)
 (foreign_archives kimchi_stubs)
 (no_dynlink)
 ; ^ Required for compilation of this library separately
 ; from libraries that depend on it
 (c_library_flags :standard "-lpthread")
 (libraries mina_stdlib)
 (instrumentation
  (backend bisect_ppx))
 (inline_tests
  (flags -verbose -show-counts))
 (preprocess
  (pps ppx_version ppx_inline_test))
 (implements pasta_bindings.backend))

;;
;; generate the OCaml bindings
;;

;; note: to build Mina, nix will set `KIMCHI_STUBS` and ignore this rule

(rule
 (targets kimchi_types.ml pasta_bindings.ml kimchi_bindings.ml)
 (enabled_if
  (= %{env:KIMCHI_STUBS=n} n))
 (mode promote)
 (deps
  ../../../../.ocamlformat
  Cargo.toml
  rust-toolchain.toml
  (source_tree src)
  (source_tree kimchi-stubs-vendors)
  (source_tree .cargo)
  (source_tree ../../proof-systems)
  (env_var KIMCHI_STUBS))
 (locks /cargo-lock) ;; lock for rustup
 (action
  (progn
   (run rm -rf ./target)
   (run rm -f ./Cargo.lock)
   (setenv
    CARGO_TARGET_DIR
    "%{read:../dune-build-root}/cargo_kimchi_bindgen"
    (run cargo run %{targets} --offline))
   (run ocamlformat -i %{targets}))))

;; this is used by nix

(rule
 (targets kimchi_types.ml pasta_bindings.ml kimchi_bindings.ml)
 (enabled_if
  (<> %{env:KIMCHI_STUBS=n} n))
 (mode promote)
 (deps
  ../../../../.ocamlformat
  (env_var KIMCHI_STUBS))
 (action
  (progn
   (run %{env:KIMCHI_STUBS=n}/bin/wires_15_stubs %{targets})
   (run ocamlformat -i %{targets}))))
