Repository: SCons/scons

Issue:
SCons command line empty quotes "" as "." targets
This issue was originally created at: 2014-12-29 11:06:47.
This issue was reported by: `farmersez`.

farmersez said at 2014-12-29 11:06:47
>I messed around with this for about 5-6 days. We're compiling our project using SCons that's being run by another tool. Our tool's configurations can pass different flag to SCons, and the default value is an empty string (""). For instance, we can set the field to be `foobar` and the SCons call will be `scons --foobar`.
> 
>On one of our projects configurations we didn't specify any special flags, so the call to scons (from the SConstruct dir) was:
```
scons "" -j8
```
>This caused a rather annoying thing to happen - In this project configuration we only wanted a part of the source to be compiled, but this extra param was causing the whole tree to be compiled.
> 
>This will also reproduce in version 2.3.4 - the problem is in `SCons/Script/Main.py`:969 (in version 2.3.4).
> 
>The part that extracts targets from the args list does not evalueate if the current argument is an empty one or not:
```
    targets = []
    xmit_args = []
    for a in parser.largs:
        if a[:1] == '-':
            continue
        if '=' in a:
            xmit_args.append(a)
        else:
            targets.append(a)
```
>The last "else" should be changed to "elif a:", then empty strings will not be accounted for.
> 
>Another interesting part is that later on `targets` was a list containing only an empty string (`['']`), and the `fs.Dir` object converted '' to '.', meaning the current directory.
> 
>Cheers,
>S.

dirkbaechle said at 2015-02-12 13:58:03
>*** Issue 2919 has been marked as a duplicate of this issue. ***


dirkbaechle said this issue is duplicated by #2919 at 2015-02-12 13:58:03.



Discussion:
This seems a simple enough fix. I'd do it like this, I think:
```
     for a in parser.largs:
-        if a[:1] == '-':
+        if not a or a.startswith('-'):
             continue
```
worth pushing? don't have a specific test for it.
> This seems a simple enough fix. I'd do it like this, I think:
> 
> ```
>      for a in parser.largs:
> -        if a[:1] == '-':
> +        if not a or a.startswith('-'):
>              continue
> ```
> 
> worth pushing? don't have a specific test for it.

Does "" end up being a False value, or does the string get '""' ?
an empty string is false, but I'm not sure what happens here - what if we get passed a string containing an empty string?  Guess it does need a repro.
Okay, this:
```python
q = Textfile(target="foo", source="foostuff")
Textfile(target="bar", source="barstuff")
Default(q)
```
```
$ scons -n
scons: done reading SConscript files.
scons: Building targets ...
Creating 'foo.txt'
scons: done building targets.
$ scons -n .
scons: done reading SConscript files.
scons: Building targets ...
Creating 'bar.txt'
Creating 'foo.txt'
scons: done building targets.
$ scons -n ""
scons: done reading SConscript files.
scons: Building targets ...
Creating 'bar.txt'
Creating 'foo.txt'
scons: done building targets.
```

After the suggested change the third version ... Sigh - edited. Comes out like the first, rather than the second.
Is the title of this bug wrong? Shouldn't it be empty quotes?
seems like it, yes
hmm. seems like "" should === all the Defaults()?
yeah, that's borne out by the test... the third version flips from behaving like the target was "." to none, thus picking up the target set by Deault.
I can't write an E2E test for this, apparently. 

The E2E framework seems to add extra quoting so the failure differs. `Do not know how to make file target '""'` (quote dblquote pair quote)

Resolving patch:
diff --git a/SCons/Script/Main.py b/SCons/Script/Main.py
--- a/SCons/Script/Main.py
+++ b/SCons/Script/Main.py
@@ -984,13 +984,17 @@ def _main(parser):
     if options.interactive:
         SCons.Node.interactive = True
 
-    # That should cover (most of) the options.  Next, set up the variables
-    # that hold command-line arguments, so the SConscript files that we
-    # read and execute have access to them.
+    # That should cover (most of) the options.
+    # Next, set up the variables that hold command-line arguments,
+    # so the SConscript files that we read and execute have access to them.
+    # TODO: for options defined via AddOption which take space-separated
+    # option-args, the option-args will collect into targets here,
+    # because we don't yet know to do any different.
     targets = []
     xmit_args = []
     for a in parser.largs:
-        if a[:1] == '-':
+        # Skip so-far unrecognized options, and empty string args
+        if a.startswith('-') or a in ('', '""', "''"):
             continue
         if '=' in a:
             xmit_args.append(a)


Test patch:
diff --git a/test/TARGETS.py b/test/TARGETS.py
--- a/test/TARGETS.py
+++ b/test/TARGETS.py
@@ -1,6 +1,8 @@
 #!/usr/bin/env python
 #
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright The SCons Foundation
 #
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the
@@ -20,9 +22,6 @@
 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 """
 Test use of the COMMAND_LINE_TARGETS and DEFAULT_TARGETS variables.
@@ -137,6 +136,21 @@
 
 
 
+# blanks in cmdline should not be treated as targets (issue 2986)
+test.write(
+    file='SConstruct',
+    content="""\
+tgt_foo = Textfile(target="foo", source="foostuff")
+tgt_bar = Textfile(target="bar", source="bartuff")
+Default(tgt_foo)
+""",
+)
+test.run(arguments=["-Q", "-n", "''"], stdout="Creating 'foo.txt'\n")
+test.run(arguments=["-Q", "-n", ""], stdout="Creating 'foo.txt'\n")
+test.run(arguments=["-Q", "-n", '""'], stdout="Creating 'foo.txt'\n")
+
+
+
 test.pass_test()
 
 # Local Variables: