#include <sstream>
#include "base/files/file_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "gn/build_settings.h"
#include "gn/err.h"
#include "gn/filesystem_utils.h"
#include "gn/functions.h"
#include "gn/input_file.h"
#include "gn/output_conversion.h"
#include "gn/parse_tree.h"
#include "gn/scheduler.h"
#include "gn/string_output_buffer.h"
#include "util/build_config.h"
namespace functions {
const char kWriteFile[] = "write_file";
const char kWriteFile_HelpShort[] = "write_file: Write a file to disk.";
const char kWriteFile_Help[] =
R"(write_file: Write a file to disk.
write_file(filename, data, output_conversion = "")
If data is a list, the list will be written one-item-per-line with no quoting
or brackets.
If the file exists and the contents are identical to that being written, the
file will not be updated. This will prevent unnecessary rebuilds of targets
that depend on this file.
One use for write_file is to write a list of inputs to an script that might
be too long for the command line. However, it is preferable to use response
files for this purpose. See "gn help response_file_contents".
Arguments
filename
Filename to write. This must be within the output directory.
data
The list or string to write.
output_conversion
Controls how the output is written. See `gn help io_conversion`.
)";
Value RunWriteFile(Scope* scope,
const FunctionCallNode* function,
const std::vector<Value>& args,
Err* err) {
if (args.size() != 3 && args.size() != 2) {
*err = Err(function->function(), "Wrong number of arguments to write_file",
"I expected two or three arguments.");
return Value();
}
const SourceDir& cur_dir = scope->GetSourceDir();
SourceFile source_file = cur_dir.ResolveRelativeFile(
args[0], err, scope->settings()->build_settings()->root_path_utf8());
if (err->has_error())
return Value();
if (!EnsureStringIsInOutputDir(
scope->settings()->build_settings()->build_dir(), source_file.value(),
args[0].origin(), err))
return Value();
g_scheduler->AddWrittenFile(source_file);
g_scheduler->AddGenDependency(
scope->settings()->build_settings()->GetFullPath(source_file));
Value output_conversion;
if (args.size() != 3)
output_conversion = Value();
else
output_conversion = args[2];
StringOutputBuffer storage;
std::ostream contents(&storage);
ConvertValueToOutput(scope->settings(), args[1], output_conversion, contents,
err);
if (err->has_error())
return Value();
base::FilePath file_path =
scope->settings()->build_settings()->GetFullPath(source_file);
if (!storage.WriteToFileIfChanged(file_path, err)) {
*err = Err(function->function(), err->message(), err->help_text());
return Value();
}
return Value();
}
}