Run the first verified Flow.
Install the sealed Darwin SDK, build the checked consumer example, and verify its exact result. Every command below uses the prefix created by the verifier.
1. Prepare the host
| Need | Current release boundary |
|---|---|
| Host and toolchain | Every field in the exact Darwin 1.0.4 host tuple. |
| Backend dependencies | The exact Homebrew versions in that same tuple; the SDK does not bundle MoltenVK. |
| Install location | An existing destination directory with no rund-sdk-1.0.4-darwin-arm64 child. |
2. Verify and install
Create an empty working directory. Download these three adjacent files from the 1.0.4 release into it:
rund-sdk-1.0.4-darwin-arm64.tar.gz
rund-sdk-1.0.4-darwin-arm64.sha256
rund-verifychmod +x ./rund-verify
./rund-verify \
./rund-sdk-1.0.4-darwin-arm64.tar.gz \
./rund-sdk-1.0.4-darwin-arm64.sha256 \
"$PWD"
Success creates $PWD/rund-sdk-1.0.4-darwin-arm64. Failure creates no
usable prefix; keep the typed diagnostic and use
Troubleshooting instead of bypassing it.
3. Create the project
cmake_minimum_required(VERSION 3.20)
project(rund_first_flow LANGUAGES CXX)
find_package(runD 1.0.4 EXACT CONFIG REQUIRED)
add_executable(rund_first_flow main.cpp)
target_link_libraries(rund_first_flow PRIVATE runD::sdk)
Link only runD::sdk. Do not add the source tree, copy include paths, or link
Kernel, Accel, Node, Metal, or Vulkan targets yourself.
#include <rund/compute.hpp>
#include <array>
#include <cstdint>
#include <cstdio>
#include <string_view>
#include <vector>
int main() {
std::array<std::int32_t, 4> input{1, 2, 3, 4};
auto output = rund::compute::on(rund::compute::Target::cpu(), input)
.map("twice", [](auto value) { return value * 2 + 5; })
.collect();
if (!output) {
const std::string_view message = output.error();
std::fprintf(stderr, "cpu failed (code=%u): %.*s\n",
static_cast<unsigned>(output.code()),
static_cast<int>(message.size()), message.data());
return output.exit_code();
}
if (*output != std::vector<std::int32_t>{7, 9, 11, 13}) {
std::fputs("unexpected output; expected [7, 9, 11, 13]\n", stderr);
return 2;
}
std::printf("cpu: [%d, %d, %d, %d]\n", (*output)[0], (*output)[1],
(*output)[2], (*output)[3]);
return 0;
}
4. Build and run
cmake -S . -B build \
-DCMAKE_PREFIX_PATH="$PWD/rund-sdk-1.0.4-darwin-arm64"
cmake --build build
./build/rund_first_flow
cpu: [7, 9, 11, 13]
It then exits 0. A product failure prints its code and diagnostic and returns its own
exit_code(). Exit 2 means runD succeeded but the application
assertion did not match.
5. Verify the same bytes on every target
Replace main.cpp with this complete checked program and rebuild. The Flow is
declared once; only the explicit target changes. Device opening is the capability
boundary; every backend that opens must execute and match the CPU bytes.
#include <rund/compute.hpp>
#include <array>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <span>
#include <string_view>
#include <utility>
#include <vector>
int main() {
const std::array<std::int32_t, 4> input{1, 2, 3, 4};
const auto execute = [&input](const rund::compute::Device &device) {
auto flow = rund::compute::on(device).map<std::int32_t>(
"step", input.size(), [](auto value) { return value * 2 + 1; });
auto program = std::move(flow).compile();
if (!program) {
return rund::compute::Result<std::vector<std::int32_t>>::fail(
program.reason());
}
return program->run(std::span<const std::int32_t>{input});
};
const auto report = [](const std::string_view target, const auto &result) {
const std::string_view message = result.error();
std::fprintf(stderr, "%.*s failed (code=%u): %.*s\n",
static_cast<int>(target.size()), target.data(),
static_cast<unsigned>(result.code()),
static_cast<int>(message.size()), message.data());
return result.exit_code();
};
auto cpu_device = rund::compute::open(rund::compute::Target::cpu());
if (!cpu_device) {
return report("cpu", cpu_device);
}
const auto cpu = execute(*cpu_device);
if (!cpu) {
return report("cpu", cpu);
}
const auto same_bits = [](const auto &left, const auto &right) {
return left.size() == right.size() &&
std::memcmp(left.data(), right.data(),
left.size() * sizeof(std::int32_t)) == 0;
};
const std::vector<std::int32_t> expected{3, 5, 7, 9};
if (*cpu != expected) {
std::fputs("cpu output mismatch\n", stderr);
return 2;
}
std::size_t available_backend_count = 1u;
#if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))
constexpr bool require_accelerators = true;
#else
constexpr bool require_accelerators = false;
#endif
const auto compare = [&](const std::string_view name,
const rund::compute::Target target) {
auto device = rund::compute::open(target);
if (!device) {
if (!require_accelerators &&
device.reason() == rund::compute::Reason::AdapterUnavailable) {
const std::string_view message = device.error();
std::fprintf(stderr, "%.*s unavailable (code=%u): %.*s\n",
static_cast<int>(name.size()), name.data(),
static_cast<unsigned>(device.code()),
static_cast<int>(message.size()), message.data());
return 0;
}
return report(name, device);
}
const auto result = execute(*device);
if (!result) {
return report(name, result);
}
if (!same_bits(*cpu, *result)) {
std::fprintf(stderr, "%.*s output mismatch\n",
static_cast<int>(name.size()), name.data());
return 2;
}
++available_backend_count;
return 0;
};
if (const int metal = compare("metal", rund::compute::Target::metal());
metal != 0) {
return metal;
}
if (const int vulkan = compare("vulkan", rund::compute::Target::vulkan());
vulkan != 0) {
return vulkan;
}
if (available_backend_count == 3u) {
std::printf("same bytes: cpu = metal = vulkan [%d, %d, %d, %d]\n",
(*cpu)[0], (*cpu)[1], (*cpu)[2], (*cpu)[3]);
} else {
std::printf("verified [%d, %d, %d, %d] on %zu native backend(s)\n",
(*cpu)[0], (*cpu)[1], (*cpu)[2], (*cpu)[3],
available_backend_count);
}
return 0;
}
Expected output is
same bytes: cpu = metal = vulkan [3, 5, 7, 9].
Darwin ARM64 requires all three backends. A non-Apple candidate may report the exact
AdapterUnavailable result while opening a device; it never reruns that Flow
on CPU. Any failure after a device opens remains fatal. This checked source is the
complete public parity example for the release.