Improve installation hygiene of built and header-only dependencies - #22341
Conversation
b8c6f9d to
ff6a861
Compare
41f6c6f to
e387c3d
Compare
aeae8ea to
245ee2f
Compare
29563c8 to
413b42e
Compare
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…llation # Conflicts: # dependencies.yaml
…llation # Conflicts: # cpp/CMakeLists.txt
When building shared libcudf with static dependencies, rmm and rapids_logger are absorbed into the shared library using --whole-archive to ensure all symbols are exported. This commit adds: - Conditional WHOLE_ARCHIVE linkage for rmm/rapids_logger - BUILD_INTERFACE wrapping to hide absorbed static deps from install - Transitive dependency promotion for absorbed libraries - Export set merging (rmm-exports/rapids_logger-exports into cudf-exports) - Conda/pre-installed shared library detection (TYPE introspection) - DSO header installation for standalone mode - get_rmm.cmake: full EXCLUDE_FROM_ALL support + conda fix - get_nvtx.cmake: remove export sets (rmm handles nvtx publicly) - rapids_logger: conditional static build + export package for conda
WHOLE_ARCHIVE is only meaningful when absorbing a static library into a shared library. Applying it to a shared library target triggers CMake warnings. Gate both WHOLE_ARCHIVE and BUILD_INTERFACE behind the TYPE==STATIC_LIBRARY check so the genex is never generated for pre-installed shared deps (e.g. conda rmm/rapids_logger).
Two issues caused CI failure: 1. foreach(_mode BUILD INSTALL) used uppercase, but rapids-cmake export targets use lowercase names (rapids_export_build_*, rapids_export_install_*). The if(NOT TARGET) check silently skipped the entire merge block. 2. get_nvtx.cmake was missing BUILD_EXPORT_SET/INSTALL_EXPORT_SET args. When rmm is absorbed into libcudf, its public dep nvtx3-cpp must be in an export set for CMake's install(EXPORT) validation to pass.
When static deps (rmm, rapids_logger) are absorbed into libcudf.so via whole-archive, they are not installed separately. The export-set merging loop was copying rmm-exports' install packages (including rapids_logger) into cudf-exports, producing a find_dependency(rapids_logger) that would fail for consumers of an installed standalone build. Skip packages matching _absorbed_deps names when merging install-side export set metadata.
When promoting an absorbed library's transitive deps into cudf's public interface, filter out deps that are themselves absorbed (already linked via whole-archive) and LINK_ONLY entries (private link deps already statically linked into the absorbed library).
nvtx3 is header-only. By installing its headers directly into cudf's install tree, consumers find them via cudf's include path without needing find_dependency(nvtx3) or any separate nvtx3 package. Changes: - get_nvtx.cmake: remove INSTALL_EXPORT_SET; propagate nvtx3_SOURCE_DIR to parent scope for header installation - get_rmm.cmake: strip nvtx3::nvtx3-cpp from rmm's INTERFACE_LINK_LIBRARIES after fetch, preventing the absorption loop from promoting it into cudf's installed public interface - CMakeLists.txt: filter nvtx3 from install-side export set merging; install nvtx3 headers from nvtx3_SOURCE_DIR in the DSO headers section
jameslamb
left a comment
There was a problem hiding this comment.
Left a suggestion, but otherwise approving.
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR refactors cudf's CMake build system to centralize static/shared dependency control. It introduces a 3-state ChangesCentralized Dependency Control & Parameterization
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@cpp/CMakeLists.txt`:
- Around line 1101-1112: The code is mutating the actual rmm::rmm target
(_rmm_real / _rmm_libs) to remove nvtx3::nvtx3-cpp; instead, stop altering the
real RMM target and perform the nvtx3 filter only on the interface list you plan
to promote into cuDF (e.g., build a separate _iface_libs variable from
get_target_property(... INTERFACE_LINK_LIBRARIES) and list(REMOVE_ITEM
_iface_libs nvtx3::nvtx3-cpp) before using set_property or installing/setting
cuDF's INTERFACE_LINK_LIBRARIES), leaving rmm::rmm and its ALIASED_TARGET
untouched so other in-tree targets still see nvtx headers.
- Around line 320-323: CUDF_BUILD_STATIC_DEPS currently sets CPM_DOWNLOAD_ALL ON
only when equal to "FORCE", but because CPM_DOWNLOAD_ALL is a CMake cache
variable it must be explicitly reset when not in FORCE mode; update the CMake
logic around CUDF_BUILD_STATIC_DEPS to add an else() branch that sets
CPM_DOWNLOAD_ALL to OFF (mirroring how CUDA_STATIC_RUNTIME is handled) so
previously configured FORCE builds don’t leave CPM_DOWNLOAD_ALL cached ON after
switching to ON or OFF.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 963eee15-17d8-48e3-b7e5-f35aeb338748
📒 Files selected for processing (15)
cpp/CMakeLists.txtcpp/cmake/thirdparty/get_arrow.cmakecpp/cmake/thirdparty/get_croaring.cmakecpp/cmake/thirdparty/get_cucollections.cmakecpp/cmake/thirdparty/get_dlpack.cmakecpp/cmake/thirdparty/get_flatbuffers.cmakecpp/cmake/thirdparty/get_kvikio.cmakecpp/cmake/thirdparty/get_nanoarrow.cmakecpp/cmake/thirdparty/get_nvcomp.cmakecpp/cmake/thirdparty/get_nvtx.cmakecpp/cmake/thirdparty/get_rmm.cmakecpp/cmake/thirdparty/get_thread_pool.cmakecpp/cmake/thirdparty/get_zstd.cmakecpp/tests/CMakeLists.txtjava/src/main/native/CMakeLists.txt
|
/merge |
#22341 removed the usage of this function in `get_nvcomp`, which I suspect was previously being relied on to supply the definition for some of these others. We do properly fetch it in `get_arrow.cmake` as well so it's just a matter of when each file is included. Authors: - Vyas Ramasubramani (https://github.com/vyasr) - Bradley Dice (https://github.com/bdice) - Kyle Edwards (https://github.com/KyleFromNVIDIA) Approvers: - Bradley Dice (https://github.com/bdice) URL: #22460
…VIDIA#22341) Historically we have taken a very piecemeal approach to controlling when we build some dependency statically or dynamically, and we've patched out header-only dependencies from our installation on a case-by-case basis. This PR standardizes that process with a few common controls. Specifically, we assume that there are almost no practical use cases where we want a CPM-downloaded package to be built as a shared library; if we want to dynamically link, it will be because we found the shared library on the system (e.g. a conda environment). Further, we assume that installation of private header-only deps is almost never desirable, so we should always `EXCLUDE_FROM_ALL` all private dependencies. Since rmm and rapids-logger are public dependencies, handling them is a bit more challenging. If they are downloaded as part of the build, they must also be installed along with the necessary CMake, headers, and libraries. In the case where we are building a shared libcudf.so but statically linking in the dependencies, however, we instead subsume those dependencies with whole-archive linking and revendor the headers directly. Authors: - Vyas Ramasubramani (https://github.com/vyasr) Approvers: - Bradley Dice (https://github.com/bdice) - MithunR (https://github.com/mythrocks) - James Lamb (https://github.com/jameslamb) URL: NVIDIA#22341
NVIDIA#22341 removed the usage of this function in `get_nvcomp`, which I suspect was previously being relied on to supply the definition for some of these others. We do properly fetch it in `get_arrow.cmake` as well so it's just a matter of when each file is included. Authors: - Vyas Ramasubramani (https://github.com/vyasr) - Bradley Dice (https://github.com/bdice) - Kyle Edwards (https://github.com/KyleFromNVIDIA) Approvers: - Bradley Dice (https://github.com/bdice) URL: NVIDIA#22460
Description
Historically we have taken a very piecemeal approach to controlling when we build some dependency statically or dynamically, and we've patched out header-only dependencies from our installation on a case-by-case basis. This PR standardizes that process with a few common controls. Specifically, we assume that there are almost no practical use cases where we want a CPM-downloaded package to be built as a shared library; if we want to dynamically link, it will be because we found the shared library on the system (e.g. a conda environment). Further, we assume that installation of private header-only deps is almost never desirable, so we should always
EXCLUDE_FROM_ALLall private dependencies.Since rmm and rapids-logger are public dependencies, handling them is a bit more challenging. If they are downloaded as part of the build, they must also be installed along with the necessary CMake, headers, and libraries. In the case where we are building a shared libcudf.so but statically linking in the dependencies, however, we instead subsume those dependencies with whole-archive linking and revendor the headers directly.
Checklist