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

Fix pkgconfig files (mostly for static linking) #2005

Merged
merged 12 commits into from
Oct 2, 2024
104 changes: 104 additions & 0 deletions cmake/modules/BuildPkgConfigDependencies.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Get all dependencies for ${lib} and add them to ${LIBDIRS_VAR} and ${LIBS_VAR}. Ignore any
# dependencies in the list ${ignored} to: - avoid infinite recursion - avoid libscap dependencies in
# libsinsp.pc (which requires libscap.pc and pulls them in that way)
function(add_pkgconfig_library LIBDIRS_VAR LIBS_VAR lib ignored)

# if it's not a target, it doesn't have dependencies we know or care about
if(NOT TARGET ${lib})
return()
endif()

# get the libraries that ${lib} links to
get_target_property(PKGCONFIG_LIBRARIES ${lib} LINK_LIBRARIES)
if("${PKGCONFIG_LIBRARIES}" STREQUAL "PKGCONFIG_LIBRARIES-NOTFOUND")
return()
endif()

get_property(
target_type
TARGET ${lib}
PROPERTY TYPE
)
foreach(dep ${PKGCONFIG_LIBRARIES})
# ignore dependencies in the list ${ignored}
if(${dep} IN_LIST "${ignored}")
continue()
endif()

if(${target_type} STREQUAL "SHARED_LIBRARY")
# for shared libraries, do not add static libraries as dependencies
if(TARGET ${dep})
# skip static libraries which are CMake targets
get_property(
dep_target_type
TARGET ${dep}
PROPERTY TYPE
)
if(${dep_target_type} STREQUAL "STATIC_LIBRARY")
continue()
endif()
else()
# skip static libraries which are just file paths
get_filename_component(ext ${dep} LAST_EXT)
if("${ext}" STREQUAL "${CMAKE_STATIC_LIBRARY_SUFFIX}")
continue()
endif()
endif()
elseif(${target_type} STREQUAL "STATIC_LIBRARY")
# for static libraries which are not CMake targets, redirect them to
# ${libdir}/${LIBS_PACKAGE_NAME} note that ${libdir} is not a CMake variable, but a
# pkgconfig variable, so we quote it and end up with a literal ${libdir} in the
# pkgconfig file
if(NOT TARGET ${dep})
get_filename_component(filename ${dep} NAME)
set(dep "\${libdir}/${LIBS_PACKAGE_NAME}/${filename}")
endif()
endif()

add_pkgconfig_dependency(${LIBDIRS_VAR} ${LIBS_VAR} ${dep} "${ignored}")
endforeach()

# Remove duplicate search paths. We cannot remove duplicates from ${LIBS_VAR} because the order
# of libraries is important.
list(REMOVE_DUPLICATES ${LIBDIRS_VAR})

set(${LIBS_VAR}
${${LIBS_VAR}}
PARENT_SCOPE
)
set(${LIBDIRS_VAR}
${${LIBDIRS_VAR}}
PARENT_SCOPE
)
endfunction()

function(add_pkgconfig_dependency LIBDIRS_VAR LIBS_VAR lib ignored)
if(${lib} IN_LIST ignored)
# already processed, avoid infinite recursion
elseif(${lib} MATCHES "^-")
# We have a flag. Pass it through unchanged.
list(APPEND ${LIBS_VAR} ${lib})
elseif(${lib} MATCHES "/")
# We have a path. Convert it to -L<dir> + -l<lib>.
get_filename_component(lib_dir ${lib} DIRECTORY)
list(APPEND ${LIBDIRS_VAR} -L${lib_dir})
get_filename_component(lib_base ${lib} NAME_WE)
string(REGEX REPLACE "^lib" "" lib_base ${lib_base})
list(APPEND ${LIBS_VAR} -l${lib_base})
else()
# Assume we have a plain library name. Prefix it with "-l". Then recurse into its
# dependencies but ignore the library itself, so we don't end up in an infinite loop with
# cyclic dependencies
list(APPEND ${LIBS_VAR} -l${lib})
list(APPEND ignored ${lib})
add_pkgconfig_library(${LIBDIRS_VAR} ${LIBS_VAR} ${lib} "${ignored}")
endif()
set(${LIBS_VAR}
${${LIBS_VAR}}
PARENT_SCOPE
)
set(${LIBDIRS_VAR}
${${LIBDIRS_VAR}}
PARENT_SCOPE
)
endfunction()
5 changes: 0 additions & 5 deletions cmake/modules/libbpf.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,6 @@ else()
DESTINATION "${CMAKE_INSTALL_LIBDIR}/${LIBS_PACKAGE_NAME}"
COMPONENT "libs-deps"
)
install(
DIRECTORY "${LIBBPF_INCLUDE}"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${LIBS_PACKAGE_NAME}"
COMPONENT "libs-deps"
)
endif()

if(NOT TARGET libbpf)
Expand Down
5 changes: 0 additions & 5 deletions cmake/modules/libelf.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,6 @@ else()
DESTINATION "${CMAKE_INSTALL_LIBDIR}/${LIBS_PACKAGE_NAME}"
COMPONENT "libs-deps"
)
install(
DIRECTORY "${LIBELF_INCLUDE}"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${LIBS_PACKAGE_NAME}"
COMPONENT "libs-deps"
)
endif()

# We add a custom target, in this way we can always depend on `libelf` without distinguishing
Expand Down
30 changes: 4 additions & 26 deletions cmake/modules/libscap.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ if(NOT HAVE_LIBSCAP)
check_symbol_exists(strlcpy "string.h" HAVE_STRLCPY)
check_symbol_exists(strlcat "string.h" HAVE_STRLCAT)

include(BuildPkgConfigDependencies)

if(HAVE_STRLCPY)
message(STATUS "Existing strlcpy found, will *not* use local definition")
else()
Expand Down Expand Up @@ -89,33 +91,9 @@ if(NOT HAVE_LIBSCAP)
endif()
endforeach()

# Installation targets and their dependencies
set(libscap_link_libraries)
set(libscap_link_libdirs)
foreach(libscap_install_lib ${LIBSCAP_INSTALL_LIBS})
list(APPEND libscap_link_libraries ${libscap_install_lib})
get_target_property(install_lib_link_libraries ${libscap_install_lib} LINK_LIBRARIES)
foreach(install_lib_link_library ${install_lib_link_libraries})
if(NOT ${install_lib_link_library} IN_LIST libscap_subdir_targets)
if(${install_lib_link_library} MATCHES "/")
# We have a path. Convert it to -L<dir> + -l<lib>.
get_filename_component(scap_lib_dir ${install_lib_link_library} DIRECTORY)
list(APPEND libscap_link_libdirs -L${scap_lib_dir})
get_filename_component(scap_lib_base ${install_lib_link_library} NAME_WE)
string(REGEX REPLACE "^lib" "" scap_lib_base ${scap_lib_base})
list(APPEND libscap_link_libraries ${scap_lib_base})
else()
list(APPEND libscap_link_libraries ${install_lib_link_library})
endif()
endif()
endforeach()
endforeach()
list(REMOVE_DUPLICATES libscap_link_libraries)

set(libscap_link_flags)
foreach(libscap_link_library ${libscap_link_libraries})
list(APPEND libscap_link_flags "-l${libscap_link_library}")
endforeach()
set(libscap_link_libdirs "")
add_pkgconfig_dependency(libscap_link_libdirs libscap_link_flags scap "")

string(REPLACE ";" " " LIBSCAP_LINK_LIBRARIES_FLAGS "${libscap_link_flags}")
string(REPLACE ";" " " LIBSCAP_LINK_LIBDIRS_FLAGS "${libscap_link_libdirs}")
Expand Down
37 changes: 8 additions & 29 deletions cmake/modules/libsinsp.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -48,44 +48,23 @@ if(NOT HAVE_LIBSINSP)
include(bs_threadpool)
endif()

set(LIBSINSP_INCLUDE_DIRS ${LIBS_DIR} ${LIBS_DIR}/userspace ${LIBSCAP_INCLUDE_DIRS}
${DRIVER_CONFIG_DIR}
)

