8 ms·
My unusual application of Docker here is no exception. Most software builds are needlessly complicated and fragile, especially Autoconf-based builds. Ironically
by simfoo 6y ago
My unusual application of Docker here is no exception. Most software builds are needlessly complicated and fragile, especially Autoconf-based builds. Ironically, the worst configure scripts I’ve dealt with come from GNU projects. They waste time doing useless checks (“Does your compiler define size_t?”) then produce a build that doesn’t work anyway because you’re doing something slightly unusual. Worst of all, despite my best efforts, the build will be contaminated by the state of the system doing the build.
Completely agree, Autoconf needs to die. C++ builds don't need to be complex and fragile, even if many environments are supported. Just use a minimal CMake build and resist the urge to implement "clever" things in it.
- pornel 6y agoIf you do only minimal things, you will have fragile builds. The hacks are there not because people like adding complex code for no reason, but they're scars from broken builds. For example, requirements for what has to be static and what dynamic are different on Linux (distros want unbundling) and macOS and Windows (you can link to handful of things that ship with the OS). macOS is especially annoying, because if you're not careful, you'll link dynamically to homebrew's non-permanent locations. `find_package` doesn't do the right thing without clever non-minimal things around it.
- CJefferson 6y agoThe problem is, autoconf does a terrible job of supporting Windows, and actively rejects patches which would improve things (for example, it does very badly with spaces in filenames, which are common in Windows, for example "Program Files" and "My Documents")
- mehrdadn 6y agoEven Bazel doesn't support spaces in file names!
- vbezhenar 6y ago"My Documents" are called "Documents". You can also install your application into user directory, something like "C:\Users\Vladimir\AppData\Local\YourApplication", so no spaces necessary unless user name contains spaces (not sure if it's even possible). I'm not claiming that spaces should not be supported, but you can live without them.
- fomine3 6y agoIt's shame that it still needs workaround in 2020.
- cheez 6y agoautoconf is an attempt to commoditize the insanity that people have experienced over the years. This is the wrong approach. The right approach is to make it easier to add checks for only your particular insanity. CMake does it correctly.
- tannhaeuser 6y agoNot that I think autotools are great, but, to the contrary, feature-detection is exactly what all those macros in configure.ac etc. do, as opposed to cmake which tries to guess a platform and is a monolith with magical behaviour that nobody groks in its entirety. cmake, for one, is actually a case of the cure being worse than the illness. Already autotools treats Makefiles as output (and many macros shit gmake-specific if/else cascades into it) when the solution is simply using Makefiles properly, and assume POSIX headers/defs in this millenium. See git's Makefile, or those on suckless.org, for how to do it properly.
- cheez 6y agoCMake doesn't do any feature detection if you don't want it to.
- simfoo 6y agoTrue but I think addressing those inconsistencies in the build system is doing it on the wrong level. Ideally this should happen outside the actual build and any dynamic configuration that is derived from the system environment should simply be passed into the build. CMake makes this easy using toolchains.
- ValleZ 6y agoIs this really easy? I spent days lately trying to compile popular library on Mac for all platforms (Win, Linux) only to figure out that it is MUCH easier just to set up bunch of dockers/VM and compile it there. I suspect it is close to impossible to compile the library (LevelDB) for Linux on a Mac.
- cheez 6y agocross-compiling was necessary when hardware was expensive. You can rent a Linux box for $10 if you want to compile.
- jcranmer 6y agoHaving worked on compilers, I can honestly say that autotools' attempts to be helpful are more often the cause of the trouble than fixing anything broken. For example, it checks for memcpy by writing this program: void memcpy(void); int main() { (void)memcpy(); } and checking if it compiles. Which is of course illegal and completely nonsensical C code that no one would ever write. It is not entirely unreasonable for a compiler to error out if it sees this code, and ince we were working on an aggressive pointer analysis for C, we did do so. Of course, since the compiler failed on this code, autoconf concluded that the system didn't have memcpy, and it helpfully provided its own implementation... which immediately crashes the build (after autoconf completes, of course) for multiple redefinitions of memcpy. To top it all off, it appears that there has never been any system that didn't have memcpy that was capable of running any version of autoconf, let alone any software written this millennium. This check literally has no benefit, and is "complex code [added] for no reason."
- vbezhenar 6y agoI don't understand why is it illegal C? memcpy is just another function in some library. It might be libc or not. I don't expect compiler to care about it, just put function call into object code and move on. Warning might be useful.
- stephanimal 6y agoBecause it is a function in the C Standard Library. Programs are typically prohibited from declaring these functions. You can if you don't link with libc and pass in the correct compiler flags (gcc will turn some raw loops into a memcpy call as an optimization even without linking libc afaik) https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html https://www.gnu.org/software/libc/manual/html_node/Reserved-...
- HelloNurse 6y agoCompilation units are required to declare all standard library functions they call. They usually do so by including the compiler's header files rather than doing more work and risk errors with explicit declarations.
- pornel 6y agoTo be clear, I'm not defending autotools. But every C build system will have to deal with some mess. That may be having multiple configurations for multiple OSes (with weird exceptions for weird OSes or WASM), snowflake libraries that just had to have their own pkg-config replacement, fiddling with flags for various flavors and versions of MSVC and non-MSVC compilers, rpaths, sovers, etc. To me it's inevitable that every project that starts with "just 5 lines of simple CMake/Makefile, look how simple it is!" will end up with the same mess everyone else ends up with.
- radarsat1 6y agoIf only CMake weren't just as awful. It seems to have become an industry standard yet I can't begin to tell you how much time I've wasted wrestling with it lately. In an ideal world all projects would use CMake "correctly" but it's just not the case; problems are really hard to debug, no one really seems to know the current "right way" to do things, and the "right way" keeps changing anyway. Coupled with an awful language, I just can't say that CMake is better, or much better, than autotools. But at least it handles Visual Studio and ninja. So yeah, we use it for the support it provides which is second-to-none, but it's a mostly terrible user experience, frankly.
- DagAgren 6y agoThe only reason CMake is considered better than automake is because automake is so unimaginably dreadful. CMake is a lot worse than pretty much any competent piece of software.
- mister_hn 6y agoYet CMake is much better and comes with support for installers (Deb/rpm/MSI/DMG), which is a killer feature. And now it's even better to couple it with Conan for dependency management
- irishcoffee 6y agoIgnoring the qt part entirely, I think qmake is the best of the bunch.
- dasloop 6y agoQt is moving to CMake too. And the latest versions of CMake are as good, or better, than qmake. Add to that vcpkg and you will have a fantastic solution for managing dependencies. Maybe CMake is not the best but is good enough and the new standard in the C++ world.
- irishcoffee 6y ago
- fefe23 6y agoautoconf is a typical GNU project. It looks like it would be horrible and crufty but when you make an effort to get to know it it is actually pretty sweet. Just a little example of how clever it is: If you want to cross compile to a target, you can't actually run the test programs you compile. So it becomes important to make them fail at compile or link time, not at run-time. If the expression to be tested is constant at compile time, autoconf will compile a test program that uses the expression in the size of an array type. So, let's say you want to check if sizeof(int) is at least 4. Then autoconf would make a test program that declares something like typedef char foo[1-(sizeof(int)<4)*2]; If sizeof(int) is less than 4, then the array size would become negative, and that produces a compile time error. No need to actually run the program. That is the place where I learned about this pattern many years ago. I'm still grateful for autoconf for teaching me that. This is how you did compile time assertions in C before C introduced _Static_assert. Also note that autoconf has lots of other awesome features if you would like to learn about them. For example it can be configured to have a system-wide cache for test results, which speeds up future runs. But the most important part of autoconf to me is that it is dependably configurable. On my system, I have both /usr/lib and /usr/lib64 so I can develop for both 32-bit and 64-bit worlds at the same time. Run configure with --libdir=/usr/lib64 and you are good to go. There is no single way to reliably do this with cmake. Among the conventions, -DLIB_SUFFIX=64 has apparently crystallized out as de-facto standard, but you can't rely on it. For LLVM you have to set LLVM_LIBDIR_SUFFIX instead. Or let's say you want cmake to also look for include files in /usr/X11R7/include and for library files in /usr/X11R7/lib64. Good luck with that! I'm not trying to say that cmake is bad. It is a good solution for what it is trying to achieve. But automake had higher goals and also achieved them. But I think cmake vs autoconf is a false dichotomy. cmake is not the enemy here, and neither is autoconf. I'm actually more disappointed in the hubris of all the people deciding they can make better build systems than automake or cmake and then roll their own, but consistently fail in situations that other people already encountered, thought about, and solved. We now have autoconf, cmake, jam, bjam (Boost), qmake (Qt), meson, waf, python and perl have their own stuff, everybody believes they need to ram a package manager down my throat as well. To me, life time is the only resource that actually matters. For every 5 minutes you think saved by not going autoconf, you made your "build from source" users waste 50 minutes per person to get your build scripts to work.
- zaptheimpaler 6y agoI don't know WTF is going on in C++ world but they seem to be unable to adopt a build & dependency management system given all the historical baggage. In Python: . ./venv/bin/activate pip install -r requirements.txt In Java: mvn build In C++: cat README.txt ..... now go apt install some packages. Except they might be named differently in your distro. Also some of them might be a different version but my README specifies no version, so it might fail to compile or error out later because of a header mismatch. Also the one available in your distro might not be compiled with the "X_POTATO=1" flag (which you will discover somewhere along the way is required), so its time to build that dependency from source and restart this whole dependency management hell one layer down have fun :) There are different versions of compilers supporting different features floating around, but Makefiles or whatever don't specify that. Build dependency management is frequently something like `sudo apt install...`, tying the build process into packages installed in the OS itself rather than being sandboxed which creates all sorts of problems.
- saurik 6y agoSo, my experience is the total opposite, but it is probably because you only want to compile for your one computer whereas I am constantly trying to compile for twenty platform / architecture combinations with sometimes arbitrary toolchain requirements (like "must use clang" or "must use a compile newer than X" or "must generate object files capable of being used on this older version of the operating system"). I have _never_ had a hard time compiling something when it uses autoconf: I had to learn how autocons works and what its expectations about the world are, but they are actually mostly correct... libtool, on the other hand, causes me issues sometimes, but I have largely figured those out over the years. But when people use CMake? Ugh. I am in for a world of hurt, and probably so many custom assumptions about how to interface with the compiler and the operating system that not only is cross compilation probably off the table, but compiling it at all for one of my target platforms is likely not going to work :/. I pretty much always end up having to just throw away your build system entirely and start over from scratch just to even test the project for my target. OMG: a bunch of projects like using tools like Meson... the entire Meson 0.52.x line entirely broke the ability to cross compile to targets like Android on macOS as it incorrectly detected stuff about the target linker using the host compiler, and as it is largely a black box the only real way to deal with this is to avoid 0.52.x forever (I filed an issue about this right as 0.52 came out but they failed to fix this serious regression until 0.53). And in languages other than C++? Ha ha ha omg they are all so horrible :(. I have been fighting for a month now trying to get a Rust library compiled to a static archive so I can link it into my project, and have nothing but a long list of bugs filed with upstream and workarounds for their broken build system to show for it, as in the end I finally decided it just wasn't worth dealing with anymore: bindgen passes the wrong target to clang for iOS (with no way to work around it as the person doing the compile, and often this happens in some deep dependency which makes overriding that really hard, as the build system believes it should be in charge of building dependencies), buildcc incorrectly mixes up HOST_CC and TARGET_CC when you are doing a cross compile to a target (such as CentOS 6) from a host (such as Ubuntu bionic) that shares a triple, the MinGW build not only tries to link against some entirely-wrong set of libraries that comes with Rust (they just last month shipped a broken fix for this that works in cases where you aren't passing a custom sysroot... but if you are doing MinGW seriously you have a custom sysroot so you can be compatible with MSYS2) but it also embeds into the archives parts of the target's standard libraries (which is just crazy: they apparently do this for MinGW, musl, and one other target), and I can't yet for the life of me get it to generate reproducible builds even for simpler packages (which is normally trivial with C++--yes, even with autoconf--I need to spend more time looking into this problem and filing issues about it, though).
- ezoe 6y agoThe autoconf checks if the build environment has a sane C compiler, standard C library, shell and command and all. At that time, well 30 years ago, it might be useful, but today, it's completely garbage. If the build environment found out to have an insane non standard conforming behaviours, there is nothing to do about it. And the autoconf's workaround implementation almost always won't work today in such an insane environment anyway. What I don't get is the autoconf failed to update it to the modern situation and still keeping the behaviour that is totally irrelevant and considered harmful today.