Code Monkey home page Code Monkey logo

packageproject.cmake's Introduction

Test

PackageProject.cmake

Creating installable CMake scripts always requires a large amount of boilerplate code to get things working. This small script should simplify the CMake packaging process into a single, easy-to-use command.

PackageProject.cmake has been tested with CMake v3.18.4.

Usage

To create an installable target for your current project, add the following to your CMakeLists.txt. This example assumes the project to be versioned and the name to be identical to the library to export. Also the CPM.cmake script should be included. See here for an example usage.

CPMAddPackage("gh:TheLartians/[email protected]")

packageProject(
  # the name of the target to export
  NAME ${PROJECT_NAME}
  # the version of the target to export
  VERSION ${PROJECT_VERSION}
  # a temporary directory to create the config files
  BINARY_DIR ${PROJECT_BINARY_DIR}
  # location of the target's public headers
  INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include
  # should match the target's INSTALL_INTERFACE include directory
  INCLUDE_DESTINATION include/${PROJECT_NAME}-${PROJECT_VERSION}
  # (optional) option to install only header files with matching pattern
  INCLUDE_HEADER_PATTERN "*.h"
  # semicolon separated list of the project's dependencies
  DEPENDENCIES "fmt 7.1.3;cxxopts 2.2.0"
  # (optional) create a header containing the version info
  # Note: that the path to headers should be lowercase
  VERSION_HEADER "${PROJECT_NAME}/version.h"
  # (optional) create a export header using GenerateExportHeader module
  EXPORT_HEADER "${PROJECT_NAME}/export.h"
  # (optional) install your library with a namespace (Note: do NOT add extra '::')
  NAMESPACE ${PROJECT_NAMESPACE}
  # (optional) define the project's version compatibility, defaults to `AnyNewerVersion`
  # supported values: `AnyNewerVersion|SameMajorVersion|SameMinorVersion|ExactVersion`
  COMPATIBILITY AnyNewerVersion
  # (optional) option to disable the versioning of install destinations
  DISABLE_VERSION_SUFFIX YES
  # (optional) option to ignore target architecture for package resolution
  # defaults to YES for header only (i.e. INTERFACE) libraries
  ARCH_INDEPENDENT YES
  # (optional) option to generate CPack variables
  CPACK YES
)

CPack

We provide only the most basic variables for CPack generation, however this might not be enough for each and every generator.

For example, Debians' DEB generator needs additionally CPACK_DEBIAN_PACKAGE_MAINTAINER or a CPACK_PACKAGE_CONTACT:

set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Foo Bar <[email protected]>")

If you need extra functionality feel free to open an issue or a PR.

packageproject.cmake's People

Contributors

clausklein avatar friendlyanon avatar jan-moeller avatar michaelunknown avatar mscofield0 avatar olivierldff avatar salman-javed-nz avatar schtobia avatar thelartians avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

packageproject.cmake's Issues

namespace with multiple project

Hi I would like to know if a use case is possible.
I want to create 2 targets : projectname_target1 & projectname_target2. When I install them, I want them to be available with an alias: projectname::target1 & projectname::target2.
Can packageProject achieve this result? Right now I'm have projectname::projectname_target2.

Thank you for the library.

Arch-independent library directory support

Currently CMAKE_INSTALL_LIBDIR is used for the installation, e.g. /usr/lib/x86-64-linux-gnu. However, for arch-independent packages the files should go into /usr/lib (${CMAKE_INSTALL_PREFIX}/lib).

target "grpc" is not in any export set

I started from the project "ModernCppStarter".

Add grpc sinppet:

CPMAddPackage(
  NAME gRPC
  GITHUB_REPOSITORY grpc/grpc
  VERSION 1.38.0
  OPTIONS
    "gRPC_INSTALL ON"
    "gRPC_BUILD_TESTS OFF"
)

if(gRPC_ADDED)
  add_library(gRPC::grpc++ ALIAS grpc++)
endif()

# Link dependencies
target_link_libraries(${PROJECT_NAME} PRIVATE fmt::fmt grpc++)

