How do you handle recursive dependencies in CMake

classic Classic list List threaded Threaded
28 messages Options
12
Reply | Threaded
Open this post in threaded view
|

How do you handle recursive dependencies in CMake

Sven Baars
Hey everyone,

I posted a question on StackOverflow a while ago, but got no real answer
to my question there. I posted an answer there by myself, but this
solution does not work on every system. Since it also involves some
possible inconsistencies in the CMake documentation, I decided to ask
the question here as well.

Say I have packages A, B, and C. Package B uses package A and package C
uses package B. I create shared libraries.

So in package B I do something like

    find_package(A)
    ...
    if(${A_FOUND})
    target_link_libraries(B ${A_LIBRARIES})
    endif()

and in package C I do

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

    add_executable(main main.cpp)
    target_link_libraries(main C)

where ${B_LIBRARIES} contains only B. The compiler will now complain

    /usr/bin/ld: cannot find -lA
    collect2: error: ld returned 1 exit status

as long as A is installed in a place that is not in the default
directories. I was wondering what is the correct way of handling this.
For me using find_package(A) in C (which would work) doesn't seem to be
the nice. For me especially, because I don't know in advance if B
depends on A or not. It might also depend on a different package.

According to the documentation

https://cmake.org/cmake/help/v3.0/command/link_directories.html

