Make your own library

Category: c/c++ tips
Tags: C Makefile

Disclaimer

  1. I probably need to learn more about linker and stuff, but it seems that I can get a way with what I know.

  2. YMMV, but this method is linux, darwin is a little different. On MSVC it is link.exe/lib.exe all the way

Background

Sometimes you have just a (bunch of) c-file(s) that you want to turn into a library.

The reasons may vary but consider:

  • It is an external code that you want to keep out your code base.
  • If you want to ship your code as a library so that others can link their application (duh).

The setup

Your header 'magic.h'

file: magic.h

#ifndef groksome_magic_h_
#define groksome_magic_h_

int magic(const int magic);

#endif

Your code 'magic.c'

file: magic.c

#include "magic.h"
#include "magic.h"

int magic(const int magic) {
    return magic + 1;
}

Your main file 'main.c'

file: main.c

#include <magic.h>

#include <stdio.h>

int main(const int argc, const char ** argv) {
    int dummy;

    dummy = 1;
    dummy = magic(dummy);
    printf("%d\n", dummy);

    return 0;
}

Compile and create a library

Static

file: static.mk

CC=clang

all: ./tmp/main ./tmp/libmagic.a

./tmp:
    mkdir -p $@

./tmp/main: ./tmp/main.o ./tmp/libmagic.a
    #$(CC) -o $@ $< -L./tmp -lmagic
    $(CC) -o $@ $< ./tmp/libmagic.a
    strip $@


./tmp/libmagic.a: ./tmp/magic_static.o
    ar cr $@ $<
    ranlib $@

./tmp/magic_static.o: magic.c magic.h ./tmp
    $(CC) -std=c99 -Wall -Wextra -Weverything -O2 -c -o $@ $<

./tmp/main.o: main.c magic.h ./tmp
    $(CC) -std=c99 -I. -Wall -Wextra -Weverything -Wno-unused-parameter -O2 -c -o $@ $<

.PHONY: clean

clean:
    rm -rf ./tmp

That 's is: Now anybody can use your code with static linking, either:

  • with -L/path/to/libmagic.a -lmagic
  • with /path/to/libmagic.a/libmagic.a

Compile it:

make -f static.mk 

Shared

file: shared.mk

CC=clang

all: ./tmp/main ./tmp/libmagic.so

./tmp:
    mkdir -p $@

./tmp/main: ./tmp/main.o ./tmp/libmagic.so
    $(CC) -o $@ $^ -L./tmp -lmagic
    strip $@

./tmp/libmagic.so: ./tmp/magic_shared.o
    $(CC) -shared -Wl,-soname,$@ -o $@ $<

./tmp/magic_shared.o: magic.c magic.h ./tmp
    $(CC) -std=c99 -Wall -Wextra -Weverything -O2 -fPIC -c -o $@ $<

./tmp/main.o: main.c magic.h ./tmp
    $(CC) -std=c99 -I. -Wall -Wextra -Weverything -Wno-unused-parameter -O2 -c -o $@ $<


.PHONY: clean

clean:
    rm -rf ./tmp

Compile it:

make -f shared.mk

That 's is: Now anybody can use your code with shard linking:

  • with -L/path/to/libmagic.so -lmagic

Notes

There is a time and place for both static linking and shared linking. Here are just my two cents:

  • If you have very large libraries, linking your binary with shared libraries is a bit faster. This keeps you a bit more in the develop-compile-link-test mode
  • If you ship your static linked binaries to other (linux-distros) computers, you'll probably have less compatibility problems.