1. Make resource dir unique and global.

2. Use our custom CDB loader.
This commit is contained in:
ykiko
2024-12-10 16:15:50 +08:00
parent f9bff085b2
commit c082458fb1
16 changed files with 332 additions and 194 deletions

69
src/Compiler/Command.cpp Normal file
View File

@@ -0,0 +1,69 @@
#include "Compiler/Command.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
namespace clice {
llvm::Error mangleCommand(llvm::StringRef command,
llvm::SmallVectorImpl<const char*>& out,
llvm::SmallVectorImpl<char>& buffer) {
llvm::SmallString<128> current;
llvm::SmallVector<uint32_t> indices;
bool inSingleQuote = false;
bool inDoubleQuote = false;
for(size_t i = 0; i < command.size(); ++i) {
char c = command[i];
if(c == ' ' && !inSingleQuote && !inDoubleQuote) {
if(!current.empty()) {
indices.push_back(buffer.size());
buffer.append(current);
buffer.push_back('\0');
current.clear();
}
} else if(c == '\'' && !inDoubleQuote) {
inSingleQuote = !inSingleQuote;
} else if(c == '"' && !inSingleQuote) {
inDoubleQuote = !inDoubleQuote;
} else {
current.push_back(c);
}
}
if(!current.empty()) {
indices.push_back(buffer.size());
buffer.append(current);
buffer.push_back('\0');
}
/// Add resource directory.
indices.push_back(buffer.size());
current = std::format("-resource-dir={}", fs::resource_dir);
buffer.append(current);
buffer.push_back('\0');
/// FIXME: use better way to remove args.
for(size_t i = 0; i < indices.size(); ++i) {
llvm::StringRef arg(buffer.data() + indices[i]);
/// Skip `-c` and `-o` arguments.
if(arg == "-c") {
continue;
}
if(arg.starts_with("-o")) {
if(arg == "-o") {
++i;
}
continue;
}
/// TODO: remove PCH.
out.push_back(arg.data());
}
return llvm::Error::success();
}
} // namespace clice

View File

@@ -1,4 +1,6 @@
#include <Compiler/Command.h>
#include <Compiler/Compiler.h>
#include <clang/Lex/PreprocessorOptions.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
@@ -17,24 +19,32 @@ bool PCHInfo::needUpdate(llvm::StringRef content) {
namespace {
void adjustInvocation(clang::CompilerInvocation& invocation) {
auto& frontOpts = invocation.getFrontendOpts();
auto createInvocation(CompliationParams& params) {
llvm::SmallString<1024> buffer;
llvm::SmallVector<const char*, 16> args;
if(auto error = mangleCommand(params.command, args, buffer)) {
std::terminate();
}
clang::CreateInvocationOptions options = {};
options.VFS = params.vfs;
auto invocation = clang::createInvocation(args, options);
auto& frontOpts = invocation->getFrontendOpts();
frontOpts.DisableFree = false;
clang::LangOptions& langOpts = invocation.getLangOpts();
clang::LangOptions& langOpts = invocation->getLangOpts();
langOpts.CommentOpts.ParseAllComments = true;
langOpts.RetainCommentsFromSystemHeaders = true;
// FIXME: add more.
return invocation;
}
auto createInstance(CompliationParams& params) {
auto instance = std::make_unique<clang::CompilerInstance>();
/// TODO: Figure out `CreateInvocationOptions`.
clang::CreateInvocationOptions options = {};
options.VFS = params.vfs;
instance->setInvocation(clang::createInvocation(params.args, options));
instance->setInvocation(createInvocation(params));
/// TODO: use a thread safe filesystem and our customized `DiagnosticConsumer`.
instance->createDiagnostics(
@@ -44,8 +54,6 @@ auto createInstance(CompliationParams& params) {
instance->createFileManager(params.vfs);
adjustInvocation(instance->getInvocation());
/// Add remapped files, if bounds is provided, cut off the content.
std::size_t size =
params.bounds.has_value() ? params.bounds.value().Size : params.content.size();
@@ -140,7 +148,7 @@ void CompliationParams::computeBounds(llvm::StringRef header) {
assert(!content.empty() && "Source content is required to compute bounds");
if(header.empty()) {
auto invocation = clang::createInvocation(args, {});
auto invocation = createInvocation(*this);
bounds = clang::Lexer::ComputePreamble(content, invocation->getLangOpts());
return;
}