8000 feat(forge): Automatically download dylibs defined in `cog.scm` by nik-rev · Pull Request #424 · mattwparas/steel · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat(forge): Automatically download dylibs defined in cog.scm #424

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 60 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 71 additions & 0 deletions cogs/installer/package.scm
10000
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
run-dylib-installation
find-dylib-name))

(require-builtin steel/http as http.)

;; Used for detecting if directories/files have changed
(require "crypt.scm")

Expand Down Expand Up @@ -147,11 +149,80 @@

destination)

(define (find pred lst)
(cond
[(null? lst) #f]
[(pred (car lst)) (car lst)]
[else (find pred (cdr lst))]))

(define (install-dylib-from-spec package dylib-dependency)

(displayln "Attempting to install: " dylib-dependency)

(cond
; If we have urls for dylibs, instead of manually installing
; the dylibs with Cargo
;
; We will download files at the specified `url` into the correct `dylib-path`
[(hash-contains? dylib-dependency '#:urls)

; Name of the dylib dependency.
;
; Excludes:
; - File extension (e.g. `".dll"`)
; - Prefix (e.g. `"lib"`)
(define dylib-name (hash-ref dylib-dependency '#:name))

; e.g. `x86_64-linux`
(define target
(string-append
(target-arch!)
"-"
(current-os!)))

; Example:
;
; (
; #:platform
; "x86_64-linux"
; #:url
; "https://example.com/example.so"
; )
(define url-entry
(find (lambda (url-entry)
(let ([m (apply hash url-entry)])
(string=? (hash-ref m '#:platform) target)))
(hash-ref dylib-dependency '#:urls)))

(unless url-entry
(displayln "dylib not found for target: " target
(return! void)))

; URL to the dylib, e.g. `"https://example.com/example.so"`
(define url (hash-ref (apply hash url-entry) '#:url))

; Must be `https` connection, otherwise the file could be spoofed
; to serve a malicious dylib
(unless
(starts-with? url "https")
(displayln "url " url " must be `https://` for security purposes")
(return! void))

; Where the dylib will be downloaded
;
; e.g. `"~/.steel/native/libexample.so"`
(define dylib-path
(string-append
*DYLIB-DIR*
(path-separator)
(platform-dll-prefix!)
dylib-name
"."
(platform-dll-extension!)))

(http.download-file! url dylib-path)
]

[(hash-contains? dylib-dependency '#:git-url)
(download-and-install-library (hash-ref dylib-dependency '#:name)
(hash-ref dylib-dependency '#:git-url)
Expand Down
4 changes: 2 additions & 2 deletions crates/forge/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ version.workspace = true
[dependencies]
# TODO: Don't use the workspace, instead explicitly
# depend on the version with the git dependency
steel-core = { path = "../steel-core", version = "0.7.0", features = ["dylibs", "stacker", "sync", "git"] }
steel-core = { path = "../steel-core", version = "0.7.0", features = ["dylibs", "stacker", "sync", "git", "ureq"] }

[build-dependencies]
steel-core = { path = "../steel-core", version = "0.7.0", features = ["dylibs", "stacker", "sync", "git"] }
steel-core = { path = "../steel-core", version = "0.7.0", features = ["dylibs", "stacker", "sync", "git", "ureq"] }

[features]
default = ["dylib-build"]
Expand Down
2 changes: 2 additions & 0 deletions crates/steel-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ httparse = "1.9.4"
compact_str = { version = "0.8.0", features = ["serde"] }

git2 = { version = "0.20.2", optional = true, features = ["vendored-openssl"] }
ureq = { version = "3.0.12", optional = true }

# For the constant map
arc-swap = "1.7.1"
Expand Down Expand Up @@ -132,6 +133,7 @@ rooted-instructions = []
recycle = []
# git = ["dep:gix", "anyhow"]
git = ["dep:git2", "anyhow"]
ureq = ["dep:ureq"]
disable-arity-checking = ["steel-derive/disable-arity-checking"]
experimental-drop-handler = []
unsandboxed-kernel = []
Expand Down
39 changes: 37 additions & 2 deletions crates/steel-core/src/primitives/http.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::{
gc::{Gc, ShareableMut},
rerrs::ErrorKind,
rvals::{AsRefSteelVal, Custom, IntoSteelVal, SteelByteVector, SteelHashMap, SteelString},
steel_vm::builtin::BuiltInModule,
SteelVal,
SteelErr, SteelVal,
};

use crate::rvals::Result;
Expand Down Expand Up @@ -62,6 +63,39 @@
.map(SteelVal::StringV)
}

/// Download file from a URL
#[steel_derive::function(name = "download-file!")]
fn download_file(url: &SteelString, file: &SteelString) -> Result<SteelVal> {

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (macos-latest, aarch64-apple-darwin)

unused variable: `file`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (macos-latest, aarch64-apple-darwin)

unused variable: `url`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (macos-latest, aarch64-apple-darwin)

unused variable: `file`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (macos-latest, aarch64-apple-darwin)

unused variable: `url`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (macos-latest, aarch64-apple-darwin)

unused variable: `file`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (macos-latest, aarch64-apple-darwin)

unused variable: `url`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (ubuntu-latest, x86_64-unknown-linux-gnu)

unused variable: `file`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (ubuntu-latest, x86_64-unknown-linux-gnu)

unused variable: `url`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (ubuntu-latest, x86_64-unknown-linux-gnu)

unused variable: `file`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (ubuntu-latest, x86_64-unknown-linux-gnu)

unused variable: `url`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (ubuntu-latest, x86_64-unknown-linux-gnu)

unused variable: `file`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (ubuntu-latest, x86_64-unknown-linux-gnu)

unused variable: `url`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (windows-latest, x86_64-pc-windows-msvc)

unused variable: `file`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (windows-latest, x86_64-pc-windows-msvc)

unused variable: `url`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (windows-latest, x86_64-pc-windows-msvc)

unused variable: `file`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (windows-latest, x86_64-pc-windows-msvc)

unused variable: `url`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (windows-latest, x86_64-pc-windows-msvc)

unused variable: `file`

Check warning on line 68 in crates/steel-core/src/primitives/http.rs

View workflow job for this annotation

GitHub Actions / Test Suite (sync) (windows-latest, x86_64-pc-windows-msvc)

unused variable: `url`
#[cfg(not(feature = "ureq"))]
{
Err(SteelErr::new(
ErrorKind::BadSyntax,
"download-file! is not implemented".to_string(),
))
}

#[cfg(feature = "ureq")]
{
use std::{fs, path::PathBuf};

let url = url.as_str();
let file = PathBuf::from(file.as_str());
let contents = ureq::get(url)
.call()
.map_err(|err| {
SteelErr::new(ErrorKind::Io, format!("failed to call http method: {err}"))
})?
.body_mut()
.read_to_vec()
.map_err(|err| SteelErr::new(ErrorKind::Io, format!("http request failed: {err}")))?;

fs::write(file, contents)
.map_err(|err| SteelErr::new(ErrorKind::Io, format!("failed to write: {err}")))?;

Ok(().into())
}
}

#[steel_derive::function(name = "http-request-body-offset")]
pub fn body_offset(value: &SteelVal) -> Result<SteelVal> {
SteelRequest::as_ref(value)
Expand Down Expand Up @@ -189,7 +223,8 @@
.register_native_fn_definition(BODY_OFFSET_DEFINITION)
.register_native_fn_definition(HEADERS_DEFINITION)
.register_native_fn_definition(RESP_HEADERS_DEFINITION)
.register_native_fn_definition(PARSE_HTTP_RESPONSE_DEFINITION);
.register_native_fn_definition(PARSE_HTTP_RESPONSE_DEFINITION)
.register_native_fn_definition(DOWNLOAD_FILE_DEFINITION);

// module
// .register_native_fn_definition(TCP_CONNECT_DEFINITION)
Expand Down
6 changes: 6 additions & 0 deletions crates/steel-core/src/steel_vm/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1916,6 +1916,12 @@ fn meta_module() -> BuiltInModule {
)
.register_value("get-contract-struct", SteelVal::FuncV(get_contract))
.register_fn("current-os!", || std::env::consts::OS)
.register_fn("target-arch!", || std::env::consts::ARCH)
.register_fn("platform-dll-prefix!", || std::env::consts::DLL_PREFIX)
.register_fn("path-separator", || std::path::MAIN_SEPARATOR_STR)
.register_fn("platform-dll-extension!", || {
std::env::consts::DLL_EXTENSION
})
.register_fn(
"#%build-dylib",
|_args: Vec<String>, _env_vars: Vec<(String, String)>| {
Expand Down
Loading
0