Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / native_client / build / build_nexe.py
index cb04234..a6f144b 100644 (file)
@@ -121,6 +121,25 @@ def IsEnvFlagTrue(flag_name, default=False):
   return bool(re.search(r'^([tTyY]|1:?)', flag_value))
 
 
+def GetIntegerEnv(flag_name, default=0):
+  """Parses and returns integer environment variable.
+
+  Args:
+    flag_name: a string name of a flag.
+    default: default return value if the flag is not set.
+
+  Returns:
+    Integer value of the flag.
+  """
+  flag_value = os.environ.get(flag_name)
+  if flag_value is None:
+    return default
+  try:
+    return int(flag_value)
+  except ValueError:
+    raise Error('Invalid ' + flag_name + ': ' + flag_value)
+
+
 class Builder(object):
   """Builder object maintains options and generates build command-lines.
 
@@ -149,18 +168,18 @@ class Builder(object):
     if len(build_type) > 2 and build_type[2] == 'pnacl':
       self.is_pnacl_toolchain = True
 
+    if arch.endswith('-nonsfi'):
+      arch = arch[:-len('-nonsfi')]
+
     if arch in ['x86-32', 'x86-64']:
       mainarch = 'x86'
-      self.subarch = arch.split('-')[1]
       self.tool_prefix = 'x86_64-nacl-'
     elif arch == 'arm':
-      self.subarch = ''
       self.tool_prefix = 'arm-nacl-'
       mainarch = 'arm'
     elif arch == 'mips':
       self.is_pnacl_toolchain = True
     elif arch == 'pnacl':
-      self.subarch = ''
       self.is_pnacl_toolchain = True
     else:
       raise Error('Toolchain architecture %s not supported.' % arch)
@@ -179,9 +198,12 @@ class Builder(object):
 
     if self.is_pnacl_toolchain:
       self.tool_prefix = 'pnacl-'
-      tooldir = '%s_pnacl' % self.osname
+      tool_subdir = 'pnacl_newlib'
     else:
-      tooldir = '%s_%s_%s' % (self.osname, mainarch, toolname)
+      tool_subdir = 'nacl_%s_%s' % (mainarch, toolname)
+
+    build_arch = pynacl.platform.GetArch()
+    tooldir = os.path.join('%s_%s' % (self.osname, build_arch), tool_subdir)
 
     self.root_path = options.root
     self.nacl_path = os.path.join(self.root_path, 'native_client')
@@ -215,6 +237,7 @@ class Builder(object):
     goma_config = self.GetGomaConfig(options.gomadir, arch, toolname)
     self.gomacc = goma_config.get('gomacc', '')
     self.goma_burst = goma_config.get('burst', False)
+    self.goma_threads = goma_config.get('threads', 1)
 
     # Use unoptimized native objects for debug IRT builds for faster compiles.
     if (self.is_pnacl_toolchain
@@ -481,11 +504,10 @@ class Builder(object):
           self.Log('Strange gomacc %s found, try another one: %s' % (gomacc, e))
 
     if goma_config:
-      default_value = False
-      if self.osname == 'linux':
-        default_value = True
-      goma_config['burst'] = IsEnvFlagTrue('NACL_GOMA_BURST',
-                                           default=default_value)
+      goma_config['burst'] = IsEnvFlagTrue('NACL_GOMA_BURST')
+      default_threads = 100 if self.osname == 'linux' else 1
+      goma_config['threads'] = GetIntegerEnv('NACL_GOMA_THREADS',
+                                             default=default_threads)
     return goma_config
 
   def NeedsRebuild(self, outd, out, src, rebuilt=False):
@@ -527,7 +549,13 @@ class Builder(object):
     deps = deps.replace('\\\n', ' ')
     deps = deps.replace('\n', '')
     # The dependencies are whitespace delimited following the first ':'
-    deps = deps.split(':', 1)[1]
+    # (that is not part of a windows drive letter)
+    deps = deps.split(':', 1)
+    if pynacl.platform.IsWindows() and len(deps[0]) == 1:
+      # The path has a drive letter, find the next ':'
+      deps = deps[1].split(':', 1)[1]
+    else:
+      deps = deps[1]
     deps = deps.split()
     if pynacl.platform.IsWindows():
       deps = [self.FixWindowsPath(d) for d in deps]
@@ -917,22 +945,41 @@ def Main(argv):
       build.Translate(list(files)[0])
       return 0
 
-    if build.gomacc and build.goma_burst:  # execute gomacc as many as possible.
+    if build.gomacc and (build.goma_burst or build.goma_threads > 1):
       returns = Queue.Queue()
-      def CompileThread(filename, queue):
+
+      # Push all files into the inputs queue
+      inputs = Queue.Queue()
+      for filename in files:
+        inputs.put(filename)
+
+      def CompileThread(input_queue, output_queue):
         try:
-          queue.put(build.Compile(filename))
+          while True:
+            try:
+              filename = input_queue.get_nowait()
+            except Queue.Empty:
+              return
+            output_queue.put(build.Compile(filename))
         except Exception:
           # Put current exception info to the queue.
-          queue.put(sys.exc_info())
-      build_threads = []
+          output_queue.put(sys.exc_info())
+
+      # Don't limit number of threads in the burst mode.
+      if build.goma_burst:
+        num_threads = len(files)
+      else:
+        num_threads = min(build.goma_threads, len(files))
+
       # Start parallel build.
-      for filename in files:
-        thr = threading.Thread(target=CompileThread, args=(filename, returns))
+      build_threads = []
+      for _ in xrange(num_threads):
+        thr = threading.Thread(target=CompileThread, args=(inputs, returns))
         thr.start()
         build_threads.append(thr)
-      for thr in build_threads:
-        thr.join()
+
+      # Wait for results.
+      for _ in files:
         out = returns.get()
         # An exception raised in the thread may come through the queue.
         # Raise it again here.
@@ -941,6 +988,15 @@ def Main(argv):
           raise out[0], None, out[2]
         elif out:
           objs.append(out)
+
+      assert inputs.empty()
+
+      # Wait until all threads have stopped and verify that there are no more
+      # results.
+      for thr in build_threads:
+        thr.join()
+      assert returns.empty()
+
     else:  # slow path.
       for filename in files:
         out = build.Compile(filename)