We have a lot of problems with VCPKG in our own registry, but for external dependencies it's pretty good. Our projects tend to be really small and all our libs are spread across multiple repositories, so we have to update the baseline in every repo in the right order to not screw up builds. This means updating libA -> Update Registry -> Update Baseline in libB -> Update Registry for libB -> Update Baseline in libC -> update Registry for libC -> Update Baseline in Application. Would be much easier if you could just use HEAD instead and pin baselines for releases but that's not possible afaik....
Package management in a C++ context can never be trivial. I love my C++ but darn it the committee should do a "call for submissions on a standardized package manager for C++" Conan+CMake will have to due for now...
Played around with it and was able to move all of my .gitmodules excluding one over to this, and some include locations, but overall worked nicely. Not sure I'll actually change my practices or push to master though.
@@Omnifarious0 According to the doc it does. CPM uses CMakes builtin FetchContent, which in turn is built on top of CMakes ExternalProject. So usually the Parameters of ExternalProject just work. Which means you have a lot of possibilities to fetch dependencies. CPM is mainly about caching your downloads and giving you additional options to, i.e. feed in already downloaded work environments.
@@lnx648 - I know how to use it, but I think it has an obnoxious and poorly designed CLI interface. So, I will speak of it with disdain and antipathy every chance I get. A lot of people think it's the only thing out there that does what it does.
I don't see anything in the documentation or in the issue tracker regarding an option to prevent "cmake clean" from cleaning the dependencies; maybe someone who is an active user would consider a feature request for this option?
If using CPM, what is the easiest way to check for new versions of dependencies, is there some tool that can summarize them or should you just check manually?
It seems like it's using FetchContent behin the scenes. One problem I had when using FetchContent was that some libraries would throw compiler warnings that would be caught when compiling my project with -werror. I hope there's a way to handle that case with CPM
sounds like your problem was less about FetchContent and more about about how you were defining compiler flags for your target you should use target_compile_options to set it only for specific targets
You could use "SYSTEM" keyword in FetchContent_Declare after CMake 3.25 to prevent such warnings. CPM handles a limited amount of arguments and passes all other to FetchContent module, so it should work with CPM too.
@@sergeymatveev4397 I tried that, but it didn't work, in the end i just changed the target compiler arguments for them maybe my configuration was just bad haha
I use ExternalProject_Add for dependencies not in conan (either fetching with git or from a subdirectory in my repository), but that can be set up to work with any build system (e.g. autotools) not just CMake; any provision in CPM for that kind of thing? (ExternalProject can be quite annoying and tricky to integrate or work with though, debugging issues with it is quite annoying)
CPM is layered on top of FetchContent which is partially layered on top of ExternalProject. FetchContent moves the activities of ExternalProject download and configure towards the configuration step, and preserves the build environment that you are using. Meanwhile ExternalProject is creating a new build environment during the build step! Which is very important difference: if you are doing a cross compiler build - the cross compiler setup is by default not forwarded to your ExternalProject. The big benefit of CPM is that it allows you to organize dependencies in a local cache, or even allows you to have specific locations for specific dependencies. This helps a lot, if you are working on multiple libraries at once and feed those into a main project. I usually have complete git clones (CPM also does grafted clones) of my libraries and when I want to test them with a consumer project I launch cmake with -D_SOURCE_DIR=clone-location. Hence I can easily test local changes over multiple projects. Adding CPM to my toolbox led to me splitting out more and more code into re-useable modules, because CPM made working with dependencies so much easier.
7:24 CPM is entirely pointless. vcpkg can already pick up such things that aren't in a registry or the main repo using overlay ports. Please please please use a package manager like vcpkg or Conan, not abominations like CPM! Anything that requires intrusive code changes to your CML is not a solution at all! vcpkg and Conan default to the real workflow of using find_package()!
CPM can also be made to pull in dependencies via find_package if available. So if you happen to integrate a library that uses CPM already - you can force it to rely on find_package also.
What's the point though? Especially now that you can hook into find_package yet another way using dependency providers. CPM is just such a bad deal, because you aren't writing idiomatic CMake by not using find_package verbatim.
I've spent a lot of time with CPM since making this video, and BY FAR the best part about it is being able to easily control how the dependencies are built, and avoiding UB and ODR violations because of differing control flags between app and dependencies. Last I looked, vcpkg refuses to use your existing build change and insists on installing its own. Vcpkg and Conan both use whatever script they were programmed with. CPM makes it trivial for me to enable LTO and hardening on my dependencies - something that borders on impossible with CMake. CPM also shines in the fact that it encourages authors of C++ libraries to be better CMake citizens.
@@stephenhowe4107 He was such a legend, its so strange that nobody is talking about him as one of the greats. He was awesome on Computer chronicles tv program too.
@@torarinvik4920 Yes he was. I used CP/M-86 as an Operating System in 1984 for a Sirius Computer (a competitor to IBM). MS-DOS was also available and I used dbaseII and Wordstar and MBASIC (Microsoft). These products worked on non-IBM computers without the IBM BIOS chip. But legend has it that Gary Kildall was flying a small plane and kept IBM executives waiting on the ground. So IBM chose Microsoft. And the rest is history. I also remember using DRDOS-6. CP/M was dominant for 8-bit computers in the 1970's.
@@cppweekly I want correcting, just finding amusement. I use spacemacs now anyway.
Год назад+5
I like the fact that there is no good package manager for C++. It forces people to limit the amount of dependencies to a few big ones at most. Nobody should be using a third-party string padding library! The worst thing about Rust is Cargo, it makes it so that even the simplest of projects have dozens if not hundreds of dependencies, and most of these are trivially simple to implement. It's a terrible idea, both from maintainability and security point of view.
100% Agree. That's one of the major downsides to rust. Even the hello world example in the rust docs downloads like 15 dependencies. It's total madness.
Isn't that an indictment of CMake's abstruseness? Personally I wrap CMake in ordinary makefiles, which are far easier to program. Thanks for this video. I'll check out CPM.
@@erichlf Makefiles use shell syntax. Which in my world everyone knows. So it's easy to write arbitrary programs in your makefile for creating directories, moving files about, patching source files before or after build, whatever. In CMake that all takes special purpose bizarre keywords if it's possible at all.
@@erichlf Ok, simple example: I want a record of precisely how cmake was invoked: the exact commandline, and a isting of the full environment at that time. That's why I wrap the cmake call in a makefile. It's ridiculous that cmake doesn't even record how it's invoked. At least no one has told me how to do this.
😊 a tip to save disk space with Cpm, you can specify exact GIT TAG (hash), and GIT SHALLOW, instead of it pulling entire repo and history
Finally, a package manager that doesn't make my skin crawl with how convoluted it can be
We have a lot of problems with VCPKG in our own registry, but for external dependencies it's pretty good.
Our projects tend to be really small and all our libs are spread across multiple repositories, so we have to update the baseline in every repo in the right order to not screw up builds.
This means updating libA -> Update Registry -> Update Baseline in libB -> Update Registry for libB -> Update Baseline in libC -> update Registry for libC -> Update Baseline in Application.
Would be much easier if you could just use HEAD instead and pin baselines for releases but that's not possible afaik....
Package management in a C++ context can never be trivial.
I love my C++ but darn it the committee should do a "call for submissions on a standardized package manager for C++"
Conan+CMake will have to due for now...
Standardized package management makes little to no sense without standardized build system and I doubt the committee will ever do that.
@@ALivingDinosaur It's the missing part of C++
@@marcbotnope1728 I think language standard should specify only language itself and its standard library, building-related stuff is outside its scope.
@@ALivingDinosaur 90% of "the shit C++" makes me deal with is "building related stuff". Standardize that shit NOW!
@@ALivingDinosaur in this case they should have never touched and introduced modules
Played around with it and was able to move all of my .gitmodules excluding one over to this, and some include locations, but overall worked nicely. Not sure I'll actually change my practices or push to master though.
Does it support Mercurial? I don't use that atrocious git thing unless I have to.
@@Omnifarious0 According to the doc it does. CPM uses CMakes builtin FetchContent, which in turn is built on top of CMakes ExternalProject. So usually the Parameters of ExternalProject just work. Which means you have a lot of possibilities to fetch dependencies. CPM is mainly about caching your downloads and giving you additional options to, i.e. feed in already downloaded work environments.
@@Omnifarious0 "git thing" lmaoooooo
@@lnx648 - I know how to use it, but I think it has an obnoxious and poorly designed CLI interface. So, I will speak of it with disdain and antipathy every chance I get. A lot of people think it's the only thing out there that does what it does.
I don't see anything in the documentation or in the issue tracker regarding an option to prevent "cmake clean" from cleaning the dependencies; maybe someone who is an active user would consider a feature request for this option?
If you set CPM_CACHE_PATH to another directory apart from build/ dir, it wont delete it
I kind of want a follow up on how to makr CPM work together with Conan or vcpkg projects
If using CPM, what is the easiest way to check for new versions of dependencies, is there some tool that can summarize them or should you just check manually?
Manual
How does this compare to Hunter?
Is it similar to Hunter CMake?
C++ with a package manager like Cargo and things are solved.
It seems like it's using FetchContent behin the scenes. One problem I had when using FetchContent was that some libraries would throw compiler warnings that would be caught when compiling my project with -werror. I hope there's a way to handle that case with CPM
Shouldn't compiler settings be orthogonal to whether or not you use .gitmodules or CPM?
sounds like your problem was less about FetchContent and more about about how you were defining compiler flags for your target
you should use target_compile_options to set it only for specific targets
You could use "SYSTEM" keyword in FetchContent_Declare after CMake 3.25 to prevent such warnings. CPM handles a limited amount of arguments and passes all other to FetchContent module, so it should work with CPM too.
@@sergeymatveev4397 I tried that, but it didn't work, in the end i just changed the target compiler arguments for them
maybe my configuration was just bad haha
@@Stowy I've also ran into this not working everywhere. private compiler flags in build propogate to my dependencies even on 3.27.
I've used CP/M, but it's been _ages_. I never knew it could be used to manage dependencies. Does it still have a 360K limit on storage device size?
I use ExternalProject_Add for dependencies not in conan (either fetching with git or from a subdirectory in my repository), but that can be set up to work with any build system (e.g. autotools) not just CMake; any provision in CPM for that kind of thing? (ExternalProject can be quite annoying and tricky to integrate or work with though, debugging issues with it is quite annoying)
CPM is layered on top of FetchContent which is partially layered on top of ExternalProject. FetchContent moves the activities of ExternalProject download and configure towards the configuration step, and preserves the build environment that you are using. Meanwhile ExternalProject is creating a new build environment during the build step!
Which is very important difference: if you are doing a cross compiler build - the cross compiler setup is by default not forwarded to your ExternalProject.
The big benefit of CPM is that it allows you to organize dependencies in a local cache, or even allows you to have specific locations for specific dependencies. This helps a lot, if you are working on multiple libraries at once and feed those into a main project. I usually have complete git clones (CPM also does grafted clones) of my libraries and when I want to test them with a consumer project I launch cmake with -D_SOURCE_DIR=clone-location. Hence I can easily test local changes over multiple projects.
Adding CPM to my toolbox led to me splitting out more and more code into re-useable modules, because CPM made working with dependencies so much easier.
7:24 CPM is entirely pointless. vcpkg can already pick up such things that aren't in a registry or the main repo using overlay ports.
Please please please use a package manager like vcpkg or Conan, not abominations like CPM! Anything that requires intrusive code changes to your CML is not a solution at all! vcpkg and Conan default to the real workflow of using find_package()!
CPM can also be made to pull in dependencies via find_package if available. So if you happen to integrate a library that uses CPM already - you can force it to rely on find_package also.
What's the point though? Especially now that you can hook into find_package yet another way using dependency providers. CPM is just such a bad deal, because you aren't writing idiomatic CMake by not using find_package verbatim.
I've spent a lot of time with CPM since making this video, and BY FAR the best part about it is being able to easily control how the dependencies are built, and avoiding UB and ODR violations because of differing control flags between app and dependencies.
Last I looked, vcpkg refuses to use your existing build change and insists on installing its own. Vcpkg and Conan both use whatever script they were programmed with.
CPM makes it trivial for me to enable LTO and hardening on my dependencies - something that borders on impossible with CMake.
CPM also shines in the fact that it encourages authors of C++ libraries to be better CMake citizens.
@@cppweekly Very true - I turned into, the 'let me fix your cmake' guy at my company.
I remember when CPM was an "operating system" for 8080 computers... (OK, I guess the slash is significant (CP/M))
Ah the one made by Gary Kildal?
@@torarinvik4920 Yes. Gary Kildall
@@stephenhowe4107 He was such a legend, its so strange that nobody is talking about him as one of the greats. He was awesome on Computer chronicles tv program too.
@@torarinvik4920 Yes he was. I used CP/M-86 as an Operating System in 1984 for a Sirius Computer (a competitor to IBM). MS-DOS was also available and I used dbaseII and Wordstar and MBASIC (Microsoft). These products worked on non-IBM computers without the IBM BIOS chip.
But legend has it that Gary Kildall was flying a small plane and kept IBM executives waiting on the ground. So IBM chose Microsoft. And the rest is history.
I also remember using DRDOS-6. CP/M was dominant for 8-bit computers in the 1970's.
@@stephenhowe4107 Interesting, how was the user experience of CP/M compared to the other OS of that time?
cpm, ccache, done
And don't forget about CPM_SOURCE_CACHE (environment or cmake) variable to speed up your downloading process!
Love CPM!
I find it ironic when someone using VIM uses `:wq` instead of `:x`.
My colleagues were surprised when last Friday I did ":x" 😂 c'mon it was one of the first thing I searched when starting vim!!!
And here I am using ZZ and ZQ ^^
Fun fact - one reason I stopped using vim in videos is because people would "correct" my vim usage all the time.
@@cppweekly I want correcting, just finding amusement. I use spacemacs now anyway.
I like the fact that there is no good package manager for C++. It forces people to limit the amount of dependencies to a few big ones at most.
Nobody should be using a third-party string padding library!
The worst thing about Rust is Cargo, it makes it so that even the simplest of projects have dozens if not hundreds of dependencies, and most of these are trivially simple to implement. It's a terrible idea, both from maintainability and security point of view.
100% Agree. That's one of the major downsides to rust. Even the hello world example in the rust docs downloads like 15 dependencies. It's total madness.
Isn't that an indictment of CMake's abstruseness? Personally I wrap CMake in ordinary makefiles, which are far easier to program. Thanks for this video. I'll check out CPM.
I'm hoping this is a joke. The only reason I am not sure is because I have actually seen someone do this.
I've also been doing this, but it wasn't cross platform so I made a python script that generates my makefiles that wrap CMake.
@@StowyI hope this is also sarcasm.
@@erichlf Makefiles use shell syntax. Which in my world everyone knows. So it's easy to write arbitrary programs in your makefile for creating directories, moving files about, patching source files before or after build, whatever. In CMake that all takes special purpose bizarre keywords if it's possible at all.
@@erichlf Ok, simple example: I want a record of precisely how cmake was invoked: the exact commandline, and a isting of the full environment at that time. That's why I wrap the cmake call in a makefile. It's ridiculous that cmake doesn't even record how it's invoked. At least no one has told me how to do this.
xmake is better than this tool