RobLoach / raylib-nuklear

Nuklear immediate mode GUI for raylib
https://robloach.github.io/raylib-nuklear/
zlib License
141 stars 19 forks source link

65912 kb size increase in the executable on include #67

Closed alexlnkp closed 2 months ago

alexlnkp commented 3 months ago

not sure if this is expected or even intended, but the executable size grows SIGNIFICANTLY whenever i try to use raylib-nuklear. and the 65912kb size increase? that's with -flto! without -flto, the size increase is 348560kb!

i'm not using CMake or Make, i have a small compilation script:

#!/bin/bash

_PROJ_NAME="3dren"
_C_STANDARD=99

_EXT_LIBS="raylib"

_SOURCES="main.c"

# common flags
_C_FLAGS="-Wall -Werror -Wextra -Wpedantic"

# C standard
_C_FLAGS="${_C_FLAGS} -std=c${_C_STANDARD}"

# optim
_C_FLAGS="${_C_FLAGS} -O3 -flto"

# strip
_C_FLAGS="${_C_FLAGS} -s"

# libs
# if _EXT_LIBS is not empty - add it
if [[ -n "${_EXT_LIBS}" ]]; then
    _C_FLAGS="${_C_FLAGS} $(pkgconf --libs ${_EXT_LIBS}) $(pkgconf --cflags ${_EXT_LIBS})"
fi

# compile
gcc -o ${_PROJ_NAME} ${_SOURCES} ${_C_FLAGS}

wc -c ${_PROJ_NAME} # display size of executable in kb

and all of that in a simple 3d render:

#include <raylib.h>

#define RAYLIB_NUKLEAR_IMPLEMENTATION
#include <raylib-nuklear.h>

void handle_keys() {
    if (IsKeyPressed(KEY_M)) {
        if (IsCursorHidden()) EnableCursor();
        else DisableCursor();
    }
}

int main(void) {
    SetConfigFlags(FLAG_WINDOW_UNDECORATED);

    InitWindow(1600, 800, "raylib");

    int fontSize = 10;
    struct nk_context *ctx = InitNuklear(fontSize);

    Camera camera = { 0 };
    camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position
    camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };      // Camera looking at point
    camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };          // Camera up vector (rotation towards target)
    camera.fovy = 45.0f;                                // Camera field-of-view Y
    camera.projection = CAMERA_PERSPECTIVE;

    int cameraMode = CAMERA_FREE;

    Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };

    SetTargetFPS(60);

    DisableCursor();

    while (!WindowShouldClose()) {
        handle_keys();
        UpdateCamera(&camera, cameraMode);
        UpdateNuklear(ctx);

        if (nk_begin(ctx, "Nuklear", nk_rect(100, 100, 220, 220),
                NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) {
            nk_layout_row_static(ctx, 50, 150, 1);
            if (nk_button_label(ctx, "Button")) {
                // Button was clicked!
            }
        }
        nk_end(ctx);

        BeginDrawing();
            ClearBackground((Color){ 245, 245, 245, 255 });

            BeginMode3D(camera);
                DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, (Color){ 230, 41, 55, 255 });
                DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, (Color){ 190, 33, 55, 255 });
                DrawGrid(100, 1.0f);
            EndMode3D();

            DrawNuklear(ctx);
        EndDrawing();
    }

    UnloadNuklear(ctx);
    CloseWindow();
    return 0;
}

the raylib GUI works though, no issues there... just odd how it takes SO much space

RobLoach commented 3 months ago

340MB executable does sound suspect. The only thing I can think of is maybe we should consider NK_ASSERT? https://github.com/RobLoach/raylib-nuklear/blob/master/include/raylib-nuklear.h#L55

#ifndef NK_ASSERT
#define NK_ASSERT(condition) do { if (!(condition)) { TraceLog(LOG_WARNING, "NUKLEAR: Failed assert \"%s\" (%s:%i)", #condition, "nuklear.h", __LINE__); }} while (0)
#endif  // NK_ASSERT

Think that would do anything suspect on execution size? Debug symbols do take up a lot of space.

RobLoach commented 3 months ago

