Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] CMake Install rule proposal #182

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions CMake/AbseilHelpers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ set(ABSL_IDE_FOLDER Abseil)
# SRCS
# "b.cc"
# DEPS
# absl_internal_awesome # not "awesome"!
# absl::awesome
# )
#
# If PUBLIC is set, absl_cc_library will instead create a target named
# absl_${NAME} and still an alias absl::${NAME}.
# Warning: Only libraries with the PUBLIC flag set can be used by user.
# Otherwise they are internal absl targets that shouldn't be used externally.
#
# absl_cc_library(
# NAME
Expand All @@ -76,14 +76,18 @@ set(ABSL_IDE_FOLDER Abseil)
# TODO: Implement "ALWAYSLINK"
function(absl_cc_library)
cmake_parse_arguments(ABSL_CC_LIB
"DISABLE_INSTALL;PUBLIC;TESTONLY"
"PUBLIC;TESTONLY"
"NAME"
"HDRS;SRCS;COPTS;DEFINES;LINKOPTS;DEPS"
${ARGN}
)

if (NOT ABSL_CC_LIB_TESTONLY OR ABSL_RUN_TESTS)
set(_NAME "absl_${ABSL_CC_LIB_NAME}")
if(NOT ABSL_ENABLE_INSTALL)
set(_NAME "absl_${ABSL_CC_LIB_NAME}")
else()
set(_NAME "${ABSL_CC_LIB_NAME}")
endif()

# Check if this is a header-only library
# Note that as of February 2019, many popular OS's (for example, Ubuntu
Expand All @@ -103,9 +107,14 @@ function(absl_cc_library)

if(NOT ABSL_CC_LIB_IS_INTERFACE)
add_library(${_NAME} STATIC "")
Copy link

@dennisklein dennisklein Jan 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To support shared libraries (Please ignore, if this is not a desired feature at all):

Suggested change
add_library(${_NAME} STATIC "")
add_library(${_NAME})

The user can now choose between static and shared libraries via -DBUILD_SHARED_LIBS=ON/OFF. For good practice, you may want to explicitely declare this build switch with an explicit default via option(). Without declaring it as an option, the default is OFF (=> static).

Because there are library dependencies within the absl package, it is recommended to add relative RPATH entries for relocatability. Here is a snippet how we usually add such entries on Linux and MacOS:

set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" isSystemDir)
if("${isSystemDir}" STREQUAL "-1")
  if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
    set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-Wl,--enable-new-dtags")
    set(CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} "-Wl,--enable-new-dtags")
    set(CMAKE_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}")
  elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
    set(CMAKE_INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR}")
  endif()
endif()

set_target_properties(${_NAME} PROPERTIES
OUTPUT_NAME "absl_${_NAME}"
)
target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})
target_include_directories(${_NAME}
PUBLIC ${ABSL_COMMON_INCLUDE_DIRS})
target_include_directories(${_NAME} PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> # <prefix>/include
)
target_compile_options(${_NAME}
PRIVATE ${ABSL_CC_LIB_COPTS})
target_link_libraries(${_NAME}
Expand All @@ -129,15 +138,27 @@ function(absl_cc_library)
else()
# Generating header-only library
add_library(${_NAME} INTERFACE)
target_include_directories(${_NAME}
INTERFACE ${ABSL_COMMON_INCLUDE_DIRS})
target_include_directories(${_NAME} INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> # <prefix>/include
)
target_link_libraries(${_NAME}
INTERFACE ${ABSL_CC_LIB_DEPS} ${ABSL_CC_LIB_LINKOPTS}
)
target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES})
endif()

add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME})

