Troubles making simple autoconf setup for distributing a shared library - c

After having trouble extending a standard makefile for having (examples, clean, (un) install, etc) I decided to try autoconf.
The only documentation I could find is how to supply a file to be compiled and installed, but not a file that will be linked and installed in to a library location.
An example a tutorial gives me:
# what flags you want to pass to the C compiler & linker
CFLAGS = --pedantic -Wall -std=c99 -O2
LDFLAGS =
# this lists the binaries to produce, the (non-PHONY, binary) targets in
# the previous manual Makefile
bin_PROGRAMS = targetbinary1 targetbinary2 [...] targetbinaryN
targetbinary1_SOURCES = targetbinary1.c myheader.h [...]
targetbinary2_SOURCES = targetbinary2.c
.
.
targetbinaryN_SOURCES = targetbinaryN.c
Of course this seems a bit limiting as it does not expose where the Cflags (or LDFLAGS in the case I wish to have) go or if they are automatically applied.
bin_PROGRAMS can be a few other options but they only seem to be for including libraries (.la) rather than compiling one, or installing the compiled shared library to system.
Am I being a bit silly packaging my library so it can be ./configured and alike? Are there any base line guides for GNU make with this sort of packaging or informal conventions that would be easier doing this? I am looking forward to researching all my options.

I found the answer by using libtool with automake, this makes a lot more sense than handling platform-specific flags and such on my own.

Related

Qt creator pure C project

