Hitting upload limit on crates.io on a sys crate - rust

I'm trying to publish a sys crate for libvmaf. Unfortunately I can not simply dynamically link to libvmaf because it's not distributed anywhere and I need to build it from source and include it in my library. Unfortunately libvmaf is absolutely huge and my .rlib file is ending up at 1.4 megabytes which is over the upload limit for crates.io. Am I boned here?
Here's my build.rs file
use meson_next;
use std::env;
use std::fs::canonicalize;
use std::path::PathBuf;
fn main() {
//env::set_var("RUST_BACKTRACE", "1");
let build_dir = PathBuf::from(env::var("OUT_DIR").unwrap()).join("build");
let lib_dir = build_dir.join("src");
let build_dir_str = build_dir.to_str().unwrap();
let lib_dir_str = lib_dir.to_str().unwrap();
meson_next::build("vmaf/libvmaf", build_dir_str);
println!("cargo:rustc-link-lib=static=vmaf");
println!("cargo:rustc-link-search=native={lib_dir_str}");
// Path to vendor header files
let headers_dir = PathBuf::from("vmaf/libvmaf/include");
let headers_dir_canonical = canonicalize(headers_dir).unwrap();
let include_path = headers_dir_canonical.to_str().unwrap();
// Generate bindings to libvmaf using rust-bindgen
let bindings = bindgen::Builder::default()
.header("vmaf/libvmaf/include/libvmaf/libvmaf.h")
.clang_arg(format!("-I{include_path}"))
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate()
.expect("Unable to generate bindings");
// Write bindings to build directory
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}

In general you should not be including compiled libraries in your package. Include the source code, and have your build script perform the build.
This will usually result in a smaller package, and also means that your package works on any target architecture (that is supported by the library).

Related

How do I execute a Move script on Aptos using the Rust SDK?

I want to execute this Move script, e.g. at sources/top_up.move:
script {
use std::signer;
use aptos_framework::aptos_account;
use aptos_framework::aptos_coin;
use aptos_framework::coin;
fun main(src: &signer, dest: address, desired_balance: u64) {
let src_addr = signer::address_of(src);
let balance = coin::balance<aptos_coin::AptosCoin>(src_addr);
if (balance < desired_balance) {
aptos_account::transfer(src, dest, desired_balance - balance);
};
}
}
This is calling functions on the aptos_coin.move module, which is deployed on chain. What it does isn't so important for this question, but in short, it checks that the balance of the destination account is less than desired_balance, and if so, tops it up to desired_balance.
I can execute this Move script via the CLI easily like this:
aptos move compile
aptos move run-script --compiled-script-path build/MyModule/bytecode_scripts/main.mv
Or even just this:
aptos move run-script --script-path sources/top_up.move
What I want to know is whether I can do this using the Rust SDK?
First, you need to compile the script, as you did above. Imagine you have a project layout like this:
src/
main.rs
move/
Move.toml
sources/
top_up.mv
You would want to go in to move/ and run aptos move compile, like you said above. From there, you can depend on the compiled script in your code (see below).
With that complete, here is a minimal code example demonstrating how to execute a Move script using the Rust SDK.
Cargo.toml:
[package]
name = "my-example"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1"
aptos-sdk = { git = "https://github.com/aptos-labs/aptos-core", branch = "mainnet" }
src/main.rs:
use aptos_sdk::crypto::ed25519::Ed25519PublicKey;
use aptos_sdk::types::transaction::authenticator::AuthenticationKey;
use aptos_sdk::{
rest_client::Client,
transaction_builder::TransactionFactory,
types::{
account_address::AccountAddress,
chain_id::ChainId,
transaction::{Script, SignedTransaction, TransactionArgument},
LocalAccount,
},
};
static SCRIPT: &[u8] =
include_bytes!("../../move/build/MyModule/bytecode_scripts/main.mv");
fn main() -> anyhow::Result<()> {
// Prior to the follow code we assume you've already acquired the necessary
// information such as chain_id, the private key of the account submitting
// the transaction, arguments for the Move script, etc.
// Build a transaction factory.
let txn_factory = TransactionFactory::new(chain_id);
// Build a local representation of an account.
let account = LocalAccount::new(
AuthenticationKey::ed25519(&Ed25519PublicKey::from(&private_key)).derived_address()
private_key,
0,
);
// Build an API client.
let client = Client::new("https://fullnode.mainnet.aptoslabs.com");
// Create a builder where the payload is the script.
let txn_builder = transaction_factory.script(Script::new(
SCRIPT.to_vec(),
// type args
vec![],
// args
vec![
TransactionArgument::Address(dest_address),
TransactionArgument::U64(desired_balance),
],
)));
// Build the transaction request and sign it.
let signed_txn = account.sign_with_transaction_builder(
txn_builder
);
// Submit the transaction.
client.submit_and_wait_bcs(&signed_transaction).await?;
}