"Library locations returned by find_package() and find_library() are
absolute paths.". This is true for system libraries like
/usr/lib/libmpi.so. However, this seems not to be true for most other
packages that I use. A reason for this might be that I use the
FooBarConfig.cmake file for finding the package (not a FindFooBar.cmake
file, since that's not always available). I myself create those
following this example:

https://cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file

Here we have the line

set(FOOBAR_LIBRARIES foo)

which in the end will not use absolute paths. You can, however, use this
file for the find_package function, so according to the documentation it
should return absolute paths, which it apparently does not. So this
results in the error I described above when I compile C (where it links
to -lA instead of /custompath/A.so). So what is the correct way of
handling this?

Thanks in advance and best regards,
Sven

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Chuck Atkins
The FooBarConfig.cmake is something that should be generated by FooBar's build.   The reason you don't get absolute paths for the "libraries" from a package config file is that they're not actually libraries but imported targets.  The imported target let's you treat "foo" as though it were a library built by your project.  It then has the appropriate target properties set on it ti define the full path to it's library, etc.  That being said, if you're manually creating the FooBarConfig.cmake that's not really the right approach.  If the FooBar buil;d doesn't actually generate it's own FooBarConfig.cmake file then you'll want to create you're own FindFooBar.cmake.  A bare bones find module that creates an imported target would look something like this:

if(NOT FooBar_FOUND AND NOT TARGET FooBar::FooBar)
  find_path(FooBar_INCLUDE_DIR FooBar.h)
  find_library(FooBar_LIBRARY FooBar)

  include(FindPackageHandleStandardArgs)
  find_package_handle_standard_args(FooBar
    FOUND_VAR FooBar_FOUND
    REQUIRED_VARS FooBar_INCLUDE_DIR FooBar_LIBRARY
  )
endif()

if(FooBar_FOUND AND NOT TARGET FooBar::FooBar)
  add_library(FooBar::FooBar UNKNOWN IMPORTED)
  set_target_properties(FooBar::FooBar PROPERTIES
    IMPORTED_LOCATION ${FooBar_LIBRARY}
    INTERFACE_INCLUDE_DIRECTORIES ${FooBar_INCLUDE_DIR}
  )
endif()


Then in your project you can use:

find_package(FooBar)
add_library(MyLib supercoolfiles.cxx)
target_libkLibraries(MyLib FooBar::FooBar)

Where this starts to get really helpful in your situation is if you have an imported target for A, B, and C, then you can create the appropriate dependencies.  Say, for example, you have a FindA.cmake that follows the pattern above and generates an A::A target.  Then in your FindB.cmake you can have:

if(NOT B_FOUND AND NOT TARGET B::B)
  find_path(B_INCLUDE_DIR B.h)
  find_library(B_LIBRARY B)

  include(FindPackageHandleStandardArgs)
  find_package_handle_standard_args(B
    FOUND_VAR B_FOUND
    REQUIRED_VARS B_INCLUDE_DIR B_LIBRARY
  )

  find_package(A QUIET)
  if(A_FOUND)
    set(B_Extra_Deps A::A)
  endif()

endif()

if(B_FOUND AND NOT TARGET B::B)
  add_library(B::B UNKNOWN IMPORTED)
  set_target_properties(B::B PROPERTIES
    IMPORTED_LOCATION ${B_LIBRARY}
    INTERFACE_INCLUDE_DIRECTORIES ${B_INCLUDE_DIR}
  )
  if(B_Extra_Deps)
    set_target_properties(B::B PROPERTIES
      INTERFACE_LINK_LIBRARIES ${B_Extra_Deps}
    )
  endif()

endif()


and similarly for FindC.cmake.  Since A::A, B::B, and C::C are actual proper CMake targets and not just library files then they carry with them associated target dependency information.  In CMake vernacular we refer this as "target usage requirements" since the target caries with it all the necessary information for something to actually use it, whether that's just extra link libraries or also extra include directories and compile definitions needed.  The Package::Target naming convention is the idea that each package has it's own namespace where you may define multiple targets.

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Sven Baars
In my case all projects provide their own FooBarConfig.cmake, but not a FindFooBar.cmake. For this reason I wanted to use those, because I thought it saves me the effort of writing a lot of FindFooBar.cmake files, and it also seemed like the right way to do it, because it provides things like FooBar_LIBRARIES, which is what I need. The reason I said that I create my own FooBarConfig.cmake, is because I want to use CMake properly in my own project, so I also want to provide a FoorBarConfig.cmake file for my users. So even if the projects I use don't do everything properly, I still want to do it properly myself. The problem in this case is that I'm not sure what the proper way is. If the FoorBarConfig.cmake file is not enough to handle the dependencies I encounter, should I provide a FindFooBar.cmake file or something, instead of just the FooBarConfig.cmake? And meanwhile also write a FindFooBar.cmake file for all my dependencies?

Another reason why this seems odd to me, is because if N different projects use FooBar, then also possibly N different versions of FindFooBar.cmake are created by all the different projects (I have actually already seen this a lot). That is the case, because the FindFooBar.cmake file is not provided by the FooBar project, unlike the FooBarConfig.cmake.

Cheers,
Sven

On 06/08/2016 03:11 PM, Chuck Atkins wrote:
The FooBarConfig.cmake is something that should be generated by FooBar's build.   The reason you don't get absolute paths for the "libraries" from a package config file is that they're not actually libraries but imported targets.  The imported target let's you treat "foo" as though it were a library built by your project.  It then has the appropriate target properties set on it ti define the full path to it's library, etc.  That being said, if you're manually creating the FooBarConfig.cmake that's not really the right approach.  If the FooBar buil;d doesn't actually generate it's own FooBarConfig.cmake file then you'll want to create you're own FindFooBar.cmake.  A bare bones find module that creates an imported target would look something like this:

if(NOT FooBar_FOUND AND NOT TARGET FooBar::FooBar)
  find_path(FooBar_INCLUDE_DIR FooBar.h)
  find_library(FooBar_LIBRARY FooBar)

  include(FindPackageHandleStandardArgs)
  find_package_handle_standard_args(FooBar
    FOUND_VAR FooBar_FOUND
    REQUIRED_VARS FooBar_INCLUDE_DIR FooBar_LIBRARY
  )
endif()

if(FooBar_FOUND AND NOT TARGET FooBar::FooBar)
  add_library(FooBar::FooBar UNKNOWN IMPORTED)
  set_target_properties(FooBar::FooBar PROPERTIES
    IMPORTED_LOCATION ${FooBar_LIBRARY}
    INTERFACE_INCLUDE_DIRECTORIES ${FooBar_INCLUDE_DIR}
  )
endif()


Then in your project you can use:

find_package(FooBar)
add_library(MyLib supercoolfiles.cxx)
target_libkLibraries(MyLib FooBar::FooBar)

Where this starts to get really helpful in your situation is if you have an imported target for A, B, and C, then you can create the appropriate dependencies.  Say, for example, you have a FindA.cmake that follows the pattern above and generates an A::A target.  Then in your FindB.cmake you can have:

if(NOT B_FOUND AND NOT TARGET B::B)
  find_path(B_INCLUDE_DIR B.h)
  find_library(B_LIBRARY B)

  include(FindPackageHandleStandardArgs)
  find_package_handle_standard_args(B
    FOUND_VAR B_FOUND
    REQUIRED_VARS B_INCLUDE_DIR B_LIBRARY
  )

  find_package(A QUIET)
  if(A_FOUND)
    set(B_Extra_Deps A::A)
  endif()

endif()

if(B_FOUND AND NOT TARGET B::B)
  add_library(B::B UNKNOWN IMPORTED)
  set_target_properties(B::B PROPERTIES
    IMPORTED_LOCATION ${B_LIBRARY}
    INTERFACE_INCLUDE_DIRECTORIES ${B_INCLUDE_DIR}
  )
  if(B_Extra_Deps)
    set_target_properties(B::B PROPERTIES
      INTERFACE_LINK_LIBRARIES ${B_Extra_Deps}
    )
  endif()

endif()


and similarly for FindC.cmake.  Since A::A, B::B, and C::C are actual proper CMake targets and not just library files then they carry with them associated target dependency information.  In CMake vernacular we refer this as "target usage requirements" since the target caries with it all the necessary information for something to actually use it, whether that's just extra link libraries or also extra include directories and compile definitions needed.  The Package::Target naming convention is the idea that each package has it's own namespace where you may define multiple targets.


--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Chuck Atkins
If the projects are each providing their own Config.cmake file then you probably will want to use those instead of Find modules.  Instead of using the Foo_Bar_LIBRARIES variable though, try using the actual imported targets from the config files.  Those should have the appropriate dependency information. If you're not sure what they are you should be able to dig through the provided Config.cmake and Targets.cmake files for FooBar and see which targets are created bu "add_library(FooBar::Foo ... IMPORTED)".

- Chuck

On Wed, Jun 8, 2016 at 11:31 AM, Sven Baars <[hidden email]> wrote:
In my case all projects provide their own FooBarConfig.cmake, but not a FindFooBar.cmake. For this reason I wanted to use those, because I thought it saves me the effort of writing a lot of FindFooBar.cmake files, and it also seemed like the right way to do it, because it provides things like FooBar_LIBRARIES, which is what I need. The reason I said that I create my own FooBarConfig.cmake, is because I want to use CMake properly in my own project, so I also want to provide a FoorBarConfig.cmake file for my users. So even if the projects I use don't do everything properly, I still want to do it properly myself. The problem in this case is that I'm not sure what the proper way is. If the FoorBarConfig.cmake file is not enough to handle the dependencies I encounter, should I provide a FindFooBar.cmake file or something, instead of just the FooBarConfig.cmake? And meanwhile also write a FindFooBar.cmake file for all my dependencies?

Another reason why this seems odd to me, is because if N different projects use FooBar, then also possibly N different versions of FindFooBar.cmake are created by all the different projects (I have actually already seen this a lot). That is the case, because the FindFooBar.cmake file is not provided by the FooBar project, unlike the FooBarConfig.cmake.

Cheers,
Sven


On 06/08/2016 03:11 PM, Chuck Atkins wrote:
The FooBarConfig.cmake is something that should be generated by FooBar's build.   The reason you don't get absolute paths for the "libraries" from a package config file is that they're not actually libraries but imported targets.  The imported target let's you treat "foo" as though it were a library built by your project.  It then has the appropriate target properties set on it ti define the full path to it's library, etc.  That being said, if you're manually creating the FooBarConfig.cmake that's not really the right approach.  If the FooBar buil;d doesn't actually generate it's own FooBarConfig.cmake file then you'll want to create you're own FindFooBar.cmake.  A bare bones find module that creates an imported target would look something like this:

if(NOT FooBar_FOUND AND NOT TARGET FooBar::FooBar)
  find_path(FooBar_INCLUDE_DIR FooBar.h)
  find_library(FooBar_LIBRARY FooBar)

  include(FindPackageHandleStandardArgs)
  find_package_handle_standard_args(FooBar
    FOUND_VAR FooBar_FOUND
    REQUIRED_VARS FooBar_INCLUDE_DIR FooBar_LIBRARY
  )
endif()

if(FooBar_FOUND AND NOT TARGET FooBar::FooBar)
  add_library(FooBar::FooBar UNKNOWN IMPORTED)
  set_target_properties(FooBar::FooBar PROPERTIES
    IMPORTED_LOCATION ${FooBar_LIBRARY}
    INTERFACE_INCLUDE_DIRECTORIES ${FooBar_INCLUDE_DIR}
  )
endif()


Then in your project you can use:

find_package(FooBar)
add_library(MyLib supercoolfiles.cxx)
target_libkLibraries(MyLib FooBar::FooBar)

Where this starts to get really helpful in your situation is if you have an imported target for A, B, and C, then you can create the appropriate dependencies.  Say, for example, you have a FindA.cmake that follows the pattern above and generates an A::A target.  Then in your FindB.cmake you can have:

if(NOT B_FOUND AND NOT TARGET B::B)
  find_path(B_INCLUDE_DIR B.h)
  find_library(B_LIBRARY B)

  include(FindPackageHandleStandardArgs)
  find_package_handle_standard_args(B
    FOUND_VAR B_FOUND
    REQUIRED_VARS B_INCLUDE_DIR B_LIBRARY
  )

  find_package(A QUIET)
  if(A_FOUND)
    set(B_Extra_Deps A::A)
  endif()

endif()

if(B_FOUND AND NOT TARGET B::B)
  add_library(B::B UNKNOWN IMPORTED)
  set_target_properties(B::B PROPERTIES
    IMPORTED_LOCATION ${B_LIBRARY}
    INTERFACE_INCLUDE_DIRECTORIES ${B_INCLUDE_DIR}
  )
  if(B_Extra_Deps)
    set_target_properties(B::B PROPERTIES
      INTERFACE_LINK_LIBRARIES ${B_Extra_Deps}
    )
  endif()

endif()


and similarly for FindC.cmake.  Since A::A, B::B, and C::C are actual proper CMake targets and not just library files then they carry with them associated target dependency information.  In CMake vernacular we refer this as "target usage requirements" since the target caries with it all the necessary information for something to actually use it, whether that's just extra link libraries or also extra include directories and compile definitions needed.  The Package::Target naming convention is the idea that each package has it's own namespace where you may define multiple targets.



--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Sven Baars
Hey Chuck,

In ATargets.cmake it says

add_library(a SHARED IMPORTED)

and in BTargets.cmake it says

add_library(b SHARED IMPORTED)

However, if I build C it will say

/usr/bin/ld: cannot find -la

when I do

    find_package(B)
    target_link_libraries(c b)
    add_executable(main main.cpp)
    target_link_libraries(main c)

This, I think, because the 'b' target depends on 'a' but doesn't know where 'a' is located, because this is not described in BTargets.cmake.

Sven

On 06/08/2016 06:07 PM, Chuck Atkins wrote:
If the projects are each providing their own Config.cmake file then you probably will want to use those instead of Find modules.  Instead of using the Foo_Bar_LIBRARIES variable though, try using the actual imported targets from the config files.  Those should have the appropriate dependency information. If you're not sure what they are you should be able to dig through the provided Config.cmake and Targets.cmake files for FooBar and see which targets are created bu "add_library(FooBar::Foo ... IMPORTED)".

- Chuck

On Wed, Jun 8, 2016 at 11:31 AM, Sven Baars <[hidden email]> wrote:
In my case all projects provide their own FooBarConfig.cmake, but not a FindFooBar.cmake. For this reason I wanted to use those, because I thought it saves me the effort of writing a lot of FindFooBar.cmake files, and it also seemed like the right way to do it, because it provides things like FooBar_LIBRARIES, which is what I need. The reason I said that I create my own FooBarConfig.cmake, is because I want to use CMake properly in my own project, so I also want to provide a FoorBarConfig.cmake file for my users. So even if the projects I use don't do everything properly, I still want to do it properly myself. The problem in this case is that I'm not sure what the proper way is. If the FoorBarConfig.cmake file is not enough to handle the dependencies I encounter, should I provide a FindFooBar.cmake file or something, instead of just the FooBarConfig.cmake? And meanwhile also write a FindFooBar.cmake file for all my dependencies?

Another reason why this seems odd to me, is because if N different projects use FooBar, then also possibly N different versions of FindFooBar.cmake are created by all the different projects (I have actually already seen this a lot). That is the case, because the FindFooBar.cmake file is not provided by the FooBar project, unlike the FooBarConfig.cmake.

Cheers,
Sven


On 06/08/2016 03:11 PM, Chuck Atkins wrote:
The FooBarConfig.cmake is something that should be generated by FooBar's build.   The reason you don't get absolute paths for the "libraries" from a package config file is that they're not actually libraries but imported targets.  The imported target let's you treat "foo" as though it were a library built by your project.  It then has the appropriate target properties set on it ti define the full path to it's library, etc.  That being said, if you're manually creating the FooBarConfig.cmake that's not really the right approach.  If the FooBar buil;d doesn't actually generate it's own FooBarConfig.cmake file then you'll want to create you're own FindFooBar.cmake.  A bare bones find module that creates an imported target would look something like this:

if(NOT FooBar_FOUND AND NOT TARGET FooBar::FooBar)
  find_path(FooBar_INCLUDE_DIR FooBar.h)
  find_library(FooBar_LIBRARY FooBar)

  include(FindPackageHandleStandardArgs)
  find_package_handle_standard_args(FooBar
    FOUND_VAR FooBar_FOUND
    REQUIRED_VARS FooBar_INCLUDE_DIR FooBar_LIBRARY
  )
endif()

if(FooBar_FOUND AND NOT TARGET FooBar::FooBar)
  add_library(FooBar::FooBar UNKNOWN IMPORTED)
  set_target_properties(FooBar::FooBar PROPERTIES
    IMPORTED_LOCATION ${FooBar_LIBRARY}
    INTERFACE_INCLUDE_DIRECTORIES ${FooBar_INCLUDE_DIR}
  )
endif()


Then in your project you can use:

find_package(FooBar)
add_library(MyLib supercoolfiles.cxx)
target_libkLibraries(MyLib FooBar::FooBar)

Where this starts to get really helpful in your situation is if you have an imported target for A, B, and C, then you can create the appropriate dependencies.  Say, for example, you have a FindA.cmake that follows the pattern above and generates an A::A target.  Then in your FindB.cmake you can have:

if(NOT B_FOUND AND NOT TARGET B::B)
  find_path(B_INCLUDE_DIR B.h)
  find_library(B_LIBRARY B)

  include(FindPackageHandleStandardArgs)
  find_package_handle_standard_args(B
    FOUND_VAR B_FOUND
    REQUIRED_VARS B_INCLUDE_DIR B_LIBRARY
  )

  find_package(A QUIET)
  if(A_FOUND)
    set(B_Extra_Deps A::A)
  endif()

endif()

if(B_FOUND AND NOT TARGET B::B)
  add_library(B::B UNKNOWN IMPORTED)
  set_target_properties(B::B PROPERTIES
    IMPORTED_LOCATION ${B_LIBRARY}
    INTERFACE_INCLUDE_DIRECTORIES ${B_INCLUDE_DIR}
  )
  if(B_Extra_Deps)
    set_target_properties(B::B PROPERTIES
      INTERFACE_LINK_LIBRARIES ${B_Extra_Deps}
    )
  endif()

endif()


and similarly for FindC.cmake.  Since A::A, B::B, and C::C are actual proper CMake targets and not just library files then they carry with them associated target dependency information.  In CMake vernacular we refer this as "target usage requirements" since the target caries with it all the necessary information for something to actually use it, whether that's just extra link libraries or also extra include directories and compile definitions needed.  The Package::Target naming convention is the idea that each package has it's own namespace where you may define multiple targets.




--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Sven Baars
Hey all,

Since I did not receive a reply to my previous mail, I decided to write a minimal example explaining my problem, where I kept al the names as I used in my previous mails. I hope that after seeing my example, someone can explain me what I am doing wrong here. I included a script that reproduces the problem.

Cheers,
Sven

On 06/10/2016 01:34 PM, Sven Baars wrote:
Hey Chuck,

In ATargets.cmake it says

add_library(a SHARED IMPORTED)

and in BTargets.cmake it says

add_library(b SHARED IMPORTED)

However, if I build C it will say

/usr/bin/ld: cannot find -la

when I do

    find_package(B)
    target_link_libraries(c b)
    add_executable(main main.cpp)
    target_link_libraries(main c)

This, I think, because the 'b' target depends on 'a' but doesn't know where 'a' is located, because this is not described in BTargets.cmake.

Sven

On 06/08/2016 06:07 PM, Chuck Atkins wrote:
If the projects are each providing their own Config.cmake file then you probably will want to use those instead of Find modules.  Instead of using the Foo_Bar_LIBRARIES variable though, try using the actual imported targets from the config files.  Those should have the appropriate dependency information. If you're not sure what they are you should be able to dig through the provided Config.cmake and Targets.cmake files for FooBar and see which targets are created bu "add_library(FooBar::Foo ... IMPORTED)".

- Chuck

On Wed, Jun 8, 2016 at 11:31 AM, Sven Baars <[hidden email]> wrote:
In my case all projects provide their own FooBarConfig.cmake, but not a FindFooBar.cmake. For this reason I wanted to use those, because I thought it saves me the effort of writing a lot of FindFooBar.cmake files, and it also seemed like the right way to do it, because it provides things like FooBar_LIBRARIES, which is what I need. The reason I said that I create my own FooBarConfig.cmake, is because I want to use CMake properly in my own project, so I also want to provide a FoorBarConfig.cmake file for my users. So even if the projects I use don't do everything properly, I still want to do it properly myself. The problem in this case is that I'm not sure what the proper way is. If the FoorBarConfig.cmake file is not enough to handle the dependencies I encounter, should I provide a FindFooBar.cmake file or something, instead of just the FooBarConfig.cmake? And meanwhile also write a FindFooBar.cmake file for all my dependencies?

Another reason why this seems odd to me, is because if N different projects use FooBar, then also possibly N different versions of FindFooBar.cmake are created by all the different projects (I have actually already seen this a lot). That is the case, because the FindFooBar.cmake file is not provided by the FooBar project, unlike the FooBarConfig.cmake.

Cheers,
Sven


On 06/08/2016 03:11 PM, Chuck Atkins wrote:
The FooBarConfig.cmake is something that should be generated by FooBar's build.   The reason you don't get absolute paths for the "libraries" from a package config file is that they're not actually libraries but imported targets.  The imported target let's you treat "foo" as though it were a library built by your project.  It then has the appropriate target properties set on it ti define the full path to it's library, etc.  That being said, if you're manually creating the FooBarConfig.cmake that's not really the right approach.  If the FooBar buil;d doesn't actually generate it's own FooBarConfig.cmake file then you'll want to create you're own FindFooBar.cmake.  A bare bones find module that creates an imported target would look something like this:

if(NOT FooBar_FOUND AND NOT TARGET FooBar::FooBar)
  find_path(FooBar_INCLUDE_DIR FooBar.h)
  find_library(FooBar_LIBRARY FooBar)

  include(FindPackageHandleStandardArgs)
  find_package_handle_standard_args(FooBar
    FOUND_VAR FooBar_FOUND
    REQUIRED_VARS FooBar_INCLUDE_DIR FooBar_LIBRARY
  )
endif()

if(FooBar_FOUND AND NOT TARGET FooBar::FooBar)
  add_library(FooBar::FooBar UNKNOWN IMPORTED)
  set_target_properties(FooBar::FooBar PROPERTIES
    IMPORTED_LOCATION ${FooBar_LIBRARY}
    INTERFACE_INCLUDE_DIRECTORIES ${FooBar_INCLUDE_DIR}
  )
endif()


Then in your project you can use:

find_package(FooBar)
add_library(MyLib supercoolfiles.cxx)
target_libkLibraries(MyLib FooBar::FooBar)

Where this starts to get really helpful in your situation is if you have an imported target for A, B, and C, then you can create the appropriate dependencies.  Say, for example, you have a FindA.cmake that follows the pattern above and generates an A::A target.  Then in your FindB.cmake you can have:

if(NOT B_FOUND AND NOT TARGET B::B)
  find_path(B_INCLUDE_DIR B.h)
  find_library(B_LIBRARY B)

  include(FindPackageHandleStandardArgs)
  find_package_handle_standard_args(B
    FOUND_VAR B_FOUND
    REQUIRED_VARS B_INCLUDE_DIR B_LIBRARY
  )

  find_package(A QUIET)
  if(A_FOUND)
    set(B_Extra_Deps A::A)
  endif()

endif()

if(B_FOUND AND NOT TARGET B::B)
  add_library(B::B UNKNOWN IMPORTED)
  set_target_properties(B::B PROPERTIES
    IMPORTED_LOCATION ${B_LIBRARY}
    INTERFACE_INCLUDE_DIRECTORIES ${B_INCLUDE_DIR}
  )
  if(B_Extra_Deps)
    set_target_properties(B::B PROPERTIES
      INTERFACE_LINK_LIBRARIES ${B_Extra_Deps}
    )
  endif()

endif()


and similarly for FindC.cmake.  Since A::A, B::B, and C::C are actual proper CMake targets and not just library files then they carry with them associated target dependency information.  In CMake vernacular we refer this as "target usage requirements" since the target caries with it all the necessary information for something to actually use it, whether that's just extra link libraries or also extra include directories and compile definitions needed.  The Package::Target naming convention is the idea that each package has it's own namespace where you may define multiple targets.





--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake

cmake-example.tar.gz (2K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Raymond Wan-2
Hi Sven,


On Tue, Jun 28, 2016 at 5:26 PM, Sven Baars <[hidden email]> wrote:

> Hey all,
>
> Since I did not receive a reply to my previous mail, I decided to write a
> minimal example explaining my problem, where I kept al the names as I used
> in my previous mails. I hope that after seeing my example, someone can
> explain me what I am doing wrong here. I included a script that reproduces
> the problem.
>
> Cheers,
> Sven


I'm not much of an expert with CMake, but I can explain to you what
I've done, at least.

If I understand correctly, package X makes use of package Y, but
during compilation, it cannot find it?  I think what you can do
depends on whether X and Y are in two separate source trees.

If they are, then it is almost like Y is the zlib library.  Then what
you can do is, like the zlib library, install it into a system
directory (i.e., via INSTALL ()) and then X will use a FIND_PACKAGE to
look for it.

But, suppose Y isn't like zlib.  For example, it is a library that is
within the same source tree and will only ever be used by X (both of
which are written by you).  I think this is the scenario that you're
talking about?  In my case, I have done this in my CMakeLists.txt:

SET (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

I guess you can set it
[https://cmake.org/cmake/help/v3.3/variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY.html]
to anything so that all of the libraries will be installed into one
place without doing an INSTALL.  Of course, this directory is or
somewhere within the build/ directory.  (I suppose doing an install
into ${CMAKE_BINARY_DIR} would achieve the same thing?)

I had previously installed Y's archive into a system directory, but
besides the need to run FIND_PACKAGE, I thought it was "silly" to
install an archive into a system directory that is only used by my own
program.  Seems a bit messy and intrusive to the end-user -- my
libraries are quite unlike zlib; few chance someone else will use it
:-) .  At the very least, this approach keeps it in one place within
build/ .

I'm not sure if it is the "right" way to do it, but this is what I do
at the moment...  I hope it helps!

Ray
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Sven Baars
Hi Ray,

The packages I use are installed in a non-standard path, because I don't
have access to the system directories on most systems I work on, but are
used by many other libraries. They are also all separate packages, not
packages in the same source tree. I did not see my attachment on the
mailing list archive, so instead I just put it on Github. It can be
found here:

https://github.com/Sbte/cmake-example

I hope the example shows my workflow, and also what doesn't work for me.

Sven

On 06/28/2016 11:52 AM, Raymond Wan wrote:

> Hi Sven,
>
>
> On Tue, Jun 28, 2016 at 5:26 PM, Sven Baars <[hidden email]> wrote:
>> Hey all,
>>
>> Since I did not receive a reply to my previous mail, I decided to write a
>> minimal example explaining my problem, where I kept al the names as I used
>> in my previous mails. I hope that after seeing my example, someone can
>> explain me what I am doing wrong here. I included a script that reproduces
>> the problem.
>>
>> Cheers,
>> Sven
>
> I'm not much of an expert with CMake, but I can explain to you what
> I've done, at least.
>
> If I understand correctly, package X makes use of package Y, but
> during compilation, it cannot find it?  I think what you can do
> depends on whether X and Y are in two separate source trees.
>
> If they are, then it is almost like Y is the zlib library.  Then what
> you can do is, like the zlib library, install it into a system
> directory (i.e., via INSTALL ()) and then X will use a FIND_PACKAGE to
> look for it.
>
> But, suppose Y isn't like zlib.  For example, it is a library that is
> within the same source tree and will only ever be used by X (both of
> which are written by you).  I think this is the scenario that you're
> talking about?  In my case, I have done this in my CMakeLists.txt:
>
> SET (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
>
> I guess you can set it
> [https://cmake.org/cmake/help/v3.3/variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY.html]
> to anything so that all of the libraries will be installed into one
> place without doing an INSTALL.  Of course, this directory is or
> somewhere within the build/ directory.  (I suppose doing an install
> into ${CMAKE_BINARY_DIR} would achieve the same thing?)
>
> I had previously installed Y's archive into a system directory, but
> besides the need to run FIND_PACKAGE, I thought it was "silly" to
> install an archive into a system directory that is only used by my own
> program.  Seems a bit messy and intrusive to the end-user -- my
> libraries are quite unlike zlib; few chance someone else will use it
> :-) .  At the very least, this approach keeps it in one place within
> build/ .
>
> I'm not sure if it is the "right" way to do it, but this is what I do
> at the moment...  I hope it helps!
>
> Ray

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Raymond Wan-2
Hi Sven,


On Tue, Jun 28, 2016 at 6:03 PM, Sven Baars <[hidden email]> wrote:

> The packages I use are installed in a non-standard path, because I don't
> have access to the system directories on most systems I work on, but are
> used by many other libraries. They are also all separate packages, not
> packages in the same source tree. I did not see my attachment on the
> mailing list archive, so instead I just put it on Github. It can be
> found here:
>
> https://github.com/Sbte/cmake-example
>
> I hope the example shows my workflow, and also what doesn't work for me.


Hmmmm, in that case, I should probably remain quiet as this is not
quite something I've had to do.

Maybe the only advice I can give is, if you plan to distribute your
work to others, what are your expectations in terms of where do you
think users should install these dependencies.

For example, if it's a system-level directory, then maybe you can
consider a FIND_PACKAGE solution which has a list of default paths to
search.  When you're developing on your own computer, you just change
the default path to include paths in your home directory.

There is also the ExternalProject () directive which you could
consider [https://cmake.org/cmake/help/v3.3/module/ExternalProject.html]
.  This would retrieve the dependencies from outside sources (i.e.,
repositories) and build them.  This would keep everything within the
same build/ path and I haven't done that (and didn't mention it
before) because all of my packages are within the same source tree.

So, still not quite your situation, though.

I hope this helps!  Perhaps others can chime in and help you with
exactly what you're stuck with...

Ray
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Sven Baars
Hey Ray,

Project A is used by many projects, and so is project B. So
ExternalProject is not the right solution. I just want to be able to fix
project B in such a way that people, including myself, can easily use it
without knowledge of where project A is located. The packages will all
be used mostly on supercomputers, where users never have rights to
install anything, and even if they install them as a module, it is still
in a non-standard path. As you can see from the example, this works fine
for project B which depends on A, but not for project C which depends on
B. Even if you set the PATH correctly.

Sven

On 06/28/2016 12:25 PM, Raymond Wan wrote:

> Hi Sven,
>
>
> On Tue, Jun 28, 2016 at 6:03 PM, Sven Baars <[hidden email]> wrote:
>> The packages I use are installed in a non-standard path, because I don't
>> have access to the system directories on most systems I work on, but are
>> used by many other libraries. They are also all separate packages, not
>> packages in the same source tree. I did not see my attachment on the
>> mailing list archive, so instead I just put it on Github. It can be
>> found here:
>>
>> https://github.com/Sbte/cmake-example
>>
>> I hope the example shows my workflow, and also what doesn't work for me.
>
> Hmmmm, in that case, I should probably remain quiet as this is not
> quite something I've had to do.
>
> Maybe the only advice I can give is, if you plan to distribute your
> work to others, what are your expectations in terms of where do you
> think users should install these dependencies.
>
> For example, if it's a system-level directory, then maybe you can
> consider a FIND_PACKAGE solution which has a list of default paths to
> search.  When you're developing on your own computer, you just change
> the default path to include paths in your home directory.
>
> There is also the ExternalProject () directive which you could
> consider [https://cmake.org/cmake/help/v3.3/module/ExternalProject.html]
> .  This would retrieve the dependencies from outside sources (i.e.,
> repositories) and build them.  This would keep everything within the
> same build/ path and I haven't done that (and didn't mention it
> before) because all of my packages are within the same source tree.
>
> So, still not quite your situation, though.
>
> I hope this helps!  Perhaps others can chime in and help you with
> exactly what you're stuck with...
>
> Ray

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Cfyz
Hello.

I've posted a message a few days ago on a very similar subject. Didn't know there was a discussion already.

The main problem in my opinion is that CMake target exporting system does not handle transitive dependencies at all. CMake handles them correctly at the build step, but not at the export. As I've noted in my message there is a small hint on that being a conscious decision: documentation about target_link_libraries and relevant target properties advises not to include paths to dependencies into the target interface as it would hard-code dependencies' locations. Personally I do not agree with that as I see neither any way around specifying paths to dependencies not any substantial harm in that. Maybe I am missing something but as far as I've found there was not discussion about this matter before.

With that there are some ways to make transitive dependencies work. Though you'll have to forsake most of CMake's export machinery. Probably the easiest way is to make each library export it's full interface in the Foo_INCLUDE_DIRS / Foo_LIBRARIES variables. By writing the AConfig.cmake by hand you can figure out and export the full path to the A. Therefore AConfig.cmake will essentially be:

  get_filename_component(A_CONFIG_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
  find_library(A_LIB "A" HINTS ${A_CONFIG_DIR}/../../../lib)
  set(A_INCLUDE_DIRS ${A_CONFIG_DIR}/../../../include)
  set(A_LIBRARIES ${A_LIB})
  set(A_FOUND TRUE)

From here on, every other library which care about its dependencies will have to export its interface in a similar way. However, since BConfig.cmake cannot find A by itself, it will need some help from the project configuration step. B project will need to gather its interface and do a configure_file() fixing B's interface dependencies in it:

  find_package(A)
  list(APPEND B_INTERFACE_INCLUDE_DIRS ${A_INCLUDE_DIRS})
  list(APPEND B_INTERFACE_LIBRARIES ${A_LIBRARIES}) # here comes the full path to A library
  ...
  configure_file(BConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/BConfig.cmake @ONLY)

Where BConfig.cmake.in may look like:

  get_filename_component(B_CONFIG_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
  find_library(B_LIB "B" HINTS ${B_CONFIG_DIR}/../../../lib)
  set(B_INCLUDE_DIRS ${B_CONFIG_DIR}/../../../include @B_INTERFACE_INCLUDE_DIRS@)
  set(B_LIBRARIES ${B_LIB} @B_INTERFACE_LIBRARIES@)
  set(B_FOUND TRUE)

Now find_package(B) will export B_INCLUDE_DIRS / B_LIBRARIES which will list full paths to everything necessary to build against it.

At my company we usually use static libraries so that it's rarely a problem but with dynamic libraries (.so) this approach will not be enough to run the app. Searching for dynamic libraries is not exactly the build system responsibility, though and greatly depends on the platform and the way you distribute the resulting application. If anything it always possible to make another transitive Foo_RPATHS property.

This 'simple' approach does not work with libraries that export 'imported targets' only (if I recall correctly, the Qt find module exports Qt::XYZ targets but not Qt_LIBRARIES) so that there is no interface variables to merge. In this case one would need to iterate over imported targets and merge their INTERFACE_xxx properties in a similar way.

I believe this to be an oversight. Everything should be fine if there was an option to resolve and export transitive dependencies along the targets in CMake export() command. Probably this may be fixed by an external helper script (similar to CMakePackageConfigHelpers module) providing some function that takes a list of targets, analyzes them and writes a config file complete with targets and their dependencies.

On 28 June 2016 at 13:35, Sven Baars <[hidden email]> wrote:
Hey Ray,

Project A is used by many projects, and so is project B. So
ExternalProject is not the right solution. I just want to be able to fix
project B in such a way that people, including myself, can easily use it
without knowledge of where project A is located. The packages will all
be used mostly on supercomputers, where users never have rights to
install anything, and even if they install them as a module, it is still
in a non-standard path. As you can see from the example, this works fine
for project B which depends on A, but not for project C which depends on
B. Even if you set the PATH correctly.

Sven

On 06/28/2016 12:25 PM, Raymond Wan wrote:
> Hi Sven,
>
>
> On Tue, Jun 28, 2016 at 6:03 PM, Sven Baars <[hidden email]> wrote:
>> The packages I use are installed in a non-standard path, because I don't
>> have access to the system directories on most systems I work on, but are
>> used by many other libraries. They are also all separate packages, not
>> packages in the same source tree. I did not see my attachment on the
>> mailing list archive, so instead I just put it on Github. It can be
>> found here:
>>
>> https://github.com/Sbte/cmake-example
>>
>> I hope the example shows my workflow, and also what doesn't work for me.
>
> Hmmmm, in that case, I should probably remain quiet as this is not
> quite something I've had to do.
>
> Maybe the only advice I can give is, if you plan to distribute your
> work to others, what are your expectations in terms of where do you
> think users should install these dependencies.
>
> For example, if it's a system-level directory, then maybe you can
> consider a FIND_PACKAGE solution which has a list of default paths to
> search.  When you're developing on your own computer, you just change
> the default path to include paths in your home directory.
>
> There is also the ExternalProject () directive which you could
> consider [https://cmake.org/cmake/help/v3.3/module/ExternalProject.html]
> .  This would retrieve the dependencies from outside sources (i.e.,
> repositories) and build them.  This would keep everything within the
> same build/ path and I haven't done that (and didn't mention it
> before) because all of my packages are within the same source tree.
>
> So, still not quite your situation, though.
>
> I hope this helps!  Perhaps others can chime in and help you with
> exactly what you're stuck with...
>
> Ray

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake


--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Sven Baars
In reply to this post by Sven Baars
Hey Cfyz,

After reading your post to the list, it does indeed seem like we have the same problem. I also wrote a lot of homebrew code you mentioned at the end of the post, but it indeed always seems to always break something for some user of the code, even though it seems to work for everyone else. Hence my question if there is some "right" way of doing this with CMake, without all of the code I wrote to work around the problem.

In the mean time I'll have a look at the code you wrote, but it seems very similar to something I already had, which broke for some users.

Sven

On 06/28/2016 02:35 PM, Cfyz wrote:
Hello.

I've posted a message a few days ago on a very similar subject. Didn't know there was a discussion already.

The main problem in my opinion is that CMake target exporting system does not handle transitive dependencies at all. CMake handles them correctly at the build step, but not at the export. As I've noted in my message there is a small hint on that being a conscious decision: documentation about target_link_libraries and relevant target properties advises not to include paths to dependencies into the target interface as it would hard-code dependencies' locations. Personally I do not agree with that as I see neither any way around specifying paths to dependencies not any substantial harm in that. Maybe I am missing something but as far as I've found there was not discussion about this matter before.

With that there are some ways to make transitive dependencies work. Though you'll have to forsake most of CMake's export machinery. Probably the easiest way is to make each library export it's full interface in the Foo_INCLUDE_DIRS / Foo_LIBRARIES variables. By writing the AConfig.cmake by hand you can figure out and export the full path to the A. Therefore AConfig.cmake will essentially be:

  get_filename_component(A_CONFIG_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
  find_library(A_LIB "A" HINTS ${A_CONFIG_DIR}/../../../lib)
  set(A_INCLUDE_DIRS ${A_CONFIG_DIR}/../../../include)
  set(A_LIBRARIES ${A_LIB})
  set(A_FOUND TRUE)

From here on, every other library which care about its dependencies will have to export its interface in a similar way. However, since BConfig.cmake cannot find A by itself, it will need some help from the project configuration step. B project will need to gather its interface and do a configure_file() fixing B's interface dependencies in it:

  find_package(A)
  list(APPEND B_INTERFACE_INCLUDE_DIRS ${A_INCLUDE_DIRS})
  list(APPEND B_INTERFACE_LIBRARIES ${A_LIBRARIES}) # here comes the full path to A library
  ...
  configure_file(BConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/BConfig.cmake @ONLY)

Where BConfig.cmake.in may look like:

  get_filename_component(B_CONFIG_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
  find_library(B_LIB "B" HINTS ${B_CONFIG_DIR}/../../../lib)
  set(B_INCLUDE_DIRS ${B_CONFIG_DIR}/../../../include @B_INTERFACE_INCLUDE_DIRS@)
  set(B_LIBRARIES ${B_LIB} @B_INTERFACE_LIBRARIES@)
  set(B_FOUND TRUE)

Now find_package(B) will export B_INCLUDE_DIRS / B_LIBRARIES which will list full paths to everything necessary to build against it.

At my company we usually use static libraries so that it's rarely a problem but with dynamic libraries (.so) this approach will not be enough to run the app. Searching for dynamic libraries is not exactly the build system responsibility, though and greatly depends on the platform and the way you distribute the resulting application. If anything it always possible to make another transitive Foo_RPATHS property.

This 'simple' approach does not work with libraries that export 'imported targets' only (if I recall correctly, the Qt find module exports Qt::XYZ targets but not Qt_LIBRARIES) so that there is no interface variables to merge. In this case one would need to iterate over imported targets and merge their INTERFACE_xxx properties in a similar way.

I believe this to be an oversight. Everything should be fine if there was an option to resolve and export transitive dependencies along the targets in CMake export() command. Probably this may be fixed by an external helper script (similar to CMakePackageConfigHelpers module) providing some function that takes a list of targets, analyzes them and writes a config file complete with targets and their dependencies.

On 28 June 2016 at 13:35, Sven Baars <[hidden email]> wrote:
Hey Ray,

Project A is used by many projects, and so is project B. So
ExternalProject is not the right solution. I just want to be able to fix
project B in such a way that people, including myself, can easily use it
without knowledge of where project A is located. The packages will all
be used mostly on supercomputers, where users never have rights to
install anything, and even if they install them as a module, it is still
in a non-standard path. As you can see from the example, this works fine
for project B which depends on A, but not for project C which depends on
B. Even if you set the PATH correctly.

Sven

On 06/28/2016 12:25 PM, Raymond Wan wrote:
> Hi Sven,
>
>
> On Tue, Jun 28, 2016 at 6:03 PM, Sven Baars <[hidden email]> wrote:
>> The packages I use are installed in a non-standard path, because I don't
>> have access to the system directories on most systems I work on, but are
>> used by many other libraries. They are also all separate packages, not
>> packages in the same source tree. I did not see my attachment on the
>> mailing list archive, so instead I just put it on Github. It can be
>> found here:
>>
>> https://github.com/Sbte/cmake-example
>>
>> I hope the example shows my workflow, and also what doesn't work for me.
>
> Hmmmm, in that case, I should probably remain quiet as this is not
> quite something I've had to do.
>
> Maybe the only advice I can give is, if you plan to distribute your
> work to others, what are your expectations in terms of where do you
> think users should install these dependencies.
>
> For example, if it's a system-level directory, then maybe you can
> consider a FIND_PACKAGE solution which has a list of default paths to
> search.  When you're developing on your own computer, you just change
> the default path to include paths in your home directory.
>
> There is also the ExternalProject () directive which you could
> consider [https://cmake.org/cmake/help/v3.3/module/ExternalProject.html]
> .  This would retrieve the dependencies from outside sources (i.e.,
> repositories) and build them.  This would keep everything within the
> same build/ path and I haven't done that (and didn't mention it
> before) because all of my packages are within the same source tree.
>
> So, still not quite your situation, though.
>
> I hope this helps!  Perhaps others can chime in and help you with
> exactly what you're stuck with...
>
> Ray

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake



--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Raymond Wan-2
In reply to this post by Cfyz
Hi,


On Tue, Jun 28, 2016 at 8:41 PM, Cfyz <[hidden email]> wrote:
> dependencies' locations. Personally I do not agree with that as I see
> neither any way around specifying paths to dependencies not any substantial
> harm in that. Maybe I am missing something but as far as I've found there
> was not discussion about this matter before.


Actually, there has been discussions about transitive dependencies
before.  In fact, such discussions crop up once a month or two.

See for example,
http://public.kitware.com/pipermail/cmake/2016-January/062590.html
(which I did reply, also with a link to my GitHub repository with a
minimal example).  Perhaps many others before me have also done the
same.  [Again, just because I reply doesn't mean I think I'm
right...I'm learning through discussions, as well!]

In my humble opinion, Sven's problem is two-fold.  They are
inter-related, but they could be separated.  The first is the
transitive dependency and for this, if it's all within the same source
code tree then something like what I did could work.  The second is
that the dependencies are not installed in system-level directories,
even though multiple users on a super-computer need to share them.

Because of this second factor, I don't have an idea what Sven should
do.  Indeed, what you suggest could work -- as I don't have a need, I
haven't given that much thought.

I think if I were presented with the same problem as Sven, I'd ask the
system administrator to install it.  Or, if that wasn't possible, use
ExternalProject.  Yes, if there are 100 users, then there would be 100
copies of the dependency.  But, running CMake will grab the most
recent copy from the source repository.  It's inefficient in terms of
disk space, but at least A (assuming A depends on B) will be built
correctly.  I don't know if CMake's aim is to build software correctly
*and* save disk space...  :-)

Ray
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Cfyz
In reply to this post by Sven Baars
Hello Sven, Raymond.

On 28 June 2016 at 16:07, Sven Baars <[hidden email]> wrote:
> Hence my question if there is some "right" way of doing this with CMake, without all of the code I wrote to work around the problem.

I am under impression there is an important bit missing from CMake export system. If some library has an unspecified set of dependencies (decided during its configuration) then it will not be able to generate a config file for find_package with CMake default tools alone. I think I will raise it as an issue at the main CMake issue tracker after some more investigation.


On 28 June 2016 at 16:07, Sven Baars <[hidden email]> wrote:
> I also wrote a lot of homebrew code you mentioned at the end of the post, but it indeed always seems to always break something for some user of the code
> In the mean time I'll have a look at the code you wrote, but it seems very similar to something I already had, which broke for some users.

The code examples and what I've mentioned earlier are just pieces of the possible solution. A complete export has a lot of nuances (e. g. versioning, build configurations, etc.) and is unlikely to work flawlessly right from the start. But think it might be worthwhile to try and make such helper module somewhere on github.


On 28 June 2016 at 17:19, Raymond Wan <[hidden email]> wrote:
> I think if I were presented with the same problem as Sven, I'd <...> Or, if that wasn't possible, use ExternalProject.
> It's inefficient in terms of disk space, but at least A (assuming A depends on B) will be built correctly.

What I'm trying to solve (and what Sven's problem looks very similar to) is more about keeping the information about dependencies. You've mentioned that yourself in the linked discussion: the real problem are projects with complex tree-like dependencies, more than one edge deep. And once those dependencies become optional and configurable, things break completely. It is impossible to search for the dependency you don't even know about =(.

ExternalProject has a somewhat similar flaw. I've tried once to use it for FFmpeg and found out that ExternalProject does its work at the build step. On the configure step there is nothing yet and consequently there is no way to figure out what will be needed to link against the library. Even though FFmpeg does report its dependencies (via pkg-config) later after being installed, it is too late. There was a workaround with two-step build but that looked ugly, scaled even worse and I've settled on separate builds and custom find modules.



--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Raymond Wan-2
On Wed, Jun 29, 2016 at 3:23 AM, Cfyz <[hidden email]> wrote:

> On 28 June 2016 at 17:19, Raymond Wan <[hidden email]> wrote:
>> I think if I were presented with the same problem as Sven, I'd <...> Or,
>> if that wasn't possible, use ExternalProject.
>> It's inefficient in terms of disk space, but at least A (assuming A
>> depends on B) will be built correctly.
> What I'm trying to solve (and what Sven's problem looks very similar to) is
> more about keeping the information about dependencies. You've mentioned that
> yourself in the linked discussion: the real problem are projects with
> complex tree-like dependencies, more than one edge deep. And once those
> dependencies become optional and configurable, things break completely. It
> is impossible to search for the dependency you don't even know about =(.


I agree that what we're observing is a problem, but I don't think it
is that big.  There are at least 3 solutions discussed so far:

1)  The "ad-hoc" method I first mentioned by setting
CMAKE_LIBRARY_OUTPUT_DIRECTORY.
2)  ExternalProject which will grab a repository and build it.
3)  Some Find_Package () mechanism that will do a search for it.
4)  Your option of including *.cmake files that provide the paths
[sorry, I might have misunderstood it].

If we have some kind of transitive dependency:  A depends on B; B depends on C.

Then when we build A, we don't really need to know [in detail] that
this transitive dependency exists (*).  All the compiler needs to know
is where is B and where is C.  And if B and C are in the same
directory (i.e., a system-level directory), that's fine.

Suppose B and C are in two different directories.  I don't know if
it's common, but often, I see install scripts provide a symbolic link
from the system-level directory to where B and C are

In Sven's case (sorry to put you on the spot, Sven!  :-) ), the 3
options don't work because:

1)  Modules are in different source trees.
2)  Duplication between users on a super-computer.
3)  Too many combinations of Find_Package ().
4)  Seems ad-hoc?

