• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <sstream>
6 
7 #include "base/files/file_util.h"
8 #include "base/strings/string_split.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "gn/build_settings.h"
12 #include "gn/err.h"
13 #include "gn/filesystem_utils.h"
14 #include "gn/functions.h"
15 #include "gn/input_file.h"
16 #include "gn/output_conversion.h"
17 #include "gn/parse_tree.h"
18 #include "gn/scheduler.h"
19 #include "gn/string_output_buffer.h"
20 #include "util/build_config.h"
21 
22 namespace functions {
23 
24 const char kWriteFile[] = "write_file";
25 const char kWriteFile_HelpShort[] = "write_file: Write a file to disk.";
26 const char kWriteFile_Help[] =
27     R"(write_file: Write a file to disk.
28 
29   write_file(filename, data, output_conversion = "")
30 
31   If data is a list, the list will be written one-item-per-line with no quoting
32   or brackets.
33 
34   If the file exists and the contents are identical to that being written, the
35   file will not be updated. This will prevent unnecessary rebuilds of targets
36   that depend on this file.
37 
38   One use for write_file is to write a list of inputs to an script that might
39   be too long for the command line. However, it is preferable to use response
40   files for this purpose. See "gn help response_file_contents".
41 
42 Arguments
43 
44   filename
45       Filename to write. This must be within the output directory.
46 
47   data
48       The list or string to write.
49 
50   output_conversion
51     Controls how the output is written. See `gn help io_conversion`.
52 )";
53 
RunWriteFile(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,Err * err)54 Value RunWriteFile(Scope* scope,
55                    const FunctionCallNode* function,
56                    const std::vector<Value>& args,
57                    Err* err) {
58   if (args.size() != 3 && args.size() != 2) {
59     *err = Err(function->function(), "Wrong number of arguments to write_file",
60                "I expected two or three arguments.");
61     return Value();
62   }
63 
64   // Compute the file name and make sure it's in the output dir.
65   const SourceDir& cur_dir = scope->GetSourceDir();
66   SourceFile source_file = cur_dir.ResolveRelativeFile(
67       args[0], err, scope->settings()->build_settings()->root_path_utf8());
68   if (err->has_error())
69     return Value();
70   if (!EnsureStringIsInOutputDir(
71           scope->settings()->build_settings()->build_dir(), source_file.value(),
72           args[0].origin(), err))
73     return Value();
74   g_scheduler->AddWrittenFile(source_file);  // Track that we wrote this file.
75 
76   // Track how to recreate this file, since we write it a gen time.
77   // Note this is a hack since the correct output is not a dependency proper,
78   // but an addition of this file to the output of the gn rule that writes it.
79   // This dependency will, however, cause the gen step to be re-run and the
80   // build restarted if the file is missing.
81   g_scheduler->AddGenDependency(
82       scope->settings()->build_settings()->GetFullPath(source_file));
83 
84   // Extract conversion value.
85   Value output_conversion;
86   if (args.size() != 3)
87     output_conversion = Value();
88   else
89     output_conversion = args[2];
90 
91   // Compute output.
92   StringOutputBuffer storage;
93   std::ostream contents(&storage);
94   ConvertValueToOutput(scope->settings(), args[1], output_conversion, contents,
95                        err);
96   if (err->has_error())
97     return Value();
98 
99   base::FilePath file_path =
100       scope->settings()->build_settings()->GetFullPath(source_file);
101 
102   // Make sure we're not replacing the same contents.
103   if (!storage.WriteToFileIfChanged(file_path, err)) {
104     *err = Err(function->function(), err->message(), err->help_text());
105     return Value();
106   }
107 
108   return Value();
109 }
110 
111 }  // namespace functions
112