PackageProject(
  NAME ${PROJECT_NAME}
  VERSION ${PROJECT_VERSION}
  NAMESPACE ${PROJECT_NAME}
  BINARY_DIR ${PROJECT_BINARY_DIR}
  INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include
  INCLUDE_DESTINATION include/${PROJECT_NAME}-${PROJECT_VERSION}
  VERSION_HEADER "${VERSION_HEADER_LOCATION}"
  COMPATIBILITY SameMajorVersion
  DEPENDENCIES "fmt 7.1.3;gRPC 1.38.0"
)

It seem got a error:

CMake Error: install(EXPORT "GreeterTargets" ...) includes target "Greeter" which requires target "grpc++" that is not in any export set.

Issue with third-party dependencies

I am facing a problem where I am using CPM.make to add third party dependencies to my project and finally I am using packageProject to make it installable. However I am facing this issue where the third party target is not in any export set.

CMake Error: install(EXPORT "asabru_commonsTargets" ...) includes target "asabru_commons" which requires target "nlohmann_json" that is not in any export set.
CMake Error: install(EXPORT "asabru_commonsTargets" ...) includes target "asabru_commons" which requires target "stduuid" that is not in any export set.

This is the packageProject command :

packageProject(
        NAME ${PROJECT_NAME}
        VERSION ${PROJECT_VERSION}
        NAMESPACE ${PROJECT_NAME}
        BINARY_DIR ${PROJECT_BINARY_DIR}
        INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include
        INCLUDE_DESTINATION include/${PROJECT_NAME}-${PROJECT_VERSION}
        VERSION_HEADER "${VERSION_HEADER_LOCATION}"
        COMPATIBILITY SameMajorVersion
        DEPENDENCIES "nlohmann_json 3.11.3"
)

I believe it is because the CMakeLists.txt of the third-party dependencies do not have a install / export command.
Can anyone help with this scenario ?

add support for CMAKE_VERIFY_INTERFACE_HEADER_SETS

CMake v3.24 added a new feature for verifying that headers are self-contained, meaning they don’t rely on some other header having been included first. It builds on the file sets feature added in CMake v3.23. The new CMAKE_VERIFY_INTERFACE_HEADER_SETS variable can be set to true to enable the creation of targets that carry out these checks for appropriately defined file sets. It is intended to be a developer control, not something the project sets. For projects already using file sets to install their headers, it should be a very simple step for developers to enable these checks.

Emit warning if public include path is unversioned

One thing I actually do worry about now is if a user installs different versions of the same package without using a versioned include path. Then the include path would only contain the most recent installed version, but the CMake modules would still exist for all versions.

Perhaps we could check if the include path contains the version string and emit an informative warning if the flag NO_VERSION_SUFFIX isn't set. (using flag would completely overwrite the old versions, so CMake won't find old versions at all)

Originally posted by @TheLartians in #15 (comment)

Export targets at configure time

This would allow to use find_package of a local dependency at configure time as suggested on the CMake slack. Example:

if(DEFINED ${PROJECT_NAME}_EXPORTED_TARGETS)
        # This is to make find_package(${PROJECT_NAME}_PACKAGE_NAME) 
        # work @ build time
        export(TARGETS ${${PROJECT_NAME}_EXPORTED_TARGETS} 
               NAMESPACE ${${PROJECT_NAME}_PACKAGE_NAME}:: 
               FILE ${${PROJECT_NAME}_PACKAGE_NAME}-Exports.cmake)
        export(PACKAGE ${${PROJECT_NAME}_PACKAGE_NAME}) # Should do nothing according to docs. 
    endif()
    # This only exists @ install time
    install(EXPORT ${PROJECT_NAME}_EXPORTS
            NAMESPACE ${${PROJECT_NAME}_PACKAGE_NAME}:: 
            FILE ${${PROJECT_NAME}_PACKAGE_NAME}-Targets.cmake 
            DESTINATION "share/${${PROJECT_NAME}_PACKAGE_NAME}")
    set(${PROJECT_NAME}_LOCKED TRUE)

feature request: add support to install a component library like boost

see adding-components
and https://discourse.cmake.org/t/how-to-install-component-libraries-like-boost/2854

My cmake project based on the guide/importing-exporting:

cmake_minimum_required(VERSION 3.15...3.20)

