Support of clangd for the project

This commit is contained in:
Patedam committed 2026-10-05 23:37:18 -04:00
1 parent 7075556bf2
commit 16ba641d8a
6 files changed
+607 -120

No files matched your search

+23
View File
@@ -0,0 +1,23 @@
CompileFlags:
Add:
- --driver-mode=cl
- -Wno-unknown-pragmas
- -Wno-unused-command-line-argument
Remove:
- /Yu*
- /Yc*
- /Fp*
- /MP
- /Zi
- /Gw
- /Gy
- /Bt+
- /EHa-
Diagnostics:
UnusedIncludes: None
InlayHints:
Enabled: Yes
ParameterNames: Yes
DeducedTypes: Yes
+4
View File
@@ -56,3 +56,7 @@ launch_*.txt
*.log *.log
misc/agent_error.log misc/agent_error.log
misc/agent_output_ship.log misc/agent_output_ship.log
# Clangd
compile_commands.json
.cache/
+2 -1
View File
@@ -76,8 +76,9 @@ if %ERRORLEVEL% neq 0 (
exit /b %ERRORLEVEL% exit /b %ERRORLEVEL%
) )
echo Solutions generated successfully: echo Solutions and LSP configuration generated successfully:
echo - Juliet.sln echo - Juliet.sln
echo - Romeo.sln echo - Romeo.sln
echo - JulietShaderCompiler.sln echo - JulietShaderCompiler.sln
echo - compile_commands.json
exit /b 0 exit /b 0
+11
View File
@@ -33,6 +33,11 @@ if /i "%~1"=="gen_vs" (
set GEN_VS_PLAN=%~2 set GEN_VS_PLAN=%~2
goto do_compile_build_tool goto do_compile_build_tool
) )
if /i "%~1"=="gen_compile_commands" (
set COMMAND_GEN_COMPILE_COMMANDS=1
set GEN_COMPILE_COMMANDS_PLAN=%~2
goto do_compile_build_tool
)
if /i "%~1"=="clean" ( if /i "%~1"=="clean" (
echo [BUILD] Cleaning output directories... echo [BUILD] Cleaning output directories...
if exist Intermediate rmdir /s /q Intermediate if exist Intermediate rmdir /s /q Intermediate
@@ -118,6 +123,12 @@ if "!COMMAND_GEN_VS!"=="1" (
exit /b !ERRORLEVEL! exit /b !ERRORLEVEL!
) )
if "!COMMAND_GEN_COMPILE_COMMANDS!"=="1" (
echo [BUILD] Generating compile_commands.json...
"%BUILD_TOOL%" gen_compile_commands "!GEN_COMPILE_COMMANDS_PLAN!"
exit /b !ERRORLEVEL!
)
echo [BUILD] Generating Build Plan... echo [BUILD] Generating Build Plan...
set PLAN_FILE=Intermediate\build_plan.txt set PLAN_FILE=Intermediate\build_plan.txt
if exist "!PLAN_FILE!" del /f /q "!PLAN_FILE!" if exist "!PLAN_FILE!" del /f /q "!PLAN_FILE!"
+1 -1
View File
@@ -4,5 +4,5 @@ pushd .
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
popd popd
set path=W:\Classified\Juliet\misc;%path% set path=%~dp0;%path%
set _NO_DEBUG_HEAP=1 set _NO_DEBUG_HEAP=1
+566 -118
View File
@@ -1551,163 +1551,608 @@ static void GenerateDeterministicGuid(const char* input, char* outputGuid) {
hash2 & 0xFFFFFFFFFFFFULL); hash2 & 0xFFFFFFFFFFFFULL);
} }
static int CommandGenVS(int argc, char* argv[]) static void clean_include_path(const char* in_path, char* out_path, size_t out_size)
{ {
if (argc < 3) { assert(in_path != NULL);
printf("[ERROR] Usage: build_system gen_vs <plan_file>\n"); assert(out_path != NULL);
return 1; assert(out_size > 0);
const char* p = in_path;
const char* sln_prefix_win = "$(SolutionDir)..\\";
const char* sln_prefix_fwd = "$(SolutionDir)../";
if (strncmp(p, sln_prefix_win, 17) == 0 || strncmp(p, sln_prefix_fwd, 17) == 0)
{
p += 17;
} }
const char* planFile = argv[2]; else if (strncmp(p, "..\\", 3) == 0 || strncmp(p, "../", 3) == 0)
FileContent planContent = ReadEntireFile(planFile); {
if (!planContent.Data) { p += 3;
printf("[ERROR] Could not read VS plan: %s\n", planFile);
return 1;
} }
char globalInclude[1024] = {0}; while (*p == '\\' || *p == '/')
char globalDefCommon[1024] = {0}; {
char globalDefDebug[1024] = {0}; p++;
char globalDefProfile[1024] = {0}; }
char globalDefRelease[1024] = {0};
VSProject projects[16];
int projCount = 0;
VSSolution solutions[8]; size_t j = 0;
int slnCount = 0; for (size_t i = 0; p[i] != '\0' && j + 1 < out_size; i++)
{
if (p[i] == '\\')
{
out_path[j++] = '/';
}
else
{
out_path[j++] = p[i];
}
}
out_path[j] = '\0';
const char* pos = planContent.Data; while (j > 0 && out_path[j - 1] == '/')
while (*pos) { {
const char* lineStart = pos; out_path[--j] = '\0';
while (*pos && *pos != '\n' && *pos != '\r') pos++; }
int lineLen = (int)(pos - lineStart); }
if (lineLen > 0) { static void parse_semicolon_tokens(const char* input, char tokens[32][256], int* count)
if (lineLen > 15 && memcmp(lineStart, "GLOBAL_INCLUDE ", 15) == 0) { {
int nLen = lineLen - 15; assert(tokens != NULL);
if (nLen >= 1024) nLen = 1023; assert(count != NULL);
memcpy(globalInclude, lineStart + 15, nLen);
globalInclude[nLen] = '\0'; *count = 0;
if (input == NULL || input[0] == '\0')
{
return;
}
const char* start = input;
while (*start != '\0')
{
while (*start == ' ' || *start == '\t' || *start == ';')
{
start++;
}
if (*start == '\0')
{
break;
}
const char* end = start;
while (*end != '\0' && *end != ';')
{
end++;
}
int len = (int)(end - start);
while (len > 0 && (start[len - 1] == ' ' || start[len - 1] == '\t' || start[len - 1] == '\r' || start[len - 1] == '\n'))
{
len--;
}
if (len > 0 && *count < 32)
{
int copy_len = len < 255 ? len : 255;
memcpy(tokens[*count], start, copy_len);
tokens[*count][copy_len] = '\0';
(*count)++;
}
start = end;
}
}
static void generate_compile_commands(
const VSProject* projects,
int proj_count,
const char* global_include,
const char* def_common,
const char* def_debug)
{
assert(projects != NULL);
assert(proj_count >= 0);
assert(global_include != NULL);
char cwd[MAX_PATH_LEN];
HANDLE dir_handle = CreateFileA(".", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (dir_handle != INVALID_HANDLE_VALUE)
{
char real_path[MAX_PATH_LEN];
DWORD len = GetFinalPathNameByHandleA(dir_handle, real_path, MAX_PATH_LEN, FILE_NAME_NORMALIZED);
CloseHandle(dir_handle);
if (len > 0 && len < MAX_PATH_LEN)
{
const char* p = real_path;
if (strncmp(p, "\\\\?\\", 4) == 0)
{
p += 4;
} }
else if (lineLen > 11 && memcmp(lineStart, "DEF_COMMON ", 11) == 0) { strncpy_s(cwd, sizeof(cwd), p, _TRUNCATE);
int nLen = lineLen - 11; }
if (nLen >= 1024) nLen = 1023; else
memcpy(globalDefCommon, lineStart + 11, nLen); {
globalDefCommon[nLen] = '\0'; GetCurrentDirectoryA((DWORD)sizeof(cwd), cwd);
}
}
else
{
GetCurrentDirectoryA((DWORD)sizeof(cwd), cwd);
}
for (int i = 0; cwd[i] != '\0'; i++)
{
if (cwd[i] == '\\')
{
cwd[i] = '/';
}
}
size_t cwd_len = strlen(cwd);
while (cwd_len > 0 && cwd[cwd_len - 1] == '/')
{
cwd[--cwd_len] = '\0';
}
size_t buffer_size = 8 * 1024 * 1024;
char* json_buf = (char*)ArenaPush(buffer_size);
int offset = 0;
offset += sprintf_s(json_buf + offset, buffer_size - offset, "[\n");
bool is_first_entry = true;
for (int i = 0; i < proj_count; i++)
{
const VSProject* p = &projects[i];
const char* inc_str = p->IncludeSearch[0] != '\0' ? p->IncludeSearch : global_include;
char inc_tokens[32][256];
int inc_count = 0;
parse_semicolon_tokens(inc_str, inc_tokens, &inc_count);
char def_common_tokens[32][256];
int def_common_count = 0;
parse_semicolon_tokens(def_common, def_common_tokens, &def_common_count);
char def_debug_tokens[32][256];
int def_debug_count = 0;
parse_semicolon_tokens(def_debug, def_debug_tokens, &def_debug_count);
char def_extra_tokens[32][256];
int def_extra_count = 0;
parse_semicolon_tokens(p->ExtraDef, def_extra_tokens, &def_extra_count);
bool has_imgui_api = false;
for (int d = 0; d < def_extra_count; d++)
{
if (strncmp(def_extra_tokens[d], "IMGUI_API", 9) == 0)
{
has_imgui_api = true;
break;
} }
else if (lineLen > 10 && memcmp(lineStart, "DEF_DEBUG ", 10) == 0) { }
int nLen = lineLen - 10;
if (nLen >= 1024) nLen = 1023; FilePathList* src_files = CreateFilePathList();
memcpy(globalDefDebug, lineStart + 10, nLen); if (p->SrcCount > 0)
globalDefDebug[nLen] = '\0'; {
for (int s = 0; s < p->SrcCount; s++)
{
if (EndsWithNoCase(p->Srcs[s], ".cpp") || EndsWithNoCase(p->Srcs[s], ".c"))
{
FilePathListAdd(src_files, p->Srcs[s]);
}
} }
else if (lineLen > 12 && memcmp(lineStart, "DEF_PROFILE ", 12) == 0) { }
int nLen = lineLen - 12; else
if (nLen >= 1024) nLen = 1023; {
memcpy(globalDefProfile, lineStart + 12, nLen); CollectFiles(p->Dir, NULL, ".cpp", src_files);
globalDefProfile[nLen] = '\0'; CollectFiles(p->Dir, NULL, ".c", src_files);
}
for (int f = 0; f < src_files->Count; f++)
{
const char* raw_path = src_files->Paths[f];
char clean_rel[MAX_PATH_LEN];
clean_include_path(raw_path, clean_rel, sizeof(clean_rel));
char full_path[MAX_PATH_LEN];
if ((clean_rel[1] == ':' && clean_rel[2] == '/') || (clean_rel[0] == '/'))
{
strncpy_s(full_path, sizeof(full_path), clean_rel, _TRUNCATE);
} }
else if (lineLen > 12 && memcmp(lineStart, "DEF_RELEASE ", 12) == 0) { else
int nLen = lineLen - 12; {
if (nLen >= 1024) nLen = 1023; snprintf(full_path, sizeof(full_path), "%s/%s", cwd, clean_rel);
memcpy(globalDefRelease, lineStart + 12, nLen);
globalDefRelease[nLen] = '\0';
} }
else if (lineLen > 8 && memcmp(lineStart, "PROJECT ", 8) == 0) {
if (projCount < 16) { if (!is_first_entry)
VSProject* p = &projects[projCount++]; {
offset += sprintf_s(json_buf + offset, buffer_size - offset, ",\n");
}
is_first_entry = false;
offset += sprintf_s(json_buf + offset, buffer_size - offset,
" {\n"
" \"directory\": \"%s\",\n"
" \"file\": \"%s\",\n"
" \"arguments\": [\n"
" \"clang-cl.exe\",\n"
" \"--driver-mode=cl\",\n"
" \"/nologo\",\n"
" \"/std:c++20\",\n"
" \"/W4\",\n"
" \"/utf-8\",\n",
cwd, full_path);
for (int d = 0; d < def_common_count; d++)
{
offset += sprintf_s(json_buf + offset, buffer_size - offset,
" \"/D%s\",\n", def_common_tokens[d]);
}
for (int d = 0; d < def_debug_count; d++)
{
offset += sprintf_s(json_buf + offset, buffer_size - offset,
" \"/D%s\",\n", def_debug_tokens[d]);
}
offset += sprintf_s(json_buf + offset, buffer_size - offset,
" \"/DIMGUI_DEFINE_MATH_OPERATORS\",\n");
for (int d = 0; d < def_extra_count; d++)
{
offset += sprintf_s(json_buf + offset, buffer_size - offset,
" \"/D%s\",\n", def_extra_tokens[d]);
}
if (!has_imgui_api)
{
if (strcmp(p->Name, "Juliet") == 0 || strcmp(p->Name, "ImGui") == 0)
{
offset += sprintf_s(json_buf + offset, buffer_size - offset,
" \"/DIMGUI_API=__declspec(dllexport)\",\n");
}
else
{
offset += sprintf_s(json_buf + offset, buffer_size - offset,
" \"/DIMGUI_API=__declspec(dllimport)\",\n");
}
}
for (int c = 0; c < inc_count; c++)
{
char clean_inc[MAX_PATH_LEN];
clean_include_path(inc_tokens[c], clean_inc, sizeof(clean_inc));
if (clean_inc[0] != '\0')
{
offset += sprintf_s(json_buf + offset, buffer_size - offset,
" \"/I%s\",\n", clean_inc);
}
}
if (p->PchHeader[0] != '\0')
{
char clean_pch[MAX_PATH_LEN];
clean_include_path(p->PchHeader, clean_pch, sizeof(clean_pch));
offset += sprintf_s(json_buf + offset, buffer_size - offset,
" \"/FI%s\",\n", clean_pch);
}
offset += sprintf_s(json_buf + offset, buffer_size - offset,
" \"-c\",\n"
" \"%s\"\n"
" ]\n"
" }",
full_path);
}
}
offset += sprintf_s(json_buf + offset, buffer_size - offset, "\n]\n");
WriteEntireFile("compile_commands.json", json_buf, offset);
printf("Generated compile_commands.json\n");
}
static bool parse_vs_plan(
const char* plan_file,
char* global_include,
size_t global_include_size,
char* global_def_common,
size_t global_def_common_size,
char* global_def_debug,
size_t global_def_debug_size,
char* global_def_profile,
size_t global_def_profile_size,
char* global_def_release,
size_t global_def_release_size,
VSProject* projects,
int* proj_count,
VSSolution* solutions,
int* sln_count)
{
assert(plan_file != NULL);
assert(projects != NULL);
assert(proj_count != NULL);
FileContent plan_content = ReadEntireFile(plan_file);
if (!plan_content.Data)
{
printf("[ERROR] Could not read VS plan: %s\n", plan_file);
return false;
}
*proj_count = 0;
if (sln_count != NULL)
{
*sln_count = 0;
}
const char* pos = plan_content.Data;
while (*pos != '\0')
{
const char* line_start = pos;
while (*pos != '\0' && *pos != '\n' && *pos != '\r')
{
pos++;
}
int line_len = (int)(pos - line_start);
if (line_len > 0)
{
if (line_len > 15 && memcmp(line_start, "GLOBAL_INCLUDE ", 15) == 0 && global_include != NULL)
{
int n_len = line_len - 15;
if ((size_t)n_len >= global_include_size)
{
n_len = (int)global_include_size - 1;
}
memcpy(global_include, line_start + 15, n_len);
global_include[n_len] = '\0';
}
else if (line_len > 11 && memcmp(line_start, "DEF_COMMON ", 11) == 0 && global_def_common != NULL)
{
int n_len = line_len - 11;
if ((size_t)n_len >= global_def_common_size)
{
n_len = (int)global_def_common_size - 1;
}
memcpy(global_def_common, line_start + 11, n_len);
global_def_common[n_len] = '\0';
}
else if (line_len > 10 && memcmp(line_start, "DEF_DEBUG ", 10) == 0 && global_def_debug != NULL)
{
int n_len = line_len - 10;
if ((size_t)n_len >= global_def_debug_size)
{
n_len = (int)global_def_debug_size - 1;
}
memcpy(global_def_debug, line_start + 10, n_len);
global_def_debug[n_len] = '\0';
}
else if (line_len > 12 && memcmp(line_start, "DEF_PROFILE ", 12) == 0 && global_def_profile != NULL)
{
int n_len = line_len - 12;
if ((size_t)n_len >= global_def_profile_size)
{
n_len = (int)global_def_profile_size - 1;
}
memcpy(global_def_profile, line_start + 12, n_len);
global_def_profile[n_len] = '\0';
}
else if (line_len > 12 && memcmp(line_start, "DEF_RELEASE ", 12) == 0 && global_def_release != NULL)
{
int n_len = line_len - 12;
if ((size_t)n_len >= global_def_release_size)
{
n_len = (int)global_def_release_size - 1;
}
memcpy(global_def_release, line_start + 12, n_len);
global_def_release[n_len] = '\0';
}
else if (line_len > 8 && memcmp(line_start, "PROJECT ", 8) == 0)
{
if (*proj_count < 16)
{
VSProject* p = &projects[(*proj_count)++];
memset(p, 0, sizeof(VSProject)); memset(p, 0, sizeof(VSProject));
char lineBuf[1024]; char line_buf[1024];
int nLen = lineLen - 8; int n_len = line_len - 8;
if (nLen >= 1024) nLen = 1023; if (n_len >= 1024)
memcpy(lineBuf, lineStart + 8, nLen); {
lineBuf[nLen] = '\0'; n_len = 1023;
int scanned = sscanf_s(lineBuf, "%s %s %s", p->Name, (unsigned)_countof(p->Name), p->Dir, (unsigned)_countof(p->Dir), p->Guid, (unsigned)_countof(p->Guid)); }
if (scanned < 2) { memcpy(line_buf, line_start + 8, n_len);
line_buf[n_len] = '\0';
int scanned = sscanf_s(line_buf, "%s %s %s", p->Name, (unsigned)_countof(p->Name), p->Dir, (unsigned)_countof(p->Dir), p->Guid, (unsigned)_countof(p->Guid));
if (scanned < 2)
{
strcpy_s(p->Dir, sizeof(p->Dir), p->Name); strcpy_s(p->Dir, sizeof(p->Dir), p->Name);
} }
if (scanned < 3) { if (scanned < 3)
{
GenerateDeterministicGuid(p->Name, p->Guid); GenerateDeterministicGuid(p->Name, p->Guid);
} }
} }
} }
else if (lineLen > 12 && memcmp(lineStart, "PROJECT_SRC ", 12) == 0 && projCount > 0) { else if (line_len > 12 && memcmp(line_start, "PROJECT_SRC ", 12) == 0 && *proj_count > 0)
VSProject* p = &projects[projCount - 1]; {
if (p->SrcCount < 64) { VSProject* p = &projects[*proj_count - 1];
int nLen = lineLen - 12; if (p->SrcCount < 64)
if (nLen >= 256) nLen = 255; {
memcpy(p->Srcs[p->SrcCount], lineStart + 12, nLen); int n_len = line_len - 12;
p->Srcs[p->SrcCount][nLen] = '\0'; if (n_len >= 256)
{
n_len = 255;
}
memcpy(p->Srcs[p->SrcCount], line_start + 12, n_len);
p->Srcs[p->SrcCount][n_len] = '\0';
p->SrcCount++; p->SrcCount++;
} }
} }
else if (lineLen > 10 && memcmp(lineStart, "EXTRA_DEF ", 10) == 0 && projCount > 0) { else if (line_len > 10 && memcmp(line_start, "EXTRA_DEF ", 10) == 0 && *proj_count > 0)
VSProject* p = &projects[projCount - 1]; {
int nLen = lineLen - 10; VSProject* p = &projects[*proj_count - 1];
if (nLen >= 1024) nLen = 1023; int n_len = line_len - 10;
memcpy(p->ExtraDef, lineStart + 10, nLen); if (n_len >= 1024)
p->ExtraDef[nLen] = '\0'; {
n_len = 1023;
}
memcpy(p->ExtraDef, line_start + 10, n_len);
p->ExtraDef[n_len] = '\0';
} }
else if (lineLen > 15 && memcmp(lineStart, "INCLUDE_SEARCH ", 15) == 0 && projCount > 0) { else if (line_len > 15 && memcmp(line_start, "INCLUDE_SEARCH ", 15) == 0 && *proj_count > 0)
VSProject* p = &projects[projCount - 1]; {
int nLen = lineLen - 15; VSProject* p = &projects[*proj_count - 1];
if (nLen >= 1024) nLen = 1023; int n_len = line_len - 15;
memcpy(p->IncludeSearch, lineStart + 15, nLen); if (n_len >= 1024)
p->IncludeSearch[nLen] = '\0'; {
n_len = 1023;
}
memcpy(p->IncludeSearch, line_start + 15, n_len);
p->IncludeSearch[n_len] = '\0';
} }
else if (lineLen > 10 && memcmp(lineStart, "DEBUG_CMD ", 10) == 0 && projCount > 0) { else if (line_len > 10 && memcmp(line_start, "DEBUG_CMD ", 10) == 0 && *proj_count > 0)
VSProject* p = &projects[projCount - 1]; {
int nLen = lineLen - 10; VSProject* p = &projects[*proj_count - 1];
if (nLen >= 1024) nLen = 1023; int n_len = line_len - 10;
memcpy(p->DebugCmd, lineStart + 10, nLen); if (n_len >= 1024)
p->DebugCmd[nLen] = '\0'; {
n_len = 1023;
}
memcpy(p->DebugCmd, line_start + 10, n_len);
p->DebugCmd[n_len] = '\0';
} }
else if (lineLen > 4 && memcmp(lineStart, "PCH ", 4) == 0 && projCount > 0) { else if (line_len > 4 && memcmp(line_start, "PCH ", 4) == 0 && *proj_count > 0)
VSProject* p = &projects[projCount - 1]; {
char lineBuf[1024]; VSProject* p = &projects[*proj_count - 1];
int nLen = lineLen - 4; char line_buf[1024];
if (nLen >= 1024) nLen = 1023; int n_len = line_len - 4;
memcpy(lineBuf, lineStart + 4, nLen); if (n_len >= 1024)
lineBuf[nLen] = '\0'; {
sscanf_s(lineBuf, "%s %s", p->PchHeader, (unsigned)_countof(p->PchHeader), p->PchSrc, (unsigned)_countof(p->PchSrc)); n_len = 1023;
}
memcpy(line_buf, line_start + 4, n_len);
line_buf[n_len] = '\0';
sscanf_s(line_buf, "%s %s", p->PchHeader, (unsigned)_countof(p->PchHeader), p->PchSrc, (unsigned)_countof(p->PchSrc));
} }
else if (lineLen > 9 && memcmp(lineStart, "SOLUTION ", 9) == 0) { else if (line_len > 9 && memcmp(line_start, "SOLUTION ", 9) == 0 && solutions != NULL && sln_count != NULL)
if (slnCount < 8) { {
VSSolution* s = &solutions[slnCount++]; if (*sln_count < 8)
{
VSSolution* s = &solutions[(*sln_count)++];
memset(s, 0, sizeof(VSSolution)); memset(s, 0, sizeof(VSSolution));
int nLen = lineLen - 9; int n_len = line_len - 9;
if (nLen >= 64) nLen = 63; if (n_len >= 64)
memcpy(s->Name, lineStart + 9, nLen); {
s->Name[nLen] = '\0'; n_len = 63;
}
memcpy(s->Name, line_start + 9, n_len);
s->Name[n_len] = '\0';
} }
} }
else if (lineLen > 9 && memcmp(lineStart, "SLN_PROJ ", 9) == 0 && slnCount > 0) { else if (line_len > 9 && memcmp(line_start, "SLN_PROJ ", 9) == 0 && sln_count != NULL && *sln_count > 0 && solutions != NULL)
VSSolution* s = &solutions[slnCount - 1]; {
if (s->ProjCount < 16) { VSSolution* s = &solutions[*sln_count - 1];
int nLen = lineLen - 9; if (s->ProjCount < 16)
if (nLen >= 64) nLen = 63; {
memcpy(s->Projects[s->ProjCount], lineStart + 9, nLen); int n_len = line_len - 9;
s->Projects[s->ProjCount][nLen] = '\0'; if (n_len >= 64)
{
n_len = 63;
}
memcpy(s->Projects[s->ProjCount], line_start + 9, n_len);
s->Projects[s->ProjCount][n_len] = '\0';
s->ProjCount++; s->ProjCount++;
} }
} }
} }
while (*pos == '\n' || *pos == '\r') pos++; while (*pos == '\n' || *pos == '\r')
{
pos++;
}
} }
for (int i = 0; i < projCount; i++) { return true;
}
static int CommandGenCompileCommands(int argc, char* argv[])
{
if (argc < 3)
{
printf("[ERROR] Usage: build_system gen_compile_commands <plan_file>\n");
return 1;
}
const char* plan_file = argv[2];
char global_include[1024] = {0};
char global_def_common[1024] = {0};
char global_def_debug[1024] = {0};
char global_def_profile[1024] = {0};
char global_def_release[1024] = {0};
VSProject projects[16];
int proj_count = 0;
if (!parse_vs_plan(plan_file,
global_include, sizeof(global_include),
global_def_common, sizeof(global_def_common),
global_def_debug, sizeof(global_def_debug),
global_def_profile, sizeof(global_def_profile),
global_def_release, sizeof(global_def_release),
projects, &proj_count, NULL, NULL))
{
return 1;
}
generate_compile_commands(projects, proj_count, global_include, global_def_common, global_def_debug);
return 0;
}
static int CommandGenVS(int argc, char* argv[])
{
if (argc < 3)
{
printf("[ERROR] Usage: build_system gen_vs <plan_file>\n");
return 1;
}
const char* plan_file = argv[2];
char global_include[1024] = {0};
char global_def_common[1024] = {0};
char global_def_debug[1024] = {0};
char global_def_profile[1024] = {0};
char global_def_release[1024] = {0};
VSProject projects[16];
int proj_count = 0;
VSSolution solutions[8];
int sln_count = 0;
if (!parse_vs_plan(plan_file,
global_include, sizeof(global_include),
global_def_common, sizeof(global_def_common),
global_def_debug, sizeof(global_def_debug),
global_def_profile, sizeof(global_def_profile),
global_def_release, sizeof(global_def_release),
projects, &proj_count, solutions, &sln_count))
{
return 1;
}
for (int i = 0; i < proj_count; i++)
{
VSProject* p = &projects[i]; VSProject* p = &projects[i];
const char* incs = p->IncludeSearch[0] != '\0' ? p->IncludeSearch : globalInclude; const char* incs = p->IncludeSearch[0] != '\0' ? p->IncludeSearch : global_include;
GenerateProject(p->Name, p->Dir, p->Guid, incs, p->ExtraDef, p->DebugCmd, p->Srcs, p->SrcCount, globalDefCommon, globalDefDebug, globalDefProfile, globalDefRelease, p->PchHeader, p->PchSrc); GenerateProject(p->Name, p->Dir, p->Guid, incs, p->ExtraDef, p->DebugCmd, p->Srcs, p->SrcCount, global_def_common, global_def_debug, global_def_profile, global_def_release, p->PchHeader, p->PchSrc);
} }
for (int i = 0; i < slnCount; i++) { for (int i = 0; i < sln_count; i++)
{
VSSolution* s = &solutions[i]; VSSolution* s = &solutions[i];
const char* pNames[16]; const char* pNames[16];
const char* pGuids[16]; const char* pGuids[16];
for (int j = 0; j < s->ProjCount; j++) { for (int j = 0; j < s->ProjCount; j++)
{
pNames[j] = s->Projects[j]; pNames[j] = s->Projects[j];
for (int k = 0; k < projCount; k++) { for (int k = 0; k < proj_count; k++)
if (strcmp(projects[k].Name, s->Projects[j]) == 0) { {
if (strcmp(projects[k].Name, s->Projects[j]) == 0)
{
pGuids[j] = projects[k].Guid; pGuids[j] = projects[k].Guid;
break; break;
} }
@@ -1716,6 +2161,7 @@ static int CommandGenVS(int argc, char* argv[])
GenerateSolution(s->Name, pNames, pGuids, s->ProjCount); GenerateSolution(s->Name, pNames, pGuids, s->ProjCount);
} }
generate_compile_commands(projects, proj_count, global_include, global_def_common, global_def_debug);
return 0; return 0;
} }
@@ -1728,9 +2174,10 @@ int main(int argc, char* argv[])
{ {
printf("Usage: build_system <command> [args...]\n"); printf("Usage: build_system <command> [args...]\n");
printf("Commands:\n"); printf("Commands:\n");
printf(" run_plan <plan_file> Run the build from a generated plan file\n"); printf(" run_plan <plan_file> Run the build from a generated plan file\n");
printf(" gen_vs Generate Visual Studio project and solution files\n"); printf(" gen_vs <plan_file> Generate Visual Studio project, solution, and compile_commands files\n");
printf(" check_alive Returns 0 immediately to test execution\n"); printf(" gen_compile_commands <plan_file> Generate compile_commands.json for Neovim/clangd\n");
printf(" check_alive Returns 0 immediately to test execution\n");
return 1; return 1;
} }
@@ -1738,6 +2185,7 @@ int main(int argc, char* argv[])
if (strcmp(cmd, "check_alive") == 0) return 0; if (strcmp(cmd, "check_alive") == 0) return 0;
if (strcmp(cmd, "run_plan") == 0) return CommandRunPlan(argc, argv); if (strcmp(cmd, "run_plan") == 0) return CommandRunPlan(argc, argv);
if (strcmp(cmd, "gen_vs") == 0) return CommandGenVS(argc, argv); if (strcmp(cmd, "gen_vs") == 0) return CommandGenVS(argc, argv);
if (strcmp(cmd, "gen_compile_commands") == 0) return CommandGenCompileCommands(argc, argv);
printf("[ERROR] Unknown command: %s\n", cmd); printf("[ERROR] Unknown command: %s\n", cmd);
return 1; return 1;