From 22185bfe223fdd6a446d83793471816f007b30d8 Mon Sep 17 00:00:00 2001 From: nakst <> Date: Tue, 21 Sep 2021 21:58:33 +0100 Subject: [PATCH] cleanup gl test --- apps/gl_test.ini | 8 - apps/gl_test.c => ports/mesa/obj_viewer.c | 254 ++++++++++------------ ports/mesa/obj_viewer.ini | 18 ++ util/build.c | 4 +- util/build_common.h | 1 + util/build_core.c | 71 +++--- 6 files changed, 182 insertions(+), 174 deletions(-) delete mode 100644 apps/gl_test.ini rename apps/gl_test.c => ports/mesa/obj_viewer.c (92%) create mode 100644 ports/mesa/obj_viewer.ini diff --git a/apps/gl_test.ini b/apps/gl_test.ini deleted file mode 100644 index 6326d9a..0000000 --- a/apps/gl_test.ini +++ /dev/null @@ -1,8 +0,0 @@ -[general] -name=GL Test -permission_posix_subsystem=1 -permission_all_files=1 - -[build] -custom_compile_command=x86_64-essence-gcc -o "bin/GL Test" apps/gl_test.c -lOSMesa -lstdc++ -lz -g -D ESSENCE_WINDOW -Wall -Wextra -require=root/Applications/POSIX/lib/libOSMesa.a diff --git a/apps/gl_test.c b/ports/mesa/obj_viewer.c similarity index 92% rename from apps/gl_test.c rename to ports/mesa/obj_viewer.c index 7a88d41..9bcf6e9 100644 --- a/apps/gl_test.c +++ b/ports/mesa/obj_viewer.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -11,7 +12,6 @@ #include #define MODERN_GL -#define LIVE_UPDATE #define CHECK_ERRORS() do { GLenum error; while ((error = glGetError()) != GL_NO_ERROR) { EsPrint("Error on line %d: %d\n", __LINE__, error); } } while (0) @@ -19,6 +19,9 @@ #define IMAGE_HEIGHT (600) uint32_t *buffer; +uint32_t modelVBO, modelIBO; +bool loadedModel; + #ifdef MODERN_GL static GLenum (*glCheckFramebufferStatus)(GLenum target); static GLint (*glGetUniformLocation)(GLuint program, const GLchar *name); @@ -115,6 +118,10 @@ void PrepareNormalTransform(float *_modelTransform, float *_normalTransform) { } void Render() { + if (!loadedModel) { + return; + } + glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #ifdef MODERN_GL @@ -146,14 +153,11 @@ void Render() { glFinish(); } -#ifdef ESSENCE_WINDOW #include int CanvasCallback(EsElement *element, EsMessage *message) { if (message->type == ES_MSG_PAINT_BACKGROUND) { -#ifdef LIVE_UPDATE Render(); -#endif EsRectangle bounds = EsPainterBoundsInset(message->painter); EsRectangle imageBounds = EsRectangleCenter(bounds, ES_RECT_2S(IMAGE_WIDTH, IMAGE_HEIGHT)); EsDrawBitmap(message->painter, imageBounds, buffer, IMAGE_WIDTH * 4, ES_DRAW_BITMAP_OPAQUE); @@ -182,7 +186,105 @@ int CanvasCallback(EsElement *element, EsMessage *message) { return 0; } -#endif + +bool LoadModel(char *model, size_t modelBytes) { + triangleCount = 0, vertexCount = 0; + + for (uintptr_t i = 0; i < modelBytes; i++) { + if (!i || model[i - 1] == '\n') { + if (model[i] == 'f' && model[i + 1] == ' ') { + triangleCount++; + } else if (model[i] == 'v' && model[i + 1] == ' ') { + vertexCount++; + } + } + } + + float *modelVBOArray = (float *) EsHeapAllocate(6 * sizeof(float) * vertexCount, true, NULL); + uint32_t *modelIBOArray = (uint32_t *) EsHeapAllocate(3 * sizeof(uint32_t) * triangleCount, true, NULL); + uintptr_t triangleIndex = 0, vertexIndex = 0; + + float minimumX = ES_INFINITY, maximumX = -ES_INFINITY; + float minimumY = ES_INFINITY, maximumY = -ES_INFINITY; + float minimumZ = ES_INFINITY, maximumZ = -ES_INFINITY; + + for (uintptr_t i = 0; i < modelBytes; i++) { + if (!i || model[i - 1] == '\n') { + if (model[i] == 'v' && model[i + 1] == ' ') { + char *position = model + i + 2; + modelVBOArray[6 * vertexIndex + 0] = strtod(position, &position); + modelVBOArray[6 * vertexIndex + 1] = strtod(position, &position); + modelVBOArray[6 * vertexIndex + 2] = strtod(position, &position); + minimumX = modelVBOArray[6 * vertexIndex + 0] < minimumX ? modelVBOArray[6 * vertexIndex + 0] : minimumX; + minimumY = modelVBOArray[6 * vertexIndex + 1] < minimumY ? modelVBOArray[6 * vertexIndex + 1] : minimumY; + minimumZ = modelVBOArray[6 * vertexIndex + 2] < minimumZ ? modelVBOArray[6 * vertexIndex + 2] : minimumZ; + maximumX = modelVBOArray[6 * vertexIndex + 0] > maximumX ? modelVBOArray[6 * vertexIndex + 0] : maximumX; + maximumY = modelVBOArray[6 * vertexIndex + 1] > maximumY ? modelVBOArray[6 * vertexIndex + 1] : maximumY; + maximumZ = modelVBOArray[6 * vertexIndex + 2] > maximumZ ? modelVBOArray[6 * vertexIndex + 2] : maximumZ; + vertexIndex++; + } else if (model[i] == 'f' && model[i + 1] == ' ') { + char *position = model + i + 2; + uint32_t i0 = strtoul(position, &position, 10) - 1; + uint32_t i1 = strtoul(position, &position, 10) - 1; + uint32_t i2 = strtoul(position, &position, 10) - 1; + if (i0 >= vertexCount) return false; + if (i1 >= vertexCount) return false; + if (i2 >= vertexCount) return false; + modelIBOArray[3 * triangleIndex + 0] = i0; + modelIBOArray[3 * triangleIndex + 1] = i1; + modelIBOArray[3 * triangleIndex + 2] = i2; + triangleIndex++; + } + } + } + + EsPrint("Model bounds: %F -> %F, %F -> %F, %F -> %F\n", minimumX, maximumX, minimumY, maximumY, minimumZ, maximumZ); + EsAssert(vertexIndex == vertexCount); + EsAssert(triangleIndex == triangleCount); + + for (uintptr_t i = 0; i < triangleCount; i++) { + // Calculate the normals as a weighted average of the face normals, + // where the weight is the surface area of the face. + + float d1x = modelVBOArray[6 * modelIBOArray[3 * i + 1] + 0] - modelVBOArray[6 * modelIBOArray[3 * i + 0] + 0]; + float d1y = modelVBOArray[6 * modelIBOArray[3 * i + 1] + 1] - modelVBOArray[6 * modelIBOArray[3 * i + 0] + 1]; + float d1z = modelVBOArray[6 * modelIBOArray[3 * i + 1] + 2] - modelVBOArray[6 * modelIBOArray[3 * i + 0] + 2]; + float d2x = modelVBOArray[6 * modelIBOArray[3 * i + 2] + 0] - modelVBOArray[6 * modelIBOArray[3 * i + 0] + 0]; + float d2y = modelVBOArray[6 * modelIBOArray[3 * i + 2] + 1] - modelVBOArray[6 * modelIBOArray[3 * i + 0] + 1]; + float d2z = modelVBOArray[6 * modelIBOArray[3 * i + 2] + 2] - modelVBOArray[6 * modelIBOArray[3 * i + 0] + 2]; + float nx = d1y * d2z - d1z * d2y; + float ny = d1z * d2x - d1x * d2z; + float nz = d1x * d2y - d1y * d2x; + + for (uintptr_t j = 0; j < 3; j++) { + modelVBOArray[6 * modelIBOArray[3 * i + j] + 3] += nx; + modelVBOArray[6 * modelIBOArray[3 * i + j] + 4] += ny; + modelVBOArray[6 * modelIBOArray[3 * i + j] + 5] += nz; + } + } + + for (uintptr_t i = 0; i < vertexCount; i++) { + // Normalize the normals. + + float x = modelVBOArray[6 * i + 3]; + float y = modelVBOArray[6 * i + 4]; + float z = modelVBOArray[6 * i + 5]; + float d = sqrtf(x * x + y * y + z * z); + modelVBOArray[6 * i + 3] /= d; + modelVBOArray[6 * i + 4] /= d; + modelVBOArray[6 * i + 5] /= d; + } + + glBindBuffer(GL_ARRAY_BUFFER, modelVBO); + glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float) * vertexCount, modelVBOArray, GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelIBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * sizeof(uint32_t) * triangleCount, modelIBOArray, GL_STATIC_DRAW); + + EsHeapFree(modelVBOArray, 0, NULL); + EsHeapFree(modelIBOArray, 0, NULL); + + return true; +} int main(int argc, char **argv) { (void) argc; @@ -244,116 +346,8 @@ int main(int argc, char **argv) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_MULTISAMPLE); -#if 0 - triangleCount = 2, vertexCount = 4; - uint32_t modelIBOArray[] = { 0, 1, 2, 0, 2, 3 }; - - float modelVBOArray[] = { - -1, -1, 0.5f, 0, 0, 0, - -1, 1, 0.5f, 0, 0, 0, - 1, 1, 0.5f, 0, 0, 0, - 1, -1, 0.5f, 0, 0, 0, - }; -#else - // TODO Loading files properly. - size_t modelBytes; - char *model = (char *) EsFileReadAll(EsLiteral("0:/teapot.obj"), &modelBytes, NULL); - - triangleCount = 0, vertexCount = 0; - - for (uintptr_t i = 0; i < modelBytes; i++) { - if (!i || model[i - 1] == '\n') { - if (model[i] == 'f' && model[i + 1] == ' ') { - triangleCount++; - } else if (model[i] == 'v' && model[i + 1] == ' ') { - vertexCount++; - } - } - } - - float *modelVBOArray = (float *) EsHeapAllocate(6 * sizeof(float) * vertexCount, true, NULL); - uint32_t *modelIBOArray = (uint32_t *) EsHeapAllocate(3 * sizeof(uint32_t) * triangleCount, true, NULL); - uintptr_t triangleIndex = 0, vertexIndex = 0; - - float minimumX = ES_INFINITY, maximumX = -ES_INFINITY; - float minimumY = ES_INFINITY, maximumY = -ES_INFINITY; - float minimumZ = ES_INFINITY, maximumZ = -ES_INFINITY; - - for (uintptr_t i = 0; i < modelBytes; i++) { - if (!i || model[i - 1] == '\n') { - if (model[i] == 'v' && model[i + 1] == ' ') { - char *position = model + i + 2; - modelVBOArray[6 * vertexIndex + 0] = strtod(position, &position); - modelVBOArray[6 * vertexIndex + 1] = strtod(position, &position); - modelVBOArray[6 * vertexIndex + 2] = strtod(position, &position); - minimumX = modelVBOArray[6 * vertexIndex + 0] < minimumX ? modelVBOArray[6 * vertexIndex + 0] : minimumX; - minimumY = modelVBOArray[6 * vertexIndex + 1] < minimumY ? modelVBOArray[6 * vertexIndex + 1] : minimumY; - minimumZ = modelVBOArray[6 * vertexIndex + 2] < minimumZ ? modelVBOArray[6 * vertexIndex + 2] : minimumZ; - maximumX = modelVBOArray[6 * vertexIndex + 0] > maximumX ? modelVBOArray[6 * vertexIndex + 0] : maximumX; - maximumY = modelVBOArray[6 * vertexIndex + 1] > maximumY ? modelVBOArray[6 * vertexIndex + 1] : maximumY; - maximumZ = modelVBOArray[6 * vertexIndex + 2] > maximumZ ? modelVBOArray[6 * vertexIndex + 2] : maximumZ; - vertexIndex++; - } else if (model[i] == 'f' && model[i + 1] == ' ') { - char *position = model + i + 2; - uint32_t i0 = strtoul(position, &position, 10) - 1; - uint32_t i1 = strtoul(position, &position, 10) - 1; - uint32_t i2 = strtoul(position, &position, 10) - 1; - EsAssert(i0 < vertexCount); // TODO Error reporting. - EsAssert(i1 < vertexCount); - EsAssert(i2 < vertexCount); - modelIBOArray[3 * triangleIndex + 0] = i0; - modelIBOArray[3 * triangleIndex + 1] = i1; - modelIBOArray[3 * triangleIndex + 2] = i2; - triangleIndex++; - } - } - } - - EsPrint("Model bounds: %F -> %F, %F -> %F, %F -> %F\n", minimumX, maximumX, minimumY, maximumY, minimumZ, maximumZ); - EsAssert(vertexIndex == vertexCount); - EsAssert(triangleIndex == triangleCount); -#endif - - for (uintptr_t i = 0; i < triangleCount; i++) { - // Calculate the normals as a weighted average of the face normals, - // where the weight is the surface area of the face. - - float d1x = modelVBOArray[6 * modelIBOArray[3 * i + 1] + 0] - modelVBOArray[6 * modelIBOArray[3 * i + 0] + 0]; - float d1y = modelVBOArray[6 * modelIBOArray[3 * i + 1] + 1] - modelVBOArray[6 * modelIBOArray[3 * i + 0] + 1]; - float d1z = modelVBOArray[6 * modelIBOArray[3 * i + 1] + 2] - modelVBOArray[6 * modelIBOArray[3 * i + 0] + 2]; - float d2x = modelVBOArray[6 * modelIBOArray[3 * i + 2] + 0] - modelVBOArray[6 * modelIBOArray[3 * i + 0] + 0]; - float d2y = modelVBOArray[6 * modelIBOArray[3 * i + 2] + 1] - modelVBOArray[6 * modelIBOArray[3 * i + 0] + 1]; - float d2z = modelVBOArray[6 * modelIBOArray[3 * i + 2] + 2] - modelVBOArray[6 * modelIBOArray[3 * i + 0] + 2]; - float nx = d1y * d2z - d1z * d2y; - float ny = d1z * d2x - d1x * d2z; - float nz = d1x * d2y - d1y * d2x; - - for (uintptr_t j = 0; j < 3; j++) { - modelVBOArray[6 * modelIBOArray[3 * i + j] + 3] += nx; - modelVBOArray[6 * modelIBOArray[3 * i + j] + 4] += ny; - modelVBOArray[6 * modelIBOArray[3 * i + j] + 5] += nz; - } - } - - for (uintptr_t i = 0; i < vertexCount; i++) { - // Normalize the normals. - - float x = modelVBOArray[6 * i + 3]; - float y = modelVBOArray[6 * i + 4]; - float z = modelVBOArray[6 * i + 5]; - float d = sqrtf(x * x + y * y + z * z); - modelVBOArray[6 * i + 3] /= d; - modelVBOArray[6 * i + 4] /= d; - modelVBOArray[6 * i + 5] /= d; - } - - uint32_t modelVBO, modelIBO; glGenBuffers(1, &modelVBO); - glBindBuffer(GL_ARRAY_BUFFER, modelVBO); - glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float) * vertexCount, modelVBOArray, GL_STATIC_DRAW); glGenBuffers(1, &modelIBO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelIBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * sizeof(uint32_t) * triangleCount, modelIBOArray, GL_STATIC_DRAW); const char *vertexShaderSource = "#version 330\n" @@ -390,14 +384,14 @@ int main(int argc, char **argv) { glCompileShader(vertexShader); glGetShaderInfoLog(vertexShader, sizeof(shaderInfoLog), NULL, shaderInfoLog); glAttachShader(shader, vertexShader); - printf("Vertex shader log: '%s'\n", shaderInfoLog); + EsPrint("Vertex shader log: '%z'\n", shaderInfoLog); unsigned fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, shaderSources + 1, shaderSourceLengths + 1); glCompileShader(fragmentShader); glGetShaderInfoLog(fragmentShader, sizeof(shaderInfoLog), NULL, shaderInfoLog); glAttachShader(shader, fragmentShader); - printf("Fragment shader log: '%s'\n", shaderInfoLog); + EsPrint("Fragment shader log: '%z'\n", shaderInfoLog); glLinkProgram(shader); glValidateProgram(shader); @@ -423,39 +417,25 @@ int main(int argc, char **argv) { glDepthFunc(GL_LESS); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); - #endif -#ifndef ESSENCE_WINDOW - FILE *out = fopen("test.ppm", "wb"); - fprintf(out, "P6\n%d %d\n255\n", IMAGE_WIDTH, IMAGE_HEIGHT); - - for (int j = 0; j < IMAGE_HEIGHT; j++) { - for (int i = 0; i < IMAGE_WIDTH; i++) { - fwrite(buffer + j * IMAGE_WIDTH + i, 1, 3, out); - } - } - - fclose(out); - OSMesaDestroyContext(context); - free(buffer); -#else while (true) { EsMessage *message = EsMessageReceive(); if (message->type == ES_MSG_INSTANCE_CREATE) { - EsInstance *instance = EsInstanceCreate(message, "GL Test", -1); - EsWindowSetTitle(instance->window, "GL Test", -1); + EsInstance *instance = EsInstanceCreate(message, "Object Viewer", -1); + EsWindowSetIcon(instance->window, ES_ICON_MODEL); EsElement *canvas = EsCustomElementCreate(instance->window, ES_CELL_FILL, 0); canvas->messageUser = (EsUICallback) CanvasCallback; -#ifdef LIVE_UPDATE EsElementStartAnimating(canvas); -#else - Render(); -#endif + } else if (message->type == ES_MSG_INSTANCE_OPEN) { + size_t modelBytes; + void *model = EsFileStoreReadAll(message->instanceOpen.file, &modelBytes); + EsInstanceOpenComplete(message, LoadModel(model, modelBytes), NULL, 0); + EsHeapFree(model, 0, NULL); + loadedModel = true; } } -#endif return 0; } diff --git a/ports/mesa/obj_viewer.ini b/ports/mesa/obj_viewer.ini new file mode 100644 index 0000000..419019f --- /dev/null +++ b/ports/mesa/obj_viewer.ini @@ -0,0 +1,18 @@ +[general] +name=Object Viewer +permission_posix_subsystem=1 +icon=icon_model + +[build] +link_flags=-lOSMesa -lstdc++ -lz +with_cstdlib=1 +source=ports/mesa/obj_viewer.c + +[@handler] +extension=obj +action=open + +[@file_type] +extension=obj +name=3D model +icon=icon_model diff --git a/util/build.c b/util/build.c index 2f5b526..ddf071b 100644 --- a/util/build.c +++ b/util/build.c @@ -162,10 +162,10 @@ void OutputStartOfBuildINI(FILE *f, bool forceDebugBuildOff) { "convert_svg=bin/render_svg\n" "linker_scripts=util/\n" "crt_objects=bin/\n" - "\n[general]\nsystem_build=1\nminimal_rebuild=1\ncolored_output=%d\nthread_count=%d\nskip_header_generation=1\ncommon_compile_flags=", + "\n[general]\nsystem_build=1\nminimal_rebuild=1\ncolored_output=%d\nthread_count=%d\nskip_header_generation=1\nverbose=%d\ncommon_compile_flags=", compilerPath, getenv("TMPDIR") ?: "", compilerPath, compilerPath, compilerPath, compilerPath, compilerPath, compilerPath, - buffer, coloredOutput, (int) sysconf(_SC_NPROCESSORS_CONF)); + buffer, coloredOutput, (int) sysconf(_SC_NPROCESSORS_CONF), IsOptionEnabled("BuildCore.Verbose")); for (uintptr_t i = 0; i < sizeof(options) / sizeof(options[0]); i++) { Option *option = &options[i]; diff --git a/util/build_common.h b/util/build_common.h index 30fb6e8..026226c 100644 --- a/util/build_common.h +++ b/util/build_common.h @@ -306,6 +306,7 @@ Option options[] = { { "Emulator.SecondaryDriveMB", OPTION_TYPE_STRING, { .s = NULL } }, { "Emulator.VBoxEFI", OPTION_TYPE_BOOL, { .b = false } }, { "Emulator.QemuEFI", OPTION_TYPE_BOOL, { .b = false } }, + { "BuildCore.Verbose", OPTION_TYPE_BOOL, { .b = false } }, { "General.first_application", OPTION_TYPE_STRING, { .s = NULL } }, { "General.wallpaper", OPTION_TYPE_STRING, { .s = NULL } }, { "General.installation_state", OPTION_TYPE_STRING, { .s = "0" } }, diff --git a/util/build_core.c b/util/build_core.c index a2b9ec9..ec420d4 100644 --- a/util/build_core.c +++ b/util/build_core.c @@ -139,8 +139,9 @@ File FileOpen(const char *path, char mode) { // Toolchain flags: -char commonCompileFlags[4096] = " -Wall -Wextra -Wno-missing-field-initializers -Wno-frame-address " - "-Wno-unused-function -Wno-format-truncation -ffreestanding -fno-exceptions -g -I. "; +const char *commonCompileFlagsFreestanding = " -ffreestanding -fno-exceptions "; +char commonCompileFlags[4096] = " -Wall -Wextra -Wno-missing-field-initializers -Wno-frame-address -Wno-unused-function -Wno-format-truncation -g -I. "; +char commonCompileFlagsWithCStdLib[4096]; char cCompileFlags[4096] = ""; char cppCompileFlags[4096] = " -std=c++14 -Wno-pmf-conversions -Wno-invalid-offsetof -fno-rtti "; char kernelCompileFlags[4096] = " -mno-red-zone -mcmodel=kernel -fno-omit-frame-pointer "; @@ -523,7 +524,7 @@ typedef struct Application { FileType *fileTypes; Handler *handlers; - bool install, builtin; + bool install, builtin, withCStdLib; const char **sources; const char *compileFlags; @@ -619,21 +620,26 @@ void BuildApplication(Application *application) { snprintf(objectFile, sizeof(objectFile), "bin/%s_%d.o", application->name, (int) i); objectFilesPosition += sprintf(objectFiles + objectFilesPosition, "\"%s\" ", objectFile); - if (sourceBytes > 2 && source[sourceBytes - 1] == 'c' && source[sourceBytes - 2] == '.') { - ExecuteForApp(application, toolchainCC, "-MD", "-o", objectFile, "-c", source, - ArgString(cCompileFlags), ArgString(commonCompileFlags), ArgString(application->compileFlags)); - } else { - ExecuteForApp(application, toolchainCXX, "-MD", "-o", objectFile, "-c", source, - ArgString(cppCompileFlags), ArgString(commonCompileFlags), ArgString(application->compileFlags)); - } + bool isC = sourceBytes > 2 && source[sourceBytes - 1] == 'c' && source[sourceBytes - 2] == '.'; + const char *cstdlibFlags = application->withCStdLib ? commonCompileFlagsWithCStdLib : commonCompileFlags; + const char *languageFlags = isC ? cCompileFlags : cppCompileFlags; + const char *compiler = isC ? toolchainCC : toolchainCXX; + + ExecuteForApp(application, compiler, "-MD", "-o", objectFile, "-c", source, + ArgString(languageFlags), ArgString(application->compileFlags), ArgString(cstdlibFlags)); } assert(objectFilesPosition < sizeof(objectFiles)); objectFiles[objectFilesPosition] = 0; - ExecuteForApp(application, toolchainCC, "-o", symbolFile, - "-Wl,--start-group", ArgString(application->linkFlags), crti, crtbegin, ArgString(objectFiles), crtend, crtn, "-Wl,--end-group", - ArgString(applicationLinkFlags), "-T", linkerScript); + if (application->withCStdLib) { + ExecuteForApp(application, toolchainCC, "-o", symbolFile, ArgString(objectFiles), ArgString(application->linkFlags)); + } else { + ExecuteForApp(application, toolchainCC, "-o", symbolFile, + "-Wl,--start-group", ArgString(application->linkFlags), crti, crtbegin, ArgString(objectFiles), crtend, crtn, "-Wl,--end-group", + ArgString(applicationLinkFlags), "-T", linkerScript); + } + ExecuteForApp(application, toolchainStrip, "-o", strippedFile, "--strip-all", symbolFile); ADD_BUNDLE_INPUT(strippedFile, "$Executables/x86_64", 0x1000); @@ -708,6 +714,7 @@ void ParseApplicationManifest(const char *manifestPath) { INI_READ_STRING_PTR(compile_flags, application.compileFlags); INI_READ_STRING_PTR(link_flags, application.linkFlags); INI_READ_STRING_PTR(custom_compile_command, application.customCompileCommand); + INI_READ_BOOL(with_cstdlib, application.withCStdLib); INI_READ_STRING_PTR(require, require); } else if (0 == strcmp(s.section, "general")) { INI_READ_STRING_PTR(name, application.name); @@ -1398,6 +1405,9 @@ int main(int argc, char **argv) { return 1; } + strcpy(commonCompileFlagsWithCStdLib, commonCompileFlags); + strcat(commonCompileFlags, commonCompileFlagsFreestanding); + buildStartTimeStamp = time(NULL); sh_new_strdup(applicationDependencies); @@ -1508,27 +1518,34 @@ int main(int argc, char **argv) { // Build all these applications. + bool skip = false; + #ifdef PARALLEL_BUILD - if (useColoredOutput) StartSpinner(); - pthread_t *threads = (pthread_t *) malloc(sizeof(pthread_t) * threadCount); + if (!verbose) { + if (useColoredOutput) StartSpinner(); + pthread_t *threads = (pthread_t *) malloc(sizeof(pthread_t) * threadCount); - for (uintptr_t i = 0; i < threadCount; i++) { - pthread_create(threads + i, NULL, BuildApplicationThread, NULL); - } + for (uintptr_t i = 0; i < threadCount; i++) { + pthread_create(threads + i, NULL, BuildApplicationThread, NULL); + } - for (uintptr_t i = 0; i < threadCount; i++) { - pthread_join(threads[i], NULL); - } + for (uintptr_t i = 0; i < threadCount; i++) { + pthread_join(threads[i], NULL); + } - if (useColoredOutput) StopSpinner(); -#else - for (uintptr_t i = 0; i < arrlenu(applications); i++) { - Log("[%d/%d] Compiling %s...\n", i + 1, arrlenu(applications), applications[i].name); - if (applications[i].skipped) continue; - applications[i].buildCallback(&applications[i]); + if (useColoredOutput) StopSpinner(); + skip = true; } #endif + if (!skip) { + for (uintptr_t i = 0; i < arrlenu(applications); i++) { + Log("[%d/%d] Compiling %s...\n", (int) i + 1, (int) arrlenu(applications), applications[i].name); + if (applications[i].skipped) continue; + applications[i].buildCallback(&applications[i]); + } + } + // Output information about the built applications, // and parse the dependency files for successfully built ones.