Skip to content

Only add typical CUDA paths to the linker search paths if no explicit path is supplied#475

Merged
chelsea0x3b merged 3 commits into
chelsea0x3b:mainfrom
johanpel:optional-standard-locations
Oct 30, 2025
Merged

Only add typical CUDA paths to the linker search paths if no explicit path is supplied#475
chelsea0x3b merged 3 commits into
chelsea0x3b:mainfrom
johanpel:optional-standard-locations

Conversation

@johanpel

Copy link
Copy Markdown
Contributor

In the build script fn link_searches(...) figures out where CUDA libraries may be.
There are two ways of generating linker search paths

  1. supplied through some typical environment variables, e.g. CUDA_PATH
  2. from some hardcoded "standard locations" that include system paths, e.g. /usr.

Currently, the way the linker search paths are generated is that any valid paths generated from 2 are always appended to the linker search paths.

This is a problem when building in Conda environments, because this will cause the linker to see all system-installed libraries. This will cause obscure linker errors as shown below, because Conda environments may use a different libc etc. than the system-installed one:

  = note: rust-lld: error: undefined symbol: __libc_csu_fini
          >>> referenced by /home/johan/workspace/cudarc/.pixi/envs/cuda-12090/bin/../x86_64-conda-linux-gnu/sysroot/usr/lib/../lib/Scrt1.o:(_start)

          rust-lld: error: undefined symbol: __libc_csu_init
          >>> referenced by /home/johan/workspace/cudarc/.pixi/envs/cuda-12090/bin/../x86_64-conda-linux-gnu/sysroot/usr/lib/../lib/Scrt1.o:(_start)

Therefore, this PR does two things:

  1. If any CUDA_PATH-like environment variable is defined during building, it will no longer add any "standard locations" to the linker search paths in order to prevent system libraries from being exposed to the linker.
  2. For the Conda-specific problem described above, emit a warning at build time when dynamically linking without setting any of the CUDA_PATH-like environment variables, just to help out folks running into this scenario.

@johanpel johanpel requested a review from chelsea0x3b as a code owner October 30, 2025 10:16

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request correctly modifies the build script to only use typical CUDA search paths when no explicit environment variables like CUDA_PATH are set. This helps prevent linker errors in environments like Conda. It also adds a helpful warning for Conda users. The changes are logical and address the described problem. I have one suggestion to improve the implementation's efficiency by using iterators instead of collecting into vectors, which will reduce memory allocations in the build process.

Comment thread build.rs
Comment on lines +242 to +246
let env_vars = TYPICAL_CUDA_PATH_ENV_VARS
.iter()
.map(std::env::var)
.filter_map(Result::ok);
.filter_map(Result::ok)
.collect::<Vec<_>>();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Collecting the environment variables into a Vec here is inefficient as it forces an allocation. The subsequent logic then requires another allocation if no environment variables are found. This can be made more performant and idiomatic by using iterators.

Consider refactoring this part of link_searches to use a peekable() iterator and a trait object (Box<dyn Iterator<...>>) to avoid allocations:

// In link_searches function
let mut env_vars_iter = TYPICAL_CUDA_PATH_ENV_VARS
    .iter()
    .map(std::env::var)
    .filter_map(Result::ok)
    .peekable();

let no_env_vars = env_vars_iter.peek().is_none();

// ... conda warning logic using `no_env_vars` ...

let roots_iter: Box<dyn Iterator<Item = PathBuf>> = if no_env_vars {
    Box::new(typical_locations.into_iter().map(PathBuf::from))
} else {
    Box::new(env_vars_iter.map(PathBuf::from))
};

for root in roots_iter {
    // ... existing loop body
}

This approach avoids intermediate collections, reducing memory allocations and making the code cleaner.

Comment thread build.rs Outdated
@chelsea0x3b chelsea0x3b merged commit 8f2d1d1 into chelsea0x3b:main Oct 30, 2025
33 checks passed
@chelsea0x3b

Copy link
Copy Markdown
Owner

Great improvement, ty!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants