This is by far the best CMake video on the internet. After watching this, I went back and cleaned up my terrible CMake build scripts. I really hope this isn't the only good video we will ever get on CMake.
Altthough the project you referenced covers a lot of of topics, it does not consequently use Modern CMake. Example #1: add_library is explicitly called via STATIC/SHARED (one should use BUILD_SHARED_LIBS) Otherwise one can get problems with transitive dependencies. Example #2: Variables from the FindBoost module are used instead of targets. etc. I've found CGold (cgold.readthedocs.io) very useful, though the author sadly didn't finish the documentation. Nonetheless the information included in CGold is very valueable, imo.
This highlights the lack of good onboarding tutorials for CMake. I have just been ramping up on all the easily accessible tutorials but they target 2.8x generation but the latest CMake 3.8.x is a different paradigm. It is updating faster than the documentation and tutorials. Definitely need more talks like this. I'm off to rewrite my CMake scripts.
A big problem of almost everything in developer land at the moment. The documentation pages is fine, but again as usual, it is lacking the overall design explaination document.
Yes, it's still the same old tutorial. Kitware should really remove that (together with the outdated wiki - I refuse to link to it here) and link to the latest documentation cmake.org/cmake/help/latest instead. Can anyone tell something about the quality of the latest version of the "Mastering CMake" book covering CMake v3.1? I am afraid that book is also outdated and contains a lot of information related to v2.x.
True. CMake v3.1 has been released on 2014-12-17, so it is almost three years old. Since I haven't read the book, I can't judge it. The current stable version is 3.9.4 though, to be fair.
Excellent video! (Video/audio quality, content, etc). Internet is full of obsolete documentation about CMake. I would really love if people start writing CMake files using this modern approach.
It's videos like this that remind me why Meson has been getting so much headwind as of late. CMake and Meson are so similar, except that Meson has great guides for learning from the ground up. If this video is too complex, Meson might be the ideal way to learn CMake.
Holy shit. This was way over my head. I personally don't think this is a tutorial video into CMake. It felt more like "hey CMake 2.8 guys. This is how we changed in 3.8". When this comment is over 1 year old, and if CMake is still version 3, reply to my comment whether I can do CMake. As of 2018 October 11, the 3.13.0-rc1 is ready for testing. I'll go grab some tears and look for version-friendly CMake tutorial first.
If you're still working on C++, yes, CMake is still like this. It's great. It's a little bit more to learn and a little bit more setup initially, but _dang_ if it makes everything else way simpler! Even upgrading existing old CMake to target properties, despite being more annoying than doing it that way from the start, feels like such a breath of fresh air! No more "Make the library in _this_ CMake build and re-create all that same dependency info in _each one_ of the other CMake builds that needs this library"! No more "_ROOT" environment variables everywhere!
"This is really straightforward!" *barfulous list of arcane runes follows* Truly a disgrace in every sense. I'll be reporting as a bug whenever packages _do_ support cmake.
The people in the audience seem like they're trying to fight his recommendations every step of the way lol I'm glad to see most projects have taken this advice into consideration in the years since this talk
I understand the need of not deprecation, but i would love that cmake and c++ compilers using optional deprecation so recent projects can be forced to use the lastest/modern features.
That's absolutely possible, but to do that right now you have to 1) setup the appropriate compiler warnings and add "-Werror"/"/WX" in your CI, which will already be very helpful, and 2) integrate clang-tidy (see 1:15:23) into your CI setup. From the zillion CppCon videos I watched, the reason of the comittee to take time making this kind of behavior standard is that the industry everywhere needs the many immense and critically important existing codebases that make use of bad C++ stuff. So they want to avoid breaking compatibility as much as is reasonable, so they often have to take the careful approach. The standard comittee keep saying that eventually the standard will require, by default, for compilers to disable the bad bits of C++ and only allow them when explicitly enabled somehow. To be sure, it's been a number of years they've been saying that, but at least I'm incredibly grateful we have things like compiler warnings and nowadays have clang-tidy. This requires some setup, which is annoying, but at least for a real-world project you *_can_* get the safety if you care enough about it or if you're interested enough about writing good C++. For example, "-Wmisleading-indentation" warns about, well, misleading indentations, such as in the case of the famous 'goto fail' Apple bug. With both "-Werror" and "-Wmisleading-indentation" in your CI, you will never let misleasing indentations through to production again --at least not on GCC or Clang, since MSVC would require different flags! In a way, because it's the project that chooses its own language safety rules via compiler warnings/clang-tidy checks, it means the project is able to enforce its own set of guidelines if needed. For example, a project's team might decide to implement a clang-tidy check that warns on every use of known heap allocation APIs (new/delete/malloc/free/my_custom_alloc/etc.), which makes sense if the project is meant to run on embedded systems that are not required to have a heap at all. The team might add this check to their CI setup, with warnings treated as errors inside the ".clang-tidy" file, to automatically reject any pull request that attempts to add a call to one of these allocation/deallocation APIs. This means, in a way, that they've just implemented their own "version" of C++, as if they had added the words _"Any use of new/delete/etc. is ill-formed"_ at the end of the C++ standard that they're using.
"you can just add a simple include file, or you can mess with this gross list of arcane incantations with random runes that come out of nowhere and do god knows what" No I don't think I will. Old cmake is way less terrible than modern cmake.
Great video...! I think, learning CMake is more difficult than learning C++ itself :/ Even if C++ is difficult, we at least have definitive learning material for it...
I was trying on and off to keep in touch with C++ for about 7 years, despite hating some of its language features like I have to watch a 90 minutes video on trivial things like object initialization. This coupled with confusing features like collapsible references etc, lack of library management tools etc kept me at the bay. Then latest projects started using this insanity called CMake. That was the final nail in the coffin.
I could really use a tutorial before I grok this lecture. The only easy tutorial that I found so far has taught me everything that this guy says I shouldn't use. Harumpf. So where is the gentle introduction to the right way to do things?
A lack of up-to-date documentation is the big issue with CMake as you will have read many times already, but maybe these two sites can help a bit: cliutils.gitlab.io/modern-cmake/ cgold.readthedocs.io/en/latest/
I worked with a medium sized code base that uses recursive Make. I am having difficulty selling(older C-developers) anything to allow parallel compiling. Any tips or tools on moving something like this to CMake. Love Clion!!!
Why is using make in parallel compiling a problem? It does this very well with -j option? Selling CMake is hard if you are not multiplatform and/or users want use modern IDE's.
The best way to convince salty old engineers is to dig in, do the work, show that it works, and also show how it can improve their lives (i.e. adding value). So for example, moving to Cmake would make it easy to import the project into qt creator and use a graphical debugger that really works. Adding the compile_commands property will enable code completion plugins like YouCompleteMe, it's also a parseable index of how an object was really compiled, which makes it really easy way to track down build flag disputes, or just copy paste to rebuild an object on the CLI. Transparent use of ninja to parallelize the build. Having multiple build targets for Clang's static analyzers that improve code quality. The list goes on.
What happens if all your target needs to link to the same library, wouldn't it be easier to use `link_libraries()` instead of `target_link_libraries()`
Not really. It's like using global variables in C/C++: it makes it easier to _write_ the code intially, but not to _read_ it and not to _change_ it later. As the CMake project grows, I'd much rather read self-contained code that does one thing and one thing only, even if that code is a bit longer (like a long-ish function that only has local variables), rather than having to run through dozens of CMake files that all perform global operations like link_libraries() everywhere (like a somewhat smaller but terrible function that keeps reading/writing global variables from lots of different places). It's definitely not that bad on small projects, but for larger ones it can get quite terrible! And I personally value the little sanity I have left :') Plus, with link_libraries() you don't get the incredible automatic dependency info that target_link_libraries() provides and that this presentation talks about. With link_libraries(), you have to essentially re-create the dependency information (include dirs, other libraries needed, etc) that the library you use has, whereas with target_link_libraries() you shouldn't. So if your library, A, needs library B, with target_link_libraries(A PUBLIC B) you shouldn't need to know/specify anything else. With link_libraries() though, you will need to specify link_libraries(B), you will have to also specify link_libraries(C) if B needs a library called C, you will have to do link_directories(path/to/B/include), you will have to do add_definitions(macro=value) if B needs macros, etc.
I don' understand why shouldn't we require ISO C++17 for example, but lambdas etc. I want to use VS2017 in C++17 mode, and passing one of the features I need just to get everything seems kinda hacky. I would much rather say I want ALL of C++17 and continue building my library.
Exactly, just use something such as target_compile_features(mylib PUBLIC cxx_std_11) (cmake.org/cmake/help/latest/manual/cmake-compile-features.7.html#requiring-language-standards). I find it much easier to use too, since I do not need to manually synchronise the required features in the build file with the features used in the C++ source files.
Dude unironically telling you to write in a list of implementation details in your cmakelists, absolutely bonkers. "Code against an interface, not an implementation, except in your build system."
If i want to trigger my build system to see a new file from file(GLOB) i just manually re invoke Cmake to 'update' my build system, We need do that even without file(GLOB) after the file was added. So, i don't see nothing bad in file(GLOB)
@@HarinduDilshan It is very different. One requires you to keep a running list of files you add/remove in your head as you work on a new feature(or use git to help a little, granted) or preemptively add a bunch of empty, anticipated files. Just so you can then type out those new files by hand into the correct spots your CMake. All of that is very error-prone and distracting(breaking flow). While file(GLOB) just requires you to manually re-enter the same command. Literally Up Arrow, then Enter in most cases. None of the reasons I've heard for while they can't get rid of this issue make any sense either. If they are already generating make files that automatically retrigger when CMakeLists changes, why can't they do the same thing with another file called SourceList that are just plain old lists? That way IDE's can easily just auto-populate the list, adjusted as their project tree changes. Someone, please tell me why this wouldn't work.
@@thanatos454 In cmake 3.12 they added CONFIGURE_DEPENDS to file(GLOB ...) so it can check at build time, so you don't even have to manually check. They say it adds to the build time though. I disagree with you that the typing of the files is error prone because you'll generally know if a file is not recognized anyway.
Would it make sense to have an "always call cmake" first to the target build system to make sure it is always up to date especially for globing calls? Store the globs in a sorted file for comparison, only update if there is a change. Seems like monitoring directory for new content is a legitimate set of functionality for a build system and for a tool supposedly to help bridge gaps between them.
@thegod3500 I think there are a lot of people on both sides of the issue. The CMake maintainers, and others generally seem to strongly discourage file(GLOB) (even with the newer CONFIGURE_DEPENDS) for source files to allow supporting all generators and for a number of other reasons, while many others encourage it to avoid forgetting stuff.
No. "Foo" before the "::" represents the project/package name, and "Foo" after the "::" represents the library/executable name. If you have a package that exports two libraries/executables, you could have "Foo::server" and "Foo::client" for example. However, this is just a suggestion; you can use whatever name you want. The "::" is not mandatory; this talk only suggests doing so, and for good reasons.
11:45 "Create macros to wrap commands that have output parameters. Otherwise create a function. " This isn't very clear at first sight. Because if you know the names of output variables and wants to foward it to the caller you can just set PARENT_SCOPE. I'd say you only need the macro when you don't know what the names of output parameters are and you want to forward them to the caller. An example would be all the global variables that come from calling find_package.
I think I agree. These are, of course, guidelines, not absolute rules. However, using a macro is still avisable in many cases even when you do know what the output variables are, since mis-setting variables is a bug that's always around the corner in CMake, especially if you want your codebase to remain actively developed for many years and you/someone might add/remove variables someday.
Ah yes, everything is so "straightforward" that we need an obscene amount of explanations before being able to setup something simple. This presentation is clearly aimed at people who are already familiar with CMake. If you're just trying to figure out your particular situation and found that you need to learn CMake, this presentation won't help you much. You're better off finding something more tutorial-like... except that most content out there is giving obsolete "advice" for obsolete CMake versions... It's amazing that all of this crap has not been automated as part of IDEs in some way. Really... wth.
Agree 110%! I would love to have a command line tool which entirely automates this with best practices. Something like: > cmake-tool init cmake-tool create cmake-tool add-package
"except that most content out there is giving obsolete "advice" for obsolete CMake versions..." Yeah except all that advice is telling you things like "to frabulate your build, you just do set(FRABULATE_BUILD ON)" meanwhile all the "modern cmake" bozos are like "ah yes this is really straightforward, not hard like it used to be in old cmake, what you do now is include(CMAKE_BUILD_FRABULATION) target(foo PRIVATE interface SET $
This is rather confusing as an onboarding video. Is there a good 3.x tutorial document or book? The talk is frustrating in that it introduced some powerful concepts of CMake without enough background to employ them.
Never had good experience with CMake - it is not really "cross-platform" - you always need to tweak something when you change from Linux to MacOS to whatever you use :(
I've did the same. I've added a CMake convention-over-configuration framework using CMake modules that is added to each of my C++ components as a submodule (each component is either one application or one library together with optional tests and examples). With that approach I only have a very slim CMakeLists.txt that does contain the dependencies and source files only. Yes, I need to use variables to achieve this, but at least I do not have to maintain copy-&-pasted boilerplate code. I've already added integration (using strong assumptions, but still being flexible) for Doxygen, Protocol Buffers, Google Test, cloc, Flawfinder, etc. Future tasks include addition of other static analyse tools as well as code coverage and so on. IMO it's sad that everyone has to built its own solution and that CMake does not provide (optional) stronger assumptions how-to structure and build a C++ component. Package Management is also still an issue.
@@FlorianWolters85 ". Yes, I need to use variables to achieve this, " Literally every cmakelists.txt I've seen uses a bunch of variables. This "modern cmake" everyone seems to talk about seems like a unicorn that exists only in people's heads.
This fellow clearly knows what he's talking about and could be considered a subject matter expert, but it seems to me he's an utterly incompetent presenter. He utilizes details before he describes them, goes off into unnecessary tangents without making it clear he's doing so, and presents sections of script files without labeling them or mentioning where they go, all of which force the confused audience members to interrupt with questions that should have been unnecessary. I can see this being useful and informative to a certain subset of CMake users who are sufficiently up-to-speed to intuitively understand the contextual information he leaves out (eg. what file he's showing the contents of on his slide), but there's an inconsistency of assumption of prior knowledge, given that the talk starts out with very basic syntax -- anyone who could benefit from the first few minutes will get nothing from any of the content beyond that. Despite having used CMake 3.x for over a year now I am so far understanding very little of the bulk of this talk. If he wants to promote CMake as excessively baroque and complicated to those not already well-versed in its use, this presentation works well for that purpose.
Having watched this in its entirety, I respectfully disagree with you wholeheartedly and think his presentation still is great. The talk is "Effective CMake". Not "Cmake 101" and your point about this having useful information for CMake users "sufficiently up to speed" is completely correct and seemingly intentional. If you've used 3.x for over a year and understand "very little of the bulk of this talk" I don't believe any talk will help you.
CMake is dominant and plain horrible. Its "language" is an example of how to not design programming languages. It is a good idea to switch to Lua, Python, JavaScript or any other modern scripting programming language. And yes, I want Turing completeness in the build system.
If something is unclear - ask. Because if you don;t you could fail do understand the rest. And then we have developers who are afraid to admit they dont understant and project that onto new people creating more and more problems with less and less maintainable solutions.
The idea that you should put in feature flags instead of specifying the standard version is absurd. The feature's you're using are an _implementation detail_ of your target; the standard is the _interface._ Depend on the interface, not on the implementation detail. The more I learn about this vaunted "modern cmake" the more it looks like a downgrade over the old one.
"At least this is straightforward :)" .. What about any of that is straightforward? You just laid out a bunch of random incantations filled with names that are themselves random incantations. Where did you define "footargets"? How would one even know what to write? It's not boilerplate, it's _runes._
Bloody hell; why're you defining another language to compile the language you actually care about? And please, C++ community, fix your versioning standards: [major.minor.patch.whatever-the-hell-you-want] is _not_ hard.
Can't wait for Rust to replace C++ in all new developments. The dependency management of C++ is primitive and out of date. There are no benefits. C++ itself also struggles with legacy design problems. There is no valid reason to use C++, except for "the project already is C++".
Not too familiar with Rust myself aside from watching a few hours' worth of presentations on it, but I keep hearing good things about it (e.g. StackOverflow's surveys made it the #1 most loved language for a few years now). On the other hand though, "the project already is C++" is just **soooooo** common that "replacing C++" would probably take decades; we'd have to be both C++ _and_ Rust experts for the majority of our careers if we don't want to lock ourselves in "Rust-only projects" and want to benefit from the higher salary which projects that need developers that know _both_ would definitely give in this scenario. Think about this for example: C++ has been superseding the vast majority of use-cases of C for 30+ years, and yet C is still here even though C++ is mostly backward-compatible... All your basic user-space Linux libaries and executables, like bash, the libc, system headers, OpenGL, BLAS, QEMU, as well as the Linux kernel, and so forth, are made in C, not C++ (with or without good reason is another question), so you still have to occasionally manage reading/writing C. Imagine how long it would take to "replace C++" with a language that isn't even really backward-compatible with C++ and therefore have to more or less "restart" entire dozen/hundred-million-dollar projects for the sake of using a newer language! Or we could go halfway and do major compatibility work to have both Rust _and_ C++ live in the same codebase, meaning you would need a lot of developers that need to know _both_ very well. How would we convince people who pay us that this is the right way to go? Note that I'm not implying that "staying with C++ is great and that moving to Rust is bad"; I'm just pointing out that all options are imperfect to a varying degree. Sometimes we just see that "option A is bad" and choose option B, which might be just as bad. It's all about tradeoffs; this is engineering after all! Perhaps one thing going Rust's way is that Linux now allows writing drivers in it. It's not the whole kernel that's going to see Rust right now (if ever) however, but how this turns out is going to be interesting. Will developing the kernel one day require its developers to know both C and Rust, or will the kernel just always stay in C forever? I remember when Google launched the Carbon language a couple of years ago, which was designed to be easily compatible with C++ to support gradual adoption in the codebase. However, I don't think Carbon gained much traction; I haven't heard about it again since. _However, the emergence of languages like Rust might prompt quicker and more pragmatic development of C++._ Let's just hope that C++ standard development is not so quick that the new C++ features are only half-usable immediately after standardization! Perhaps another, more reasonable option, is what Herb Sutter is doing: writing a "Cpp2" language that gets transpiled into normal C++, like TypeScript is to JavaScript. Since this is a whole new language, you don't need to preserve compatibility with anything, so you can redo the defaults, plus you can always just grab the transpiled C++ if it Cpp2 doesn't work out and you want to go back to plain C++. I have yet to hear about large projects adopting this though.
00:03:40 - Organization
00:05:05 - Commands
00:05:55 - Variables
00:06:45 - Comments
00:07:35 - Generator Expressions
00:08:20 - Custom commands
00:09:08 - Custom command: Function
00:10:27 - Custom command: Macro
00:11:25 - Custom command: Guideline
00:11:50 - Evolving CMake Code
00:12:22 - Deprecate CMake commands
00:12:45 - Deprecate CMake variables
00:13:39 - Evolving CMake Note
00:13:47 - Targets and Properties
00:14:55 - Targets and Properties Notes
00:17:22 - Imagine Targets as Objects
00:18:23 - Commands to forget
00:19:07 - Example
00:20:37 - Don't use CMAKE_CXX_FLAGS
00:22:07 - Build Specification and Usage Requirements
00:23:09 - Use target_link_libraries()
00:24:15 - Use target_link_libraries() example
00:28:09 - Pure usage requirements
00:29:16 - Don't abuse requirements
00:29:33 - Project Boundaries (how to use external libraries)
00:30:55 - FindFoo.cmake
00:33:30 - FindPNG.cmake (massive file)
00:34:35 - Guideline on Find
00:37:35 - Export your library interface
00:39:31 - Export your library interface (continued)
00:43:40 - Export the right information
00:44:48 - Creating Packages
00:44:59 - CPack
00:45:44 - Write your own CPackConfig.cmake
00:46:18 - CPack Secret
00:46:50 - Packaging multiple configurations
00:48:58 - Package Management
00:49:10 - Requirements
00:50:31 - How to use external libraries
00:50:51 - Do not require any changes to my projects
00:52:08 - Use the your public interface
00:52:35 - Guideline on export
00:52:38 - The toplevel super-project
00:55:38 - How does that work?
00:58:09 - CTest
00:58:13 - How to run
01:00:35 - CTest guideline
01:00:46 - Filtering tests by name
01:01:37 - CTest guideline
01:01:41 - Fail to compile
01:03:03 - Running crosscompiled tests
01:03:46 - Run tests on real hardware
01:04:03 - Cross Compiling Toolchain.cmake
01:04:44 - Toolchain guideline
01:04:58 - Static Analysis
01:05:11 - Question
01:06:15 - How do you treat build errors?
01:06:30 - Treat warnings as errors!
01:06:54 - -Werror causes pain
01:07:36 - Better: Treat new warnings as errors
01:08:54 - Pull out all the stops!
01:09:28 - Target properties for static analysis
01:10:36 - Scanning header files
01:11:20 - Guideline
01:15:17 - Create associated source files
01:15:23 - Enable warnings from outside the project
01:16:03 - Supported by all IDEs
01:16:28 - Finish
01:18:58 - Personal Wishlist
This is by far the best CMake video on the internet. After watching this, I went back and cleaned up my terrible CMake build scripts. I really hope this isn't the only good video we will ever get on CMake.
Haha, just got the same feeling! Got some fixing to do!
Yeah, CMake is lacking a good source of examples and tutorials. A lot of that is just googling or stackoverflow searching.
A great repository for examples covering many scenarios with GREAT commentary: github.com/ttroy50/cmake-examples
Altthough the project you referenced covers a lot of of topics, it does not consequently use Modern CMake. Example #1: add_library is explicitly called via STATIC/SHARED (one should use BUILD_SHARED_LIBS) Otherwise one can get problems with transitive dependencies. Example #2: Variables from the FindBoost module are used instead of targets. etc. I've found CGold (cgold.readthedocs.io) very useful, though the author sadly didn't finish the documentation. Nonetheless the information included in CGold is very valueable, imo.
Also a nice read, linking to this video: gist.github.com/mbinna/c61dbb39bca0e4fb7d1f73b0d66a4fd1
This highlights the lack of good onboarding tutorials for CMake. I have just been ramping up on all the easily accessible tutorials but they target 2.8x generation but the latest CMake 3.8.x is a different paradigm. It is updating faster than the documentation and tutorials. Definitely need more talks like this. I'm off to rewrite my CMake scripts.
A big problem of almost everything in developer land at the moment.
The documentation pages is fine, but again as usual, it is lacking the overall design explaination document.
Yes! The offical CMake tutorial is still in the old paradigm!? cmake.org/cmake-tutorial/
Yes, it's still the same old tutorial. Kitware should really remove that (together with the outdated wiki - I refuse to link to it here) and link to the latest documentation cmake.org/cmake/help/latest instead. Can anyone tell something about the quality of the latest version of the "Mastering CMake" book covering CMake v3.1? I am afraid that book is also outdated and contains a lot of information related to v2.x.
What is CMake 3.1? This is still ages old. We are at 3.10 at the moment.
True. CMake v3.1 has been released on 2014-12-17, so it is almost three years old. Since I haven't read the book, I can't judge it. The current stable version is 3.9.4 though, to be fair.
Excellent video! (Video/audio quality, content, etc). Internet is full of obsolete documentation about CMake. I would really love if people start writing CMake files using this modern approach.
Late to the party but adding my +1, this talk is pure gold!
It's videos like this that remind me why Meson has been getting so much headwind as of late.
CMake and Meson are so similar, except that Meson has great guides for learning from the ground up. If this video is too complex, Meson might be the ideal way to learn CMake.
Holy shit. This was way over my head. I personally don't think this is a tutorial video into CMake. It felt more like "hey CMake 2.8 guys. This is how we changed in 3.8". When this comment is over 1 year old, and if CMake is still version 3, reply to my comment whether I can do CMake. As of 2018 October 11, the 3.13.0-rc1 is ready for testing.
I'll go grab some tears and look for version-friendly CMake tutorial first.
If you're still working on C++, yes, CMake is still like this. It's great. It's a little bit more to learn and a little bit more setup initially, but _dang_ if it makes everything else way simpler! Even upgrading existing old CMake to target properties, despite being more annoying than doing it that way from the start, feels like such a breath of fresh air! No more "Make the library in _this_ CMake build and re-create all that same dependency info in _each one_ of the other CMake builds that needs this library"! No more "_ROOT" environment variables everywhere!
"This is really straightforward!"
*barfulous list of arcane runes follows*
Truly a disgrace in every sense. I'll be reporting as a bug whenever packages _do_ support cmake.
i once spend 2 hours trying to figure out how to append items to a list in cmake
Cmake is not for you
😂😂 Nice one!
@@abelmqueralto cmake is not for anyone.
Unbelivable content, just thank you
The people in the audience seem like they're trying to fight his recommendations every step of the way lol I'm glad to see most projects have taken this advice into consideration in the years since this talk
Probably because his recommendations are all insane
writing c++ isn't so bad, but getting an executable out of it makes me want to smash my keyboard. the learning curve for a newcomer is just insane.
I understand the need of not deprecation, but i would love that cmake and c++ compilers using optional deprecation so recent projects can be forced to use the lastest/modern features.
That's absolutely possible, but to do that right now you have to 1) setup the appropriate compiler warnings and add "-Werror"/"/WX" in your CI, which will already be very helpful, and 2) integrate clang-tidy (see 1:15:23) into your CI setup. From the zillion CppCon videos I watched, the reason of the comittee to take time making this kind of behavior standard is that the industry everywhere needs the many immense and critically important existing codebases that make use of bad C++ stuff. So they want to avoid breaking compatibility as much as is reasonable, so they often have to take the careful approach.
The standard comittee keep saying that eventually the standard will require, by default, for compilers to disable the bad bits of C++ and only allow them when explicitly enabled somehow. To be sure, it's been a number of years they've been saying that, but at least I'm incredibly grateful we have things like compiler warnings and nowadays have clang-tidy.
This requires some setup, which is annoying, but at least for a real-world project you *_can_* get the safety if you care enough about it or if you're interested enough about writing good C++. For example, "-Wmisleading-indentation" warns about, well, misleading indentations, such as in the case of the famous 'goto fail' Apple bug. With both "-Werror" and "-Wmisleading-indentation" in your CI, you will never let misleasing indentations through to production again --at least not on GCC or Clang, since MSVC would require different flags!
In a way, because it's the project that chooses its own language safety rules via compiler warnings/clang-tidy checks, it means the project is able to enforce its own set of guidelines if needed. For example, a project's team might decide to implement a clang-tidy check that warns on every use of known heap allocation APIs (new/delete/malloc/free/my_custom_alloc/etc.), which makes sense if the project is meant to run on embedded systems that are not required to have a heap at all. The team might add this check to their CI setup, with warnings treated as errors inside the ".clang-tidy" file, to automatically reject any pull request that attempts to add a call to one of these allocation/deallocation APIs. This means, in a way, that they've just implemented their own "version" of C++, as if they had added the words _"Any use of new/delete/etc. is ill-formed"_ at the end of the C++ standard that they're using.
"Still use a build system for header only libraries"..... YES
"you can just add a simple include file, or you can mess with this gross list of arcane incantations with random runes that come out of nowhere and do god knows what"
No I don't think I will. Old cmake is way less terrible than modern cmake.
Great video...!
I think, learning CMake is more difficult than learning C++ itself :/
Even if C++ is difficult, we at least have definitive learning material for it...
this presentation makes me want to write makefiles again
I was trying on and off to keep in touch with C++ for about 7 years, despite hating some of its language features like I have to watch a 90 minutes video on trivial things like object initialization. This coupled with confusing features like collapsible references etc, lack of library management tools etc kept me at the bay. Then latest projects started using this insanity called CMake. That was the final nail in the coffin.
This video is incredibly helpful. Seriously, who downvoted it?
I could really use a tutorial before I grok this lecture. The only easy tutorial that I found so far has taught me everything that this guy says I shouldn't use. Harumpf. So where is the gentle introduction to the right way to do things?
A lack of up-to-date documentation is the big issue with CMake as you will have read many times already, but maybe these two sites can help a bit:
cliutils.gitlab.io/modern-cmake/
cgold.readthedocs.io/en/latest/
@@HiAdrian Thank you very much for sharing
I worked with a medium sized code base that uses recursive Make. I am having difficulty selling(older C-developers) anything to allow parallel compiling.
Any tips or tools on moving something like this to CMake. Love Clion!!!
Why is using make in parallel compiling a problem? It does this very well with -j option? Selling CMake is hard if you are not multiplatform and/or users want use modern IDE's.
The best way to convince salty old engineers is to dig in, do the work, show that it works, and also show how it can improve their lives (i.e. adding value). So for example, moving to Cmake would make it easy to import the project into qt creator and use a graphical debugger that really works. Adding the compile_commands property will enable code completion plugins like YouCompleteMe, it's also a parseable index of how an object was really compiled, which makes it really easy way to track down build flag disputes, or just copy paste to rebuild an object on the CLI. Transparent use of ninja to parallelize the build. Having multiple build targets for Clang's static analyzers that improve code quality. The list goes on.
could anyone suggest me a github project with clean cmake files? Thanks in advance.
What happens if all your target needs to link to the same library, wouldn't it be easier to use `link_libraries()` instead of `target_link_libraries()`
Not really.
It's like using global variables in C/C++: it makes it easier to _write_ the code intially, but not to _read_ it and not to _change_ it later. As the CMake project grows, I'd much rather read self-contained code that does one thing and one thing only, even if that code is a bit longer (like a long-ish function that only has local variables), rather than having to run through dozens of CMake files that all perform global operations like link_libraries() everywhere (like a somewhat smaller but terrible function that keeps reading/writing global variables from lots of different places).
It's definitely not that bad on small projects, but for larger ones it can get quite terrible! And I personally value the little sanity I have left :')
Plus, with link_libraries() you don't get the incredible automatic dependency info that target_link_libraries() provides and that this presentation talks about. With link_libraries(), you have to essentially re-create the dependency information (include dirs, other libraries needed, etc) that the library you use has, whereas with target_link_libraries() you shouldn't. So if your library, A, needs library B, with target_link_libraries(A PUBLIC B) you shouldn't need to know/specify anything else. With link_libraries() though, you will need to specify link_libraries(B), you will have to also specify link_libraries(C) if B needs a library called C, you will have to do link_directories(path/to/B/include), you will have to do add_definitions(macro=value) if B needs macros, etc.
This guy makes nice looking slideshows
I don' understand why shouldn't we require ISO C++17 for example, but lambdas etc. I want to use VS2017 in C++17 mode, and passing one of the features I need just to get everything seems kinda hacky. I would much rather say I want ALL of C++17 and continue building my library.
CMake supports this since 3.8 via cxx_std_17: cmake.org/cmake/help/v3.8/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html
Exactly, just use something such as target_compile_features(mylib PUBLIC cxx_std_11) (cmake.org/cmake/help/latest/manual/cmake-compile-features.7.html#requiring-language-standards). I find it much easier to use too, since I do not need to manually synchronise the required features in the build file with the features used in the C++ source files.
Dude unironically telling you to write in a list of implementation details in your cmakelists, absolutely bonkers. "Code against an interface, not an implementation, except in your build system."
If i want to trigger my build system to see a new file from file(GLOB) i just manually re invoke Cmake to 'update' my build system, We need do that even without file(GLOB) after the file was added. So, i don't see nothing bad in file(GLOB)
How is it different from updating cmake everytime?
@@HarinduDilshan It is very different.
One requires you to keep a running list of files you add/remove in your head as you work on a new feature(or use git to help a little, granted) or preemptively add a bunch of empty, anticipated files. Just so you can then type out those new files by hand into the correct spots your CMake. All of that is very error-prone and distracting(breaking flow).
While file(GLOB) just requires you to manually re-enter the same command. Literally Up Arrow, then Enter in most cases.
None of the reasons I've heard for while they can't get rid of this issue make any sense either. If they are already generating make files that automatically retrigger when CMakeLists changes, why can't they do the same thing with another file called SourceList that are just plain old lists? That way IDE's can easily just auto-populate the list, adjusted as their project tree changes. Someone, please tell me why this wouldn't work.
@@thanatos454 In cmake 3.12 they added CONFIGURE_DEPENDS to file(GLOB ...) so it can check at build time, so you don't even have to manually check. They say it adds to the build time though.
I disagree with you that the typing of the files is error prone because you'll generally know if a file is not recognized anyway.
Would it make sense to have an "always call cmake" first to the target build system to make sure it is always up to date especially for globing calls? Store the globs in a sorted file for comparison, only update if there is a change. Seems like monitoring directory for new content is a legitimate set of functionality for a build system and for a tool supposedly to help bridge gaps between them.
@thegod3500 I think there are a lot of people on both sides of the issue. The CMake maintainers, and others generally seem to strongly discourage file(GLOB) (even with the newer CONFIGURE_DEPENDS) for source files to allow supporting all generators and for a number of other reasons, while many others encourage it to avoid forgetting stuff.
27:27 does it have to repeat the name after the double colon or not? I haven't understood that part.
No. "Foo" before the "::" represents the project/package name, and "Foo" after the "::" represents the library/executable name. If you have a package that exports two libraries/executables, you could have "Foo::server" and "Foo::client" for example. However, this is just a suggestion; you can use whatever name you want. The "::" is not mandatory; this talk only suggests doing so, and for good reasons.
11:45 "Create macros to wrap commands that have output parameters. Otherwise create a function. "
This isn't very clear at first sight. Because if you know the names of output variables and wants to foward it to the caller you can just set PARENT_SCOPE. I'd say you only need the macro when you don't know what the names of output parameters are and you want to forward them to the caller. An example would be all the global variables that come from calling find_package.
I think I agree. These are, of course, guidelines, not absolute rules. However, using a macro is still avisable in many cases even when you do know what the output variables are, since mis-setting variables is a bug that's always around the corner in CMake, especially if you want your codebase to remain actively developed for many years and you/someone might add/remove variables someday.
Ah yes, everything is so "straightforward" that we need an obscene amount of explanations before being able to setup something simple. This presentation is clearly aimed at people who are already familiar with CMake. If you're just trying to figure out your particular situation and found that you need to learn CMake, this presentation won't help you much. You're better off finding something more tutorial-like... except that most content out there is giving obsolete "advice" for obsolete CMake versions...
It's amazing that all of this crap has not been automated as part of IDEs in some way. Really... wth.
Not all people use fully fledged IDEs with bells and whistles, I e.g. use vim for editing and cmake for building.
Agree 110%! I would love to have a command line tool which entirely automates this with best practices. Something like:
> cmake-tool init cmake-tool create cmake-tool add-package
"except that most content out there is giving obsolete "advice" for obsolete CMake versions..."
Yeah except all that advice is telling you things like
"to frabulate your build, you just do
set(FRABULATE_BUILD ON)"
meanwhile all the "modern cmake" bozos are like
"ah yes this is really straightforward, not hard like it used to be in old cmake, what you do now is
include(CMAKE_BUILD_FRABULATION)
target(foo PRIVATE interface SET $
This is rather confusing as an onboarding video. Is there a good 3.x tutorial document or book? The talk is frustrating in that it introduced some powerful concepts of CMake without enough background to employ them.
Never had good experience with CMake - it is not really "cross-platform" - you always need to tweak something when you change from Linux to MacOS to whatever you use :(
is it okay to set c++ standard like this set(CMAKE_CXX_STANDARD 11)
Yeah I do this as well. You can also use the meta-feature: target_compile_features(Foo PUBLIC cxx_std_11)
CMake still does not works with the I18N and L17N features of XCode.
I have written a build system on top of the cmake buildsystem.
I've did the same. I've added a CMake convention-over-configuration framework using CMake modules that is added to each of my C++ components as a submodule (each component is either one application or one library together with optional tests and examples). With that approach I only have a very slim CMakeLists.txt that does contain the dependencies and source files only. Yes, I need to use variables to achieve this, but at least I do not have to maintain copy-&-pasted boilerplate code. I've already added integration (using strong assumptions, but still being flexible) for Doxygen, Protocol Buffers, Google Test, cloc, Flawfinder, etc. Future tasks include addition of other static analyse tools as well as code coverage and so on. IMO it's sad that everyone has to built its own solution and that CMake does not provide (optional) stronger assumptions how-to structure and build a C++ component. Package Management is also still an issue.
@@FlorianWolters85 ". Yes, I need to use variables to achieve this, "
Literally every cmakelists.txt I've seen uses a bunch of variables. This "modern cmake" everyone seems to talk about seems like a unicorn that exists only in people's heads.
great👍
At ruclips.net/video/bsXLMQ6WgIk/видео.html I believe you should use ARGV0 instead of ARG0 (see cmake.org/cmake/help/latest/command/macro.html )
This fellow clearly knows what he's talking about and could be considered a subject matter expert, but it seems to me he's an utterly incompetent presenter. He utilizes details before he describes them, goes off into unnecessary tangents without making it clear he's doing so, and presents sections of script files without labeling them or mentioning where they go, all of which force the confused audience members to interrupt with questions that should have been unnecessary.
I can see this being useful and informative to a certain subset of CMake users who are sufficiently up-to-speed to intuitively understand the contextual information he leaves out (eg. what file he's showing the contents of on his slide), but there's an inconsistency of assumption of prior knowledge, given that the talk starts out with very basic syntax -- anyone who could benefit from the first few minutes will get nothing from any of the content beyond that. Despite having used CMake 3.x for over a year now I am so far understanding very little of the bulk of this talk.
If he wants to promote CMake as excessively baroque and complicated to those not already well-versed in its use, this presentation works well for that purpose.
Having watched this in its entirety, I respectfully disagree with you wholeheartedly and think his presentation still is great. The talk is "Effective CMake". Not "Cmake 101" and your point about this having useful information for CMake users "sufficiently up to speed" is completely correct and seemingly intentional. If you've used 3.x for over a year and understand "very little of the bulk of this talk" I don't believe any talk will help you.
@@ninepoints5932 If his presentation is great, cmake itself is awful and nobody should use it for any purpose.
23:40
CMake is dominant and plain horrible. Its "language" is an example of how to not design programming languages. It is a good idea to switch to Lua, Python, JavaScript or any other modern scripting programming language. And yes, I want Turing completeness in the build system.
wow dem sounds like fighting 💪 words 😤
Wow, C++ developers interrupt a lot. Let the man talk!
If something is unclear - ask. Because if you don;t you could fail do understand the rest. And then we have developers who are afraid to admit they dont understant and project that onto new people creating more and more problems with less and less maintainable solutions.
The idea that you should put in feature flags instead of specifying the standard version is absurd. The feature's you're using are an _implementation detail_ of your target; the standard is the _interface._ Depend on the interface, not on the implementation detail. The more I learn about this vaunted "modern cmake" the more it looks like a downgrade over the old one.
"At least this is straightforward :)"
.. What about any of that is straightforward? You just laid out a bunch of random incantations filled with names that are themselves random incantations. Where did you define "footargets"? How would one even know what to write? It's not boilerplate, it's _runes._
At this point, I'm inclined to report as a bug whenever any package _does_ support cmake. This is disgraceful in every way and nobody should use it.
Bloody hell; why're you defining another language to compile the language you actually care about?
And please, C++ community, fix your versioning standards: [major.minor.patch.whatever-the-hell-you-want] is _not_ hard.
No! I will use 1.a.dev-alpha for the rest of eternity! XD
Can't wait for Rust to replace C++ in all new developments. The dependency management of C++ is primitive and out of date. There are no benefits. C++ itself also struggles with legacy design problems. There is no valid reason to use C++, except for "the project already is C++".
Not too familiar with Rust myself aside from watching a few hours' worth of presentations on it, but I keep hearing good things about it (e.g. StackOverflow's surveys made it the #1 most loved language for a few years now).
On the other hand though, "the project already is C++" is just **soooooo** common that "replacing C++" would probably take decades; we'd have to be both C++ _and_ Rust experts for the majority of our careers if we don't want to lock ourselves in "Rust-only projects" and want to benefit from the higher salary which projects that need developers that know _both_ would definitely give in this scenario.
Think about this for example: C++ has been superseding the vast majority of use-cases of C for 30+ years, and yet C is still here even though C++ is mostly backward-compatible... All your basic user-space Linux libaries and executables, like bash, the libc, system headers, OpenGL, BLAS, QEMU, as well as the Linux kernel, and so forth, are made in C, not C++ (with or without good reason is another question), so you still have to occasionally manage reading/writing C. Imagine how long it would take to "replace C++" with a language that isn't even really backward-compatible with C++ and therefore have to more or less "restart" entire dozen/hundred-million-dollar projects for the sake of using a newer language! Or we could go halfway and do major compatibility work to have both Rust _and_ C++ live in the same codebase, meaning you would need a lot of developers that need to know _both_ very well. How would we convince people who pay us that this is the right way to go? Note that I'm not implying that "staying with C++ is great and that moving to Rust is bad"; I'm just pointing out that all options are imperfect to a varying degree. Sometimes we just see that "option A is bad" and choose option B, which might be just as bad. It's all about tradeoffs; this is engineering after all!
Perhaps one thing going Rust's way is that Linux now allows writing drivers in it. It's not the whole kernel that's going to see Rust right now (if ever) however, but how this turns out is going to be interesting. Will developing the kernel one day require its developers to know both C and Rust, or will the kernel just always stay in C forever?
I remember when Google launched the Carbon language a couple of years ago, which was designed to be easily compatible with C++ to support gradual adoption in the codebase. However, I don't think Carbon gained much traction; I haven't heard about it again since.
_However, the emergence of languages like Rust might prompt quicker and more pragmatic development of C++._ Let's just hope that C++ standard development is not so quick that the new C++ features are only half-usable immediately after standardization!
Perhaps another, more reasonable option, is what Herb Sutter is doing: writing a "Cpp2" language that gets transpiled into normal C++, like TypeScript is to JavaScript. Since this is a whole new language, you don't need to preserve compatibility with anything, so you can redo the defaults, plus you can always just grab the transpiled C++ if it Cpp2 doesn't work out and you want to go back to plain C++. I have yet to hear about large projects adopting this though.
33:27