How to specify dependency on external C library in .cabal? - windows

I maintain a library with FFI bindings on Hackage. So my Haskell library depends on the corresponding C library and its header files. Now I specify the external dependency in the .cabal file like this:
PkgConfig-Depends:
libfoo >= 1.2
And it works well for me in Linux. However, I have a user of the library who reports, that installing pkg-config on Windows is rather cumbersome, and instead he prefers
Includes:
foo.h
Extra-libraries:
foo
I'd like my library to be as easy to build as possible, and don't want to force build dependencies which are not strictly required. However, I see that Cabal manual suggests to use PkgConfig-Depends.
My questions:
Which way I should prefer for cross-platform packages?
Is it possible to write a .cabal file in such a way, that it can work with pkg-config and without?
And, by the way, is pkg-config included in the Haskell platform (I don't have a Windows machine to check right now)?

The pkg-config method is preferable because pkg-config knows where to find include and library files, which may be in nonstandard locations on some systems.
You can write the .cabal file to use both methods. Using a flag, as shown here, has the advantage that Cabal will automatically try the other flag value if the default fails. (Below example is not tested)
Flag UsePkgConfig
Description: Use pkg-config to check for library dependences
Default: True
Executable hax
if flag(UsePkgConfig)
PkgConfig-Depends: libfoo >= 1.2
else
Includes: foo.h
Extra-libraries: foo

pkg-config is not included in the Haskell Platform, nor could I imagine that it ever would be.
Usually I will use includes/Extra-libraries if they're relatively simple. But for complex packages that may have a lot of included libraries, such as gtk, it's much nicer to use pkg-config when available.
It is possible to write a .cabal file that will work with and without specific fields. Try this:
if os(windows)
Includes:
foo.h
Extra-libraries:
foo
else
PkgConfig-Depends:
libfoo >= 1.2
Also note that .cabal can run a configure script, which can help in some situations but isn't very windows-friendly.

Related

Configure compilation options and compiler autoconf

I'm working on a personal project with Rust and tcl but i still want to use the classic makefile structure.
I know that to compile multifile I just need to declare mod second on main.rs and rustc automatically connect the modules. So I use
$ rustc main.rs -o output -C debuginfo=2
Now I tried to integrate autoconf and automake because I want to make a configure script to check for tcl, rustup etc... But I don't know how to edit to compile with rustc and its options insead of cc and c options (like trying a .o that doesn't compile because they don't have a main function).
for the configure.ac i used:
AC_CONFIG_SRCDIR([source/main.rs])
AC_CONFIG_AUX_DIR(config)
# I manually checked for rustup and tclsh
AM_INIT_AUTOMAKE
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
for the Makefile.am:
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = output
SUBDIRS = sources
output_SOURCES = sources/main.rs
I have the main directory with configure.ac and Makefile.am and the sources directory with all the stuff (and also the config directory for autoconf)
Now I tried to integrate autoconf and automake because I want to make a configure script to check for tcl, rustup etc...
The configure script is the responsibility of Autoconf. It is not obligatory to use Automake together with Autoconf, and you should consider whether it would be sensible for you to use Autoconf alone. That would give you complete control over the generated Makefile, as you would write a Makefile.in directly instead of relying on Automake to do that for you. Presumably, you would write a much simpler Makefile.in than Automake generates, and that's fine.
Automake is not necessarily out of the question, but its manual has this to say about language support:
Automake currently only includes full support for C, C++ (see C++
Support), Objective C (see Objective C Support), Objective C++ (see
Objective C++ Support), Fortran 77 (see Fortran 77 Support), Fortran
9x (see Fortran 9x Support), and Java (see Java Support with gcj).
There is only rudimentary support for other languages, support for
which will be improved based on user demand.
Some limited support for adding your own languages is available via
the suffix rule handling (see Suffixes).
The referenced section about suffix rules shows how you might use such a rule to teach Automake how to build Rust programs. It might look something like this:
.rs:
$(RUSTC) $< -o $# $(AM_RUSTFLAGS) $(RUSTFLAGS)
SUFFIXES = .rs
That assumes that configure will identify the Rust compiler and export its name as RUSTC. AM_RUSTFLAGS is for defining compilation flags internally in your project (typically in your Makefile.am), and RUSTFLAGS is for the builder to add or override compilation flags at build time.
But since the compiler does not produce intermediate object files (or so I gather), I would expect that defining sources in output_SOURCES would not yield a working Makefile, and that you would probably need the name of the top-level Rust source to match the name of the wanted binary (i.e. output.rs instead of main.rs). The single-suffix rule should, then, get your binary built without any sources being explicitly specified. You would also want to name all contributing Rust sources in the EXTRA_SOURCES variable, else they would be omitted from distribution packages built via make dist.
Note, too, that the above does not define all the build dependencies that actually exist if you're building multifile programs. I would suggest doing that by adding an appropriate prerequisite-only rule, such as
output: $(output_extra_sources)
(with no recipe) in multifile cases. This will ensure that make will recognize when output needs to be rebuilt as a result of a modification to one of its sources other than output.rs.

GCC: Statically adding an external shared-object to the compilation

I have 2 C libraries:
A dependency library, compiled as a shared-object
My library - which I also want to compile as a shared-object
I want to compile my library into a shared object, but I do not want the dependency library to be loaded on runtime.
I.e. I want the dependency library to become a part of the shared-object I create from my library, so one won't have to add the dependency to LD_LIBRARY_PATH when using my library.
How can I do it with GCC?
This seems to be a XY problem: You want to add a SO statically to avoid using LD_LIBRARY_PATH. Allow me to address the latter and ignore the former. ;-)
LD_LIBRARY_PATH is a means to temporarily overwrite the library search path. Note "overwrite": The paths given in LD_LIBRARY_PATH are searched first, and if a library is found in them, the standard search paths are not considered for that library. It "knocks out" other versions that might be installed in the standard paths. It's easy to see how this could have surprising and unwanted consequences. It is a debug feature, mostly, so you are right in not wanting to use it.
There are three "correct" ways to address this:
1) Install the dependency in one of the standard search paths (/usr/lib/* / /lib/*, check /etc/ld.so.conf for a list). This will require superuser priviledges.
2) Add the path of the dependency to the standard search paths (in /etc/ld.so.conf). This will require superuser priviledges.
3) Configure the path of the dependency into your library at compilation time (-Wl,-rpath=/path/to/lib/). This will add the given path to the paths searched by this library only. It does not require any special priviledges, and has none of the disadvantages that LD_LIBRARY_PATH has.
As an aside, you can check where your binary does "find" its libraries via ldd <filename>.

Multiple version of library, how to compile with GCC/g++ whit out version number

I am working on a library in C, let us call it ninja.
Ninja depends upon some under laying libraries (which we also provide) (e.g jutsu, goku, bla).
These are all placed in a shared library folder, let us say /usr/lib/secret/.
The clients whom are using this project wants to be able to havde ninja version 1 and 2 laying side by side, this it not so hard. The problem comes when ninja 1 dependes up on for instance jutsu 1 and ninja 2 depends upon jutsu 3. How the h... do we/I do so so that when installing ninja from our package repository. It knows the correct version of jutsu. Of course the rpm/deb package should depend upon the correct version of the jutsu package.
so what we want is when, we execute for instance zypper in ninja. and it installs and compiles on the system, it knows which jutsu library to take with out been given a version number.
So we in the make file don't have to do this:
gcc ninja.c -o ninja -L /usr/local/lib/secret/ -l jutsu_2
But just
gcc ninja.c -o ninja -L /usr/local/lib/secret/ -l jutsu
NOTE: I know it is random to use ninja and so on, but I am not allowed to publish the real library names
You want to use an SONAME. Describing all the steps necessary is probably too large a scope for a good StackOverflow answer, but I can give an overview and point to some documentation.
An SONAME is a special data field inside a shared library. It is typically used to indicate compatibility with other versions of the same library; if two different versions of a shared library have the same SONAME, the linkers will know that either one can fill the dependency on that library. If they have a different SONAME, they can't.
Example: I have libdns88 and libbind-dev version 1:9.8.4.dfsg.P1-6+nmu2+deb7u1 installed on a Debian wheezy system. I build a binary called samurai with -ldns. The GNU linker finds "libdns.so" in my library search path and dynamically links samurai with it. It reads the SONAME field from libdns.so (which is a symlink to libdns.so.88.1.1). The SONAME there is "libdns.so.88".
$ objdump -p /usr/lib/libdns.so | grep SONAME
SONAME libdns.so.88
The libdns developers (or maybe packagers) chose that SONAME to indicate that any version 88.* of libdns is expected to be binary compatible with any other version 88.*. They use that same SONAME for all versions with a compatible ABI. When the ABI had a change, they changed the SONAME to libdns.so.89, and so on. (Most well-managed libraries don't change their ABI that often.)
So the library dependency written into the samurai binary is just libdns.so.88. When I run samurai later, the dynamic linker/loader looks for a file called "libdns.so.88" instead of just "libdns.so".
Also by convention, the name of an rpm or deb package should change when the SONAME of the library contained changes. That's why there is a libdns88 package separate from the libdns100 package, and they can be installed side by side without interfering with each other. My samurai package will have a dependency on "libdns88" and I can expect that any package called libdns88 will have a compatible ABI to the one I built it against. Tools like dpkg-shlibdeps make it simple to create the right shared library package dependencies when SONAMEs and versioned symbols are used.
http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

Use headers and libraries from different folders

I have two GTK builds on my Mac, an X11 one with headers and a Quartz one without. I can compile Vala code for X11 just fine, but how do I use the Quartz libraries?
This is probably a C question, but I only ever used that toolchain through valac.
When using valac, it gets the appropriate compile and link flags from pkg-config based on the --pkg flags. You can see what is being included with pkg-config --cflags --libs gtk+-2.0. If you wish to change this you have two opions:
Use valac -C to only produce C files and manage the compilation and linking yourself.
Set export PKG_CONFIG_PATH=/usr/lib/pkgconfig:/sw/lib/pkgconfig or whatever collection of directories to get your packages coming in the desired order.
I'm not quite sure where your GTK+ installs are located, presumably in a MacPorts tree.

using agg (antigrain) library and getting gsl shell working

My main aim is to get the GSL Shell working on my OSX 10.7 system. So far I have the correct version of lua with the correct patches running. I also have a working version of GSL which compiles and runs example programs. I can build agg perfectly and also run their example programs by running make in the macosx_sdl folder.
My first question is how on earth do I create my own project with agg? I know that you are supposed to simply add the files to your project file and go, but this does not seem to want to compile for me. Is it simply a case of adding the include directory and the libagg.a?
Finally, how do I build gsl shell? Currently it complains about the agg-plot folder a lot, so where do I put the agg files to make this build, then when i've done it where do I place the agg files so that the lua scripts can get to them?!
Hope someone can help!
In general to use the AGG library you need to make sure that the compiler is able to find the headers files and, during the linking, the libraries, either in form of a static or dynamic libraries.
To make the headers files and the libraries available you need to take into account the system that is used to build the software. If a traditional makefile sistem is used you need to add some flags to make sure that the headers file can be found. This can be achieved by adding into the makefile something like:
CFLAGS += -I/path/to/agg/headers
and for the linker:
LIBS += -L/path/to/agg/library -lagg -lm
In the specific case of GSL Shell 1.1 the file "make-packages" is used in the Makefile to configure the required packages. You can add here the flags required to locate the AGG library:
AGG_INCLUDES = -I/usr/include/agg2
AGG_LIBS = -lagg -lX11 -lpthread -lsupc++
you should just modify the path provided with the "-I" option and, in AGG_LIBS, add an option "-L/path/to/agg/library" to specify the path where the AGG libraries are located.
Please note also that the agg libraries depends on other libraries. For example on linux it needs at least the X11 library. The libraries supc++ may be needed if the linking is made by invoking gcc instead of g++ because if gcc is used the C++ runtime libraries are not included.

Resources