Skip to content

Commit 8b3d5a4

Browse files
committed
Implement initialization option compilationDatabaseCommand on Windows
1 parent 464443c commit 8b3d5a4

4 files changed

Lines changed: 41 additions & 69 deletions

File tree

src/platform.hh

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,5 @@ void FreeUnusedMemory();
2828
// Stop self and wait for SIGCONT.
2929
void TraceMe();
3030

31-
std::string GetExternalCommandOutput(const std::vector<std::string> &command,
32-
std::string_view input);
33-
3431
void SpawnThread(void *(*fn)(void *), void *arg);
3532
} // namespace ccls

src/platform_posix.cc

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -73,49 +73,6 @@ void TraceMe() {
7373
raise(traceme[0] == 's' ? SIGSTOP : SIGTSTP);
7474
}
7575

76-
std::string GetExternalCommandOutput(const std::vector<std::string> &command,
77-
std::string_view input) {
78-
int pin[2], pout[2];
79-
if (pipe(pin) < 0) {
80-
perror("pipe(stdin)");
81-
return "";
82-
}
83-
if (pipe(pout) < 0) {
84-
perror("pipe(stdout)");
85-
close(pin[0]);
86-
close(pin[1]);
87-
return "";
88-
}
89-
pid_t child = fork();
90-
if (child == 0) {
91-
dup2(pout[0], 0);
92-
dup2(pin[1], 1);
93-
close(pin[0]);
94-
close(pin[1]);
95-
close(pout[0]);
96-
close(pout[1]);
97-
auto argv = new char *[command.size() + 1];
98-
for (size_t i = 0; i < command.size(); i++)
99-
argv[i] = const_cast<char *>(command[i].c_str());
100-
argv[command.size()] = nullptr;
101-
execvp(argv[0], argv);
102-
_Exit(127);
103-
}
104-
close(pin[1]);
105-
close(pout[0]);
106-
// O_NONBLOCK is disabled, write(2) blocks until all bytes are written.
107-
(void)write(pout[1], input.data(), input.size());
108-
close(pout[1]);
109-
std::string ret;
110-
char buf[4096];
111-
ssize_t n;
112-
while ((n = read(pin[0], buf, sizeof buf)) > 0)
113-
ret.append(buf, n);
114-
close(pin[0]);
115-
waitpid(child, NULL, 0);
116-
return ret;
117-
}
118-
11976
void SpawnThread(void *(*fn)(void *), void *arg) {
12077
pthread_t thd;
12178
pthread_attr_t attr;

src/platform_win.cc

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,6 @@ void FreeUnusedMemory() {}
5757
// TODO Wait for debugger to attach
5858
void TraceMe() {}
5959

60-
std::string GetExternalCommandOutput(const std::vector<std::string> &command,
61-
std::string_view input) {
62-
return "";
63-
}
64-
6560
void SpawnThread(void *(*fn)(void *), void *arg) {
6661
std::thread(fn, arg).detach();
6762
}

src/project.cc

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,17 @@ limitations under the License.
3131
#include <llvm/ADT/STLExtras.h>
3232
#include <llvm/ADT/StringSet.h>
3333
#include <llvm/Support/LineIterator.h>
34+
#include <llvm/Support/Program.h>
3435

3536
#include <rapidjson/writer.h>
3637

37-
#if defined(__unix__) || defined(__APPLE__)
38-
#include <unistd.h>
38+
#ifdef _WIN32
39+
# include <Windows.h>
40+
#else
41+
# include <unistd.h>
3942
#endif
4043

44+
#include <array>
4145
#include <limits.h>
4246
#include <unordered_set>
4347
#include <vector>
@@ -308,7 +312,8 @@ int ComputeGuessScore(std::string_view a, std::string_view b) {
308312
} // namespace
309313

310314
void Project::LoadDirectory(const std::string &root, Project::Folder &folder) {
311-
SmallString<256> Path, CDBDir;
315+
SmallString<256> CDBDir, Path, StdinPath;
316+
std::string err_msg;
312317
folder.entries.clear();
313318
if (g_config->compilationDatabaseCommand.empty()) {
314319
CDBDir = root;
@@ -319,33 +324,49 @@ void Project::LoadDirectory(const std::string &root, Project::Folder &folder) {
319324
// If `compilationDatabaseCommand` is specified, execute it to get the
320325
// compdb.
321326
#ifdef _WIN32
322-
// TODO
327+
char tmpdir[L_tmpnam];
328+
tmpnam_s(tmpdir, L_tmpnam);
329+
CDBDir = tmpdir;
330+
if (sys::fs::create_directory(tmpdir, false))
331+
return;
323332
#else
324333
char tmpdir[] = "/tmp/ccls-compdb-XXXXXX";
325334
if (!mkdtemp(tmpdir))
326335
return;
327336
CDBDir = tmpdir;
328-
sys::path::append(Path, CDBDir, "compile_commands.json");
329-
rapidjson::StringBuffer input;
330-
rapidjson::Writer<rapidjson::StringBuffer> writer(input);
331-
JsonWriter json_writer(&writer);
332-
Reflect(json_writer, *g_config);
333-
std::string contents = GetExternalCommandOutput(
334-
std::vector<std::string>{g_config->compilationDatabaseCommand, root},
335-
input.GetString());
336-
FILE *fout = fopen(Path.c_str(), "wb");
337-
fwrite(contents.c_str(), contents.size(), 1, fout);
338-
fclose(fout);
339337
#endif
338+
sys::path::append(Path, CDBDir, "compile_commands.json");
339+
sys::path::append(StdinPath, CDBDir, "stdin");
340+
{
341+
rapidjson::StringBuffer sb;
342+
rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
343+
JsonWriter json_writer(&writer);
344+
Reflect(json_writer, *g_config);
345+
std::string input = sb.GetString();
346+
FILE *fout = fopen(StdinPath.c_str(), "wb");
347+
fwrite(input.c_str(), input.size(), 1, fout);
348+
fclose(fout);
349+
}
350+
std::array<Optional<StringRef>, 3> Redir{StringRef(StdinPath),
351+
StringRef(Path), StringRef()};
352+
std::vector<StringRef> args{g_config->compilationDatabaseCommand, root};
353+
if (sys::ExecuteAndWait(args[0], args, llvm::None, Redir, 0, 0, &err_msg) <
354+
0) {
355+
LOG_S(ERROR) << "failed to execute " << args[0].str() << " "
356+
<< args[1].str() << ": " << err_msg;
357+
return;
358+
}
340359
}
341360

342-
std::string err_msg;
343361
std::unique_ptr<tooling::CompilationDatabase> CDB =
344362
tooling::CompilationDatabase::loadFromDirectory(CDBDir, err_msg);
345363
if (!g_config->compilationDatabaseCommand.empty()) {
346364
#ifdef _WIN32
347-
// TODO
365+
DeleteFileA(StdinPath.c_str());
366+
DeleteFileA(Path.c_str());
367+
RemoveDirectoryA(CDBDir.c_str());
348368
#else
369+
unlink(StdinPath.c_str());
349370
unlink(Path.c_str());
350371
rmdir(CDBDir.c_str());
351372
#endif
@@ -354,7 +375,9 @@ void Project::LoadDirectory(const std::string &root, Project::Folder &folder) {
354375
ProjectProcessor proc(folder);
355376
StringSet<> Seen;
356377
std::vector<Project::Entry> result;
357-
if (CDB) {
378+
if (!CDB) {
379+
LOG_S(ERROR) << "failed to load " << Path.c_str() << " " << err_msg;
380+
} else {
358381
LOG_S(INFO) << "loaded " << Path.c_str();
359382
for (tooling::CompileCommand &Cmd : CDB->getAllCompileCommands()) {
360383
static bool once;

0 commit comments

Comments
 (0)