Live data from Hacker News

CMake Part 1 – The Dark Arts

blog.feabhas.com

51–60 of 70 posts

Re: CMake Part 1 – The Dark Arts

#51
post #36

Earlier quoted context omitted.

> I think I had the best experience with Meson/Ninja so far. cmake lets you use ninja as the backend if that's your cup of tea. You can even set it to the default generator , by setting the CMAKE_GENERATOR environment variable to ninja. (I have no meson experience, so can't compare it). > I don't think that I have ever been able to successfully compile a project that uses CMake. That's quite the statement. In practic…

You missed the point. "__CLASSIC_C__" is not a thing (why they don't use __STDC__? I don't know, they don't seem to know either) and the syntax that they use inside that ifdef is.. not what people mean by classic C. It has been there for years and multiple people have pointed it out but they do not seem to care. The funny thing is that they do know how to use the pre-standard C argument syntax (as in https://gitlab.k…

> You missed the point. "__CLASSIC_C__" is not a thing (why they don't use __STDC__?

I dont know, I'm not going to defend it. Imnot going to do a line by line review of the file you picked, as I said I'm sure I can find awful code in bazel, meson, etc.

> Also, I have been told that cmake-generated Makefiles invoke cmake itself, so you can't really generate portable Makefiles with it.

Cmake generates a target for makefile that will re run cmake if your cmake file changes. If you're bukldong with cmake, you distribute the cmakelists txt, and treat the makefiles, ninja files etc as build intermediates

> In addition to that, I have been told that cmake takes ages to compile.

Do you compile your own make regularly? I've compiled cmake once or twice and it's not quick, but it's definitely doable (maybe 5 or so minutes?)

> I find that much better honestly.

The reason to use a build tool is to avoid hacks like that in user code. I would rather have cmake or meson or whatever my meta build tool is handle and test that logic, so I can focus on my library or application code.

Re: CMake Part 1 – The Dark Arts

#52
post #43
post #30

I wish all the CMake haters invested a fraction of their energy putting together a tool that they feel was superior to CMake, or at least a better alternatice. CMake has been around for a few decades, and perhaps a dozen alternative makefile generators and higher-level build systems already popped up, but still each and every single one of them failed miserably in gaining any traction. Why is that, given that CMake i…

Oh, there are tons of CMake replacements. There's a ?make for every letter of the alphabet. The problem is that C users can't agree on which one is the best. Whichever build system you pick, it will have detractors who think it's the worst and refuse to use it. I think CMake survives, because it got early traction from not ignoring Visual Studio like every one else, and survives by being the least objectionable (whic…

> -- Could NOT find ZLIB (missing: ZLIB_LIBRARY) (found version "1.2.8")

that liklely means that the headers were found but not the .so. For instance maybe you have a stale zlib.h in /usr/local, but not zlib-dev installed (thus no libz.so).

You can use cmake's --debug-find first to have more info, and if that's not enough, --trace / --trace-expand ; for instance the person who wrote the FindZLIB.cmake used in that case could have done something like:

    find_library(ZLIB_LIBRARY z)
    if(ZLIB_LIBRARY) 
      if(NOT /* logic to detect if the library has a specific symbol, for instance gzopen */) 
        unset(ZLIB_LIBRARY)
      endif()
    endif()
which would result in the above error message. The main problem being that the person who wrote that script did not add a small log output to indicate why a given .so was not considered valid.

Re: CMake Part 1 – The Dark Arts

#53
post #36

Earlier quoted context omitted.

> I think I had the best experience with Meson/Ninja so far. cmake lets you use ninja as the backend if that's your cup of tea. You can even set it to the default generator , by setting the CMAKE_GENERATOR environment variable to ninja. (I have no meson experience, so can't compare it). > I don't think that I have ever been able to successfully compile a project that uses CMake. That's quite the statement. In practic…

You missed the point. "__CLASSIC_C__" is not a thing (why they don't use __STDC__? I don't know, they don't seem to know either) and the syntax that they use inside that ifdef is.. not what people mean by classic C. It has been there for years and multiple people have pointed it out but they do not seem to care. The funny thing is that they do know how to use the pre-standard C argument syntax (as in https://gitlab.k…

>And then for CHECK_FUNCTION_EXISTS();, there are a few rare compilers that do not throw an error at compile-time if said function does not exist. check_function_exists() verifies that the symbol can be linked to rather than compile. That's why it gives it a bogus declaration of char CHECK_FUNCTION_EXISTS().

Funny enough I was trying to build a library yesterday that used check_function_exists() to detect the presence of some library functions. The project was set up to output a static library so check_function_exists() returned true for all the missing functions since it linked the test program without issue. https://gitlab.kitware.com/cmake/cmake/-/issues/18121

Re: CMake Part 1 – The Dark Arts

#54
post #44

"CMake, you say? Yeah, CMake is like smashing your face on high quality pavement. You can admire the stonework while the blood pours down your face." Pieter Hintjens, http://hintjens.com/blog:79

This. I'm stunned this kit was ever created with the shape it has, but even more stunned a second person agreed to use it.

It completely blows my mind that this demoware has made inroads anywhere.

Re: CMake Part 1 – The Dark Arts

#55
post #50

Earlier quoted context omitted.

> People: write simple, portable code! That isn't always how it works in practice, though. It's useful for your build system (or meta-build system) to be able to check for, say, C++17 support, and cause the build to fail early if this is missing. Similarly, you can use a tool like CMake to detect libraries. If a library is missing, you might want the build (or, rather the 'configure' stage) to instantly fail, or you…

>, you can use a tool like CMake to detect libraries. If a library is missing, you might want the build (or, rather the 'configure' stage) to instantly fail, or you might want to build with certain features removed to cope with the library being missing. CMake supports both, as does autotools. The gp enriquto had a rigid stance on so-called "optional" libraries. If the library is not there, the build should fail and…

Hey! I remember that interaction (and sorry for my crass language, I was having a hard time by then).

Your explanation was certainly satisfactory. Now I understand a bit the motivation of people who want to compile different programs depending on what happens to be installed at a particular moment in their computers. I still think that it is "an exceptionally bad idea which could only have originated in California" ;)

Re: CMake Part 1 – The Dark Arts

#56
I had my first real exposure to CMake earlier this year.

It demos beautifully, but quickly becomes an outrageous collection of side quests to find the secret key.

What collection of hidden methods, global constants, environmental variables and insane incantations must I assemble to cross compile this software?

None. The answer is, None.

The best I was able to find, was get the whole artifice running on your actual workstation, then get it (and an entirely different tool chain, including IDE's?!!) up and running on each target platform, dust off your sneakers to go sit in front of another computer, fire up an IDE and find it's build button.

I know it's not, but CMake somehow manages to feel like a solution created by hand wringing, cat petting, volcano living, mustachioed, cigar-smoking proprietary OS and IDE vendors.

OTOH, zig cc leaves me with a single tear of joy and wonder sliding down my cheek like a framed Velvet Elvis.

Update: Also, premake isn't terrible.

Re: CMake Part 1 – The Dark Arts

#57

This is a pretty nice article. CMake is a pretty nice tool and this is a good article for its good parts. One thing I *hate* with build systems is having to enumerate all of my files. I have a file system. It knows about the files. If I organize my code appropriately (say a lib, inc, and prog directory) the organization says how to build the source code. I often make my build system support finding all the files in d…

The main reason why not enumerating all the files in the build system is a bad idea is that the build system won't know to rerun itself and re-scan dependencies after you added a file. If you do enumerate the files, you need to change a build system file to add an entry for the new source code file, and that tells the build system to rerun itself and re-scan dependencies. And in the grand order of things, adding a fi…

Couldn't a build system use a hash of the accumulated files as a cache key and rebuild it's internal state when that changes?

I'm not seeing a big downside, but maybe I'm missing something obvious.

Re: CMake Part 1 – The Dark Arts

#58
post #25

Earlier quoted context omitted.

Maybe it wasn't your intention, but your comment is the most scathing critique I've ever read of cmake. Boilerplate code and "compiler checks" are strongly negative anti-patterns. Maybe the worst in programming. That cmake makes it easy to do these awful things just shows how evil it is! People: write simple, portable code!

I'm not sure you understood what I've said at all. CMake eliminates boilerplate code and compiler checks. They do not exist, at all. With CMake you state that you have a C++11/14/17/20 project, it builds N static/shared libs and M executables, you set dependencies, and you're done. They do exist in Makefile projects because Makefiles only define the DAG for the build, and don't perform any sanity check at all. So if…

> Checking if the compiler you're using supports a specific version of C++ is not evil or superfluous.

It is both evil and superfluous. It is evil because you should be writing portable code and do not depend on compiler specificities. It is superfluous because if you do not check, the compilation will still fail, which is precisely the expected behaviour.

> How exactly do you think simple, portable code is done?

By writing it carefully and testing it on different systems. You test with -Wall -Wextra -Werror -pedantic on all systems but you distribute the Makefile without these compiler flags.

> Do you expect code to compile on different platforms by magic?

No, of course. At first you will have a few linuxisms or macOS-isms, that you will gradually remove through a few rounds of multi-platform testing (which is free and easy to do nowadays).

Re: CMake Part 1 – The Dark Arts

#59
Some time ago, I - a seasoned C++ and Python developer - became part of a team, redesigning build and deployment aspects of a complete embedded code landscape, embracing a lot of developmental activities, projects, whole product lines etc..

I think most people who recommend alternatives completely underestimate the degree and extent of specific compiler, tool, library, IDE, and general native-build environment knowledge that CMake has swallowed and incorporated over its years of existence and continues to do so. Including all these quirks & particularities of the endless number of components, software artifacts and tools it handles. This is the whole reason for his success and the one thing no swift, elegant, new-paradigm new player can surpass short-, mid- or - in some cases - even long-term.

Most of the time you can tell the real experience of someone judging CMake simply by his kind of troubles with it. Admittedly, the syntax is ugly and often inconsistent. Consider a list 'alist' and depending on context you can or must reference it as either alist, ${alist} or "${alist}" - terrible, true. The most complex data type is aforementioned list, often as under pain bearable nested variant. Math is cumbersome, no unicode support for string manipulations like positions, length calculations, the list is going on seemingly ad infinitum.

But you can learn this rather quickly and when you write CMake code for some weeks you will become accustomed to it. In the meantime, other levels of annoyances begin to appear. For example, the allowed context of generator expressions is inconsistent, incomplete and sometimes - from a cmake writers point of use - almost artificially limited. Take add_custom_command: It allows for GE's in his DEPENDS and also COMMAND sections - but not as argument for OUTPUT. But wait, starting with CMake 3.20 it does, but:

" Arguments to OUTPUT may use a restricted set of generator expressions. Target-dependent expressions are not permitted. "

Unfortunately, those are often exactly what the developer is looking for. Reason here is as in many cases the deeply ingrained two-pass configure-generator nature of CMake.

For any real project, state becomes quickly important. Diving through many levels of sub directories and maintaining/conveying information between the associated CMake projects becomes far from trivial in no time. And no, cache variables are not the solution.

Another issue is the interaction with higher languages in CMake code. Most people start quickly with execute_process(${MY_PYTHON} ...) in order to handle more challenging topics. Problem is the lack of smooth communication of the results without workarounds like temp files, whatever else.

Also, any dependency requirements not covered by the standard cases, might it affect rebuilds, reconfigures or regenerations, requires deeper knowledge of CMake's actual dependency resolution mechanisms. Often only inspecting his time-stamping bookkeeping or exploiting his trace / graphviz / file-api output will help here (neglecting source code inspection, this is rather rarely required).

In principle, the task requires a fully-fledged programming language - but containing all the accumulated knowledge of CMake about his subjects.

Not an advertisment, but for any beginner I can only recommend Craig's book

https://crascit.com/professional-cmake/

It continously integrates changes from new versions. He is also always helpful in CMakes own discourse forum and gitlab issue tracker.

Re: CMake Part 1 – The Dark Arts

#60
post #9

Earlier quoted context omitted.

I've been burnt by that convention pretty regularly: (1) build automatically scans and adds all files in a directory (2) I write a quick script foo.py in the directory to check something (3) Boom, binary contains foo.py I try to manually enumerate all files whenever I touch a build file.

A better solution is to a checkout of your build, then you wont have foo.py and you can be sure you haven't missed anything.

That would work only if you always build after committing all your changes, which is IMHO another anti-pattern.
Post reply on HN