Skip to content

Conversation

@sleeptightAnsiC
Copy link
Contributor

@sleeptightAnsiC sleeptightAnsiC commented Nov 18, 2025

This PR fixes several issues related to build process and symbol resolution through preprocesor. I separated it into 4 logical commits, each one fixing slightly different issues. I could submit them as separate PRs, but this would be very impractical to deal with, since all those changes have some overlap in the code.

For better explanation of each change, please read the corresponding commit message.

Closes: #256
Closes: #851

nk_do_property was using 'nk_strtod' instead of 'NK_STRTOD'
which was not picking the user-provided implementation of NK_STRTOD

Fixes: Immediate-Mode-UI#851
This fixes an issue, where you would not be able to build Nuklear from
sources (without amalgamated header), caused by nuklear_math/util.c
not declaring some function definitions, due to wrong preprocessor logic.
This fix is an "Option 3" mentioned in following comment...
Immediate-Mode-UI#256 (comment)
... where we define additional macro at definition (e.g. FOO_IMPLEMENTATION)
so the preprocessor will be able to correctly detect it in all cases.

Fixes: Immediate-Mode-UI#256
nk_strtod implementation was never guarder by the preprocessor,
so if you ever provided your own NK_STRTOD, the default one would
still be compiled. This fix was INTENTIONALLY split into another commit,
because the lack of the guard was very suspicious to me...

Fixes: Immediate-Mode-UI#851 (comment)
There was a note inside nuklear_sdl3_renderer saying that SDL3 does not
have "dtoa", so I simulated it's behavior with printf. This helps us
test the actual NK_DTOA preprocessor path. This neat trick is not mine.
I discovered it here [link below] and tweaked a bit to make it work.
Immediate-Mode-UI#699 (comment)
@sleeptightAnsiC
Copy link
Contributor Author

sleeptightAnsiC commented Nov 18, 2025

I've decided to turn it into DRAFT, because I think I should test it a bit better, however, feel free to review. I don't believe I will change anything really.

In order to test the build from sources (without amalgamation header), you can use this:

$ git clone https://github.com/sleeptightAnsiC/Nuklear.git --branch fix__math_util_build
$ cd Nuklear/src
$ for i in $(ls ./*.c); do echo "$i"; cc -x c -c "$i" -o "$i.o" -DNK_INCLUDE_FIXED_TYPES -DNK_INCLUDE_DEFAULT_ALLOCATOR -DNK_INCLUDE_STANDARD_IO -DNK_INCLUDE_STANDARD_VARARGS -DNK_INCLUDE_STANDARD_BOOL -DNK_INCLUDE_VERTEX_BUFFER_OUTPUT -DNK_INCLUDE_DEFAULT_FONT -DNK_INCLUDE_COMMAND_USERDATA ; done

@PavelSharp
Copy link
Contributor

PavelSharp commented Nov 19, 2025

Readed and verified by me. I have carefully reviewed the changes and compiled it successfully. The work looks good, and very canonical in style of Nuklear. We may still need to do deep testing, although the changes are small.

Copy link
Contributor Author

@sleeptightAnsiC sleeptightAnsiC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I've retested everything, and the only problem I found is this non-fatal warning [see below].

It happens only if you provide your own NK_DTOA, and only nuklear_sdl3_renderer is able to trigger it right now. Basically, nk_dtoa implementation was using all those symbols listed below, and when user provides it's own implementation, these remain "defined but not used". It breaks nothing, just triggers a warning, and I don't believe it's even worth fixing.

I could guard those symbols with #ifdef NK_DTOA_IMPLEMENTATION, but this could be dangerous whenever someone starts using them in some other internal function. I guess, people using -Werror might be pissed, but it's hard to believe that someone would use -Werror for building library code.

~/Nuklear (fix__math_util_build) $ cd demo/sdl3_renderer/
~/Nuklear/demo/sdl3_renderer (fix__math_util_build) $ make
mkdir -p bin/
cc main.c -o bin/demo -MD -MF ./bin/demo.d -std=c89 -Wall -Wextra -Wpedantic -O2  -lm -lSDL3
In file included from main.c:116:
../../nuklear.h:6626:1: warning: ‘nk_log10’ defined but not used [-Wunused-function]
 6626 | nk_log10(double n)
      | ^~~~~~~~
../../nuklear.h:6602:1: warning: ‘nk_ifloord’ defined but not used [-Wunused-function]
 6602 | nk_ifloord(double x)
      | ^~~~~~~~~~
../../nuklear.h:6587:1: warning: ‘nk_pow’ defined but not used [-Wunused-function]
 6587 | nk_pow(double x, int n)
      | ^~~~~~

/*#define NK_DTOA (str, d)*/
/* HACK: SDL3 does not provide "dtoa" (only integer version)
* so we use sprintf with %g formatting to get almost the same result */
#define NK_DTOA(str, d) (SDL_snprintf(str, 999, "%g", d), str)
Copy link
Contributor Author

@sleeptightAnsiC sleeptightAnsiC Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is quite evil but works just fine. Comma-operator with "((...), str)" at the very end makes sure that we get the proper return value. The 999 indicates that we don't care about buffer length (dtoa is unsafe anyway). Formatting with %g turns longer values into scientific notation (nk_dtoa does a very same thing). I hope I didn't miss any case.

Copy link
Contributor Author

@sleeptightAnsiC sleeptightAnsiC Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope I didn't miss any case.

Actually, I missed the str == NULL case, I thought that SDL handles it (because it does... just not correctly).

EDIT: Actually actually, SDL makes a correct nullcheck, but only for it's build-in version. If it uses the libc version, it has no such check, lol :D

I'll fix it in few days. I should probably test this thing more deeply.

EDIT: nah, the doc for SDL_snprintf clearly says that neither of pointers should be null, so it does not matter what SDL does internally. dtoa is unsafe and should never take null. However, I still want to ensure this macro is fully correct, and I don't like its current form. I think, I will just reimplement it into the function.

NK_API float nk_strtof(const char *str, char **endptr);
#ifndef NK_STRTOD
#define NK_STRTOD nk_strtod
#define NK_STRTOD_IMPLEMENTATION
Copy link
Contributor Author

@sleeptightAnsiC sleeptightAnsiC Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: nk_strtod is the only public utility function that you can overwrite with the macro. Other similar ones have their declarations kept private inside of src/nuklear_internal.h. I thought this is worth mentioning (but I don't remember why, lol)

@sleeptightAnsiC
Copy link
Contributor Author

sleeptightAnsiC commented Nov 19, 2025

@RobLoach ready to merge, unless you have some objections :)

EDIT: ooops, I need to take a better look at it again: #862 (comment)

@sleeptightAnsiC sleeptightAnsiC marked this pull request as ready for review November 19, 2025 02:36
@sleeptightAnsiC sleeptightAnsiC marked this pull request as draft November 19, 2025 15:07
Copy link

@RafaDEV99 RafaDEV99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, this looks good to me! Additionally, it is beneficial to use as many code implementation macros for this use case (because before it was a mess)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

nk_do_property() uses nk_strtod() instead of NK_STRTOD() Failure to build

3 participants