1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#![allow(clippy::unwrap_used)]
#![allow(clippy::expect_used)]
use std::{
env,
path::{Path, PathBuf},
};
fn main() {
let mut lib_builder = cc::Build::new();
let mut builder = bindgen::Builder::default();
let host = env::var("HOST").expect("host triple is always set");
lib_builder
.include("c/include")
.opt_level(2)
.file(Path::new("c/src/lib.c"));
builder = builder
.use_core()
.detect_include_paths(true)
.clang_arg("-I")
.clang_arg("c/include")
.header("c/include/wrapper.h")
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
// Bare-metal checks parse NVTX headers using the host target, so bindgen's
// generated host layout assertions are not meaningful for that target.
.layout_tests(false)
.allowlist_recursively(false)
.generate_comments(false)
.generate_cstr(true)
.default_alias_style(bindgen::AliasVariation::TypeAlias)
.default_enum_style(bindgen::EnumVariation::Rust {
non_exhaustive: false,
})
.constified_enum_module("nvtxResource.*_t")
.c_naming(false)
.default_macro_constant_type(bindgen::MacroTypeVariation::Signed)
.sort_semantically(true)
.translate_enum_integer_types(true)
.wrap_unsafe_ops(true)
// mark any nvtx(...)_t type as required except those starting with nvtxRes
.must_use_type("nvtx[^R][^e][^s].*_t")
// permit all nvtx-prefixed types except internal ones
.allowlist_type("nvtx[^_].*")
// expose NVTX_VERSION
.allowlist_var("NVTX_VERSION")
// expose all nvtx-prefixed functions
.allowlist_function("nvtx.*")
// expose wchar_t for wide function parameters
.allowlist_type("wchar_t")
// allow cuda types
.allowlist_type("CU.*")
.allowlist_type("cuda.*")
// disallow impl-specific
.blocklist_type("__.*");
if cfg!(feature = "tools") {
builder = builder
// expose the callback-subscription types (export tables, callback
// modules, and callback ids)
.allowlist_type("Nvtx.*")
// expose the dependency-free fake types referenced by the
// fakeimpl fntypes (required because allowlisting is not recursive)
.allowlist_type("nvtx_.*")
// expose the injection result codes
.allowlist_var("NVTX_SUCCESS")
.allowlist_var("NVTX_FAIL")
.allowlist_var("NVTX_ERR_.*");
// the function-table slot signatures (`*_impl_fntype` and
// `*_fakeimpl_fntype`) are covered by the "nvtx[^_].*" allowlist above
} else {
// disallow any fntypes
builder = builder.blocklist_type(".*fntype.*");
}
if cfg!(feature = "cuda") {
builder = builder.clang_arg("-DENABLE_CUDA");
lib_builder.define("ENABLE_CUDA", None);
}
if cfg!(feature = "cuda_runtime") {
builder = builder.clang_arg("-DENABLE_CUDART");
lib_builder.define("ENABLE_CUDART", None);
}
let target_os = env::var("CARGO_CFG_TARGET_OS").expect("target OS is always set");
if target_os == "none" {
// For bare-metal cross checks, parse headers against the host's libc headers.
// NVTX does not expose target-dependent structs, so host parsing is sufficient.
builder = builder.clang_arg(format!("--target={host}"));
println!("cargo:warning=Skipping C shim build for target OS 'none'");
} else {
lib_builder.compile("nvtx");
}
let bindings = builder.generate().expect("Unable to generate bindings");
// Write the bindings to the $OUT_DIR/bindings.rs file.
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}