CORE JSC

International Technology Partnership

Mobile Development

Resolving Gradle Cross-Drive Hard Link Failures in React Native Android Builds

When your React Native project lives on one drive (e.g., D:) and the global Gradle cache resides on another (e.g., C:), CMake operations during Android compilation fail to create hard links for native .so libraries. This forces Gradle to fall back to a slower copy mechanism, degrading build times by 20-30%. This comprehensive guide provides multiple concrete solutions to synchronize your environments and restore optimal build speeds.

Core JSC Team·May 28, 2026
React NativeGradleAndroidCMakeBuild PerformanceWindowsCross-Drive
Resolving Gradle Cross-Drive Hard Link Failures in React Native Android Builds

Optimizing React Native Android Build Pipelines: Fixing Cross-Drive Hard Link Failures

When running npx react-native run-android on a Windows workspace setup where your project repository and your user profile (containing global build caches) are separated across different logical drives, you may notice a significant degradation in build speeds. A deeper investigation into the build streams often uncovers warning logs indicating that CMake could not establish "hard links" between source cache assets and target build directories.


The Problem

The performance penalty arises during the compilation of C/C++ native modules (such as React Native's core architecture components like Fabric, TurboModules, or custom CMake/Prefab configurations).

Here is an example of the typical build output stream demonstrating this failure:

> Task :app:buildCMakeDebug[armeabi-v7a]
C/C++: Hard link from 'C:\Users\Core\.gradle\caches\9.3.1\transforms\2321ffcfab7439b6200de4724cf7ba76\workspace\transformed\react-android-0.85.3-debug\prefab\modules\reactnative\libs\android.armeabi-v7a\libreactnative.so' to 'D:\Projects\core-erp-mobile\android\app\build\intermediates\cxx\Debug\6a1a306s\obj\armeabi-v7a\libreactnative.so' failed. Doing a slower copy instead.

> Task :app:buildCMakeDebug[x86]
C/C++: Hard link from 'C:\Users\Core\.gradle\caches\9.3.1\transforms\2321ffcfab7439b6200de4724cf7ba76\workspace\transformed\react-android-0.85.3-debug\prefab\modules\reactnative\libs\android.x86\libreactnative.so' to 'D:\Projects\core-erp-mobile\android\app\build\intermediates\cxx\Debug\6a1a306s\obj\x86\libreactnative.so' failed. Doing a slower copy instead.

> Task :app:buildCMakeDebug[x86_64]
C/C++: Hard link from 'C:\Users\Core\.gradle\caches\9.3.1\transforms\2321ffcfab7439b6200de4724cf7ba76\workspace\transformed\react-android-0.85.3-debug\prefab\modules\reactnative\libs\android.x86_64\libreactnative.so' to 'D:\Projects\core-erp-mobile\android\app\build\intermediates\cxx\Debug\6a1a306s\obj\x86_64\libreactnative.so' failed. Doing a slower copy instead.

Why This Happens

By default, the Windows operating system file system (NTFS) restricts the creation of hard links across different volumes or partition drives. A hard link is essentially a duplicate directory entry pointing directly to the exact same physical sectors on a single disk storage cluster.

Because the global .gradle cache folder is natively initialized in the user profile directory (C:\Users\<User>\.gradle), and your React Native repository is placed on a secondary development workspace partition (D:\Projects\...), CMake tries to cross boundaries. When Hard link... failed occurs, the build system falls back to a full file binary replication stream (memcpy equivalents across partitions). This adds an immediate 20% to 30% performance penalty on complex compilations involving massive Shared Objects (.so) libraries.


The Solution

To circumvent this architectural restriction, we must ensure that both the compilation engine's target build folder and the Gradle cache cache directory reside on the same physical/logical drive volume.

Solution 1: Relocating the Global Gradle User Home via Environment Variables (Recommended)

The cleanest approach involves redirecting Gradle to read and write caches on the same drive as your development projects without moving your project repositories.

Step 1: Configure Windows Environment Variables

  1. Open the Windows Start Menu, search for "Edit the system environment variables", and open it.
  2. Click on Environment Variables....
  3. Under User variables (or System variables for global coverage), click New....
  4. Set the value parameters as follows:
  • Variable name: GRADLE_USER_HOME
  • Variable value: D:\.gradle
  1. Click OK to save and apply.

Step 2: Clean and Reinitialize the Daemon

Close all active terminal instances, VS Code, and Android Studio instances to refresh the environment flags. Open a new terminal and clear out the old project cache state:

# Navigate to your project directory
cd D:\Projects\core-erp-mobile\android

# Clean the local gradle workspace project structure
./gradlew clean

# Return to root and execute the build pipeline
cd ..
npx react-native run-android

Solution 2: Project-Level Gradle Cache Overriding

If you want this fix scoped strictly to this specific repository instead of modifying global OS settings, you can override the Gradle tracking parameters inside the execution file wrappers or global properties files.

Modify gradle.properties

Open your project's android/gradle.properties file and append the following configuration line to declare a dedicated cache root on the D: drive:

# android/gradle.properties
# Redirect the project's gradle execution path to prevent cross-drive linkages
gradle.user.home=D:/.gradle

Modify gradlew.bat

Alternatively, you can force the execution script inside android/gradlew.bat to automatically append the home parameter during runtime compilation. Modify the DEFAULT_JVM_OPTS setting:

@rem Find this section inside android/gradlew.bat and append the property definition
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" "-Dorg.gradle.appname=%APP_BASE_NAME%" "-Dgradle.user.home=D:/.gradle"

Solution 3: Re-allocating Project Repositories

If your primary C: drive has adequate high-speed storage overhead (e.g., an NVMe SSD drive partition), shifting the workspace directory from D:\Projects back into your native user space directory volume will resolve the discrepancy immediately:

# Move repository directory via terminal if applicable
mkdir C:\Projects
move D:\Projects\core-erp-mobile C:\Projects\core-erp-mobile
cd C:\Projects\core-erp-mobile
npx react-native run-android

Why This Works

To understand why this change completely removes the bottleneck, let's look at the underlying low-level operating system storage management principles.

  • Hard Links: A hard link creates an alternative directory entry mapping directly to the identical Inode or file reference descriptor blocks on the disk. It takes $O(1)$ time complexity because no data sectors are written; only a pointer is created.
  • The Multi-Drive Constraint: Because an NTFS Master File Table (MFT) cannot index or cross-reference clusters belonging to a separate disk volume or logical partition, true hard links across C: and D: are architecturally impossible.
  • The Copy Fallback: When CMake attempts to call the native Windows file management APIs to link across drives, the operation returns a failure code. The build architecture catches this error and triggers a classic synchronous file-copy pipeline. This requires allocating memory blocks, reading the source binary byte streams from disk, transmitting them across the bus infrastructure, and writing them down sector-by-sector onto the new partition, changing an $O(1)$ operation into a resource-intensive $O(N)$ operation.

By keeping everything on a single drive, CMake successfully generates the pointers instantaneously, leading to significantly faster build times.


Conclusion

Cross-drive compilation bottlenecks are common on multi-drive development environments. If you notice logs indicating that hard links are failing during Android compilation tasks, you should align your storage locations. By setting the GRADLE_USER_HOME environment variable to match your project's logical drive, you can eliminate file system copying overhead, maximize disk I/O performance, and significantly speed up your React Native build pipeline.