[CMake] How do you handle recursive dependencies in CMake

Sven Baars s.baars at rug.nl
Thu Jun 30 07:42:53 EDT 2016


Hey Ray,

For myself it is not a big problem either, but I don't want to tell
users of my libraries that they have to look up how the administrators
at their supercomputing facility compiled 20 other libraries so they can
set  their environment variables in the right way, while at the same
time making my own CMakeLists.txt files much longer (because I would
need many more find_package calls for dependencies of dependencies that
I don't use). Whereas if CMake would just provide some means of using
absolute paths instead of targets for libraries, or attach the
information about those paths to the targets or something like that,
this would never be a problem, since in that case everything would be
found automatically.

Also, it still doesn't make sense to me that instead of one find_package
call for a package I actually use, I also need 20 find_package calls for
dependencies of that other package. Also it doesn't make sense that I
would actually need these find_package calls, whereas if the packages
were just installed in /usr/lib or something it would work without any
knowledge of this package even being used.

Something that causes problems is the case where you use either A1 or
A2. Then in B you would do something like

option(B_USE_A2 OFF "Use package A2 instead of A1")

if (NOT B_USE_A2)
    find_package(A1)
    if (A1_FOUND)
        ...
        target_link_libraries(B ${A1_LIBRARIES})
        ...
    else()
        set(B_USE_A2 ON)
endif()

if (B_USE_A2)
    find_package(A2)
    if (A2_FOUND)
        ...
        target_link_libraries(B ${A2_LIBRARIES})
        ...
    endif()
endif()

which makes sense, but then also in C instead of doing

find_package(B)
if (B_FOUND)
    target_link_libraries(C ${B_LIBRARIES})
endif()

you would also have to do

if (B_FOUND)
    option(C_USE_A2 OFF "Use package A2 instead of A1, which is used in
package B. Make sure C_USE_A2 is equal to what you used in package B as
B_USE_A2")

    if (NOT C_USE_A2)
        find_package(A1)
        if (A1_FOUND)
            ...
            target_link_libraries(C ${A1_LIBRARIES})
            ...
        else()
            set(C_USE_A2 ON)
    endif()

    if (C_USE_A2)
            find_package(A2)
            if (A2_FOUND)
                ...
                target_link_libraries(C ${A2_LIBRARIES})
                ...
            endif()
    endif()
    target_link_libraries(C ${B_LIBRARIES})
endif()

or something like that, which is quite silly. Especially the part where
compilation fails if B_USE_A2 is unequal to C_USE_A2. In general, my
CMakeLists.txt is a lot more complicated, so I'd prefer the option where
I only look for B.

Sven

On 06/30/2016 01:05 PM, Raymond Wan wrote:
> Hi Sven,
>
>
> On Thu, Jun 30, 2016 at 6:40 PM, Sven Baars <s.baars at rug.nl> wrote:
>> So let's take Trilinos as an example, which is quite a big library,
>> which depends on a lot of libraries as well. In every project that
>> builds upon it (but does not even use functionality of any libraries),
>> we would have to set: SCALAPACK_ROOT, LAPACK_ROOT, BLAS_ROOT,
>> BOOST_ROOT, GTEST_ROOT, BLACS_ROOT, UMFPACK_ROOT, MKL_ROOT, etc... and
>> then inside the CMakeFiles.txt do a find_package(Trilinos),
>> find_package(Scalapack), find_package(LAPACK), etc... just to compile
>> int main() {} with one call to a Trilinos function inside of it. I'd say
>> that it should be enough to just do a find_package(Trilinos).
>
> Perhaps I'm alone here, but I actually don't see this as being a "big" problem.
>
> For the environment variables, you can place them all in a bash script
> and source it during log in.
>
> For all of the Find_Package calls, they only matter whenever you have
> to re-run cmake.  I don't know what Trilinos is, but for something
> that big, I presume it takes more time to compile it (during active
> development) than to run cmake to look through all those paths...
>
> Ray



More information about the CMake mailing list