Antimake variable SUBDIRS list names of directories that the Make needs to recurse into. Each of them contains stand-alone Makefile that directs building in that subdirs.

  • Plus: you can call make while being in subdir to build only local targets.

  • Minus: dependencies between subdirs do not work.

Setup source tree

Setup directories, install Antimake

$ mkdir -p lib1/sublib lib2
$ cp ../../antimake.mk .

Prepare sources

File: api.h
void func1(void);
void func2(void);
void func3(void);
File: main.c
#include <stdio.h>
#include "api.h"

int main(void)
{
        func1();
        func2();
        func3();
        printf("main\n");
        return 0;
}
File: lib1/func1.c
#include <stdio.h>
#include "api.h"

void func1(void)
{
        printf("func1\n");
}
File: lib1/sublib/func2.c
#include <stdio.h>
#include "api.h"

void func2(void)
{
        printf("func2\n");
}
File: lib2/func3.c
#include <stdio.h>
#include "api.h"

void func3(void)
{
        printf("func3\n");
}

Prepare Makefiles

File: Makefile
PACKAGE_NAME = test-subdirs
PACKAGE_VERSION = 1.0

SUBDIRS = lib1 lib2

bin_PROGRAMS = prog
prog_SOURCES = main.c
prog_LDADD = lib1/func1.a lib1/sublib/func2.a lib2/func3.a

EXTRA_DIST = Makefile antimake.mk

include antimake.mk
File: lib1/Makefile
SUBLOC = lib1
SUBDIRS = sublib

noinst_LIBRARIES = func1.a
func1_a_SOURCES = func1.c
func1_a_CPPFLAGS = -I..

EXTRA_DIST = Makefile

include ../antimake.mk
File: lib1/sublib/Makefile
SUBLOC = lib1/sublib

noinst_LIBRARIES = func2.a
func2_a_SOURCES = func2.c
func2_a_CPPFLAGS = -I../..

EXTRA_DIST = Makefile

include ../../antimake.mk
File: lib2/Makefile
SUBLOC = lib2

noinst_LIBRARIES = func3.a
func3_a_SOURCES = func3.c
func3_a_CPPFLAGS = -I$(top_srcdir)

EXTRA_DIST = Makefile

include ../antimake.mk

Building

Build the project

$ make
     -->      lib1
     -->      lib1/sublib
     CC       func2.c
     AR       func2.a
     RANLIB   func2.a
     <--      lib1/sublib
     CC       func1.c
     AR       func1.a
     RANLIB   func1.a
     <--      lib1
     -->      lib2
     CC       func3.c
     AR       func3.a
     RANLIB   func3.a
     <--      lib2
     CC       main.c
     CCLD     prog
$ ls
Makefile  antimake.mk  api.h  lib1  lib2  main.c  prog
$ ./prog
func1
func2
func3
main

We can now install it:

$ make install DESTDIR=./inst
     -->      lib1
     -->      lib1/sublib
make[2]: Nothing to be done for `install'.
     <--      lib1/sublib
     <--      lib1
     -->      lib2
make[1]: Nothing to be done for `install'.
     <--      lib2
     INSTALL  prog ./inst/usr/local/bin
$ ls ./inst/usr/local/bin
prog

Now we can create package that can be given to others.

$ make dist
     CHECK    dist-gzip
     MKDIR    test-subdirs-1.0
     COPY     test-subdirs-1.0
     PACK     test-subdirs-1.0.tar.gz
$ ls
Makefile     api.h  lib1  main.c  test-subdirs-1.0.tar.gz
antimake.mk  inst   lib2  prog
$ tar tzf test-subdirs-1.0.tar.gz | sort
test-subdirs-1.0/
test-subdirs-1.0/Makefile
test-subdirs-1.0/antimake.mk
test-subdirs-1.0/lib1/
test-subdirs-1.0/lib1/Makefile
test-subdirs-1.0/lib1/func1.c
test-subdirs-1.0/lib1/sublib/
test-subdirs-1.0/lib1/sublib/Makefile
test-subdirs-1.0/lib1/sublib/func2.c
test-subdirs-1.0/lib2/
test-subdirs-1.0/lib2/Makefile
test-subdirs-1.0/lib2/func3.c
test-subdirs-1.0/main.c

Clean the tree

$ make clean
     -->      lib1
     -->      lib1/sublib
     CLEAN    func2.a
     <--      lib1/sublib
     CLEAN    func1.a
     <--      lib1
     -->      lib2
     CLEAN    func3.a
     <--      lib2
     CLEAN    prog
$ ls
Makefile  antimake.mk  api.h  inst  lib1  lib2  main.c  test-subdirs-1.0.tar.gz

Test O=

$ mkdir -p build
$ make O=build
     MKDIR    Create lib1
     -->      lib1
     MKDIR    Create lib1/sublib
     -->      lib1/sublib
     CC       ../../../lib1/sublib/func2.c
     AR       func2.a
     RANLIB   func2.a
     <--      lib1/sublib
     CC       ../../lib1/func1.c
     AR       func1.a
     RANLIB   func1.a
     <--      lib1
     MKDIR    Create lib2
     -->      lib2
     CC       ../../lib2/func3.c
     AR       func3.a
     RANLIB   func3.a
     <--      lib2
     CC       ../main.c
     CCLD     prog
$ ls
Makefile     api.h  inst  lib2    test-subdirs-1.0.tar.gz
antimake.mk  build  lib1  main.c
$ ls build
Makefile  antimake.mk  lib1  lib2  prog

Done!