# Note: set version PROJECT_VERSION her! CK
project(
  MathFunctionsComponents
  VERSION 3.4.1
  LANGUAGES CXX
)

# specify the C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# Note: set namespace for export cmake config package! CK
set(namespace MathFunctions)

set(CMAKE_DEBUG_POSTFIX -d)

# control where the static and shared libraries are built so that on windows
# we don't need to tinker with the path to run the executable
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)

add_subdirectory(Addition)
add_subdirectory(SquareRoot)
add_subdirectory(MathFunctions)

# generate and install export file
install(
  EXPORT ${namespace}Targets
  FILE ${namespace}Targets.cmake
  NAMESPACE ${namespace}::
  DESTINATION lib/cmake/${namespace}
)

# include CMakePackageConfigHelpers macro
include(CMakePackageConfigHelpers)

# generate the version file for the config file
write_basic_package_version_file(
  ${CMAKE_CURRENT_BINARY_DIR}/${namespace}ConfigVersion.cmake
  VERSION ${PROJECT_VERSION}
  COMPATIBILITY AnyNewerVersion
)

# Note: create config file with NO_CHECK_REQUIRED_COMPONENTS_MACRO! CK
configure_package_config_file(
  ${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
  ${CMAKE_CURRENT_BINARY_DIR}/${namespace}Config.cmake
  INSTALL_DESTINATION lib/cmake/${namespace}
  NO_CHECK_REQUIRED_COMPONENTS_MACRO
)

# install config files
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${namespace}Config.cmake
              ${CMAKE_CURRENT_BINARY_DIR}/${namespace}ConfigVersion.cmake
        DESTINATION lib/cmake/${namespace}
)

# generate the export targets for the entire build tree
# Note: needs to be after all install(TARGETS ) commands
export(
  EXPORT ${namespace}Targets
  FILE ${CMAKE_CURRENT_BINARY_DIR}/cmake/MathFunctionsTargets.cmake
  NAMESPACE ${namespace}::
)
#
# create a component library like boost
#
add_library(Addition STATIC Addition.cxx Addition.h)

add_library(${namespace}::Addition ALIAS Addition)

# add include directories
target_include_directories(
  Addition PUBLIC "$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>"
                  $<INSTALL_INTERFACE:include>
)

# install the target and create export-set
install(
  TARGETS Addition
  #XXX EXPORT AdditionTargets
  EXPORT ${namespace}Targets
  LIBRARY DESTINATION lib
  ARCHIVE DESTINATION lib
  RUNTIME DESTINATION bin
  INCLUDES
  DESTINATION include
)

# install header file
install(FILES Addition.h DESTINATION include/${namespace})

# generate and install export file
install(
  #XXX EXPORT AdditionTargets
  EXPORT ${namespace}Targets
  FILE ${namespace}AdditionTargets.cmake
  NAMESPACE ${namespace}::
  DESTINATION lib/cmake/${namespace}
)
Claus-iMac:MathFunctionsComponents clausklein$ tree root/
root/
β”œβ”€β”€ include
β”‚Β Β  └── MathFunctions
β”‚Β Β      β”œβ”€β”€ Addition.h
β”‚Β Β      β”œβ”€β”€ MathFunctions.h
β”‚Β Β      └── SquareRoot.h
└── lib
    β”œβ”€β”€ cmake
    β”‚Β Β  └── MathFunctions
    β”‚Β Β      β”œβ”€β”€ MathFunctionsAdditionTargets-debug.cmake
    β”‚Β Β      β”œβ”€β”€ MathFunctionsAdditionTargets.cmake
    β”‚Β Β      β”œβ”€β”€ MathFunctionsConfig.cmake
    β”‚Β Β      β”œβ”€β”€ MathFunctionsConfigVersion.cmake
    β”‚Β Β      β”œβ”€β”€ MathFunctionsMathFunctionsTargets-debug.cmake
    β”‚Β Β      β”œβ”€β”€ MathFunctionsMathFunctionsTargets.cmake
    β”‚Β Β      β”œβ”€β”€ MathFunctionsSquareRootTargets-debug.cmake
    β”‚Β Β      β”œβ”€β”€ MathFunctionsSquareRootTargets.cmake
    β”‚Β Β      β”œβ”€β”€ MathFunctionsTargets-debug.cmake
    β”‚Β Β      └── MathFunctionsTargets.cmake
    β”œβ”€β”€ libAddition-d.a
    β”œβ”€β”€ libMathFunctions-d.a
    └── libSquareRoot-d.a

