Discussion:
Using autoconf for a shared library
Thomas Nyberg
2016-08-15 16:44:00 UTC
Permalink
Hello,

I've been reading the manuals for autoconf/automake and have been unable
to get a setup working correctly with autoconf. I've written up a toy
shared library and right now the Makefile has a rule to install the
library directly to `/usr/local`. All I really want from autoconf is to
be able to have `--prefix` user-configurable. I figured it was better to
use autoconf/automake than reinvent the wheel, but I'm totally unable to
get it working.

Does anyone here know a source for a very simple example of what is
needed (configure.ac/Makefile.in) to get this type of setup working?
I've been reading both manuals, but I can't figure it out. Maybe someone
here can even immediately see how to do this.

I'm attaching an extremely simplified version of a shared library setup.
I'm also pasting the text of the files in below in case you just want to
read directly (instead of extracting something from a random person on
the internet). Basically if you run `make` it compiles a shared library
for you with publicly exports one function called `public_func`. If you
run `make test` it will test it by setting the current directory to
LD_LIBRARY_PATH. You can install it by running `make install` and then
ldconfig (though I doubt you want to...). This is the repo structure:

.
├── include
│ └── public.h
├── Makefile
├── src
│ ├── private.c
│ ├── private.h
│ └── public.c
└── test.c

Here are the files:

include/public.h
-----------------------------------
int public_func(void);
-----------------------------------

src/public.h
-----------------------------------
#include <private.h>


int public_func(void) {
return private_func();
}
-----------------------------------

src/private.h
-----------------------------------
int private_func(void);
-----------------------------------

src/private.c
-----------------------------------
#include <private.h>


int private_func(void) {
return 1;
}
-----------------------------------

test.c
-----------------------------------
#include <public.h>
#include <stdio.h>


int main(void) {
printf("public value: %d\n", public_func());
return 0;
}
-----------------------------------

Makefile
-----------------------------------
so = libpublic.so
solinkname = -lpublic

install_target = /usr/local

