1d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// found in the LICENSE file.
4d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
5a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/atomicops.h"
6d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/bind.h"
7d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/command_line.h"
8d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/strings/string_number_conversions.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/timer/elapsed_timer.h"
10d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/build_settings.h"
11d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/commands.h"
12d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/ninja_target_writer.h"
13d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/ninja_writer.h"
14d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scheduler.h"
15d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/setup.h"
16d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/standard_out.h"
1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "tools/gn/target.h"
18d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
19a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace commands {
20a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochnamespace {
22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Suppress output on success.
24d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kSwitchQuiet[] = "q";
25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kSwitchCheck[] = "check";
27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Called on worker thread to write the ninja file.
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BackgroundDoWrite(const Target* target) {
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  NinjaTargetWriter::RunAndWriteFile(target);
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  g_scheduler->DecrementWorkCount();
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Called on the main thread.
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ItemResolvedCallback(base::subtle::Atomic32* write_counter,
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          scoped_refptr<Builder> builder,
37e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                          const BuilderRecord* record) {
38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::subtle::NoBarrier_AtomicIncrement(write_counter, 1);
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
40e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  const Item* item = record->item();
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const Target* target = item->AsTarget();
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (target) {
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    g_scheduler->IncrementWorkCount();
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    g_scheduler->ScheduleWork(base::Bind(&BackgroundDoWrite, target));
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
48d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}  // namespace
49d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kGen[] = "gen";
51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kGen_HelpShort[] =
52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "gen: Generate ninja files.";
53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kGen_Help[] =
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    "gn gen: Generate ninja files.\n"
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    "\n"
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    "  gn gen <output_directory>\n"
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    "\n"
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    "  Generates ninja files from the current tree and puts them in the given\n"
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    "  output directory.\n"
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    "\n"
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    "  The output directory can be a source-repo-absolute path name such as:\n"
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    "      //out/foo\n"
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    "  Or it can be a directory relative to the current directory such as:\n"
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    "      out/foo\n"
65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  See \"gn help\" for the common command-line switches.\n";
67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int RunGen(const std::vector<std::string>& args) {
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ElapsedTimer timer;
70d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (args.size() != 1) {
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    Err(Location(), "Need exactly one build directory to generate.",
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        "I expected something more like \"gn gen out/foo\"\n"
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        "You can also see \"gn help gen\".").PrintToStdout();
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return 1;
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
78d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Deliberately leaked to avoid expensive process teardown.
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Setup* setup = new Setup();
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!setup->DoSetup(args[0], true))
81d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return 1;
82d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (CommandLine::ForCurrentProcess()->HasSwitch(kSwitchCheck))
84c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    setup->set_check_public_headers(true);
85c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Cause the load to also generate the ninja files for each target. We wrap
87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // the writing to maintain a counter.
88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::subtle::Atomic32 write_counter = 0;
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  setup->builder()->set_resolved_callback(
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(&ItemResolvedCallback, &write_counter,
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 scoped_refptr<Builder>(setup->builder())));
92d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
93d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Do the actual load. This will also write out the target ninja files.
94d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!setup->Run())
95d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return 1;
96d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
97d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Write the root ninja files.
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!NinjaWriter::RunAndWriteFiles(&setup->build_settings(),
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     setup->builder()))
100d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return 1;
101d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::TimeDelta elapsed_time = timer.Elapsed();
103d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
104d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!CommandLine::ForCurrentProcess()->HasSwitch(kSwitchQuiet)) {
105d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    OutputString("Done. ", DECORATION_GREEN);
106d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::string stats = "Wrote " +
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        base::IntToString(static_cast<int>(write_counter)) +
109d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        " targets from " +
110d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        base::IntToString(
111d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch            setup->scheduler().input_file_manager()->GetInputFileCount()) +
112d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        " files in " +
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::IntToString(elapsed_time.InMilliseconds()) + "ms\n";
114d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    OutputString(stats);
115d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
116d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
117d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return 0;
118d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace commands
121