Though not perfect, either (2) or (3) could solve Sven's problem.  For
(2), ignore duplication.  For (3), how about something like what
Find_Boost does?  It searches for system-level directories, but you
can nudge it by setting an environment variable (i.e., BOOST_ROOT)
where it will search first.  This means each user will have to set an
environment variable (or set it on the command-line of CMake with -D).

Hmmmmm, I *think* any of this is fine (for Sven's problem), but if it
isn't then perhaps I'm misunderstanding the problem...

Ray

(*)  At least, the order to the archives in target_link_libraries have
to be correct.  But that is done once by the CMakeLists.txt writer and
not something the end user needs to worry about.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Cfyz
On 29 June 2016 at 05:08, Raymond Wan <[hidden email]> wrote:
> I agree that what we're observing is a problem, but I don't think it is that big.

I must admit I am mixing a bit of my own situation here and trying to think about the most general case. It's just there is a missing bit in the dependency search system and how far will it bleed into a project depends on the situation. In my case it breaks on static libraries. Neither installing in same stage directory nor ExternalProject go around the fact that such targets just does not provide enough to link against them.

In case of dynamic libraries, it breaks if components are not located in (or installed to during build) the same path. Library B may find its dependency with some help (e. g. LIB_A_PATH during configure) and list libA.so in the dynamic section. But the next steps will still need to know libA.so location to link.


On 29 June 2016 at 05:08, Raymond Wan <[hidden email]> wrote:
> ExternalProject which will grab a repository and build it.

Still, what about the fact that ExternalProject provides dependency information on the main project build step, after the configuration? I've found it quite disappointing and severely limiting ExternalProject usefulness. Especially with CMake-based projects where you cannot use usual find_package to search for that external project because its configuration file would not be installed until much later.

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Sven Baars
In reply to this post by Raymond Wan-2
This is a reply to the options that Ray gave. Here I will use the
package dependencies C -> B -> A{1,2}:

1)  The "ad-hoc" method I first mentioned by setting
CMAKE_LIBRARY_OUTPUT_DIRECTORY.

