开发者

Testing file existence in NMake

In a makefile for GNU Make I use this idiom to test whether a file exists:

static:
ifeq ($(wildcard $(FileName)),)
    # do something when the file doesn't exist
else
    # do something different when it does
endif

But it doesn't work in NMake (fatal error U1000: syntax error : ')' missing in macro invocation). How can I rep开发者_运维技巧lace it? It would be perfect if the replacement works in both build systems.


Nmake can run preprocessor directives:

http://msdn.microsoft.com/en-us/library/7y32zxwh.aspx

The conditions can vary, but Exists() is one of them:

http://msdn.microsoft.com/en-us/library/8t2e8d78.aspx

!IF EXISTS(foo.txt)

Lastly you use a command-line, http://msdn.microsoft.com/en-us/library/wkxa7sac.aspx

!IF [cmd /C IF NOT EXIST "foo.txt" exit 1]

Either way, this should work, using either !IF above here is full example:

!IF !EXISTS(foo.txt)
!ERROR Unable to locate foo.
!ELSE
!MESSAGE I Found foo!
!ENDIF


Just to add to Jack Kelly's suggestion, you can do the test for existence in a CMD.EXE shell. NMake also includes the ability to create a temporary .cmd file, and execute it.

Here's an example of the (n)makefile syntax, that I use for a "check-syntax" target. It checks the syntax in a single C# source file, in a multi-file project, by doing a compile.

check-syntax :
    <<flymake-build.cmd  $(CS_SOURCE)
SETLOCAL ENABLEDELAYEDEXPANSION
set errorlevel=
for %%I in (%*) do if NOT x%%I == x$(FLYMAKE_ORIGINAL) (
   set filesToBuild=!filesToBuild! %%I
)
$(_CSC) /t:module $(LIBSREF) $(FLYMAKE_CHECK) !filesToBuild!
ENDLOCAL && exit /b %errorlevel%
<<

The "flymake-build.cmd" is the name of the temporary cmd file that gets created. The double angle brackets (<<) denote the beginning and end of the content that goes into the temp file, before the file is executed.

The stuff after the filename on that first line are arguments passed to the .cmd file. In this example, the arguments are the contents of a makefile variable called CS_SOURCE. In my case this is just a list of filenames in the project. Makefile variables will be expanded within the text for the temporary file, as well. You can see I refer to a compiler (_CSC) and some other symbols.

Inside the .cmd code, you can do for loops, if statements, anything you like. It's a regular .cmd file.

If you want nmake to respond to errors (eg, terminate the build) generated by commands within the .cmd file, then you need to use the exit /b approach to end the cmd.

I found the documentation for this in a dark corner somewhere, so I thought I'd share it here for general elucidation. (EDIT: here's the link.)


csharptest.net's answer is almost on point, but it lacks a minuscule detail regarding the difference in indentation rules between commands and directives:

static:
!if exists($(FileName)) 
    @echo $(FileName) does exist!
#^^^ DO MIND THE INDENTATION HERE, a command shall fail otherwise!
#
!else
!error $(FileName) does not exist!
#^^^^^ !directives don't have to be indented, though.
#
!endif

Oddly enough, it can be either exist (as given in official docs) or exists to the same effect.


Do it at the shell level instead of the Makefile level. If you can rely on posix tools:

static:
    @if test -f $(FileName); then \
      echo something; \
    else \
      echo some other thing; \
    fi

Note the line continuation markers everywhere.

If you need to do this in CMD.EXE, then perhaps you can do similar using an IF EXIST $(FileName) COMMAND ELSE COMMAND construct.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