How to set cabal extra dirs for all packages in a sandbox - haskell

I'm currently working on a Haskell project that uses lots of native code. This means that include files and libraries have to be accessible to cabal. I'm doing that by --extra-lib-dirs and --extra-include-dirs command-line flags.
I'm also using cabal sandboxes feature to avoid global dependency hell.
The trouble is that cabal often needs to reinstall some of my packages and thus rebuilds them, which requires native include files and libraries. So I have to specify --extra-lib-dirs and --extra-include-dirs at the command line when building any of my packages at all, even for those that don't require native code, which is very annoying.
I know I can use extra-lib-dirs and extra-include-dirs in .cabal files, but that ones don't allow relative paths and I prefer not committing files with absolute paths on my computer to a centralized repository.
So I wonder, is there any way to add directories to extra-lib-dirs or extra-include-dirs for all the packages in a sandbox? Or maybe globally for a computer?

You can simply create a local cabal.config in the directory where your sandbox is located. (Don't modify cabal.sandbox.config, as that file is auto-generated.)

Related

How to properly build package from sources

I'm using ubuntu 18.04.
I want to modify and build a project and install it as a package. For example gstreamer1.5.
So I clone repo, modify code and use ./autogen.sh and make install in project folder. Why don't I see it in apt list then? Also there is no files in /usr/lib/x86_64-linux-gnu/gstreamer-1.5/.
The reason why I want it to behave as the original package is becase I want to build another project that uses it (kurento media server). So I just want to remove some plugins I don't need that use another packages as deps I cannot use.
apt list is from the Linux distribution. You custom made things won't appear there magically.
If you make install from your custom tree your libraries and plugins will land in /usr/local/lib/.. (note the local path). You may have some control over it by setting the prefix path. Just be careful you don't break you system by overwriting with broken libraries.

Standard linux `make install` of an application, linking to correct libs

I am working on an application that consists of a number of binaries, scripts, and libs. Under development this far, I've built and run inside my repository:
myapp:
bin/
include/
lib/
scripts/
src/
Makefile
src/ contains code for several modules, either libs or binaries. Each have their makefiles.
Running make from myapp/ sets up environment variables for target install directories, then recursively runs make install (which uses the environment variables) for each submodule in src/.
This installs the binaries, includes, and libs in the relevant subdirectory of myapp/, since that is how the environment variables are setup.
Now I am reaching a time where I want to install system-wide, presumably in /usr/local. I am also interested in keeping the ability to build and install locally in myapp/ while developing. It is convenient to be able to run the binaries in myapp/bin/ without having to install them system wide first.
My first plan was to keep the default make target creating the installables (binaries, libs, includes, scripts) under myapp, then have a new install target in myapp/Makefile which would copy these installables in /usr/local/ (requiring sudo).
My problem is that under development, the binaries need to know where the libs are. I have been linking to the libs in myapp/lib/ with -Wl,-rpath=/path/to/myapp/lib. However this will not be appropriate with system installed binaries, these should refer to /usr/local/lib/ instead.
I can see several solutions, but none very good:
make install rebuilds instead of just copying, with the environment variable target directories set in /usr/local instead of myapp/. Drawback: I think this will require sudo for the whole rebuild process, instead of only for the install.
remove linking with -Wl,-rpath, and instead set LD_LIBRARY_PATH to include myapp/lib while in development, but not otherwise. Apparently this is considered harmful. I could easily forget to unset it when I want to run system wide, and the local libs would wrongly be used.
remove linking with -Wl,-rpath, and require to install the libs system wide before building the binaries locally in myapp/. This is cumbersome, I would like to keep the ability to clone my repo and build locally in one step.
Others have probably had this very problem, and I would like to know if there is a standard solution.
This was interesting, but does not deal with my issue of linking libs.

how to make cabal sandbox aware of (installed) packages in other locations?

When I have a sandbox, it seems cabal install ignores packages in $HOME/.ghc/x86_64-linux-7.8.4/package.conf.d.
How can I configure the sandbox such that these packages become visible?
I am seeing a vague reference to --package-db=db in https://www.haskell.org/cabal/users-guide/installing-packages.html#sandboxes-advanced-usage
but I understand neither how nor when to use it. (with sandbox init? configure? install? none seems to work - none gives any error message either.)
I know about add-source but my question refers to installed packages.
The whole point of the sandbox is that it ignores your local package database.
If you want to share installations across many sandboxes, you may install to the global database; but then you should be very careful, as fixing the badness of a broken package is much more difficult. Keep it to really core packages that you expect to be widely shared across many, many projects -- not just the half dozen you're stressing out about right now for your job.
Alternately, you may share one sandbox between the builds of many packages; simply set the CABAL_SANDBOX_CONFIG variable to an absolute path pointing to the appropriate cabal.sandbox.config file. This is significantly safer, and much more flexible, as you can choose how widely your installed packages are shared (and in bad cases, simply nuke the sandbox and start over).
Here is something you can try - copy (or symlink) the files from ~/.ghc/{arch-os-ghc-version}/package.conf.d to the sandbox's {arch-os-ghc-version}-packages.conf.d directory.
There is a question about the package.cache file. The following procedure seems to be a safe way to proceed:
Start with an empty sandbox
Copy the package.conf.d files from ~/.ghc to the sandbox (including package.cache)
Add packages to the sandbox via cabal install --only-dependencies
I don't know if the package.cache file is required or if there is a way to rebuild it.
One disadvantage is that cabal install --only-deps seems to reinstall broken packages in the sandbox even if they are not required by your application. Maybe there is work-around for this.

How to manage development and installed versions of a shared library?

In short: This question is basically about telling Linux to load the development version of the .so file for executables in the dev directory and the installed .so file for others.
In long: Imagine a shared library, let's call it libasdf.so. And imagine the following directories:
/home/user/asdf/lib: libasdf.so
/home/user/asdf/test: ... perform_test
/opt/asdf/lib: libasdf.so
/home/user/jkl: ... use_asdf
In other words, you have a development directory for your library (/home/user/asdf) and you have an installed copy of its previous stable version (/opt/asdf) and some other programs using it (/home/user/jkl).
My question is, how can I tell Linux, to load /home/user/asdf/lib/libasdf.so when executing /home/user/asdf/test/perform_test and to load /opt/asdf/lib/libasdf.so when executing /home/user/jkl/use_asdf? Note that, even though I specify the directory by -L during link, Linux uses other methods (for example /ect/ld.so.conf and $LD_LIBRARY_PATH) to find the .so file.
The reason I need such a thing is that, of course the executables in the development directory need to link with the latest version of the library, while the other programs, would want to use the stable version.
Putting ../lib in the library path doesn't seem like a secure idea, not to mention not completely correct since you can't run the test from a different directory.
One solution I thought about is to have perform_test link with libasdf-dev.so and upon install, copy libasdf-dev.so as libasdf.so and have others link with that. This solution has one problem though. Imagine the following additional directory:
/home/user/asdf/tool: ... use_asdf_too
Which gets installed to:
/opt/asdf/bin: use_asdf_too
In my solution, it is unknown what use_asdf_too should be linked against. If linked against libasdf.so, it wouldn't work properly if invoked from the dev directory and if linked against libasdf-dev.so, it wouldn't work properly if invoked from the installed location.
What can I do? How is this managed by other people?
Installed shared objects usually don't just end with ".so". Usually they also include their soname, such as libadsf.so.42.1. The .so file for development is typically a symlink to a fully-versioned filename. The linker will look for the .so file and resolve it to the full filename, and the loader will then load the fully-versioned library instead.

How to to build src from a CygPort?

I have a question about the structure of the source code from a cygport package.
Here is the contents of a Cygports source file:
the actual source bundle for the project (tar.gz, tar.bz2, etc.)
the any number of *.patch files.
a .cygport file
I am trying to build gedit-3.4.2 from cygports repository.
How does the .cygport file help me run the proper options in the ./configure ?
For instance, in gedit if i don't specify --disable-spell it won't proceed due to error. How do I get the list of ./configure options that were used to build the project when the cygport was built?
Is there some way we can use the cygport executable to build the cygport and change the prefix too?
Here is the contents of gedit-3.4.2-1.cygport:
inherit python gnome2
DESCRIPTION="GNOME text editor"
PATCH_URI="3.4.2-cygwin.patch"
DEPEND="gnome-common gtk-doc
girepository(Gtk-3.0)
pkgconfig(enchant)
pkgconfig(gtksourceview-3.0)
pkgconfig(libpeas-gtk-1.0)"
PKG_NAMES="${PN} ${PN}-devel"
PKG_HINTS="setup devel"
gedit_CONTENTS="--exclude=gtk-doc --exclude=libgedit* etc/ usr/bin/ usr/lib/gedit/ ${PYTHON_SITELIB#/} usr/share/"
gedit_devel_CONTENTS="usr/include/ usr/lib/gedit/libgedit* usr/lib/pkgconfig/ usr/share/gtk-doc/"
DIFF_EXCLUDES="*.desktop.in *.schemas.in *-marshal.h"
CYGCONF_ARGS="--libexecdir=/usr/lib --enable-python"
KEEP_LA_FILES="none"
EDIT Someone from Cygwin Ports mailing list said:
"The configure options are
--libexecdir=/usr/lib --enable-python
Which is from CYGCONF_ARGS."
Here is the contents of a Cygports source file:
You'd do better to think of it as a Cygwin package source file.
cygport is simply a tool for automating the creation of Cygwin binary and source packages. It is the primary tool available, but unlike with some other packaging systems, there's really nothing forcing you to use it. It is quite possible to build a Cygwin package entirely by hand, since it is really nothing more than a tarball that Cygwin's setup.exe can blindly unpack into the Cygwin root directory (typically c:\cygwin) with the expectation that this will put the package's files in sensible locations.
Before cygport existed, people did build their own ad hoc packaging systems. Many Cygwin package maintainers still use these tools they created. (Yours truly included; two of my three packages use cygport, but the third still uses a custom build system.)
Ultimately, you want to read the cygport manual, in /usr/share/doc/cygport/manual.html.
(Yes, I know, "RTFM" answers are frowned on here. But, as one who currently maintains two cygport based packages in the official Cygwin package repository, please believe me when I tell you that the manual is still the single best resource available on this topic.)
How does the .cygport file help me run the proper options in the ./configure ?
As you found out through other resources, you'd first need to edit the CYGCONF_ARGS value in the .cygport file.
The simplest possible step after that is cygport gedit-3.4.2-1.cygport all. That attempts to rebuild all the binary packages in a single step. It also builds a new source package containing updated .cygport and patch files.
If something breaks in the all build process, it is usually faster to switch to using the sub-commands contained by all instead of completely restarting the process. The all step just runs prep, compile, install, package, and finish for you, in that order. For instance, if all fails during the compilation step, there's probably no need to repeat the prep step.
(It is exceptionally uncommon for cygport or a sane build system to wreck the build tree, forcing you to re-run prep. Far more commonly, you end up needing to re-do prep when you manually wreck the build tree while trying to get a new package to build for the first time and need to start over.)
For instance, in gedit if i don't specify --disable-spell it won't proceed due to error.
You can probably fix that by installing the libaspell-devel package from the official Cygwin package repository with setup.exe.
Personally, I wouldn't disable any feature unless it meant installing unofficial packages, such as those from the Cygwin Ports project.[*] It is nice to have Cygwin Ports repository, but because it contains so many packages, installing one can end up creating an "install the world" situation: package A depends on packages B, C and D, and C depends on E, F, G, H, and G depends on I, J, K, and... Dependency hierarchies within the Cygwin package repo tend to be flatter and narrower than those in the Cygports repo.
Is there some way we can use the cygport executable to build the cygport and change the prefix too?
You have guessed that you just add --prefix=/my/private/program/tree to CYGCONF_ARGS, I trust.
[*] If you are feeling confused about "Cygwin Ports" and cygport, the naming similarity is no coincidence. cygport is a tool created by Yaakov Selkowitz for himself when creating the Cygwin Ports package repository. Later, it became popular enough among other Cygwin package maintainers that it pushed out most of the competing build systems.

Resources