mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-24 08:35:08 +00:00
Implement initialization option compilationDatabaseCommand on Windows
This commit is contained in:
parent
0dbf6c89f1
commit
b2fcec4b97
@ -28,8 +28,5 @@ void FreeUnusedMemory();
|
|||||||
// Stop self and wait for SIGCONT.
|
// Stop self and wait for SIGCONT.
|
||||||
void TraceMe();
|
void TraceMe();
|
||||||
|
|
||||||
std::string GetExternalCommandOutput(const std::vector<std::string> &command,
|
|
||||||
std::string_view input);
|
|
||||||
|
|
||||||
void SpawnThread(void *(*fn)(void *), void *arg);
|
void SpawnThread(void *(*fn)(void *), void *arg);
|
||||||
} // namespace ccls
|
} // namespace ccls
|
||||||
|
@ -73,49 +73,6 @@ void TraceMe() {
|
|||||||
raise(traceme[0] == 's' ? SIGSTOP : SIGTSTP);
|
raise(traceme[0] == 's' ? SIGSTOP : SIGTSTP);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetExternalCommandOutput(const std::vector<std::string> &command,
|
|
||||||
std::string_view input) {
|
|
||||||
int pin[2], pout[2];
|
|
||||||
if (pipe(pin) < 0) {
|
|
||||||
perror("pipe(stdin)");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if (pipe(pout) < 0) {
|
|
||||||
perror("pipe(stdout)");
|
|
||||||
close(pin[0]);
|
|
||||||
close(pin[1]);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
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]);
|
|
||||||
// O_NONBLOCK is disabled, write(2) blocks until all bytes are written.
|
|
||||||
(void)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);
|
|
||||||
close(pin[0]);
|
|
||||||
waitpid(child, NULL, 0);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpawnThread(void *(*fn)(void *), void *arg) {
|
void SpawnThread(void *(*fn)(void *), void *arg) {
|
||||||
pthread_t thd;
|
pthread_t thd;
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
|
@ -57,11 +57,6 @@ void FreeUnusedMemory() {}
|
|||||||
// TODO Wait for debugger to attach
|
// TODO Wait for debugger to attach
|
||||||
void TraceMe() {}
|
void TraceMe() {}
|
||||||
|
|
||||||
std::string GetExternalCommandOutput(const std::vector<std::string> &command,
|
|
||||||
std::string_view input) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpawnThread(void *(*fn)(void *), void *arg) {
|
void SpawnThread(void *(*fn)(void *), void *arg) {
|
||||||
std::thread(fn, arg).detach();
|
std::thread(fn, arg).detach();
|
||||||
}
|
}
|
||||||
|
@ -31,13 +31,17 @@ limitations under the License.
|
|||||||
#include <llvm/ADT/STLExtras.h>
|
#include <llvm/ADT/STLExtras.h>
|
||||||
#include <llvm/ADT/StringSet.h>
|
#include <llvm/ADT/StringSet.h>
|
||||||
#include <llvm/Support/LineIterator.h>
|
#include <llvm/Support/LineIterator.h>
|
||||||
|
#include <llvm/Support/Program.h>
|
||||||
|
|
||||||
#include <rapidjson/writer.h>
|
#include <rapidjson/writer.h>
|
||||||
|
|
||||||
#if defined(__unix__) || defined(__APPLE__)
|
#ifdef _WIN32
|
||||||
|
# include <Windows.h>
|
||||||
|
#else
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -308,7 +312,8 @@ int ComputeGuessScore(std::string_view a, std::string_view b) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void Project::LoadDirectory(const std::string &root, Project::Folder &folder) {
|
void Project::LoadDirectory(const std::string &root, Project::Folder &folder) {
|
||||||
SmallString<256> Path, CDBDir;
|
SmallString<256> CDBDir, Path, StdinPath;
|
||||||
|
std::string err_msg;
|
||||||
folder.entries.clear();
|
folder.entries.clear();
|
||||||
if (g_config->compilationDatabaseCommand.empty()) {
|
if (g_config->compilationDatabaseCommand.empty()) {
|
||||||
CDBDir = root;
|
CDBDir = root;
|
||||||
@ -319,33 +324,49 @@ void Project::LoadDirectory(const std::string &root, Project::Folder &folder) {
|
|||||||
// If `compilationDatabaseCommand` is specified, execute it to get the
|
// If `compilationDatabaseCommand` is specified, execute it to get the
|
||||||
// compdb.
|
// compdb.
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// TODO
|
char tmpdir[L_tmpnam];
|
||||||
|
tmpnam_s(tmpdir, L_tmpnam);
|
||||||
|
CDBDir = tmpdir;
|
||||||
|
if (sys::fs::create_directory(tmpdir, false))
|
||||||
|
return;
|
||||||
#else
|
#else
|
||||||
char tmpdir[] = "/tmp/ccls-compdb-XXXXXX";
|
char tmpdir[] = "/tmp/ccls-compdb-XXXXXX";
|
||||||
if (!mkdtemp(tmpdir))
|
if (!mkdtemp(tmpdir))
|
||||||
return;
|
return;
|
||||||
CDBDir = tmpdir;
|
CDBDir = tmpdir;
|
||||||
|
#endif
|
||||||
sys::path::append(Path, CDBDir, "compile_commands.json");
|
sys::path::append(Path, CDBDir, "compile_commands.json");
|
||||||
rapidjson::StringBuffer input;
|
sys::path::append(StdinPath, CDBDir, "stdin");
|
||||||
rapidjson::Writer<rapidjson::StringBuffer> writer(input);
|
{
|
||||||
|
rapidjson::StringBuffer sb;
|
||||||
|
rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
|
||||||
JsonWriter json_writer(&writer);
|
JsonWriter json_writer(&writer);
|
||||||
Reflect(json_writer, *g_config);
|
Reflect(json_writer, *g_config);
|
||||||
std::string contents = GetExternalCommandOutput(
|
std::string input = sb.GetString();
|
||||||
std::vector<std::string>{g_config->compilationDatabaseCommand, root},
|
FILE *fout = fopen(StdinPath.c_str(), "wb");
|
||||||
input.GetString());
|
fwrite(input.c_str(), input.size(), 1, fout);
|
||||||
FILE *fout = fopen(Path.c_str(), "wb");
|
|
||||||
fwrite(contents.c_str(), contents.size(), 1, fout);
|
|
||||||
fclose(fout);
|
fclose(fout);
|
||||||
#endif
|
}
|
||||||
|
std::array<Optional<StringRef>, 3> Redir{StringRef(StdinPath),
|
||||||
|
StringRef(Path), StringRef()};
|
||||||
|
std::vector<StringRef> args{g_config->compilationDatabaseCommand, root};
|
||||||
|
if (sys::ExecuteAndWait(args[0], args, llvm::None, Redir, 0, 0, &err_msg) <
|
||||||
|
0) {
|
||||||
|
LOG_S(ERROR) << "failed to execute " << args[0].str() << " "
|
||||||
|
<< args[1].str() << ": " << err_msg;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string err_msg;
|
|
||||||
std::unique_ptr<tooling::CompilationDatabase> CDB =
|
std::unique_ptr<tooling::CompilationDatabase> CDB =
|
||||||
tooling::CompilationDatabase::loadFromDirectory(CDBDir, err_msg);
|
tooling::CompilationDatabase::loadFromDirectory(CDBDir, err_msg);
|
||||||
if (!g_config->compilationDatabaseCommand.empty()) {
|
if (!g_config->compilationDatabaseCommand.empty()) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// TODO
|
DeleteFileA(StdinPath.c_str());
|
||||||
|
DeleteFileA(Path.c_str());
|
||||||
|
RemoveDirectoryA(CDBDir.c_str());
|
||||||
#else
|
#else
|
||||||
|
unlink(StdinPath.c_str());
|
||||||
unlink(Path.c_str());
|
unlink(Path.c_str());
|
||||||
rmdir(CDBDir.c_str());
|
rmdir(CDBDir.c_str());
|
||||||
#endif
|
#endif
|
||||||
@ -354,7 +375,10 @@ void Project::LoadDirectory(const std::string &root, Project::Folder &folder) {
|
|||||||
ProjectProcessor proc(folder);
|
ProjectProcessor proc(folder);
|
||||||
StringSet<> Seen;
|
StringSet<> Seen;
|
||||||
std::vector<Project::Entry> result;
|
std::vector<Project::Entry> result;
|
||||||
if (CDB) {
|
if (!CDB) {
|
||||||
|
if (g_config->compilationDatabaseCommand.size() || sys::fs::exists(Path))
|
||||||
|
LOG_S(ERROR) << "failed to load " << Path.c_str();
|
||||||
|
} else {
|
||||||
LOG_S(INFO) << "loaded " << Path.c_str();
|
LOG_S(INFO) << "loaded " << Path.c_str();
|
||||||
for (tooling::CompileCommand &Cmd : CDB->getAllCompileCommands()) {
|
for (tooling::CompileCommand &Cmd : CDB->getAllCompileCommands()) {
|
||||||
static bool once;
|
static bool once;
|
||||||
|
Loading…
Reference in New Issue
Block a user