Skip to content

Commit

Permalink
aarch64-darwin support (#195)
Browse files Browse the repository at this point in the history
for nix build, use flake-utils for multi-platform and support libc++/libstdc++
Use InterruptibleFFI for safer Haskell/C++ interactions

* use flake-utils. support aarch64-darwin
* ghc 9.2.3. remove -Werror for now.
* update nixpkgs
* remove stdc++ dep
* remove ../build-tools in cabal.project
* if os(darwin) conditional for libc++/libstdc++
* not use os(darwin) due to cabal2nix problem
* don't fix GHC version
* use InterruptbileFFI
* remove nix flake check in CI due to IFD limitation
https://discourse.nixos.org/t/nix-flake-show-fails-when-the-flake-provides-packages-for-other-platforms/18726/2
* fix missing ForeignFunctionInterface and InterruptibleFFI for top-level modules.
* make macos case pass
  • Loading branch information
wavewave authored Oct 21, 2022
1 parent d3a0864 commit 9181428
Show file tree
Hide file tree
Showing 12 changed files with 167 additions and 109 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ jobs:
uses: cachix/install-nix-action@v16
with:
nix_path: nixpkgs=channel:nixos-unstable
- name: check flake
run: |
nix flake check
- name: build fficxx-runtime
run: |
nix build --print-build-logs .#fficxx-runtime
Expand Down
21 changes: 13 additions & 8 deletions fficxx-multipkg-test/test/TemplateDepSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import System.IO.Silently (capture_)
--

--
import Test.Hspec (Spec, afterAll, around, beforeAll, describe, it, shouldBe)
import Test.Hspec (Spec, afterAll, around, beforeAll, describe, it, shouldBe, shouldSatisfy)
import TmplDepTest.T1.TH
import TmplDepTest.T1.Template
import TmplDepTest.T2.TH
Expand Down Expand Up @@ -74,10 +74,15 @@ spec =
callT1 t2 t1
s <- capture_ action
s `shouldBe` "In T2::callT1(), calling T1::method: \nIn T1::method(), typeid(P) = i\n"
it "should call template function that depends on another template class, for non-primitive type param" $ do
let action = do
t1 <- newT1 :: IO (T1 CppString)
t2 <- newT2 :: IO (T2 CppString)
callT1 t2 t1
s <- capture_ action
s `shouldBe` "In T2::callT1(), calling T1::method: \nIn T1::method(), typeid(P) = NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE\n"
it "should call template function that depends on another template class, for non-primitive type param" $
do
let action = do
t1 <- newT1 :: IO (T1 CppString)
t2 <- newT2 :: IO (T2 CppString)
callT1 t2 t1
s <- capture_ action
s
`shouldSatisfy` ( \s ->
s == "In T2::callT1(), calling T1::method: \nIn T1::method(), typeid(P) = NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE\n"
|| s == "In T2::callT1(), calling T1::method: \nIn T1::method(), typeid(P) = NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE\n"
)
1 change: 0 additions & 1 deletion fficxx-runtime/fficxx-runtime.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,5 @@ Library
Function.h
cpp_magic.h
ghc-options: -Wall
-Werror
-funbox-strict-fields
-fno-warn-unused-do-bind
1 change: 0 additions & 1 deletion fficxx/fficxx.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ Library
FFICXX.Generate.Type.Module
FFICXX.Generate.Type.PackageInterface
ghc-options: -Wall
-Werror
-funbox-strict-fields
-fno-warn-unused-do-bind
-fno-warn-missing-signatures
37 changes: 33 additions & 4 deletions fficxx/src/FFICXX/Generate/ContentMaker.hs
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,12 @@ buildTopLevelCppDef tih =

-- |
buildFFIHsc :: ClassModule -> Module ()
buildFFIHsc m = mkModule (mname <.> "FFI") [lang ["ForeignFunctionInterface"]] ffiImports hscBody
buildFFIHsc m =
mkModule
(mname <.> "FFI")
[lang ["ForeignFunctionInterface", "InterruptibleFFI"]]
ffiImports
hscBody
where
mname = cmModule m
ffiImports =
Expand Down Expand Up @@ -582,7 +587,14 @@ buildTopLevelHs ::
buildTopLevelHs modname (mods, tmods) =
mkModuleE modname pkgExtensions pkgExports pkgImports pkgBody
where
pkgExtensions = [lang ["FlexibleContexts", "FlexibleInstances"]]
pkgExtensions =
[ lang
[ "FlexibleContexts",
"FlexibleInstances",
"ForeignFunctionInterface",
"InterruptibleFFI"
]
]
pkgExports =
map (emodule . cmModule) mods
++ map emodule [modname <.> "Ordinary", modname <.> "Template", modname <.> "TH"]
Expand All @@ -599,7 +611,14 @@ buildTopLevelOrdinaryHs modname (_mods, tmods) tih =
mkModuleE modname pkgExtensions pkgExports pkgImports pkgBody
where
tfns = tihFuncs tih
pkgExtensions = [lang ["FlexibleContexts", "FlexibleInstances"]]
pkgExtensions =
[ lang
[ "FlexibleContexts",
"FlexibleInstances",
"ForeignFunctionInterface",
"InterruptibleFFI"
]
]
pkgExports = map (evar . unqual . hsFrontNameForTopLevel . TLOrdinary) (filterTLOrdinary tfns)
pkgImports =
map mkImport ["Foreign.C", "Foreign.Ptr", "FFICXX.Runtime.Cast"]
Expand All @@ -622,6 +641,8 @@ buildTopLevelTemplateHs modname tih =
[ lang
[ "EmptyDataDecls",
"FlexibleInstances",
"ForeignFunctionInterface",
"InterruptibleFFI",
"MultiParamTypeClasses",
"TypeFamilies"
]
Expand Down Expand Up @@ -652,7 +673,15 @@ buildTopLevelTHHs modname tih =
mkModuleE modname pkgExtensions pkgExports pkgImports pkgBody
where
tfns = filterTLTemplate (tihFuncs tih)
pkgExtensions = [lang ["FlexibleContexts", "FlexibleInstances", "TemplateHaskell"]]
pkgExtensions =
[ lang
[ "FlexibleContexts",
"FlexibleInstances",
"ForeignFunctionInterface",
"InterruptibleFFI",
"TemplateHaskell"
]
]
pkgExports =
map
( evar
Expand Down
4 changes: 2 additions & 2 deletions fficxx/src/FFICXX/Generate/Util/HaskellSrcExts.hs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ import Language.Haskell.Exts
QOp (QVarOp),
QualConDecl (..),
Rhs (UnGuardedRhs),
Safety (PlaySafe),
Safety (PlayInterruptible),
Splice (ParenSplice),
Stmt
( Generator,
Expand Down Expand Up @@ -212,7 +212,7 @@ mkNewtype n tbinds qdecls mderiv = DataDecl () (NewType ()) Nothing declhead qde
declhead = mkDeclHead n tbinds

mkForImpCcall :: String -> String -> Type () -> Decl ()
mkForImpCcall quote n typ = ForImp () (CCall ()) (Just (PlaySafe () False)) (Just quote) (Ident () n) typ
mkForImpCcall quote n typ = ForImp () (CCall ()) (Just (PlayInterruptible ())) (Just quote) (Ident () n) typ

mkModule :: String -> [ModulePragma ()] -> [ImportDecl ()] -> [Decl ()] -> Module ()
mkModule n pragmas idecls decls = Module () (Just mhead) pragmas idecls decls
Expand Down
24 changes: 20 additions & 4 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

147 changes: 78 additions & 69 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -1,88 +1,97 @@
{
description = "fficxx";
inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-21.11"; };
outputs = { self, nixpkgs }:
let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
inputs = {
# nixpkgs/master on 2022-07-18
nixpkgs.url = "github:NixOS/nixpkgs/31997025a4d59f09a9b4c55a3c6ff5ade48de2d6";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
};

haskellPackages = pkgs.haskell.packages.ghc8107;
haskellPackages = pkgs.haskellPackages;

newHaskellPackages0 = haskellPackages.override {
overrides = self: super: {
newHaskellPackages0 = haskellPackages.override {
overrides = self: super: {
"fficxx-runtime" =
self.callCabal2nix "fficxx-runtime" ./fficxx-runtime { };
"fficxx" = self.callCabal2nix "fficxx" ./fficxx { };
};
};

stdcxxSrc = import ./stdcxx-gen/gen.nix {
inherit (pkgs) lib stdenv;
haskellPackages = newHaskellPackages0;
};

finalHaskellOverlay = self: super: {
"fficxx-runtime" =
self.callCabal2nix "fficxx-runtime" ./fficxx-runtime { };
"fficxx" = self.callCabal2nix "fficxx" ./fficxx { };
"stdcxx" = self.callCabal2nix "stdcxx" stdcxxSrc { };
};
};

stdcxxSrc = import ./stdcxx-gen/gen.nix {
inherit (pkgs) stdenv;
haskellPackages = newHaskellPackages0;
};

finalHaskellOverlay = self: super: {
"fficxx-runtime" =
self.callCabal2nix "fficxx-runtime" ./fficxx-runtime { };
"fficxx" = self.callCabal2nix "fficxx" ./fficxx { };
"stdcxx" = self.callCabal2nix "stdcxx" stdcxxSrc { };
};

newHaskellPackages = haskellPackages.override {
overrides = let
tmfTestSrc = import ./fficxx-multipkg-test/template-member/gen.nix {
inherit (pkgs) stdenv;
haskellPackages = newHaskellPackages0;
};
tmplDepTestSrc = import ./fficxx-multipkg-test/template-dep/gen.nix {
inherit (pkgs) stdenv;
haskellPackages = newHaskellPackages0;
};
tmplTopLevelTestSrc =
import ./fficxx-multipkg-test/template-toplevel/gen.nix {
newHaskellPackages = haskellPackages.override {
overrides = let
tmfTestSrc = import ./fficxx-multipkg-test/template-member/gen.nix {
inherit (pkgs) stdenv;
haskellPackages = newHaskellPackages0;
};
tmplDepTestSrc = import ./fficxx-multipkg-test/template-dep/gen.nix {
inherit (pkgs) stdenv;
haskellPackages = newHaskellPackages0;
};
tmplTopLevelTestSrc =
import ./fficxx-multipkg-test/template-toplevel/gen.nix {
inherit (pkgs) stdenv;
haskellPackages = newHaskellPackages0;
};

in self: super:
finalHaskellOverlay self super // {
"fficxx-test" = self.callCabal2nix "fficxx-test" ./fficxx-test { };
"fficxx-multipkg-test" =
self.callCabal2nix "fficxx-multipkg-test" ./fficxx-multipkg-test
{ };
"tmf-test" = self.callCabal2nix "tmf-test" tmfTestSrc { };
"tmpl-dep-test" =
self.callCabal2nix "tmpl-dep-test" tmplDepTestSrc { };
"tmpl-dup-inst" = self.callCabal2nix "tmpl-dup-inst"
./fficxx-multipkg-test/tmpl-dup-inst { };
"tmpl-toplevel-test" =
self.callCabal2nix "tmpl-toplevel-test" tmplTopLevelTestSrc { };
in self: super:
finalHaskellOverlay self super // {
"fficxx-test" = self.callCabal2nix "fficxx-test" ./fficxx-test { };
"fficxx-multipkg-test" =
self.callCabal2nix "fficxx-multipkg-test" ./fficxx-multipkg-test
{ };
"tmf-test" = self.callCabal2nix "tmf-test" tmfTestSrc { };
"tmpl-dep-test" =
self.callCabal2nix "tmpl-dep-test" tmplDepTestSrc { };
"tmpl-dup-inst" = self.callCabal2nix "tmpl-dup-inst"
./fficxx-multipkg-test/tmpl-dup-inst { };
"tmpl-toplevel-test" =
self.callCabal2nix "tmpl-toplevel-test" tmplTopLevelTestSrc { };
};
};
};

in {
packages.x86_64-linux = {
inherit (newHaskellPackages)
fficxx fficxx-runtime stdcxx fficxx-test fficxx-multipkg-test tmf-test
tmpl-dep-test tmpl-dup-inst tmpl-toplevel-test;
};
in {
packages = {
"stdcxx-src" = stdcxxSrc;
inherit (newHaskellPackages)
fficxx fficxx-runtime stdcxx fficxx-test fficxx-multipkg-test tmf-test
tmpl-dep-test tmpl-dup-inst tmpl-toplevel-test;
};

# see these issues and discussions:
# - https://github.com/NixOS/nixpkgs/issues/16394
# - https://github.com/NixOS/nixpkgs/issues/25887
# - https://github.com/NixOS/nixpkgs/issues/26561
# - https://discourse.nixos.org/t/nix-haskell-development-2020/6170
overlay = final: prev: {
haskellPackages = prev.haskellPackages.override (old: {
overrides = final.lib.composeExtensions (old.overrides or (_: _: { }))
finalHaskellOverlay;
});
};
# see these issues and discussions:
# - https://github.com/NixOS/nixpkgs/issues/16394
# - https://github.com/NixOS/nixpkgs/issues/25887
# - https://github.com/NixOS/nixpkgs/issues/26561
# - https://discourse.nixos.org/t/nix-haskell-development-2020/6170
overlay = final: prev: {
haskellPackages = prev.haskellPackages.override (old: {
overrides = final.lib.composeExtensions (old.overrides or (_: _: { }))
finalHaskellOverlay;
});
};

devShell.x86_64-linux = newHaskellPackages0.shellFor {
packages = ps: [ ps.fficxx ps.fficxx-runtime ];
buildInputs = [ pkgs.cabal-install ];
withHoogle = false;
};
};
devShell = newHaskellPackages0.shellFor {
packages = ps: [ ps.fficxx ps.fficxx-runtime ];
buildInputs = [ pkgs.cabal-install pkgs.ormolu ];
withHoogle = false;
};
}
);
}

6 changes: 5 additions & 1 deletion stdcxx-gen/gen.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{ stdenv, haskellPackages }:
{ lib, stdenv, haskellPackages }:

let
hsenv = haskellPackages.ghcWithPackages (p: with p; [ fficxx-runtime fficxx ]);
Expand All @@ -10,6 +10,10 @@ stdenv.mkDerivation {
src = ./.;
buildPhase = ''
runhaskell Gen.hs
'' + lib.optionalString (stdenv.isDarwin) ''
# for gcc/clang difference, we need this ad hoc treatment.
# TODO: find a better way than os(darwin)
sed -i 's/stdc++/c++/g' stdcxx/stdcxx.cabal
'';
installPhase = ''
mkdir -p $out
Expand Down
12 changes: 6 additions & 6 deletions workspace/build_dep.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ rm -rf dist-newstyle
rm -rf stdcxx
rm -rf tmpl-dep-test
rm -rf working
cabal new-build fficxx-runtime
cabal new-build fficxx
cabal build fficxx-runtime
cabal build fficxx
sleep 1s
cabal new-exec runhaskell ../stdcxx-gen/Gen.hs
cabal new-build stdcxx
cabal exec runhaskell -- ../stdcxx-gen/Gen.hs
cabal build stdcxx


# template-member
runhaskell ../fficxx-multipkg-test/template-dep/Gen.hs ../fficxx-multipkg-test/template-dep/template
cabal new-build tmpl-dep-test
cabal exec runhaskell -- ../fficxx-multipkg-test/template-dep/Gen.hs ../fficxx-multipkg-test/template-dep/template
cabal build tmpl-dep-test
#cabal new-exec -- runhaskell -- -fobject-code -O0 template-member/app.hs

Loading

0 comments on commit 9181428

Please sign in to comment.