ome / ome-files-cpp

OME Files is a C++ library for reading and writing data using the open and standard OME-TIFF file format using the OME data model
https://www.openmicroscopy.org/ome-files/
Other
6 stars 13 forks source link

ome-files does not correctly load dependencies when imported in CMake #85

Open seanwarren opened 7 years ago

seanwarren commented 7 years ago

I'm trying to integrating ome-files in a CMake C++ project. In my hands, the following is a minimal CMakeLists.txt to successfully build a ome-files project. I am building on macOS 10.12.6 with clang 4.0.

cmake_minimum_required(VERSION 3.9)
project(ome-test) 

set(CMAKE_CXX_STANDARD 11)

set(CMAKE_PREFIX_PATH "$ENV{OME_FILES_ROOT}")

find_package(Boost COMPONENTS log iostreams) # <- Build fails without this line
find_package(OMEXML REQUIRED)
find_package(OMEFiles REQUIRED)

include_directories($ENV{OME_FILES_ROOT}/include)
add_executable(ome-test main.cpp)
target_link_libraries(ome-test OME::Files)

If I exclude the find_package(Boost COMPONENTS log iostreams) line (or use different boost components) CMake fails with the following error:

CMake Error at CMakeLists.txt:14 (add_executable):
  Target "ome-test" links to target "Threads::Threads" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?

CMake Error at CMakeLists.txt:14 (add_executable):
  Target "ome-test" links to target "Threads::Threads" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?

CMake Error at CMakeLists.txt:14 (add_executable):
  Target "ome-test" links to target "Boost::log_setup" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?

CMake Error at CMakeLists.txt:14 (add_executable):
  Target "ome-test" links to target "Boost::log" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?

CMake Error at CMakeLists.txt:14 (add_executable):
  Target "ome-test" links to target "Boost::iostreams" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?

[SNIP]

CMake Error at CMakeLists.txt:14 (add_executable):
  Target "ome-test" links to target "Boost::filesystem" but the target was
  not found.  Perhaps a find_package() call is missing for an IMPORTED
  target, or an ALIAS target is missing?

As far as I understand, find_package(OMEFiles REQUIRED) should automatically import its dependencies and this line should not be required. This error occurs when using either the downloaded ome-files build or when using a freshly compiling super-build from head.

I have the build working now but thought I'd let you know as it look a while to figure this out.

rleigh-codelibre commented 7 years ago

Hi Sean,

I've opened a PR to rectify the missing log component: https://github.com/ome/ome-common-cpp/pull/51

However, iostreams is already present, so I haven't changed this.

There is a caveat though. find_dependency is unfortunately broken: it deliberately does nothing if find_package has already been run (i.e. Boost_FOUND is set to TRUE). See https://gitlab.kitware.com/cmake/cmake/blob/master/Modules/CMakeFindDependencyMacro.cmake#L34 . You can run find_package multiple times though (it doesn't care if it was already found or not). The configuration files invoke find_dependency, but this will be a no-op if it's already been called. So for

find_package(Boost COMPONENTS log iostreams) # <- Build fails without this line
find_package(OMEXML REQUIRED)
find_package(OMEFiles REQUIRED)

only the first line will invoke FindBoost.cmake. For OMEXMLConfig.cmake and OMEFiles.cmake, which use find_dependency(Boost …), their dependencies will be completely ignored. I've mentioned this on the CMake mailing list a few times; nothing has happened to fix it yet. The existing usage of find_dependency in our module configuration is there in anticipation that this will work properly in the future once it's fixed.

Our workaround in the meantime is to run find_package(Boost) up front with a comprehensive set of components (the superset of all needed components in all our libraries, plus any additional ones we need). Example:

https://github.com/openmicroscopy/ome-files-performance/blob/master/cmake/BoostChecks.cmake#L40

Here we include all the needed components plus random, which we use in this package.

If you have any ideas for how to better work around this find_dependency defect in the interim, I'd be happy to hear them!

seanwarren commented 7 years ago

Hi Roger,

Thanks for the quick reply. I'm no CMake expert so that workaround sounds good to me, I'll bear it in mind if I run into any more boost related issues. Slightly off topic but it might be useful to have a minimal example of a working CMake project incorporating ome-files - it took me a while to figure out what was needed above, even if it's fairly obvious in retrospect.

Cheers

rleigh-codelibre commented 7 years ago

Hi Sean,

Yes, definitely agreed on the need for some standalone examples which demonstate what you need to do to build. We do have some examples in ome-files (docs/sphinx/examples) but it's still tied into the main project's cmake build, so isn't properly standalone. I've added https://trello.com/c/bNE1EV2E/17-add-example-cmake-build-for-examples for this; I'll try to get this done for the next release.