[HN Gopher] RGFW: Single-header C99 window abstraction library
___________________________________________________________________
RGFW: Single-header C99 window abstraction library
Author : klaussilveira
Score : 144 points
Date : 2024-11-22 21:31 UTC (1 days ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| colleagueRiley wrote:
| Thanks :)
| CyberDildonics wrote:
| I love single header libraries and I like the idea here of taking
| care of one necessity well. It seems like good modularity all
| around.
|
| A quick heads up, the micro UI emscripten example doesn't work on
| chrome or firefox. The error is: _DrawElements doesn 't actually
| prepareClientAttributes properly._
| colleagueRiley wrote:
| I'm aware of the errors for the micro UI (on the web), it's
| something I plan on looking into soon!
| ranger_danger wrote:
| The one big downside I see is that if you want to actually work
| on the library itself, it's a pain to have to re-compile the
| entire thing every time you change something.
|
| Nuklear (https://github.com/Immediate-Mode-UI/Nuklear) uses
| separate files with a deploy script that combines them all into
| a single header; I think that approach is quicker for iterating
| on the code.
| colleagueRiley wrote:
| Sure, but the library is also relatively small, so it
| compiles quickly. Although if you want to you can compile it
| on its own.
|
| It's also possible to compile it on its own using `gcc -c -x
| c -D RGFW_IMPLEMENTATION RGFW.h`
|
| Nuklear is not a true single-header style library, it only
| uses that as a format. The difference is that the design is
| far less compact and lightweight than a stb-style library.
|
| I'm pretty sure GLFW has some files that are nearly the same
| size as RGFW, for example.
| ranger_danger wrote:
| Why do you claim Nuklear is not a "true single-header style
| library"? And who gets to say what that even means?
| colleagueRiley wrote:
| It is a single-header library in terms of the format,
| yes. But it is also not designed to be a single-header
| library, unlike an STB-style library.
|
| Nuklear is a full-sized library that can be compiled into
| and used as one file. However, RGFW and STB are designed
| to be lightweight and minimalistic. That's the
| distinctive part of single-header libraries, also known
| as STB-style libraries.
|
| To be clear, I don't mean this to hate on Nuklear, it's a
| cool UI library, but its design doesn't match the single-
| header format.
| ranger_danger wrote:
| How is it not designed to be a single-header library? The
| README even directly states "Single-header library".
|
| How is it not designed to be lightweight and
| minimalistic?
|
| How do you think the design differs from your idea (which
| is what exactly?) of a "single-header format"?
| colleagueRiley wrote:
| https://github.com/SasLuca/glfw-single-
| header/blob/master/ex...
| ranger_danger wrote:
| What is this supposed to be telling me? This also looks
| like it was multiple files concatenated together because
| there are multiple different header guards throughout the
| file.
| CyberDildonics wrote:
| Have you actually tried? This is 287 KB of C. MSVC on
| computers from 15 years ago will compile C at about 60 MB/s.
| I'm skeptical this is actually a problem.
|
| SQLite is distributed as a single 6 MB .c file and compiles
| in ... 0.1 seconds.
| jstimpfle wrote:
| That may be true for extremely simple source code, but it's
| almost too good to be true. Your number sounded so
| impressive that I tried with gcc (12.2) on my Linux VM.
| With -O0, it takes around 27s, with -O2 it's 1m07s.
|
| With -E (only preprocess) we are at around 0.320s for the
| 260K lines of sqlite3.c. Which makes sense, 1M lines/s for
| the preprocessor and maybe also the AST should be doable
| (that may be where you got your 60MB/s number from). But
| compiling is something else.
|
| MSVC may be faster here or not, I haven't tested it.
|
| A more modern machine (mine is a i5-7600K from 2018) may be
| 2x or more faster, and running on multiple threads will
| speed up the build as well.
| mandarax8 wrote:
| What exactly did you try to compile and how?
| $ time gcc -x c -c RGFW.h -D RGFW_IMPLEMENTATION -fPIC
| -D RGFW_EXPORT 0.42s user 0.03s system 93% cpu
| 0.485 total
| jstimpfle wrote:
| sqlite3, if you read carefully again.
| CyberDildonics wrote:
| _(that may be where you got your 60MB /s number from)_
|
| It's not that. I think I messed up and the 0.1 seconds
| was tcc and msvc was 1 or 2 seconds. Nothing was 27
| seconds. Try tcc, even though you are in a VM it should
| be very fast as a baseline for what's possible.
|
| The point is that some people talk about single header
| files being slow are really saying "what if". C is
| incredibly fast to compile and the slow parts are the
| overhead from each compilation unit and the optimizers.
|
| 287 KB of source code added to a compilation unit is
| nothing in the modern era. Not only that, but you can
| just choose to put a lot of them in the same compilation
| unit and not touch it again.
|
| Every time I've used single file header libraries it
| makes things simple and fast. I'm not going to change
| them so dumping them all into a single compilation unit
| is fine.
| felipefar wrote:
| You could support mobile platforms as well. IIRC, even if Android
| allows creating only one window per activity, this behavior can
| be easily mapped on the abstraction that you provide.
| colleagueRiley wrote:
| That's something I plan on looking into at some point. I'm
| unsure if I want that in the main version or a separate branch
| for embedded devices.
|
| It's low priority though because my main focus is desktop
| applications.
| slmjkdbtl wrote:
| sokol_app.h has mobile support
| dmitrygr wrote:
| > Wayland support is very experimental and broken
|
| You and everyone else, RGFW, you and everyone else.
| colleagueRiley wrote:
| X11 needs a real alternative :(
| themerone wrote:
| What do you expect from an alternative?
| colleagueRiley wrote:
| - Better API design - Not being experimental after 11 years
|
| I think that Wayland actually has some steps in the right
| direction, but overall I don't think it's actually a very
| good alternative. It's way more low-level than X11 and a
| lot of higher level features, like window decorations, are
| not even officially supported.
| akira2501 wrote:
| X11 is fine. It's mostly just Video Games that need an
| alternative. It'd be nice if there was a "pause X11 video
| card control and give exclusive access to a single
| application." Then there's no need to care.
| ori_b wrote:
| You just described X11's DRI (direct rendering
| infrastructure).
|
| https://en.m.wikipedia.org/wiki/Direct_Rendering_Infrastruc
| t...
| Longhanks wrote:
| X11 is utterly broken for multi-monitor setups with
| different resolutions at different scales (e. g. builtin
| laptop screen @1.25x, external display at 1x or some
| variation of that). With high resolution screens (e g. 4k
| at only 27"), that setup is not uncommon anymore.
|
| (Wayland is broken in very many other ways, though, so you
| trade one evil for... 5 others).
| alwayslikethis wrote:
| Wayland's scaling for 1.25x and even 1.5x is not so great
| either, though it is slowly going in the right direction
| with wp-fractional-scale-v1
| uecker wrote:
| X was a very well designed system IMHO that could be
| evolved via extensions (e.g. how compositing was added
| etc.). It is sad that few people work on it anymore to
| fix such issues.
| freeone3000 wrote:
| This actually doesn't work with modern expectations.
|
| Modern games are expected to work in multi-monitor setups
| and render in "borderless windowed" mode, so you can alt-
| tab out to multitask, or have a comms overlay. Single
| monitor single process gaming still _happens_ , but a good
| 85% of setups (according to the Steam Hardware Survey) are
| not that. There are five games I know or that actually
| handle multimonitor natively of the hundreds I've played.
| So we need some form of cooperative multitasking for
| graphics with the window manager.
| 1oooqooq wrote:
| Modern good games are not expected to "render in
| "borderless windowed" mode, so you can alt-tab out to
| multitask"
|
| Really bad games with slow multiplayer match making lobby
| and tiresome repetitive gameplay and bad UX where you
| need to look most of the actual game information on a fan
| wiki, or triple A games where you have to login and enter
| credit card information on a "launcher"... those are the
| ones you expect to "render in "borderless windowed" mode,
| so you can alt-tab out to multitask". Good riddance.
| jll29 wrote:
| Are you kidding? I started reading the X11 handbook series in
| the 1980s and now it's 2024 and I'm nearly finished, and you
| want to replace it? ;-)
| amjoshuamichael wrote:
| Yeah, I've been looking for a minimal SDL alternative for a
| long time and I was really excited reading through this as that
| solution, but the lack of Wayland support is a huge dealbreaker
| for me.
|
| Are there any good minimal windowing utilities that support
| Wayland? SDL does a _lot_ I don 't need and I try to maintain
| minimal dependencies. I suppose I could just use glfw &
| libsoundio, haven't tried that yet.
| colleagueRiley wrote:
| As far as I know, RGFW is the only minimal windowing of its
| kind. I guess I would suggest either targeting XWayland or
| using GLFW.
|
| The Wayland API itself also really sucks to work with, even
| more so than Xlib....
|
| But, RGFW's Wayland support will probably be improved in the
| future. :)
| PittleyDunkin wrote:
| GLFW has worked well for me.
| marcthe12 wrote:
| Waylands problem is that to use it, you need code generation
| so the wayland backend kinda hard to design for a header only
| lib.
| colleagueRiley wrote:
| I just have the Makefile do the code generation, it would
| be annoying for the user, but they can complain to Wayland
| if they don't like it.
| amjoshuamichael wrote:
| I've seen some interesting work in doing Wayland by hand:
|
| https://gaultier.github.io/blog/wayland_from_scratch.html
|
| I'd also look at the work done on minimal wayland projects
| like [foot](https://codeberg.org/dnkl/foot), which supports
| wayland well and seems to be written by hand (see:
| https://codeberg.org/dnkl/foot/src/branch/master/wayland.c)
| vkazanov wrote:
| Isn't SDL itself is quite minimal already? I mean, it is
| definitely not high-level in any sense of the word.
| Sharlin wrote:
| Not minimal in the sense of "just give me a window, a
| minimal event loop, and a GPU context/swapbuffers
| function".
| colleagueRiley wrote:
| Even then, that's what GLFW is designed to do, and it's
| entire source code is still far larger than RGFW's.
| slimsag wrote:
| SDL provides..
|
| ..an image decoding library.
|
| ..an audio input/output library.
|
| ..a multi-channel audio mixer.
|
| ..ttf and rtf font rendering.
|
| ..networking.
|
| ..runtime shader cross-compilation
|
| ..its own entire graphics abstraction layer / API.
|
| ..its own shader language, shader compiler, and shader
| bytecode format.
|
| I don't know at which point something becomes 'high level',
| but SDL is only 'minimal' if you use a subset of its
| functionality.
| nextaccountic wrote:
| Rust has a lot of those small libs, my favorite is miniquad
|
| https://crates.io/crates/miniquad
| Sharlin wrote:
| Other alternatives: pixels, minifb, softbuffer.
| colleagueRiley wrote:
| Sure, but none of these are true alternatives because
| they are missing a lot of features that libraries like
| GLFW or RGFW have.
|
| (They may be good alternatives for certain use-cases)
| Sharlin wrote:
| Oh, just based on the README I assumed RGFW was more
| minimal than it actually is.
| colleagueRiley wrote:
| Minimal refers to the code itself.
|
| GLFW's codebase is ~10MB while RGFW's is about ~300kb.
| But RGFW tries to support nearly everything that GLFW
| supports.
| Sharlin wrote:
| Yeah, my bad :)
| garbagepatch wrote:
| This was added to raylib as a backend recently:
| https://github.com/raysan5/raylib/releases#:~:text=RGFW
| eqvinox wrote:
| Every time I see a "single-header C library", I wonder to myself
| where we'd be if only Windows had a proper package manager.
|
| (Especially since that'd force the POSIX world to de-fracture
| itself too.)
| perching_aix wrote:
| > a proper package manager
|
| Those are a thing? Wasn't aware.
| raymond_goo wrote:
| Isn't the one from Rust pretty good?
| perching_aix wrote:
| Haven't worked with it much yet, not really my point
| either. They were talking about OS package managers, most
| likely the typical Linux package managers, and so did I.
| linkdd wrote:
| scoop? chocolatey? pacman in msys2? winget?
| eqvinox wrote:
| Remind me please, which of these is shipped with a default
| Windows install?
| wis wrote:
| I realize you asked sarcastically, but as of relatively
| recently WinGet is shipped by default with the latest
| versions of Windows 10 and in Windows 11. [1]
|
| But why is being installed by default important?
|
| [1] https://www.petergirnus.com/blog/how-to-use-windows-
| package-...
| kreetx wrote:
| It's an adoption barrier.
| 1oooqooq wrote:
| meh. it's not.
|
| If you are convincing people to run commands to install
| packages:
|
| - they care about trust, they will already have their
| package manager from the ecosystem they trust (which
| should be msys+pacman on windows, btw)
|
| - they couldn't care less and will trust your `curl |
| bash` or `Invoke-RestMethod -Uri
| http://hacker.com/totallysafe.exe`
|
| on both cases, not having a default package manager
| shipped caused zero adoption attrition, I mean, besides
| the attrition of needing a non-standard package to begin
| with.
| frizlab wrote:
| IMHO it is though. I have a windows VM I rarely use and
| tried using a package manager at some point, but end up
| not succeeding until winget was part of the system and
| was a no-brainer.
|
| Too many possibilities made me choose none.
| Conscat wrote:
| I know very non-technical people who use Chocolatey for
| acquiring ffmpeg.
| eqvinox wrote:
| It was only partially sarcastic (yeah that didn't
| communicate at all, bad habit on my end), I had googled
| them but didn't quite understand the winget situation at
| glance. Thanks for the answer, actually appreciated!
| flohofwoe wrote:
| Most of those are for installing applications, not system-
| wide C library source distributions (e.g. you'll need to
| figure out the path of the source and header files in build
| scripts since there's no standard location for that on
| Windows).
|
| The closest thing to a C/C++ package manager standard on
| Windows is probably vcpkg: https://vcpkg.io/en/
| colleagueRiley wrote:
| We'd be at the same spot, single-header files are still useful.
|
| A single-header file is not a 'full-sized' library compressed
| into one file it's codebase is designed to actually be
| minimalist. Many libraries have single files that are the same
| size as their alternative single-header.
| Philpax wrote:
| I wonder where we'd be if we'd stopped relying on system
| packages to provide dependencies for C / C++. It is positively
| miserable to have to pollute your system when a codebase
| written in Go / Rust / your favourite modern language Just
| Works out of the box.
| linkdd wrote:
| With a central, curated, audited package repository where
| publishing rights are given to absolutely everyone then
| supply chain attacks in C and C++ would be even easier.
| IshKebab wrote:
| We'd be in exactly the same place because nobody wants to use
| an OS-dependent package manager for an OS-agnostic project.
|
| I don't know if you noticed but no modern languages use Linux
| packages to provide dependencies, because that obviously sucks
| balls for many reasons.
| eska wrote:
| Not sure whether this is tested on Windows at all. I opened the
| header and immediately found this `typedef signed long i64`, i.e.
| i64 is actually i32.
| Conscat wrote:
| I'm not sure that issue would be caught by ordinary testing. It
| will implicitly cast into long long, so it might make little or
| no difference in this case.
| eska wrote:
| A lot of people use i64 in the global namespace, so this will
| affect later code. It's basically `#define true false`. When
| I consider a library I will do a quick sniff test to look for
| very obvious mistakes, at which point I won't look further.
| colleagueRiley wrote:
| :( That's disappointing, but I understand.
| colleagueRiley wrote:
| I test Windows mainly with MINGW, that might be an issue with
| MSVC. Feel free to report the issue on the github repository.
|
| I'm pretty sure windows uses "long" for 64 bit but linux uses
| "long long" for 64 bit
| tredre3 wrote:
| > I'm pretty sure windows uses "long" for 64 bit but linux
| uses "long long" for 64 bit
|
| Windows long is 32bit even on 64bit CPUs.
|
| Linux long is arch dependent and is 64bit on x64, 32bit on
| x86.
|
| long long is always 64bit on both platforms.
| colleagueRiley wrote:
| Okay, thank you.
| eska wrote:
| It's just that the #if checks for the MSVC compiler, not for
| Windows as a platform. And on that compiler you will never
| have LP64, but LLP64: https://en.wikipedia.org/wiki/64-bit_co
| mputing#64-bit_data_m...
|
| I just roll my own for this because I don't need all the
| functionality, and generally find such cross-platform
| libraries to only really test on Linux, and it's too much of
| a hassle.
| colleagueRiley wrote:
| Yes, because MSVC may or may not have stdint.h
| flohofwoe wrote:
| Since you're using C99 as the base C version, why not use the
| fixed-width types from stdint.h (int32_t, int64_t, ...)?
|
| You can still typedef those to i32, i64 shortcuts etc, but I
| would try to avoid this in libraries since it might collide
| with user typedefs of the same name - or at least try to
| avoid it in the public API declarations.
| colleagueRiley wrote:
| I use those by default although I read that MSVC's support
| for those are iffy. I'm pretty sure STB does the same thing
| for the same reason.
|
| Source: https://handmade.network/forums/articles/t/7138-how
| _to_write...
| flohofwoe wrote:
| Since around Visual Studio 2015 you're fine.
|
| AFAIK the STB headers are on C89 mainly because nothings
| likes to use VC6 as C IDE.
|
| E.g. if you depend on other C99 features anyway,
| including stdint.h is fine, also on MSVC.
|
| PS: FWIW I use stdint.h types in the Sokol headers since
| around 2017 and never heard complaints from users, with
| the supported compilers being MSVC, GCC and Clang.
| colleagueRiley wrote:
| Oh, I wasn't sure if that was you :)
|
| Thanks for the advice, I'm a little worried about
| breaking compatibility with compilers that don't support
| stdint. But if it's standard for C99 thing then sure.
| eska wrote:
| _Since around Visual Studio 2015 you 're fine._
|
| I personally use `_MSC_VER >= 1600`, so it's since Visual
| Studio 2010 from April 2010. Built-in types like __int32
| from before then may be used as well.
| InfiniteRand wrote:
| It depends whether you're compiling in 32-bit or 64-bit mode,
| MSVC has two different modes and there are different versions
| of MinGW for 32-bit and 64-bit
| tom_ wrote:
| For MSVC, long is 4 bytes: https://learn.microsoft.com/en-
| us/cpp/cpp/fundamental-types-...
| bluecalm wrote:
| This is strange because C99 has stdint.h so we don't need to
| use "short/long/long long/long long long" nonsense anymore.
| uecker wrote:
| I like simple code written in C, but when does this "single-
| header" nonsense stop? C has super nice and simple modularization
| via the classical .h/.c split which ensures fast compilation,
| proper encapsulation, no instruction bloat via creating multiple
| instances for all functions.
| colleagueRiley wrote:
| Try putting GLFW's source code into one file and then compile
| it. That will take at least a few seconds, RGFW compiles in
| less than a second.
|
| Where's the bloat? :)
|
| https://github.com/SasLuca/glfw-single-header/blob/master/ex...
| uecker wrote:
| The issue if if you have many such libraries and any change
| to the implementation forces recompilation of everything.
| Maybe not such a big deal for such small libraries, but an
| annoying trend IMHO.
| tredre3 wrote:
| > no instruction bloat via creating multiple instances for all
| functions.
|
| This makes me think that you're using single-header libraries
| wrong. These kind of libraries usually require you to do
| something special prior to including it to get the actual code
| and you must do it only in ONE file.
|
| For example, you'd #define RGFW_IMPLEMENTATION before #include
| rgfw.h in exactly ONE .c. If you need the header in other
| files, you do NOT define RGFW_IMPLEMENTATION and no code will
| be produced.
| uecker wrote:
| Well, I do not use them at all. But I agree that this
| mechanism would avoid the additional copies. I have seen
| other single-header libraries though...
|
| In any case, forcing me to figure out the specific
| XYZ_IMPLEMENTATION for each library is less user friendly
| that just proving a .c and .h file.
| CyberDildonics wrote:
| I can't figure out why anyone would call it 'nonsense'. The
| definitions and functions have to be together, they may as well
| be a single file separated by a preprocessor definition.
|
| Include the header where you want the definitions. Include the
| header and use the preproccesor definition in the compilation
| unit you want the functions in. Done.
|
| There is no speed issue here. It would take 100x the C to make
| a difference and it's actually going to be much faster and
| simpler to put a lot of single file libraries into one
| compilation unit. I always wonder if the downsides are
| theoretical or if people are really doing what I've been doing
| and still have a problem with it.
___________________________________________________________________
(page generated 2024-11-23 23:00 UTC)