diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index e6b4553b2a..fabb9b6404 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -1,13 +1,17 @@
 ---
 minimum_bazel_version: &minimum_bazel_version "7.4.1"
+minimum_bazel_shell_commands: &minimum_bazel_shell_commands
+  - echo "build --build_runfile_links" >> user.bazelrc
 no_bzlmod_bazel_version: &no_bzlmod_bazel_version "7.4.1"
 no_bzlmod_shell_commands: &no_bzlmod_shell_commands
   - echo "common --noenable_bzlmod --enable_workspace" >> user.bazelrc
+  - echo "build --build_runfile_links" >> user.bazelrc
   - echo "7.4.1" > .bazelversion
 no_bzlmod_rbe_shell_commands: &no_bzlmod_rbe_shell_commands
   - sed -i 's/^# load("@bazel_ci_rules/load("@bazel_ci_rules/' WORKSPACE.bazel
   - sed -i 's/^# rbe_preconfig/rbe_preconfig/' WORKSPACE.bazel
   - echo "common --noenable_bzlmod --enable_workspace" >> user.bazelrc
+  - echo "build --build_runfile_links" >> user.bazelrc
   - echo "7.4.1" > .bazelversion
 aspects_flags: &aspects_flags
   - "--config=rustfmt"
@@ -340,6 +344,7 @@ tasks:
     # If updating the minimum bazel version, please also update /docs/index.md
     bazel: *minimum_bazel_version
     platform: ubuntu1804
+    shell_commands: *minimum_bazel_shell_commands
     build_targets: *default_linux_targets
     test_targets: *default_linux_targets
     coverage_targets: *default_linux_targets
@@ -348,6 +353,7 @@ tasks:
     name: "Min Bazel Version With Aspects"
     bazel: *minimum_bazel_version
     platform: ubuntu1804
+    shell_commands: *minimum_bazel_shell_commands
     build_targets: *default_linux_targets
     test_targets: *default_linux_targets
     build_flags: *aspects_flags
diff --git a/.bazelrc b/.bazelrc
index 28c284447b..2842c5307e 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -5,6 +5,9 @@
 ## https://bazel.build/docs/best-practices#bazelrc-file
 ###############################################################################
 
+# Skip building runfiles links for faster builds.
+build --nobuild_runfile_links
+
 # https://bazel.build/reference/command-line-reference#flag--enable_platform_specific_config
 common --enable_platform_specific_config
 
diff --git a/util/collect_coverage/collect_coverage.rs b/util/collect_coverage/collect_coverage.rs
index 22b57f7911..7aba667885 100644
--- a/util/collect_coverage/collect_coverage.rs
+++ b/util/collect_coverage/collect_coverage.rs
@@ -25,7 +25,7 @@ use std::path::Path;
 use std::path::PathBuf;
 use std::process;
 
-macro_rules! log {
+macro_rules! debug_log {
     ($($arg:tt)*) => {
         if env::var("VERBOSE_COVERAGE").is_ok() {
             eprintln!($($arg)*);
@@ -38,7 +38,7 @@ fn find_metadata_file(execroot: &Path, runfiles_dir: &Path, path: &str) -> PathB
         return execroot.join(path);
     }
 
-    log!(
+    debug_log!(
         "File does not exist in execroot, falling back to runfiles: {}",
         path
     );
@@ -74,7 +74,7 @@ fn find_test_binary(execroot: &Path, runfiles_dir: &Path) -> PathBuf {
             .join(configuration)
             .join(env::var("TEST_BINARY").unwrap());
 
-        log!(
+        debug_log!(
             "TEST_BINARY is not found in runfiles. Falling back to: {}",
             test_binary.display()
         );
@@ -94,8 +94,8 @@ fn main() {
         runfiles_dir = execroot.join(runfiles_dir);
     }
 
-    log!("ROOT: {}", execroot.display());
-    log!("RUNFILES_DIR: {}", runfiles_dir.display());
+    debug_log!("ROOT: {}", execroot.display());
+    debug_log!("RUNFILES_DIR: {}", runfiles_dir.display());
 
     let coverage_output_file = coverage_dir.join("coverage.dat");
     let profdata_file = coverage_dir.join("coverage.profdata");
@@ -132,7 +132,7 @@ fn main() {
         .arg("--output")
         .arg(&profdata_file);
 
-    log!("Spawning {:#?}", llvm_profdata_cmd);
+    debug_log!("Spawning {:#?}", llvm_profdata_cmd);
     let status = llvm_profdata_cmd
         .status()
         .expect("Failed to spawn llvm-profdata process");
@@ -153,7 +153,7 @@ fn main() {
         .arg(test_binary)
         .stdout(process::Stdio::piped());
 
-    log!("Spawning {:#?}", llvm_cov_cmd);
+    debug_log!("Spawning {:#?}", llvm_cov_cmd);
     let child = llvm_cov_cmd
         .spawn()
         .expect("Failed to spawn llvm-cov process");
@@ -161,10 +161,10 @@ fn main() {
     let output = child.wait_with_output().expect("llvm-cov process failed");
 
     // Parse the child process's stdout to a string now that it's complete.
-    log!("Parsing llvm-cov output");
+    debug_log!("Parsing llvm-cov output");
     let report_str = std::str::from_utf8(&output.stdout).expect("Failed to parse llvm-cov output");
 
-    log!("Writing output to {}", coverage_output_file.display());
+    debug_log!("Writing output to {}", coverage_output_file.display());
     fs::write(
         coverage_output_file,
         report_str
@@ -174,8 +174,8 @@ fn main() {
     .unwrap();
 
     // Destroy the intermediate binary file so lcov_merger doesn't parse it twice.
-    log!("Cleaning up {}", profdata_file.display());
+    debug_log!("Cleaning up {}", profdata_file.display());
     fs::remove_file(profdata_file).unwrap();
 
-    log!("Success!");
+    debug_log!("Success!");
 }
diff --git a/util/process_wrapper/main.rs b/util/process_wrapper/main.rs
index 2cb637fc39..68551abbac 100644
--- a/util/process_wrapper/main.rs
+++ b/util/process_wrapper/main.rs
@@ -65,7 +65,7 @@ impl fmt::Display for ProcessWrapperError {
 
 impl std::error::Error for ProcessWrapperError {}
 
-macro_rules! log {
+macro_rules! debug_log {
     ($($arg:tt)*) => {
         if std::env::var_os("RULES_RUST_PROCESS_WRAPPER_DEBUG").is_some() {
             eprintln!($($arg)*);
@@ -135,7 +135,7 @@ fn main() -> Result<(), ProcessWrapperError> {
             Stdio::inherit()
         })
         .stderr(Stdio::piped());
-    log!("{:#?}", command);
+    debug_log!("{:#?}", command);
     let mut child = command
         .spawn()
         .map_err(|e| ProcessWrapperError(format!("failed to spawn child process: {}", e)))?;