if(NOT EMSCRIPTEN)
get_filename_component(TBB_ABSOLUTE_INCLUDE_DIR ${TBB_INCLUDE_DIR} ABSOLUTE)
list(APPEND LIBSINSP_INCLUDE_DIRS ${TBB_ABSOLUTE_INCLUDE_DIR})
endif()

get_filename_component(JSONCPP_ABSOLUTE_INCLUDE_DIR ${JSONCPP_INCLUDE} ABSOLUTE)
list(APPEND LIBSINSP_INCLUDE_DIRS ${JSONCPP_ABSOLUTE_INCLUDE_DIR})

get_filename_component(VALIJSON_ABSOLUTE_INCLUDE_DIR ${VALIJSON_INCLUDE} ABSOLUTE)
list(APPEND LIBSINSP_INCLUDE_DIRS ${VALIJSON_ABSOLUTE_INCLUDE_DIR})
set(LIBSINSP_INCLUDE_DIRS)

get_filename_component(RE2_ABSOLUTE_INCLUDE_DIR ${RE2_INCLUDE} ABSOLUTE)
list(APPEND LIBSINSP_INCLUDE_DIRS ${RE2_ABSOLUTE_INCLUDE_DIR})

if(ENABLE_THREAD_POOL AND NOT EMSCRIPTEN)
get_filename_component(BS_THREADPOOL_ABSOLUTE_INCLUDE_DIR ${BS_THREADPOOL_INCLUDE} ABSOLUTE)
list(APPEND LIBSINSP_INCLUDE_DIRS ${BS_THREADPOOL_ABSOLUTE_INCLUDE_DIR})
if(NOT USE_BUNDLED_TBB AND NOT EMSCRIPTEN)
list(APPEND LIBSINSP_INCLUDE_DIRS ${TBB_INCLUDE_DIR})
endif()

if(NOT MINIMAL_BUILD
AND NOT EMSCRIPTEN
AND NOT APPLE
)
get_filename_component(CARES_ABSOLUTE_INCLUDE_DIR ${CARES_INCLUDE} ABSOLUTE)
list(APPEND LIBSINSP_INCLUDE_DIRS ${CARES_ABSOLUTE_INCLUDE_DIR})
if(NOT USE_BUNDLED_JSONCPP)
list(APPEND LIBSINSP_INCLUDE_DIRS ${JSONCPP_INCLUDE})
endif()

if(NOT WIN32
if(NOT USE_BUNDLED_CURL
AND NOT WIN32
AND NOT APPLE
AND NOT MINIMAL_BUILD
AND NOT EMSCRIPTEN
)
get_filename_component(CURL_ABSOLUTE_INCLUDE_DIR ${CURL_INCLUDE_DIRS} ABSOLUTE)
list(APPEND LIBSINSP_INCLUDE_DIRS ${CURL_ABSOLUTE_INCLUDE_DIR})
list(APPEND LIBSINSP_INCLUDE_DIRS ${CURL_INCLUDE_DIRS})
endif()

function(set_sinsp_target_properties target)
Expand Down
9 changes: 9 additions & 0 deletions userspace/libpman/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,12 @@ endif()
if(USE_BUNDLED_LIBBPF)
add_dependencies(pman libbpf)
endif()

install(
TARGETS pman
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
COMPONENT "scap"
OPTIONAL
)
10 changes: 1 addition & 9 deletions userspace/libscap/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,7 @@ endif()

if(HAS_ENGINE_GVISOR)
add_subdirectory(engine/gvisor)
# The static and shared build differs here because a shared scap_engine_gvisor will result in
# circular dependencies.
if(BUILD_SHARED_LIBS)
Copy link
Member

Choose a reason for hiding this comment

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

Just a question after a very first look: will BUILD_SHARED_LIBS behave like before? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

WDYM? libscap_engine_gvisor.so becomes a separate shared library, so that's a change, but other than that, there should be no observable changes (at least, Works For Me ™️)

TBH I'm not entirely sure when the circular dependency disappeared, probably when extracting some scap_platform_util or other

Copy link
Member

Choose a reason for hiding this comment

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

I meant regarding BUILD_SHARED_LIBS in general, but I noticed right now that it's only related to gvisor (and I believe it's acceptable).