Perhaps see if doing something like this affects it?

#define NK_ASSERT(condition) ((void)0)
alexlnkp commented 3 months ago

Perhaps see if doing something like this affects it?

#define NK_ASSERT(condition) ((void)0)

And this does indeed help, but still the executable's size seems unintentionally too big

Regarding #define NK_ASSERT(condition) ((void)0), you could fix this with a simple:

#ifndef NK_ASSERT
#ifdef NDEBUG
#define NK_ASSERT(condition) ((void)0)
#else
#define NK_ASSERT(condition) do { if (!(condition)) { TraceLog(LOG_WARNING, "NUKLEAR: Failed assert \"%s\" (%s:%i)", #condition, "nuklear.h", __LINE__); }} while (0)
#endif
#endif

Though I'm not sure if NDEBUG flag is as widely used in C as it is in C++?

RobLoach commented 3 months ago

Love the NDEBUG idea, whether or not it's C++/C... Made a PR https://github.com/RobLoach/raylib-nuklear/pull/71

alexlnkp commented 3 months ago

I've noticed that nuklear.h is included multiple times, this could also be a part of the issue

nuklear.h itself is REALLY heavy, including it twice seems a bit excessive however i can not help with figuring out how to not do that, the structure of raylib-nuklear.h is too complex for me (never had to work on a single-header type of projects, sorry)

RobLoach commented 3 months ago

The applications end up around 1.9MB for me when compiling now. With or without NDEBUG. I'm not that fluent in raylib's base Makefile. Is there anything else missing that we could add to your set up? Thnaks!

mhcerri commented 2 months ago

@alexlnkp, add more information about how you're building or installing and also include the final GCC command that your build script is running.

alexlnkp commented 2 months ago

@alexlnkp, add more information about how you're building or installing and also include the final GCC command that your build script is running.

I simply installed the raylib package from AUR. The final command that is ran to build is gcc -s -Wall -Wextra -Wpedantic -std=c99 -DNDEBUG -O3 -flto=auto -s -lraylib -lm -o 3dren main.c The output size is 84608 (kb)

mhcerri commented 2 months ago

Try something like gcc -Wall -Wextra -Wpedantic -std=c99 -DNDEBUG -O3 -c main.c to compile your program but not link it. Thay will produce main.o, please check its size. If main.o is small, then it's unlikely that's caused by raylib-nuklear.

Just a side note, including nuklear.h several times is fine. It has guards to prevent duplicating itself.

alexlnkp commented 2 months ago

Try something like gcc -Wall -Wextra -Wpedantic -std=c99 -DNDEBUG -O3 -c main.c to compile your program but not link it. Thay will produce main.o, please check its size. If main.o is small, then it's unlikely that's caused by raylib-nuklear.

Just a side note, including nuklear.h several times is fine. It has guards to prevent duplicating itself.

Well, it didn't seem to work to be honest.

$ gcc -Wall -Wextra -Wpedantic -std=c99 -DNDEBUG -O3 -c main.c

$ wc -c main.o 
406696 main.o
mhcerri commented 2 months ago

So it seems the program itself, including nuklear and raylib-nuklear, is not that big. It's just ~400 kb.

Are you sure you are getting an increase of 348560 kb? Or is that 348560 bytes (basically around 350 kb)? wc -c should report bytes, not kb.

If it's 350 kb, I would say that's pretty much expected. Nuklear and raylib-nuklear are basically static libraries and they are fairly complex too.

alexlnkp commented 2 months ago

So it seems the program itself, including nuklear and raylib-nuklear, is not that big. It's just ~400 kb.

Are you sure you are getting an increase of 348560 kb? Or is that 348560 bytes (basically around 350 kb)? wc -c should report bytes, not kb.

If it's 350 kb, I would say that's pretty much expected. Nuklear and raylib-nuklear are basically static libraries and they are fairly complex too.

Oh my god, You are right... All this time it was bytes, not kilobytes.... I'm so sorry for wasting your time here. I'll close this issue.

RobLoach commented 2 months ago

Thanks for testing it out! Glad we figured it out :laughing: