Skip to content

Commit 21033c7

Browse files
bmehta001Copilot
andcommitted
Restore WinML bootstrap auto-detection
Restore the bootstrap auto-detection behavior that 4a7dde2 removed across the C#, JS, Python, and Rust SDKs, while leaving the C# WinML minimum-version alignment intact. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 4a7dde2 commit 21033c7

9 files changed

Lines changed: 69 additions & 5 deletions

File tree

sdk/cs/src/Detail/CoreInterop.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,14 @@ internal CoreInterop(Configuration config, ILogger logger)
125125

126126
var request = new CoreInteropRequest { Params = config.AsDictionary() };
127127

128+
#if IS_WINML
129+
// WinML builds require bootstrapping the Windows App Runtime
130+
if (!request.Params.ContainsKey("Bootstrap"))
131+
{
132+
request.Params["Bootstrap"] = "true";
133+
}
134+
#endif
135+
128136
var response = ExecuteCommand("initialize", request);
129137

130138
if (response.Error != null)

sdk/js/src/detail/coreInterop.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ export class CoreInterop {
5050
const corePath = path.join(packageDir, `Microsoft.AI.Foundry.Local.Core${ext}`);
5151
if (fs.existsSync(corePath)) {
5252
config.params['FoundryLocalCorePath'] = corePath;
53+
54+
// Auto-detect if WinML Bootstrap is needed by checking for Bootstrap DLL in FoundryLocalCorePath
55+
// Only auto-set if the user hasn't explicitly provided a value
56+
if (!('Bootstrap' in config.params)) {
57+
const bootstrapDllPath = path.join(packageDir, 'Microsoft.WindowsAppRuntime.Bootstrap.dll');
58+
if (fs.existsSync(bootstrapDllPath)) {
59+
// WinML Bootstrap DLL found, enable bootstrapping
60+
config.params['Bootstrap'] = 'true';
61+
}
62+
}
63+
5364
return corePath;
5465
}
5566

sdk/js/test/testUtils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ export const TEST_CONFIG: FoundryLocalConfig = {
3434
appName: 'FoundryLocalTest',
3535
modelCacheDir: getTestDataSharedPath(),
3636
logLevel: 'warn',
37-
logsDir: path.join(getGitRepoRoot(), 'sdk', 'js', 'logs')
37+
logsDir: path.join(getGitRepoRoot(), 'sdk', 'js', 'logs'),
38+
additionalSettings: { 'Bootstrap': 'false' }
3839
};
3940

4041
export const TEST_MODEL_ALIAS = 'qwen2.5-0.5b';

sdk/python/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pip install foundry-local-sdk
2929
pip install foundry-local-sdk-winml
3030
```
3131

32-
Each package installs the correct native binaries (`foundry-local-core`, `onnxruntime-core`, `onnxruntime-genai-core`) as wheel dependencies. They are mutually exclusive — install only one per environment. The WinML package carries the reg-free WinML runtime app-locally, so no Windows App Runtime bootstrap step is required.
32+
Each package installs the correct native binaries (`foundry-local-core`, `onnxruntime-core`, `onnxruntime-genai-core`) as wheel dependencies. They are mutually exclusive — install only one per environment. WinML is auto-detected at runtime: if the WinML package is installed, the SDK automatically enables the Windows App Runtime Bootstrap.
3333

3434
### Building from source
3535

@@ -154,6 +154,7 @@ config = Configuration(
154154
app_name="MyApp",
155155
model_cache_dir="/path/to/cache", # optional
156156
log_level=LogLevel.INFORMATION, # optional (default: Warning)
157+
additional_settings={"Bootstrap": "false"}, # optional
157158
)
158159
FoundryLocalManager.initialize(config)
159160
manager = FoundryLocalManager.instance
@@ -303,4 +304,4 @@ See [test/README.md](test/README.md) for detailed test setup and structure.
303304

304305
```bash
305306
python examples/chat_completion.py
306-
```
307+
```

sdk/python/src/detail/core_interop.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,21 @@ def __init__(self, config: Configuration):
202202
config.additional_settings["OrtLibraryPath"] = str(paths.ort)
203203
config.additional_settings["OrtGenAILibraryPath"] = str(paths.genai)
204204

205+
# Auto-detect WinML Bootstrap: if the Bootstrap DLL is present
206+
# in the native binaries directory and the user hasn't explicitly
207+
# set the Bootstrap config, enable it automatically.
208+
if sys.platform.startswith("win"):
209+
bootstrap_dll = paths.core_dir / "Microsoft.WindowsAppRuntime.Bootstrap.dll"
210+
if bootstrap_dll.exists():
211+
# Pre-load so the DLL is already in the process when
212+
# C# P/Invoke resolves it during Bootstrap.Initialize().
213+
ctypes.CDLL(str(bootstrap_dll))
214+
if config.additional_settings is None:
215+
config.additional_settings = {}
216+
if "Bootstrap" not in config.additional_settings:
217+
logger.info("WinML Bootstrap DLL detected — enabling Bootstrap")
218+
config.additional_settings["Bootstrap"] = "true"
219+
205220
request = InteropRequest(params=config.as_dictionary())
206221
response = self.execute_command("initialize", request)
207222
if response.error is not None:

sdk/python/test/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ def get_test_config() -> Configuration:
6565
model_cache_dir=get_test_data_shared_path(),
6666
log_level=LogLevel.WARNING,
6767
logs_dir=str(repo_root / "sdk" / "python" / "logs"),
68+
additional_settings={"Bootstrap": "false"},
6869
)
6970