srcs = $(wildcard src/*.c)
objs = $(patsubst %.c,%.o,$(srcs))

includes = include/public.h
installed_includes = $(addprefix $(install_target)/,$(includes))

cc = gcc
cflags = -c -g -fPIC -Wall -Wextra -Wfatal-errors -pedantic-errors
privateincludedirs = -Isrc
publicincludedirs = -Iinclude
ldflags = -shared -Wl,-soname,$(so)


all: $(so)

$(so): $(objs)
$(cc) $(ldflags) $(objs) -o $(so)

%.o:%.c
$(cc) $(cflags) $(privateincludedirs) -c -o $@ $<

clean:
rm -f *.o src/*.o *.so test

install:
cp -v $(includes) $(install_target)/include
cp -v $(so) $(install_target)/lib
-----------------------------------

Thanks for any help!

Cheers,
Thomas
Thomas Nyberg
2016-08-15 16:29:40 UTC
Permalink
Hello,

I've been reading the manuals for autoconf/automake and have been unable
to get a setup working correctly with autoconf. I've written up a toy
shared library and right now the Makefile has a rule to install the
library directly to `/usr/local`. All I really want from autoconf is to
be able to have `--prefix` user-configurable. I figured it was better to
use autoconf/automake than reinvent the wheel, but I'm totally unable to
get it working.

Does anyone here know a source for a very simple example of what is
needed (configure.ac/Makefile.in) to get this type of setup working?
I've been reading both manuals, but I can't figure it out. Maybe someone
here can even immediately see how to do this.

I'm attaching an extremely simplified version of a shared library setup.
I'm also pasting the text of the files in below in case you just want to
read directly (instead of extracting something from a random person on
the internet). Basically if you run `make` it compiles a shared library
for you with publicly exports one function called `public_func`. If you
run `make test` it will test it by setting the current directory to
LD_LIBRARY_PATH. You can install it by running `make install` and then
ldconfig (though I doubt you want to...). This is the repo structure:

.
├── include
│ └── public.h
├── Makefile
├── src
│ ├── private.c
│ ├── private.h
│ └── public.c
└── test.c

Here are the files:

include/public.h
-----------------------------------
int public_func(void);
-----------------------------------

src/public.h
-----------------------------------
#include <private.h>


int public_func(void) {
return private_func();
}
-----------------------------------

src/private.h
-----------------------------------
int private_func(void);
-----------------------------------

src/private.c
-----------------------------------
#include <private.h>


int private_func(void) {
return 1;
}
-----------------------------------

test.c
-----------------------------------
#include <public.h>
#include <stdio.h>


int main(void) {
printf("public value: %d\n", public_func());
return 0;
}
-----------------------------------

Makefile
-----------------------------------
so = libpublic.so
solinkname = -lpublic

install_target = /usr/local

srcs = $(wildcard src/*.c)
objs = $(patsubst %.c,%.o,$(srcs))

includes = include/public.h
installed_includes = $(addprefix $(install_target)/,$(includes))

cc = gcc
cflags = -c -g -fPIC -Wall -Wextra -Wfatal-errors -pedantic-errors
privateincludedirs = -Isrc
publicincludedirs = -Iinclude
ldflags = -shared -Wl,-soname,$(so)


all: $(so)

$(so): $(objs)
$(cc) $(ldflags) $(objs) -o $(so)

%.o:%.c
$(cc) $(cflags) $(privateincludedirs) -c -o $@ $<

clean:
rm -f *.o src/*.o *.so test

install:
cp -v $(includes) $(install_target)/include
cp -v $(so) $(install_target)/lib
-----------------------------------

Thanks for any help!

Cheers,
Thomas
Thomas Nyberg
2016-08-15 16:29:13 UTC
Permalink
Hello,

I've been reading the manuals for autoconf/automake and have been unable
to get a setup working correctly with autoconf. I've written up a toy
shared library and right now the Makefile has a rule to install the
library directly to `/usr/local`. All I really want from autoconf is to
be able to have `--prefix` user-configurable. I figured it was better to
use autoconf/automake than reinvent the wheel, but I'm totally unable to
get it working.

Does anyone here know a source for a very simple example of what is
needed (configure.ac/Makefile.in) to get this type of setup working?
I've been reading both manuals, but I can't figure it out. Maybe someone
here can even immediately see how to do this.

I'm attaching an extremely simplified version of a shared library setup.
I'm also pasting the text of the files in below in case you just want to
read directly (instead of extracting something from a random person on
the internet). Basically if you run `make` it compiles a shared library
for you with publicly exports one function called `public_func`. If you
run `make test` it will test it by setting the current directory to
LD_LIBRARY_PATH. You can install it by running `make install` and then
ldconfig (though I doubt you want to...). This is the repo structure:

.
├── include
│ └── public.h
├── Makefile
├── src
│ ├── private.c
│ ├── private.h
│ └── public.c
└── test.c

Here are the files:

include/public.h
-----------------------------------
int public_func(void);
-----------------------------------

src/public.h
-----------------------------------
#include <private.h>


int public_func(void) {
return private_func();
}
-----------------------------------

src/private.h
-----------------------------------
int private_func(void);
-----------------------------------

src/private.c
-----------------------------------
#include <private.h>


int private_func(void) {
return 1;
}
-----------------------------------

test.c
-----------------------------------
#include <public.h>
#include <stdio.h>


int main(void) {
printf("public value: %d\n", public_func());
return 0;
}
-----------------------------------

Makefile
-----------------------------------
so = libpublic.so
solinkname = -lpublic

install_target = /usr/local

srcs = $(wildcard src/*.c)
objs = $(patsubst %.c,%.o,$(srcs))

includes = include/public.h
installed_includes = $(addprefix $(install_target)/,$(includes))

cc = gcc
cflags = -c -g -fPIC -Wall -Wextra -Wfatal-errors -pedantic-errors
privateincludedirs = -Isrc
publicincludedirs = -Iinclude
ldflags = -shared -Wl,-soname,$(so)


all: $(so)

$(so): $(objs)
$(cc) $(ldflags) $(objs) -o $(so)

%.o:%.c
$(cc) $(cflags) $(privateincludedirs) -c -o $@ $<

clean:
rm -f *.o src/*.o *.so test

install:
cp -v $(includes) $(install_target)/include
cp -v $(so) $(install_target)/lib
-----------------------------------

Thanks for any help!

Cheers,
Thomas
Basin Ilya
2016-08-15 19:11:04 UTC
Permalink
See attached tarball. Unpack,
./autoreconf -fi
./configure
make
make check
make install DESTDIR=`pwd`/../library-dst


From your makefile:

"so = libpublic.so"
"lib_LTLIBRARIES = libpublic.la"

"ldflags = -shared -Wl,-soname,$(so)"
automatic (soname will be "*.so.0")

"solinkname = -lpublic"
"LDADD = src/libpublic.la"

"install_target = /usr/local"
"install:"
"uninstall:"
automatic


"srcs = $(wildcard src/*.c)"
"libpublic_la_SOURCES = private.c public.c ..."

"objs = $(patsubst %.c,%.o,$(srcs))"
automatic

"includes = include/public.h"
"AM_CPPFLAGS = -I${top_srcdir}/include"


"installed_includes = $(addprefix $(install_target)/,$(includes))"
"include_HEADERS = ../include/public.h"

"cc = gcc"
automatic



"-c , -fPIC"
automatic


"-g -O3 -Wall -Wextra -Wfatal-errors -pedantic-errors"
optionally provide as configure arg: CFLAGS="..."


"privateincludedirs = -Isrc"
not needed, because "src" is current dir during compilation

"publicincludedirs = -Iinclude"
"AM_CPPFLAGS = -I${top_srcdir}/include"



"LD_LIBRARY_PATH="
not needed. Test binaries are built with RPATH


"test:"
"TESTS = test"
"check_PROGRAMS = test"
...

"test" stdout goes to "test.log"
Post by Thomas Nyberg
Hello,
I've been reading the manuals for autoconf/automake and have been unable
to get a setup working correctly with autoconf. I've written up a toy
shared library and right now the Makefile has a rule to install the
library directly to `/usr/local`. All I really want from autoconf is to
be able to have `--prefix` user-configurable. I figured it was better to
use autoconf/automake than reinvent the wheel, but I'm totally unable to
get it working.
Does anyone here know a source for a very simple example of what is
needed (configure.ac/Makefile.in) to get this type of setup working?
I've been reading both manuals, but I can't figure it out. Maybe someone
here can even immediately see how to do this.
I'm attaching an extremely simplified version of a shared library setup.
I'm also pasting the text of the files in below in case you just want to
read directly (instead of extracting something from a random person on
the internet). Basically if you run `make` it compiles a shared library
for you with publicly exports one function called `public_func`. If you
run `make test` it will test it by setting the current directory to
LD_LIBRARY_PATH. You can install it by running `make install` and then
.
├── include
│ └── public.h
├── Makefile
├── src
│ ├── private.c
│ ├── private.h
│ └── public.c
└── test.c
include/public.h
-----------------------------------
int public_func(void);
-----------------------------------
src/public.h
-----------------------------------
#include <private.h>
int public_func(void) {
return private_func();
}
-----------------------------------
src/private.h
-----------------------------------
int private_func(void);
-----------------------------------
src/private.c
-----------------------------------
#include <private.h>
int private_func(void) {
return 1;
}
-----------------------------------
test.c
-----------------------------------
#include <public.h>
#include <stdio.h>
int main(void) {
printf("public value: %d\n", public_func());
return 0;
}
-----------------------------------
Makefile
-----------------------------------
so = libpublic.so
solinkname = -lpublic
install_target = /usr/local
srcs = $(wildcard src/*.c)
objs = $(patsubst %.c,%.o,$(srcs))
includes = include/public.h
installed_includes = $(addprefix $(install_target)/,$(includes))
cc = gcc
cflags = -c -g -fPIC -Wall -Wextra -Wfatal-errors -pedantic-errors
privateincludedirs = -Isrc
publicincludedirs = -Iinclude
ldflags = -shared -Wl,-soname,$(so)
all: $(so)
$(so): $(objs)
$(cc) $(ldflags) $(objs) -o $(so)
%.o:%.c
rm -f *.o src/*.o *.so test
cp -v $(includes) $(install_target)/include
cp -v $(so) $(install_target)/lib
-----------------------------------
Thanks for any help!
Cheers,
Thomas
_______________________________________________
Autoconf mailing list
https://lists.gnu.org/mailman/listinfo/autoconf
Peter Johansson
2016-08-16 00:44:39 UTC
Permalink
Hi Thomas,
Post by Thomas Nyberg
I've been reading the manuals for autoconf/automake and have been
unable to get a setup working correctly with autoconf. I've written up
a toy shared library and right now the Makefile has a rule to install
the library directly to `/usr/local`. All I really want from autoconf
is to be able to have `--prefix` user-configurable. I figured it was
better to use autoconf/automake than reinvent the wheel, but I'm
totally unable to get it working.
For shared libraries and Automake, I'd have a look at libtool. Start
with the chapter in the Automake manual

https://www.gnu.org/software/automake/manual/automake.html#A-Shared-Library

Cheers,
Peter
Thomas Nyberg
2016-08-16 13:56:29 UTC
Permalink
It is a bit overkill, but: when I start a new project I copy this
<https://github.com/marcomaggi/cctemplate>
and customise it. It is just a template for a C language library
project, it does nothing in itself. You just read the REAMDE, then you
go around substituting the string "cctemplate" with your project's name,
renaming files to your liking both in the directories and in the
"Makefile.am" template.
C source files are under the "src" directory; test files are under the
"tests" directory. Documentation in Texinfo format is under the "doc"
directory. If you need some help with the customisation, drop me an
email.
HTH
Thanks so much! I've now received three great messages, but only sent
individual thank you responses, but this time I figure I should spam the
list just so that it's clear that my problem has been solved. For anyone
looking in the archives, the three responses are all very helpful.

Marco this is great I'll take a look at this. I started running with the
setup that Basin Ilya sent me and I'll stick with that for now, but soon
I'm going to sit down and really try to grok all the great info I've
received. Thanks so much!

Cheers,
Thomas

Loading...