risc0_build/config.rs
1// Copyright 2025 RISC Zero, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::{env, path::PathBuf};
16
17use cargo_metadata::Package;
18use derive_builder::Builder;
19use risc0_zkos_v1compat::V1COMPAT_ELF;
20use serde::{Deserialize, Serialize};
21
22use crate::DEFAULT_DOCKER_TAG;
23
24/// Options for configuring a docker build environment.
25#[derive(Clone, Debug, Default, Serialize, Deserialize, Builder)]
26#[builder(default)]
27#[non_exhaustive]
28pub struct DockerOptions {
29 /// Specify the root directory for docker builds.
30 ///
31 /// The current working directory is used if this option is unspecified.
32 #[builder(setter(into, strip_option))]
33 pub root_dir: Option<PathBuf>,
34
35 /// Additional environment variables for the build container.
36 pub env: Vec<(String, String)>,
37
38 /// Docker container tag to use
39 #[builder(setter(into, strip_option))]
40 pub docker_container_tag: Option<String>,
41}
42
43impl DockerOptions {
44 /// Get the configured root dir, or current working directory if None.
45 pub fn root_dir(&self) -> PathBuf {
46 self.root_dir
47 .clone()
48 .unwrap_or_else(|| env::current_dir().unwrap())
49 }
50
51 /// Get the configured custom environment variables.
52 pub fn env(&self) -> Vec<(&str, &str)> {
53 self.env
54 .iter()
55 .map(|(key, val)| (key.as_str(), val.as_str()))
56 .collect()
57 }
58
59 /// Get the docker container tag, or default container tag if none
60 ///
61 /// This value may be set by using the `RISC0_DOCKER_CONTAINER_TAG` environment variable.
62 pub fn docker_container_tag(&self) -> String {
63 if let Ok(tag) = env::var("RISC0_DOCKER_CONTAINER_TAG") {
64 return tag;
65 }
66
67 self.docker_container_tag
68 .clone()
69 .unwrap_or(DEFAULT_DOCKER_TAG.to_string())
70 }
71}
72
73/// Options defining how to embed a guest package in
74/// [`crate::embed_methods_with_options`].
75///
76/// ```
77/// use risc0_build::{DockerOptionsBuilder, GuestOptionsBuilder};
78///
79/// let docker_options = DockerOptionsBuilder::default()
80/// .root_dir("../../")
81/// .env(vec![("ENV_VAR".to_string(), "value".to_string())])
82/// .build()
83/// .unwrap();
84///
85/// let guest_options = GuestOptionsBuilder::default()
86/// .features(vec!["my-features".to_string()])
87/// .use_docker(docker_options)
88/// .build()
89/// .unwrap();
90/// ```
91#[derive(Default, Clone, Debug, Builder)]
92#[builder(default)]
93#[non_exhaustive]
94pub struct GuestOptions {
95 /// Features for cargo to build the guest with.
96 pub features: Vec<String>,
97
98 /// Use a docker environment for building.
99 #[builder(setter(strip_option))]
100 pub use_docker: Option<DockerOptions>,
101
102 /// Override the default kernel ELF to be used for execution.
103 #[builder(setter(strip_option))]
104 pub kernel: Option<Vec<u8>>,
105}
106
107impl GuestOptions {
108 /// Get the kernel ELF to be used for execution.
109 pub fn kernel(&self) -> Vec<u8> {
110 self.kernel.clone().unwrap_or_else(|| V1COMPAT_ELF.to_vec())
111 }
112}
113
114/// Metadata defining options to build a guest
115#[derive(Serialize, Deserialize, Clone, Default)]
116pub(crate) struct GuestMetadata {
117 /// Configuration flags to build the guest with.
118 #[serde(rename = "rustc-flags")]
119 pub(crate) rustc_flags: Option<Vec<String>>,
120
121 /// Indicates whether the guest program is a kernel.
122 #[serde(default)]
123 pub(crate) kernel: bool,
124}
125
126impl From<&Package> for GuestMetadata {
127 fn from(pkg: &Package) -> Self {
128 let Some(obj) = pkg.metadata.get("risc0") else {
129 return Default::default();
130 };
131 serde_json::from_value(obj.clone()).unwrap()
132 }
133}
134
135/// Extended options defining how to embed a guest package in
136/// [`crate::embed_methods_with_options`].
137#[derive(Default, Clone)]
138pub(crate) struct GuestInfo {
139 /// Options specified by build script or library usage.
140 pub(crate) options: GuestOptions,
141
142 /// Metadata specified in guest crate `Cargo.toml`.
143 pub(crate) metadata: GuestMetadata,
144}