4 ms·
Glad to see this covered -- I also had the experience of picking it up the hard way, over many years! My own tips after writing a custom build system for C++
by chubot 3y ago
Glad to see this covered -- I also had the experience of picking it up the hard way, over many years!
My own tips after writing a custom build system for C++
- the order of objects and -l flags to the linker matters! I remember being very surprised / frustrated by this.
- Sanitizers are built into compilers and trivial to use. Learn to use AddressSanitizer simply with -fsanitize=address! Ironically I think many people don't use it because their build system doesn't have good build variants (dbg, opt, asan), or they don't know how to configure the build system. Plain make generally isn't good enough.
- Some flags have to be passed to both the compiler and link steps, and others don't. I mostly figured this out by trial and error, and the error messages aren't great.
- You can compile and link in one driver invocation (c++ -o), or you can build each object separately and link (c++ -c).
I thought the former might be faster, and it seems simpler, but there doesn't seem to be any real advantage (edit: this post explains why -- it's literally subprocessing, which you can do better from a shell or build system). The latter is more common because it supports parallel and incremental builds.
Some options, I think -ftime-trace for Clang, which outputs JSON compile time traces, don't even respect the first style of building.
- Spending some time with a plain shell script and the compiler isn't a bad way to learn. Now I can finally read all those crappy long error commands from big build systems. The most common and useful flags are -I to add to the #include path and -D to define a preprocessor symbol.
---
edit after skimming the whole thing: This is really excellent, should be titled "Compilers: The Missing Manual".
I have actually looked at the manuals, e.g. https://gcc.gnu.org/onlinedocs/gcc-13.1.0/gcc/Invoking-GCC.html https://gcc.gnu.org/onlinedocs/gcc-13.1.0/gcc/Invoking-GCC.h... but they seem to be missing the high level conceptual overview.
They also seem to be missing the name "driver", which is important, even though I have encountered a page about that before. It seems to be in a separate "GCC Internals" doc:
https://gcc.gnu.org/onlinedocs/gcc-4.3.2/gccint/Driver.html#Driver https://gcc.gnu.org/onlinedocs/gcc-4.3.2/gccint/Driver.html#...
Other notes: I should have been using the -v flag to the driver all along! That's a little embarrassing.
Also it's good to realize that g++ and gcc are both drivers, and the former sets the -I path to the location of the C++ stdlib and so forth.
Looks like lots of great examples of 'readelf' as well, which I'll go over again.
It is kind of crazy how people generally pick this up piecemeal over so many years ... A big problem in my mind is that it's usually wrapped in GNU make or CMake or IDE configs, which add their own line noise on top of the raw driver invocations. Which in turn have a ton of logic before the actual tools are invoked.
- izacus 3y ago> - the order of objects and -l flags to the linker matters! I remember being very surprised / frustrated by this. This took so long for me to actually find out... and then beat most build systems into submission because they have no ability to configure priority of linkage.