1

My makefile:

ifndef VEC_LEN
        VEC_LEN = 1
endif

my_target: a.c
        gcc a.c -DVEC_LEN=$(VEC_LEN)

Is there a way to tell make that my_target should be updated when VEC_LEN changes?

Update:

My scripts now look like this (and they work): Makefile

SHELL := /bin/bash

# Define the answer if not defined yet
ANSWERTOLIFETHEUNIVERSEANDEVERYTHING ?= 42

# Update the header file if the answer has changed
# := always executes the shell command, = does not! Quote from http://www.gnu.org/software/make/manual/make.html:
#      immediate = deferred
#      immediate := immediate
DUMMY := $(shell ./updateAnswer.sh $(ANSWERTOLIFETHEUNIVERSEANDEVERYTHING) >logMakefile.txt)

answer : answer.h 
    echo "Updated!"
    touch answer

updateAnswer.sh

#!/bin/bash

# Check if the definition of the answer has changed in the header file
# If yes, re-write it. If not, do not touch it to avoid an updated timestamp.
if grep -q "ANSWER ${1}" answer.h
then
    echo "ANSWER unchanged, is still ${1}."
else
    echo "#define ANSWER ${1}" >answer.h
    echo 'Answer has changed:'
    cat answer.h
fi

Example output:

simon@x220:~$ make
echo "Updated!"
Updated!
touch answer
simon@x220:~$ make
make: `answer' is up to date.
simon@x220:~$ make ANSWERTOLIFETHEUNIVERSEANDEVERYTHING=3
echo "Updated!"
Updated!
touch answer
simon@x220:~$ make ANSWERTOLIFETHEUNIVERSEANDEVERYTHING=3
make: `answer' is up to date.
Simon A. Eugster
  • 4,114
  • 4
  • 36
  • 31
  • Changes when? During the building of other targets? Since the last run of Make? Can you give an example? – Beta Oct 12 '11 at 11:55
  • @Beta I have a bash script that builds my target multiple times for benchmarking, usually with different VEC_LEN. So if I call «make;make» then my_target should only be built once. For «make;make VEC_LEN=10» it should be built with VEC_LEN=1 and then with VEC_LEN=10. – Simon A. Eugster Oct 12 '11 at 16:12
  • Duplicate: http://stackoverflow.com/questions/3236145/force-gnu-make-to-rebuild-objects-affected-by-compiler-definition – slowdog Oct 16 '11 at 15:15

2 Answers2

2

I think this will do it, within the makefile:

-include old_vec_len

VEC_LEN ?= 1

ifneq ($(VEC_LEN),$(OLD_VEC_LEN))
target: marker
endif

target:
    @echo run_script_to_make_target with VEC_LEN=$(VEC_LEN)

.PHONY:marker
marker:
    @echo OLD_VEC_LEN=$(VEC_LEN) > old_vec_len
Beta
  • 96,650
  • 16
  • 149
  • 150
  • Interesting. Can you give me a hint about how to use it? When I run make, it tells me that there is nothing to do for target. When I put «OLD_VEC_LEN=1» into a manually created old_vec_len and run «make VEC_LEN=2» I get the same output. – Simon A. Eugster Oct 15 '11 at 08:47
  • @SimonA.Eugster: really? "Nothing to be done" means that Make does not know a rule for that target. Is it possible that the target name in the makefile and the target name in your command (`make target`) do not exactly agree? – Beta Oct 15 '11 at 14:07
  • Ah. Problem located. You are right: when I copy/paste the makefile from above, I get four spaces for indentation. If I replace them by a tab it works! Very nice. – Simon A. Eugster Oct 18 '11 at 09:54
1

Assuming that the language is C, I think the most straightforward way is probably:

  1. Prepares vec_len.h which has a line #define VEC_LEN 1
  2. Adds #include "vec_len.h" in a.c
  3. If VEC_LEN's value has to be updated, rewrites vec_len.h
  4. Builds using usual .c file and header file dependency

EDIT:
Though this is a little naive way, does the following change work in your situation?

Prepares a script(define.sh) like the following:

#!/usr/bin/bash
echo '#define VEC_LEN' $1 > vec_len.h

And adds the following lines at the beginning of the makefile:

VEC_LEN ?= 1
DUMMY := $(shell define.sh $(VEC_LEN))
Ise Wisteria
  • 11,259
  • 2
  • 43
  • 26
  • Yes, this is no problem. As long as it works. I now try to run a bash script at the beginning of the makefile which updates the header file if necessary, but I cannot find any way to run a simple bash command at the beginning of a makefile. – Simon A. Eugster Oct 12 '11 at 16:21
  • Thanks a lot! This worked. I added my code in the question. I actually tried something similar, but used = instead of := so the bash script was never executed. – Simon A. Eugster Oct 14 '11 at 10:59
  • @SimonA.Eugster: Glad it helped :-) Now I found _Beta_'s interesting answer. It also seems good for you. – Ise Wisteria Oct 14 '11 at 14:28