blob: 720231b4015b6198d23f3909fbcefcb6da382e1b [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "tools/gn/eclipse_writer.h"
#include <fstream>
#include <memory>
#include "base/files/file_path.h"
#include "tools/gn/builder.h"
#include "tools/gn/config_values_extractors.h"
#include "tools/gn/filesystem_utils.h"
#include "tools/gn/loader.h"
#include "tools/gn/xml_element_writer.h"
namespace {
// Escapes |unescaped| for use in XML element content.
std::string EscapeForXML(const std::string& unescaped) {
std::string result;
result.reserve(unescaped.length());
for (const char c : unescaped) {
if (c == '<')
result += "&lt;";
else if (c == '>')
result += "&gt;";
else if (c == '&')
result += "&amp;";
else
result.push_back(c);
}
return result;
}
} // namespace
EclipseWriter::EclipseWriter(const BuildSettings* build_settings,
const Builder& builder,
std::ostream& out)
: build_settings_(build_settings), builder_(builder), out_(out) {
languages_.push_back("C++ Source File");
languages_.push_back("C Source File");
languages_.push_back("Assembly Source File");
languages_.push_back("GNU C++");
languages_.push_back("GNU C");
languages_.push_back("Assembly");
}
EclipseWriter::~EclipseWriter() = default;
// static
bool EclipseWriter::RunAndWriteFile(
const BuildSettings* build_settings,
const Builder& builder,
Err* err) {
base::FilePath file = build_settings->GetFullPath(build_settings->build_dir())
.AppendASCII("eclipse-cdt-settings.xml");
std::ofstream file_out;
file_out.open(FilePathToUTF8(file).c_str(),
std::ios_base::out | std::ios_base::binary);
if (file_out.fail()) {
*err =
Err(Location(), "Couldn't open eclipse-cdt-settings.xml for writing");
return false;
}
EclipseWriter gen(build_settings, builder, file_out);
gen.Run();
return true;
}
void EclipseWriter::Run() {
GetAllIncludeDirs();
GetAllDefines();
WriteCDTSettings();
}
void EclipseWriter::GetAllIncludeDirs() {
std::vector<const Target*> targets = builder_.GetAllResolvedTargets();
for (const Target* target : targets) {
if (!UsesDefaultToolchain(target))
continue;
for (ConfigValuesIterator it(target); !it.done(); it.Next()) {
for (const SourceDir& include_dir : it.cur().include_dirs()) {
include_dirs_.insert(
FilePathToUTF8(build_settings_->GetFullPath(include_dir)));
}
}
}
}
void EclipseWriter::GetAllDefines() {
std::vector<const Target*> targets = builder_.GetAllResolvedTargets();
for (const Target* target : targets) {
if (!UsesDefaultToolchain(target))
continue;
for (ConfigValuesIterator it(target); !it.done(); it.Next()) {
for (const std::string& define : it.cur().defines()) {
size_t equal_pos = define.find('=');
std::string define_key;
std::string define_value;
if (equal_pos == std::string::npos) {
define_key = define;
} else {
define_key = define.substr(0, equal_pos);
define_value = define.substr(equal_pos + 1);
}
defines_[define_key] = define_value;
}
}
}
}
bool EclipseWriter::UsesDefaultToolchain(const Target* target) const {
return target->toolchain()->label() ==
builder_.loader()->GetDefaultToolchain();
}
void EclipseWriter::WriteCDTSettings() {
out_ << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
XmlElementWriter cdt_properties_element(out_, "cdtprojectproperties",
XmlAttributes());
{
const char* kIncludesSectionName =
"org.eclipse.cdt.internal.ui.wizards.settingswizards.IncludePaths";
std::unique_ptr<XmlElementWriter> section_element =
cdt_properties_element.SubElement(
"section", XmlAttributes("name", kIncludesSectionName));
section_element->SubElement(
"language", XmlAttributes("name", "holder for library settings"));
for (const std::string& language : languages_) {
std::unique_ptr<XmlElementWriter> language_element =
section_element->SubElement("language",
XmlAttributes("name", language));
for (const std::string& include_dir : include_dirs_) {
language_element
->SubElement("includepath",
XmlAttributes("workspace_path", "false"))
->Text(EscapeForXML(include_dir));
}
}
}
{
const char* kMacrosSectionName =
"org.eclipse.cdt.internal.ui.wizards.settingswizards.Macros";
std::unique_ptr<XmlElementWriter> section_element =
cdt_properties_element.SubElement(
"section", XmlAttributes("name", kMacrosSectionName));
section_element->SubElement(
"language", XmlAttributes("name", "holder for library settings"));
for (const std::string& language : languages_) {
std::unique_ptr<XmlElementWriter> language_element =
section_element->SubElement("language",
XmlAttributes("name", language));
for (const auto& key_val : defines_) {
std::unique_ptr<XmlElementWriter> macro_element =
language_element->SubElement("macro");
macro_element->SubElement("name")->Text(EscapeForXML(key_val.first));
macro_element->SubElement("value")->Text(EscapeForXML(key_val.second));
}
}
}
}