hot take: cmake would not exist if *nix people (i am including myself in that set) collectively took portability of software seriously. no, i do not consider "i kept adding preprocessor statements until it ran on AIX and then relied on a mixture of fear and guilt for everyone else to not touch them for the next decade" serious
@whitequark Yes and no.
As someone who tries his damn hardest to write portable software, and someone who also hates CMake and autotools and every single other build system generator under the sun so much that he wrote his own configure scripts by hand, complete with tests for OS idiosyncrasies and common lack of POSIX compliance, I can honestly tell you:
That shit is hard.
And I can't blame people who have more important code to write for choosing not to do that work and delegating it to a build system generator, even one as shitty as CMake.
I'm doing the portability dance myself because I value correctness above anything else and build system generators are not correct, and because I consider it a part of my skill set, one that I choose to hone. But it is a serious time and energy investment, and unrealistic to expect from every programmer.
If there is someone to blame, it is the various operating systems who just cannot get their shit together. Most OSes are super ugly and super behind and don't even make a decent attempt to follow the new standards. The big exception is Linux, which has its own huge problem: it can't stop growing nonportable interfaces to provide new functionality, so it fragments the Unix programmer pool even more. With one OS running too fast and the others lagging behind, it is getting more impossible to write portable code by the day. I have to divide my software between portable and Linux-only, and I hate it.
So, yeah. If you want people to stop relying on crap build system generators and care about portability again, you'll have to find a way to slow down the Unix fragmentation, let alone mend the rift. And if you're going to attempt to do that, I'm 💯 with you.
@ska yeah, that's why it's a "hot take". I essentially agree, although I think that from an end user perspective, portability needs to include Windows because if it doesn't, you still have to deal with it but now it is done in an ad-hoc, bug-ridden, incomplete way by a third party you don't have a good relationship with.
If you want people to stop relying on crap build system generators and care about portability again, you'll have to find a way to slow down the Unix fragmentation, let alone mend the rift. And if you're going to attempt to do that, I'm 💯 with you.
my tilting at this particular windmill has some examples; namely, using Wasm/WASI as a lowest-common-denominator platform plus architecture, then relying on others to make it runnable on every interesting platform. this barely works for batch applications like compilers, and does not work for most interactive applications, so it isn't exactly a solution for people who don't have Catherine-shaped problems (yet?)
@ska @whitequark I mean folks can just decline to use the perpetual flood of gratuitous Linuxisms. The benefits they offer are generally either someone's ideological quest or c100k stuff.
@dalias @ska this would be a reasonable take if POSIX was an actual standard that provided useful features with well-defined semantics instead of a rubber-stamped stack of paper not worth the bandwidth it took to transmit it, or if Unix (as a general concept we're all stuck in the mindset of, not specifically SysV) had an actual design instead of being a pile of ad-hoc junk barely held together with duct tape.
Unix: everything is a file!!1
also Unix: no memfd_create
it is a completely unserious attempt at OS engineering which does not deserve purism. extensions are what makes it actually useful for non-trivial applications. if you are fine with "no Linuxisms" you should probably just build your application into a WASI blob to make it even more portable
@whitequark cmake is one of the worse build systems, really. It cannot even install manpages.
@mirabilos at no point in my life have I wanted to write or install a manpage, so shrug
@whitequark Having used autoconf in anger (to build on linux-armel,linux-ppc,darwin-ppc, linux-x86, darwin-x86, and irix-mips) I am wary of any "take it seriously" being enough, at least if performance is important. There's only so much you can do when your endians, instruction sets, and c libraries are that different. I will say it was more than just preprocessor, it was also a bunch of "replace or wrap this mess" shims.
@AMS it is absolutely possible to abstract over endiannesses, instruction sets, and C libraries. Rust does it today; while some of the things it does (like "zero cost" abstractions) are enabled by newer computers, a lot of it is just giving enough of a fuck about what you're doing, and could've been done decades ago if we wanted to
@whitequark do you mean to say people would be using pure Makefiles instead?
@hikari not specifically that, though if you did have abstractions for all the various platforms you're using, your build system could be much simpler as a side effect
(i really don't like Make either, for unrelated reasons)
@whitequark But... CMake makes software less portable compared to auto*
It's a step backwards from automake/autoconf when it comes to portability.
CMake exists because someone looked at auto* and was like "This stuff is so complex it can be much simpler" and then proceeded to make a subset of Auto* features, and they've been adding ducktape and spit and now it's almost at feature parity of auto* it's more convoluted.
So now people are replacing IT without understanding why auto* ever existed.
@hp bullshit. autotools doesn't have a strategy for supporting software on Windows that isn't "drag an awful port of an outdated unix system with you"; cmake does. this is actually my #1 reason for having replaced autotools with cmake (generally, after soft-forking a project) before.
/Cinny
@whitequark @hp also have run into auto* software that refused to build on decently normal linux glibc targets because all of the cross-platform compat is vendored into a gigantic autogenerated shell file instead of being a tool that you can update separately
@charlotte @whitequark you can update it separately, you run autoreconf.
/Cinny
@hp @whitequark then what is the point with vendoring it if you need to manually update it for every project that is not new?
/Cinny
@hp @whitequark that is ignoring of course that the project might need bespoke old versions of autotools or host libraries in order for it to work correctly. last time i had to run autoreconf it silently didn’t expand an M4 macro into the final configure file
@whitequark if your definition of portable is "builds on windows and my Linux box" by that definition maybe cmake is easier. (Although given that to develop any software on windows you have to install gigabytes of stuff,.I don't see why bash is such a burden but whatever)
Cmake cross compilation basically doesn't work, and porting a cmake project to a target that the original author hadn't envisioned always requires changes to the build system itself.
With auto* that's generally not the case.
@hp I cross-compiled more cmake projects than I care to remember. take your FUD to someone who is less familiar with subject matter
@doragasu I don't know anybody who likes cmake, myself included
@charlotte Sure, it's not perfect. 😃
But in my experience it is much easier to get a very old auto* project to build (most of the time) than it is to get an old CMake project to build.
Especially on a target not explicitly supported by the original author.
You can totally mess up an auto* project as well of course. My general thesis is that is just easier to mess up a CMake project.
@whitequark I'm not saying you CAN'T do it.
But like, cross-compiling CMake projects generally speaking involves some kind of CMake wrapper. Like if I want to build a CMake project for Windows on my Linux box I end up using mingw64-cmake which sets a pile of stuff.
on auto* you tend to just do a --target and set a CC variable.
CMake just makes that harder, without the wrapper it is really hard to cross-compile a CMake project.
That's not FUD, I don't think.
@hp so generally you would supply a "toolchain file" via -DCMAKE_TOOLCHAIN_FILE= (like this one here https://github.com/YoWASP/clang/blob/develop/build.sh#L29-L47).
this is pretty much equivalent to setting a few environment variables. you can do the exact same thing for mingw64; I've never used a wrapper for something like that
@hp to demonstrate a point, here's me using it to cross-compile a Windows application:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
project(app C)
add_executable(app main.c)
main.c:
#include <stdio.h>
int main() {
puts("hello");
}
Toolchain-MinGW64.cmake:
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
set(CMAKE_LINKER x86_64-w64-mingw32-gcc)
terminal:
$ cmake . -DCMAKE_TOOLCHAIN_FILE=Toolchain-MinGW64.cmake
-- The C compiler identification is GNU 14.0.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/x86_64-w64-mingw32-gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done (0.2s)
-- Generating done (0.0s)
-- Build files have been written to: /home/whitequark/tt
0? whitequark@bluefin:~/tt
$ make
[ 50%] Building C object CMakeFiles/app.dir/main.c.obj
[100%] Linking C executable app.exe
[100%] Built target app
0? whitequark@bluefin:~/tt
$ wine app.exe
hello
@whitequark Maybe this is just a preference thing, but I personally think that
./configure CC=x86_64-w64-mingw32-gcc
Is easier. I can then just rely on auto* to figure out I'm trying to build on windows and what `ld` to use and such.
I personally think that those toolchain files are a step backwards. Especially since in my experience different project have different conventions for what needs to be in them to successfully cross-compile.
@whitequark That script you linked to as a whole, in my mind, should not exist. That whole thing should be behind ./configure.
I personally believe that if you need a custom build driver then something has GoneHorriblyWrong™
For me the fact that you have a build.sh to do a cross-compile vindicates my stance that CMake is bad at cross compiling 😃
@hp I have a build.sh to download an SDK from the web, you dolt
In my mind configuring the sub-projects should be done by the "main" configure. Your build.sh just takes the place of a main "./configure" and hardcodes it for one platform.
That is exactly what I meant originally. You're saying this is better than auto* but you're just writing a shell script that doesn't do what auto* would've done.
I'm not saying you're doing it wrong, I'm just saying that you wrote a wrapper around cmake to make it do what you want.
I didn't mean to piss you off. I'm sorry I did, it is difficult to ascertain tone in these short messages.
In my mind we were having a cordial disagreement. I very much apologize that what I wrote didn't reflect what was going in my mind.
Sorry for making the Internet a little worse for you today. It really was an accident.
@robryk @hp cmake's find_package facility, combined with the code below in the toolchain file, generally takes care of that when cross-compiling
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)