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