7071

sdk/rust/src/configuration.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,10 @@ mod tests {
228228
#[test]
229229
fn builder_additional_settings() {
230230
let cfg = FoundryLocalConfig::new("App")
231-
.additional_setting("ExampleSetting", "value")
231+
.additional_setting("Bootstrap", "false")
232232
.additional_setting("Foo", "bar");
233233
let (c, _) = Configuration::new(cfg).unwrap();
234-
assert_eq!(c.params["ExampleSetting"], "value");
234+
assert_eq!(c.params["Bootstrap"], "false");
235235
assert_eq!(c.params["Foo"], "bar");
236236
}
237237
}

sdk/rust/src/detail/core_interop.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,21 @@ impl CoreInterop {
255255
pub fn new(config: &mut Configuration) -> Result<Self> {
256256
let lib_path = Self::resolve_library_path(config)?;
257257

258+
// Auto-detect WinAppSDK Bootstrap DLL next to the core library.
259+
// If present, tell the native core to run the bootstrapper during
260+
// initialisation — this is required for WinML execution providers.
261+
#[cfg(target_os = "windows")]
262+
if !config.params.contains_key("Bootstrap") {
263+
if let Some(dir) = lib_path.parent() {
264+
if dir
265+
.join("Microsoft.WindowsAppRuntime.Bootstrap.dll")
266+
.exists()
267+
{
268+
config.params.insert("Bootstrap".into(), "true".into());
269+
}
270+
}
271+
}
272+
258273
#[cfg(target_os = "windows")]
259274
let _dependency_libs = Self::load_windows_dependencies(&lib_path)?;
260275

@@ -576,6 +591,16 @@ impl CoreInterop {
576591

577592
let mut libs = Vec::new();
578593

594+
// Load WinML bootstrap if present.
595+
let bootstrap = dir.join("Microsoft.WindowsAppRuntime.Bootstrap.dll");
596+
if bootstrap.exists() {
597+
// SAFETY: Pre-loading a known dependency DLL from the same trusted
598+
// directory as the core library.
599+
if let Ok(lib) = unsafe { Library::new(&bootstrap) } {
600+
libs.push(lib);
601+
}
602+
}
603+
579604
for dep in &["onnxruntime.dll", "onnxruntime-genai.dll"] {
580605
let dep_path = dir.join(dep);
581606
if dep_path.exists() {

sdk/rust/tests/integration/common/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ pub fn get_audio_file_path() -> PathBuf {
6868
/// * `modelCacheDir` → `<repo-root>/../test-data-shared`
6969
/// * `logsDir` → `<repo-root>/sdk/rust/logs`
7070
/// * `logLevel` → `Warn`
71+
/// * `Bootstrap` → `false` (via additional settings)
7172
pub fn test_config() -> FoundryLocalConfig {
7273
let repo_root = get_git_repo_root();
7374
let logs_dir = repo_root.join("sdk").join("rust").join("logs");
@@ -76,6 +77,7 @@ pub fn test_config() -> FoundryLocalConfig {
7677
.model_cache_dir(get_test_data_shared_path().to_string_lossy().into_owned())
7778
.logs_dir(logs_dir.to_string_lossy().into_owned())
7879
.log_level(LogLevel::Warn)
80+
.additional_setting("Bootstrap", "false")
7981
}
8082

8183
/// Create (or return the cached) [`FoundryLocalManager`] for tests.

0 commit comments

Comments
 (0)