2

I want to know what is the best way to make directory structure for multiple dependent c++ projects which is built using cmake and how cmake script should look like in this case. (I do it in linux with gcc if it is important.)

I have multiple independent projects A, B. Also I have multiple libraries X, Y.

There are no problem when those libraries is made by other developers. I can use existing FindX.cmake or write own to track them.

The problem arises when X, Y are my own libraries. Let A depends on X and Y, project B depends on Y. Furthermore, let Y depends on X (because I reuse some common, not task related code). However I assume that there can be more libraries, projects, and greater depth of their nesting. The second assumption is that libraries (X for example) can provide not only libraries like *.so, but also can provide some executables (not only for testing).

When I rebuild my project I want to rebuild all dependencies, because I can make modifications in projects and libraries simultaneously. Moreover, I want to separate libraries from each other and create one directory code with all my projects, which will contain 4 subdirs: ~/code/A, ~/code/B, ~/code/X, ~/code/Y. Every project will have own tests and will be pushed in separate code repositories.

The best links I found about building proper directory structure is this and this. However authors suggest to create nested directory structure, which seems difficult to do in my example, because if I do this way, I will end up with directory structure like this:

A/X
A/Y/X
B/Y/X

which I can get by using symlinks. But then in my separate directory with compiled binaries for each project (A/build, B/build, X/build, Y/build) I will have copy of libraries and executables from different libraries. If I call make install for all builds, those copies will create mess due to duplication of binaries and libraries.

UPDATE (SOLUTION):

The answer happens to be rather simple, I found it after few days of experimenting with cmake and reading documentation.

  1. Libray. Add next two lines:

    export(PACKAGE <pkgName>)
    export(TARGETS <libTarget> FILE <pkgName>Config.cmake)
    
    • First line will create entry in ~/.cmake/packages/ which will tell where build dir of library is situated. Cmake invocations in other projects start search from that path.

    • Second line will create Find<pkgName>.cmake in build directory.

  2. Executable. Add next lines:

    find_package(<pkgName> QUIET)
    
    if(${<pkgName>_FOUND})
      message(STATUS "Found <pkgName>.")
    else(${<pkgName>_FOUND})
      message(FATAL_ERROR "Could not locate <pkgName>!")
    endif(${<pkgName>_FOUND})
    

    So, if library wasn't built we will see error message, otherwise we will be able to use target <libTarget>.

Of course, building executable don't trigger rebuilding library if some changes in library sources are made. To overcome this problem I wrote bash script to call make firstly in library, and next in executable build dir.

P. S. If you know better solution, I am still waiting for it.

1 Answer 1

1

What I personally use is something like this

~/my_project
~/my_project/src
~/my_project/src/A
~/my_project/src/B
~/my_project/src/X
~/my_project/src/Y

The main CMakeLists.txt uses add_subdirectory to add the src directory. The src/CMakeLists.txt in turn uses add_subdirectory to add A, B, X and Y.

With properly setup dependencies in the CMakeLists.txt files, CMake will handle the dependencies correctly, and rebuild everything needed (so if you make a change in X then Y, A and B should be rebuilt correctly).

Sign up to request clarification or add additional context in comments.

2 Comments

If A and B absolutely independent and I push them in different online repositories, where ~/my_project/CMakeLists.txt, ~/my_project/src/CMakeLists.txt should go?
@BhavinChirag If A and B are truly independent, then my scheme won't work, as it sees A and B as part of a package, or sub-projects. My recommendation in this case is to make X and Y independent as well, creating your own FindX.cmake and FindY.cmake files that can be used, and build the libraries independently, and then build and install each library separately and in the right order.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.