OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016 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 "tools/gn/qt_creator_writer.h" |
| 6 |
| 7 #include <set> |
| 8 #include <sstream> |
| 9 #include <string> |
| 10 |
| 11 #include "base/files/file_path.h" |
| 12 #include "base/files/file_util.h" |
| 13 #include "base/strings/utf_string_conversions.h" |
| 14 |
| 15 #include "tools/gn/builder.h" |
| 16 #include "tools/gn/config_values_extractors.h" |
| 17 #include "tools/gn/deps_iterator.h" |
| 18 #include "tools/gn/filesystem_utils.h" |
| 19 #include "tools/gn/label.h" |
| 20 #include "tools/gn/loader.h" |
| 21 |
| 22 namespace { |
| 23 base::FilePath::CharType kProjectDirName[] = |
| 24 FILE_PATH_LITERAL("qtcreator_project"); |
| 25 base::FilePath::CharType kProjectName[] = FILE_PATH_LITERAL("all"); |
| 26 base::FilePath::CharType kMainProjectFileSuffix[] = |
| 27 FILE_PATH_LITERAL(".creator"); |
| 28 base::FilePath::CharType kSourcesFileSuffix[] = FILE_PATH_LITERAL(".files"); |
| 29 base::FilePath::CharType kIncludesFileSuffix[] = FILE_PATH_LITERAL(".includes"); |
| 30 base::FilePath::CharType kDefinesFileSuffix[] = FILE_PATH_LITERAL(".config"); |
| 31 } |
| 32 |
| 33 // static |
| 34 bool QtCreatorWriter::RunAndWriteFile(const BuildSettings* build_settings, |
| 35 const Builder* builder, |
| 36 Err* err, |
| 37 const std::string& root_target) { |
| 38 base::FilePath project_dir = |
| 39 build_settings->GetFullPath(build_settings->build_dir()) |
| 40 .Append(kProjectDirName); |
| 41 if (!base::DirectoryExists(project_dir)) { |
| 42 base::File::Error error; |
| 43 if (!base::CreateDirectoryAndGetError(project_dir, &error)) { |
| 44 *err = |
| 45 Err(Location(), "Could not create the QtCreator project directory '" + |
| 46 FilePathToUTF8(project_dir) + "': " + |
| 47 base::File::ErrorToString(error)); |
| 48 return false; |
| 49 } |
| 50 } |
| 51 |
| 52 base::FilePath project_prefix = project_dir.Append(kProjectName); |
| 53 QtCreatorWriter gen(build_settings, builder, project_prefix, root_target); |
| 54 gen.Run(); |
| 55 if (gen.err_.has_error()) { |
| 56 *err = gen.err_; |
| 57 return false; |
| 58 } |
| 59 return true; |
| 60 } |
| 61 |
| 62 QtCreatorWriter::QtCreatorWriter(const BuildSettings* build_settings, |
| 63 const Builder* builder, |
| 64 const base::FilePath& project_prefix, |
| 65 const std::string& root_target_name) |
| 66 : build_settings_(build_settings), |
| 67 builder_(builder), |
| 68 project_prefix_(project_prefix), |
| 69 root_target_name_(root_target_name) {} |
| 70 |
| 71 QtCreatorWriter::~QtCreatorWriter() {} |
| 72 |
| 73 void QtCreatorWriter::CollectDeps(const Target* target) { |
| 74 for (const auto& dep : target->GetDeps(Target::DEPS_ALL)) { |
| 75 const Target* dep_target = dep.ptr; |
| 76 if (targets_.count(dep_target)) |
| 77 continue; |
| 78 targets_.insert(dep_target); |
| 79 CollectDeps(dep_target); |
| 80 } |
| 81 } |
| 82 |
| 83 bool QtCreatorWriter::DiscoverTargets() { |
| 84 auto all_targets = builder_->GetAllResolvedTargets(); |
| 85 |
| 86 if (root_target_name_.empty()) { |
| 87 targets_ = std::set<const Target*>(all_targets.begin(), all_targets.end()); |
| 88 return true; |
| 89 } |
| 90 |
| 91 const Target* root_target = nullptr; |
| 92 for (const Target* target : all_targets) { |
| 93 if (target->label().name() == root_target_name_) { |
| 94 root_target = target; |
| 95 break; |
| 96 } |
| 97 } |
| 98 |
| 99 if (!root_target) { |
| 100 err_ = Err(Location(), "Target '" + root_target_name_ + "' not found."); |
| 101 return false; |
| 102 } |
| 103 |
| 104 targets_.insert(root_target); |
| 105 CollectDeps(root_target); |
| 106 return true; |
| 107 } |
| 108 |
| 109 void QtCreatorWriter::AddToSources(const Target::FileList& files) { |
| 110 for (const SourceFile& file : files) { |
| 111 const std::string& file_path = |
| 112 FilePathToUTF8(build_settings_->GetFullPath(file)); |
| 113 sources_.insert(file_path); |
| 114 } |
| 115 } |
| 116 |
| 117 void QtCreatorWriter::HandleTarget(const Target* target) { |
| 118 SourceFile build_file = Loader::BuildFileForLabel(target->label()); |
| 119 sources_.insert(FilePathToUTF8(build_settings_->GetFullPath(build_file))); |
| 120 AddToSources(target->settings()->import_manager().GetImportedFiles()); |
| 121 |
| 122 AddToSources(target->sources()); |
| 123 AddToSources(target->public_headers()); |
| 124 AddToSources(target->inputs()); |
| 125 |
| 126 for (ConfigValuesIterator it(target); !it.done(); it.Next()) { |
| 127 SourceFile precompiled_source = it.cur().precompiled_source(); |
| 128 if (!precompiled_source.is_null()) { |
| 129 sources_.insert( |
| 130 FilePathToUTF8(build_settings_->GetFullPath(precompiled_source))); |
| 131 } |
| 132 |
| 133 for (const SourceDir& include_dir : it.cur().include_dirs()) { |
| 134 includes_.insert( |
| 135 FilePathToUTF8(build_settings_->GetFullPath(include_dir))); |
| 136 } |
| 137 |
| 138 for (std::string define : it.cur().defines()) { |
| 139 size_t equal_pos = define.find('='); |
| 140 if (equal_pos != std::string::npos) |
| 141 define[equal_pos] = ' '; |
| 142 define.insert(0, "#define "); |
| 143 defines_.insert(define); |
| 144 } |
| 145 } |
| 146 } |
| 147 |
| 148 void QtCreatorWriter::GenerateFile(const base::FilePath::CharType* suffix, |
| 149 const std::set<std::string>& items) { |
| 150 const base::FilePath file_path = project_prefix_.AddExtension(suffix); |
| 151 std::ostringstream output; |
| 152 for (const std::string& item : items) |
| 153 output << item << std::endl; |
| 154 WriteFileIfChanged(file_path, output.str(), &err_); |
| 155 } |
| 156 |
| 157 void QtCreatorWriter::Run() { |
| 158 if (!DiscoverTargets()) |
| 159 return; |
| 160 |
| 161 for (const Target* target : targets_) { |
| 162 if (target->toolchain()->label() != |
| 163 builder_->loader()->GetDefaultToolchain()) |
| 164 continue; |
| 165 HandleTarget(target); |
| 166 } |
| 167 |
| 168 std::set<std::string> empty_list; |
| 169 |
| 170 GenerateFile(kMainProjectFileSuffix, empty_list); |
| 171 GenerateFile(kSourcesFileSuffix, sources_); |
| 172 GenerateFile(kIncludesFileSuffix, includes_); |
| 173 GenerateFile(kDefinesFileSuffix, defines_); |
| 174 } |
OLD | NEW |