Support of clangd for the project
This commit is contained in:
1 parent
7075556bf2
commit
16ba641d8a
6 files changed
+607
-120
No files matched your search
@@ -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
|
||||
@@ -56,3 +56,7 @@ launch_*.txt
|
||||
*.log
|
||||
misc/agent_error.log
|
||||
misc/agent_output_ship.log
|
||||
|
||||
# Clangd
|
||||
compile_commands.json
|
||||
.cache/
|
||||
+2
-1
@@ -76,8 +76,9 @@ if %ERRORLEVEL% neq 0 (
|
||||
exit /b %ERRORLEVEL%
|
||||
)
|
||||
|
||||
echo Solutions generated successfully:
|
||||
echo Solutions and LSP configuration generated successfully:
|
||||
echo - Juliet.sln
|
||||
echo - Romeo.sln
|
||||
echo - JulietShaderCompiler.sln
|
||||
echo - compile_commands.json
|
||||
exit /b 0
|
||||
@@ -33,6 +33,11 @@ if /i "%~1"=="gen_vs" (
|
||||
set GEN_VS_PLAN=%~2
|
||||
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" (
|
||||
echo [BUILD] Cleaning output directories...
|
||||
if exist Intermediate rmdir /s /q Intermediate
|
||||
@@ -118,6 +123,12 @@ if "!COMMAND_GEN_VS!"=="1" (
|
||||
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...
|
||||
set PLAN_FILE=Intermediate\build_plan.txt
|
||||
if exist "!PLAN_FILE!" del /f /q "!PLAN_FILE!"
|
||||
|
||||
+1
-1
@@ -4,5 +4,5 @@ pushd .
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
popd
|
||||
|
||||
set path=W:\Classified\Juliet\misc;%path%
|
||||
set path=%~dp0;%path%
|
||||
set _NO_DEBUG_HEAP=1
|
||||
+566
-118
@@ -1551,163 +1551,608 @@ static void GenerateDeterministicGuid(const char* input, char* outputGuid) {
|
||||
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) {
|
||||
printf("[ERROR] Usage: build_system gen_vs <plan_file>\n");
|
||||
return 1;
|
||||
assert(in_path != NULL);
|
||||
assert(out_path != NULL);
|
||||
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];
|
||||
FileContent planContent = ReadEntireFile(planFile);
|
||||
if (!planContent.Data) {
|
||||
printf("[ERROR] Could not read VS plan: %s\n", planFile);
|
||||
return 1;
|
||||
else if (strncmp(p, "..\\", 3) == 0 || strncmp(p, "../", 3) == 0)
|
||||
{
|
||||
p += 3;
|
||||
}
|
||||
|
||||
char globalInclude[1024] = {0};
|
||||
char globalDefCommon[1024] = {0};
|
||||
char globalDefDebug[1024] = {0};
|
||||
char globalDefProfile[1024] = {0};
|
||||
char globalDefRelease[1024] = {0};
|
||||
VSProject projects[16];
|
||||
int projCount = 0;
|
||||
while (*p == '\\' || *p == '/')
|
||||
{
|
||||
p++;
|
||||
}
|
||||
|
||||
VSSolution solutions[8];
|
||||
int slnCount = 0;
|
||||
size_t j = 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 (*pos) {
|
||||
const char* lineStart = pos;
|
||||
while (*pos && *pos != '\n' && *pos != '\r') pos++;
|
||||
int lineLen = (int)(pos - lineStart);
|
||||
while (j > 0 && out_path[j - 1] == '/')
|
||||
{
|
||||
out_path[--j] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (lineLen > 0) {
|
||||
if (lineLen > 15 && memcmp(lineStart, "GLOBAL_INCLUDE ", 15) == 0) {
|
||||
int nLen = lineLen - 15;
|
||||
if (nLen >= 1024) nLen = 1023;
|
||||
memcpy(globalInclude, lineStart + 15, nLen);
|
||||
globalInclude[nLen] = '\0';
|
||||
static void parse_semicolon_tokens(const char* input, char tokens[32][256], int* count)
|
||||
{
|
||||
assert(tokens != NULL);
|
||||
assert(count != NULL);
|
||||
|
||||
*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) {
|
||||
int nLen = lineLen - 11;
|
||||
if (nLen >= 1024) nLen = 1023;
|
||||
memcpy(globalDefCommon, lineStart + 11, nLen);
|
||||
globalDefCommon[nLen] = '\0';
|
||||
strncpy_s(cwd, sizeof(cwd), p, _TRUNCATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
memcpy(globalDefDebug, lineStart + 10, nLen);
|
||||
globalDefDebug[nLen] = '\0';
|
||||
}
|
||||
|
||||
FilePathList* src_files = CreateFilePathList();
|
||||
if (p->SrcCount > 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;
|
||||
if (nLen >= 1024) nLen = 1023;
|
||||
memcpy(globalDefProfile, lineStart + 12, nLen);
|
||||
globalDefProfile[nLen] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
CollectFiles(p->Dir, NULL, ".cpp", src_files);
|
||||
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) {
|
||||
int nLen = lineLen - 12;
|
||||
if (nLen >= 1024) nLen = 1023;
|
||||
memcpy(globalDefRelease, lineStart + 12, nLen);
|
||||
globalDefRelease[nLen] = '\0';
|
||||
else
|
||||
{
|
||||
snprintf(full_path, sizeof(full_path), "%s/%s", cwd, clean_rel);
|
||||
}
|
||||
else if (lineLen > 8 && memcmp(lineStart, "PROJECT ", 8) == 0) {
|
||||
if (projCount < 16) {
|
||||
VSProject* p = &projects[projCount++];
|
||||
|
||||
if (!is_first_entry)
|
||||
{
|
||||
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));
|
||||
char lineBuf[1024];
|
||||
int nLen = lineLen - 8;
|
||||
if (nLen >= 1024) nLen = 1023;
|
||||
memcpy(lineBuf, lineStart + 8, nLen);
|
||||
lineBuf[nLen] = '\0';
|
||||
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) {
|
||||
char line_buf[1024];
|
||||
int n_len = line_len - 8;
|
||||
if (n_len >= 1024)
|
||||
{
|
||||
n_len = 1023;
|
||||
}
|
||||
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);
|
||||
}
|
||||
if (scanned < 3) {
|
||||
if (scanned < 3)
|
||||
{
|
||||
GenerateDeterministicGuid(p->Name, p->Guid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (lineLen > 12 && memcmp(lineStart, "PROJECT_SRC ", 12) == 0 && projCount > 0) {
|
||||
VSProject* p = &projects[projCount - 1];
|
||||
if (p->SrcCount < 64) {
|
||||
int nLen = lineLen - 12;
|
||||
if (nLen >= 256) nLen = 255;
|
||||
memcpy(p->Srcs[p->SrcCount], lineStart + 12, nLen);
|
||||
p->Srcs[p->SrcCount][nLen] = '\0';
|
||||
else if (line_len > 12 && memcmp(line_start, "PROJECT_SRC ", 12) == 0 && *proj_count > 0)
|
||||
{
|
||||
VSProject* p = &projects[*proj_count - 1];
|
||||
if (p->SrcCount < 64)
|
||||
{
|
||||
int n_len = line_len - 12;
|
||||
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++;
|
||||
}
|
||||
}
|
||||
else if (lineLen > 10 && memcmp(lineStart, "EXTRA_DEF ", 10) == 0 && projCount > 0) {
|
||||
VSProject* p = &projects[projCount - 1];
|
||||
int nLen = lineLen - 10;
|
||||
if (nLen >= 1024) nLen = 1023;
|
||||
memcpy(p->ExtraDef, lineStart + 10, nLen);
|
||||
p->ExtraDef[nLen] = '\0';
|
||||
else if (line_len > 10 && memcmp(line_start, "EXTRA_DEF ", 10) == 0 && *proj_count > 0)
|
||||
{
|
||||
VSProject* p = &projects[*proj_count - 1];
|
||||
int n_len = line_len - 10;
|
||||
if (n_len >= 1024)
|
||||
{
|
||||
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) {
|
||||
VSProject* p = &projects[projCount - 1];
|
||||
int nLen = lineLen - 15;
|
||||
if (nLen >= 1024) nLen = 1023;
|
||||
memcpy(p->IncludeSearch, lineStart + 15, nLen);
|
||||
p->IncludeSearch[nLen] = '\0';
|
||||
else if (line_len > 15 && memcmp(line_start, "INCLUDE_SEARCH ", 15) == 0 && *proj_count > 0)
|
||||
{
|
||||
VSProject* p = &projects[*proj_count - 1];
|
||||
int n_len = line_len - 15;
|
||||
if (n_len >= 1024)
|
||||
{
|
||||
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) {
|
||||
VSProject* p = &projects[projCount - 1];
|
||||
int nLen = lineLen - 10;
|
||||
if (nLen >= 1024) nLen = 1023;
|
||||
memcpy(p->DebugCmd, lineStart + 10, nLen);
|
||||
p->DebugCmd[nLen] = '\0';
|
||||
else if (line_len > 10 && memcmp(line_start, "DEBUG_CMD ", 10) == 0 && *proj_count > 0)
|
||||
{
|
||||
VSProject* p = &projects[*proj_count - 1];
|
||||
int n_len = line_len - 10;
|
||||
if (n_len >= 1024)
|
||||
{
|
||||
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) {
|
||||
VSProject* p = &projects[projCount - 1];
|
||||
char lineBuf[1024];
|
||||
int nLen = lineLen - 4;
|
||||
if (nLen >= 1024) nLen = 1023;
|
||||
memcpy(lineBuf, lineStart + 4, nLen);
|
||||
lineBuf[nLen] = '\0';
|
||||
sscanf_s(lineBuf, "%s %s", p->PchHeader, (unsigned)_countof(p->PchHeader), p->PchSrc, (unsigned)_countof(p->PchSrc));
|
||||
else if (line_len > 4 && memcmp(line_start, "PCH ", 4) == 0 && *proj_count > 0)
|
||||
{
|
||||
VSProject* p = &projects[*proj_count - 1];
|
||||
char line_buf[1024];
|
||||
int n_len = line_len - 4;
|
||||
if (n_len >= 1024)
|
||||
{
|
||||
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) {
|
||||
if (slnCount < 8) {
|
||||
VSSolution* s = &solutions[slnCount++];
|
||||
else if (line_len > 9 && memcmp(line_start, "SOLUTION ", 9) == 0 && solutions != NULL && sln_count != NULL)
|
||||
{
|
||||
if (*sln_count < 8)
|
||||
{
|
||||
VSSolution* s = &solutions[(*sln_count)++];
|
||||
memset(s, 0, sizeof(VSSolution));
|
||||
int nLen = lineLen - 9;
|
||||
if (nLen >= 64) nLen = 63;
|
||||
memcpy(s->Name, lineStart + 9, nLen);
|
||||
s->Name[nLen] = '\0';
|
||||
int n_len = line_len - 9;
|
||||
if (n_len >= 64)
|
||||
{
|
||||
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) {
|
||||
VSSolution* s = &solutions[slnCount - 1];
|
||||
if (s->ProjCount < 16) {
|
||||
int nLen = lineLen - 9;
|
||||
if (nLen >= 64) nLen = 63;
|
||||
memcpy(s->Projects[s->ProjCount], lineStart + 9, nLen);
|
||||
s->Projects[s->ProjCount][nLen] = '\0';
|
||||
else if (line_len > 9 && memcmp(line_start, "SLN_PROJ ", 9) == 0 && sln_count != NULL && *sln_count > 0 && solutions != NULL)
|
||||
{
|
||||
VSSolution* s = &solutions[*sln_count - 1];
|
||||
if (s->ProjCount < 16)
|
||||
{
|
||||
int n_len = line_len - 9;
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
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];
|
||||
const char* incs = p->IncludeSearch[0] != '\0' ? p->IncludeSearch : globalInclude;
|
||||
GenerateProject(p->Name, p->Dir, p->Guid, incs, p->ExtraDef, p->DebugCmd, p->Srcs, p->SrcCount, globalDefCommon, globalDefDebug, globalDefProfile, globalDefRelease, p->PchHeader, p->PchSrc);
|
||||
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, 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];
|
||||
const char* pNames[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];
|
||||
for (int k = 0; k < projCount; k++) {
|
||||
if (strcmp(projects[k].Name, s->Projects[j]) == 0) {
|
||||
for (int k = 0; k < proj_count; k++)
|
||||
{
|
||||
if (strcmp(projects[k].Name, s->Projects[j]) == 0)
|
||||
{
|
||||
pGuids[j] = projects[k].Guid;
|
||||
break;
|
||||
}
|
||||
@@ -1716,6 +2161,7 @@ static int CommandGenVS(int argc, char* argv[])
|
||||
GenerateSolution(s->Name, pNames, pGuids, s->ProjCount);
|
||||
}
|
||||
|
||||
generate_compile_commands(projects, proj_count, global_include, global_def_common, global_def_debug);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1728,9 +2174,10 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
printf("Usage: build_system <command> [args...]\n");
|
||||
printf("Commands:\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(" check_alive Returns 0 immediately to test execution\n");
|
||||
printf(" run_plan <plan_file> Run the build from a generated plan file\n");
|
||||
printf(" gen_vs <plan_file> Generate Visual Studio project, solution, and compile_commands files\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;
|
||||
}
|
||||
|
||||
@@ -1738,6 +2185,7 @@ int main(int argc, char* argv[])
|
||||
if (strcmp(cmd, "check_alive") == 0) return 0;
|
||||
if (strcmp(cmd, "run_plan") == 0) return CommandRunPlan(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);
|
||||
return 1;
|
||||
|
||||
Reference in new issue
Block a user