android: Handle inputs with spaces inside make functions.

A chromium gyp rule for generating assembly offsets for libvpx/webrtc
needs to be able to refer to $(call ...) macros from the Android build
system internals in order to function, but the gyp backend currently
rejects input and output names that include spaces as a sanity check to
prevent make from misinterpreting a filename with whitespace as two
files.

Skip this check in the case where the input or output filename starts
with '$(' so that make macros are not rejected. Add two test cases: one
to check that normal filenames with spaces are forbidden, and one to
check that using a make macro as an input definitely works.

BUG=gyp:432
R=sbc@chromium.org

Review URL: https://codereview.chromium.org/310833002

git-svn-id: http://gyp.googlecode.com/svn/trunk@1927 78cadc50-ecff-11dd-a971-7dbc132099af
diff --git a/pylib/gyp/generator/android.py b/pylib/gyp/generator/android.py
index 3988474..3c95143 100644
--- a/pylib/gyp/generator/android.py
+++ b/pylib/gyp/generator/android.py
@@ -317,12 +317,19 @@
       self.WriteLn('%s: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))'
                    % main_output)
 
+      # Don't allow spaces in input/output filenames, but make an exception for
+      # filenames which start with '$(' since it's okay for there to be spaces
+      # inside of make function/macro invocations.
       for input in inputs:
-        assert ' ' not in input, (
-            "Spaces in action input filenames not supported (%s)"  % input)
+        if not input.startswith('$(') and ' ' in input:
+          raise gyp.common.GypError(
+              'Action input filename "%s" in target %s contains a space' %
+              (input, self.target))
       for output in outputs:
-        assert ' ' not in output, (
-            "Spaces in action output filenames not supported (%s)"  % output)
+        if not output.startswith('$(') and ' ' in output:
+          raise gyp.common.GypError(
+              'Action output filename "%s" in target %s contains a space' %
+              (output, self.target))
 
       self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES)' %
                    (main_output, ' '.join(map(self.LocalPathify, inputs))))
diff --git a/test/android/file.in b/test/android/file.in
new file mode 100644
index 0000000..68016f0
--- /dev/null
+++ b/test/android/file.in
@@ -0,0 +1 @@
+A boring test file
diff --git a/test/android/gyptest-make-functions.py b/test/android/gyptest-make-functions.py
new file mode 100755
index 0000000..cdf0e0e
--- /dev/null
+++ b/test/android/gyptest-make-functions.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2014 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Verifies that it's possible for gyp actions to use the result of calling a make
+function with "$()".
+"""
+
+import TestGyp
+
+test = TestGyp.TestGyp(formats=['android'])
+
+test.run_gyp('make_functions.gyp')
+
+test.build('make_functions.gyp', test.ALL)
+
+file_content = 'A boring test file\n'
+test.built_file_must_match('file.in', file_content)
+test.built_file_must_match('file.out', file_content)
+
+test.pass_test()
diff --git a/test/android/gyptest-space-filenames.py b/test/android/gyptest-space-filenames.py
new file mode 100755
index 0000000..c6caf26
--- /dev/null
+++ b/test/android/gyptest-space-filenames.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2014 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Verifies that action input/output filenames with spaces are rejected.
+"""
+
+import TestGyp
+
+test = TestGyp.TestGyp(formats=['android'])
+
+stderr = ('gyp: Action input filename "name with spaces" in target do_actions '
+          'contains a space\n')
+test.run_gyp('space_filenames.gyp', status=1, stderr=stderr)
+
+test.pass_test()
diff --git a/test/android/make_functions.gyp b/test/android/make_functions.gyp
new file mode 100644
index 0000000..4b617cc
--- /dev/null
+++ b/test/android/make_functions.gyp
@@ -0,0 +1,31 @@
+# Copyright (c) 2014 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'targets': [
+    {
+      'target_name': 'file-in',
+      'type': 'none',
+      'copies': [
+        {
+          'destination': '<(PRODUCT_DIR)',
+          'files': [ 'file.in' ],
+        },
+      ],
+    },
+    {
+      'target_name': 'file-out',
+      'type': 'none',
+      'dependencies': [ 'file-in' ],
+      'actions': [
+        {
+          'action_name': 'copy-file',
+          'inputs': [ '$(strip <(PRODUCT_DIR)/file.in)' ],
+          'outputs': [ '<(PRODUCT_DIR)/file.out' ],
+          'action': [ 'cp', '$(strip <(PRODUCT_DIR)/file.in)', '<(PRODUCT_DIR)/file.out' ],
+        }
+      ],
+    },
+  ],
+}
diff --git a/test/android/space_filenames.gyp b/test/android/space_filenames.gyp
new file mode 100644
index 0000000..487ac55
--- /dev/null
+++ b/test/android/space_filenames.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2014 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'targets': [
+    {
+      'target_name': 'do_actions',
+      'type': 'none',
+      'actions': [{
+        'action_name': 'should_be_forbidden',
+        'inputs': [ 'name with spaces' ],
+        'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/name with spaces' ],
+        'action': [ 'true' ],
+      }],
+    },
+  ],
+}