makefilegnu-makebuild-systembuild-dependencies

How to build a programs that's output will be used in a Make variable name


I want to create a Makefile which will build a program which when run's output will be used as a value for a variable in the same Makefile.

Consider the program:

print_name.c:

#include <stdio.h>
int main() {
   printf("foo\n");
   return 0;
}

I'd like to use the standard output of this program to then determine a directory name to be stored in a variable used in the makefile and used for other rules, so far I've tried:

all: $(MY_DIRECTORY_NAME)/my_program

print_name: print_name.c | print_name
    gcc $^ -o $@

MY_DIRECTORY_NAME:=$(shell ./print_name)

$(MY_DIRECTORY_NAME)/my_program: my_program.c 
    mkdir -p $(MY_DIRECTORY_NAME)
    gcc $^ -o $@

However when I run:

 make all

I get:

make: *** No rule to make target '/my_program', needed by 'all'.  Stop

Whereas I'd like:

mkdir -p foo
gcc my_program.c -o foo/my_program

So basically, I want to compile print_name before the assignment to MY_DIRECTORY_NAME, and then that variable in then used in the following rules. Is this possible, and if not are there any workarounds for this?


Solution

  • The basic problem is that you need to build (and run) print_name before you can parse the rules that use it -- but all rules are read and parsed before anything is built. So you need to run make twice -- first to build print_name and second to build everything that depends on it. Something like

    all: print_name
            $(MAKE) `./print_name`/my_program
    

    should do the trick