5 ms·
eww. “Try to compile and see if it fails” is awful. I have never and would never do that. That’s so gross.
by forrestthewoods 3y ago
eww. “Try to compile and see if it fails” is awful. I have never and would never do that. That’s so gross.
- stonogo 3y agoIt's literally the only way to be absolutely certain a specific feature is available. Version checks, shibboleth strings like __GLIBC__, documentation, all of these things can be subverted or lied to. In the end, verifying the desired behavior is present is the only correct move.
- forrestthewoods 3y agoIn 17 years of professional dev I have never, ever worked on a project that required such dark arts. glibc is a special evil. zig, which can compile C/C++, solves that conundrum. Hopefully someday the core glibc project fixes itself. Food for thought: cross-compile should be a first class feature of any build system. If you’re depending on a pile of arbitrary system state you’re doing it wrong. zig can compile for any target from any target. It’s beautiful. And not nearly as difficult as people seem to think.
- naasking 3y agoZig definitely has the right approach, but it's targets are still a bit limited so saying it's not difficult is maybe ignoring gcc's extreme portability that zig hasn't yet had to deal with.
- stonogo 3y agoCongrats on the clean living, but it remains the norm regardless. Both CMake and Autotools use this approach. C and C++ aren't the only languages for which this is true, by the way. It is de rigueur these days to have versioned releases for the purposes of feature gating, but there's half a century of code out there written in languages without that, and explicit feature testing will be with us as long as that code is. Anyway, native cross-compilation is also not a language feature. Plan 9's C compilers can target any supported architecture from any other supported architecture with no special configuration. Autotools, CMake, and "compile and see" are all artifacts of a highly diverse unix ecosystem. Tools like it are the price we pay for heterogeneity. Flexing to accomodate so many subtly different platforms is a big part of what brought things like GNU and llvm to promenence, so it's not a good idea to dismiss it as a bad thing.
- forrestthewoods 3y ago> it remains the norm regardless. Both CMake and Autotools use this approach Yes, it is the norm (in certain circles, but not others). No, it doesn't have to be that way. CMake and Autotools are both genuinely awful. The world would be a better place if Bazel/Buck2/similar were the norm. I find it extraordinarily bizarre how defensive Linux people get when I say "the status quo is actually bad, but it doesn't have to be!". > there's half a century of code out there written in languages without that, and explicit feature testing will be with us as long as that code is. I think you radically overestimate how difficult of a problem this is. It doesn't have to be this way. I promise you! > native cross-compilation is also not a language feature. Correct. That's why I called it a feature of a build system. C/C++ standards famously do not even attempt to describe a build system. This has resulted in many elements that really ought to be language features to actually be implementation defined. > so it's not a good idea to dismiss it as a bad thing. "because of" vs "despite of"
- stonogo 3y agoI didn't say Autotools and CMake weren't awful, I said that approach exists for a reason. You seem not to understand; maybe it's my poor communication skills. And I don't appreciate being called "Linux people," because I am not one, thanks. Not sure why personal attacks are in play here. The thing you're missing is that Bazel, Buck2, Zig, and all these things that do not require the compile-testing approach is they are not portable. They support Windows, MacOS, and Linux, by special-casing each platform, and even the Linux support is restricted to a few mainstream distros. This is a perfectly valid technical decision, and one I support, but it was not possible for decades. Now people take Linux for granted, but until relatively recently you had dozens of almost-compatible Unix clones from dozens of vendors, of which Linux was but one. All of them had to be, essentially, written from scratch or based on a BSD release, with the differentiating features implemented on top by a given vendor. Since different developers had different interpretations and priorities for "Unix compatibility," this led to a combinatorial explosion of possible software configurations even just at the libc level, much less kernel API. The Single Unix Specification and POSIX standards were assembled to try to correct this, but there was no way to go back and un-differentiate all these Unix clones. So developers targeted SUS or POSIX, and mostly got what they needed, but something had to account for all the little differences that remained. This was the purpose of Autotools, and Cmake was written because Autotools sucked. So, these things you're praising which avoid that whole scene, are able to do so because, for better or worse, Linux won. The other Unix clones have either completely died out (SCO Unix etc), are dying out quickly (Solaris etc), or have stabilized into their own distinct platforms (FreeBSD, MacOS, etc). It has nothing to do with the build system. It has everything to do with platform consistency. That's why Plan 9 can do it without any build system beyond mk (a weird clone of Make), and why the FAANG companies can crank out build systems as get-me-promoted projects -- they're targeting three stable operating systems, instead of an uncountable number of weird almost-compatible monsters. But again, from this terrible Unix scenery emerged a remarkably robust and portable set of tools (gcc, the gnu coreutils, etc) which became the de facto standard across all the Unix clones. People liked them because they worked the same on every Unix, and because (thanks to Autotools) they could build on every Unix. Because they had this versatile build system, when Linux came around the GNU tools were the easiest to port. Because they were the main tools running on Linux, and people had experience with them from other Unix clones, Linux adoption was quick and easy. And so it grew in popularity... So yes, I mean "because of." It's easy to hate on complicated old rickety shit like Autotools, and I will be happy when I never have to deal with it again, but pretending it has no value and typing in "ewww" is needlessly dismissive and denies the actual importance this code had in getting us to a place where we can live without it.
- lelanthran 3y agoOkay, what's the alternative when `accept` has three parameters when using glibc and two parameters when using musl?[1] How else do you determine which one to use other than by compiling against the chosen library and seeing what fails? [1] just an example, musl mighy actually have same amount of parameters as glibc for all I know. But newlib doesn't.
- forrestthewoods 3y agoThe build system should specify whether it wants glibc or musl and what version. Relying on current system state is one of the reasons that glibc is such a monumental pain in the ass. It should be trivial to target an arbitrary version of glibc. (zig build system achieves this). The way C projects from the 90s work is you locally run .configure and it generates a whole bunch of headers, if not .c files, with a whole bunch of crap based on local system state. Then you run a build script. "The Right Thing" is for the repo files to contain a superset and for the build system pass the tiny handful of defines necessary to select the target platform. For example glibc, musl, PlayStation4, NintendoSwitch, etc. It's very, very easy to do. musl does things right. glibc is the only bad citizen stuck in the 90s. The difference between the libc headers across the kajillion target platforms is exceedingly minimal.
- lelanthran 3y ago> Relying on current system state Autoconf is most useful when the build isn't relying on current system state! That's it's most useful characteristic. If the goal was to build against the current system, autoconf probably would never have existed. Building against the current system is a side-effect of doing proper cross-compilation builds. > "The Right Thing" is for the repo files to contain a superset and for the build system pass the tiny handful of defines necessary to select the target platform. For example glibc, musl, PlayStation4, NintendoSwitch, etc. For common platforms, sure... that works well and that is sort of how my Makefiles are written.[1] But to cover the domain that autoconf/configure.sh covers ... well that is not feasible. Glibc might have 3 parameters when compiling against Linux, but 2 when compiling against Solaris. Linux itself might have some `#define`s when compiling on x86_64, and a different set when compiling on RISC-V. The target distribution might have different parameters when compiled for Debian vs when compiled for Alpine. It's why gcc uses hyphenated targets: `ISA`-`kernel`-`platform`. So you see things like `x86_64-w64-mingw32` and `sparc-unknown-linux-gnu`. The combinatorial explosion of ISA + kernel + ABI + distro + user libs is much much harder to manage for a portable project that has many dependencies than simply putting up with autoconf. I mean, I don't even like autoconf (which is why I avoid it), but I gotta say, autoconf actually does solve those problems especially for cross-compiling, because then the entire chain of libraries getting linked in will be guaranteed to be the correct ones, for the correct ABI, on the correct target ISA, on the correct target kernel, on the correct target distribution ... and if something doesn't match, you'll know before Make is even run. This is especially important with C++, which needs another value in the tuple for seh/sjlj, and you cannot detect which of the two you need until you run the resulting program and it generates an exception. It's just possible that, in 2024, we don't actually need the level of portability that autoconf brings to cross-compilation anymore - build it against Windows/Linux/BSD on x86_64/ARM and you cover about 50% of useful scenarios. Those that need the remaining 50% probably already know what they are doing and can tweak the Makefiles and/or source code to build for their target. [1] I do minimal detection and expect the user to set certain variables if they don't want the defaults.