pngexportnmakebalsamiq

Using nmake with wildcards in the makefile


I am attempting to set up an nmake makefile to export our balsamiq mockup files to png files automatically, but I'm afraid I can't make heads nor tails of how to make a generic rule for doing so, without explicitly listing all the files I want exported.

This page details the command line syntax for exporting the files, and this page contains an example which looks like it contains a generic rule for .obj files to .exe files.

The makefile I have tried so far looks like this:

.bmml.png:
    "C:\Program Files\Balsamiq Mockups\Balsamiq Mockups.exe" export $< $@

But this doesn't work.

If I simply run nmake (with some outdated png files), nmake just does this:

[C:\Temp] :nmake

Microsoft (R) Program Maintenance Utility Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.


[C:\Temp] :

If I ask it to build one specific file, it does this:

[C:\Temp] :nmake "TestFile.png"

Microsoft (R) Program Maintenance Utility Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

NMAKE : fatal error U1073: don't know how to make '"TestFile.png"'
Stop.

[C:\Temp] :

Any nmake gurus out there that can set me straight?

An example makefile which simply makes .dat files from .txt files by copying them, to experiment with, looks like this:

.txt.dat:
    copy $< $@

this does nothing as well, so clearly I'm not understanding how such generic rules work. Do I need to specify a goal above that somehow lists the files I want?


Solution

  • NMAKE pattern rules are a lot like GNU make old-school suffix rules. In your case, you had it almost right to begin with, but you were missing the .SUFFIXES declaration. For example:

    .SUFFIXES: .bmml .png
    .bmml.png:
        @echo Building $@ from $<
    

    I think this is only part of your solution though, because you also mentioned wanting to avoid explicitly listing all of the files to be converted. Unfortunately, I don't know of a very clean way to do that in NMAKE, since it only expands wildcards in dependency lists, and what you really want in your dependency list is not the list of files that already exist (the *.bmml files), but the list of files that will be created from those files (the *.png files). Nevertheless, I think you can achieve your goal with a recursive NMAKE invocation like this:

    all: *.bmml
        $(MAKE) $(**:.bmml=.png)
    

    Here, NMAKE will expand *.bmml in the prereq list for all into the list of .bmml files in the directory, and then it will start a new NMAKE instance, specifying the goals to build as that list of files with all instances of .bmml replaced by .png. So, putting it all together:

    .SUFFIXES: .bmml .png
    all: *.bmml
        @echo Converting $(**) to .png...
        @$(MAKE) $(**:.bmml=.png)
    
    .bmml.png:
        @echo Building $@ from $<
    

    If I create files Test1.bmml and Test2.bmml and then run this makefile, I get the following output:

    Converting Test1.bmml Test2.bmml to .png...
    Building Test1.png from Test1.bmml
    Building Test2.png from Test2.bmml
    

    Of course, if you have very many of these .bmml files, you may run afoul of command-line length limitations, so watch out for that. In that case, I recommend either explicitly listing the source files, or using a more capable make tool, like GNU make (which is available for Windows in a variety of forms).