# Makefile: Neukompilieren auch bei Änderungen in .hpp

## manuels

Moin,

ich schreibe ein C++-Programm, das stark auf Templates setzt.

Diese sind in .hpp-Dateien definiert.

Normalerweise kompiliert make ja nur .cpp Dateien automatisch neu, wenn diese sich geändert haben.

Ich möchte aber, dass dies auch bei Änderungen in .hpp-Dateien geschieht.

Da make aber keine Ahnung hat, welche .cpp-Datei es kompilieren muss, wenn sich eine .hpp-Datei geändert hat, ist dies wahrscheinlich so gar nicht möglich, oder?

Zur Not würde es auch ein automatisches "make clean" tun, wenn sich eine .hpp-Datei ändert.

Habt ihr ne Idee, wie das funktionieren könnte?

----------

## franzf

Kannst du dein Header.hpp beim target als Abhängigkeit eintragen?

Ich hab bisher nur für ganz primitive Versuche ein eigenes Makefile geschrieben, sonst verwende ich cmake. In einem Makefile staht dann sowas drin:

```
CMakeFiles/test.dir/main.cpp.o: Header.hpp
```

Und es wird main.cpp neu kompiliert, wenn sich der Header ändert.

----------

## manuels

Mist, merke gerade, dass es doch noch etwas komplizierter wird:

Die .hpp-Dateien liegen in anderen Verzeichnissen. Alle aufzulisten wäre zu mühsam.

Es gibt doch irgendein Tool, das die Include-Dateien auflistet. Wie ging das nochmal?

Wenn ich das mit deinem Ansatz verbinde, sollte es klappen.

Edit: es war "g++ -M file.cpp"

Nun muss ich allerdings noch für alle .cpp-Dateien die Dependencies quasi dynamisch über den o.g. Befehl erstellen lassen.

Wie stellt man denn das nun schon wieder an?

----------

## Necoro

Google einfach mal ... vor diesem Problem steht jeder der Makefiles schreibt früher oder später  :Very Happy: .

Alternative wäre ein besseres Buildsystem. Scons sollte sowas direkt können ohne hacks. autotools denke ich mal auch. cmake weiß ich nicht.

----------

## franzf

 *Necoro wrote:*   

> cmake weiß ich nicht.

 

Ja, tut es.

----------

## manuels

da das Programm auf verschiedensten Rechnern kompiliert werden soll, kann ich auf cmake nicht zurückgreifen.

----------

## Necoro

wie gesagt: google mal. gibt tausendundein programm/snippet was ein "dependency tracking" für normales make implementiert.

/edit: oder halt autotools  :Smile:  ... das sollte bis auf windows überall lauffähig sein

----------

## franzf

Ich denke, cmake läuft auf (fast) allen Plattformen.

Aber wurscht  :Razz: 

Hier mal ein erster Ansatz eines totalen Noobs  :Wink: 

Makefile:

```
all:    main

main: compile_dependencies

        g++ main.o -o main

compile_dependencies: create_dependencies

        make -f main_deps main.o

create_dependencies:

        ./create_dep_helper "main.o" "main.cpp" "main_deps"
```

create_dep_helper

```
#!/bin/bash

echo "write dependencies for $2 to target $1 in fil $3"

echo "$1:" > $3

echo "  g++ -o $1 -c $2" >> $3

echo $(g++ -MM $2) >> $3
```

Das kann man aber sicherlich noch verbessern...

----------

## Necoro

Wie gesagt ... googeln  :Razz: 

Bringt zB diesen Abschnitt aus dem GNU Make Manual: http://www.gnu.org/software/automake/manual/make/Automatic-Prerequisites.html

----------

## mv

Wer ein Makefile für ein nichttriviales Projekt von Hand schreibt, ist selbst schuld: man autotools.

----------

## manuels

 *franzf wrote:*   

> Ich denke, cmake läuft auf (fast) allen Plattformen.

 

Ja, aber leider ist es auf vielen Rechnern, auf denen ich das Programm kompilieren muss nicht installiert.

Da sind nur die "Unix-Basics" drauf und Root-Rechte habe ich nicht (cmake ins Home-Verzeichnis zu installieren wäre eine Möglichkeit, aber auch ein bisschen umständlich dies für jeden Rechner zu machen).

Werde mir wohl mal die autotools anschauen müssen. Für mich war ./configure immer eine "magische Blackbox"...

----------

## mv

 *manuels wrote:*   

> Werde mir wohl mal die autotools anschauen müssen. Für mich war ./configure immer eine "magische Blackbox"...

 

Das ist inzwischen gar nicht schwer, weil die Dokumentation mittlerweile brauchbar ist. Wenn Du keine Spirenzchien brauchst, musst Du i.W. in automake.am nur einer Variable Deine Liste mit Source-Files zuweisen und in autoconf.ac eine Standard-Initialisierung benutzen.

----------

