[CMake] Problem with creating shared library

Damir Porobic damir_porobic at live.com
Sun Aug 19 09:16:40 EDT 2018


Thanks Sebastián for providing those links!


I've followed the second link that you've provided but somehow I'm still running into issue.


I've changed the directory structure to this:

- kImageAnnotator
    - cmake
        - kImageAnnotator-config.cmake.in
    - example
        - main.cpp
        - CMakeLists.txt
    - include
        - kImageAnnotator
            - KImageAnnotator.h     // the main api header
    - src
        - KImageAnnotator.cpp
        - "And all other .cpp and .h files"
        - CMakeLists.txt
    - CMakeLists.txt

src/CMakeList.txt looks like this:
add_library(kImageAnnotator ${kimageannotator_SRCS} ${CMAKE_SOURCE_DIR}/include/kImageAnnotator/KImageAnnotator.h)

add_library(kImageAnnotator::kImageAnnotator ALIAS kImageAnnotator)

option(BUILD_SHARED_LIBS "Build shared library" ON)
include(GenerateExportHeader)

generate_export_header(kImageAnnotator
        EXPORT_MACRO_NAME KIMAGEANNOTATOR_API
        EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/include/KImageAnnotator.h
        )

target_include_directories(kImageAnnotator
        PUBLIC
        $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
        $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>
        $<INSTALL_INTERFACE:include>
        PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}
        )

set_target_properties(kImageAnnotator PROPERTIES
        ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
        LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
        RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
        )

find_package(Qt5 ${QT_MIN_VERSION} REQUIRED Widgets)

find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS CoreAddons I18n WidgetsAddons)

target_link_libraries(kImageAnnotator Qt5::Widgets KF5::CoreAddons KF5::I18n KF5::WidgetsAddons)

include(GNUInstallDirs)

install(TARGETS kImageAnnotator
        EXPORT kImageAnnotator-targets
        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
        INCLUDES DESTINATION ${LIBLEGACY_INCLUDE_DIRS}
)

install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/kImageAnnotator
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

install(EXPORT kImageAnnotator-targets
        FILE kImageAnnotator-targets.cmake
        NAMESPACE kImageAnnotator::
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/kImageAnnotator
)


include(CMakePackageConfigHelpers)

configure_package_config_file(
        ${CMAKE_SOURCE_DIR}/cmake/kImageAnnotator-config.cmake.in
        ${CMAKE_BINARY_DIR}/cmake/kImageAnnotator-config.cmake
        INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/kImageAnnotator
)

write_basic_package_version_file(
        ${CMAKE_BINARY_DIR}/cmake/kImageAnnotator-config-version.cmake
        VERSION ${PROJECT_VERSION}
        COMPATIBILITY AnyNewerVersion
)

install(FILES
        ${CMAKE_BINARY_DIR}/cmake/kImageAnnotator-config.cmake
        ${CMAKE_BINARY_DIR}/cmake/kImageAnnotator-config-version.cmake
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/kImageAnnotator
)

export(EXPORT kImageAnnotator-targets
        FILE ${CMAKE_BINARY_DIR}/cmake/kImageAnnotator-targets.cmake
        NAMESPACE kImageAnnotator::
)



kImageAnnotator-config.cmake.in looks like this:

include(CMakeFindDependencyMacro)

@PACKAGE_INIT@

# find_dependency(Threads)
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED Widgets)

find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS CoreAddons I18n WidgetsAddons)

if(NOT TARGET kImageAnnotator::kImageAnnotator)
  include("${CMAKE_CURRENT_LIST_DIR}/kImageAnnotator-targets.cmake")
endif()



example/CMakeLists.txt looks like this:

add_executable(kImageAnnotator-example ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)

target_link_libraries(kImageAnnotator-example PRIVATE kImageAnnotator::kImageAnnotator)



And example/main.cpp looks like this:

#include <QApplication>
#include <kImageAnnotator/KImageAnnotator.h>

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    QPixmap pixmap(QSize(500, 500));
    pixmap.fill(QColor(Qt::darkGreen));
    auto kImageAnnotator = new KImageAnnotator(pixmap);
    kImageAnnotator->show();

    return app.exec();
}



Still I'm getting following error when trying to build kImageAnnotator-example:

Scanning dependencies of target kImageAnnotator-example
[ 98%] Building CXX object example/CMakeFiles/kImageAnnotator-example.dir/main.cpp.o
[ 98%] Building CXX object example/CMakeFiles/kImageAnnotator-example.dir/kImageAnnotator-example_autogen/mocs_compilation.cpp.o
[100%] Linking CXX executable kImageAnnotator-example
CMakeFiles/kImageAnnotator-example.dir/main.cpp.o: In function `main':
/home/dporobic/projects/kImageAnnotator/example/main.cpp:29: undefined reference to `KImageAnnotator::KImageAnnotator(QPixmap const&)'
collect2: error: ld returned 1 exit status
example/CMakeFiles/kImageAnnotator-example.dir/build.make:98: recipe for target 'example/kImageAnnotator-example' failed

