-
Notifications
You must be signed in to change notification settings - Fork 627
[CMAKE] Clean up pkg-config install methods and add tests #4528
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
base: main
Are you sure you want to change the base?
Changes from all commits
42d6a40
8368812
fa57f66
cecfb86
9241137
9a69e8e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,53 +5,88 @@ include_guard(GLOBAL) | |
|
|
||
| # Unlike functions, macros do not introduce a scope. This is an advantage when | ||
| # trying to set global variables, as we do here. | ||
| macro (opentelemetry_set_pkgconfig_paths) | ||
| if (IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") | ||
| set(OPENTELEMETRY_PC_LIBDIR "${CMAKE_INSTALL_LIBDIR}") | ||
| else () | ||
| set(OPENTELEMETRY_PC_LIBDIR | ||
| "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") | ||
| endif () | ||
|
|
||
| if (IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") | ||
| set(OPENTELEMETRY_PC_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}") | ||
| else () | ||
| set(OPENTELEMETRY_PC_INCLUDEDIR | ||
| "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") | ||
| endif () | ||
| endmacro () | ||
|
|
||
| # Create the pkgconfig configuration file (aka *.pc files) and the rules to install it. | ||
| macro(opentelemetry_set_pkgconfig_paths) | ||
| if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") | ||
| set(OPENTELEMETRY_PC_LIBDIR "${CMAKE_INSTALL_LIBDIR}") | ||
| else() | ||
| set(OPENTELEMETRY_PC_LIBDIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") | ||
| endif() | ||
|
|
||
| if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") | ||
| set(OPENTELEMETRY_PC_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}") | ||
| else() | ||
| set(OPENTELEMETRY_PC_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") | ||
| endif() | ||
| endmacro() | ||
|
|
||
| # Register pkg-config metadata on a target. Installation is performed later by | ||
| # _otel_install_target_pkgconfig() from _otel_install_component(). | ||
| # | ||
| # * library: the short name of the target, such as `api` or `resources`. | ||
| # * name: the displayed name of the library, such as "OpenTelemetry API". | ||
| # * description: the description of the library. | ||
| # * ARGN: the names of any pkgconfig modules the generated module depends on. | ||
| # | ||
| function (opentelemetry_add_pkgconfig library name description) | ||
| function(opentelemetry_add_pkgconfig library name description) | ||
| set(_target "opentelemetry_${library}") | ||
|
|
||
| if(NOT TARGET "${_target}") | ||
| message(FATAL_ERROR | ||
| "opentelemetry_add_pkgconfig: target ${_target} not found") | ||
| endif() | ||
|
|
||
| set_target_properties( | ||
| "${_target}" | ||
| PROPERTIES INTERFACE_OTEL_PKGCONFIG_SHORT_NAME "${library}" | ||
| INTERFACE_OTEL_PKGCONFIG_NAME "${name}" | ||
| INTERFACE_OTEL_PKGCONFIG_DESCRIPTION "${description}" | ||
| INTERFACE_OTEL_PKGCONFIG_REQUIRES "${ARGN}") | ||
| endfunction() | ||
|
|
||
| # Generate and install a pkg-config file for a target that registered metadata | ||
| # via opentelemetry_add_pkgconfig(). | ||
| function(_otel_install_target_pkgconfig _TARGET _COMPONENT) | ||
| get_target_property(_short_name "${_TARGET}" INTERFACE_OTEL_PKGCONFIG_SHORT_NAME) | ||
| if(NOT _short_name OR _short_name STREQUAL "_short_name-NOTFOUND") | ||
| return() | ||
| endif() | ||
|
|
||
| get_target_property(_pc_name "${_TARGET}" INTERFACE_OTEL_PKGCONFIG_NAME) | ||
| get_target_property(_pc_desc "${_TARGET}" INTERFACE_OTEL_PKGCONFIG_DESCRIPTION) | ||
| get_target_property(_pc_requires "${_TARGET}" INTERFACE_OTEL_PKGCONFIG_REQUIRES) | ||
|
|
||
| opentelemetry_set_pkgconfig_paths() | ||
| set(target "opentelemetry_${library}") | ||
| set(OPENTELEMETRY_PC_NAME "${name}") | ||
| set(OPENTELEMETRY_PC_DESCRIPTION ${description}) | ||
| string(JOIN " " OPENTELEMETRY_PC_REQUIRES ${ARGN}) | ||
| get_target_property(target_type ${target} TYPE) | ||
| if ("${target_type}" STREQUAL "INTERFACE_LIBRARY") | ||
|
|
||
| set(OPENTELEMETRY_PC_NAME "${_pc_name}") | ||
| set(OPENTELEMETRY_PC_DESCRIPTION "${_pc_desc}") | ||
| string(JOIN " " OPENTELEMETRY_PC_REQUIRES ${_pc_requires}) | ||
|
|
||
| get_target_property(_target_type "${_TARGET}" TYPE) | ||
| if("${_target_type}" STREQUAL "INTERFACE_LIBRARY") | ||
| # Interface libraries only contain headers. They do not generate lib files | ||
| # to link against with `-l`. | ||
| set(OPENTELEMETRY_PC_LIBS "") | ||
| else () | ||
| set(OPENTELEMETRY_PC_LIBS "-l${target}") | ||
| endif () | ||
| get_target_property(target_defs ${target} INTERFACE_COMPILE_DEFINITIONS) | ||
| if (target_defs) | ||
| foreach (def ${target_defs}) | ||
| string(APPEND OPENTELEMETRY_PC_CFLAGS " -D${def}") | ||
| endforeach () | ||
| endif () | ||
|
|
||
| # Create and install the pkg-config files. | ||
| configure_file("${PROJECT_SOURCE_DIR}/cmake/templates/config.pc.in" "${target}.pc" @ONLY) | ||
| else() | ||
| set(OPENTELEMETRY_PC_LIBS "-lopentelemetry_${_short_name}") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just windering, would
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kept Using I don’t think any otel targets currently diverge from the |
||
| endif() | ||
|
|
||
| set(OPENTELEMETRY_PC_CFLAGS "") | ||
| get_target_property(_target_defs "${_TARGET}" INTERFACE_COMPILE_DEFINITIONS) | ||
| if(_target_defs AND NOT _target_defs STREQUAL "_target_defs-NOTFOUND") | ||
| foreach(_def IN LISTS _target_defs) | ||
| string(APPEND OPENTELEMETRY_PC_CFLAGS " -D${_def}") | ||
| endforeach() | ||
| endif() | ||
|
|
||
| set(_target "opentelemetry_${_short_name}") | ||
| set(_pc_file "${PROJECT_BINARY_DIR}/pkgconfig/${_target}.pc") | ||
| file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/pkgconfig") | ||
|
|
||
| configure_file("${PROJECT_SOURCE_DIR}/cmake/templates/config.pc.in" "${_pc_file}" | ||
| @ONLY) | ||
|
|
||
| install( | ||
| FILES "${CMAKE_CURRENT_BINARY_DIR}/${target}.pc" | ||
| DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") | ||
| FILES "${_pc_file}" | ||
| DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" | ||
| COMPONENT "${_COMPONENT}") | ||
| endfunction() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| # Copyright The OpenTelemetry Authors | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| cmake_minimum_required(VERSION 3.16) | ||
|
|
||
| project(opentelemetry-cpp-pkgconfig-install-test LANGUAGES CXX) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test currently only covers the pkgconfig files in the ostream component dependency chain. Can it take on a form similar to the current package test to cover all components and pkgconfig files installed? |
||
|
|
||
| if(NOT DEFINED INSTALL_TEST_SRC_DIR) | ||
| message( | ||
| FATAL_ERROR | ||
| "INSTALL_TEST_SRC_DIR must be defined when running cmake on this test project" | ||
| ) | ||
| endif() | ||
|
|
||
| if(NOT INSTALL_TEST_COMPONENTS) | ||
| message(FATAL_ERROR "INSTALL_TEST_COMPONENTS is empty") | ||
| endif() | ||
|
|
||
| find_package(PkgConfig REQUIRED) | ||
| find_package(GTest CONFIG REQUIRED) | ||
|
|
||
| file(GLOB _pkgconfig_pc_files | ||
| "${CMAKE_PREFIX_PATH}/lib/pkgconfig/opentelemetry_*.pc") | ||
| if(NOT _pkgconfig_pc_files) | ||
| message( | ||
| FATAL_ERROR | ||
| "No installed opentelemetry pkg-config files found under ${CMAKE_PREFIX_PATH}/lib/pkgconfig" | ||
| ) | ||
| endif() | ||
|
|
||
| set(_pkgconfig_modules "") | ||
| foreach(_pc_file IN LISTS _pkgconfig_pc_files) | ||
| get_filename_component(_module "${_pc_file}" NAME_WE) | ||
| list(APPEND _pkgconfig_modules "${_module}") | ||
| endforeach() | ||
| list(SORT _pkgconfig_modules) | ||
|
|
||
| message(STATUS "Testing pkg-config install on modules = ${_pkgconfig_modules}") | ||
| message( | ||
| STATUS "Testing pkg-config install on components = ${INSTALL_TEST_COMPONENTS}" | ||
| ) | ||
|
|
||
| pkg_check_modules(OTEL_PKGCONFIG REQUIRED ${_pkgconfig_modules}) | ||
|
|
||
| add_executable(full_pkgconfig_test) | ||
|
|
||
| foreach(component IN LISTS INSTALL_TEST_COMPONENTS) | ||
| message(STATUS "Adding test source for component ${component}") | ||
| target_sources(full_pkgconfig_test | ||
| PRIVATE "${INSTALL_TEST_SRC_DIR}/test_${component}.cc") | ||
| endforeach() | ||
|
|
||
| target_include_directories(full_pkgconfig_test | ||
| PRIVATE ${OTEL_PKGCONFIG_INCLUDE_DIRS}) | ||
| target_compile_options(full_pkgconfig_test | ||
| PRIVATE ${OTEL_PKGCONFIG_CFLAGS_OTHER}) | ||
| target_link_libraries( | ||
| full_pkgconfig_test | ||
| PRIVATE ${OTEL_PKGCONFIG_LIBRARIES} ${OTEL_PKGCONFIG_LDFLAGS} GTest::gtest | ||
| GTest::gtest_main) | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My idea with #4503 is to remove the separate opentelemetry_add_pkgconfig, which redefines export name and dependencies of the target. We would then rely on the
otel_add_componentfunction to create the pkgconfig files given the targets provided and their properties.The
opentelemetry_add_pkgconfigfunction then becomes unecessary and the install of the pkgconfig files is a private implementation detail of installing a component.Current mapping from the
opentelemetry_add_pkgconfigargs to target properties could be:EXPORT_NAMEproperty (this seems to be generally the case now but needs to be verified)opentelemetry-cpp::api)LINK_LIBRARIESandINTERFACE_LINK_LIBRARIESproperties. See_otel_collect_component_dependenciesfor how this is done now at the component level.Setting the target properties is still done in many places today (
EXPORT_NAME,VERSION, andSOVERSIONare separate function calls on each target). These can be consolidated to a functionotel_set_target_propertiesthat takes the export name and description.Looking at the current opentelemetry_metrics target we can already see divergence in the target dependencies between the pkgconfig function and the linked libraries.
Current:
Proposed refactor: