Closed mouse07410 closed 2 months ago
As far as I understand, you are not supposed to use Foo_stub.h
files directly, but copy them to known location (as Foo.h
) and edit them into proper header files, to be used as part of your bigger C development.
At least when making e.g. foreign libraries, _stub.h
files are something you want to distribute with your shared library binary, and that might have more stuff.
As far as I understand, you are not supposed to use
Foo_stub.h
files directly,
I never heard that.
...but copy them to a known location (as
Foo.h
)
Re. renaming - probably depends. With other ecosystems I've seen it both ways - using Foo_stub.h
and using Foo.h
, without clear definition of reasons why one or the other.
Re. copying - sure. But how do I do it within the Cabal "realm"?
and edit them into proper header files,
Honestly, in general I don't see the need - these generated _stub.h
files appear proper, and perfectly usable as-is.
to be used as part of your bigger C development
Sure. As I expect that more often than not a (shared) library would be installed (copied to) somewhere, and other software on that machine would link against it, and load it. Same for the header files.
But in this toy project, the library can stay where it's built - Cabal and GHC seem to manage finding it without any problem.
It's only this one generated header file that gives us trouble.
At least when making e.g. foreign libraries,
_stub.h
files are something you want to distribute with your shared library binary, and that might have more stuff.
Yes, certainly.
But how can we resolve this problem now? I'd be equally happy with either telling Cabal to tell GHC where to find that Fib_stub.h
file, or telling Cabal to copy that file to, e.g., ./c_code/
directory after it's generated (library
target built) but before the next target (executable test
) starts building. Question is - how?
Basically, the problem is:
Fib_stub.h
and places it inside the dist-newstyle/...
Something needs to copy that file to, e.g., c_code/
directory, but Cabal doesn't do that;test
needs Fib_stub.h
, but since Cabal neither copied it to a "known" directory, nor passed it's actual location dir to GHC (who in turn did not pass it to clang
), the executable build fails.Two possible solutions:
-I./dist-newstyle/build/x86_64-osx/ghc-8.10.2/h-tst2-0.1.0.0/build
to clang
.(1) is required when a self-contained Haskell library is created. Users will access it via FFI, so there should be mechanisms that tell Cabal where to install these files, or how to package them.
(2) is required when one builds a mixed package that contains executables (in foreign language) which require that file to compile.
As far as I understand, the Something in
Something needs to copy that file to, ... but Cabal doesn't do that;
is a programmer.
Calling Haskell, from Haskell, but through C-wrappers feels round-about to me. I understand the idea of testing however, yet there I'd still imagine having a vanilla C-program (not compiled by Cabal) to do testing.
Yet, I have no idea how the foreign export
was ever planned to be integrated into Cabal builds, so I leave this issue open for someone who knows better to comment.
As far as I understand, the Something in
Something needs to copy that file to, ... but Cabal doesn't do that;
is a programmer.
That cannot work, because you pointed out yourself that it is wrong to try to dig into the bowels of the dist-newstyle/...
content. There has to be a way for Cabal to "install" those files (library itself, maybe some metadata, and header files) somewhere into a predictable stable documented location.
Calling Haskell, from Haskell, but through C-wrappers feels round-about to me
Sure, but I'm not doing that!
src/Fib.hs
library defined in the library
block of h-tst2.cabal
that exposes module Fib
. It provides Haskell and FFI interface to a Haskell function: Haskell function fib
and FFI API to it named fib_hs
. In the process of building it generates Fib_stub.h
header file and libHSh-tst2-0.1.0.0-inplace-ghc8.10.2.dylib
shared library itself. NB: Cabal and all the components it invokes, find that library fine.app/Main.hs
that calls fib
- for no particular purpose. This is the executable h-tst2
part of the h-tst2.cabal
, which is optional. It happens to work fine, but is not needed.test.c
that calls fib_hs
. For that it compiles test.c
including header Fib_stub.h
(which apparently it cannot find on its own, and links it with the library libHSh-tst2-0.1.0.0-inplace-ghc8.10.2.dylib
, which it can find (or Cabal can find) OK.One workaround would be to make Cabal do (1) - build the library itself, then make it take the files it generated, and install somewhere. Then, on a second invocation make Cabal build (3), taking Fib_stub.h
from where the previous step installed it to.
Questions:
~/.cabal/store
, apparently Cabal can find, so Haskell-to-Haskell shouldn't be a problem.Poking around, I found file dist-newstyle/packagedb/ghc-8.10.2/h-tst2-0.1.0.0-inplace.conf
. It's content has the directories I need, if there's a way to refer to them in/from the .cabal
file.
name: h-tst2
version: 0.1.0.0
visibility: public
id: h-tst2-0.1.0.0-inplace
key: h-tst2-0.1.0.0-inplace
license: MIT
copyright: "Copyright (C) 2020, MIT"
description:
Experiment to time performance of Haskell functions called from C
abi: inplace
exposed: True
exposed-modules: Fib
hidden-modules: Paths_h_tst2
import-dirs:
/Users/ur20980/src/h-tst2/dist-newstyle/build/x86_64-osx/ghc-8.10.2/h-tst2-0.1.0.0/build
library-dirs:
/Users/ur20980/src/h-tst2/dist-newstyle/build/x86_64-osx/ghc-8.10.2/h-tst2-0.1.0.0/build
/opt/local/lib/liconv /opt/local/lib /usr/local/lib
dynamic-library-dirs:
/Users/ur20980/src/h-tst2/dist-newstyle/build/x86_64-osx/ghc-8.10.2/h-tst2-0.1.0.0/build
/opt/local/lib/liconv /opt/local/lib /usr/local/lib
data-dir: /Users/ur20980/src/h-tst2
hs-libraries: HSh-tst2-0.1.0.0-inplace
include-dirs: /opt/local/include /usr/local/include
depends: base-4.14.1.0
haddock-interfaces:
/Users/ur20980/src/h-tst2/dist-newstyle/build/x86_64-osx/ghc-8.10.2/h-tst2-0.1.0.0/doc/html/h-tst2/h-tst2.haddock
haddock-html:
/Users/ur20980/src/h-tst2/dist-newstyle/build/x86_64-osx/ghc-8.10.2/h-tst2-0.1.0.0/doc/html/h-tst2
If only I could add something like include-dirs: $import-dirs
, it would find the required header file.
So, is there a way to refer to one of these variables (imports-dir
, libdir
, dynlibdir
) from inside h-tst2.cabal
file, using it as the value? E.g., some way to say
. . . . .
executable test
include-dirs: $(import-dirs)
main-is: test.c
ghc-options: -no-hs-main
. . . . .
Note: to reproduce checkout 7052904fed8eb06b79dad25fede7fcad134548ab
from the reproducer
Now Cabal works as expected - tested with 3.10.3.0 and 3.12.1.0, GHC-9.8.2 and 9.10.1 - when h-tst2.cabal
specifies a directory other than .
(see https://github.com/mouse07410/h-tst2/blob/master/h-tst2.cabal).
Describe the bug Cabal seems unable to figure where the .h header files that GHC generated on its behalf, are placed within the
dist-newstyle/
path.To Reproduce
Try to clone and build this sample project: https://github.com/mouse07410/h-tst2.git It should work:
Then comment out this obviously-wrong kludge-y line from
h-tst2.cabal
:do
cabal clean
and try the build again - the build would fail:Observe that the file in question
Fib_stub.h
does exist: