Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,14 @@ jobs:
with:
vcpkgGitCommitId: "f3e10653cc27d62a37a3763cd84b38bca07c6075"

# Static-md triplet: exercise the SAME self-contained linkage the release
# leg ships (vcpkg deps linked into lci.exe, dynamic CRT). See release.yml
# windows leg for why; keep the two in lockstep so this gate proves the
# shipped artifact loads standalone.
- name: Configure
run: |
cmake --preset release `
-DVCPKG_TARGET_TRIPLET=x64-windows-static-md `
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"

- name: Dump vcpkg logs on failure
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,18 @@ jobs:
with:
vcpkgGitCommitId: "f3e10653cc27d62a37a3763cd84b38bca07c6075"

# x64-windows-static-md links the vcpkg deps (abseil, re2, xxhash, ...)
# statically INTO lci.exe while keeping the dynamic CRT (/MD) that the
# project and its FetchContent deps already use. Without this the default
# x64-windows triplet builds those deps as DLLs that the CPack TGZ does
# not bundle, so the shipped binary fails to load on any machine without
# them (the libprofiler.so.0 failure's Windows analogue). Keep this in
# lockstep with the ci.yml windows leg so the unit gate exercises the same
# linkage that ships.
- name: Configure
run: |
cmake --preset release `
-DVCPKG_TARGET_TRIPLET=x64-windows-static-md `
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"

- name: Build
Expand Down
50 changes: 31 additions & 19 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -133,35 +133,47 @@ if(WIN32)
endif()
# CoreServices framework no longer needed: efsw vendors its own FSEvents bindings.

# Optional: gperftools for --profile-cpu / --profile-memory wiring.
# When found, profiling.cpp uses ProfilerStart/HeapProfilerStart; when absent,
# the runtime path emits a clear error (Karpathy rule 6) instead of silent no-op.
# Optional: gperftools for --profile-cpu / --profile-memory wiring (DEV ONLY).
#
# OFF by default so release binaries stay self-contained. Auto-detecting the
# system gperftools and linking its SHARED libprofiler/libtcmalloc made the
# release binary hard-depend on libprofiler.so.0; machines without
# libgoogle-perftools installed fail at load ("error while loading shared
# libraries: libprofiler.so.0"). Enable explicitly for local profiling:
# -DLCI_ENABLE_GPERFTOOLS=ON. When disabled, profiling.cpp fails fast at
# runtime (Karpathy rule 6) with a clear rebuild hint.
#
# tcmalloc replaces the global allocator and is incompatible with the
# sanitizer allocators (ASan/TSan/MSan); linking both aborts at startup
# ("Attempt to free invalid pointer"). Skip gperftools entirely under any
# -fsanitize build so sanitizer presets (e.g. tsan) link and run.
# ("Attempt to free invalid pointer"). Force-disabled under any -fsanitize
# build so sanitizer presets (e.g. tsan) link and run even if ON is passed.
option(LCI_ENABLE_GPERFTOOLS "Link gperftools (shared libprofiler/libtcmalloc) for --profile-cpu/--profile-memory; dev only, breaks self-contained release" OFF)
string(FIND "${CMAKE_CXX_FLAGS}" "-fsanitize" LCI_SANITIZER_POS)
if(LCI_SANITIZER_POS GREATER -1)
set(LCI_SANITIZER_BUILD ON)
else()
set(LCI_SANITIZER_BUILD OFF)
endif()
find_library(LCI_GPERFTOOLS_PROFILER profiler)
find_library(LCI_GPERFTOOLS_TCMALLOC tcmalloc)
find_path(LCI_GPERFTOOLS_INCLUDE gperftools/profiler.h)
if(LCI_SANITIZER_BUILD)
message(STATUS "sanitizer build - gperftools/tcmalloc disabled (allocator conflict)")
elseif(LCI_GPERFTOOLS_PROFILER AND LCI_GPERFTOOLS_TCMALLOC AND LCI_GPERFTOOLS_INCLUDE)
message(STATUS "gperftools found - enabling --profile-cpu / --profile-memory")
target_compile_definitions(lci_lib PUBLIC LCI_HAVE_GPERFTOOLS=1)
target_include_directories(lci_lib PUBLIC "${LCI_GPERFTOOLS_INCLUDE}")
target_link_libraries(lci_lib PUBLIC
"${LCI_GPERFTOOLS_PROFILER}"
"${LCI_GPERFTOOLS_TCMALLOC}"
)
if(NOT LCI_ENABLE_GPERFTOOLS)
message(STATUS "gperftools disabled (LCI_ENABLE_GPERFTOOLS=OFF) - --profile-cpu/--profile-memory fail-fast at runtime")
elseif(LCI_SANITIZER_BUILD)
message(STATUS "sanitizer build - gperftools/tcmalloc force-disabled (allocator conflict)")
else()
message(STATUS "gperftools not found - --profile-cpu/--profile-memory will fail-fast at runtime")
find_library(LCI_GPERFTOOLS_PROFILER profiler)
find_library(LCI_GPERFTOOLS_TCMALLOC tcmalloc)
find_path(LCI_GPERFTOOLS_INCLUDE gperftools/profiler.h)
if(LCI_GPERFTOOLS_PROFILER AND LCI_GPERFTOOLS_TCMALLOC AND LCI_GPERFTOOLS_INCLUDE)
message(STATUS "gperftools found - enabling --profile-cpu / --profile-memory")
target_compile_definitions(lci_lib PUBLIC LCI_HAVE_GPERFTOOLS=1)
target_include_directories(lci_lib PUBLIC "${LCI_GPERFTOOLS_INCLUDE}")
target_link_libraries(lci_lib PUBLIC
"${LCI_GPERFTOOLS_PROFILER}"
"${LCI_GPERFTOOLS_TCMALLOC}"
)
else()
message(FATAL_ERROR "LCI_ENABLE_GPERFTOOLS=ON but gperftools not found "
"(apt: libgoogle-perftools-dev, brew: gperftools, vcpkg: gperftools)")
endif()
endif()

add_executable(lci
Expand Down
Loading