# install rules
if(ABSL_ENABLE_INSTALL)
install(TARGETS ${_NAME}
EXPORT ${PROJECT_NAME}Targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
endif()
endif()
endfunction()

Expand Down Expand Up @@ -194,7 +215,7 @@ function(absl_cc_test)
add_executable(${_NAME} "")
target_sources(${_NAME} PRIVATE ${ABSL_CC_TEST_SRCS})
target_include_directories(${_NAME}
PUBLIC ${ABSL_COMMON_INCLUDE_DIRS}
PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
PRIVATE ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
)
target_compile_definitions(${_NAME}
Expand Down
7 changes: 7 additions & 0 deletions CMake/abslConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## absl CMake configuration file

set(ABSL_VERSION @PROJECT_VERSION@)

@PACKAGE_INIT@

Copy link

@dennisklein dennisklein Jan 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to have more meta data here, e.g.

set_and_check(@PROJECT_NAME@_HOME "${PACKAGE_PREFIX_DIR}")
set_and_check(@PROJECT_NAME@_INCLUDEDIR "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@")
set_and_check(@PROJECT_NAME@_LIBDIR "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_LIBDIR@")

set(@PROJECT_NAME@_TARGETS absl::* absl::*_internal)
set(@PROJECT_NAME@_PUBLIC_TARGETS absl::*)
set(@PROJECT_NAME@_PRIVATE_TARGETS absl::*_internal)

The paths may be extracted from the target properties, but experience shows, it is nicer to have them at hand in a convenient variable (${PACKAGE_PREFIX_DIR} is populated by the code generated via @PACKAGE_INIT@ at import time).

The entries in the proposed target lists could e.g. easily be collected in the absl_cc_library function.

Note: @PROJECT_NAME@ is case-sensitive. You may wish to convert to upper case characters.

Note: If you decide to export a path via set_and_check as proposed in my example above, make sure, this is done only in the cases, when something is installed into these paths. E.g. if you had a build option, which would result in nothing being installed into the lib directory, it is likely the lib directory will not be created and set_and_check will fail.

include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
61 changes: 55 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,31 @@
cmake_minimum_required(VERSION 3.5)

# Compiler id for Apple Clang is now AppleClang.
if (POLICY CMP0025)
if(POLICY CMP0025)
cmake_policy(SET CMP0025 NEW)
endif()

project(absl)
# Enable MACOSX_RPATH by default.
if(POLICY CMP0042)
cmake_policy (SET CMP0042 NEW)
endif()

project(absl VERSION 1.0.0 LANGUAGES CXX)

option(ABSL_ENABLE_INSTALL "If ON, Abseil enable install rules." ON)
# when absl is included as subproject (i.e. using add_subdirectory(abseil-cpp))
# in the source tree of a project that uses it, install rules are disabled.
if(NOT "^${CMAKE_SOURCE_DIR}$" STREQUAL "^${PROJECT_SOURCE_DIR}$")
set(ABSL_ENABLE_INSTALL OFF)
endif()

list(APPEND CMAKE_MODULE_PATH
${CMAKE_CURRENT_LIST_DIR}/CMake
${CMAKE_CURRENT_LIST_DIR}/absl/copts
)

include(GNUInstallDirs)
include(AbseilHelpers)


##
## Using absl targets
##
Expand All @@ -47,7 +57,6 @@ include(AbseilHelpers)
##
## DO NOT rely on the internal targets outside of the prefix


# include current path
list(APPEND ABSL_COMMON_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR})

Expand Down Expand Up @@ -75,7 +84,6 @@ endif()

## check targets
if(BUILD_TESTING)

if(${ABSL_USE_GOOGLETEST_HEAD})
include(CMake/DownloadGTest.cmake)
endif()
Expand All @@ -93,3 +101,44 @@ if(BUILD_TESTING)
endif()

add_subdirectory(absl)

# install rules
if(ABSL_ENABLE_INSTALL)
# See https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html
include(GNUInstallDirs)
# See https://cmake.org/cmake/help/latest/command/find_package.html#search-procedure
set(CMAKE_INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
install(
EXPORT ${PROJECT_NAME}Targets
NAMESPACE absl::
DESTINATION ${CMAKE_INSTALL_CONFIGDIR}
)
install(
DIRECTORY absl
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT Devel
FILES_MATCHING
PATTERN "*.inc"
PATTERN "*.h"
)

# See https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html
include(CMakePackageConfigHelpers)
configure_package_config_file(
CMake/abslConfig.cmake.in
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_CONFIGDIR}"
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
COMPATIBILITY ExactVersion
)
install(
FILES
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION "${CMAKE_INSTALL_CONFIGDIR}"
COMPONENT Devel
)
endif()