-
Notifications
You must be signed in to change notification settings - Fork 701
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
hookedPrograms
are not configurable from cabal configure
#9144
Comments
There's no intention of replacing the That said, the But finally, we also want to encourage users, over the long-term, to attempt to avoid custom Setup.hs scripts wherever possible in favor of improving the expressiveness of cabal files themselves, so it is worth considering the minimal extension to existing cabal file syntax that might allow avoiding a custom Setup. In this case, it looks like despite the hook being simple, its doing something pretty nontrivial, and there may not be a nice alternative -- but its always good to ponder. |
@gbaz, thank you for the clarification!
Good!
Yes, I know. I'm still using the
I wouldn't mind using My scenario is very simple:
That's it. Not sure if this can be achieved in Cabal without using a custom |
@lyokha Let me say I am very interested in your usecase! cabal-install supports building foreign-libraries. You can do
and There is also some support to build standalone libraries:
I am not sure what is preventing it from working on linux but I guess one can try. |
More discussion in #4827. |
@andreabedini This is a good point! I somehow missed availability of the As to building shared libraries in |
And down the rabbit hole I went! I turns out the only thing that is stopping us from using standalone libraries on Linux is that the boot packages shipped with GHC bindists are not compiled with -fPIC. So this happens:
BUT With modern tooling like ghcup, it's (relatively) easy to get a GHC with suitable boot packages. Putting together various examples I found online, I tried this:
And a couple of hours later, I could try again
Which is quite the improvement! FLibSimple has lens as a direct dependency, so RTS and all Haskell libraries got compiled in. See ghcup guide for the details about compiling GHC. Note: I am not sure this is a reasonable GHC build, I invite you to do your own research.
There are few ways to get a GHC environment from a cabal project. Beside the one you mention you can do
where cabal-install has sorted out the dependencies but you compile your code yourself.
I am not sure I understand this. The environment that cabal spits out is minimal (sort of, since it includes the dependencies of any exe component in any package in the build plan). But if you follow what libraries the dynamic linker is loading, you won't need a minimal environment. |
Yes, I know :) Some long time ago, at the dawn of the Ghc 8.x era, I even wrote a tutorial of how to build standalone shared libraries for Linux which also implied rebuild of the base libraries. Here it is: https://github.com/lyokha/nginx-haskell-module/tree/master/docs/static-linkage#readme.
Yes, but I built dependent libraries together with dependent libraries of the build tool (ngx-export-distribution, which depends on Cabal) in the same Ghc environment. Obviously, the target library won't likely need Cabal and its dependencies, but it got linked against them as Cabat etc. was listed in the Ghc environment file. |
And I somehow missed your tutorial, damn! This seems to be haskell folkore that should be properly documented.
I don't think setup dependencies end up in the environment but I will dobule check (following the example here). |
In the example, I did two preliminary steps: $ cabal v2-install --lib --only-dependencies --package-env . $ cabal v2-install --lib ngx-export-distribution --package-env . Hmm, it looks that the 2nd command can be replaced with $ cabal v2-build ngx-export-distribution and, as soon as ngx-export-distribution gets built by the 1st command, this step is not needed at all. Trying to reproduce excessive linkage in a fresh Cabal store Indeed, in a fresh Cabal store, after $ cabal --store-dir=$HOME/tmp/cabal v2-install --lib --only-dependencies --package-env . I get the following .ghc.environment.x86_64-linux-9.6.2:
After the 2nd command $ cabal --store-dir=$HOME/tmp/cabal v2-install --lib ngx-export-distribution --package-env . the evironment gets
Now, to build this, I should inject direct dependencies found by cabal-plan: $ . ../cabal-plan-direct-deps.sh >> .ghc.environment.x86_64-linux-9.6.2 The Ghc environment gets:
Now, if I configure this without deleting $ runhaskell --ghc-arg=-package=base --ghc-arg=-package=ngx-export-distribution Setup.hs build --ghc-options="ngx_distribution_test.hs -o ngx_distribution_test.so -threaded" my target library gets linked against Trying to skip v2-install --lib ngx-export-distribution Refresh the temporary Cabal store: $ rm -rf ~/tmp/cabal/ghc-9.6.2/ With
Looks good. Try to configure $ ADD_CABAL_STORE=$(sed -n 's/^\(package-db\)\s\+/--\1=/p' .ghc.environment.x86_64-linux-$(ghc --numeric-version))
$ runhaskell --ghc-arg=-package=base --ghc-arg=-package=ngx-export-distribution Setup.hs configure --package-db=clear --package-db=global $ADD_CABAL_STORE --prefix=/var/lib/nginx
<command line>: cannot satisfy -package-id ngx-distribution-test-0.1.0.0-c485dd0e274da10ef940cc2f882582edc5dddfe78b0fd60950b7adff131ac004
(use -v for more information) I still have to comment the current Now I'm using |
That's indeed a behavior change in cabal-install, to put far fewer packages in the env file when |
@andreabedini Finally, I implemented a simple build approach by collecting commands from here in a Makefile. Projects affected:
The latter 2 involves linking against C libraries, in which case the libraries call graph is
A typical cabal.project is -- note that ngx-export-tools-extra will be taken from Hackage;
-- to build ngx-export-tools-extra locally, add
-- ../../ngx-export-tools-extra.cabal to packages
packages: test-tools-extra-subrequest.cabal A typical Makefile is NAME := test_tools_extra_subrequest
PKGNAME := $(subst _,-,$(NAME))
PKGVER := 0.1.0.0
PREFIX := /var/lib/nginx
MACHINE := $(shell uname -m)
KERNEL := $(shell uname -s | tr A-Z a-z)
PKGDISTR := ngx-export-distribution
SRC := $(NAME).hs
LIB := $(NAME).so
STUB := $(NAME)_stub.h
DISTR := $(PKGNAME)-$(PKGVER).tar.gz
GHCVER := $(shell ghc --numeric-version)
GHCENV := .ghc.environment.$(MACHINE)-$(KERNEL)-$(GHCVER)
DEPLIBS := $(MACHINE)-$(KERNEL)-ghc-$(GHCVER)
DISTDIR := dist
DISTV2DIR := dist-newstyle
INPLACE := $(shell grep '^packages:.*\.\./\.\./ngx-export-tools-extra' \
cabal.project &>/dev/null && echo 1 || echo 0)
all: $(DISTR)
$(DISTR): $(SRC)
cabal install --lib --only-dependencies --package-env .
cabal build $(PKGDISTR)
ifeq ($(INPLACE),1)
cabal build ngx-export-tools-extra
echo "package-db $$(pwd)/$(DISTV2DIR)/packagedb/ghc-$(GHCVER)" >> \
$(GHCENV)
endif
sed -i 's/\(^package-id \)/--\1/' $(GHCENV)
runhaskell --ghc-arg=-package=base \
--ghc-arg=-package=$(PKGDISTR) Setup.hs configure \
--package-db=clear --package-db=global \
$$(sed -n 's/^\(package-db\)\s\+/--\1=/p' $(GHCENV)) \
--prefix=$(PREFIX)
. ../cabal-plan-direct-deps.sh | grep -v '.-e-ede-' >> $(GHCENV)
runhaskell --ghc-arg=-package=base \
--ghc-arg=-package=$(PKGDISTR) Setup.hs build \
--ghc-options="$(SRC) -o $(LIB) $(LINKRTS)"
install: $(DISTR)
install -d $(PREFIX)
tar xf $(DISTR) -C $(PREFIX) --no-same-owner
.PHONY: clean
clean:
rm -rf $(DISTDIR) $(DISTV2DIR) $(DEPLIBS)
rm -f $(GHCENV) $(STUB) $(NAME).hi $(NAME).o
rm -f $(LIB)
clean-all: clean
rm -f $(DISTR) With this, after typing only 2 commands $ make
$ sudo make install the libraries are ready to use. There were no problems with building and testing this so far, including builds of the host modules inplace (i.e. when I build the test code together with the basic module). Except the following: when I built ngx-export-tools-extra inplace, I got the error runhaskell --ghc-arg=-package=base \
--ghc-arg=-package=ngx-export-distribution Setup.hs build \
--ghc-options="test_tools_extra_subrequest.hs -o test_tools_extra_subrequest.so "
<command line>: cannot satisfy -package-id ede-0.3.3.0-e-ede-087231545cc80ecfefe6ed914609123982fd69780ec55708bd7a4e96b7463ea7
(use -v for more information) Module ngx-export-tools-extra depends on package ede which includes an executable
Not sure if this a bug in Cabal. Supposedly, executables should either not be configured at all when building dependencies for a library or, otherwise, not fail. Fortunately, I control the contents of the Ghc environment, and filter out the package with the . ../cabal-plan-direct-deps.sh | grep -v '.-e-ede-' >> $(GHCENV) After this, build succeeds. |
@lyokha Thanks for the detailed instructions. I had little time in the last few days so I couldn't compare my test with your instructions :-/ I uploaded it to https://gist.github.com/andreabedini/a3b012345124854c2fe58380dfe3d4ae so perhaps you can let me know if I misunderstood the problem you are trying to solve. Also, feel free to contact me in private. I'd be happy to help you with this. |
@andreabedini Great! |
Though |
What is your question?
Essentially, why? Is it by design or just a hard-to-implement thing?
Related question. Is the
runhaskell Setup.hs
interface going to be fully replaced by thecabal-install
interface? Is it regarded obsolete or a bad manner?System information
Applied to any OS and Cabal versions.
Additional context
I implemented a custom
UserHooks
which declares ahookedPrograms
with a small shell scripthslibdeps
patchingrunpath
in the target library withpatchelf
and, additionally, collecting all dependent libraries.(The code and some docs can be found at https://hackage.haskell.org/package/ngx-export-distribution.)
The script accepts some options that I can pass via
Setup.hs
, say$ runhaskell Setup.hs configure --user --hslibdeps-options="-t/var/lib/nginx/deps -ddeps -adeps"
But I cannot pass them in
cabal configure
, bothv1
andv2
.Note that
lists
hslibdeps
, whiledoesn't.
After digging into the Cabal's source code
In
defaultMainHelper
,configureCommand
gets fed withhookedPrograms
:and that is why
Setup.hs
knows abouthslibdeps
.In the
cabal-install
,configureCommand
ignoresuserHooks
. Probably, because the Cabal'sconfigureCommand
cannot be called ahead (or not called at all?). Therefore, lack of ability to configure hooked programs may appear a hard-to-implement thing. Am I right?On the other hand, the question could be of no importance if
runhaskell Setup.hs
were regarded as indispensable and not fully covered bycabal-install
command interface.The text was updated successfully, but these errors were encountered: