7
7
build systems, primarily ninja.
8
8
"""
9
9
10
+ import collections
10
11
import os
11
12
import re
12
13
import subprocess
19
20
windows_quoter_regex = re .compile (r'(\\*)"' )
20
21
21
22
22
- def QuoteForRspFile (arg ):
23
+ def QuoteForRspFile (arg , quote_cmd = True ):
23
24
"""Quote a command line argument so that it appears as one argument when
24
25
processed via cmd.exe and parsed by CommandLineToArgvW (as is typical for
25
26
Windows programs)."""
@@ -36,7 +37,8 @@ def QuoteForRspFile(arg):
36
37
# For a literal quote, CommandLineToArgvW requires 2n+1 backslashes
37
38
# preceding it, and results in n backslashes + the quote. So we substitute
38
39
# in 2* what we match, +1 more, plus the quote.
39
- arg = windows_quoter_regex .sub (lambda mo : 2 * mo .group (1 ) + '\\ "' , arg )
40
+ if quote_cmd :
41
+ arg = windows_quoter_regex .sub (lambda mo : 2 * mo .group (1 ) + '\\ "' , arg )
40
42
41
43
# %'s also need to be doubled otherwise they're interpreted as batch
42
44
# positional arguments. Also make sure to escape the % so that they're
@@ -48,12 +50,17 @@ def QuoteForRspFile(arg):
48
50
# These commands are used in rsp files, so no escaping for the shell (via ^)
49
51
# is necessary.
50
52
51
- # Finally, wrap the whole thing in quotes so that the above quote rule
52
- # applies and whitespace isn't a word break.
53
- return '"' + arg + '"'
53
+ # As a workaround for programs that don't use CommandLineToArgvW, gyp
54
+ # supports msvs_quote_cmd=0, which simply disables all quoting.
55
+ if quote_cmd :
56
+ # Finally, wrap the whole thing in quotes so that the above quote rule
57
+ # applies and whitespace isn't a word break.
58
+ return f'"{ arg } "'
54
59
60
+ return arg
55
61
56
- def EncodeRspFileList (args ):
62
+
63
+ def EncodeRspFileList (args , quote_cmd ):
57
64
"""Process a list of arguments using QuoteCmdExeArgument."""
58
65
# Note that the first argument is assumed to be the command. Don't add
59
66
# quotes around it because then built-ins like 'echo', etc. won't work.
@@ -67,7 +74,8 @@ def EncodeRspFileList(args):
67
74
program = call + " " + os .path .normpath (program )
68
75
else :
69
76
program = os .path .normpath (args [0 ])
70
- return program + " " + " " .join (QuoteForRspFile (arg ) for arg in args [1 :])
77
+ return (program + " " +
78
+ " " .join (QuoteForRspFile (arg , quote_cmd ) for arg in args [1 :]))
71
79
72
80
73
81
def _GenericRetrieve (root , default , path ):
@@ -933,13 +941,22 @@ def BuildCygwinBashCommandLine(self, args, path_to_base):
933
941
)
934
942
return cmd
935
943
936
- def IsRuleRunUnderCygwin (self , rule ):
937
- """Determine if an action should be run under cygwin. If the variable is
938
- unset, or set to 1 we use cygwin."""
939
- return (
940
- int (rule .get ("msvs_cygwin_shell" , self .spec .get ("msvs_cygwin_shell" , 1 )))
941
- != 0
942
- )
944
+ RuleShellFlags = collections .namedtuple ("RuleShellFlags" , ["cygwin" , "quote" ])
945
+
946
+ def GetRuleShellFlags (self , rule ):
947
+ """Return RuleShellFlags about how the given rule should be run. This
948
+ includes whether it should run under cygwin (msvs_cygwin_shell), and
949
+ whether the commands should be quoted (msvs_quote_cmd)."""
950
+ # If the variable is unset, or set to 1 we use cygwin
951
+ cygwin = int (rule .get ("msvs_cygwin_shell" ,
952
+ self .spec .get ("msvs_cygwin_shell" , 1 ))) != 0
953
+ # Default to quoting. There's only a few special instances where the
954
+ # target command uses non-standard command line parsing and handle quotes
955
+ # and quote escaping differently.
956
+ quote_cmd = int (rule .get ("msvs_quote_cmd" , 1 ))
957
+ assert quote_cmd != 0 or cygwin != 1 , \
958
+ "msvs_quote_cmd=0 only applicable for msvs_cygwin_shell=0"
959
+ return MsvsSettings .RuleShellFlags (cygwin , quote_cmd )
943
960
944
961
def _HasExplicitRuleForExtension (self , spec , extension ):
945
962
"""Determine if there's an explicit rule for a particular extension."""
0 commit comments