From 8d0cfd91013fbf2e55ca672fcaa6368d678edef2 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 24 Mar 2019 23:42:00 -0700 Subject: [PATCH 1/5] Add initialization option index.initialNoLinkage: false By default, the background indexer doesn't handle names of no linkage. They are indexed when their files are opened. This saves memory and makes cache files smaller. --- src/config.hh | 18 +++++++++++------- src/indexer.cc | 38 ++++++++++++++++++-------------------- src/indexer.hh | 2 +- src/messages/workspace.cc | 2 +- src/pipeline.cc | 18 ++++++++++-------- src/pipeline.hh | 2 +- src/project.cc | 6 +++--- src/test.cc | 3 ++- 8 files changed, 47 insertions(+), 42 deletions(-) diff --git a/src/config.hh b/src/config.hh index 5ac3ed4a..6f0d7bd6 100644 --- a/src/config.hh +++ b/src/config.hh @@ -255,9 +255,12 @@ struct Config { // - https://github.com/autozimu/LanguageClient-neovim/issues/224 int comments = 2; - // By default, all project entries will be indexed on initialization. Use - // these two options to exclude some. They can still be indexed after you - // open them. + // If false, names of no linkage are not indexed in the background. They are + // indexed after the files are opened. + bool initialNoLinkage = false; + + // Use the two options to exclude files that should not be indexed in the + // background. std::vector initialBlacklist; std::vector initialWhitelist; @@ -344,10 +347,11 @@ REFLECT_STRUCT(Config::Diagnostics, blacklist, onChange, onOpen, onSave, spellChecking, whitelist) REFLECT_STRUCT(Config::Highlight, largeFileSize, lsRanges, blacklist, whitelist) REFLECT_STRUCT(Config::Index::Name, suppressUnwrittenScope); -REFLECT_STRUCT(Config::Index, blacklist, comments, initialBlacklist, - initialWhitelist, maxInitializerLines, multiVersion, - multiVersionBlacklist, multiVersionWhitelist, name, onChange, - parametersInDeclarations, threads, trackDependency, whitelist); +REFLECT_STRUCT(Config::Index, blacklist, comments, initialNoLinkage, + initialBlacklist, initialWhitelist, maxInitializerLines, + multiVersion, multiVersionBlacklist, multiVersionWhitelist, name, + onChange, parametersInDeclarations, threads, trackDependency, + whitelist); REFLECT_STRUCT(Config::Request, timeout); REFLECT_STRUCT(Config::Session, maxNum); REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort); diff --git a/src/indexer.cc b/src/indexer.cc index f4e9be8b..22fe697f 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -62,7 +62,8 @@ struct IndexParam { VFS &vfs; ASTContext *Ctx; - IndexParam(VFS &vfs) : vfs(vfs) {} + bool no_linkage; + IndexParam(VFS &vfs, bool no_linkage) : vfs(vfs), no_linkage(no_linkage) {} void SeenFile(const FileEntry &File) { // If this is the first time we have seen the file (ignoring if we are @@ -78,7 +79,7 @@ struct IndexParam { if (std::optional content = ReadContent(path)) it->second.content = *content; - if (!vfs.Stamp(path, it->second.mtime, 1)) + if (!vfs.Stamp(path, it->second.mtime, no_linkage ? 3 : 1)) return; it->second.db = std::make_unique(path, it->second.content); } @@ -693,6 +694,12 @@ public: bool handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles, ArrayRef Relations, SourceLocation Loc, ASTNodeInfo ASTNode) override { + if (!param.no_linkage) { + if (auto *ND = dyn_cast(D); ND && ND->hasLinkage()) + ; + else + return true; + } SourceManager &SM = Ctx->getSourceManager(); const LangOptions &Lang = Ctx->getLangOpts(); FileID LocFID; @@ -1217,7 +1224,7 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs, const std::string &opt_wdir, const std::string &main, const std::vector &args, const std::vector> &remapped, - bool &ok) { + bool no_linkage, bool &ok) { ok = true; auto PCH = std::make_shared(); llvm::IntrusiveRefCntPtr FS = llvm::vfs::getRealFileSystem(); @@ -1231,17 +1238,6 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs, // code completion. if (g_config->index.comments > 1) CI->getLangOpts()->CommentOpts.ParseAllComments = true; - { - // FileSystemOptions& FSOpts = CI->getFileSystemOpts(); - // if (FSOpts.WorkingDir.empty()) - // FSOpts.WorkingDir = opt_wdir; - // HeaderSearchOptions &HSOpts = CI->getHeaderSearchOpts(); - // llvm::errs() << HSOpts.ResourceDir << "\n"; - // // lib/clang/7.0.0 is incorrect - // if (HSOpts.ResourceDir.compare(0, 3, "lib") == 0 && - // HSOpts.UseBuiltinIncludes) - // HSOpts.ResourceDir = g_config->clang.resourceDir; - } std::string buf = wfiles->GetContent(main); std::vector> Bufs; if (buf.size()) @@ -1260,19 +1256,21 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs, if (!Clang->hasTarget()) return {}; - IndexParam param(*vfs); + IndexParam param(*vfs, no_linkage); auto DataConsumer = std::make_shared(param); index::IndexingOptions IndexOpts; IndexOpts.SystemSymbolFilter = index::IndexingOptions::SystemSymbolFilterKind::All; - IndexOpts.IndexFunctionLocals = true; - IndexOpts.IndexImplicitInstantiation = true; + if (no_linkage) { + IndexOpts.IndexFunctionLocals = true; + IndexOpts.IndexImplicitInstantiation = true; #if LLVM_VERSION_MAJOR >= 9 - IndexOpts.IndexParametersInDeclarations = - g_config->index.parametersInDeclarations; - IndexOpts.IndexTemplateParameters = true; + IndexOpts.IndexParametersInDeclarations = + g_config->index.parametersInDeclarations; + IndexOpts.IndexTemplateParameters = true; #endif + } std::unique_ptr Action = createIndexingAction( DataConsumer, IndexOpts, std::make_unique(param)); diff --git a/src/indexer.hh b/src/indexer.hh index 62401ab3..ca87c5d6 100644 --- a/src/indexer.hh +++ b/src/indexer.hh @@ -348,7 +348,7 @@ Index(SemaManager *complete, WorkingFiles *wfiles, VFS *vfs, const std::string &opt_wdir, const std::string &file, const std::vector &args, const std::vector> &remapped, - bool &ok); + bool all_linkages, bool &ok); } // namespace idx } // namespace ccls diff --git a/src/messages/workspace.cc b/src/messages/workspace.cc index 60ff01ae..86ce0b25 100644 --- a/src/messages/workspace.cc +++ b/src/messages/workspace.cc @@ -55,7 +55,7 @@ void MessageHandler::workspace_didChangeWatchedFiles( return; IndexMode mode = - wfiles->GetFile(path) ? IndexMode::Normal : IndexMode::NonInteractive; + wfiles->GetFile(path) ? IndexMode::Normal : IndexMode::Background; switch (event.type) { case FileChangeType::Created: case FileChangeType::Changed: { diff --git a/src/pipeline.cc b/src/pipeline.cc index f2b75524..7bf0bd61 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -229,18 +229,20 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles, std::string path_to_index = entry.filename; std::unique_ptr prev; - bool deleted = false; + bool deleted = false, no_linkage = g_config->index.initialNoLinkage || + request.mode != IndexMode::Background; int reparse = 0; std::optional write_time = LastWriteTime(path_to_index); if (!write_time) { deleted = true; } else { - reparse = vfs->Stamp(path_to_index, *write_time, 0); + if (vfs->Stamp(path_to_index, *write_time, no_linkage ? 2 : 0)) + reparse = no_linkage ? 2 : 1; if (request.path != path_to_index) { std::optional mtime1 = LastWriteTime(request.path); if (!mtime1) deleted = true; - else if (vfs->Stamp(request.path, *mtime1, 0)) + else if (vfs->Stamp(request.path, *mtime1, no_linkage ? 2 : 0)) reparse = 2; } } @@ -293,7 +295,7 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles, auto dependencies = prev->dependencies; IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); on_indexed->PushBack(std::move(update), - request.mode != IndexMode::NonInteractive); + request.mode != IndexMode::Background); { std::lock_guard lock1(vfs->mutex); vfs->state[path_to_index].loaded++; @@ -318,7 +320,7 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles, } IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); on_indexed->PushBack(std::move(update), - request.mode != IndexMode::NonInteractive); + request.mode != IndexMode::Background); if (entry.id >= 0) { std::lock_guard lock2(project->mtx); project->root2folder[entry.root].path2entry_index[path] = entry.id; @@ -351,7 +353,7 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles, } bool ok; indexes = idx::Index(completion, wfiles, vfs, entry.directory, - path_to_index, entry.args, remapped, ok); + path_to_index, entry.args, remapped, no_linkage, ok); if (!ok) { if (request.id.Valid()) { @@ -403,7 +405,7 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles, } } on_indexed->PushBack(IndexUpdate::CreateDelta(prev.get(), curr.get()), - request.mode != IndexMode::NonInteractive); + request.mode != IndexMode::Background); { std::lock_guard lock1(vfs->mutex); vfs->state[path].loaded++; @@ -743,7 +745,7 @@ void Index(const std::string &path, const std::vector &args, IndexMode mode, bool must_exist, RequestId id) { pending_index_requests++; index_request->PushBack({path, args, mode, must_exist, id}, - mode != IndexMode::NonInteractive); + mode != IndexMode::Background); } void RemoveCache(const std::string &path) { diff --git a/src/pipeline.hh b/src/pipeline.hh index be881c06..2d0db15b 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -30,7 +30,7 @@ struct VFS { }; enum class IndexMode { - NonInteractive, + Background, OnChange, Normal, }; diff --git a/src/project.cc b/src/project.cc index 25bfa34c..10359515 100644 --- a/src/project.cc +++ b/src/project.cc @@ -576,7 +576,7 @@ void Project::Index(WorkingFiles *wfiles, RequestId id) { bool interactive = wfiles->GetFile(entry.filename) != nullptr; pipeline::Index(entry.filename, entry.args, interactive ? IndexMode::Normal - : IndexMode::NonInteractive, + : IndexMode::Background, false, id); } else { LOG_V(1) << "[" << i << "/" << folder.entries.size() << "]: " << reason @@ -590,7 +590,7 @@ void Project::Index(WorkingFiles *wfiles, RequestId id) { pipeline::loaded_ts = pipeline::tick; // Dummy request to indicate that project is loaded and // trigger refreshing semantic highlight for all working files. - pipeline::Index("", {}, IndexMode::NonInteractive, false); + pipeline::Index("", {}, IndexMode::Background, false); } void Project::IndexRelated(const std::string &path) { @@ -604,7 +604,7 @@ void Project::IndexRelated(const std::string &path) { std::string reason; if (sys::path::stem(entry.filename) == stem && entry.filename != path && match.Matches(entry.filename, &reason)) - pipeline::Index(entry.filename, entry.args, IndexMode::NonInteractive, + pipeline::Index(entry.filename, entry.args, IndexMode::Background, true); } break; diff --git a/src/test.cc b/src/test.cc index 7faf948c..3215fc2b 100644 --- a/src/test.cc +++ b/src/test.cc @@ -327,7 +327,8 @@ bool RunIndexTests(const std::string &filter_path, bool enable_update) { for (auto &arg : flags) cargs.push_back(arg.c_str()); bool ok; - auto dbs = ccls::idx::Index(&completion, &wfiles, &vfs, "", path, cargs, {}, ok); + auto dbs = ccls::idx::Index(&completion, &wfiles, &vfs, "", path, cargs, + {}, true, ok); for (const auto &entry : all_expected_output) { const std::string &expected_path = entry.first; From 32bd6f8ecfbd377d6aa0ca60bc23b6a102d42843 Mon Sep 17 00:00:00 2001 From: Max Rietmann Date: Mon, 1 Apr 2019 14:32:45 +0200 Subject: [PATCH 2/5] Initial support for CUDA. Modify CUDA compile arguments by removing everything but -I header.h stuff --- src/lsp.hh | 2 +- src/project.cc | 57 ++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/lsp.hh b/src/lsp.hh index b92578b8..a818dff9 100644 --- a/src/lsp.hh +++ b/src/lsp.hh @@ -261,6 +261,6 @@ struct ShowMessageParam { // Used to identify the language at a file level. The ordering is important, as // a file previously identified as `C`, will be changed to `Cpp` if it // encounters a c++ declaration. -enum class LanguageId { Unknown = -1, C = 0, Cpp = 1, ObjC = 2, ObjCpp = 3 }; + enum class LanguageId { Unknown = -1, C = 0, Cpp = 1, ObjC = 2, ObjCpp = 3, CUDA = 4 }; } // namespace ccls diff --git a/src/project.cc b/src/project.cc index 10359515..4a9daf34 100644 --- a/src/project.cc +++ b/src/project.cc @@ -59,7 +59,9 @@ std::pair lookupExtension(std::string_view filename) { I == types::TY_ObjCXXHeader; bool objc = types::isObjC(I); LanguageId ret; - if (types::isCXX(I)) + if (I == types::TY_CUDA) + ret = LanguageId::CUDA; + else if (types::isCXX(I)) ret = objc ? LanguageId::ObjCpp : LanguageId::Cpp; else if (objc) ret = LanguageId::ObjC; @@ -123,6 +125,8 @@ struct ProjectProcessor { ok |= lang == LanguageId::ObjC; else if (A.consume_front("%objective-cpp ")) ok |= lang == LanguageId::ObjCpp; + else if (A.consume_front("%cu ")) + ok |= lang == LanguageId::CUDA; else break; } @@ -326,6 +330,13 @@ int ComputeGuessScore(std::string_view a, std::string_view b) { } // namespace +template +auto as_integer(Enumeration const value) + -> typename std::underlying_type::type +{ + return static_cast::type>(value); +} + void Project::LoadDirectory(const std::string &root, Project::Folder &folder) { SmallString<256> CDBDir, Path, StdinPath; std::string err_msg; @@ -412,11 +423,45 @@ void Project::LoadDirectory(const std::string &root, Project::Folder &folder) { DoPathMapping(entry.filename); std::vector args = std::move(Cmd.CommandLine); - entry.args.reserve(args.size()); - for (std::string &arg : args) { - DoPathMapping(arg); - if (!proc.ExcludesArg(arg)) - entry.args.push_back(Intern(arg)); + + auto [lang, header] = lookupExtension(entry.filename); + + // CMAKE splits nvcc compiles into 2 seperates commands, and has (mostly) non-clang arguments. Replace these with a simple call to clang with only "-I /path/header.h" arguments. + // .ccls will also need: + // clang + // %cu --cuda-gpu-arch=sm_70 --cuda-path=/usr/local/cuda-9.2/ + if(lang == LanguageId::CUDA) { + entry.args.push_back(Intern("/usr/bin/clang-7")); + entry.args.push_back(Intern("-c")); + entry.args.push_back(Intern(entry.filename)); + LOG_S(INFO) << entry.filename << ": (CUDA) clang-7 -c filename"; + bool take_next_arg = false; + for (std::string &arg : args) { + // take header includes (-I /path/to/header.h) + if(arg == "-I") { + entry.args.push_back(Intern(arg)); + take_next_arg = true; + } + else if (take_next_arg) { + // take actual header include location (/path/to/header.h) + entry.args.push_back(Intern(arg)); + take_next_arg = false; + } + else { + LOG_S(INFO) << entry.filename << ": (CUDA) Ignoring arg: " << arg; + } + } + } + else { + entry.args.reserve(args.size()); + for (std::string &arg : args) { + DoPathMapping(arg); + if (!proc.ExcludesArg(arg)) { + // LOG_S(INFO) << entry.filename << ": Accepted arg: " << arg << + // "\n"; + entry.args.push_back(Intern(arg)); + } + } } entry.compdb_size = entry.args.size(); From 7bf2e8797bab0e015b7cd25fd57e110482c645fc Mon Sep 17 00:00:00 2001 From: Max Rietmann Date: Mon, 1 Apr 2019 15:10:26 +0200 Subject: [PATCH 3/5] Some fixes for CUDA. not quite working reliably for big project --- src/project.cc | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/project.cc b/src/project.cc index 4a9daf34..937c11b9 100644 --- a/src/project.cc +++ b/src/project.cc @@ -429,23 +429,27 @@ void Project::LoadDirectory(const std::string &root, Project::Folder &folder) { // CMAKE splits nvcc compiles into 2 seperates commands, and has (mostly) non-clang arguments. Replace these with a simple call to clang with only "-I /path/header.h" arguments. // .ccls will also need: // clang - // %cu --cuda-gpu-arch=sm_70 --cuda-path=/usr/local/cuda-9.2/ + // %cu --cuda-gpu-arch=sm_70 --cuda-path=/usr/local/cuda-9.2/ --std=c++11 if(lang == LanguageId::CUDA) { entry.args.push_back(Intern("/usr/bin/clang-7")); + entry.args.push_back(Intern("--cuda-gpu-arch=sm_70")); + entry.args.push_back(Intern("--cuda-path=/usr/local/cuda-9.2/")); + entry.args.push_back(Intern("--std=c++11")); entry.args.push_back(Intern("-c")); entry.args.push_back(Intern(entry.filename)); LOG_S(INFO) << entry.filename << ": (CUDA) clang-7 -c filename"; - bool take_next_arg = false; for (std::string &arg : args) { - // take header includes (-I /path/to/header.h) - if(arg == "-I") { + // take header includes (-I/path/to/header.h) + if((arg.find("-I") != std::string::npos) + ) { + LOG_S(INFO) << entry.filename << ": (CUDA) Adding Arg: " << arg; entry.args.push_back(Intern(arg)); - take_next_arg = true; } - else if (take_next_arg) { - // take actual header include location (/path/to/header.h) + else if(arg.find("-isystem") != std::string::npos) { + auto equals = arg.find("="); + arg.replace(equals,1," "); + LOG_S(INFO) << entry.filename << ": (CUDA) Adding Arg: " << arg; entry.args.push_back(Intern(arg)); - take_next_arg = false; } else { LOG_S(INFO) << entry.filename << ": (CUDA) Ignoring arg: " << arg; From d136012fab54f3216cc31c5a44ed3bb09d0f7b48 Mon Sep 17 00:00:00 2001 From: Max Rietmann Date: Mon, 1 Apr 2019 16:52:08 +0200 Subject: [PATCH 4/5] Rely more heavily on .ccls --- src/project.cc | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/project.cc b/src/project.cc index 937c11b9..9343301c 100644 --- a/src/project.cc +++ b/src/project.cc @@ -51,6 +51,15 @@ using namespace clang; using namespace llvm; namespace ccls { + +template +auto as_integer(Enumeration const value) + -> typename std::underlying_type::type +{ + return static_cast::type>(value); +} + + std::pair lookupExtension(std::string_view filename) { using namespace clang::driver; auto I = types::lookupTypeForExtension( @@ -136,6 +145,7 @@ struct ProjectProcessor { args.push_back(arg); } } + entry.args = args; GetSearchDirs(entry); } @@ -330,12 +340,6 @@ int ComputeGuessScore(std::string_view a, std::string_view b) { } // namespace -template -auto as_integer(Enumeration const value) - -> typename std::underlying_type::type -{ - return static_cast::type>(value); -} void Project::LoadDirectory(const std::string &root, Project::Folder &folder) { SmallString<256> CDBDir, Path, StdinPath; @@ -432,9 +436,10 @@ void Project::LoadDirectory(const std::string &root, Project::Folder &folder) { // %cu --cuda-gpu-arch=sm_70 --cuda-path=/usr/local/cuda-9.2/ --std=c++11 if(lang == LanguageId::CUDA) { entry.args.push_back(Intern("/usr/bin/clang-7")); - entry.args.push_back(Intern("--cuda-gpu-arch=sm_70")); - entry.args.push_back(Intern("--cuda-path=/usr/local/cuda-9.2/")); - entry.args.push_back(Intern("--std=c++11")); + // entry.args.push_back(Intern("--cuda-gpu-arch=sm_70")); + // entry.args.push_back(Intern("--cuda-path=/usr/local/cuda-9.2/")); + // entry.args.push_back(Intern("-I/home/max/dev/cuml/thirdparty/cuml/googletest/googletest/include")); + // entry.args.push_back(Intern("--std=c++11")); entry.args.push_back(Intern("-c")); entry.args.push_back(Intern(entry.filename)); LOG_S(INFO) << entry.filename << ": (CUDA) clang-7 -c filename"; @@ -451,6 +456,10 @@ void Project::LoadDirectory(const std::string &root, Project::Folder &folder) { LOG_S(INFO) << entry.filename << ": (CUDA) Adding Arg: " << arg; entry.args.push_back(Intern(arg)); } + else if(arg.find("-std=") != std::string::npos) { + LOG_S(INFO) << entry.filename << ": (CUDA) Adding Arg: " << arg; + entry.args.push_back(Intern(arg)); + } else { LOG_S(INFO) << entry.filename << ": (CUDA) Ignoring arg: " << arg; } From 2a204bcaf804a176bd426114f8b330852abcb692 Mon Sep 17 00:00:00 2001 From: Max Rietmann Date: Tue, 2 Apr 2019 09:20:50 +0200 Subject: [PATCH 5/5] A few notes in the readme --- README.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e02351f5..1a848251 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Telegram](https://img.shields.io/badge/telegram-@cclsp-blue.svg)](https://telegram.me/cclsp) [![Gitter](https://img.shields.io/badge/gitter-ccls--project-blue.svg?logo=gitter-white)](https://gitter.im/ccls-project/ccls) -ccls, which originates from [cquery](https://github.com/cquery-project/cquery), is a C/C++/Objective-C language server. +This is a temporary fork of ccls with experimental CUDA support. `ccls` originates from [cquery](https://github.com/cquery-project/cquery), is a C/C++/Objective-C language server. * code completion (with both signature help and snippets) * [definition](src/messages/textDocument_definition.cc)/[references](src/messages/textDocument_references.cc), and other cross references @@ -17,6 +17,26 @@ ccls, which originates from [cquery](https://github.com/cquery-project/cquery), * semantic highlighting and preprocessor skipped regions * semantic navigation: `$ccls/navigate` +## CUDA quickstart + +Your `.ccls` configuration should look something like: +``` +%compile_commands.json +%cu --cuda-gpu-arch=sm_70 +%cu --cuda-path=/usr/local/cuda-9.2/ +``` +This fork changes the compile commands from the `compile_commands.json` file that look like: + + /usr/local/cuda/bin/nvcc -ccbin=gcc-6 -I../src -I../external/cutlass -I../external/cub -isystem=../external/googletest/googletest/include -Xcompiler -fopenmp --expt-extended-lambda --std=c++11 -gencode arch=compute_70,code=sm_70 -gencode arch=compute_70,code=compute_70 -g -x cu -c /home/max/dev/cuml/ml-prims/test/add.cu -o test/CMakeFiles/mlcommon_test.dir/add.cu.o && /usr/local/cuda/bin/nvcc -ccbin=gcc-6 -I../src -I../external/cutlass -I../external/cub -isystem=../external/googletest/googletest/include -Xcompiler -fopenmp --expt-extended-lambda --std=c++11 -gencode arch=compute_70,code=sm_70 -gencode arch=compute_70,code=compute_70 -g -x cu -M /home/max/dev/cuml/ml-prims/test/add.cu -MT test/CMakeFiles/mlcommon_test.dir/add.cu.o -o $DEP_FILE + +To something more like: + + clang -I../src -I../external/cutlass -I../external/cub -isystem=../external/googletest/googletest/include --std=c++11 --cuda-gpu-arch=sm_70 --cuda-path=/usr/local/cuda-9.2/ -c add.cu + +In other words, it whitelists includes (`-I`) and c++ standard flags, but ignores all the `nvcc` switches that `clang` doesn't understand. Note that clang understands CUDA files by default. + +## General Info + It has a global view of the code base and support a lot of cross reference features, see [wiki/FAQ](../../wiki/FAQ). It starts indexing the whole project (including subprojects if exist) parallelly when you open the first file, while the main thread can serve requests before the indexing is complete. Saving files will incrementally update the index.