Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Export a Package in CMake?

I am having trouble exporting a package correctly in CMake so that it can be imported using the find_package command, and no matter what I seem to do, it still doesn't work. I've recreated the simplest possible scenario that shows my process in terms of exporting, so it should be easier to diagnose.

I've setup two projects, which I've put in the same folder: foo and bar, where foo is a library and bar is an executable which depends on foo.

├───bar
│       bar.c
│       CMakeLists.txt
│
└───foo
        CMakeLists.txt
        foo.c
        foo.h

Notice that these are two separate projects, and not subprojects of one overarching project.

Contents of foo/CMakeLists.txt:

cmake_minimum_required (VERSION 3.8)

project (Foo)

set (LIB_NAME foo)

add_library (${LIB_NAME} STATIC foo.c foo.h)

install (TARGETS ${LIB_NAME} EXPORT ${LIB_NAME}Targets
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        RUNTIME DESTINATION bin
        INCLUDES DESTINATION include
)

install (FILES foo.h
        DESTINATION include
)

install (EXPORT ${LIB_NAME}Targets
        NAMESPACE foo::
        DESTINATION lib/cmake
)

Contents of bar/CMakeLists.txt:

cmake_minimum_required (VERSION 3.8)

project (Bar)

set (EXE_NAME bar)

find_package (foo REQUIRED)

add_executable (${EXE_NAME} bar.c)
target_link_libraries (${EXE_NAME} PRIVATE foo::foo)

The sequence of commands that I use to build the two projects:

md foo_build
md bar_build
cd foo_build
cmake ..\foo -DCMAKE_INSTALL_PREFIX=..\install\foo
cmake --build . --target INSTALL
cd ..\bar_build
cmake ..\bar -DCMAKE_PREFIX_PATH=..\install\foo

When all of this was done, the resultant error was:

CMake Error at CMakeLists.txt:7 (find_package):
  By not providing "Findfoo.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "foo", but
  CMake did not find one.

  Could not find a package configuration file provided by "foo" with any of
  the following names:

    fooConfig.cmake
    foo-config.cmake

  Add the installation prefix of "foo" to CMAKE_PREFIX_PATH or set "foo_DIR"
  to a directory containing one of the above files.  If "foo" provides a
  separate development package or SDK, be sure it has been installed.

When I tried exporting with the Config suffix instead of the Target suffix for the package exports, there doesn't seem to be any difference to the output:

CMake Error at CMakeLists.txt:7 (find_package):
  By not providing "Findfoo.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "foo", but
  CMake did not find one.

  Could not find a package configuration file provided by "foo" with any of
  the following names:

    fooConfig.cmake
    foo-config.cmake

  Add the installation prefix of "foo" to CMAKE_PREFIX_PATH or set "foo_DIR"
  to a directory containing one of the above files.  If "foo" provides a
  separate development package or SDK, be sure it has been installed.

I've got no idea what I'm doing wrong, and the CMake Documentation doesn't seem to be helping me at all.

My CMake version, if it helps, is 3.17.3.

Thank you in advance.

Edit:

I've followed the advice that @Tsyvarev gave, and unfortunately, it did not seem to fix the problem. I read the documentation that he sent, and followed all the parts of it that were different from my current approach.

The main two differences in the approach was to create separate -Targets, -Config, and -ConfigVersion cmake files, with the following changes.

The new structure of the whole program:

├───bar
│       bar.c
│       CMakeLists.txt
│
└───foo
    │   CMakeLists.txt
    │   foo.c
    │   foo.h
    │
    └───cmake
            fooConfig.cmake

The lines I've added to foo's CMakeLists.txt file:

include (CMakePackageConfigHelpers)
write_basic_package_version_file (
        ${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}ConfigVersion.cmake
        VERSION ${${PROJECT_NAME}_VERSION}
        COMPATIBILITY AnyNewerVersion
)

install (
        FILES
            cmake/${LIB_NAME}Config.cmake
            ${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}ConfigVersion.cmake
        DESTINATION lib/cmake
)

The contents of fooConfig.cmake:

include ("${CMAKE_CURRENT_LIST_DIR}/fooTargets.cmake")

Just as a reference, the output of installing foo is as one may expect:

├───include
│       foo.h
│
└───lib
    │   foo.lib
    │
    └───cmake
            fooConfig.cmake
            fooConfigVersion.cmake
            fooTargets-debug.cmake
            fooTargets.cmake

And when running cmake on the bar project, the same error occurs:

  By not providing "Findfoo.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "foo", but
  CMake did not find one.

  Could not find a package configuration file provided by "foo" with any of
  the following names:

    fooConfig.cmake
    foo-config.cmake

  Add the installation prefix of "foo" to CMAKE_PREFIX_PATH or set "foo_DIR"
  to a directory containing one of the above files.  If "foo" provides a
  separate development package or SDK, be sure it has been installed.

By the way, the CMAKE_PREFIX_PATH is being set, as much as the error message would beg to differ, and I can't seem to figure out what else I have to do to appease it.

Any help would be greatly appreciated.

like image 854
carsonalh Avatar asked Oct 28 '25 16:10

carsonalh


1 Answers

After some very frustrating research, I finally found the answer to this question, which is in the way that find_package works. It turns out that the directory structure that I was giving it was not good enough, but as soon as I changed the "lib/cmake" installs into "lib/cmake/${LIB_NAME}", and changed the CMAKE_PREFIX_PATH to ..\install instead of ..\install\foo, everything seemed to work out okay, and I finally got this simple program to work.

like image 171
carsonalh Avatar answered Oct 31 '25 06:10

carsonalh