| // 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 += "<"; | |
| 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<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)); | |
| } | |
| } | |
| } | |
| } |