Hacker News new | ask | show | jobs
by cheesedoodle 1907 days ago
I really appreciate the advice from Daniel Pfeifer [0] where you treat all your build-tree sub-projects as out of tree dependencies, by overriding the `find_package` macro. This way, you can just find project dependencies using the `find_package` as if you were referring to something pre-built. Save a lot of hassle.

  macro(find_package)
    if(NOT "${ARG0}" IN_LIST as_subproject)
      _find_package(${ARGV})
    endif()
  endmacro()

[0] C++Now 2017: Daniel Pfeifer “Effective CMake" https://www.youtube.com/watch?v=bsXLMQ6WgIk&vl=en slides: https://github.com/boostcon/cppnow_presentations_2017/blob/m...
1 comments

This requires a lot of extra work and doesn't often work like you'd expect. However, this is a shortcoming of CMake not having a good dependency model aside from the old (and IMO not far from obsolete) system dependencies model that Linux popularized. It made sense then but things have changed, and dependency injection is something CMake fails miserably at.

We shouldn't have to do macro/function overrides, but I'm glad they exist in CMake. Current status quo is "it's really annoying and a huge headache to do, but at least CMake allows me to do it, unlike others".

If you mean the extra work is exporting your libraries and having a list of all your sub_projects in the root CMakeLists.txt, then yes.

I think it's minimal work, as I would like to have all my libraries imported and linked anyway:

  find_package(MyLib)
  target_link_libraries(${PROJECT_NAME} PRIVATE MyLib::MyLib)
This looks tidy any more explicit, avoids transitive leakage and more.

What is it that does not often work as you expect?

Because you're ignoring how find_package works and how dependencies use the variables inside of them. Not every find script creates some sort of target.