Skip to content
15 changes: 3 additions & 12 deletions .github/workflows/binding.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,18 @@ jobs:
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt update
sudo apt install -y cmake build-essential libtbb-dev libspdlog-dev libsimdjson-dev doxygen
sudo apt install -y cmake build-essential doxygen

- name: Install system dependencies (macOS)
if: matrix.os == 'macos-latest'
run: |
brew install cmake tbb spdlog simdjson doxygen
echo "CPLUS_INCLUDE_PATH=$(brew --prefix tbb)/include:$(brew --prefix fmt)/include:$(brew --prefix spdlog)/include:$(brew --prefix simdjson)/include" >> $GITHUB_ENV
echo "LIBRARY_PATH=$(brew --prefix tbb)/lib:$(brew --prefix fmt)/lib:$(brew --prefix spdlog)/lib:$(brew --prefix simdjson)/lib" >> $GITHUB_ENV
echo "LD_LIBRARY_PATH=$(brew --prefix tbb)/lib:$(brew --prefix fmt)/lib:$(brew --prefix spdlog)/lib:$(brew --prefix simdjson)/lib" >> $GITHUB_ENV
brew install cmake doxygen

- name: Install system dependencies (Windows)
if: matrix.os == 'windows-latest'
run: |
choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System'
choco install doxygen.install
# Install vcpkg for spdlog and tbb on Windows
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg install spdlog:x64-windows tbb:x64-windows
echo "VCPKG_ROOT=$env:GITHUB_WORKSPACE\vcpkg" >> $env:GITHUB_ENV

- name: Upgrade pip and install build dependencies
run: |
Expand Down Expand Up @@ -189,7 +180,7 @@ jobs:
- name: Install system dependencies
run: |
sudo apt update
sudo apt install -y cmake build-essential libtbb-dev libspdlog-dev libsimdjson-dev doxygen
sudo apt install -y cmake build-essential doxygen

- name: Install development dependencies
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/cmake_examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
run: |
if [ ${{ matrix.os }} == 'ubuntu-latest' ]; then
sudo apt update
sudo apt install libtbb-dev libsimdjson-dev binutils
sudo apt install binutils
elif [ ${{ matrix.os }} == 'macos-latest' ]; then
brew install tbb simdjson
fi
Expand Down
9 changes: 3 additions & 6 deletions .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ jobs:
- name: Install system dependencies
run: |
sudo apt update
sudo apt install -y cmake build-essential doxygen libtbb-dev libfmt-dev libspdlog-dev libsimdjson-dev
sudo apt install -y cmake build-essential doxygen

- name: Install build dependencies
run: |
Expand Down Expand Up @@ -127,7 +127,7 @@ jobs:

- name: Install system dependencies
run: |
brew install cmake tbb spdlog simdjson doxygen
brew install cmake doxygen

- name: Install build dependencies
run: |
Expand All @@ -136,9 +136,6 @@ jobs:

- name: Set macOS environment variables
run: |
echo "CPLUS_INCLUDE_PATH=$(brew --prefix tbb)/include:$(brew --prefix fmt)/include:$(brew --prefix spdlog)/include:$(brew --prefix simdjson)/include" >> $GITHUB_ENV
echo "LIBRARY_PATH=$(brew --prefix tbb)/lib:$(brew --prefix fmt)/lib:$(brew --prefix spdlog)/lib:$(brew --prefix simdjson)/lib" >> $GITHUB_ENV
echo "CMAKE_PREFIX_PATH=$(brew --prefix tbb);$(brew --prefix fmt);$(brew --prefix spdlog);$(brew --prefix simdjson)" >> $GITHUB_ENV
echo "ARCHFLAGS=-arch $(uname -m)" >> $GITHUB_ENV
echo "_PYTHON_HOST_PLATFORM=macosx-$(sw_vers -productVersion | cut -d. -f1)-$(uname -m)" >> $GITHUB_ENV

Expand Down Expand Up @@ -174,7 +171,7 @@ jobs:
- name: Install system dependencies
run: |
sudo apt update
sudo apt install -y cmake build-essential libtbb-dev libspdlog-dev libsimdjson-dev doxygen
sudo apt install -y cmake build-essential doxygen

- name: Install build dependencies
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y cmake build-essential libtbb-dev libspdlog-dev libsimdjson-dev doxygen
sudo apt install -y cmake build-essential doxygen
python -m pip install --upgrade pip
pip install pytest pytest-cov

Expand Down
32 changes: 22 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -130,17 +130,18 @@ if(NOT simdjson_POPULATED)
FetchContent_MakeAvailable(simdjson)
endif()
# Get TBB
set(TBB_TEST
OFF
CACHE BOOL "Disable TBB tests" FORCE)
set(TBB_TEST OFF CACHE BOOL "Disable TBB tests" FORCE)
set(TBB_EXAMPLES OFF CACHE BOOL "Disable TBB examples" FORCE)
set(TBB_STRICT OFF CACHE BOOL "Disable TBB strict mode" FORCE)
Comment on lines +133 to +135
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

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

[nitpick] The formatting style for these TBB CMake options is inconsistent with the rest of the file. Other similar configurations in the file (e.g., lines 101-103, 104-106, 107-109) use multi-line formatting with proper indentation. Consider reformatting for consistency:

set(TBB_TEST
    OFF
    CACHE BOOL "Disable TBB tests" FORCE)
set(TBB_EXAMPLES
    OFF
    CACHE BOOL "Disable TBB examples" FORCE)
set(TBB_STRICT
    OFF
    CACHE BOOL "Disable TBB strict mode" FORCE)
Suggested change
set(TBB_TEST OFF CACHE BOOL "Disable TBB tests" FORCE)
set(TBB_EXAMPLES OFF CACHE BOOL "Disable TBB examples" FORCE)
set(TBB_STRICT OFF CACHE BOOL "Disable TBB strict mode" FORCE)
set(TBB_TEST
OFF
CACHE BOOL "Disable TBB tests" FORCE)
set(TBB_EXAMPLES
OFF
CACHE BOOL "Disable TBB examples" FORCE)
set(TBB_STRICT
OFF
CACHE BOOL "Disable TBB strict mode" FORCE)

Copilot uses AI. Check for mistakes.
# set(TBB_BUILD_SHARED ON CACHE BOOL "Build TBB as shared library" FORCE)
# set(TBB_BUILD_TBBMALLOC OFF CACHE BOOL "Disable TBB malloc" FORCE)
Comment on lines +136 to +137
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

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

[nitpick] These commented-out CMake options for TBB configuration should either be removed if they're not needed, or uncommented and properly configured if they are. Leaving them commented suggests uncertainty about the TBB build configuration. If these options are needed for specific platforms or use cases, they should be documented; otherwise, they add clutter.

Suggested change
# set(TBB_BUILD_SHARED ON CACHE BOOL "Build TBB as shared library" FORCE)
# set(TBB_BUILD_TBBMALLOC OFF CACHE BOOL "Disable TBB malloc" FORCE)

Copilot uses AI. Check for mistakes.

FetchContent_Declare(
tbb
GIT_REPOSITORY https://github.com/uxlfoundation/oneTBB
GIT_TAG v2022.3.0)
FetchContent_GetProperties(tbb)
if(NOT tbb_POPULATED)
FetchContent_MakeAvailable(tbb)
endif()
GIT_REPOSITORY https://github.com/uxlfoundation/oneTBB.git
GIT_TAG v2022.3.0
)
FetchContent_MakeAvailable(tbb)