Any idea what I'm doing wrong? It looks like the same issue that I was having earlier.


________________________________
From: Sebastián Mancilla <smancill at jlab.org>
Sent: Wednesday, August 15, 2018 21:48
To: damir_porobic at live.com
Cc: cmake at cmake.org
Subject: Re: [CMake] Problem with creating shared library

You are mixing the config file and the targets file.

The config file is a template that you normally put in cmake/FooConfig.cmake.in<http://FooConfig.cmake.in>

You copy the template into the binary dir:

    include(CMakePackageConfigHelpers)

    set(INSTALL_CONFIGDIR lib/cmake/Foo)

    configure_package_config_file(
      "${CMAKE_CURRENT_LIST_DIR}/cmake/FooConfig.cmake.in<http://FooConfig.cmake.in>"
      "${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake"
      INSTALL_DESTINATION ${INSTALL_CONFIGDIR}
    )

It is a good idea to create a version file:

    write_basic_package_version_file(
      "${CMAKE_CURRENT_BINARY_DIR}/FooConfigVersion.cmake"
      VERSION ${PROJECT_VERSION}
      COMPATIBILITY SameMajorVersion
   )

And then install both:

    install(FILES
        "${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake"
        "${CMAKE_CURRENT_BINARY_DIR}/FooConfigVersion.cmake"
      DESTINATION ${INSTALL_CONFIGDIR}
      COMPONENT Devel
    )

For the targets is a different file. When you install the library you should use

    install(TARGETS Foo EXPORT FooTargets ...)

And then export and install the targets:

    # Into the build tree
    export(EXPORT FooTargets
      FILE "${CMAKE_CURRENT_BINARY_DIR}/FooTargets.cmake"
      NAMESPACE Foo::
    )

    # Into PREFIX
    install(EXPORT FooTargets
      FILE FooTargets.cmake
      NAMESPACE Foo::
      DESTINATION ${INSTALL_CONFIGDIR}
      COMPONENT Devel
    )

Finally, your template FooConfig.cmake.in<http://FooConfig.cmake.in> should look like this:

  include(CMakeFindDependencyMacro)

  @PACKAGE_INIT@

  # list your required dependencies here
  find_dependency(Threads)

  if(NOT TARGET Foo::Foo)
    include("${CMAKE_CURRENT_LIST_DIR}/FooTargets.cmake")
  endif()

All this is pretty much the same for any project. Here are the best links explaining it:

https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/
http://unclejimbo.github.io/2018/06/08/Modern-CMake-for-Library-Developers/




El mié., 15 de ago. de 2018 a la(s) 05:32, Damir Porobic (damir_porobic at live.com<mailto:damir_porobic at live.com>) escribió:

Hi Folks,


I'm trying to write a shared library and run into an issue where I can't find any clues to where the problem is.

I have a project with following structure:


src/

    dir1/

        file1.h

        file1.cpp

    dir2/

        file2.h

        file2.cpp



Now I have this CMakeList:

cmake_minimum_required(VERSION 3.5)

project(kImageAnnotator VERSION 0.0.1 LANGUAGES CXX)


...


add_library(${PROJECT_NAME} SHARED ${kimageannotator_SRCS})
target_link_libraries(${PROJECT_NAME} Qt5::Widgets KF5::CoreAddons KF5::I18n KF5::WidgetsAddons)

target_include_directories(${PROJECT_NAME} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<INSTALL_INTERFACE:include>)

set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION 1)

set(kimageannotator_CONFIG ${PROJECT_NAME}Config)

install(TARGETS ${PROJECT_NAME} EXPORT ${kimageannotator_CONFIG}
        ARCHIVE  DESTINATION ${CMAKE_INSTALL_LIBDIR}
        LIBRARY  DESTINATION ${CMAKE_INSTALL_LIBDIR}
        RUNTIME  DESTINATION ${CMAKE_INSTALL_BINDIR})
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME})

install(EXPORT ${kimageannotator_CONFIG} DESTINATION share/${kimageannotator_CONFIG}/cmake)

export(TARGETS ${PROJECT_NAME} FILE ${kimageannotator_CONFIG}.cmake)


In another test project, I add the library like this:
...
find_package(kImageAnnotator REQUIRED)

add_executable(testApp main.cpp)
target_link_libraries(testApp Qt5::Widgets kImageAnnotator)


Now when I try to build my test project, I get this:

dporobic at linux ~/projects/testApp/build
$ cmake .. && make
-- Could not set up the appstream test. appstreamcli is missing.
-- Configuring done
-- Generating done
-- Build files have been written to: /home/dporobic/projects/testApp/build
[ 25%] Automatic moc for target testApp
[ 25%] Built target testApp_automoc
Scanning dependencies of target testApp
[ 50%] Building CXX object CMakeFiles/testApp.dir/main.cpp.o
[ 75%] Building CXX object CMakeFiles/testApp.dir/testApp_automoc.cpp.o
[100%] Linking CXX executable testApp
CMakeFiles/testApp.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x8e): undefined reference to `KImageAnnotator::KImageAnnotator(QPixmap const&)'
collect2: error: ld returned 1 exit status
CMakeFiles/testApp.dir/build.make:120: recipe for target 'testApp' failed
make[2]: *** [testApp] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/testApp.dir/all' failed
make[1]: *** [CMakeFiles/testApp.dir/all] Error 2
Makefile:94: recipe for target 'all' failed
make: *** [all] Error 2

Any idea how I could/should troubleshoot such issue?

Thanks in advance!

Regards,
Damir



--

Powered by www.kitware.com<http://www.kitware.com>

Please keep messages on-topic and check the CMake FAQ at: https://urldefense.proofpoint.com/v2/url?u=http-3A__www.cmake.org_Wiki_CMake-5FFAQ&d=DwICAg&c=lz9TcOasaINaaC3U7FbMev2lsutwpI4--09aP8Lu18s&r=8hmSv9ww5s9qu3iT8h5WMi8-YcKXaJvelxT3fMih7S4&m=1H4kXxGuNG-DAo1qM-u8bdF6AKKHkJoiCuqwZ4QLvtY&s=JJ5RqPyjdlGGc3fT-5nQQM-JcJzwjBZU6ciOQlmEJVs&e=

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

CMake Support: https://urldefense.proofpoint.com/v2/url?u=http-3A__cmake.org_cmake_help_support.html&d=DwICAg&c=lz9TcOasaINaaC3U7FbMev2lsutwpI4--09aP8Lu18s&r=8hmSv9ww5s9qu3iT8h5WMi8-YcKXaJvelxT3fMih7S4&m=1H4kXxGuNG-DAo1qM-u8bdF6AKKHkJoiCuqwZ4QLvtY&s=vUHQvc_7Ovi_5BDjy3JYFOIvTmihTSFOQNndNSpMOnA&e=
CMake Consulting: https://urldefense.proofpoint.com/v2/url?u=http-3A__cmake.org_cmake_help_consulting.html&d=DwICAg&c=lz9TcOasaINaaC3U7FbMev2lsutwpI4--09aP8Lu18s&r=8hmSv9ww5s9qu3iT8h5WMi8-YcKXaJvelxT3fMih7S4&m=1H4kXxGuNG-DAo1qM-u8bdF6AKKHkJoiCuqwZ4QLvtY&s=91AJA3BxTfHAvsi0mAzkszAyUUmE2xfwbLgN_fYvFO4&e=
CMake Training Courses: https://urldefense.proofpoint.com/v2/url?u=http-3A__cmake.org_cmake_help_training.html&d=DwICAg&c=lz9TcOasaINaaC3U7FbMev2lsutwpI4--09aP8Lu18s&r=8hmSv9ww5s9qu3iT8h5WMi8-YcKXaJvelxT3fMih7S4&m=1H4kXxGuNG-DAo1qM-u8bdF6AKKHkJoiCuqwZ4QLvtY&s=isQW6paMIqhUFaejOZ4qfUiSVwNiR1yxoQn4J91yb8o&e=

Visit other Kitware open-source projects at https://urldefense.proofpoint.com/v2/url?u=http-3A__www.kitware.com_opensource_opensource.html&d=DwICAg&c=lz9TcOasaINaaC3U7FbMev2lsutwpI4--09aP8Lu18s&r=8hmSv9ww5s9qu3iT8h5WMi8-YcKXaJvelxT3fMih7S4&m=1H4kXxGuNG-DAo1qM-u8bdF6AKKHkJoiCuqwZ4QLvtY&s=ose8YVW10s6tWkujUCq162vyyipCdlw-MW93qUlqdGk&e=

Follow this link to subscribe/unsubscribe:
https://urldefense.proofpoint.com/v2/url?u=https-3A__cmake.org_mailman_listinfo_cmake&d=DwICAg&c=lz9TcOasaINaaC3U7FbMev2lsutwpI4--09aP8Lu18s&r=8hmSv9ww5s9qu3iT8h5WMi8-YcKXaJvelxT3fMih7S4&m=1H4kXxGuNG-DAo1qM-u8bdF6AKKHkJoiCuqwZ4QLvtY&s=KftR51q4EGgNERicS2QyHvzlrNaqb11IUwwbz1YTjVU&e=


--
Sebastian Mancilla Matta
CCTVal, UTFSM
Valparaíso, Chile
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://cmake.org/pipermail/cmake/attachments/20180819/b58691c1/attachment-0001.html>


More information about the CMake mailing list