diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.github/workflows/build_nix.yml b/.github/workflows/build_nix.yml new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore index f51fa7b..7a4e3c0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ resource/private *.bs.js lib/bs node_modules/ +result +.direnv diff --git a/bin/sdl2/dune b/bin/sdl2/dune index 2f4f36d..33c1e0a 100644 --- a/bin/sdl2/dune +++ b/bin/sdl2/dune @@ -1,4 +1,5 @@ (executables (names main bench) + (public_names camlboy-sdl camlboy-sdl-bench) (ocamlopt_flags -O3) (libraries camlboy_lib tsdl)) diff --git a/dune b/dune new file mode 100644 index 0000000..1f2f900 --- /dev/null +++ b/dune @@ -0,0 +1,11 @@ +(data_only_dirs chain node_modules) + +(env + (static + (flags + (:standard -ccopt -static)) + (ocamlopt_flags + (:standard -O3 -unbox-closures))) + (release + (ocamlopt_flags + (:standard -O3 -unbox-closures)))) diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..34d7001 --- /dev/null +++ b/flake.lock @@ -0,0 +1,80 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nix-filter": { + "locked": { + "lastModified": 1661201956, + "narHash": "sha256-RizGJH/buaw9A2+fiBf9WnXYw4LZABB5kMAZIEE5/T8=", + "owner": "numtide", + "repo": "nix-filter", + "rev": "3b821578685d661a10b563cba30b1861eec05748", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "nix-filter", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1646939531, + "narHash": "sha256-bxOjVqcsccCNm+jSmEh/bm0tqfE3SdjwS+p+FZja3ho=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "fcd48a5a0693f016a5c370460d0c2a8243b882dc", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "ocaml-overlay": { + "inputs": { + "flake-utils": [ + "flake-utils" + ] + }, + "locked": { + "lastModified": 1647238661, + "narHash": "sha256-QHR1MqzuJS8d4abZGFpcu/sETak4pHHC556pTsLJK9Q=", + "owner": "anmonteiro", + "repo": "nix-overlays", + "rev": "f8e6e97c1e016192c785f9052403e15efda91f31", + "type": "github" + }, + "original": { + "owner": "anmonteiro", + "repo": "nix-overlays", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nix-filter": "nix-filter", + "nixpkgs": "nixpkgs", + "ocaml-overlay": "ocaml-overlay" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..4530f85 --- /dev/null +++ b/flake.nix @@ -0,0 +1,49 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + + ocaml-overlay.url = "github:anmonteiro/nix-overlays"; + ocaml-overlay.inputs.flake-utils.follows = "flake-utils"; + + nix-filter.url = "github:numtide/nix-filter"; + }; + + outputs = { self, nixpkgs, flake-utils, ocaml-overlay, nix-filter }: + let + supported_ocaml_versions = [ "ocamlPackages_4_12" "ocamlPackages_4_13" "ocamlPackages_5_00" ]; + out = system: + let + pkgs = import nixpkgs { + inherit system; + overlays = [ ocaml-overlay.overlay ]; + }; + inherit (pkgs) lib; + myPkgs = pkgs.recurseIntoAttrs (import ./nix { + inherit pkgs nix-filter; + doCheck = true; + }).native; + myDrvs = lib.filterAttrs (_: value: lib.isDerivation value) myPkgs; + in + { + devShell = (pkgs.mkShell { + inputsFrom = lib.attrValues myDrvs; + buildInputs = with pkgs; + with ocamlPackages; [ + ocaml-lsp + ocamlformat + odoc + ocaml + dune_3 + nixfmt + utop + ]; + }); + + defaultPackage = myPkgs.camlboy; + }; + in + with flake-utils.lib; eachSystem defaultSystems out // { + overlays = { default = import ./nix/overlay.nix supported_ocaml_versions nix-filter; }; + }; +} diff --git a/lib/dune b/lib/dune index 9ca70bf..b311a7c 100644 --- a/lib/dune +++ b/lib/dune @@ -1,5 +1,6 @@ (library (name camlboy_lib) + (public_name camlboy) (libraries bigstringaf)) (include_subdirs unqualified) diff --git a/nix/camlboy.nix b/nix/camlboy.nix new file mode 100644 index 0000000..59cbc6c --- /dev/null +++ b/nix/camlboy.nix @@ -0,0 +1,43 @@ +{ pkgs, nix-filter, stdenv, lib, ocamlPackages, static ? false, doCheck }: + +with ocamlPackages; +buildDunePackage { + pname = "camlboy"; + version = "0.1.0"; + + src = nix-filter.lib.filter { + root = ../.; + # TODO: package the brr and include the browser front end + include = [ + "lib" + "bin/sdl2" + "dune" + "dune-project" + "camlboy.opam" + "resources" + ]; + }; + + # Static builds support, note that you need a static profile in your dune file + buildPhase = '' + echo "running ${if static then "static" else "release"} build" + dune build --profile=${if static then "static" else "release"} + ''; + + checkInputs = [ ]; + + propagatedBuildInputs = [ + ppx_deriving + tsdl + base + bigstringaf + ppx_jane + odoc + ]; + + inherit doCheck; + + meta = { + description = "A Game Boy emulator written in OCaml that runs in your browser"; + }; +} diff --git a/nix/default.nix b/nix/default.nix new file mode 100644 index 0000000..020eccc --- /dev/null +++ b/nix/default.nix @@ -0,0 +1,22 @@ +{ pkgs ? import ./sources.nix { }, nix-filter, doCheck ? false }: + +{ + native = { + camlboy = pkgs.callPackage ./camlboy.nix { + inherit doCheck nix-filter; + }; + }; + + musl64 = + let + pkgsCross = pkgs.pkgsCross.musl64.pkgsStatic; + + in + { + camlboy = pkgsCross.callPackage ./camlboy.nix { + static = true; + inherit doCheck; + ocamlPackages = pkgsCross.ocamlPackages; + }; + }; +} diff --git a/nix/overlay.nix b/nix/overlay.nix new file mode 100644 index 0000000..92542ac --- /dev/null +++ b/nix/overlay.nix @@ -0,0 +1,19 @@ +supported_ocaml_versions: nix-filter: + +final: prev: { + ocaml-ng = builtins.mapAttrs + (name: ocamlVersion: + # If the current ocamlVersion exists in supported versions + (if (builtins.any (x: x == name) supported_ocaml_versions) then + ocamlVersion.overrideScope' + (oself: osuper: { + camlboy = (prev.callPackage ./camlboy.nix { + inherit nix-filter; + ocamlPackages = oself; + doCheck = true; + }); + }) + else + ocamlVersion)) + prev.ocaml-ng; +}