What is the best way to check if an executable exists for `std::process::Command`?

I want to create a std::process::Command and check whether an executable actually exists at that location before actually spawning the Command later. What would be the pragmatic way to do this?
I have this code:
let c = std::process::Command::new("my_exe");
// something here
c.spawn().unwrap();
I want to be able to validate the my_exe path when creating the Command and then spawn way later.
check whether an executable actually exists at that location before actually spawning the Command.
Don't as that's a time-of-check to time-of-use race condition. Instead, check the error value from executing the Command: Check if a command is in PATH/executable as process.
If you want to check if a file is present in the working directory, you can use Path::exists, as described in How to check whether a path exists?.
Also, Command::spawn() takes a mutable reference to self so c needs to be mutable.
use std::path::Path;
use std::process::Command;
if Path::new("PATH_TO_EXECUTABLE").exists() {
let mut c = Command::new("PATH_TO_EXECUTABLE");
// do something
c.spawn().unwrap();
}
Use the is_executable crate:
use is_executable::IsExecutable;
use std::fs;
let paths = fs::read_dir("./").unwrap();
for path in paths {
let file_path = path.unwrap().path();
if file_path.is_executable() {
println!("File: {:?} is executable!", file_path);
} else {
println!("File: {:?} is _not_ executable!", file_path);
}
}

Rust lightningcss minify

Trying to figure out how to use minify from lightningcss. Here's my code
let fs = FileProvider::new();
let mut bundler = Bundler::new(&fs, None, ParserOptions::default());
let stylesheet = bundler.bundle(Path::new("./assets/css/global.css")).unwrap();
stylesheet.minify(MinifyOptions::default());
println!("{}", stylesheet.to_css(PrinterOptions::default()).unwrap().code);
If I try to print the unwrapped version of the minified output that is empty.
taken more from here https://docs.rs/lightningcss/1.0.0-alpha.34/lightningcss/stylesheet/struct.StyleSheet.html
And the question: how do I use the minify output?

oxipng throwing RuntimeError: unreachable when called

I'm trying to create a small WASM project for image compression.
After some search in github, I noticed that oxipng 2.2.2 has a target for wasm32-unknown-unknown, hence why I'm using that.
I'm using wasm-pack for creating the wasm file + JS bindings with target -t web
This is the code:
extern crate oxipng;
mod utils;
use std::error::Error;
use wasm_bindgen::prelude::*;
use oxipng::*;
#[wasm_bindgen]
extern "C" {
// Use `js_namespace` here to bind `console.log(..)` instead of just
// `log(..)`
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
// Next let's define a macro that's like `println!`, only it works for
// `console.log`. Note that `println!` doesn't actually work on the wasm target
// because the standard library currently just eats all output. To get
// `println!`-like behavior in your app you'll likely want a macro like this.
#[macro_export]
macro_rules! console_log {
// Note that this is using the `log` function imported above during
// `bare_bones`
($($t:tt)*) => (crate::log(&format_args!($($t)*).to_string()))
}
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
pub fn compress(data: &[u8]) -> Vec<u8> {
console_log!("{}", data.len());
let opts = Options::from_preset(6);
console_log!("after options");
let res = match optimize_from_memory(data, &&opts) {
Ok(res) => Ok(res),
Err(err) => Err(err),
};
match &res {
Ok(_) => console_log!("Optimized"),
Err(err) => console_log!("Error: {}", err),
}
return res.unwrap();
}
I don't ever get an error message, the last log I have is "after options".
In a nutshell, I'm using a Flutter web application that gets a PNG file, converts it into a Uint8List, and I send it as an integer List to the JS bindings.
When called, the following error happens:
RuntimeError: unreachable
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[1019]:0x5c6be
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[414]:0x4cd37
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[619]:0x54c96
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[915]:0x5b4ba
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[986]:0x5c139
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[645]:0x55885
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[569]:0x5324b
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[594]:0x53ff1
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[2]:0x554f
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[84]:0x2cbf2
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[73]:0x2a501
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[563]:0x52eaa
at compress (http://localhost:3000/pkg/rust_png_module.js:49:14)
at compressImage (http://localhost:3000/packages/rust_wasm/ui/screens/home/home_page.dart.lib.js:568:72)
at compressImage.next (<anonymous>)
at http://localhost:3000/dart_sdk.js:38640:33
at _RootZone.runUnary (http://localhost:3000/dart_sdk.js:38511:59)
at _FutureListener.thenAwait.handleValue (http://localhost:3000/dart_sdk.js:33713:29)
at handleValueCallback (http://localhost:3000/dart_sdk.js:34265:49)
at Function._propagateToListeners (http://localhost:3000/dart_sdk.js:34303:17)
at _Future.new.[_completeWithValue] (http://localhost:3000/dart_sdk.js:34151:23)
at async._AsyncCallbackEntry.new.callback (http://localhost:3000/dart_sdk.js:34172:35)
at Object._microtaskLoop (http://localhost:3000/dart_sdk.js:38778:13)
at _startMicrotaskLoop (http://localhost:3000/dart_sdk.js:38784:13)
at http://localhost:3000/dart_sdk.js:34519:9
Since this version is old, I don't know if I should revert back to an older version of Rust
$ rustup --version
rustup 1.24.3 (ce5817a94 2021-05-31)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.55.0 (c8dfcfe04 2021-09-06)`
Thank you in advance
The problem is you're using a very old version of oxipng (v2.2.2) that didn't support wasm yet. I believe wasm support was added in v2.3.0 (link to issue that was fixed). Anyways, you should be able to use the latest version just fine with wasm, just make sure you disable the default features when adding the crate to your Cargo.toml:
[dependencies]
oxipng = { version = "5", default-features = false }

Serving static files with actix-web 2.0

I'm struggling with actix-web 2.0 framework of rust. I want my rust server to serve the my index.html file but most of the help available is of older versions and hence a lot has changed in newer version. I tried following code but it's not working for actix-web 2.0. Please suggest some working solution in actix-web 2.0.
use actix_files::NamedFile;
use actix_web::{HttpRequest, Result};
async fn index(req: HttpRequest) -> Result<NamedFile> {
Ok(NamedFile::open(path_to_file)?)
}
By trying the code given in the answer I could serve a single html file but it is unable to load the linked JavaScript file. I have tried the following approach suggested in https://actix.rs/docs/static-files/ to serve the directory.
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
dotenv::dotenv().ok();
std::env::set_var("RUST_LOG", "actix_web=debug");
let database_url = std::env::var("DATABASE_URL").expect("set DATABASE_URL");
// create db connection pool
let manager = ConnectionManager::<PgConnection>::new(database_url);
let pool: Pool = r2d2::Pool::builder()
.build(manager)
.expect("Failed to create pool.");
//Serving the Registration and sign-in page
async fn index(_req: HttpRequest) -> Result<NamedFile> {
let path: PathBuf = "./static/index.html".parse().unwrap();
Ok(NamedFile::open(path)?)
}
// Start http server
HttpServer::new(move || {
App::new()
.data(pool.clone())
.service(fs::Files::new("/static", ".").show_files_listing())
.route("/", web::get().to(index))
.route("/users", web::get().to(handler::get_users))
.route("/users/{id}", web::get().to(handler::get_user_by_id))
.route("/users", web::post().to(handler::add_user))
.route("/users/{id}", web::delete().to(handler::delete_user))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Above is my main method. In browser console I'm still getting the error that unable to load the Registration.js resource. Following is my folder structure:
-migrations
-src
-main.rs
-handler.rs
-errors.rs
-models.rs
-schema.rs
-static
-index.html
-Registration.js
-target
Cargo.toml
.env
Cargo.lock
diesel.toml
I have already built the backend with DB integration and it is working fine as checked by curl commands and now I'm trying to build front end and as first step trying to serve static files.
I am not sure what problem you're facing since the description is not detailed, however, I ran the default example and it is working.
use actix_files::NamedFile;
use actix_web::{HttpRequest, Result};
use std::path::PathBuf;
/// https://actix.rs/docs/static-files/
async fn index(_req: HttpRequest) -> Result<NamedFile> {
let path: PathBuf = "./files/index.html".parse().unwrap();
Ok(NamedFile::open(path)?)
}
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
use actix_web::{web, App, HttpServer};
HttpServer::new(|| App::new().route("/", web::get().to(index)))
.bind("127.0.0.1:8088")?
.run()
.await
}
project structure
- files/index.html
- src/index.rs
- cargo.toml
dependencies
[dependencies]
actix-web = "2.0.0"
actix-files = "0.2.2"
actix-rt = "1.1.1"
If you want to really embed resources into executable you can use https://crates.io/crates/actix-web-static-files.
It uses build.rs to prepare resources and later you can just have single executable without dependencies.
As extra it support npm based builds out of the box.
Basically I am an author of this crate. There are versions both for 2.x and 3.x versions of actix-web.
Please see the below code that it works for the whole subdirectories:
main.rs
use actix_files as fs;
use actix_web::{App, HttpServer};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new().service(
fs::Files::new("/", "./public")
.show_files_listing()
.index_file("index.html")
.use_last_modified(true),
)
})
.bind("0.0.0.0:8000")?
.run()
.await
}
Cargo.toml
[package]
name = "actixminimal"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "4"
actix-files = "0.6.2"
It perform file serving very fast ever I'd tried.
In this case, you can create a "public" or you can use your own "static" folder (then change your code related to the folder name) or you can export the static files from your web framework. I use GatsbyJS and I use deploy parameter to "public" folder.
I share it on my github.
https://github.com/openmymai/actixminimal.git

Resources