Geoff Chappell - Software Analyst
Where a command-line token begins with an @ sign (and is not, exceptionally, an argument for some earlier option), the remainder of the token names a command file, which the product documentation also sometimes refers to as a response file. The purpose of a command file is that its text is to provide more command-line tokens. In effect, a command-line token that names a command file is a command-line macro, expanding in place to whatever command-line tokens are found in the named file.
The ordinary processing of command files is recursive. It is an error (D2035) if the recursion goes too far. The present implementation allows the recursion depth to reach 13 (counting the top-level command file as 1). It is an error (D2022) if the command file cannot be opened with read access (in text mode). The filename used is exactly as given in the command-line token, beginning immediately after the @ sign, white space included. The command file is parsed line by line, for as long as lines can be read. A read error for the file becomes an error (D2034) for CL. Parsing line by line has as an implication that although a line may contain multiple tokens, no token or option can carry beyond the line it starts on.
Support for command files is very greatly reduced during an early pass of the command line, during which the compiler seeks the state of a handful of options (/Be, /clr, /nologo, /noover and /ZX) in advance of the ordinary processing. A quick summary is that: there is no recursion; only the first line is examined; and read errors go unremarked.
Unless the early pass finished with the /nologo switch active, the ordinary processing of command files is reported by echoing each line to standard error. The first echoed line has the prefix cl as if to show how the tokens extracted from the command files might have been given as a command line.
It may help if special cases and parenthetical remarks in the general discussion above are elaborated with examples.
For an example of a command-line token that begins with an @ sign but does not count as naming a command file, consider the following command
cl /c /I @test.txt test.cpp
in which “test.txt” is intended as a command file, to provide options for the compilation of the source file “test.cpp”, but an editing error (perhaps due to some subtlety in a makefile) has left an incomplete /I option. The command is syntactically valid and causes no error or warning, but “test.txt” is ignored as a command file because the token that might be thought to name it as a command file is instead interpreted by CL as the required argument for the /I option.
It is perhaps necessary to present an example of recursive command files, especially because the product documentation states plainly that “it is not possible to specify the @ option from within a response file.” This is on a page titled @ (Specify a Compiler Response File). That response files can in fact be nested is documented in the description of Command-Line Error D2035, not that users who wonder whether command files can be nested would think to look there, and not that they could know easily which of two contradictory pages to trust.
If the file “test1.txt” contains just
and the file “test2.txt” in turn contains nothing but the name of a source file “test.cpp”, then the command
cl /c @test1.txt
compiles the source file, even though it can only have found the name in the nested command file.
Each line in a command file is parsed separately, as if it were a whole command line. This has non-trivial implications for those options that are permitted to spread to one or more subsequent command-line tokens. Such sequences end with the line that they started on.
Consider the /I option (already used in an example above). Its required argument is either the remainder of its own command-line token, else the whole of the next command-line token. In the command file
there is no next command-line token before the end of the line. The /I therefore has no argument and causes error D2004.
For another example, consider the /link option. Its (optional) argument is whatever follows in its own command-line token plus all subsequent command-line tokens. In the command file
/link/arg1 /arg2 /arg3
the fictitious arguments /arg1 /arg2 are not interpreted by CL, which regards them as arguments for the /link option, to be passed to and interpreted by the linker. However, the sequence ends with the line and /arg3 therefore is an argument for the compiler.