Search code examples
makefilegnu-maketargetaix

Implementing target-specific variable assignment in AIX's native make


I have a main makefile (common for all platforms on which my software is deployed on) and a platform specific makefile containing AIX specific settings. The platform makefile is included at the end of the main makefile.

The main makefile defines a macro A=somevalueA that I want to override with a new value somenewvalue in the context of a few (not all) targets defined in the main makefile, for AIX. This makes it easier to visualize:

# main makefile

A=somevalueA
C=$(C1) $(A) $(C2)
B1=$(B11) $(C) $(B12)
B2=$(B21) $(C) $(B22)
B3=$(B31) $(C) $(B32)
B4=$(B41) $(C) $(B42)
target1:
  # some recipe using $(B1)

target2:
  # some recipe using $(B2)

target3:
  # some recipe using $(B3)

target4:
  # some recipe using $(B4)

include aixmakefile

Now suppose I want to override the value of A on AIX for targets target1, target2 only. With gmake, I can simply add the following target-specific variable assignments in aixmakefile:

# aixmakefile
...
target1: A=somenewvalue
target2: A=somenewvalue

But this is not supported by AIX's native make program. Alternatives to target-specific assignment that come to my mind are:

  1. Copying the definitions of B1, B2 to aixmakefile and substituting occurrences of $(A) with somenewvalue ($(A) is guaranteed to be "at the end of a word" as described in this article on gmake substitution references, which is also true for AIX's native make):
# aixmakefile
...
B1=$(B11:$(A)=somenewvalue) $(C:$(A)=somenewvalue) $(B12:$(A)=somenewvalue)
B2=$(B21:$(A)=somenewvalue) $(C:$(A)=somenewvalue) $(B22:$(A)=somenewvalue)
  1. Copying the entire recipe for targets target1,target2 to aixmakefile and substituting occurrences of $(A) with somenewvalue:
# aixmakefile
...
target1:
  # some recipe using $(B1:$(A)=somenewvalue)
target2:
  # some recipe using $(B2:$(A)=somenewvalue)

As you can see, these approaches are not very elegant. I was wondering if there is a neat hack to implement target-specific variable assignments in AIX's make or some other concise, elegant solution to my problem that eludes me.

Thanks for your time.


Solution

  • If you have a well-defined relationship between the target names and the value, AND you don't need the "inheritance" feature of target-specific variables, you can just use constructed variable names:

    C = $(C1) $($@_A) $(C2)
      ...
    target1_A = somevalueA
    target2_A = somevalueA
    target3_A = somevalueA
    target4_A = somevalueA
    

    Now in aixmakefile you can set:

    target1_A = somenewvalue
    target2_A = somenewvalue
    

    The $@ in $($@_A) will expand to the target name (target1, target2, etc.) and so it will expand to $(target1_A) etc.

    You can read more about metaprogramming in make here: https://make.mad-scientist.net/category/metaprogramming/ but note only the earliest parts of this are really portable: the newer/more powerful parts require GNU Make.