As far as I understand, this would mean that every user of all of the
different projects would have to be forced to use this, and would not be
allowed to "install" anything anywhere else, which doesn't seem nice.

2)  ExternalProject which will grab a repository and build it.

This will not work. One of the projects I use is Trilinos, which has
build of around 1GB. I don't want to pull and build that for every
project I have. Also the build flags that are used sometimes differ per
machine, not per project, so it would be nice if I could build it only
once per machine.

Also, in a more generalized sense, this would also mean that every
project I pull with ExtenalProject should also pull its own dependencies
with ExternalProject. So then if every project on my system used CMake,
this would mean that I would recursively rebuild my entire system for
every project I have. This doesn't seem right.

3)  Some Find_Package () mechanism that will do a search for it.

The point I had is that we actually try to use this. However, the
find_package does not find all dependencies. And we don't know in
package C whether it depends on A1 or A2, because of build flags/CMake
checks that were used for project B. So we can't just do a find_package
for either A1 or A2, because we don't know which one was used unless we
perform all the CMake checks that were done in project B (in some cases
10k+ lines of CMake code).

4)  Your option of including *.cmake files that provide the paths
[sorry, I might have misunderstood it].

This, so far, is the only option, because then B can tell us that it
used A2, not A1. This can just be done by providing absolute paths to
the libraries that were used in the compilation of B. But we are looking
for a standardized way to do this. I'd prefer to not have a lot of
custom code in all of my libraries.

