fix windows relative path include dirs (#501)

* Only do path normalization on clang-cl + clang-format

* Improve clang-cl checking + add /I to args that could be followed by a relative path + add two test cases
This commit is contained in:
DaanDeMeyer 2018-03-11 18:08:41 +01:00 committed by Fangrui Song
parent 2a7117e6e5
commit 9b3ec699e0

View File

@ -10,8 +10,8 @@
#include <clang-c/CXCompilationDatabase.h> #include <clang-c/CXCompilationDatabase.h>
#include <doctest/doctest.h> #include <doctest/doctest.h>
#include <loguru.hpp>
#include <rapidjson/writer.h> #include <rapidjson/writer.h>
#include <loguru.hpp>
#if defined(__unix__) || defined(__APPLE__) #if defined(__unix__) || defined(__APPLE__)
#include <unistd.h> #include <unistd.h>
@ -54,8 +54,7 @@ bool IsWindowsAbsolutePath(const std::string& path) {
}; };
return path.size() > 3 && path[1] == ':' && return path.size() > 3 && path[1] == ':' &&
(path[2] == '/' || path[2] == '\\') && (path[2] == '/' || path[2] == '\\') && is_drive_letter(path[0]);
is_drive_letter(path[0]);
} }
enum class ProjectMode { CompileCommandsJson, DotCquery, ExternalCommand }; enum class ProjectMode { CompileCommandsJson, DotCquery, ExternalCommand };
@ -84,7 +83,7 @@ std::vector<std::string> kBlacklist = {
std::vector<std::string> kPathArgs = { std::vector<std::string> kPathArgs = {
"-I", "-iquote", "-isystem", "--sysroot=", "-I", "-iquote", "-isystem", "--sysroot=",
"-isysroot", "-gcc-toolchain", "-include-pch", "-iframework", "-isysroot", "-gcc-toolchain", "-include-pch", "-iframework",
"-F", "-imacros", "-include"}; "-F", "-imacros", "-include", "/I"};
// Arguments which always require an absolute path, ie, clang -working-directory // Arguments which always require an absolute path, ie, clang -working-directory
// does not work as expected. Argument processing assumes that this is a subset // does not work as expected. Argument processing assumes that this is a subset
@ -94,7 +93,7 @@ std::vector<std::string> kNormalizePathArgs = {"--sysroot="};
// Arguments whose path arguments should be injected into include dir lookup // Arguments whose path arguments should be injected into include dir lookup
// for #include completion. // for #include completion.
std::vector<std::string> kQuoteIncludeArgs = {"-iquote"}; std::vector<std::string> kQuoteIncludeArgs = {"-iquote"};
std::vector<std::string> kAngleIncludeArgs = {"-I", "-isystem"}; std::vector<std::string> kAngleIncludeArgs = {"-I", "/I", "-isystem"};
bool ShouldAddToQuoteIncludes(const std::string& arg) { bool ShouldAddToQuoteIncludes(const std::string& arg) {
return StartsWithAny(arg, kQuoteIncludeArgs); return StartsWithAny(arg, kQuoteIncludeArgs);
@ -170,8 +169,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
// ie, compiler schedular such as goma. This allows correct parsing for // ie, compiler schedular such as goma. This allows correct parsing for
// command lines like "goma clang -c foo". // command lines like "goma clang -c foo".
std::string::size_type dot; std::string::size_type dot;
while ( while (i < args.size() && args[i][0] != '-' &&
i < args.size() && args[i][0] != '-' &&
// Do not skip over main source filename // Do not skip over main source filename
NormalizePathWithTestOptOut(args[i]) != result.filename && NormalizePathWithTestOptOut(args[i]) != result.filename &&
// There may be other filenames (e.g. more than one source filenames) // There may be other filenames (e.g. more than one source filenames)
@ -221,6 +219,8 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
config->quote_dirs.insert(normalized_arg); config->quote_dirs.insert(normalized_arg);
if (add_next_flag_to_angle_dirs) if (add_next_flag_to_angle_dirs)
config->angle_dirs.insert(normalized_arg); config->angle_dirs.insert(normalized_arg);
if (clang_cl)
arg = normalized_arg;
next_flag_is_path = false; next_flag_is_path = false;
add_next_flag_to_quote_dirs = false; add_next_flag_to_quote_dirs = false;
@ -241,7 +241,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
std::string path = arg.substr(flag_type.size()); std::string path = arg.substr(flag_type.size());
assert(!path.empty()); assert(!path.empty());
path = cleanup_maybe_relative_path(path); path = cleanup_maybe_relative_path(path);
if (StartsWithAny(arg, kNormalizePathArgs)) if (clang_cl || StartsWithAny(arg, kNormalizePathArgs))
arg = flag_type + path; arg = flag_type + path;
if (ShouldAddToQuoteIncludes(flag_type)) if (ShouldAddToQuoteIncludes(flag_type))
config->quote_dirs.insert(path); config->quote_dirs.insert(path);
@ -664,9 +664,8 @@ TEST_SUITE("Project") {
CheckFlags( CheckFlags(
/* raw */ {"goma", "clang"}, /* raw */ {"goma", "clang"},
/* expected */ /* expected */
{"clang", "-working-directory=/dir/", {"clang", "-working-directory=/dir/", "-resource-dir=/w/resource_dir/",
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option", "-Wno-unknown-warning-option", "-fparse-all-comments"});
"-fparse-all-comments"});
CheckFlags( CheckFlags(
/* raw */ {"goma", "clang", "--foo"}, /* raw */ {"goma", "clang", "--foo"},
@ -679,14 +678,31 @@ TEST_SUITE("Project") {
TEST_CASE("Windows path normalization") { TEST_CASE("Windows path normalization") {
CheckFlags("E:/workdir", "E:/workdir/bar.cc", /* raw */ {"clang", "bar.cc"}, CheckFlags("E:/workdir", "E:/workdir/bar.cc", /* raw */ {"clang", "bar.cc"},
/* expected */ /* expected */
{"clang", "-working-directory=E:/workdir", {"clang", "-working-directory=E:/workdir", "&E:/workdir/bar.cc",
"&E:/workdir/bar.cc", "-resource-dir=/w/resource_dir/", "-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
"-Wno-unknown-warning-option", "-fparse-all-comments"}); "-fparse-all-comments"});
CheckFlags("E:/workdir", "E:/workdir/bar.cc", CheckFlags("E:/workdir", "E:/workdir/bar.cc",
/* raw */ {"clang", "E:/workdir/bar.cc"}, /* raw */ {"clang", "E:/workdir/bar.cc"},
/* expected */ /* expected */
{"clang", "-working-directory=E:/workdir", {"clang", "-working-directory=E:/workdir", "&E:/workdir/bar.cc",
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
"-fparse-all-comments"});
CheckFlags("E:/workdir", "E:/workdir/bar.cc",
/* raw */ {"clang-cl.exe", "/I./test", "E:/workdir/bar.cc"},
/* expected */
{"clang-cl.exe", "-working-directory=E:/workdir",
"/I&E:/workdir/./test", "&E:/workdir/bar.cc",
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
"-fparse-all-comments"});
CheckFlags("E:/workdir", "E:/workdir/bar.cc",
/* raw */
{"cl.exe", "/I../third_party/test/include", "E:/workdir/bar.cc"},
/* expected */
{"cl.exe", "-working-directory=E:/workdir",
"/I&E:/workdir/../third_party/test/include",
"&E:/workdir/bar.cc", "-resource-dir=/w/resource_dir/", "&E:/workdir/bar.cc", "-resource-dir=/w/resource_dir/",
"-Wno-unknown-warning-option", "-fparse-all-comments"}); "-Wno-unknown-warning-option", "-fparse-all-comments"});
} }