Define C/C++ version for QtCreator project Fix problem due to wrong parse C++14/17 features etc. Change-Id: I07cab1487902683c3deeea67242d648264906ee1 Reviewed-on: https://gn-review.googlesource.com/c/3060 Reviewed-by: Dirk Pranke <dpranke@google.com> Reviewed-by: Scott Graham <scottmg@chromium.org> Commit-Queue: Dirk Pranke <dpranke@google.com>
diff --git a/tools/gn/qt_creator_writer.cc b/tools/gn/qt_creator_writer.cc index b43b7d6..c245024 100644 --- a/tools/gn/qt_creator_writer.cc +++ b/tools/gn/qt_creator_writer.cc
@@ -11,6 +11,7 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/optional.h" #include "tools/gn/builder.h" #include "tools/gn/config_values_extractors.h" @@ -114,7 +115,119 @@ } } +namespace QtCreatorWriterUtils { + +enum class CVersion { + C99, + C11, +}; + +enum class CxxVersion { + CXX98, + CXX03, + CXX11, + CXX14, + CXX17, +}; + +std::string ToMacro(CVersion version) { + const std::string s = "__STDC_VERSION__"; + + switch(version) { + case CVersion::C99: + return s + " 199901L"; + case CVersion::C11: + return s + " 201112L"; + } + + return std::string(); +} + +std::string ToMacro(CxxVersion version) { + const std::string name = "__cplusplus"; + + switch(version) { + case CxxVersion::CXX98: + case CxxVersion::CXX03: + return name + " 199711L"; + case CxxVersion::CXX11: + return name + " 201103L"; + case CxxVersion::CXX14: + return name + " 201402L"; + case CxxVersion::CXX17: + return name + " 201703L"; + } + + return std::string(); +} + +const std::map<std::string, CVersion> kFlagToCVersion{ + {"-std=gnu99" , CVersion::C99}, + {"-std=c99" , CVersion::C99}, + {"-std=gnu11" , CVersion::C11}, + {"-std=c11" , CVersion::C11} +}; + +const std::map<std::string, CxxVersion> kFlagToCxxVersion{ + {"-std=gnu++11", CxxVersion::CXX11}, {"-std=c++11", CxxVersion::CXX11}, + {"-std=gnu++98", CxxVersion::CXX98}, {"-std=c++98", CxxVersion::CXX98}, + {"-std=gnu++03", CxxVersion::CXX03}, {"-std=c++03", CxxVersion::CXX03}, + {"-std=gnu++14", CxxVersion::CXX14}, {"-std=c++14", CxxVersion::CXX14}, + {"-std=c++1y" , CxxVersion::CXX14}, + {"-std=gnu++17", CxxVersion::CXX17}, {"-std=c++17", CxxVersion::CXX17}, + {"-std=c++1z" , CxxVersion::CXX17}, +}; + +template<typename Enum> +struct CompVersion { + bool operator()(Enum a, Enum b) { + return static_cast<int>(a) < static_cast<int>(b); + } +}; + +struct CompilerOptions { + base::Optional<CVersion> c_version_; + base::Optional<CxxVersion> cxx_version_; + + void SetCVersion(CVersion ver) { + SetVersionImpl(c_version_, ver); + } + + void SetCxxVersion(CxxVersion ver) { + SetVersionImpl(cxx_version_, ver); + } + +private: + template<typename Version> + void SetVersionImpl(base::Optional<Version> &cur_ver, Version ver) { + if (cur_ver) + cur_ver = std::max(*cur_ver, ver, CompVersion<Version> {}); + else + cur_ver = ver; + } +}; + +void ParseCompilerOption(const std::string& flag, CompilerOptions* options) { + auto c_ver = kFlagToCVersion.find(flag); + if (c_ver != kFlagToCVersion.end()) + options->SetCVersion(c_ver->second); + + auto cxx_ver = kFlagToCxxVersion.find(flag); + if (cxx_ver != kFlagToCxxVersion.end()) + options->SetCxxVersion(cxx_ver->second); +} + +void ParseCompilerOptions(const std::vector<std::string>& cflags, + CompilerOptions* options) { + for (const std::string& flag : cflags) + ParseCompilerOption(flag, options); +} + +} // QtCreatorWriterUtils + void QtCreatorWriter::HandleTarget(const Target* target) { + using namespace QtCreatorWriterUtils; + SourceFile build_file = Loader::BuildFileForLabel(target->label()); sources_.insert(FilePathToUTF8(build_settings_->GetFullPath(build_file))); AddToSources(target->settings()->import_manager().GetImportedFiles()); @@ -137,13 +250,26 @@ FilePathToUTF8(build_settings_->GetFullPath(include_dir))); } + static constexpr const char *define_str = "#define "; for (std::string define : it.cur().defines()) { size_t equal_pos = define.find('='); if (equal_pos != std::string::npos) define[equal_pos] = ' '; - define.insert(0, "#define "); + define.insert(0, define_str); defines_.insert(define); } + + CompilerOptions options; + ParseCompilerOptions(it.cur().cflags(), &options); + ParseCompilerOptions(it.cur().cflags_c(), &options); + ParseCompilerOptions(it.cur().cflags_cc(), &options); + + auto add_define_version = [this] (auto &ver) { + if (ver) + defines_.insert(define_str + ToMacro(*ver)); + }; + add_define_version(options.c_version_); + add_define_version(options.cxx_version_); } }