Gnu make - Makefile dependency modification detection

De openkb
Aller à : Navigation, rechercher

Sommaire

Questions

I m writing a makefile for handling the dependency of build units ONE and TWO -> build unit LIB.

By "build unit" I mean a directory containing directories src, lib, include and bin, as well as a makefile for compiling the source code in src. Libraries are placed in "lib" and library header-files in "include". The compiled binary is placed in "bin". A build unit accepts "make", "make all", "make lint" and "make clean".

When a change is made to a header-file in LIB, this makefile is meant to detect it and recompile + install (copy .a+.h-files to ONE and TWO) the new version of LIB before compiling.

.PHONY: ONE TWO CLEAN LINT

ALL: ONE TWO

%.a %.h:
    @echo ---------- Compiling LIB ----------
    @cd LIB && gmake.exe LIB

LIB_HEADERS := $(wildcard LIB/src/*.h)

ONE: ONE/lib/libLIB.a $(subst LIB/src/,ONE/include/,$(LIB_HEADERS))
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe

TWO: TWO/lib/libLIB.a $(subst LIB/src/,TWO/include/,$(LIB_HEADERS))
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe

CLEAN LINT:
    @cd ONE && gmake.exe $@
    @cd TWO && gmake.exe $@
    @cd LIB && gmake.exe $@

(Assume the makefile for LIB handles copying into ONE and TWO)

    • How come make does not run the rule "%.a %.h:" when I make a change to one of the header-files in LIB/src?
    • How do I generalize ONE and TWO into a single rule? I want to do this (but a target cannot be used in dependencies, at least this way):
    ONE TWO: $@/lib/libLIB.a $(subst LIB/src/,$@/include/,$(LIB_HEADERS))
        @echo ---------- Compiling $@ ----------
        @cd $@ && gmake.exe
    
  UPDATE:   

I found the solution by taking a step back, drawing Directed Acyclic Graphs, and thinking in terms of single files, instead of all files of a certain type.

Here is the (not very elegant) solution, for completeness:

.PHONY: ONE TWO CLEAN LINT

ALL: ONE TWO

LIB_HEADERS := $(sort $(subst name.h,,$(wildcard LIB/src/*.h)))

# ------------------------------------------------------------
ONE/include/%.h: LIB/src/%.h
    @echo Copying $< to $@
    @mkdir ONE\include 2> NUL || :)
    @copy $(subst /,,$<) ONE\include\ 1> NUL

TWO/include/%.h: LIB/src/%.h
    @echo Copying $< to $@
    @mkdir TWO\include 2> NUL || :)
    @copy $(subst /,,$<) TWO\include\ 1> NUL
# ------------------------------------------------------------
ONE/lib/liblib.a: LIB/bin/liblib.a
    @echo Copying $< to $@
    @mkdir ONE\lib 2> NUL || :)
    @copy $(subst /,,$<) ONE\lib\ 1> NUL

TWO/lib/liblib.a: LIB/bin/liblib.a
    @echo Copying $< to $@
    @mkdir TWO\lib 2> NUL || :)
# Windows-equivalent of touch (discarding any output to stdout):
    @copy $(subst /,,$<) TWO\lib\ 1> NUL
# ------------------------------------------------------------
LIB/bin/liblib.a: $(LIB_HEADERS) $(wildcard LIB/src/*.cpp)
    @echo ---------- Looking for changes to liblib ----------
    @cd LIB && gmake.exe LIB
    @copy /b $(subst /,,$@) +,, 1> NUL || :)
# ------------------------------------------------------------
ONE: ONE/lib/liblib.a $(subst LIB/src/,ONE/include/,$(LIB_HEADERS))
    @echo ---------- Compiling ONE ----------
    @cd ONE && gmake.exe

TWO: TWO/lib/liblib.a $(subst LIB/src/,TWO/include/,$(LIB_HEADERS))
    @echo ---------- Compiling TWO ----------
    @cd TWO && gmake.exe
# ------------------------------------------------------------
CLEAN LINT:
    @cd ONE && gmake.exe $@
    @cd TWO && gmake.exe $@
    @cd LIB && gmake.exe $@

I very much welcome tips on how to generalize ONE and TWO further.

Answers

For question 1 : Maybe you need to move the LIB_HEADERS definition up and change the rule to

   %.a %.h: $(LIB_HEADERS) 

?

Source

License : cc by-sa 3.0

http://stackoverflow.com/questions/18851779/makefile-dependency-modification-detection

Related

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Outils