Now some more information:

On supercomputers it is very common that every library on the system is
installed in a different directory. This is so every user can load their
own version of the library without breaking the system for others.
Therefore, you will never find libraries that are installed in the
standard system directories where CMake looks for the libraries. By
using PATH you can make it able to find the place where to look for the
FoobarConfig.cmake files, which is great when you want to build project
B, and this is also done automatically on all supercomputers I work on,
but those config files do not contain information on where the actual
libraries of project A are when you build project C. I guess Cfyz and me
think they should in some standardized way.

Sven
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Raymond Wan-2
Hi Sven,


On Thu, Jun 30, 2016 at 4:59 PM, Sven Baars <[hidden email]> wrote:
> This is a reply to the options that Ray gave. Here I will use the
> package dependencies C -> B -> A{1,2}:


Well, I presented some options to you.  Perhaps there are others, but
if none of them are right for you then there's nothing more I can add,
I think.


> On supercomputers it is very common that every library on the system is
> installed in a different directory. This is so every user can load their
> own version of the library without breaking the system for others.


Sure.  So, during the CMake run, you can set CMAKE_INSTALL_PREFIX to
be something like ~/lib/ or ~/mylib/ or whatever.


> Therefore, you will never find libraries that are installed in the
> standard system directories where CMake looks for the libraries. By