I am trying to use the Qt Creator for Ansi C program development. My problem is that I am still getting typical for g++ warnings, such as variable length array used. Is there a way to force the Qt Creator to use gcc only and never g++ at any stage (compile, link etc)?
I've needed to think about this twice in the past, when building Qt/C++ projects that were using a subproject that I wanted to compile as a C static library in QtCreator: FluidSynth and Sonivox.
QtCreator has a wizard to create a plain C application (Welcome -> New Project -> Non-Qt Project -> Plain C Application:
The compiler is not a problem; qmake does the right thing based on the suffix of the source files: gcc for *.c, and g++ for *.cpp . You only need to worry about linking, and about LFLAGS and CFLAGS when they need particular values:
QMAKE_LINK = $$QMAKE_LINK_C
QMAKE_LFLAGS_RPATH = ...
QMAKE_CFLAGS_DEBUG = ...
QMAKE_CFLAGS_RELEASE = ...

Is it possible to specify linker options from code?

I wonder if it's possible to specify a linker option from code? Compilers allow #pragma directives to suppress warnings; how far can we extend this?
(I'm considering implicitly linking on Linux systems and using the GCC compiler; you probably could adapt the answer to your OS)
No, it is impossible to specify link options in code, and notice that the linker is working on object files (not on individual functions inside them).
However, your build procedure could extract linker options from the source code. For instance, if you have a directory with many single-source programs (that is, aa.cc C++ source file compiled into aa.bin executable, bb.cc compiled into bb.bin, etc) you might have a Makefile mentioning
%.bin: %.cc
$(CXX) $(CXXFLAGS) $(shell awk /Link:/{print $2} $<) $^ -o $#
and in aa.cc a comment like:
/* the link option is
Link: -lfoo
*/
BTW, you might also have some GCC plugin which registers and handles your specific #pragma; If you use clang instead of gcc you can also have some Clang plugin; that new pragma could add something in a common Sqlite database which is later used at link time.
So you could do sophisticated things, but I would simply suggest to have your own make rules to handle your linking.

C: Compiling pre-compiled code as inline

For some rather complicated reason, I have a set of files which I would like to compile seperatly and then link, but so that the functions in one are placed inline in the second. This is because I would like them to be compiled with different flags in GCC. I know I could fix the problem by looking into how I could get around that, but I would like to know if this is possible.
EDIT 1:
If not, is it possible to compile the 'external' functions into a form of assembly that I could include in the other file. Yes crazy but also cool...
Having a quick look, this could well be an option. I guess it would be impossible to automatically compile it in, so could someone please give me a bit of information about assembly? I've only used basic ARM assembly. I've compiled to toy functions with the -S flag in GCC. How do I link registers with variables? Will they always be in the same order? The function will be highly optimised. When should I start and end the extract? Should I include .cfi_startproc at the start and .cfi_def_cfa 7, 8 at the end?#
EDIT 2:
This post details how gcc can do link-time optimisations like this with -flto. Sadly this is only available with version 4.5, which I do not have nor have the ability to install since I do not have root access of the machine I need to compile this on. Another possible solution would be to explain how I could install a different version of GCC into a folder on a unix machine.
As far as I know gcc doesn't do linktime optimizations (inlining in particular), at least with the standard ld linker (it could be that the new gold linker does it, but I really don't think so). Clang in principle should be capable of doing it, since it depends on LLVM, which supports link time optimizations (it seems that your question is gcc spacific, though).
From your question though, it seems you are looking for a a way to merge object files after compilation, not necessarily by inlining their contained functions. This can be done in multiple ways:
Archiving them into a static library with ar: e.g. ar libfoo.a obj1.o obj2.o.
Combining them together into a third relocatable object (ld's --relocatable option). gcc -Wl,--relocatable -o obj3.o obj1.o obj2.o
Putting them into a shared library (beware that this requires compiling the objects with -fPIC) e.g. gcc -shared -o libfoo.so obj1.o obj2.o
You could compile with the -c option to create a set of .o files, or even make a .so file. Then use the sequence you like in the linking phase of gcc.

Force linking a static library into a shared one with Libtool

I have a library (libfoo) that is compiled using libtool into two objects: libfoo.a and libfoo.so.
I have to create, using libtool also, another library (libbar) that will be a single shared library (libbar.so) containing all libfoo's code.
In order to do this, I have to force libbar to link against libfoo.a, and not libfoo.so.
I am in an autotools environment, so I have to solve this using standard configure.in or Makefile.am rules.
I tried several things, like in configure.in :
LDFLAGS="$LDFLAGS "-Wl,-Bstatic -lfoo -Wl,-Bdynamic"
That always results in the -Wl flags on the linking line; but -lfoo has disappeared and has been placed in an absolute-path form (/opt/foo/lib/libfoo.so) at the beginning of it.
I also tried:
LDFLAGS="$LDFLAGS "-L/opt/foo/lib libfoo.a"
or in Makefile.am:
libbar_la_LDADD = -Wl,-Bstatic -lfoo -Wl,-Bdynamic
and
libbar_la_LTLIBRARIES = libfoo.a
etc etc (with many, many variants !)
But I think that definitely I do not have knowledge enough of Autotools/Libtool to solve this alone. I have not been able to find information on the Net about it, always slightly different issues.
You could probably use a convenience library. Convenience libraries are intermediate static libraries which are not installed. You could use the prefix noinst to build one.
noinst_LTLIBRARIES = libfoo_impl.la
lib_LTLIBRARIES = libfoo.la libbar.la
libfoo_la_LIBADD = libfoo_impl.la
libbar_la_LIBADD = libfoo_impl.la
The standard way would be to build libfoo with --disable-shared. Whether to link statically or dynamically is a decision for the user to make, so there's really no way to force it as a package maintainer, but you could set the configury of libbar to fail if libfoo.so is present (I'm not sure of a clean way to do that, and believe it would be a bad idea since it really is a choice for the user.) I think the best bet is to have the user build libfoo with --disable-shared, but you can force that choice by specifying static libraries only in libfoo/configure.ac:
LT_INIT([disable-shared])
Note that if you do that, it will not be possible to build libfoo as a shared library. Perhaps that is what you want.

Portable way to link statically against one of the libraries

I am creating a utility which depends on libassuan aside other depends. While these ‘others’ provide shared libraries, libassuan comes with static one only.
libassuan comes with simple libassuan-config tool which is meant to provide CFLAGS & LDFLAGS for the compiler/linker to use. These LDFLAGS refer to the library as -lassuan.
The result of standard call of make is then:
cc -I/usr/include/libmirage -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -lmirage -lglib-2.0 -L/usr/lib64 -lassuan -o mirage2iso mirage2iso.c mirage-getopt.o mirage-wrapper.o mirage-password.o
mirage-password.o: In function `mirage_input_password':
mirage-password.c:(.text+0x1f): undefined reference to `assuan_pipe_connect'
mirage-password.c:(.text+0x32): undefined reference to `assuan_strerror'
collect2: ld returned 1 exit status
make: *** [mirage2iso] Error 1
(I've just started writing this unit and that's why there aren't more errors)
So, if I understand the result correctly, gcc doesn't want to link the app to libassuan.a.
Using -static here will cause gcc to prefer static libraries over shared which is unindented. I've seen solution suggesting using something like that:
-Wl,-Bstatic -lassuan -Wl,-Bdynamic
but I don't think it would be a portable one.
I think the best solution would be to provide full path to the static library file but libassuan-config doesn't provide much of help (all I can get from it is -L/usr/lib64 -lassuan).
Maybe I should just try to create the static library path by ‘parsing’ returned LDFLAGS and using -L for the directory name and -l for the library name — and then hoping that in all cases libassuan-config will return it like that.
What do you think about that? Is there any good, simple and portable solution to resolve the issue?
PS. Please note that although I'm referring to gcc here, I would like to use something that will work fine with other compilers.
PS2. One additional question: if package does install static library only, returning such LDFLAGS instead of full .la path can be considered as a bug?
gcc will link to libassuan.a if it doesn't find libassuan.so
It's probably the order symbols are looked up in the static library when you link. The order matters.
)
Assuming gcc can find libassuan.a and it actually provides the functions the linker complains about, try:
cc -I/usr/include/libmirage -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -lmirage -lglib-2.0 -L/usr/lib64 -o mirage2iso mirage2iso.c mirage-getopt.o mirage-wrapper.o mirage-password.o -lassuan
Since you say libassuan is under /usr/lib64 it's probably a 64 bit library, are your app and the other libraries 64 bit as well ?
Compiler's command-line options are not a portable thing. There's no standard for it. Every compiler uses its own and several can merely informally agree to comply with each other in command-line format. The most portable way for your linking is to use libassuan-config, of course. I think, it can generate not only flags for gcc, but for other compilers as well. If it can't, then no portable way exists, I suppose (other than CMake or something on higher level).
The command line to cc you shown is totally correct. If you have a static library libassuan.la and path to it is supplied to -L option, then the compiler does link against it. You can see it from its output: has it not found the static library, would it complain with error message like "can't find -lassuan". I
Moreover, if no libassuan.so is found, then compiler links against your library statically, even if you haven't used -Wl,-Bstatic stuff or -static flag.
Your problem may be in persistence of several versions of libassuan in your system. Other that that, I don't see any errors in what you've provided.
Which directory is libassuan.a in
I think the first error is not gcc doesn't want to link the app to libassuan.a it is more gcc does not know where libassuan.a . You need to pass gcc a -L parameter giving the path to libassuan.a .
e.g.
-L /home/path

Resources