2

I would like to know how to add external libraries into my project. Is there a standard way of doing so?

The way I do it and that I don't like is:

  1. Have a folder called vendors where I add submodules e.g. boost, openssl...
  2. I build the external libraries (as they come with a cmake to build in general).
  3. I add a premake (I could have used a cmake) to each external library and I configure so I can see the project in VS as well as the cpp and the hpp files.

I don't like this because I do copy the binaries of the external libraries manually, hence if I delete the bin folder I can't build my solution just by clicking build but I have to build the external libraries first using there cmake and then I copy the binaries manually to the bin/ folder of my solution.

Could you please give me a "standard" way I can do this? I feel like there could be better ways by just using to the max the CMake that comes with the external library. Also, I don't like changing the external libs too much, I just want to be able to update them anytime and everything works without me touching stuff.

How can this be done?

starball
  • 20,030
  • 7
  • 43
  • 238
Vero
  • 313
  • 2
  • 9
  • Preferably use the system libraries, unless you have very specific requirements for third-party library versions. – Some programmer dude Nov 25 '22 at 21:33
  • Have you considered using [`FetchContent`](https://cmake.org/cmake/help/latest/module/FetchContent.html)? Also see [Cmake's "using dependencies guide"](https://cmake.org/cmake/help/latest/guide/using-dependencies/index.html). – starball Nov 25 '22 at 21:39
  • @Some programmer dude could you please point me somehwere I could look. I really don't know anything about how to add external libraries and the cause a lot of trouble as the project becomes big, everything gets messy. – Vero Nov 25 '22 at 21:41
  • @starball thanks so much. Is this the "standard", I really don't to be too smart about this, just something clean that people are doing since the 90s should work for me. Do you have any links to this please? – Vero Nov 25 '22 at 21:42
  • You finished reading [CMake's "using dependencies guide"](https://cmake.org/cmake/help/latest/guide/using-dependencies/index.html) in two minutes? (jk) I edited that comment, so maybe you didn't see I added that link. I'd highly suggest you give it a read through if you haven't already. It explains the different basic approaches to using dependencies in a CMake project. – starball Nov 25 '22 at 21:45
  • Sorry missed it. Checking now! – Vero Nov 25 '22 at 21:49
  • 1
    Using a package manager like conan or vcpkg? – MatG Nov 25 '22 at 22:01
  • That sounds intersting, will that take into account all external libraries, copy the binaries where they should be and use the external libraries's cmake? My goal is clear, is don't want to touch the external libraries and use there cmake and link everything together. could you please confirm I can do this with conan or vcpkg and I will learn that please? – Vero Nov 25 '22 at 22:25
  • 1
    vcpkg does even copies the required dlls that were built for the opensource library into your bin folder for your application. – drescherjm Nov 26 '22 at 03:30
  • Thank you. If someone could give a detailed answer below that would be great. I am pretty sure many people would be interested on how to easily manage libs without pain. – Vero Nov 26 '22 at 12:24
  • Also how to handle branches? Like if I am using vcpkg, how can I install a dev branch instead of master for example? – Vero Nov 26 '22 at 12:47
  • If you use vcpkg and you want to use a dev branch instead of what's provided by default, you can create a custom port. – jpr42 Nov 27 '22 at 01:27
  • I am going for cmake from scratch, I used vspkg as an experiement but it's hidding everything and I know that is the goal but I want to be able to see what I am using not a blackbox :) (of cource vspkg is powerfull). Could just the c++ community agree on one design, from my research there is no "standard" way of doing things which is sad. Like pythong they have pip which making life easy and "standard" – Vero Nov 27 '22 at 01:33

1 Answers1

2

One approach is to use CMake's FetchContent functionality.

The FetchContent module allows specifying Git repositories of CMake projects to fetch at configure time. The default setting assumes that that repository has a CMakeLists.txt file at the repo's root directory. It clones the repo to a default (but configurable) location, and then just calls add_subdirectory() on the cloned directory.

You can read about how to use it in the reference documentation, and you can read about how that approach compares with some other CMake-supported approaches for using dependencies in the official Using Dependencies Guide. Do brace yourself when reading the reference docs, though. They're not designed to be like a beginner-friendly tutorial, and since FetchContent is built upon another module called ExternalProject, some of the docs for FetchContent just point you to go read sections from the ExternalProject docs. Be prepared to do a bit of digging.

Here's a basic example I used in a project at one point.

include(FetchContent)

FetchContent_Declare(
  range-v3
  GIT_REPOSITORY git@github.com:ericniebler/range-v3.git
  GIT_TAG "0.12.0" # https://github.com/ericniebler/range-v3/releases
  GIT_SHALLOW TRUE
  GIT_PROGRESS ON
  SYSTEM
)
# more `FetchContent_Declare`s (if any). They should all be declared
# before any calls to FetchContent_Make_available (see docs for why).

FetchContent_MakeAvailable(range-v3)
# more `FetchContent_MakeAvailable`s (if any).

FetchContent in some ways is designed to be a little bit "low level". It has a lot of machinery and customization points. If your project is super simple, you might find it useful to try out a CMake-external wrapper module called "CPM" (CMake Package Manager) that attempts to cater to sensible defaults for more common, simple use-cases.

If you use FetchContent or CPM, be aware that since they eventually just call add_subdirectory, you might need to take some steps to avoid naming conflicts of target names and CMake variable names between your CMake configs and the CMake configs of the dependencies you pull in. For more info, see How can I avoid clashes with targets "imported" with FetchContent_MakeAvailable?.

As others have mentioned, you can also look into using package managers like vcpkg or Conan. I don't know much about those so I can't comment.

starball
  • 20,030
  • 7
  • 43
  • 238