Why CMake sucks (2021)
twdev.blog
twdev.blog
Half of the post complains about syntax. In my opinion, that's irrelevant. If the `if() else() endif()` syntax is too hard to understand, good luck with modern software engineering, because you'll have to deal with many languages.
The "dealing with more complex projects" section actually shows a very simple project. IMO CMake should be just fine for that complexity, which encompasses most projects out there. If your project is too complex for CMake (and that happens, I don't deny it), then you are an exception, not the rule.
This said, the example creating a lib (lib/) and using it in a binary (exec/) in the very same project seems wrong (edit: I mean that the blog snippet seems wrong. Trying to have both lib/ and exec/ together is totally normal). I agree that `if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)` looks ugly, but I wouldn't blame CMake for that: I would refactor the CMakeLists instead, because it just seems wrong :).
"Weird function definitions" -> most of the time, functions are a coding smell to me. I always managed to not use them (or maybe I used one or two? I don't remember) and that's all fine. Projects that define a ton of functions get unreadable extremely quickly.
Admittedly, the syntax for installing the target is a bit weird. I wouldn't say it's impossible to get right, though. Usually it's similar to most of your other projects (so you essentially have to get it right once, then copy-paste), and it has to be done once per project. It's not that big of a deal.
Meson is cool, but I have seen messy Meson projects, like I have seen messy CMake projects. I wouldn't say Meson is that much better than CMake. And autotools is not that bad when done right.
Not only is this a bog standard thing to do, it's really really easy with cmake.
> refactor the CMakeLists
Precisely. This is a totally normal organization just done incredibly badly.
FWIW, a lot of complaining about syntax only looks like complaints about "syntax" to someone who already understands the tool. The problem with cmake is that it's underlying execution model is a huge frothing mess.
Is that all-caps thing a variable name or a string or a special token being passed to the function to make it do something special? What's the difference between a target and a rule again? What's the difference between a property and a variable again? When do I need to manually expand list elements and when don't I? How does All That Wrapping work when I just want to pass one -fno-this-bad-warning flag?!
To someone who knows cmake, all that fury sounds like someone complaining about mechanics. Cmake allows you to do all that stuff, just maybe with funny "syntax", so what's the problem?
The problem is that even those of us who have to use it professionally, regularly, Just Can't Understand The Thing at anything more than a superficial level, despite knowing all our other tools with depth and grace. That's the sign of a bad tool.
What is this `if (...)` function? Where is it defined? Why are some functions already there, while others I need to write myself? How does memory work when I just want to run computations with data? What is the difference between a primitive type and an object again? What the hell is an anonymous function?
I don't think it's that hard to learn the basics with CMake, and it's completely worth it when we have to use it professionally.
Cmake is its own universe of random conventions duck taped together, and is famously hated. It is a great tool in that cross-platform building of C/C++ programs is a very hard problem and it is the de facto choice for that since it can solve it, but that doesn’t make criticism of its abstractions/language less true. It really is terrible.
> If the `if() else() endif()` syntax is too hard to understand, good luck with modern software engineering, because you'll have to deal with many languages.
Coupled with:
> "Weird function definitions" -> most of the time, functions are a coding smell to me. I always managed to not use them (or maybe I used one or two? I don't remember) and that's all fine. Projects that define a ton of functions get unreadable extremely quickly.
is weird. If you can't handle a lot of functions, you'll struggle with many languages. If a lot of functions is a code smell, then the problem is with the language.
Let me kindly disagree :). You do not use a build system to write a complex program, you use it to call a compiler.
You could run your compiler manually, but it doesn't scale. You could write a shell/python/lua/etc script that scales better, but nobody else will know it (and chances are that nobody will want to learn about it).
By using a build system (autotools, cmake, meson, gradle, ...), you agree to use a standardized API to call your compiler. It doesn't really matter what API it is; what matters is that it is standardized: once you know it, you can build all the projects that use it.
Now it is true that CMake projects are often a mess. Either because it's used incorrectly, or because it's doing a lot of magic with custom functions (and therefore it looks more like a custom shell script than a CMake project).
Do I mean that CMake is perfect? Certainly not. But it doesn't suck either. And I see a whole lot of criticism coming from people who write messy CMakeLists. For a criticism to be constructive, it has to be informed.
But cmake has one overwhelming quality that overrides these: it won. Worse is better[1]. A united ecosystem behind a flawed tool is a hundred times better than a fractured ecosystem of utopian tools.
cmake has significantly improved over the last decade and continues to slowly chip away at its most pressing criticisms. Today it is 60% of what I want in a toolchain element. One day it will be 90% of what I want. And when that day comes I will be very happy with its ubiquity.
The latest Jetbrains survey has cmake usage at 57%, Bazel 3%, and Meson 2% [1]
Cmake isn't competing with Bazel and Meson, Bazel and Meson are interesting and worth talking about, but as a percentage of developer share they're irrelevant. Cmake is competing with legacy, the 33% of developers who still interact Make and VS Projects
I'm just in a very specific bubble, so I was curious what the others were.
Facebook, MS, Bloomberg, are heavy into CMake. Bloomberg notably so, and MS built vcpkg which is basically a CMake package distribution system. Netflix is mostly a Java/Scala house, and what C/C++ they do have sort of uses a "whatever" approach to build systems (variously, make, cmake, bazel, bash scripts, *gradle*).
"Where is CMake used" is a difficult question. Everywhere.
> Facebook [&c] are heavily into CMake
As an employee, I can tell you this is not accurate re: C++ dev at FB. I'm sure someone somewhere is using it heavily, but largely we use buck, our build system.
I'm not allergic to CMake. It seems fine. Ugly and a bit baroque, but it's hardly the only tool like that.
https://www.amazon.com/Autotools-Practioners-Autoconf-Automa...
Basically all of the decisions are based on decades of trying to support ever more features, backwards compatibility, many different hackers trying to keep it working for their own projects / companies, etc.
It is possible to use autotools nowadays without losing your mind. There is a "safe" path where things just work. I prefer it to CMake, but both are unwieldy beasts.
Only by punting the problems downstream.
"Oh, cross-compiling? Not my problem, ..."
GNU programs are the worst. Most of them you can't even build as a developer just by cloning their git repo and doing configure and make. When they ship a GNU program (e.g. GNU BIson or Make or whatever), there is a step that is done to produce the building version and that's what goes into the "official tarball" (now there is an antedeluvial practice right there).
To build as a deverloper working on the program, you have to run some "make boostrap" idiocy, which needs the correct version of AutoConf and AutoMake and whatevernot. Of course, every GNU program you boostrap wants different versions of these things, determined by what upstream is using.
Oh, git bisect to go backwards a few years? Different tools were used then; re-bootstrap with that ...
It's just insanity and AutoTools is at the heart of it.
I'm talking about cloning the program's git repo and working with that.
GNU programs don't include the generated configure script in their repos; you have to boostrap that first, and you need all the AutoCruft, in the correct versions which that git baseline of the program wants.
It's completely insane. It should be that to create a release of gnu-whatever-1.2.3 you just create a tarball directly out of git using the 1.2.3 version tag. That is the release. But that's not how it works; a release that doesn't require AutoTools has to be specially prepared.
Sometimes I have cheated to build a GNU program from sources. I would find the closest matching release tarball and unpack it over the cloned git repo, then run ./configure and all that. Carefully git-reset any differences and so on.
My total nightmare experience has been with CMake, with a project that mixed C and C++. IIRC it had to do with trying to get something to work on LLVM / macOS which it wasn't originally supported for.
(FD: CMake developer) I certainly understand a lot of the gripes that people have had, but the amount of tribal knowledge for obscure platform behaviors encoded in CMake is…vast. I am certainly in the "things need to improve" camp, but I don't think burning all the bridges that have been built is the way to go either.
The idea with autotools is that the generated configure script (and other assorted files) is supposed to be forwards and backwards compatible with different systems. It's not perfect, but the behaviour is mostly locked down at the time it is built, based on the particular set of macros it is generated with.
There are definitely aspects of this which don't work (it's nearly impossible to test, getting specific versions of autotools is presumably a PITA, and the make-in-bash-in-m4 language is deeply cursed), but the overall design does make some things better.
For example, if your project needs a specific version of cmake, your users will have to figure out how to install it, but if your project requires a specific version of autotools, only your developers need to install it.
(FWIW autotools is on my 'never again' list of technologies; it's incredibly cursed)
is really nice. I found it much easier to tell autotools how to find a library. Autotools made it intuitive to figure out what options were available (configure --help), and I never ran into trouble with my cmake version being too old.
But as a developer in c++ land, I much prefer cmake. It integrates very nicely with nearly all other c++ libraries out there. I think modern cmake targets do a nice job of encapsulating how to consume a dependency. And Cmake isn't restricted to only POSIX like platforms.
So I suppose it depends on who the target audience is.
For personal projects, the tool that that I can use fluently beats other tools every time. But when working in a team, that equation is different.
And cmake is the backbone of a lot of other build systems, being so popular. So it makes most Cpp projects straightforward to integrate.
I pull my hair out at this stuff too, but no more than any other tool required for configuring a workspace.
Rust benefits a bunch from second mover advantage here but cargo is just soooo good in comparison. Sane defaults, descriptive commands and stuff like cross compilation that can be hell-on-earth with CMake/etc I find actually easier in cargo + cc crate + build.rs for small/medium libraries.
The package manifest for rust projects isn't as straightforward as some imply, but yeah, better than cmake!
However the comparison isn't totally fair. When building a cmake project, it's muscle memory to go `cmake ..` out of source, then do it again and tab complete to choose the build options. That's 99% of the work I have to do when pulling dependencies.
If you want a turnkey package build, just use vcpkg for Cpp. And guess what, it'll sit right on top of cmake.
What TFA is talking about is a 5% or less workflow: making a new package from scratch when you don't have internet connectivity or don't have a bespoke cmakelists.txt to reference. Makes for a nice blog post, but that's not a common dev workflow.
- These people are replacing Make, while still using Make
- They're not clear on what problems of Make they're solving, specifically. And they have never read the manual, and don't know how to use Make
For 99% of the projects out there, some Makefiles are what you actually want. It isn't perfect, and has many well-known warts, but CMake is not a step forward.
CMake declare that it shields developer from knowing nuances of build systems and toolchains, but does it very badly.
set(PROJECT "ProjectTemplate") #this can't have spaces
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_BUILD_TYPE "Debug")
set(ARCH "x64")
set(PROJECT_ROOT "${CMAKE_CURRENT_LIST_DIR}/project")
set(PROJECT_SRC "${PROJECT_ROOT}/src")
set(PROJECT_INC "${PROJECT_ROOT}/include")
set(PROJECT_ASSETS "${PROJECT_ROOT}/assets")
set(PROJECT_LIBS "${PROJECT_ROOT}/libs") #third party libraries
set(SDL2_PATH "${PROJECT_LIBS}/SDL")
project(${PROJECT} C)
add_executable(${PROJECT} "${PROJECT_SRC}/main.c")
set(PROJECT_SOURCE_FILES "${PROJECT_SRC}/main.c")
target_sources(${PROJECT} PUBLIC ${PROJECT_SOURCE_FILES})
set(SDL2_INCLUDE_DIR "${SDL2_PATH}/include")
target_include_directories(${PROJECT} PUBLIC ${PROJECT_INC}
${SDL2_INCLUDE_DIR})
set(SDL2_LIBRARY "${SDL2_PATH}/lib/${ARCH}")
target_link_libraries(${PROJECT} "${SDL2_LIBRARY}/SDL2.lib"
"${SDL2_LIBRARY}/SDL2main.lib")
file(GLOB_RECURSE PROJECT_DLLS "${SDL2_LIBRARY}/SDL2.dll")
add_custom_command(TARGET ${PROJECT} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_DLLS}
"$<TARGET_FILE_DIR:${PROJECT}>")
if(EXISTS ${PROJECT_ASSETS})
add_custom_command(TARGET ${PROJECT} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_ASSETS}
"$<TARGET_FILE_DIR:${PROJECT}>/assets")
endif()
Is this the way it's supposed to be done? No. Is it setting someone's teeth on edge? Probably. Is it cross-platform compatible? No, but I don't need it to be, I just need it to build for the specific platform I'm using, which is Windows. Will it build? Yes, and that's all that matters.But I agree with the "keep things simple" (e.g. don't define custom functions), but I don't think that your snippet does that (ahem, I see `add_custom_command` there) :)
It's worth it when you're working on assets or lua scripts and want to import any changes for each rebuild.
./configure --prefix /usr/local
make -j$(nproc)
sudo make install
I learned these commands when I was 12 years old, at that time building a CMake project always seamed an impossible task to me, they are all different and not standard.Anyway at work I use CMake for the fact that I don't publish my software openly thus it doesn't really matter.
cmake --CMAKE_INSTALL_PREFIX=/usr/local -Bbuild -S.
cmake --build build --target install --parallel $(nproc)This is the number one reason people use CMake. It's a single binary that runs on every platform with no external dependencies, notably including Microsoft Windows. This makes it much more portable. CMake is itself a shell.
And so yeah, CMake sucks, just like all the other general purpose ones.
But the criticisms in this article are very superficial. I was expecting more technical and insightful.
CMake looks confusing because of its many predefined constants/variables/methods, all in SHOUTY_CASE but once you get past that, it seems to me like it's Good Enough™.
I think Meson is better than CMake in terms of syntax but it's not as popular (yet). It doesn't fix all the criticisms this article brings up but I found it nicer to work with.
If that doesn't suit you, you may like to look into Gradle; unlike CMake and friends, it doesn't invent a new programming language for its compilation, instead repurposing the Kotlin language for making dynamic build scripts. A very powerful setup if you want that level of the customisability.
I liken it to software processes and "research" code. Researchers are focused on their task at hand and things like TDD, sensible commits, releases, refactoring, not using magic numbers, etc. are all put to the wayside in the pursuit of their actual goal. "Regular" developers are very similar when it comes to their build systems and being "too creative" there is just as harmful.
FD: CMake developer
I used to work on a project that, at first glance, seemed like a perfect candidate for CMake: portable code, compiled with three different compilers (GCC, another GCC, and another GCC-ish for VxWorks) for four different platforms (x86 Linux, bare metal MIPS, FreeRTOS ARM Cortex M0, VxWorks ARM Cortex A53). It constantly felt like trying to shove a square peg into a round hole. Our developers would spend days in “CMake hell” regularly.
One issue we had was the verbosity. For us, a specific platform implied a specific architecture, a specific compiler, a specific operating system, specific auxiliary devices, etc. Having developers remember to do -DCMAKE_XXX half a dozen times for every build wasn’t realistic so we scripted it because CMake didn’t support the idea that a toolchain file wasn’t passed on the command line (that I’m aware of).
Warnings were another issue. Yes, yes, I know, you’re not supposed to declare warning flags in toolchain files. Too bad that doesn’t scale to many developers (same reason as above).
I also disliked that it generated recursive Makefiles. I could not find a way to beat this without changing the directory structure, which was for our project very important (certain portions of our code were standalone libraries only deliverable to certain customers, with different implementations for their specific platforms). This made builds SLOW. I flattened the Makefiles by hand once just for laughs and cut off 60% of our build time (a lot of the build system was networked drives mounted over NFS).
CMake isn’t that bad, though. For simple use cases, and small projects, it’s convenient. I just wouldn’t use it at scale for complex projects like above.
However, you're supposed to set the toolchain on the command line and toolchain files are only intended to specify what's necessary for the toolchain. Setting defaults is considered a bad thing.
You're supposed to use `-DCMAKE_TOOLCHAIN_FILE` to specify how to use a toolchain like this.
> I also disliked that it generated recursive Makefiles.
It doesn't make them in the "recursive make considered harmful" way. It is a static 3-depth graph (UI -> target graph -> target rules). Or you could use the Ninja generator.
FD: CMake developer
Also, autotools does not require the GNU file structure if you pass "foreign" to AM_INIT_AUTOMAKE. In this case, all you need is your configure.ac and your Makefile.am's.
FD: CMake developer
yeah, it's a real weird language, but i've been able to make it work for all sorts of weird things, from custom auto generation of documentation from comments in source to using obscure build tools to build extensions and bridges to/from proprietary software systems.
autotools solves portability across loads of unix variants with bizarre changes in their standard libraries, cmake solves portability across completely different platforms.
protip: buy the book. read it.
But these days a lot of those systems support CMake natively. E.g., Visual Studio can open CMake-based projects directly, you don't have to generate a VS project file. I'm curious as to how many people still use this capability directly; i.e., how many people use CMake to generate a platform-specific build file and then actually work with that file. I think probably the most common use for CMake is to generate a build file and then immediately build it. To probably 90% of CMake users, it would make no difference if CMake ran all the build commands itself, directly.
maybe you're right and the generator support will become less relevant, but when i think of cmake, i think of a build system generator that makes potential cross platform ports easier. support for generating IDE project files for multiple IDEs is a nice feature for developers as well.
[1] https://cmake.org/cmake/help/latest/manual/cmake-generators....
If it's clean, then I'm fine with basically everything, as long as it's not too exotic (it's annoying to have to learn one build system for one specific project).
I still find the bsd make (bmake for some people) and gnu make "fork" highly counter-productive.
It's a side of the GNU model which irks me: they take things which had a well understood pattern, perceive a problem with it, write a tool which MOSTLY occupies the same ground.. and then name it into the command-space to collide with the thing it's almost-but-not-entirely compatible with.
At least cmake didn't do that.
Seems like CMake configurations just kind of "happen" by trial and error, perhaps starting with a configuration copied from another project. It's not a language, it's a thing that you hack on to get the job done.
Another gripe is often when I look up "how to do X in CMake," the docs refer me to a feature that is more recent than the CMake packaged in common distros and for which there are few (no?) real world examples.
If somebody has a more constructivist approach to CMake, I'd like to try it.
FD: CMake developer
[1] https://cmake.org/cmake/help/latest/guide/tutorial/index.htm...
CMake 2.x and earlier weren't really that compelling - it was sort of a version of Make except with a macro-ish syntax and the ability to write your build rules for you. CMake 3 was a huge change in that it introduced build target properties - that's what all that `target_include_` and `target_link_` stuff is. Being able to attach build properties to target objects rather than having them sitting around in file scope made a huge difference in CMake's organizational power.
Also, as far as I know it's still the only build system that really integrates well with most IDE's. That's important if you're on a team of Windows devs but you're trying to add non-Windows builds.
But it seems like whenever I go to another compiled language I end up wishing I just had Maven. Extensible, widely adopted, builds + dependencies.
I remember autotools + make, and that didn’t do dependencies for me. CMake doesn’t look much better. NPM/Yarn/whatever is a mess too. I don’t even remember what Haskell uses. Go wasn’t bad but that was early days before dependencies were added (which was a problem in itself). I haven’t looked at it lately.
Standard repos. Standard dependencies. Standard layouts. Standard plugins. It can be a bit much, yeah it’s XML, and it’s over engineered for many projects. But I always seem to end up finding I hate Maven much less than whatever language X uses.
and the author wrote about it too: https://twdev.blog/2022/09/meson/
Now do I think CMake is perfect? No, certainly not. But syntax is the least of the issues with it. And it’s an enormous improvement on autotools in allowing you to improve portability of your build to Windows for e.g. - and worth saying that this was true before VS added CMake support.
Whenever I've had to use cmake as a user to compile a project, it never seemed to be doing anything more special than make (except, ooh, colours!).
Can someone explain what I'm missing?
autocrap, oh, sorry, autotools and CMake are software confguration systems, not build systems per se.
If you know your environment Makefiles are way to go.
If you need to build your portable software on 5 different OSes (and 3 versions of each of these OSes) with 6 different compilers... Good luck with Makefiles.
(Windows)
I open a console, make a build directory, and run cmake.exe, which generates MSVC project files. I open these in Visual Studio and already realize there's going to be a problem because the target is "Debug x86" even though I passed -DCMAKE_BUILD_TYPE=Release and this would be cross-compiled for Arm Cortex-M. (The vendor should have this in their CMakeLists.txt, so either they had a large misstep during an easy CMake step, CMake is not intuitive enough for use by a large semiconductor firm, or CMake failed to inform MSVC that the target is ARM.)
For shits and gigs, I press build. At least a dozen times: Unknown compiler.
(I have two different Arm toolchains... one contained in PATH, the other in a standard install directory.)
Now... into Configuration Manager, I change the platform to ARM, but the new error is "cannot open include file". Thanks, CMake... At this point, I can go into Project Properties, manually add the include directory, and proceed with trying to build. Last time I did this, there were more errors and missing files.
At some point, it's easier to just put all of the files in a single directory, create an .o out of anything that looks compilable, link it against anything that looks like a linker script, and try to compile a binary with all those objects and scripts.
-----
(WSL)
(The Arm toolchain is installed via package manager and is in my path.)
Running cmake .. -DCMAKE_BUILD_TYPE=Release (it really is a pain typing that with the shift key held, and it's too short for Caps Lock plus I've mapped Caps Lock to a bunch of AHK macros):
-Found assembler: /usr/bin/cc
Alright. Already, this is problematic. For completeness: "make" results in #warning Unsupported Architecture.At this point, I need to know enough about CMake to "create a toolchain file", according to StackOverflow. So I've done this---manually specifying arm-none-eabi-gcc as my compiler plus a few other possibly correct flags---but honestly, I have no idea, because CMake probably has more possible non-custom flags than mpv!
rm -rf build && mkdir build && build
cmake ... -DCMAKE_TOOLCHAIN_FILE:PATH=...
The correct compiler is detected, but I'm still getting "Unsupported Architecture". Wat?-----
I can run ccmake to try to fish out all the possible settings. When I change each of the tools to arm-none-eabi-*, I can't successfully configure (to exit ccmake) because of an error:
The C compiler
"/usr/bin/arm-none-eabi-gcc"
is not able to compile a simple test program.
...and eventually, undefined reference to _exitSo, I can probably get this to keep going by passing -k to gmake, but in ccmake (which oddly only sometimes will reset only a few of the previously changed settings, such as CMAKE_VERBOSE_MAKEFILE) I do not find the argument for passing a flag to make, so this is a dead end.
-----
Alternatively, I can dive into the manufacturer's CMakeLists.txt, but it's a rabbit hole. The base-level file is short:
cmake_min...
include(Config.cmake)
enable_language(C ASM)
project(...)
include(${CMAKE_CURRENT_LIST_DIR}/cmake/generated_src.cmake)
Config.cmake has one line: the path of the toolchain. I try /usr/bin and repeat. At this point, I wonder if every CMake expert has also deleted and recreated "build" three times by now. (Spoiler: this didn't change anything.)Along the other road, the cmake directory contains three cmake files. In one file, arm-none-eabi-gcc is hardcoded as the compiler (along with friends: ranlib, ar, objdump, etc), so the possibility of using armcc seems slim. In the second file, I see the flags that should stop all of the errors, such as -mcpu=cortex-m33 and the CMSIS include path and everything else. However, this isn't a standard variable name but something like MFRTOOL_CMAKE_CXX_FLAGS.
The manufacturer's (Windows-based) tool might clear all this up. Maybe not. But... Everything already exists in plaintext in the project directory to compile, if CMake could put the pieces together. Anyway, why use a CMakeLists.txt at all if you need an external tool? Why not have a better error message if a tool is required?
(The answer, of course, is that CMake requires more than cursory learning and---as with any unintuitive language---most users don't want to learn more than necessary or more than StackOverflowable. Plus, I can imagine the original CMakeLists.txt developer for this BSP doesn't have the resources to dump into getting this working with every Arm compiler on every host OS for every board in their repertoire.)
The final cmake file includes all source using GLOB_RECURSE. This tells me that my earlier intuition of moving all source into one directory and compiling "the old way" (a 20-line Makefile) would probably be the least stress and least rabbit holes.
-----
In the end, I don't know if I should blame the vendor, blame CMake, or blame myself and lack of tool knowledge. I DO know that I can throw together a Makefile in under 30 minutes and it will definitely take more than 30 minutes to get CMake to compile in either Windows or Linux.
-----
If I tell a person, "use the tools around my house plus this book to make an acoustic guitar" and they throw out the book and go straight to the metalworking tools to shape the body, I'd have serious doubts about their ability as a maker. This theoretical person is how I feel about CMake.
I have to explicitly (in a very verbose, clunky, uppercase flag format) tell CMake how to use my (very standard) tools to compile an essentially "hello world" CMSIS package. The author is right. It sucks.
That's a mistake. You need to always delete the command line argument cache, in case you intentionally omit arguments later:
rm -f CMakeCache.txt; cmake -DCMAKE_INSTALL_PREFIX=... .
> Autotools hell
Autotools are easier to use than people think: https://autotools.info/
We even have a script doing most of the maintenance work for us: https://github.com/stefantalpalaru/iccloader/blob/master/aut...
All the issues I had a year ago using CMAKE just went away with Microsoft CoPilot.