cc @LucaGuerra

Copy link
Contributor Author

Choose a reason for hiding this comment

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

FWIW, I consider splitting out scap_engine_gvisor as a separate .so a fix

Copy link
Contributor

Choose a reason for hiding this comment

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

sounds fine!

# We can move this to the gvisor CMakeFile when we use CMake 3.13 or later.
# https://cmake.org/cmake/help/latest/policy/CMP0079.html
target_link_libraries(scap PRIVATE ${CMAKE_THREAD_LIBS_INIT} ${PROTOBUF_LIB} ${JSONCPP_LIB})
else()
target_link_libraries(scap PRIVATE scap_engine_gvisor)
endif()
target_link_libraries(scap PUBLIC scap_engine_gvisor)
endif()

# ##################################################################################################
Expand Down
36 changes: 10 additions & 26 deletions userspace/libscap/engine/gvisor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,32 +60,16 @@ if(USE_BUNDLED_JSONCPP)
add_dependencies(scap jsoncpp)
endif()

if(BUILD_SHARED_LIBS)
# Trying to build a shared scap_engine_gvisor will result in circular dependencies, so just add
# our sources to scap. Additionally, the GENERATED property doesn't propogate across
# directories, so enforce our dependency chain using an object library.
# https://gitlab.kitware.com/cmake/cmake/-/issues/18399
add_library(
scap_engine_gvisor_o OBJECT ${scap_engine_gvisor_sources}
${scap_engine_gvisor_generated_sources}
)
set_property(TARGET scap_engine_gvisor_o PROPERTY POSITION_INDEPENDENT_CODE ON)

add_dependencies(scap_engine_gvisor_o uthash)
add_dependencies(scap scap_engine_gvisor_o)
target_sources(scap PRIVATE $<TARGET_OBJECTS:scap_engine_gvisor_o>)
else()
add_library(
scap_engine_gvisor ${scap_engine_gvisor_sources} ${scap_engine_gvisor_generated_sources}
)
add_library(
scap_engine_gvisor ${scap_engine_gvisor_sources} ${scap_engine_gvisor_generated_sources}
)

add_dependencies(scap_engine_gvisor uthash)
target_link_libraries(
scap_engine_gvisor PRIVATE scap scap_platform_util scap_error ${CMAKE_THREAD_LIBS_INIT}
${PROTOBUF_LIB} ${JSONCPP_LIB}
)
add_dependencies(scap_engine_gvisor uthash)
target_link_libraries(
scap_engine_gvisor PUBLIC scap_platform_util scap_error ${CMAKE_THREAD_LIBS_INIT}
${PROTOBUF_LIB} ${JSONCPP_LIB}
)

target_include_directories(scap_engine_gvisor PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(scap_engine_gvisor PRIVATE ${CMAKE_CURRENT_BINARY_DIR})

set_scap_target_properties(scap_engine_gvisor)
endif()
set_scap_target_properties(scap_engine_gvisor)
2 changes: 1 addition & 1 deletion userspace/libscap/engine/nodriver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
# the License.
#
add_library(scap_engine_nodriver nodriver.c)
target_link_libraries(scap_engine_nodriver PRIVATE scap_engine_noop)
target_link_libraries(scap_engine_nodriver PUBLIC scap_engine_noop)
set_scap_target_properties(scap_engine_nodriver)
4 changes: 2 additions & 2 deletions userspace/libscap/libscap.pc.in
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
prefix=${pcfiledir}/../..
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@LIBS_PACKAGE_NAME@

Name: libscap
Description: lib for System CAPture
Version: @FALCOSECURITY_LIBS_VERSION@

Libs: -L${libdir} @LIBSCAP_LINK_LIBDIRS_FLAGS@ @LIBSCAP_LINK_LIBRARIES_FLAGS@
Cflags: -I${includedir}/@LIBS_PACKAGE_NAME@/libscap
Cflags: -I${includedir}
Loading
Loading