5 directories, 16 files
Claus-iMac:MathFunctionsComponents clausklein$ 

FeatureRequest: make it optional to install the package to version less subdirectories

IMHO it would be nice to be able to install a static library in this way:

Claus-iMac:example clausklein$ ninja -C build install
ninja: Entering directory `build'
[0/1] Install the project...
-- Install configuration: ""
-- Installing: /usr/local/lib/Greeter/libGreeter.a
-- Installing: /usr/local/lib/cmake/Greeter/GreeterTargets.cmake
-- Installing: /usr/local/lib/cmake/Greeter/GreeterTargets-noconfig.cmake
-- Installing: /usr/local/lib/cmake/Greeter/GreeterConfigVersion.cmake
-- Installing: /usr/local/lib/cmake/Greeter/GreeterConfig.cmake
-- Up-to-date: /usr/local/include/Greeter
-- Up-to-date: /usr/local/include/Greeter/greeter
-- Up-to-date: /usr/local/include/Greeter/greeter/greeter.h
Claus-iMac:example clausklein$ 

with set(PROJECT_COMPATIBILITY AnyNewerVersion)
a newer version would be found and used, or not?

feature request: the version of a dependency package should be exported too

How can I require the version of my dependencies?

packageProject(
    NAME ${PROJECT_NAME}
    VERSION ${PROJECT_VERSION}
    NAMESPACE ${PROJECT_NAME}
    BINARY_DIR ${PROJECT_BINARY_DIR}
    INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include
    INCLUDE_DESTINATION include/${PROJECT_NAME}
    VERSION_HEADER "${VERSION_HEADER_LOCATION}"
    DEPENDENCIES "" # optional list of dependencies, FIXME: but without requiered version?
)

Avoid Creating Alias Target If It Already Exists

This issue addresses the lines of code that create an alias target for a specific namespace:

# we want to automatically add :: to our namespace, so only append if a namespace was given in the
# first place we also provide an alias to ensure that local and installed versions have the same
# name
if(DEFINED PROJECT_NAMESPACE)
if(PROJECT_CPACK)
set(CPACK_PACKAGE_NAMESPACE ${PROJECT_NAMESPACE})
endif()
set(PROJECT_NAMESPACE ${PROJECT_NAMESPACE}::)
add_library(${PROJECT_NAMESPACE}${PROJECT_NAME} ALIAS ${PROJECT_NAME})
endif()

It is suggested to create the alias target only if the alias does not already exist; otherwise, it may cause issues as highlighted in boost-ext/ut#564.

Before CMake 3.18, this may not have caused an issue because any new alias target would replace the old alias. However, the behavior has changed since then (see also).

Install library with namespace

Hi,
I think an option to export a namespace to my library would be nice (or I totally missed how to do it).
So with my current cmake file

add_library(mkpoker INTERFACE)
add_library(mkpoker::mkpoker ALIAS mkpoker)

I would like to do this

set(MY_LIBRARY_NAMESPACE "mkpoker")
add_library(${MY_LIBRARY_NAMESPACE}::mkpoker ALIAS mkpoker)

packageProject(
    NAME ${PROJECT_NAME}
    VERSION ${PROJECT_VERSION}
    LIBRARY_NAMESPACE ${MY_LIBRARY_NAMESPACE}
    BINARY_DIR ${PROJECT_BINARY_DIR}
    INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include
    INCLUDE_DESTINATION include/${PROJECT_NAME}-${PROJECT_VERSION}
    VERSION_HEADER "${PROJECT_NAME}/version.h"
)

so that the cmake install adds the lib with the correct namespace, resulting in something like

add_library(mkpoker::mkpoker INTERFACE IMPORTED)

Best wishes,
mike

PS: I am confused, how DEPENDENCIES is supposed to work... if I add my librarys dependencies with CPM.cmake, this will install all of them regardless, i.e., even if no deps are specified in the DEPENDENCIES variable

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.