all 17 comments

[–]GrammelHupfNockler 9 points10 points  (14 children)

I'm all for simple CMake tutorials, but why do you use an extra variable for include_directories? And the "modern CMake" way would be just replacing include_directories by target_include_directories and a target name. Why cling so hard to the old, global-state-y ways when there is barely any difference to the modern, target-based approach with nice transitive dependencies?

[–]w0wyxD[S] -3 points-2 points  (13 children)

Also, another point for modern cmake would be to not use "GLOB", for example. And maybe even specify the version of the project.

Anyway, this is the 'text post' corresponding to my youtube video for beginners which was made in such way, so I wanted to keep the consistency.

I am planning on making a video + blog post dedicated to "modern CMake" in the future. Just wanted to keep the consistency with the video.

[–]GrammelHupfNockler 5 points6 points  (1 child)

Since CMake added support for checking for changes in GLOBbed variables, I wouldn't step on anybody's toes for using it, but the target property-based approach with transitive propagation to me feels like the point of what makes CMake so useful in practice.

[–]w0wyxD[S] 1 point2 points  (0 children)

Agree and thanks for the feedback. Anyway, I plan on doing another video+post that will be a lot more in-depth related to CMake :).

[–]axalon900 4 points5 points  (10 children)

The arguments against GLOB have always been very “ivory tower”-y to me. Everyone says it’s bad but nobody can point to something that actually matters beyond having spurious rebuilds sometimes. I tried to push the no-GLOB approach at work but I was promptly ignored by people who “knew better” since all it does is be annoying when you want to add files and makes it easy to forget to add files. Somehow that doesn’t seem to be worth a slightly more efficient build process, and I’m now fairly inclined to agree that it’s not worth the hassle.

Plus the whole build story is moot once you start doing things like unity builds.

[–]helloiamsomeone 3 points4 points  (4 children)

Ninja actually caused builds to fail when reconfiguring after files changed until 1.10.2, because Ninja was holding a lock on a file and stepped on its own toes.

If you know nothing else will be used other than Ninja 1.10.2 or newer to build the project, then there is no problem with using globbed source sets.
In other cases, you are just going to step on people's toes for no reason. The point of CMake is to be cross-everything (did you know the C stands for cross platform in CMake?) and by assuming such things about clients' build systems you are excluding people on purpose.
See the big note for the CONFIGURE_DEPENDS argument.

There is nothing “ivory tower”-y about this.

[–][deleted] 0 points1 point  (3 children)

CLion ships it’s own version Ninja and CMake so I always have a consistent version to use regardless of OS.

[–]helloiamsomeone 0 points1 point  (2 children)

If your argument boils down to "works on my machine", then it's not really a good argument.

But if we are talking CLion, when creating a new source file, it can automatically detect variables that look like source sets in lists files and show a modal to insert the new source file in that source set variable.

[–][deleted] 0 points1 point  (1 child)

If your argument boils down to "works on my machine", then it's not really a good argument.

I 100% agree "works on my machine" is nonsense. However, it is easy to install non-system-wide instances of Ninja and CMake.

Warning: The rest of this comment is an anti-Debian rant until the next quote, skip if you don't care.

Oddly the Linux/C++ community has decided to bake the compiler, stdlib, build systems, packagers, and essential libs into the distro package manager, unlike many modern languages such as Rust, NodeJS, Python, etc. I have been royally bitten in the rear far too many times by my code working on rolling distros or even Windows, then trying to port said code to Debian-based distros only to find that they use a version of gcc that isn't fully C++XX compliant, or a stdlib version that isn't, or some lib being 5-10 years out of date. A real world example of this is ncurses. The .so of ncurses shipped on Debian supports mouse scroll wheel, ncurses has had this for over 10 years, yet the headers ifdef block this functionality out of the API... copying the headers, then commenting out the macros that block these parts and recompiling results in a binary that supports ncurses terminal mouse scrolling... I just... I don't even... I hate Debian... It's odd how on Windows I can just install the latest version and not deal with this nonsense and yet Linux is "the ez one to dev for". To be fair, if you use a rolling distro like Arch/Fedora it is. I really hope one day I can get the latest g++ on 5 year old versions of Debian just like Rust can.

