Yonatan.Lehman
Yonatan.Lehman

Reputation: 63

gnu makefile when targets and dependencies are dynamic

I'm trying to create a makefile that creates a subsystem makefile if it does not exists, and then runs the make to create the subsystem using that subsystem makefile (using "echo" for simplicity)

If everything was static then I could use the following pattern

build_dir/config/makefile :
    mkdir -p build_dir/config
    echo create makefile > build_dir/config/makefile

use_make : build_dir/config/makefile
    echo local makefile using `ls -l build_dir/config/makefile`

My problem is that the "config" is defined as part of the target (e.g Debug or Release) I tried the following

.SECONDEXPANSION:
tgt_d : CONFIG = Debug
tgt_r : CONFIG = Release
    
tgt_d  tgt_r : MAKEFILE_DIR = build_dir/${CONFIG}

${MAKEFILE_DIR}/makefile :
    mkdir -p ${MAKEFILE_DIR}
    echo create makefile > ${MAKEFILE_DIR}/makefile

use_make : ${MAKEFILE_DIR}/makefile
    echo local makefile using `ls -l ${MAKEFILE_DIR}/makefile`

tgt_d tgt_r : use_make

My problem is that make is interpreting the ${MAKEFILE_DIR} in the target and the prerequisite directly (when it's undefined) not in a target-specific way (even when I added .SECONDEXPANSION or use ${${MAKEFILE_DIR}} - see output below

How can I achieve what I need to do ? The next step is to define this in a general way so that I can use it for multiple targets (multiple Eclipse projects that are build together) using $< and % - so kudos to someone that takes me that extra step! Thanks !

$ make --debug=v tgt_d
GNU Make 4.3
Built for x86_64-pc-cygwin
Copyright (C) 1988-2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Reading makefile 'makefile'...
Updating makefiles....
Updating goal targets....
Considering target file 'tgt_d'.
 File 'tgt_d' does not exist.
  Considering target file 'use_make'.
   File 'use_make' does not exist.
    Considering target file 'build_dir//makefile'.
     File 'build_dir//makefile' does not exist.
     Finished prerequisites of target file 'build_dir//makefile'.
    Must remake target 'build_dir//makefile'.
mkdir -p build_dir/Debug
echo create makefile > build_dir/Debug/makefile
    Successfully remade target file 'build_dir//makefile'.
   Finished prerequisites of target file 'use_make'.
  Must remake target 'use_make'.
echo local makefile using `ls -l build_dir/Debug/makefile`
local makefile using -rw-r--r-- 1 yonatan.lehman 1049089 16 Oct 30 12:18 build_dir/Debug/makefile
  Successfully remade target file 'use_make'.
 Finished prerequisites of target file 'tgt_d'.
Must remake target 'tgt_d'.
Successfully remade target file 'tgt_d'.

Upvotes: 0

Views: 141

Answers (1)

MadScientist
MadScientist

Reputation: 100836

The manual is pretty clear about when target-specific variables are in use and when they are not:

As with automatic variables, these values are only available within the context of a target’s recipe (and in other target-specific assignments).

So, clearly your use of them in targets and prerequisites cannot work. Secondary expansion has nothing to do with this (in any event, you're not actually using any secondary expansion here even though you've enabled the feature).

I think you'll have to use a recursive invocation of make:

tgt_d  tgt_r :
        $(MAKE) use_make MAKEFILE_DIR=build_dir/${CONFIG}

Upvotes: 1

Related Questions