Skip to content
Open
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
113 changes: 102 additions & 11 deletions CMake/GeneratePkgConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,20 @@ function(get_relative_link OUTPUT PATH)
if (IS_ABSOLUTE ${PATH})
get_filename_component(DIRECTORY_NAME "${PATH}" DIRECTORY)
if (WIN32)
set(${OUTPUT} "-l\"${DIRECTORY_NAME}/${NAME}\"" PARENT_SCOPE)
# On Windows, library files can be libname.lib or name.lib
get_filename_component(FULL_NAME "${PATH}" NAME)
# Extract library name without lib prefix and extension
string(REGEX REPLACE "^lib(.+)\\.[^.]+$" "\\1" LIB_NAME "${FULL_NAME}")
# If the regex didn't match (no lib prefix), use the name without extension
if ("${LIB_NAME}" STREQUAL "${FULL_NAME}")
set(LIB_NAME "${NAME}")
endif()
set(${OUTPUT} "-L\"${DIRECTORY_NAME}\" -l${LIB_NAME}" PARENT_SCOPE)
else()
get_filename_component(FULL_NAME "${PATH}" NAME)
set(${OUTPUT} "-L\"${DIRECTORY_NAME}\" -l:${FULL_NAME}" PARENT_SCOPE)
# Extract library name without lib prefix and extension for all platforms
string(REGEX REPLACE "^lib(.+)\\.[^.]+$" "\\1" LIB_NAME "${FULL_NAME}")
set(${OUTPUT} "-L\"${DIRECTORY_NAME}\" -l${LIB_NAME}" PARENT_SCOPE)
endif()
return()
endif()
Expand All @@ -31,17 +41,85 @@ function(generate_pkgconfig TARGET DESCRIPTION)
# message("Generating pkg-config for ${TARGET}")
get_filename_component(PREFIX "${CMAKE_INSTALL_PREFIX}" REALPATH)

get_target_property(LIST "${TARGET}" LINK_LIBRARIES)
# Get the target type to handle interface libraries differently
get_target_property(LIBRARY_TYPE "${TARGET}" TYPE)
# For interface libraries, use INTERFACE_LINK_LIBRARIES instead of LINK_LIBRARIES
if ("${LIBRARY_TYPE}" STREQUAL "INTERFACE_LIBRARY")
get_target_property(LIST "${TARGET}" INTERFACE_LINK_LIBRARIES)
else()
get_target_property(LIST "${TARGET}" LINK_LIBRARIES)
endif()

# Handle the case when no libraries are found
if ("${LIST}" STREQUAL "LIST-NOTFOUND")
set(LIST "")
endif()

# Special handling for tdcore interface library
if ("${TARGET}" STREQUAL "tdcore" AND "${LIBRARY_TYPE}" STREQUAL "INTERFACE_LIBRARY")
# For tdcore interface library, we need to link to the actual part libraries
# instead of the non-existent tdcore library
set(TDCORE_LIBS "")
set(COMBINED_REQS "")
set(COMBINED_LIBS "")

foreach (PART_LIB ${LIST})
if (TARGET "${PART_LIB}" AND "${PART_LIB}" MATCHES "^tdcore_part[0-9]+$")
# Add the actual part library to link against
list(APPEND TDCORE_LIBS "-l${PART_LIB}")

# Collect dependencies from the parts
get_target_property(PART_LIST "${PART_LIB}" LINK_LIBRARIES)
if (NOT "${PART_LIST}" STREQUAL "PART_LIST-NOTFOUND")
foreach (PART_DEP ${PART_LIST})
if (TARGET "${PART_DEP}")
list(APPEND COMBINED_REQS "${PART_DEP}")
else()
list(APPEND COMBINED_LIBS "${PART_DEP}")
endif()
endforeach()
endif()
elseif (TARGET "${PART_LIB}")
list(APPEND COMBINED_REQS "${PART_LIB}")
else()
list(APPEND COMBINED_LIBS "${PART_LIB}")
endif()
endforeach()

# Remove duplicates
if (COMBINED_REQS)
list(REMOVE_DUPLICATES COMBINED_REQS)
endif()
if (COMBINED_LIBS)
list(REMOVE_DUPLICATES COMBINED_LIBS)
endif()
if (TDCORE_LIBS)
list(REMOVE_DUPLICATES TDCORE_LIBS)
endif()

set(LIST "")
list(APPEND LIST ${COMBINED_REQS})
list(APPEND LIST ${COMBINED_LIBS})

# Set a flag to use different Libs line for tdcore
set(USE_TDCORE_PARTS TRUE)
else()
set(USE_TDCORE_PARTS FALSE)
endif()

set(REQS "")
set(LIBS "")
foreach (LIB ${LIST})
if (TARGET "${LIB}")
set(HAS_REQS 1)
list(APPEND REQS "${LIB}")
# Skip internal tdcore parts as they don't have their own .pc files
if (NOT "${LIB}" MATCHES "^tdcore_part[0-9]+$")
set(HAS_REQS 1)
list(APPEND REQS "${LIB}")
endif()
else()
set(HAS_LIBS 1)
get_relative_link(LINK "${LIB}")
if (NOT LINK EQUAL "")
if (NOT "${LINK}" STREQUAL "")
list(APPEND LIBS "${LINK}")
endif()
endif()
Expand Down Expand Up @@ -77,6 +155,19 @@ function(generate_pkgconfig TARGET DESCRIPTION)
endif()

file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig")

# Generate the correct Libs line based on library type
if (USE_TDCORE_PARTS)
# For tdcore interface library, link to the actual part libraries
set(LIBS_LINE "")
foreach (PART_LIB ${TDCORE_LIBS})
set(LIBS_LINE "${LIBS_LINE} ${PART_LIB}")
endforeach()
set(LIBS_LINE "Libs: -L\"${PKGCONFIG_LIBDIR}\"${LIBS_LINE}")
else()
set(LIBS_LINE "Libs: -L\"${PKGCONFIG_LIBDIR}\" -l${TARGET}")
endif()

file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/${TARGET}.pc" CONTENT
"prefix=${PREFIX}

Expand All @@ -85,14 +176,14 @@ Description: ${DESCRIPTION}
Version: ${PROJECT_VERSION}

CFlags: -I\"${PKGCONFIG_INCLUDEDIR}\"
Libs: -L\"${PKGCONFIG_LIBDIR}\" -l${TARGET}
${LIBS_LINE}
${REQUIRES}${LIBRARIES}")

get_target_property(LIBRARY_TYPE "${TARGET}" TYPE)
if (LIBRARY_TYPE STREQUAL "STATIC_LIBRARY" OR LIBRARY_TYPE STREQUAL "SHARED_LIBRARY")
if ("${LIBRARY_TYPE}" STREQUAL "STATIC_LIBRARY" OR "${LIBRARY_TYPE}" STREQUAL "SHARED_LIBRARY")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/${TARGET}.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
elseif ("${LIBRARY_TYPE}" STREQUAL "INTERFACE_LIBRARY")
# Interface libraries are also supported, install the .pc file
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/${TARGET}.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
elseif (LIBRARY_TYPE STREQUAL "INTERFACE_LIBRARY")
# TODO: support interface libraries
else()
message(FATAL_ERROR "Don't know how to handle ${TARGET} of type ${LIBRARY_TYPE}")
endif()
Expand Down