
Building and Linking Libraries in C - vyuh
https://www.cs.swarthmore.edu/~newhall/unixhelp/howto_C_libraries.html
======
pdkl95
> LD_LIBRARY_PATH

While this works, it's generally a bad idea to depend on LD_LIBRARY_PATH. This
type of environment override should generally be left as a tool for sysadmins
and other integration/workaround needs.

Instead, you can bake the library search path into the executable with ld's
"-rpath" option.

    
    
        gcc -o foo -Wall -Wl,-rpath,/lib/search/dir
    

> -shared

Building a shared library may also require building position independent
object files. (CFLAGS += -fPIC). If the library is being distributed, it is
also a good idea to set the soname[1].

This can get complicated very quickly, so it's probably better to let
something like libtool[2] handle building and managing the library. (Autotools
is a lot easier[2] to use that its reputation suggests. Way too many
configure.ac scripts are a cargo cult mess)

[1] [http://tldp.org/HOWTO/Program-Library-HOWTO/shared-
libraries...](http://tldp.org/HOWTO/Program-Library-HOWTO/shared-
libraries.html#AEN95)

[2]
[https://autotools.io/libtool/index.html](https://autotools.io/libtool/index.html)

[3]
[https://autotools.io/whosafraid.html](https://autotools.io/whosafraid.html)

~~~
adekok
I've used libtool for 20+ years, and found it to be opaque, baroque, slow,
incomprehensible, and just plain broken.

Previous comments:
[https://news.ycombinator.com/item?id=12253252](https://news.ycombinator.com/item?id=12253252)

~~~
tannhaeuser
Wish I could upvote your more.

The jlibtool I know (and that you seem to have implemented) however is a drop-
in replacement for libtool to merely speed up libtool (rather than tar-and-
feather libtool out of existence as it deserves to) isn't it? It seems to be
used by apache httpd last I checked.

Anyway, cudos to those who do something about it. I tried a couple years ago,
but haven't followed through.

~~~
adekok
I took jlibtool from Apache. I don't think they're using it any more.

I fixed a _lot_ of bugs. It's now a 95% drop-in replacement for libtool. The
builds are MUCH faster than with libtool.

------
saticmotion
Increasingly popular are the "single header libraries", which were popularised
by Sean Barrett[0]. It's as simple as downloading the header, putting it
somewhere in your tree and #including it where you need it. It's especially
useful for redistributing libraries, but I've also found it useful to create
these in my own projects.

[0][https://github.com/nothings/stb](https://github.com/nothings/stb)

~~~
flukus
Doesn't this hurt compile times and increase exe size?

~~~
saticmotion
I tend to use a single compilation unit, and use plain C. For a 50k line
project I have build times of 1-1.2sec. On top of that I'm also linking to
opengl, windows.h and a couple of headers in the standard lib.

~~~
chj
The speed up is easy to explain. Instead of launching gcc 50 times, it's now
once for all.

~~~
saticmotion
Exactly :) I come from a .net background, where compile times are kinda bad
compared to what I get in C. I had also heard of big C++ projects that could
take more than 30 mins to build. So I was always scared to move to native
code. Until I learned the single compilation unit trick! And if compile times
were to get slow again, there are many more ways to bring it down even
further,

~~~
flukus
Since when are .Net compile times worse than c? Csc compiles extremely fast,
most long compile times are caused by msbuild doing... not much at all really.

------
Annatar
_If you create your own shared object files and do not install them in
/usr/lib, then you need to set your LD_LIBRARY_PATH environment variable so
that the runtime linker can find them and load them at run time._

A better approach would be to use the $ORIGIN linker keyword (-R works in gcc
by special dispensation for compatibility with every other linker in
existence, and is portable, as opposed to -rpath):

    
    
      gcc -L/home/newhall/lib -R'$ORIGIN:$ORIGIN/../lib' -lmine -o myprog myprog.c
    

because unfortunately the $ORIGIN keyword includes the $, to embed it
effectively into Makefiles and shell scripts, the following is needed in the
environment:

    
    
      O='$$O'; export O
      ORIGIN='$ORIGIN'; export ORIGIN
    

this way, both shell and make will expand $ORIGIN to $ORIGIN, without the need
to recursively escape anything. $ORIGIN linker keyword is supported by GNU ld,
Solaris / illumos ld, and HP-UX's ld.

[https://blogs.oracle.com/ali/entry/avoiding_ld_library_path_...](https://blogs.oracle.com/ali/entry/avoiding_ld_library_path_the)

[https://blogs.oracle.com/rie/entry/tt_ld_library_path_tt](https://blogs.oracle.com/rie/entry/tt_ld_library_path_tt)

Also, unless one is an operating system vendor, one may not install anything
into /usr, as that is the vendor's namespace and having a clash with the
vendor could bring one's production down in case of upgrades, were the vendor
to deliver the same software. The System V and LSB FHS specifications state
that /opt is for 3rd party and unbundled applications, /etc/opt for
configuration, and /var/opt for data.

Unfortunately, the essay says nothing about library interface versioning with
linker map files, for backward compatibility, so that one single shared object
library can be used by all versions of the consuming software simultaneously.

------
nicolast
Also:
[https://www.akkadia.org/drepper/dsohowto.pdf](https://www.akkadia.org/drepper/dsohowto.pdf)

~~~
nuclx
drepper to the rescue

------
peeyek
I hope there is a tool like Cargo ([https://crates.io](https://crates.io)) in
C

~~~
gens
There is, your bog standard package manager (in unix and unix-like systems).

~~~
Rusky
That sort of package manager has a totally different purpose and does
absolutely nothing to help build your code, manage dependency versions, or
control how dependencies are built.

~~~
saurik
They clearly do manage "dependency versions" (that's what they do: that's the
primary purpose of say, apt). As for the other things, I am pretty certain
those are anti-features? I don't want the way I find and manage libraries and
depenendencies to assume I am going to use some specific build environment,
and the entire point of good package management is to be able to reuse
packages so encouraging developers to "control how dependencies are built" is
asking for trouble.

~~~
Rusky
System-wide package managers give you a single, global version of a package
built to interact solely with the rest of that one distribution.

I absolutely do want to control how dependencies are built- I want to build
them in debug mode, link them using LTO, cross-compile them, or (Rust-
specific, since someone mentioned Cargo) switch the panic strategy. Further,
many packages I depend on via language-specific tools likely will never be in
any distro's repository, nor should they be.

As for assuming a build environment, that may be an issue with a language like
C or C++ that has already gone a different route, but it's better when a
language has a single, established way of building things that a package
manager can integrate with.

------
flukus
Nice simple guide. Perfect for people like me that are "relearning" c.

~~~
drothlis
You might also like
[http://david.rothlis.net/c/compilation_model/](http://david.rothlis.net/c/compilation_model/)
\-- a tutorial I wrote that goes into some detail on what the preprocessor,
compiler, assembler & linker do.

------
musicnarcoman
> (3b) you could also build an ARCHIVE FILE (a statically linked library,
> libmylib.a) from one or more .o files. If you link with a static library,
> its code is copied into the a.out file at runtime.

Huh? There is no copying at runtime when using a static library. Or have I
misunderstood this all these years?

------
ndesaulniers
See also: [https://nickdesaulniers.github.io/blog/2016/11/20/static-
and...](https://nickdesaulniers.github.io/blog/2016/11/20/static-and-dynamic-
libraries/)

------
slavik81
An alternative to using LD_LIBRARY_PATH is to bake the rpath into the
executable. It's a little nicer for the user, IMO.

------
nothrabannosir
Tangential question: why aren't we using '#pragma once' more? I've adopted it
in personal stuff and it's obviously Good. Is anyone still really coding for
some arcane compiler that doesn't support it? Or is there some good reason for
not just switching?

~~~
nanolith
There are proprietary compilers for embedded chipsets that don't support this
feature. Granted, these are fewer and further between than they once were, but
they are out there. It really depends on how portable you want your code to
be. Even though it is widely supported, it still isn't a standard language
feature.

If your goal is to have a library that runs on most Unix-like and Windows
systems, then '#pragma once' works just fine. But, if there's a possibility
that your code would be deployed to an odd platform, it's probably best to use
traditional header guards. I'm so used to using header guards that the appeal
of '#pragma once' isn't that great for me.

~~~
apaprocki
You don't have to go that far.. Oracle Studio (nee Sun Studio) for Solaris
doesn't support it.

~~~
slavik81
Wikipedia lists it as supported since version 12.5.

[https://en.wikipedia.org/wiki/Pragma_once#Portability](https://en.wikipedia.org/wiki/Pragma_once#Portability)

------
stefantalpalaru
Do yourself a favour and use libtool through Autotools:
[https://autotools.io/libtool/index.html](https://autotools.io/libtool/index.html)

