Windows build: generate the OpenCL import library, drop the SDK dependency
Building the `gpu` (OpenCL) backend on Windows no longer needs a vendor OpenCL SDK. `cl-sys` links `OpenCL` (#[link(name = "OpenCL")]); instead of requiring an SDK-provided OpenCL.lib, build.rs now generates a vendor-neutral import library at build time from windows/OpenCL.def (all 118 cl-sys exports) — lib.exe for MSVC (located via the cc crate), dlltool for MinGW — and puts it on the link search path. The real OpenCL.dll is supplied at runtime by the GPU driver. build.rs no-ops on non-Windows targets and when the gpu feature is off, and warns rather than panics if the toolchain tool is absent so `cargo check` still works. Combined with the runtime-loaded (dlopen) CUDA/NVML, a Windows build now needs zero external GPU libraries. Add BUILD-windows.md (toolchain, build, crt-static packaging, runtime deps, CI) and link it from the README. Verified the whole crate compiles for x86_64-pc-windows-gnu (default features and gpu,cuda); Linux is unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,119 @@
|
|||||||
|
# Building jackpotminer on Windows
|
||||||
|
|
||||||
|
The miner builds on Windows with **no external GPU SDKs**. The CUDA driver and
|
||||||
|
NVML are loaded at runtime (`dlopen`/`LoadLibrary`), and the OpenCL import
|
||||||
|
library is generated at build time from `windows/OpenCL.def` — so you don't need
|
||||||
|
the CUDA Toolkit, an OpenCL SDK, or any vendor libraries to compile. The whole
|
||||||
|
codebase (miner + the `jackpotminer-config` GUI) is verified to compile for
|
||||||
|
`x86_64-pc-windows-*`.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- **Rust** (https://rustup.rs). The default target is `x86_64-pc-windows-msvc`.
|
||||||
|
- **MSVC build tools** — Visual Studio 2019/2022 or the standalone *Build Tools
|
||||||
|
for Visual Studio* with the **“Desktop development with C++”** workload (gives
|
||||||
|
`link.exe`, `lib.exe`, and the Windows SDK).
|
||||||
|
- Build from a **“x64 Native Tools Command Prompt for VS”** (or any shell where
|
||||||
|
the MSVC environment is active) so `lib.exe` is found. `cargo` also locates
|
||||||
|
it automatically via the registry in most cases.
|
||||||
|
- *(Alternative toolchain)* the GNU target `x86_64-pc-windows-gnu` works too,
|
||||||
|
with **MinGW-w64** on `PATH` (provides `dlltool` and the linker).
|
||||||
|
|
||||||
|
No CUDA Toolkit and **no OpenCL SDK** are required.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
:: Default: OpenCL + CUDA backends + the GUI config tool
|
||||||
|
cargo build --release
|
||||||
|
|
||||||
|
:: Miner only (no GUI), both GPU backends
|
||||||
|
cargo build --release --no-default-features --features gpu,cuda
|
||||||
|
|
||||||
|
:: OpenCL only (AMD / Intel / NVIDIA)
|
||||||
|
cargo build --release --no-default-features --features gpu
|
||||||
|
|
||||||
|
:: NVIDIA only — needs nothing external at build time (CUDA is dlopen'd)
|
||||||
|
cargo build --release --no-default-features --features cuda
|
||||||
|
```
|
||||||
|
|
||||||
|
Outputs: `target\release\jackpotminer.exe` (and `jackpotminer-config.exe` with
|
||||||
|
the default features).
|
||||||
|
|
||||||
|
### How the OpenCL build dependency is avoided
|
||||||
|
|
||||||
|
`ocl`/`cl-sys` link `OpenCL` (`#[link(name = "OpenCL")]`), which normally needs
|
||||||
|
an `OpenCL.lib` from a vendor SDK. Instead, `build.rs` generates a
|
||||||
|
vendor-neutral import library from `windows/OpenCL.def`:
|
||||||
|
|
||||||
|
- **MSVC:** `lib.exe /def:windows\OpenCL.def /out:OpenCL.lib /machine:X64`
|
||||||
|
- **GNU:** `dlltool -d windows/OpenCL.def -l libOpenCL.a -m i386:x86-64`
|
||||||
|
|
||||||
|
and puts it on the link search path. The import library only forwards to
|
||||||
|
`OpenCL.dll`, which the GPU driver provides at runtime. If the toolchain tool
|
||||||
|
isn’t on `PATH`, `build.rs` prints a warning and the link step fails with a clear
|
||||||
|
message (compilation/`cargo check` still works).
|
||||||
|
|
||||||
|
## Distribution
|
||||||
|
|
||||||
|
Statically link the MSVC C runtime so users don’t need the VC++ redistributable:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
set RUSTFLAGS=-C target-feature=+crt-static
|
||||||
|
cargo build --release
|
||||||
|
```
|
||||||
|
|
||||||
|
## Runtime dependencies (on the mining machine)
|
||||||
|
|
||||||
|
- **`OpenCL.dll`** — the ICD loader, installed with any GPU driver (AMD/NVIDIA/
|
||||||
|
Intel). Required for the OpenCL backend.
|
||||||
|
- **`nvcuda.dll`** + **`nvml.dll`** — installed with the NVIDIA driver. Loaded
|
||||||
|
on demand for the CUDA backend; absent on AMD-only machines, where the miner
|
||||||
|
simply reports no CUDA devices.
|
||||||
|
- The **VC++ runtime**, unless you built with `+crt-static`.
|
||||||
|
|
||||||
|
A `cuda`-enabled binary still starts on a machine with no NVIDIA driver.
|
||||||
|
|
||||||
|
## Building Windows binaries without a Windows machine
|
||||||
|
|
||||||
|
### GitHub Actions (recommended)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: windows
|
||||||
|
on: [push, workflow_dispatch]
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-latest # MSVC + lib.exe already on PATH
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
- run: cargo build --release --features gpu,cuda
|
||||||
|
env:
|
||||||
|
RUSTFLAGS: -C target-feature=+crt-static
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: jackpotminer-windows
|
||||||
|
path: target/release/*.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cross-compile from Linux (GNU target)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rustup target add x86_64-pc-windows-gnu
|
||||||
|
sudo pacman -S mingw-w64 # or your distro's mingw-w64 (gives dlltool + linker)
|
||||||
|
cargo build --release --target x86_64-pc-windows-gnu --no-default-features --features gpu,cuda
|
||||||
|
```
|
||||||
|
|
||||||
|
The MSVC target can’t be linked from Linux. The GUI config tool (`eframe`) is
|
||||||
|
easiest to build natively on Windows.
|
||||||
|
|
||||||
|
## Status / caveats
|
||||||
|
|
||||||
|
- **Compilation for Windows is verified** here via `cargo check
|
||||||
|
--target x86_64-pc-windows-gnu` (default features, and `gpu,cuda`).
|
||||||
|
- The OpenCL **import-library linking** uses the standard `lib.exe`/`dlltool`
|
||||||
|
technique; validate it with an actual Windows (or MinGW cross) build, which
|
||||||
|
needs those tools present.
|
||||||
|
- `relaunch_in_terminal` (reopen-in-a-terminal on GUI launch) is Linux-only;
|
||||||
|
harmless on Windows, where double-clicking a console binary already opens a
|
||||||
|
console.
|
||||||
Generated
+1
@@ -2230,6 +2230,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"blake2b_simd",
|
"blake2b_simd",
|
||||||
|
"cc",
|
||||||
"clap",
|
"clap",
|
||||||
"core_affinity",
|
"core_affinity",
|
||||||
"ctrlc",
|
"ctrlc",
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ name = "jackpotminer-config"
|
|||||||
path = "src/config_gui.rs"
|
path = "src/config_gui.rs"
|
||||||
required-features = ["config-gui"]
|
required-features = ["config-gui"]
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
# Locates the MSVC `lib.exe` (to generate the OpenCL import library on Windows);
|
||||||
|
# unused on other platforms. See build.rs.
|
||||||
|
cc = "1"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
lto = true
|
lto = true
|
||||||
|
|||||||
@@ -114,6 +114,13 @@ cargo build --release --no-default-features --features cuda # CUDA only
|
|||||||
cargo build --release --no-default-features # CPU-only (no GPU)
|
cargo build --release --no-default-features # CPU-only (no GPU)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
Builds with no external GPU SDKs — CUDA/NVML are loaded at runtime and the
|
||||||
|
OpenCL import library is generated at build time. See
|
||||||
|
[BUILD-windows.md](BUILD-windows.md) for the toolchain, build, and packaging
|
||||||
|
steps.
|
||||||
|
|
||||||
### Portable / distributable builds
|
### Portable / distributable builds
|
||||||
|
|
||||||
The miner's only runtime dependencies are the C library and the OpenCL ICD loader
|
The miner's only runtime dependencies are the C library and the OpenCL ICD loader
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
//! Build script — Windows OpenCL import library only.
|
||||||
|
//!
|
||||||
|
//! On Windows, the `ocl`/`cl-sys` crates link `OpenCL` (`#[link(name =
|
||||||
|
//! "OpenCL")]`), which normally requires an `OpenCL.lib` import library from a
|
||||||
|
//! vendor OpenCL SDK. To avoid that build dependency, we generate a
|
||||||
|
//! vendor-neutral import library ourselves from `windows/OpenCL.def` (the list
|
||||||
|
//! of OpenCL exports) using the toolchain's own tools — `lib.exe` for MSVC,
|
||||||
|
//! `dlltool` for the GNU (MinGW) toolchain — and put it on the link search path.
|
||||||
|
//! The real `OpenCL.dll` (the ICD loader) is supplied at runtime by the GPU
|
||||||
|
//! driver, exactly like `libOpenCL.so.1` on Linux.
|
||||||
|
//!
|
||||||
|
//! Nothing here is needed on non-Windows targets (the system `libOpenCL` is used
|
||||||
|
//! directly) or when the `gpu` (OpenCL) feature is off — the script no-ops. The
|
||||||
|
//! CUDA driver / NVML are loaded at runtime via dlopen (see `src/dylib.rs`), so
|
||||||
|
//! they need no build-script support.
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
println!("cargo:rerun-if-changed=windows/OpenCL.def");
|
||||||
|
|
||||||
|
// Only Windows targets with the OpenCL backend need an import library.
|
||||||
|
if env::var("CARGO_CFG_TARGET_OS").as_deref() != Ok("windows") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if env::var_os("CARGO_FEATURE_GPU").is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||||
|
let def = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("windows/OpenCL.def");
|
||||||
|
let target = env::var("TARGET").unwrap_or_default();
|
||||||
|
let is_msvc = env::var("CARGO_CFG_TARGET_ENV").as_deref() == Ok("msvc");
|
||||||
|
|
||||||
|
let (mut cmd, tool) = if is_msvc {
|
||||||
|
// lib.exe /def:OpenCL.def /out:OpenCL.lib /machine:X64
|
||||||
|
let mut c = cc::windows_registry::find(&target, "lib.exe")
|
||||||
|
.unwrap_or_else(|| Command::new("lib.exe"));
|
||||||
|
c.arg("/nologo")
|
||||||
|
.arg(format!("/def:{}", def.display()))
|
||||||
|
.arg(format!("/out:{}", out_dir.join("OpenCL.lib").display()))
|
||||||
|
.arg("/machine:X64");
|
||||||
|
(c, "lib.exe")
|
||||||
|
} else {
|
||||||
|
// GNU/MinGW: dlltool -d OpenCL.def -l libOpenCL.a -m i386:x86-64
|
||||||
|
let dlltool = ["x86_64-w64-mingw32-dlltool", "dlltool"]
|
||||||
|
.into_iter()
|
||||||
|
.find(|t| Command::new(t).arg("--version").output().is_ok())
|
||||||
|
.unwrap_or("dlltool");
|
||||||
|
let mut c = Command::new(dlltool);
|
||||||
|
c.arg("-d")
|
||||||
|
.arg(&def)
|
||||||
|
.arg("-l")
|
||||||
|
.arg(out_dir.join("libOpenCL.a"))
|
||||||
|
.arg("-m")
|
||||||
|
.arg("i386:x86-64");
|
||||||
|
(c, "dlltool")
|
||||||
|
};
|
||||||
|
|
||||||
|
match cmd.status() {
|
||||||
|
Ok(s) if s.success() => {
|
||||||
|
// Resolve `#[link(name = "OpenCL")]` against the generated import lib.
|
||||||
|
println!("cargo:rustc-link-search=native={}", out_dir.display());
|
||||||
|
}
|
||||||
|
Ok(s) => panic!("{tool} failed ({s}) generating the OpenCL import library from {}", def.display()),
|
||||||
|
Err(e) => {
|
||||||
|
// Tool not found: let `cargo check` (which doesn't link) still succeed;
|
||||||
|
// a real build will fail at link with a clear "cannot find OpenCL".
|
||||||
|
println!(
|
||||||
|
"cargo:warning=could not run {tool} to generate the OpenCL import library ({e}); \
|
||||||
|
ensure the toolchain tools are on PATH (MSVC dev prompt, or mingw-w64). \
|
||||||
|
Linking the `gpu` feature will fail until then."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
; OpenCL import library definition for jackpotminer's Windows build.
|
||||||
|
; Generated from the cl-sys 0.4.3 exports so a vendor-neutral OpenCL.lib /
|
||||||
|
; libOpenCL.a can be produced at build time without an OpenCL SDK. The actual
|
||||||
|
; OpenCL.dll (ICD loader) is provided at runtime by the GPU driver.
|
||||||
|
LIBRARY OpenCL
|
||||||
|
EXPORTS
|
||||||
|
clBuildProgram
|
||||||
|
clCloneKernel
|
||||||
|
clCompileProgram
|
||||||
|
clCreateBuffer
|
||||||
|
clCreateCommandQueue
|
||||||
|
clCreateCommandQueueWithProperties
|
||||||
|
clCreateContext
|
||||||
|
clCreateContextFromType
|
||||||
|
clCreateFromGLBuffer
|
||||||
|
clCreateFromGLRenderbuffer
|
||||||
|
clCreateFromGLTexture
|
||||||
|
clCreateFromGLTexture2D
|
||||||
|
clCreateFromGLTexture3D
|
||||||
|
clCreateImage
|
||||||
|
clCreateImage2D
|
||||||
|
clCreateImage3D
|
||||||
|
clCreateKernel
|
||||||
|
clCreateKernelsInProgram
|
||||||
|
clCreatePipe
|
||||||
|
clCreateProgramWithBinary
|
||||||
|
clCreateProgramWithBuiltInKernels
|
||||||
|
clCreateProgramWithIL
|
||||||
|
clCreateProgramWithSource
|
||||||
|
clCreateSampler
|
||||||
|
clCreateSamplerWithProperties
|
||||||
|
clCreateSubBuffer
|
||||||
|
clCreateSubDevices
|
||||||
|
clCreateUserEvent
|
||||||
|
clEnqueueAcquireGLObjects
|
||||||
|
clEnqueueBarrier
|
||||||
|
clEnqueueBarrierWithWaitList
|
||||||
|
clEnqueueCopyBuffer
|
||||||
|
clEnqueueCopyBufferRect
|
||||||
|
clEnqueueCopyBufferToImage
|
||||||
|
clEnqueueCopyImage
|
||||||
|
clEnqueueCopyImageToBuffer
|
||||||
|
clEnqueueFillBuffer
|
||||||
|
clEnqueueFillImage
|
||||||
|
clEnqueueMapBuffer
|
||||||
|
clEnqueueMapImage
|
||||||
|
clEnqueueMarker
|
||||||
|
clEnqueueMarkerWithWaitList
|
||||||
|
clEnqueueMigrateMemObjects
|
||||||
|
clEnqueueNativeKernel
|
||||||
|
clEnqueueNDRangeKernel
|
||||||
|
clEnqueueReadBuffer
|
||||||
|
clEnqueueReadBufferRect
|
||||||
|
clEnqueueReadImage
|
||||||
|
clEnqueueReleaseGLObjects
|
||||||
|
clEnqueueSVMFree
|
||||||
|
clEnqueueSVMMap
|
||||||
|
clEnqueueSVMMemcpy
|
||||||
|
clEnqueueSVMMemFill
|
||||||
|
clEnqueueSVMMigrateMem
|
||||||
|
clEnqueueSVMUnmap
|
||||||
|
clEnqueueTask
|
||||||
|
clEnqueueUnmapMemObject
|
||||||
|
clEnqueueWaitForEvents
|
||||||
|
clEnqueueWriteBuffer
|
||||||
|
clEnqueueWriteBufferRect
|
||||||
|
clEnqueueWriteImage
|
||||||
|
clFinish
|
||||||
|
clFlush
|
||||||
|
clGetCommandQueueInfo
|
||||||
|
clGetContextInfo
|
||||||
|
clGetDeviceAndHostTimer
|
||||||
|
clGetDeviceIDs
|
||||||
|
clGetDeviceInfo
|
||||||
|
clGetEventInfo
|
||||||
|
clGetEventProfilingInfo
|
||||||
|
clGetExtensionFunctionAddress
|
||||||
|
clGetExtensionFunctionAddressForPlatform
|
||||||
|
clGetGLContextInfoKHR
|
||||||
|
clGetGLObjectInfo
|
||||||
|
clGetGLTextureInfo
|
||||||
|
clGetHostTimer
|
||||||
|
clGetImageInfo
|
||||||
|
clGetKernelArgInfo
|
||||||
|
clGetKernelInfo
|
||||||
|
clGetKernelSubGroupInfo
|
||||||
|
clGetKernelWorkGroupInfo
|
||||||
|
clGetMemObjectInfo
|
||||||
|
clGetPipeInfo
|
||||||
|
clGetPlatformIDs
|
||||||
|
clGetPlatformInfo
|
||||||
|
clGetProgramBuildInfo
|
||||||
|
clGetProgramInfo
|
||||||
|
clGetSamplerInfo
|
||||||
|
clGetSupportedImageFormats
|
||||||
|
clLinkProgram
|
||||||
|
clReleaseCommandQueue
|
||||||
|
clReleaseContext
|
||||||
|
clReleaseDevice
|
||||||
|
clReleaseEvent
|
||||||
|
clReleaseKernel
|
||||||
|
clReleaseMemObject
|
||||||
|
clReleaseProgram
|
||||||
|
clReleaseSampler
|
||||||
|
clRetainCommandQueue
|
||||||
|
clRetainContext
|
||||||
|
clRetainDevice
|
||||||
|
clRetainEvent
|
||||||
|
clRetainKernel
|
||||||
|
clRetainMemObject
|
||||||
|
clRetainProgram
|
||||||
|
clRetainSampler
|
||||||
|
clSetDefaultDeviceCommandQueue
|
||||||
|
clSetEventCallback
|
||||||
|
clSetKernelArg
|
||||||
|
clSetKernelArgSVMPointer
|
||||||
|
clSetKernelExecInfo
|
||||||
|
clSetMemObjectDestructorCallback
|
||||||
|
clSetUserEventStatus
|
||||||
|
clSVMAlloc
|
||||||
|
clSVMFree
|
||||||
|
clUnloadCompiler
|
||||||
|
clUnloadPlatformCompiler
|
||||||
|
clWaitForEvents
|
||||||
Reference in New Issue
Block a user