Well, I wasn't suggesting that you use Find_Package as-is.  I mean the
phrase "CMake looks for the libraries" isn't quite correct here since
its behaviour is affected by the Find_Package's implementation.

Presumably, you will need to write your own for the modules you're
working with.  One person would write it and this file would be
shared.

How it would work is "something like" (i.e., you need to look at how
it works yourself) the Boost library.  With that, you can set
BOOST_ROOT to override the system-installed version.  (Take a look at:
 https://cmake.org/cmake/help/v3.3/module/FindBoost.html)

I think I said this early on, but perhaps I didn't explain it very well.

Thus, each user would set an environment variable that would affect
the search path of this Find_Package that you wrote.  If this is
troublesome, then you can add some favourite paths like ~/lib/ and
~/mylib/ as default paths to the search first.

I think it is a bit unreasonable for CMake to "automatically" know
where libraries are stored for each user other than performing a
recursive search down ~/ .  (I suppose that's possible.)  To reduce
the search space for binary programs that we've installed in ~/, we
would set the PATH variable.  I don't think it's that much different
from setting something like BOOST_ROOT and then getting a Find_Package
that you've written to use this as the starting point for a search.

I mean, it seems strange to expect CMake to be able to find archive
files by itself but, by default, we do not expect the same for
executable files...

Ray
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Sven Baars
Hi Ray,

This still has the same problem. If I use FindBoost in project B, I can
use BOOST_ROOT to be able to find it. This works fine. Now, if I try to
compile project C, I can set B_ROOT for FindB, but then Boost will not
be found, because it is not in B_ROOT, so project C will not compile.
That is, unless Boost sets absolute paths for all its libraries. Which
is something we have would have to do manually with custom CMake code as
per option 4.

I don't find it weird that CMake should be able to find Boost in project
C, since Boost was already found and used in project B. And we only link
to project B explicitly in project C, not to Boost. Actually in C we
don't use any Boost functionality other than what is used inside of B.
So why should C then explicitly look for Boost, require BOOST_ROOT to do
so, then do a lot of checks to see if B actually uses Boost, and in that
case link to it, when we don't use Boost in C?

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).

Note that by finding a library, I mean that it should know where it is,
by for instance using absolute paths at linking time, which I think is
sufficient. I don't mean doing all the things that are done in Find*, or
going through directories to find the library.

Sven

On 06/30/2016 12:10 PM, Raymond Wan wrote:

> Hi Sven,
>
>
> On Thu, Jun 30, 2016 at 4:59 PM, Sven Baars <[hidden email]> wrote:
>> This is a reply to the options that Ray gave. Here I will use the
>> package dependencies C -> B -> A{1,2}:
>
> Well, I presented some options to you.  Perhaps there are others, but
> if none of them are right for you then there's nothing more I can add,
> I think.
>
>
>> On supercomputers it is very common that every library on the system is
>> installed in a different directory. This is so every user can load their
>> own version of the library without breaking the system for others.
>
> Sure.  So, during the CMake run, you can set CMAKE_INSTALL_PREFIX to
> be something like ~/lib/ or ~/mylib/ or whatever.
>
>
>> Therefore, you will never find libraries that are installed in the
>> standard system directories where CMake looks for the libraries. By
>
> Well, I wasn't suggesting that you use Find_Package as-is.  I mean the
> phrase "CMake looks for the libraries" isn't quite correct here since
> its behaviour is affected by the Find_Package's implementation.
>
> Presumably, you will need to write your own for the modules you're
> working with.  One person would write it and this file would be
> shared.
>
> How it would work is "something like" (i.e., you need to look at how
> it works yourself) the Boost library.  With that, you can set
> BOOST_ROOT to override the system-installed version.  (Take a look at:
>  https://cmake.org/cmake/help/v3.3/module/FindBoost.html)
>
> I think I said this early on, but perhaps I didn't explain it very well.
>
> Thus, each user would set an environment variable that would affect
> the search path of this Find_Package that you wrote.  If this is
> troublesome, then you can add some favourite paths like ~/lib/ and
> ~/mylib/ as default paths to the search first.
>
> I think it is a bit unreasonable for CMake to "automatically" know
> where libraries are stored for each user other than performing a
> recursive search down ~/ .  (I suppose that's possible.)  To reduce
> the search space for binary programs that we've installed in ~/, we
> would set the PATH variable.  I don't think it's that much different
> from setting something like BOOST_ROOT and then getting a Find_Package
> that you've written to use this as the starting point for a search.
>
> I mean, it seems strange to expect CMake to be able to find archive
> files by itself but, by default, we do not expect the same for
> executable files...
>
> Ray

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: How do you handle recursive dependencies in CMake

Raymond Wan-2
Hi Sven,


On Thu, Jun 30, 2016 at 6:40 PM, Sven Baars <[hidden email]> 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
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
12