cmake_minimum_required(VERSION 3.19) include(FetchContent) project(_memalloc) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Add compile options add_compile_options(-fPIC -fvisibility=hidden -pthread -Wall -Wextra) # Platform-specific compile definitions if(APPLE) # Fix for newer macOS SDKs that don't define BSD-style types These are needed by Abseil on macOS add_compile_definitions(_DARWIN_C_SOURCE) endif() add_compile_definitions(_POSIX_C_SOURCE=200809L) # Check the DD_COMPILE_ABSEIL environment variable and build type if(DEFINED ENV{DD_COMPILE_ABSEIL} AND ("$ENV{DD_COMPILE_ABSEIL}" STREQUAL "0" OR "$ENV{DD_COMPILE_ABSEIL}" STREQUAL "false")) message("==============================================================") message("WARNING: DD_COMPILE_ABSEIL set to 0 or false: not using abseil") message("==============================================================") add_definitions(-DDONT_COMPILE_ABSEIL) elseif(CMAKE_BUILD_TYPE STREQUAL "Debug") message("=====================================") message("WARNING: Debug mode: not using abseil") message("=====================================") add_definitions(-DDONT_COMPILE_ABSEIL) else() message("Release, RelWithDebInfo, or MinSizeRel mode: using abseil (DD_COMPILE_ABSEIL unset or not 0/false)") # Use a git-based fetch rather than a ZIP download: git shallow clones are more resilient to GitHub transient # failures than release archive downloads. FETCHCONTENT_UPDATES_DISCONNECTED prevents re-fetching on every configure # once the initial clone is in the cache (set by FETCHCONTENT_BASE_DIR in setup.py). set(FETCHCONTENT_UPDATES_DISCONNECTED ON CACHE BOOL "" FORCE) FetchContent_Declare( absl GIT_REPOSITORY https://github.com/abseil/abseil-cpp.git GIT_TAG 20250127.1 GIT_SHALLOW TRUE GIT_PROGRESS TRUE) FetchContent_MakeAvailable(absl) endif() # Find Python (be flexible about what's available in build environments) find_package(Python3 COMPONENTS Interpreter Development) # Make sure we have necessary Python variables if(NOT Python3_INCLUDE_DIRS) # Fallback to PYTHON_INCLUDE_DIRS if Python3_INCLUDE_DIRS not found if(PYTHON_INCLUDE_DIRS) set(Python3_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) else() message(FATAL_ERROR "Python3_INCLUDE_DIRS not found") endif() endif() # Python3::Python target might not exist in all build environments so we'll link using include dirs and let the linker # find Python dynamically if(NOT TARGET Python3::Python) message(STATUS "Python3::Python target not found, using include dirs only") endif() # Source files for the extension set(SOURCE_FILES _memalloc.cpp _memalloc_tb.cpp _memalloc_heap.cpp _memalloc_reentrant.cpp) # Get the extension name from setup.py or use default Note: EXTENSION_NAME from setup.py already includes the full # suffix if(DEFINED EXTENSION_NAME) set(FULL_EXTENSION_NAME "${EXTENSION_NAME}") else() set(FULL_EXTENSION_NAME "_memalloc.so") endif() # Create the shared library with the full name add_library(${FULL_EXTENSION_NAME} SHARED ${SOURCE_FILES}) # Set properties to prevent CMake from adding any prefix or suffix set_target_properties(${FULL_EXTENSION_NAME} PROPERTIES PREFIX "" SUFFIX "") # Set output directory if specified if(DEFINED LIB_INSTALL_DIR) set_target_properties(${FULL_EXTENSION_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${LIB_INSTALL_DIR}) endif() # Include directories target_include_directories( ${FULL_EXTENSION_NAME} PRIVATE ${Python3_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../internal/datadog/profiling/dd_wrapper/include ${RUST_GENERATED_HEADERS_DIR}) # Link libraries Python3::Python target might not exist in all build environments (e.g., manylinux) Python modules # should use -undefined dynamic_lookup on macOS and not link to libpython on Linux if(TARGET Python3::Python AND NOT APPLE) target_link_libraries(${FULL_EXTENSION_NAME} PRIVATE Python3::Python) endif() # Link Abseil if available if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR (DEFINED ENV{DD_COMPILE_ABSEIL} AND ("$ENV{DD_COMPILE_ABSEIL}" STREQUAL "0" OR "$ENV{DD_COMPILE_ABSEIL}" STREQUAL "false")))) target_link_libraries(${FULL_EXTENSION_NAME} PRIVATE absl::flat_hash_map) endif() # Platform-specific settings if(APPLE) # macOS specific - set rpath for libdd_wrapper and use dynamic lookup for Python symbols set_target_properties( ${FULL_EXTENSION_NAME} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE INSTALL_RPATH "@loader_path/../../internal/datadog/profiling" LINK_FLAGS "-undefined dynamic_lookup") elseif(UNIX) # Linux specific set_target_properties(${FULL_EXTENSION_NAME} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE INSTALL_RPATH "$ORIGIN/../../internal/datadog/profiling") endif() # Link with libdd_wrapper if NATIVE_EXTENSION_LOCATION is defined if(DEFINED NATIVE_EXTENSION_LOCATION) # Find the libdd_wrapper shared library NATIVE_EXTENSION_LOCATION is ddtrace/internal/native, so # ../datadog/profiling gets us to ddtrace/internal/datadog/profiling where libdd_wrapper is located find_library( DD_WRAPPER_LIB NAMES libdd_wrapper${EXTENSION_SUFFIX} PATHS ${CMAKE_CURRENT_SOURCE_DIR}/../../internal/datadog/profiling ${NATIVE_EXTENSION_LOCATION}/../datadog/profiling NO_DEFAULT_PATH) if(DD_WRAPPER_LIB) message(STATUS "Found libdd_wrapper: ${DD_WRAPPER_LIB}") target_link_libraries(${FULL_EXTENSION_NAME} PRIVATE ${DD_WRAPPER_LIB}) else() message(WARNING "libdd_wrapper not found, extension may not link correctly") endif() endif() # Enable allocator-hook reentry assertions in test builds. setup.py turns this on when # DD_PROFILING_MEMALLOC_ASSERT_ON_REENTRY is set in the build environment. if(MEMALLOC_ASSERT_ON_REENTRY) message(STATUS "MEMALLOC_ASSERT_ON_REENTRY enabled: will abort on reentrant allocator hook calls") target_compile_definitions(${FULL_EXTENSION_NAME} PRIVATE MEMALLOC_ASSERT_ON_REENTRY) endif() # Add NDEBUG flag for release builds if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel") target_compile_definitions(${FULL_EXTENSION_NAME} PRIVATE NDEBUG) else() target_compile_definitions(${FULL_EXTENSION_NAME} PRIVATE UNDEBUG) endif() # Install the extension install(TARGETS ${FULL_EXTENSION_NAME} LIBRARY DESTINATION ${LIB_INSTALL_DIR})