// 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 #include #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 += "<"; else if (c == '>') result += ">"; else if (c == '&') result += "&"; 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 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 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_ << "" << std::endl; XmlElementWriter cdt_properties_element(out_, "cdtprojectproperties", XmlAttributes()); { const char* kIncludesSectionName = "org.eclipse.cdt.internal.ui.wizards.settingswizards.IncludePaths"; std::unique_ptr 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 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 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 language_element = section_element->SubElement("language", XmlAttributes("name", language)); for (const auto& key_val : defines_) { std::unique_ptr macro_element = language_element->SubElement("macro"); macro_element->SubElement("name")->Text(EscapeForXML(key_val.first)); macro_element->SubElement("value")->Text(EscapeForXML(key_val.second)); } } } }