function main(args) {
  const inputPaths = [];
  let outputPath;

  for (let i = 0; i < args.length; ++i) {
    if (args[i] == '--output') {
      outputPath = args[i + 1];
      ++i;
    } else {
      inputPaths.push(args[i]);
    }
  }
  assert(outputPath, 'You must specify output file with --output <EXTERNS>');
  assert(inputPaths.length, 'You must specify at least one input file.');

  // Generate externs for all input paths.
  const names = new Set();
  const results = inputPaths.map((path) => generateExterns(names, path));

  // TODO: revisit this when the compiler supports partially-exported classes.
  if (partiallyExportedClassesDetected) {
    throw new Error(
        'Partially exported classes are not supported in the compiler!');
  }

  // Sort them in dependency order.
  const sorted = topologicalSort(results, /* getDeps= */ (object) => {
    return object.requires.map((id) => {
      const dep = results.find((x) => x.provides.includes(id));
      assert(dep, 'Cannot find dependency: ' + id);
      return dep;
    });
  });

  // Generate namespaces for all externs.  For example, if we extern
  // foo.bar.baz, foo and foo.bar will both need to be declared first.
  const namespaces = new Set();
  const namespaceDeclarations = [];
  for (const name of Array.from(names).sort()) {
    // Add the full name "foo.bar.baz" and its prototype ahead of time.  We
    // should never generate these as namespaces.
    namespaces.add(name);
    namespaces.add(name + '.prototype');

    // For name "foo.bar.baz", iterate over partialName "foo" and "foo.bar".
    const pieces = name.split('.');
    for (let i = 1; i < pieces.length; ++i) {
      const partialName = pieces.slice(0, i).join('.');
      if (!namespaces.has(partialName)) {
        let declaration;
        if (i == 1) {
          declaration = '/** @namespace */\n';
          declaration += 'window.';
        } else {
          declaration = '/** @const */\n';
        }
        declaration += partialName + ' = {};\n';
        namespaceDeclarations.push(declaration);
        namespaces.add(partialName);
      }
    }
  }

  // Get externs.
  const externs = sorted.map((x) => x.externs).join('');

  // Get license header.
  const licenseHeader = fs.readFileSync(__dirname + '/license-header', 'utf-8');

  // Output generated externs, with an appropriate header.
  fs.writeFileSync(outputPath,
      licenseHeader +
      '/**\n' +
      ' * @fileoverview Generated externs.  DO NOT EDIT!\n' +
      ' * @externs\n' +
      ' * @suppress {constantProperty, duplicate} To prevent compiler\n' +
      ' *   errors with the namespace being declared both here and by\n' +
      ' *   goog.provide in the library.\n' +
      ' */\n\n' +
      namespaceDeclarations.join('') + '\n' + externs);
}
Generate externs from exported code.
Arguments: --output <EXTERNS> <INPUT> [<INPUT> ...]

@param {!Array<string>} args The args to this script, not counting node and
  the script name itself.