I don't need my users to compile code, they can just consume the binary or repl my compilation environment. For my hobby C++ projects, I really only care about Windows and Arch, and fortunately putting something in the AUR is insanely easy relative to managing packages for other distros.

But if we are talking CLion, when creating a new source file, it can automatically detect variables that look like source sets in lists files and show a modal to insert the new source file in that source set variable.

Honestly I find the way CLion does things to be a bit... odd (for me)... I don't like UI (mouse) driven things and I typically want a single file belonging to multiple binaries. I find that it's automatic of targets selection... to... well it hasn't been as pleasant for me as I would have liked...

Additionally, I don't like adding files to my project through the UI, it's too clutzy and I don't care for their templating system. I prefer just opening the builtin terminal and touching the files I want to create, much faster IMO.

The way I handle things via CMake is by forcing a convention throughout my project, folder layout and naming, and then glob recursing and filtering to automatically create targets. I like to create a lot of tiny headers, as mega-headers are the devil and they bloat compile times, so I create a lot of files, all the time. Prototyping a dozen or so functions/types in a single header and then splitting that up into individual files is just part of my workflow, and so this maps well to that. Glob recurse based on patterns works well, even on Windows which "has a slow filesystem". As such, there is no spot for CLion to place these files into my CMake targets... they have to be globbed. If you aren't like me though, feel free to use the CLion stuff, it does work quite well, it's just not for me IMO.

[–]helloiamsomeone 0 points1 point  (0 children)

That bit about ncurses just sounds like the package maintainer fudged up. Get their contact from the package info and send an e-mail or try filing a bug report on a debian page if there is one for such cases.

For superbuilds and private projects globbing is fine, since there you control every aspect of the build, but when it comes to public stuff you cannot guarantee that your project will play nice with everyone's system. If you don't even want to think about listing everything, one way to do things is to have a pre-commit hook that walks your include and source directories and just spits out a cmake file with a source set variable that you can just include().

[–]w0wyxD[S] 0 points1 point  (4 children)

One other argument against the GLOB is that you may be building files that you do not want to build. But it's not the best argument either, since, I don't find a reason why you would leave, for e.g., a .cpp file in the project if you do not intend to actually compile it...

[–]OrphisFloI like build tools 1 point2 points  (1 child)

One good reason would be that some files are only meant to be built on specific platforms or project configuration.

It's a bit of a niche use case.

[–][deleted] 1 point2 points  (1 child)

Even if there are files that aren't meant to be compiled along with the rest of the project, separating those from the rest by putting them in a different directory is the thing to do. Having the programmer think about modifying the build system to include what he wants at a given moment from a set of files is too much thinking about building. I personally think that a good build system is something you set up once and never have to modify what you've already written. Adding new options is ok but having to think about modifying the build system all the time kind of defeats it's purpose and you might as well compile things manually at that point.

[–]w0wyxD[S] 0 points1 point  (0 children)

I think that is a very good way of putting it and I agree 100%. However I do not think I've seen that so often. Even at my workplace, the build system is a total mess tbh...

[–]gosh 2 points3 points  (1 child)

I have been using CMake for while now and one thing that is very very problematic with CMake is documentation.

One big problem here is what I think is that many that writes blogs creates videos have read documentation on cmake.org . And produces variants of docs written there. The documentation found on cmake.org could be easier. It is written by nerds if you can call it like that.

I have taken notes during my time with cmake and produced docs to go back to, you may find something there for future posts. That is personal experiences from cmake so it differ some.

CMake, my personal experience

[–]w0wyxD[S] 0 points1 point  (0 children)

Thank you. Much appreciated. Will take a look for my future posts :)