12 ms·
This is a typical idiom frequently seen in modern C and C++ codes. As https://github.com/krychu/wfc#how-to-use-the-library https://github.com/krychu/wfc#how-to-
by ktpsns 5y ago
This is a typical idiom frequently seen in modern C and C++ codes. As https://github.com/krychu/wfc#how-to-use-the-library https://github.com/krychu/wfc#how-to-use-the-library says, you need to define a macro in a C file in order to "expand" the actual code there.
Having the code in the header gives a bit more flexibility considering the file layout. IMHO this is an awkward consequence of the missing de-facto-standard in C/C++ build systems.
- titzer 5y agoAll code in the header leads to a lot of duplicated work for the compiler, which means slow build times. You should avoid this unless it is absolutely necessary for performance to inline methods.
- krychu 5y agoThat work will be done by the preprocessor and should be fairly quick given it doesn't compile the duplicated code and only removes it.
- titzer 5y agoIt may still generate code for function definitions, which are deduped by the linker, so a lot of the code can still go through the whole compiler.
- flohofwoe 5y agoAn STB-style header with the implementation disabled (which is the default) looks exactly the same to the compiler as a regular C header which only contains public API declarations (e.g. just struct declarations and function prototypes, and most importantly, no inline code). All code that would otherwise live in .c files is between an #ifdef/#endif block which is only activated in a single compilation unit in the whole project. Not sure how this approach would lead to redundant "function definitions" which would need to be deduped by the linker. The only overhead is in the preprocessor for skipping the implementation block, but that happens pretty much at IO speed - it's not comparable with the parsing overhead in typical C++ headers with template and inline code.
- titzer 5y agoSure, after brushing up on this "stb style", then I see what you mean. Still, it seems like an ugly kludge to cope with a breathtakingly antiquated way of doing things.
- sledgehammers 5y agoWhy should it be any more complicated than that? What ever happened to keeping it simple?
- titzer 5y agoThings can be locally simple but have complex and chaotic implications. E.g. just by pushing the complexity up a level and dumping it on literally everyone else. I've learned over the years that complexity sometimes has a right place and a wrong place. (Most times complexity ends up everywhere, TBH.) I think resolving references between different parts of code in different compilation units is definitely within the purview of a compiler/build system, and should not be up to every programmer to flail at poorly with #ifdefs.
- flohofwoe 5y ago> with a breathtakingly antiquated way of doing things. I think it's mainly a fix/workaround for the breathtakingly antiquated build systems in the C/C++ world ;) In the end, STB-style single-header vs. a single .h/.c pair is not all that different, both are equally straightforward to integrate into a project. The actual problem are libraries made of dozens/hundreds/thousands of header and source files and coming with their own complex build system setup.
- shannongreen 5y agoHow is it more flexible exactly? I hate this idiom every time I come across it. I like to look at the header file to see the interface and important documentation, and this just obscures it. Depending on your compiler it can make debugging a huge pain as well.
- veltas 5y agoIt does seem that 'modern' idioms tend to just be doing the same thing in a more obfuscated manner. Just a .c/.h pair would have been easier to add to your source.
- NavinF 5y agoThat would be easier if the most popular build systems weren’t terrible
- pjmlp 5y agoOr I don't know, people actually bothered to learn them.
- wizzwizz4 5y agoLearning something doesn't stop it being terrible. One time I ran `cmake`, and forgot to run `sudo -k` beforehand. It reconfigured my system.
- pjmlp 5y agoThat has more to do with sudo than cmake.
- wizzwizz4 5y agoThis might be an unpopular opinion, but compiling a program into a local directory shouldn't try to install packages globally. `make install`, I could understand doing that. I had no idea that cmake would do this, after reading quite a lot of things about cmake v.s. make and how to write various makefiles for them. I posit that the C build tools are fundamentally hard to comprehend.
- pantalaimon 5y agoYou don't need an elaborate build system to add a single .c file to your project
- chii 5y agoand now you need to add a .h to where ever you need to call those function. This .h will need to know if it got included multiple times, and so isn't just a trivial declaration. It's just easier to have a single .h you include.
- charcircuit 5y ago>to add a .h to where ever you need to call those function No, it can be in a single place and you can just #include it. >This .h will need to know if it got included multiple times, and so isn't just a trivial declaration. This is the point of using header guards. >It's just easier to have a single .h you include. Depending on the build tool it's the same or only marginally easier (you save like 10 characters)
- pjmlp 5y agoThis is a sad idom followed in C and C++ libraries that cannot be bothered to learn build tools, dealing with C and C++ as if they were scripting languages.
- floor_ 5y agoHave you ever tried using a unity build?
- pjmlp 5y agoAnother nonsense, no I haven't ever bothered with it. A hack designed by those that cannot be bothered to modularize a build with binary libraries.
- maccard 5y agoIt definitely is a hack, but it's not nonsense. The speedups on large projects are significant, even on modularised ones.
- glouwbug 5y agoNot entirely. If you think about it, a resulting C binary is just data and text - it’s all compiled into a single unit of globals and functions, much like a unity build layout. Regarding optimization it allows for LTO without the need for a link time optimizer. Regarding convenience, it spares one from function prototypes and using Make or CMake. Should one use Make to speed up build times it’s as simple as tossing the unity code you’re not working on into a precompiled header; this primes the compiler for a quick compilation of the newly written code. As for design, I find unity builds resemble the design mind of a mechanical, civil, or electrical engineer - a single assembly (main.c) incorporates sub assemblies (*.c) like a CAD designer would design SolidWorks parts for a vehicle or spacecraft
- pjmlp 5y agoI rather prefer the software engineering mind to use binary libraries for what they were designed for.