I would really like to create a single binary for my application however it depends on libzmq and I am building on OSX, has anyone managed to get an external library linking correctly on a mac?
I did something similar with lua. My aproach is to pass full path to the static library to ghc. In cabal file:
if os(darwin)
ghc-options: /usr/local/lib/liblua5.1.a
According to documentation ghc will pass it to linker:
Files with other suffixes (or without suffixes) are passed straight to
the linker.
However it doesn't work if the library is used in other package which you depend on. So if you are using e.g. zeromq4-haskell package, then you need to modify it locally.
Related
I've got the following situation:
Library X is a wrapper over some code in C.
Library A depends on library X.
Library B uses Template Haskell and depends on library A.
GHC bug #9010 makes it impossible to install library B using GHC 7.6. When TH is processed, GHCi fires up and tries to load library X, which fails with a message like
Loading package charsetdetect-ae-1.0 ... linking ... ghc:
~/.cabal/lib/x86_64-linux-ghc-7.6.3/charsetdetect-ae-1.0/
libHScharsetdetect-ae-1.0.a: unknown symbol `_ZTV15nsCharSetProber'
(the actual name of the “unknown symbol” differs from machine to machine).
Are there any workarounds for this problem (apart from “don't use Template Haskell”, of course)? Maybe library X has to be compiled differently, or there's some way to stop it from loading (as it shouldn't be called during code generation anyway)?
This is really one of the main reasons that 7.8 switched to dynamic GHCi by default. Rather than try to support every feature of every object file format, it builds dynamic libraries and lets the system dynamic loader handle them.
Try building with the g++ option -fno-weak. From the g++ man page:
-fno-weak
Do not use weak symbol support, even if it is provided by the linker. By default, G++ will use weak symbols if they are available. This option exists only for testing, and should not be used by end-users; it will result in inferior code and has no benefits. This option may be removed in a future release of G++.
There is another issue with __dso_handle. I found that you can at least get the library to load and apparently work by linking in a file which defines that symbol. I don't know whether this hack will cause anything to go wrong.
So in X.cabal add
if impl(ghc < 7.8)
cc-option: -fno-weak
c-sources: cbits/dso_handle.c
where cbits/dso_handle.c contains
void *__dso_handle;
I am a cmake newbie (on Debian/Sid/Linux/x86-64)
I forked libonion on https://github.com/bstarynk/onion to enable customization of malloc with Boehm's garbage collector; see this mail thread.
I added two files there onion/src/low_util.c and onion_src/low_util.h (which is #include-d successfully in several other patched files.
It is compiled but not linked.
set(SOURCES onion.c codecs.c dict.c low_util.c request.c response.c handler.c
log.c sessions.c sessions_mem.c shortcuts.c block.c mime.c url.c ${POLLER_C}
listen_point.c request_parser.c http.c ${HTTPS_C} websocket.c ${RANDOM_C} ${SQLITE3_C})
later:
SET(INCLUDES_ONION block.h codecs.h dict.h handler.h http.h https.h listen_point.h low_util.h log.h mime.h onion.h poller.h request.h response.h server.h sessions.h shortcuts.h types.h types_internal.h url.h websocket.h ${SQLITE3_H})
MESSAGE(STATUS "Found include files ${INCLUDES_ONION}")
but when I build, my file low_util.c got compiled but not linked.
Linking C executable otemplate
CMakeFiles/opack.dir/__/__/src/onion/dict.c.o: In function `onion_dict_new':
dict.c:(.text+0x1bc): undefined reference to `onionlow_calloc'
CMakeFiles/opack.dir/__/__/src/onion/dict.c.o: In function `onion_dict_node_data_free':
dict.c:(.text+0x2ec): undefined reference to `onionlow_free'
CMakeFiles/opack.dir/__/__/src/onion/dict.c.o: In function `onion_dict_node_add':
Notice that libonion is a library (in C, providing HTTP service) and that I just want to add a low_util.c file (wrapping malloc & pthread_create etc... to make Boehm's GC happy: it is calling GC_malloc and GC_pthread_create ....) with its low_util.h header. Surprisingly, they get compiled, but do not seems to be linked. And I am not familiar with cmake and I am not familiar with how D.Moreno (the main author of libonion) has organized his cmake files.
Any clues?
Apply the following patch to make it link. The two executables which are being linked with the symbols generated from the .c file you added are missing and are added in the patch.
http://pastebin.com/mDMRiUQu
Based on what you posted, its hard to tell what could be wrong. The cake source code above says that a variable ${SOURCES} is equivalent to onion.c codecs.c dict.c low_util.c ... ${SQLITE3_C}, and a variable ${INCLUDE_ONION} is equivalent to block.h codecs.h dict.h ... ${SQLITE3_H}. You did not provide any targets or the files included in those targets.
A brief list of things that may help:
where do you define the top level library or executable? If your making a library, you will need the command add_library(). If you are making an executable, you will need the add_executable() command.
Use the command target_link_libraries() to resolve dependencies. Rather than placing all of the source files in a single library, group similar together in a single target (a target is defined by the add_* commands), and use this command to link the targets after compilation.
Use the find_package() to get any libraries which are defined on your system but not in you project. Then, link to that library using the target_link_libraries() command.
In this case, if the onion_dict_* functions are defined within the same library, your not including those files in library. When you use add_library or add_executable, ensure you add those files to the list. If the functions are within your project but not in the same library, use the target_link_libraries() command to link to the library which contains the correct files. If those commands are defined in an external library, then first find the library using find_package(), and then link to the library using target_link_libraries().
I have pdflib_py.so library i want to call from haskell. I do not have a header file. And as you can see the lib's name is not in the standard libbla form.
How do i access it from haskell ?
I followed c2hs tutorial. But it requires a header file (which i do not have) and ghc requires a library name to be in libbla format. I could of course rename pdflib_py.so to libpdfpy.so, in fact i tried it (it did not work), but that's silly to assume that you cannot access a library from haskell because of its name. I'm surely missing something here.
You can download the pdflib library from here http://www.pdflib.com/download/pdflib-family/pdflib-8/
They have bundles for c++, java, php, python etc.
Why don't i use c++ library but a python one ? Well, c++ library libbpdf.a requires to be compiled with g++. And haskell does not work with g++, I would have to write a C wrapper first. Luckily someone already did it for me. That's what a pdflib_py.so is - a c wrapper over libpdf library.
So, how do i use a library with non standard name and no header file from haskell ?
I dont think your approach is correct. You should compile pdflib with g++ into a shared library and then link against it. The C++ library they provide already uses "extern C" wrapper so the symbols exported will be excatly as you would expect them to be.
To sum up, I propose the following solution:
Download C++ bundle
Compile with g++ to make shared .so library
Use header .h file from bundle to make Haskell bindings
Link Haskell code against .so library
The problem I had is solved. I'm posting this to solicit an explanation as to why the solution actually works. I've gotten great feedback here before.
I have a legacy code base that used a very simplistic build system, and my project is to migrate that to Autotools for customization and, particularly, building shared libraries. The main library is written in C, but must also be linkable from Fortran (for legacy purposes), and is distributed with some test codes in F77. The authors organized the source code into modules...
src_module1/
src_module2/
...
testc/
testf77/
Their built the library lib/libmain.a by compiling code in the src_*/ directories and archiving the objects with ranlib.
My first approach was to build a shared library from each src_*/ separately and "link" all of these into one shared library. Using Autotools, the src_module1/Makefile.am would contain
noinst_LTLIBRARIES = libmodule1.la
libmodule1_la_SOURCES = ...
and so on for the other modules, and finally the lib/Makefile.am would need only:
lib_LTLIBRARIES = libmain.la
libmain_la_SOURCES =
libmain_la_LIBADD = $(top_srcdir)/src_module1/libmodule1.la ...
This seemed to work perfectly. However, when the code in testc/ was compiled and linked against libmain.la, a "symbols not found" error was issued.
Thinking that this was an issue with libtool or shared libraries, I tried building static only, basically changing all .la to .a and all _LTLIBRARIES to _LIBRARIES. Same problem. This time, however, noticing the error "ranlib: warning for library: libmain.a the table of contents is empty (no object file members in the library define global symbols)" when trying to link libmain.a itself.
The solution that I found seems like a hack. I did not build Makefiles for any of the src_*/ directories, but instead used only for the lib/ directory and its Makefile.am had the lines:
lib_LTLIBRARIES = libmain.la
libmain_la_SOURCES = [all sources from all ../src_modules/ ]
This worked. The compiled programs in testc/ linked against libmain.la without issue. One of the "modules" is a set of Fortran bindings that wrap other C functions in the library. Even the Fortran codes in testf77/ linked against libmain.la properly.
Could someone carefully explain what happens when libtool builds a shared library? Or even when building a static library? Why is it that several static libraries can't be linked together to make one static library? Why are symbols only available when libtool/ranlib builds the library "from sources"? And what about installing a shared/static library, i.e. moving it to the /usr/local/lib --- what happens there? The Wikipedia article on static and shared libraries isn't really detailed enough for me.
I do appreciate all efforts to make sense of my longwinded question.
What you first tried ought to work. I am using this kind of setup all the time (in a C++ context). It's also documented, and part of the Automake test suite (although maybe not with Fortran).
A libtool library that is not installable, i.e., one declared with noinst_LTLIBRARIES, is called a libtool convenience library. That noinst_ makes a big difference in what is built. Even if Libtool is configured to build shared libraries, a libtool convenience library is not actually a shared library: it is just a set of object files (compiled as PIC so that they can be latter be used in a shared library) stored in an archive. You can use a libtool convenience library anywhere using this set of objects would make sense, e.g., to build a shared library.
When multiple libtool convenience libraries are LIBADDed to an installable libtool library (such as your libmain.la), Libtool has to unpack the archives containing the objects of each convenience library and link them into the final library.
There is a trap that is worth noting here: when building a shared library out of
convenience libraries, if the _SOURCES variable is empty Automake does not know which linker to use and default to the C linker. If you want to trick Automake into using the linking rule for some specific language, you can declare a nodist_EXTRA_..._SOURCES source file that do not have to exist. (See the Libtool Convenience Libraries section of the Automake manual for an example.)
Maybe that was your problem? If you have some Fortran files in the sources of some of your modules (your description suggests these are only C files), the Fortran linker will be used to build libmain.la only if a Fortran file appears in the source files declared for that libtool library. And the C linker will be used when libmain_la_SOURCES is empty.
Otherwise, I have no idea why it didn't work.
There is an small error in your example:
libmain_la_LIBADD = $(top_srcdir)/src_module1/libmodule1.la
should be
libmain_la_LIBADD = $(top_builddir)/src_module1/libmodule1.la
because the library is not created in the source directory. However I assume this is just a typo, and you won't see the difference unless you do a VPATH build or run make distcheck.
Your second try, using _LIBRARIES without Libtool is not expected to work.
_LIBRARIES can only be used to declare static archives, and in this case _LIBADD may only contain object files, not other static archives. Unpacking an archive to reuse its objects into another archive can be tricky to do portably. Automake's answer to this problem has always been: install Libtool and use _LTLIBRARIES (Libtool can be configured to build only static libraries).
How can I force automake to create a standard shared library, instead of a libtoolized one? Normally, I'd create the abc.so which is referenced with a full path and loaded into the main program. Is there a way to force AM to do the same? If I list it as _LIBRARY, automake complains: 'abc.so' is not a standard library name; did you mean 'libabc.a'
Just to clarify: Yes, I only need .so support - no statics. And yes, I want a custom file name.
libtool is the way to go. If you want a custom name, add the -module option to _LDFLAGS, for example:
plugindir= /some/where
plugin_LTLIBRARIES= abc.la
abc_la_LDFLAGS= -module
Automake does not know how to build a shared library because there is no portable way to do so. If you want a shared library with Automake, you have to use Automake+Libtool. Note that you can easily configure libtool not to build any static library (with LT_INIT([disable-static]) in your configure.ac) by default.
A libtoolized library is a wrapper around one or more standard libraries.
You can find these libraries in ".libs" after running "make", or in "$prefix/lib" after running "make install".
On a Linux machine, you should find eventually a file called "libabc.so".
IIRC, there is nothing special about libraries created with the help of libtool, unless you link against libltdl. If you do not want to use libtool, you have the power to choose and do not care too much about portability, then you are free to use automake without libtool. I would recommend to use the power of libtool instead.
Actually, I do not even know what _LIBRARY is good for, did not found it in the the manual/Linking section.