mirror of
https://github.com/MaskRay/ccls.git
synced 2025-01-19 03:55:49 +00:00
Add Config::compilationDatabaseCommand
If specified, this is an external command that provides the JSON compilation database, instead of compile_commands.json
This commit is contained in:
parent
d33bf50181
commit
f9d7361953
@ -23,6 +23,11 @@ initialization options specified by the client. For example, in shell syntax:
|
||||
struct Config {
|
||||
// Root directory of the project. **Not available for configuration**
|
||||
std::string projectRoot;
|
||||
// If specified, this option overrides compile_commands.json and this
|
||||
// external command will be executed with an option |projectRoot|.
|
||||
// The initialization options will be provided as stdin.
|
||||
// The stdout of the command should be the JSON compilation database.
|
||||
std::string compilationDatabaseCommand;
|
||||
// Directory containing compile_commands.json.
|
||||
std::string compilationDatabaseDirectory;
|
||||
// Cache directory for indexed files.
|
||||
@ -191,6 +196,7 @@ MAKE_REFLECT_STRUCT(Config::Completion, filterAndSort, detailedLabel);
|
||||
MAKE_REFLECT_STRUCT(Config::Extension, referenceContainer);
|
||||
MAKE_REFLECT_STRUCT(Config::Index, comments, attributeMakeCallsToCtor);
|
||||
MAKE_REFLECT_STRUCT(Config,
|
||||
compilationDatabaseCommand,
|
||||
compilationDatabaseDirectory,
|
||||
cacheDirectory,
|
||||
cacheFormat,
|
||||
|
@ -330,8 +330,8 @@ IndexFile* ConsumeFile(IndexParam* param, CXFile file) {
|
||||
// generating an index for it):
|
||||
if (param->seen_cx_files.insert(file).second) {
|
||||
std::string file_name = FileName(file);
|
||||
// Sometimes the fill name will be empty. Not sure why. Not much we can do
|
||||
// with it.
|
||||
// file_name may be empty when it contains .. and is outside of WorkingDir.
|
||||
// https://reviews.llvm.org/D42893 https://github.com/cquery-project/cquery/issues/413
|
||||
if (!file_name.empty()) {
|
||||
// Add to all files we have seen so we can generate proper dependency
|
||||
// graph.
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional.h>
|
||||
#include <string_view.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -49,4 +50,8 @@ void FreeUnusedMemory();
|
||||
// If true objective-c index tests will be run.
|
||||
bool RunObjectiveCIndexTests();
|
||||
|
||||
// Stop self and wait for SIGCONT.
|
||||
void TraceMe();
|
||||
|
||||
std::string GetExternalCommandOutput(const std::vector<std::string>& command,
|
||||
std::string_view input);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h> // required for stat.h
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@ -285,4 +286,37 @@ void TraceMe() {
|
||||
raise(SIGTSTP);
|
||||
}
|
||||
|
||||
std::string GetExternalCommandOutput(const std::vector<std::string>& command,
|
||||
std::string_view input) {
|
||||
int pin[2], pout[2];
|
||||
pipe(pin);
|
||||
pipe(pout);
|
||||
pid_t child = fork();
|
||||
if (child == 0) {
|
||||
dup2(pout[0], 0);
|
||||
dup2(pin[1], 1);
|
||||
close(pin[0]);
|
||||
close(pin[1]);
|
||||
close(pout[0]);
|
||||
close(pout[1]);
|
||||
auto argv = new char*[command.size() + 1];
|
||||
for (size_t i = 0; i < command.size(); i++)
|
||||
argv[i] = const_cast<char*>(command[i].c_str());
|
||||
argv[command.size()] = nullptr;
|
||||
execvp(argv[0], argv);
|
||||
_Exit(127);
|
||||
}
|
||||
close(pin[1]);
|
||||
close(pout[0]);
|
||||
write(pout[1], input.data(), input.size());
|
||||
close(pout[1]);
|
||||
std::string ret;
|
||||
char buf[4096];
|
||||
ssize_t n;
|
||||
while ((n = read(pin[0], buf, sizeof buf)) > 0)
|
||||
ret.append(buf, n);
|
||||
waitpid(child, NULL, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -152,4 +152,9 @@ bool RunObjectiveCIndexTests() {
|
||||
// TODO Wait for debugger to attach
|
||||
void TraceMe() {}
|
||||
|
||||
std::string GetExternalCommandOutput(const std::vector<std::string>& command,
|
||||
std::string_view input) {
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -11,6 +11,11 @@
|
||||
#include <doctest/doctest.h>
|
||||
#include <loguru.hpp>
|
||||
|
||||
#if defined(__unix__) || defined(__APPLE__)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
@ -348,17 +353,48 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
||||
if (FileExists(config->project_dir + "/.cquery"))
|
||||
return LoadFromDirectoryListing(init_opts, config);
|
||||
|
||||
// Try to load compile_commands.json, but fallback to a project listing.
|
||||
const auto& compilation_db_dir = opt_compilation_db_dir.empty()
|
||||
? config->project_dir
|
||||
: opt_compilation_db_dir;
|
||||
// If |compilationDatabaseCommand| is specified, execute it to get the compdb.
|
||||
std::string comp_db_dir;
|
||||
if (init_opts->compilationDatabaseCommand.empty()) {
|
||||
// Try to load compile_commands.json, but fallback to a project listing.
|
||||
comp_db_dir = opt_compilation_db_dir.empty() ? config->project_dir
|
||||
: opt_compilation_db_dir;
|
||||
} else {
|
||||
#ifdef _WIN32
|
||||
// TODO
|
||||
#else
|
||||
char tmpdir[] = "/tmp/cquery-compdb-XXXXXX";
|
||||
if (!mkdtemp(tmpdir))
|
||||
return {};
|
||||
comp_db_dir = tmpdir;
|
||||
rapidjson::StringBuffer input;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(input);
|
||||
JsonWriter json_writer(&writer);
|
||||
Reflect(json_writer, *init_opts);
|
||||
std::string contents = GetExternalCommandOutput(
|
||||
std::vector<std::string>{init_opts->compilationDatabaseCommand,
|
||||
config->project_dir},
|
||||
input.GetString());
|
||||
std::ofstream(comp_db_dir + "/compile_commands.json") << contents;
|
||||
#endif
|
||||
}
|
||||
|
||||
LOG_S(INFO) << "Trying to load compile_commands.json";
|
||||
CXCompilationDatabase_Error cx_db_load_error;
|
||||
CXCompilationDatabase cx_db = clang_CompilationDatabase_fromDirectory(
|
||||
compilation_db_dir.c_str(), &cx_db_load_error);
|
||||
comp_db_dir.c_str(), &cx_db_load_error);
|
||||
if (!init_opts->compilationDatabaseCommand.empty()) {
|
||||
#ifdef _WIN32
|
||||
// TODO
|
||||
#else
|
||||
unlink((comp_db_dir + "/compile_commands.json").c_str());
|
||||
rmdir(comp_db_dir.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cx_db_load_error == CXCompilationDatabase_CanNotLoadDatabase) {
|
||||
LOG_S(INFO) << "Unable to load compile_commands.json located at \""
|
||||
<< compilation_db_dir << "\"; using directory listing instead.";
|
||||
<< comp_db_dir << "\"; using directory listing instead.";
|
||||
return LoadFromDirectoryListing(init_opts, config);
|
||||
}
|
||||
|
||||
@ -416,7 +452,6 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
||||
|
||||
clang_time.ResetAndPrint("compile_commands.json clang time");
|
||||
our_time.ResetAndPrint("compile_commands.json our time");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user