Search code examples
makefilenmake

Using nmake with wildcarded targets


Using nmake I have the following makefile which currently does what I need it to do. mycmd (the program being run) will take a .inp file and produce a .out file. I can make as many .inp files as I need to and the makefile doesn't have to change. It will find them all and make all the relevant .out files.

#####################################################################################
# A SUFFIXES declaration is required in order to later use the rule with target .inp.out
#####################################################################################
.SUFFIXES: .inp

#####################################################################################
# Here, NMAKE will expand *.inp in the prereq list for all, into the list of *.inp
# files in the directory, and then it will start a new NMAKE instance, specifying the
# goals to build all those files.
#####################################################################################
all: *.inp
  $(MAKE) $(**:.inp=.out)

#####################################################################################
# $(*B) represents the current target's base name minus the path and the file extension
#####################################################################################
.inp.out:
  mycmd -i $(*B).inp -o $(*B).out

My question is, how do I enhance this makefile further so that I could, for example, run it for a set of .inp files, so not *.inp but say, ABC*.inp?


Solution

  • A simple modification to your makefile should work. Add a new $(pattern) macro:

    .SUFFIXES: .inp
    
    pattern = *                         # new macro, set to default value of *
    
    all: $(pattern).inp                 # use the new macro!
      @$(MAKE) -nologo $(**:.inp=.out)
    
    .inp.out:                           # dummy stub for testing
      @echo mycmd -i $(*B).inp -o $(*B).out
      @type NUL > $(*B).out
    

    Then in your command line, overwrite pattern. For example, nmake -nologo pattern=ABC*.


    Update: The command line in your makefile:

      $(MAKE) $(**:.inp=.out)
    

    will fail with fatal error U1095: expanded command line ... too long if the string $** is too long. On my system, this happens at roughly 32800 characters.

    Adding an exclamation mark ! to the start (see here) doesn't seem to work, probably because there is no simple $**. Two workarounds are to use:

      !call set a=$** & call nmake %%a:.inp=.out%%
    

    or:

      !for %a in ($**) do nmake -nologo %~na.out
    

    These are both about twice as slow as your original, with a do-nothing mycmd stub. (The for loop here is not really a loop, because $** is just a single item.)