TL;DR I wrote a guide for quickly setting up a C++ dev environment. It's over on github at https://github.com/kshehata/Mac-Cpp-Quickstart
I'm taking Coursera / Stanford's course on cryptography to brush up on the fundamentals. I figured I should do some of the example problems in C++, that way not only do I get to know crypto better, but I also brush up on C++ and learn the crypto libraries at the same time. I didn't need anything too complicated, just a C++ dev environment that will compile a class or two, unit tests, and the crypto library. Nothing too fancy, right?
My first attempt was Xcode. I don't need anything cross-platform, just a sandbox basically, so Xcode should work. I was almost instantly disappointed, for the following reasons:
- No out-of-the box support for gtest. I was hoping this would be as easy as File -> New -> C++ Test Case. Nope.
- Difficult to configure C++ 17 support. This should be an easy setting. Instead you have to dive into compiler configs to make it happen
- No autoformatting
- Adding a library like Crypto++ would have been a hassle. Not difficult, just means integrating it into the project
- Far more complicated that I would like for a simple project, without any cross-platform benefits (this is my general complaint about IDEs)
Basically, Xcode is great for developing iOS and Mac apps using Apple frameworks and Swift / Objective-C, but not great for anything else and definitely not aimed at C++ development. So what other options are there?
I started looking around and found both CMake and Bazel. While I'm familiar with Bazel from my Google days, it seemed like overkill and it seemed like CMake is now the accepted standard and a lot more generally supported. CMake has also improved a ton since I last used it years ago and now looks like exactly what I need: just point it at a few sources and get a build. That it supports basically any platform and can even generate files for IDEs are just gravy.
So that solves the build problem. What about dependencies like crypto++ and googletest?
- Include them in the project build itself as a submodule, as described in Modern CMake
- Do the old-school build and install at a system level
- Use something like homebrew to install them for you
None of these are great options. The first one involves a lot of management of an external dependency within your project. If it's a critical library that may be a good idea, but if your dependencies start adding up this can get unwieldy very quickly. It also doesn't make sense for every project to have its own copy of gtest. That's so general it should really be at the system level.
But the system level solutions are also problematic. What happens if two different projects want different version of the library? Or if you want to test changes to the library with your project? Do you really want to be installing dev packages system-wide for every dev dependency you have? More importantly: anyone who wants to build your code is going to have to do the same thing: install everything at a system level.
Other dev environments have this figured out. In Python I can just do "pip install" and it'll take care of everything for me. Homebrew solves some of this, but at great cost. I really don't like installing homebrew, as it always seems to bring its own set of problems. Also: someone else trying to build my code is again going to have to install everything and hope it all works.
Enter Conan. Conan is basically the C++ answer to pip. You specify what you need, and it takes care of setting it all up for you. It integrates cleanly with CMake, meaning you get all of your libraries included with very little effort. Now this is what I wanted when I set out to set up my dev environment!
Since it took me a while to get to this point, I figured it was worth writing out what I did. Of course, that took a lot longer than I thought it would, but hopefully it'll be worth it for someone. Check it out here: