diff --git a/ocaml/default.nix b/ocaml/default.nix index d58be445b..5174a927c 100644 --- a/ocaml/default.nix +++ b/ocaml/default.nix @@ -46,6 +46,7 @@ , libxcb , xorg , zstd-oc +, libfontconfig }: oself: osuper: @@ -1584,6 +1585,39 @@ with oself; }; }); + reason-harfbuzz = callPackage ./revery/reason-harfbuzz.nix { }; + reason-sdl2 = callPackage ./revery/reason-sdl2.nix { }; + reason-skia = callPackage ./revery/reason-skia.nix { + inherit libfontconfig; + }; + revery = callPackage ./revery { }; + + rench = buildDunePackage { + pname = "Rench"; + version = "0.0.0"; + src = fetchFromGitHub { + owner = "revery-ui"; + repo = "rench"; + rev = "df44c5277ed1d3ccfa959f2623705baefd26ad99"; + sha256 = "sha256-cGBYBIxVIuhbvkGxM1lAN0j5m5Fiqlc3O1xyt9OFP4U="; + }; + nativeBuildInputs = [ reason ]; + propagatedBuildInputs = [ flex fpath ]; + }; + + timber = buildDunePackage { + pname = "timber"; + version = "0.0.0"; + src = fetchFromGitHub { + owner = "revery-ui"; + repo = "timber"; + rev = "f4c40ee5d7cb93801160340ac4ac9c974ce01b66"; + sha256 = "sha256-tk/2Of0R4WzjM7Fiv0mXVSbmiRHXMtppLgBcgvX4p9s="; + }; + nativeBuildInputs = [ reason ]; + propagatedBuildInputs = [ fmt logs re ]; + }; + swhid_core = buildDunePackage { pname = "swhid_core"; version = "0.1"; diff --git a/ocaml/revery/default.nix b/ocaml/revery/default.nix new file mode 100644 index 000000000..6178677a1 --- /dev/null +++ b/ocaml/revery/default.nix @@ -0,0 +1,85 @@ +{ lib +, buildDunePackage +, fetchFromGitHub +, dune-configurator +, pkg-config +, reason +, lru +, uchar +, ppx_deriving +, brisk-reconciler +, lwt_ppx +, ppx_optcomp +, uutf +, uucp +, rebez +, bos +, charInfo_width +, reason-sdl2 +, reason-skia +, reason-harfbuzz +, rench +, timber +}: + +let + # This change is allows configuring initial capacity of the cache + # https://github.com/pqwy/lru/pull/8/commits/f646450cc5a165bbb39121d5a456dd3f5ad4dba5 + lruOverride = lru.overrideAttrs (_: super: { + patches = [ ./patches/0001-lru-initial-size.patch ]; + }); + omd = buildDunePackage { + pname = "omd"; + version = "0.0.0"; + src = fetchFromGitHub { + owner = "ocaml"; + repo = "omd"; + rev = "1535e3c684323f370f3f80bce2564863140de6ba"; + sha256 = "sha256-Tu60WdHvVq24m6QMJTe3B55gfNjtoxomW/Q3MT6//n4="; + }; + propagatedBuildInputs = [ + uchar + ]; + }; + +in + +buildDunePackage { + pname = "Revery"; + version = "0.0.0"; + # TODO: check if a patch can avoid disabling this + # https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wstrict-overflow + hardeningDisable = [ "strictoverflow" ]; + inherit (reason-sdl2) src; + preBuild = '' + substituteInPlace packages/zed/src/dune --replace "bytes" "" + # This supresses a warning from the use of CAMLparam2, where caml__frame is unused: + # dialog.c:32:5: error: unused variable 'caml__frame' [-Werror,-Wunused-variable] + # TODO: try to suppress this for the single file + substituteInPlace src/Native/dune --replace "-Werror" "-Werror -Wno-unused-variable" + ''; + buildInputs = [ + dune-configurator + ]; + nativeBuildInputs = [ + reason + pkg-config + ]; + propagatedBuildInputs = [ + ppx_deriving + brisk-reconciler + lwt_ppx + ppx_optcomp + uutf + uucp + reason-skia + omd + rebez + bos + reason-harfbuzz + charInfo_width + lruOverride + rench + timber + ]; +} diff --git a/ocaml/revery/patches/0001-lru-initial-size.patch b/ocaml/revery/patches/0001-lru-initial-size.patch new file mode 100644 index 000000000..f417cd91b --- /dev/null +++ b/ocaml/revery/patches/0001-lru-initial-size.patch @@ -0,0 +1,49 @@ +diff --git a/src/lru.ml b/src/lru.ml +index f3e1301..fffcec2 100644 +--- a/src/lru.ml ++++ b/src/lru.ml +@@ -209,7 +209,7 @@ module M = struct + type t + type k + type v +- val create : ?random:bool -> int -> t ++ val create : ?random:bool -> ?initialSize: int -> int -> t + val is_empty : t -> bool + val size : t -> int + val weight : t -> int +@@ -250,9 +250,11 @@ module M = struct + + let cap_makes_sense = cap_makes_sense ~m:"M" + +- let create ?random cap = ++ let create ?random ?initialSize cap = ++ let hashSize = ++ match initialSize with | None -> cap | (Some v) -> v in + cap_makes_sense ~f:"create" cap; +- { cap; w = 0; ht = HT.create ?random cap; q = Q.create () } ++ { cap; w = 0; ht = HT.create ?random hashSize; q = Q.create () } + + let lru t = match t.q.Q.first with Some n -> Some n.Q.value | _ -> None + +diff --git a/src/lru.mli b/src/lru.mli +index 5271846..ea81bf0 100644 +--- a/src/lru.mli ++++ b/src/lru.mli +@@ -219,12 +219,15 @@ module M : sig + type v + (** Values in {{!t}[t]}. *) + +- val create : ?random:bool -> int -> t +- (** [create ?random cap] is a new map with capacity [cap]. ++ val create : ?random:bool -> ?initialSize:int -> int -> t ++ (** [create ?random ?initialSize cap] is a new map with capacity [cap]. + + [~random] randomizes the underlying hash table. It defaults to [false]. + See {!Hashtbl.create}. + ++ [~initialSize] sets the initial size of the underlying hash table. If not set, ++ [initialSize] is set to [cap]. ++ + {b Note.} The internal hash table is created with size [cap]. + + @raise Invalid_argument when [cap < 0]. *) diff --git a/ocaml/revery/patches/0002-esy-skia-use-libtool.patch b/ocaml/revery/patches/0002-esy-skia-use-libtool.patch new file mode 100644 index 000000000..c4eda580f --- /dev/null +++ b/ocaml/revery/patches/0002-esy-skia-use-libtool.patch @@ -0,0 +1,52 @@ +From 445b2e0cb969f9de458b8464bd3b18caade11fc4 Mon Sep 17 00:00:00 2001 +From: Joseph Price +Date: Wed, 19 Jul 2023 07:37:32 -0400 +Subject: [PATCH] use libtool + +--- + gn/toolchain/BUILD.gn | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git a/gn/toolchain/BUILD.gn b/gn/toolchain/BUILD.gn +index cd1def114d..8a914a99c3 100644 +--- a/gn/toolchain/BUILD.gn ++++ b/gn/toolchain/BUILD.gn +@@ -260,11 +260,22 @@ template("gcc_like_toolchain") { + description = "assemble {{source}}" + } + ++ if (is_mac || is_ios) { ++ not_needed([ "ar" ]) # We use libtool instead. ++ } + tool("alink") { +- rspfile = "{{output}}.rsp" +- rspfile_content = "{{inputs}}" +- ar_py = rebase_path("../ar.py") +- command = "python $ar_py $ar {{output}} $rspfile" ++ if (is_mac || is_ios) { ++ command = "libtool -static -o {{output}} -no_warning_for_no_symbols {{inputs}}" ++ } else { ++ rspfile = "{{output}}.rsp" ++ rspfile_content = "{{inputs}}" ++ # TODO: add rm.py ++ #rm_py = rebase_path("../rm.py") ++ #command = "$shell python3 \"$rm_py\" \"{{output}}\" && $ar rcs {{output}} @$rspfile" ++ ar_py = rebase_path("../ar.py") ++ command = "python $ar_py $ar {{output}} $rspfile" ++ } ++ + outputs = [ + "{{root_out_dir}}/{{target_output_name}}{{output_extension}}", + ] +@@ -280,7 +291,7 @@ template("gcc_like_toolchain") { + } + + rpath = "-Wl,-soname,$soname" +- if (is_mac) { ++ if (is_mac || is_ios) { + rpath = "-Wl,-install_name,@rpath/$soname" + } + +-- +2.40.1 + diff --git a/ocaml/revery/reason-harfbuzz.nix b/ocaml/revery/reason-harfbuzz.nix new file mode 100644 index 000000000..2e2d9e44b --- /dev/null +++ b/ocaml/revery/reason-harfbuzz.nix @@ -0,0 +1,29 @@ +{ buildDunePackage +, pkg-config +, reason-sdl2 +, reason +, dune-configurator +, harfbuzz +, lib +, libcxx +, stdenv +, darwin +}: + +buildDunePackage { + pname = "reason-harfbuzz"; + version = "0.0.0"; + inherit (reason-sdl2) src; + + buildInputs = [ dune-configurator ] ++ + lib.optionals stdenv.isDarwin + (with darwin.apple_sdk.frameworks; + lib.optionals stdenv.isDarwin [ Foundation AppKit ]); + nativeBuildInputs = [ + reason + pkg-config + ]; + HARFBUZZ_INCLUDE_PATH = "${harfbuzz.dev}/include/harfbuzz"; + HARFBUZZ_LIB_PATH = ''${harfbuzz}/lib''; + NIX_CFLAGS_COMPILE = lib.optionalString stdenv.isDarwin "-I${lib.getDev libcxx}/include/c++/v1"; +} diff --git a/ocaml/revery/reason-sdl2.nix b/ocaml/revery/reason-sdl2.nix new file mode 100644 index 000000000..0ed71b95b --- /dev/null +++ b/ocaml/revery/reason-sdl2.nix @@ -0,0 +1,70 @@ +{ buildDunePackage +, fetchFromGitHub +, SDL2 +, ctypes +, findlib +, reason +, dune-configurator +, darwin +, libiconv +, lib +, stdenv +, libcxx +, libGLU +, libXxf86vm +, libXcursor +, libXrandr +, libXinerama +, libXi +}: + +buildDunePackage rec { + pname = "reason-sdl2"; + version = "0.0.0"; + src = fetchFromGitHub { + owner = "revery-ui"; + repo = "revery"; + # master branch as of Aug 27, 2021 + rev = "141f70f69d6abd69674b46d805a783411b38cd79"; + sha256 = "sha256-3AGdf0vcFoxcmGUHCUcmjb+VCpp2WDYmkv9Tp7VJqsw="; + }; + postPatch = '' + substituteInPlace packages/reason-sdl2/src/sdl2_wrapper.cpp \ + --replace "case SDL_PANEVENT:" "/* case SDL_PANEVENT:" \ + --replace "case SDL_DROPTEXT:" "*/ case SDL_DROPTEXT:" \ + --replace "case SDL_WINDOWEVENT_FULLSCREEN:" "/* case SDL_WINDOWEVENT_FULLSCREEN:" \ + --replace "case SDL_WINDOWEVENT_RESTORED:" "*/ case SDL_WINDOWEVENT_RESTORED:" \ + --replace "hash_variant" "caml_hash_variant" + ''; + buildInputs = [ + dune-configurator + # SDL2 + # SDL2.dev + libiconv + ] ++ + lib.optionals stdenv.isDarwin [ + darwin.apple_sdk.frameworks.Cocoa + darwin.apple_sdk.frameworks.ForceFeedback + ] ++ + lib.optionals stdenv.isLinux [ + libGLU + libXxf86vm + libXcursor + libXrandr + libXinerama + libXi + ]; + nativeBuildInputs = [ + reason + findlib + ]; + propagatedBuildInputs = [ + SDL2 + SDL2.dev + ctypes + ]; + SDL2_LIB_PATH = ''${(SDL2.override { withStatic = true; }).out}/lib''; + SDL2_INCLUDE_PATH = "${SDL2.dev}/include"; + cur__root = "${src}"; + env.NIX_CFLAGS_COMPILE = lib.optionalString stdenv.isDarwin "-I${lib.getDev libcxx}/include/c++/v1"; +} diff --git a/ocaml/revery/reason-skia.nix b/ocaml/revery/reason-skia.nix new file mode 100644 index 000000000..7e98f41a2 --- /dev/null +++ b/ocaml/revery/reason-skia.nix @@ -0,0 +1,72 @@ +{ buildDunePackage +, ctypes +, darwin +, dune-configurator +, esy-skia +, freetype +, libiconv +, libjpeg +, pkg-config +, reason +, reason-sdl2 +, SDL2 +, lib +, stdenv +, libGLU +, libXxf86vm +, libXcursor +, libXrandr +, libXinerama +, libXi +, zlib +, bzip2 +, fontconfig +, findlib +, libfontconfig +}: + +buildDunePackage { + pname = "reason-skia"; + version = "0.0.0"; + inherit (reason-sdl2) src; + # the cptr function was removed from ctypes, so the value now needs to be + # destructured to get to the pointer + postPatch = '' + substituteInPlace packages/reason-skia/src/Skia.re \ + --replace "module CI = Cstubs_internals;" \ + "module CI = { include Cstubs_internals; let cptr = (CPointer(a)) => a; };" + ''; + + nativeBuildInputs = [ reason pkg-config ]; + buildInputs = [ + dune-configurator + ]; + propagatedBuildInputs = with darwin.apple_sdk.frameworks; [ + libiconv + reason-sdl2 + ctypes + ] ++ + lib.optionals stdenv.isDarwin [ + AppKit + Cocoa + ForceFeedback + ] ++ + lib.optionals stdenv.isLinux [ + libfontconfig + libGLU + libXxf86vm + libXcursor + libXrandr + libXinerama + libXi + zlib + bzip2 + ]; + SDL2_INCLUDE_PATH = "${SDL2.dev}/include"; + SDL2_LIB_PATH = "${SDL2.override { withStatic = true; }}/lib"; + SKIA_INCLUDE_PATH = "${esy-skia}/include/c"; + SKIA_LIB_PATH = "${esy-skia}/out/Release"; + JPEG_LIB_PATH = "${(libjpeg.override { enableStatic = true; }).out}/lib"; + FREETYPE2_LIB_PATH = "${freetype}/lib"; + FREETYPE2_INCLUDE_PATH = "${freetype}/include"; +} diff --git a/overlay/default.nix b/overlay/default.nix index 0bc29089b..05045f8d6 100644 --- a/overlay/default.nix +++ b/overlay/default.nix @@ -11,10 +11,13 @@ let stdenv fetchFromGitHub callPackage + darwin fetchpatch + fetchgit buildGoModule haskell - haskellPackages; + haskellPackages + fontconfig; overlayOCamlPackages = attrs: import ../ocaml/overlay-ocaml-packages.nix (attrs // { inherit nixpkgs; @@ -34,6 +37,7 @@ in (callPackage ../ocaml { inherit nixpkgs; super-opaline = super.opaline; + libfontconfig = fontconfig; }) ]; }) // { @@ -143,6 +147,106 @@ in opaline = null; ott = super.ott.override { opaline = self.ocamlPackages.opaline; }; esy = callPackage ../ocaml/esy { }; + esy-skia = stdenv.mkDerivation rec { + name = "skia"; + src = fetchFromGitHub { + owner = "revery-ui"; + repo = "esy-skia"; + rev = "29349b9279ed24a73ec41acd7082caea9bd8c04e"; + sha256 = "sha256-VyY1clAdTEZu0cFy/+Bw19OQ4lb55s4gIV/7TsFKdnk="; + }; + nativeBuildInputs = with self; [ + gn + ninja + libjpeg + libpng + zlib + python3 + expat + # TODO: add optional webp support + #libwebp + # TODO handle ios, android + #-framework CoreServices -framework CoreGraphics -framework CoreText -framework CoreFoundation + ] ++ + lib.optionals stdenv.isLinux [ + fontconfig + freetype + ] ++ + lib.optionals stdenv.isDarwin [ + darwin.cctools + darwin.apple_sdk.frameworks.ApplicationServices + darwin.apple_sdk.frameworks.AppKit + darwin.apple_sdk.frameworks.OpenGL + # TODO handle ios, android + #-framework CoreServices -framework CoreGraphics -framework CoreText -framework CoreFoundation + ] ++ + lib.optionals (stdenv.isDarwin && !stdenv.isAarch64) [ darwin.cctools ]; + + patches = lib.optionals (stdenv.isDarwin && !stdenv.isAarch64) [ + ../ocaml/revery/patches/0002-esy-skia-use-libtool.patch + ]; + preConfigure = + let + angle2 = fetchgit { + url = "https://chromium.googlesource.com/angle/angle.git"; + rev = "47b3db22be33213eea4ad58f2453ee1088324ceb"; + sha256 = "sha256-ZF5wDOqh3cRfQGwOMay//4aWh9dBWk/cLmUsx+Ab2vw="; + }; + piex = fetchgit { + url = "https://android.googlesource.com/platform/external/piex.git"; + rev = "bb217acdca1cc0c16b704669dd6f91a1b509c406"; + sha256 = "05ipmag6k55jmidbyvg5mkqm69zfw03gfkqhi9jnjlmlbg31y412"; + }; + in + '' + mkdir -p third_party/externals + ln -s ${angle2} third_party/externals/angle2 + ln -s ${piex} third_party/externals/piex + + # this file is incorrectly referenced as paths are relative when gn runs in the folder + substituteInPlace gn/BUILDCONFIG.gn --replace "gn/is_clang.py" "is_clang.py" + # python 3 compat + substituteInPlace gn/is_clang.py --replace "print 'true'" "print('true')" + substituteInPlace gn/is_clang.py --replace "print 'false'" "print('false')" + # python 3 returns raw binary instead of an ecoded string + substituteInPlace gn/is_clang.py --replace "shell=True)" "shell=True).decode(sys.stdout.encoding)" + ''; + #TODO: built this based on feature flags, with sane defaults per os + #TODO: enable more features + configurePhase = '' + runHook preConfigure + gn gen out/Release \ + --args='is_debug=false is_official_build=true skia_use_egl=false skia_use_dng_sdk=false skia_enable_tools=false extra_asmflags=[] host_os="${if stdenv.isDarwin then "mac" else "linux"}" skia_enable_gpu=true skia_use_metal=${lib.trivial.boolToString stdenv.isDarwin} skia_use_vulkan=false skia_use_angle=false skia_use_fontconfig=${lib.trivial.boolToString stdenv.isLinux} skia_use_freetype=${lib.trivial.boolToString stdenv.isLinux} skia_enable_pdf=false skia_use_sfntly=false skia_use_icu=false skia_use_libwebp=false skia_use_libpng=true esy_skia_enable_svg=true target_cpu="${if stdenv.isAarch64 then "arm64" else "x86_64"}"' + runHook postConfigure + ''; + buildPhase = '' + runHook preBuild + ninja -C out/Release skia + runHook postBuild + ''; + + # TODO: these includes were taken from alperite and can probably be simplified to include everything + installPhase = '' + mkdir -p $out + + # Glob will match all subdirs. + shopt -s globstar + + cp -r --parents -t $out/ \ + include/codec \ + include/config \ + include/core \ + include/effects \ + include/gpu \ + include/private \ + include/utils \ + include/c \ + out/Release/*.a \ + src/gpu/**/*.h \ + third_party/externals/angle2/include \ + third_party/skcms/**/*.h + ''; + }; h2spec = self.buildGoModule { pname = "h2spec";