add_library(dsf STATIC ${SOURCES})
target_compile_definitions(dsf PRIVATE SPDLOG_USE_STD_FORMAT)
Expand Down Expand Up @@ -177,6 +178,12 @@ install(
if(BUILD_PYTHON_BINDINGS)
include(FetchContent)

# Check if Doxygen is available for documentation generation
find_package(Doxygen REQUIRED)
if(NOT DOXYGEN_FOUND)
message(FATAL_ERROR "Doxygen is required to build the docstrings.")
endif()
Comment on lines +183 to +185
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

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

The find_package(Doxygen REQUIRED) call already sets DOXYGEN_FOUND to TRUE if found, or fails the configuration if not found (due to REQUIRED). This subsequent check is redundant and will never trigger the FATAL_ERROR message since CMake would have already failed at the find_package step if Doxygen wasn't found.

Suggested change
if(NOT DOXYGEN_FOUND)
message(FATAL_ERROR "Doxygen is required to build the docstrings.")
endif()

Copilot uses AI. Check for mistakes.

# Get pybind11
FetchContent_Declare(
pybind11
Expand Down Expand Up @@ -218,8 +225,13 @@ if(BUILD_PYTHON_BINDINGS)
set_target_properties(
dsf_python_module
PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH "${HOMEBREW_LIB}"
INSTALL_RPATH "${HOMEBREW_LIB};@loader_path"
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

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

The CMakeLists.txt includes @loader_path in the RPATH (line 227), which is correct for loading bundled libraries. However, it still includes ${HOMEBREW_LIB} in the RPATH. Since TBB is now being fetched via FetchContent and bundled with the extension (as evidenced by setup.py copying TBB libraries), the Homebrew library paths may no longer be necessary for TBB. If spdlog and other dependencies are also fetched via FetchContent, this entire Homebrew RPATH configuration might be obsolete. Consider reviewing whether Homebrew paths are still needed or if @loader_path alone is sufficient.

Suggested change
INSTALL_RPATH "${HOMEBREW_LIB};@loader_path"
INSTALL_RPATH "@loader_path"

Copilot uses AI. Check for mistakes.
INSTALL_RPATH_USE_LINK_PATH TRUE)
elseif(UNIX)
set_target_properties(
dsf_python_module
PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH "$ORIGIN")
endif()
endif()

Expand Down
32 changes: 32 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,38 @@
cwd=build_temp,
)

# Copy TBB shared library if it exists (Linux and macOS)
if platform.system() == "Linux" or platform.system() == "Darwin":
print(f"Searching for TBB shared libraries in {build_temp}...")

tbb_libs = []
if platform.system() == "Linux":
# Look for libtbb.so* recursively
tbb_libs = list(build_temp.glob("**/libtbb.so*"))
# Also look for libtbb_debug.so* if we are in debug mode or if that's what was built
tbb_libs.extend(list(build_temp.glob("**/libtbb_debug.so*")))
Comment on lines +135 to +138
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

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

The glob pattern **/libtbb.so* will match versioned files like libtbb.so.12, but the destination uses lib.name which is just the filename (e.g., libtbb.so.12). On Linux, the extension might be linked against a symlink like libtbb.so, but this code copies the actual versioned files. If the versioned file is copied but the .so symlink is not, runtime linking might fail. Consider either:

  1. Also copying the non-versioned symlink if it exists
  2. Creating a symlink in the destination to match what the linker expects
  3. Filtering to only copy the actual library file that matches what the NEEDED entry in the ELF header expects

Copilot uses AI. Check for mistakes.
else: # macOS
# Look for libtbb.dylib* recursively
tbb_libs = list(build_temp.glob("**/libtbb*.dylib"))

if tbb_libs:
print(f"Found TBB libraries: {tbb_libs}")
for lib in tbb_libs:
# We only want the real shared object, not symlinks if possible,
# but copying everything matching the pattern is safer to ensure we get the versioned one.
# However, we need to be careful not to overwrite if multiple matches found.
# Usually we want the one that the linker linked against.
# Since we set RPATH to $ORIGIN (Linux) or @loader_path (macOS), we need the library in the same dir as the extension.

# Avoid copying if it's a symlink pointing to something we already copied?
# simpler: just copy all of them.
dest = extdir / lib.name
if not dest.exists():
shutil.copy2(lib, dest)
print(f"Copied {lib} to {dest}")
else:
print("Warning: No TBB shared libraries found to copy.")

def pre_build(self):
"""Extracts doxygen documentation from XML files and creates a C++ unordered_map"""

Expand Down
Loading