Skip to content

Commit daa77ac

Browse files
Initial windows support (#413)
Closes #387
1 parent eda2837 commit daa77ac

10 files changed

Lines changed: 38 additions & 16 deletions

File tree

.cargo/config.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[env]
22

33
RUST_LOG = "info,tower_http=debug,ort=warn,encoderfile=debug"
4+
5+
[patch.crates-io]
6+
esaxx-rs = { git = "https://github.com/mozilla-ai/esaxx-rs-dyn-msvc.git" }

Cargo.lock

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

encoderfile/src/builder/base_binary/mod.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ impl BaseBinaryResolver<'_> {
105105

106106
fn validate_binary(&self, path: &Path) -> Result<()> {
107107
terminal::info("Validating binary...");
108-
use std::os::unix::fs::PermissionsExt;
109108

110109
let meta = fs::metadata(path)
111110
.with_context(|| format!("base binary missing at {}", path.display()))?;
@@ -114,9 +113,13 @@ impl BaseBinaryResolver<'_> {
114113
anyhow::bail!("base binary is not a file: {}", path.display());
115114
}
116115

117-
let mode = meta.permissions().mode();
118-
if mode & 0o111 == 0 {
119-
anyhow::bail!("base binary is not executable: {}", path.display());
116+
#[cfg(not(target_os = "windows"))]
117+
{
118+
use std::os::unix::fs::PermissionsExt;
119+
let mode = meta.permissions().mode();
120+
if mode & 0o111 == 0 {
121+
anyhow::bail!("base binary is not executable: {}", path.display());
122+
}
120123
}
121124

122125
terminal::success("Binary validated");

encoderfile/src/builder/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ impl Transform {
244244
match self {
245245
Self::Path { path } => {
246246
if !path.exists() {
247-
bail!("No such file: {:?}", &path);
247+
bail!("No such file: {:?}", path);
248248
}
249249

250250
let mut code = String::new();

encoderfile/src/builder/tokenizer.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ fn from_tokenizer(tokenizer: &Tokenizer) -> Result<TokenizerConfig> {
117117

118118
eprintln!(
119119
"WARNING: No padding params found in `tokenizer.json`. Using defaults: {:?}",
120-
&padding_params
120+
padding_params
121121
);
122122

123123
padding_params
@@ -130,8 +130,8 @@ fn from_tokenizer(tokenizer: &Tokenizer) -> Result<TokenizerConfig> {
130130
let truncation_params = TruncationParams::default();
131131

132132
eprintln!(
133-
"WARNING: No padding params found in `tokenizer.json`. Using defaults: {:?}",
134-
&truncation_params,
133+
"WARNING: No truncation params found in `tokenizer.json`. Using defaults: {:?}",
134+
truncation_params
135135
);
136136

137137
truncation_params

encoderfile/src/transport/cli.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,9 @@ impl Commands {
175175
let banner = crate::get_banner(state.model_id().as_str());
176176

177177
if disable_grpc && disable_http {
178-
return Err(crate::error::ApiError::ConfigError(
178+
Err(crate::error::ApiError::ConfigError(
179179
"Cannot disable both gRPC and HTTP",
180-
))?;
180+
))?
181181
}
182182

183183
match enable_otel {

encoderfile/src/transport/server.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ async fn serve_with_optional_tls<S: Inference>(
103103
state: S,
104104
into_service_fn: impl Fn(&S) -> IntoMakeServiceWithConnectInfo<axum::Router, SocketAddr>,
105105
) -> Result<()> {
106-
let addr = format!("{}:{}", &hostname, &port);
106+
let addr = format!("{}:{}", hostname, port);
107107

108108
let router = into_service_fn(&state);
109109

encoderfile/tests/integration/test_build.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ tonic::include_proto!("encoderfile.metadata");
1616

1717
use encoderfile::generated::token_classification;
1818

19+
#[cfg(target_os = "windows")]
20+
const BINARY_NAME: &str = "test.encoderfile.exe";
21+
22+
#[cfg(not(target_os = "windows"))]
1923
const BINARY_NAME: &str = "test.encoderfile";
2024

2125
fn config(model_name: &String, model_path: &Path, output_path: &Path) -> String {
@@ -104,6 +108,11 @@ async fn test_build_encoderfile() -> Result<()> {
104108
.status()
105109
.expect("Failed to build encoderfile-runtime");
106110

111+
#[cfg(target_os = "windows")]
112+
let base_binary_path = fs::canonicalize("../target/debug/encoderfile-runtime.exe")
113+
.expect("Failed to canonicalize base binary path");
114+
115+
#[cfg(not(target_os = "windows"))]
107116
let base_binary_path = fs::canonicalize("../target/debug/encoderfile-runtime")
108117
.expect("Failed to canonicalize base binary path");
109118

@@ -159,13 +168,18 @@ async fn test_build_encoderfile() -> Result<()> {
159168
grpc_port,
160169
)?;
161170

171+
println!("encoderfile spawned, waiting for it to become ready...");
172+
162173
wait_for_http(
163174
format!("http://localhost:{http_port}/health").as_str(),
164175
Duration::from_secs(10),
165176
)
166177
.await?;
178+
println!("encoderfile is ready, sending inference requests...");
167179
send_http_inference(&sample_text, http_port.to_string()).await?;
180+
println!("http inference request successful");
168181
send_grpc_inference(&sample_text, grpc_port.to_string()).await?;
182+
println!("grpc inference request successful");
169183

170184
child.kill()?;
171185
child.wait().ok();
@@ -212,7 +226,7 @@ async fn send_http_inference(sample_text: &str, http_port: String) -> Result<()>
212226
}
213227

214228
async fn send_grpc_inference(sample_text: &str, grpc_port: String) -> Result<()> {
215-
let mut client = token_classification::token_classification_inference_client::TokenClassificationInferenceClient::connect(format!("http://[::]:{grpc_port}/predict")).await?;
229+
let mut client = token_classification::token_classification_inference_client::TokenClassificationInferenceClient::connect(format!("http://[::1]:{grpc_port}/predict")).await?;
216230
let req = token_classification::TokenClassificationRequest {
217231
inputs: vec![sample_text.to_owned()],
218232
metadata: std::collections::HashMap::new(),
@@ -236,7 +250,7 @@ fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> anyhow::Result<
236250
let src = src.as_ref();
237251
let dst = dst.as_ref();
238252

239-
fs::create_dir_all(dst).context(format!("Failed to create directory {:?}", &dst))?;
253+
fs::create_dir_all(dst).context(format!("Failed to create directory {:?}", dst))?;
240254

241255
for entry in fs::read_dir(src)? {
242256
let entry = entry?;

encoderfile/tests/integration/test_inspect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> anyhow::Result<
134134
let src = src.as_ref();
135135
let dst = dst.as_ref();
136136

137-
fs::create_dir_all(dst).context(format!("Failed to create directory {:?}", &dst))?;
137+
fs::create_dir_all(dst).context(format!("Failed to create directory {:?}", dst))?;
138138

139139
for entry in fs::read_dir(src)? {
140140
let entry = entry?;

test_config.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
encoderfile:
22
name: my-model-2
33
path: models/token_classification
4+
base_binary_path: target/debug/encoderfile-runtime
5+
# Base binary for windows
6+
# base_binary_path: target/debug/encoderfile-runtime.exe
47
model_type: token_classification
58
output_path: ./test-model.encoderfile
69
transform: |

0 commit comments

Comments
 (0)