Merge pull request 'develop' (#8) from develop into master

Reviewed-on: #8
This commit is contained in:
David 2024-05-18 20:53:24 +02:00
commit 93a4b7871a
19 changed files with 1633 additions and 424 deletions

6
.cargo/config.toml Normal file
View File

@ -0,0 +1,6 @@
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
[target.x86_64-apple-darwin]
linker = "x86_64-apple-darwin16-clang"
ar = "x86_64-apple-darwin16-ar"

7
.gitignore vendored
View File

@ -2,12 +2,11 @@
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# Intellij
.idea/
/*.iml
/.project
/.settings/

112
BUILD.md Normal file
View File

@ -0,0 +1,112 @@
# Build Instructions
Instructions for building this repository on Linux.
## Table of Contents
- [Build Instructions](#build-instructions)
- [Table of Contents](#table-of-contents)
- [Contributing to the Repository](#contributing-to-the-repository)
- [Repository Content](#repository-content)
- [Building on Linux](#building-on-linux)
- [Linux Development Environment Requirements](#linux-development-environment-requirements)
- [Required Package List](#required-package-list)
- [Install and Prepare Required Rust Version](#install-and-prepare-required-rust-version)
- [Required macOS SDK](#required-macos-sdk)
- [Build and Use macOS SDK from Xcode](#build-and-use-macos-sdk-from-xcode)
- [Build the Project](#build-the-project)
## Contributing to the Repository
If you intend to contribute, the preferred workflow is for you to develop your contribution in a fork of this repository in your GitHub account and then submit a pull request.
## Repository Content
This repository contains the source code necessary to build warp-packer for different platforms and architectures.
## Building on Linux
### Linux Development Environment Requirements
This repository has been built and tested on Debian 12.5 (Bookworm) on an AMD64 architecture.
#### Required Package List
```bash
apt install curl maven clang cmake libssl-dev zlib1g-dev liblzma-dev libbz2-dev gcc-aarch64-linux-gnu gcc-mingw-w64-x86-64-win32
```
#### Install and Prepare Required Rust Version
This repository has been built and tested with Rust version 1.78.
To install the newest version, run the following command:
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
If a newer version doesn't work, a specific version can be installed with the following command:
```bash
$ curl --proto '=https' --tls1.2 -sSf https://sh.rustup.rs/ | sh -s --default-toolchain=1.78.0
```
For more information see this [GitHub Issue](https://github.com/rust-lang/rustup/issues/2882).
After installing, run the following commands to get the necessary targets:
```bash
rustup target add x86_64-apple-darwin
rustup target add aarch64-unknown-linux-gnu
rustup target add x86_64-pc-windows-gnu
```
#### Required macOS SDK
To build warp-packer for the target x86_64-apple-darwin, a macOS SDK is needed. The repository has been built and tested with MacOSX10.12 SDK.
There are several GitHub repositories available that contain different SDK versions, but they all seem to miss the header files. So it is recommended to download it from Apple's website.
The macOS SDK is integrated into Xcode, and this repository has been built and tested with Xcode version 8.3.3.
##### Build and Use macOS SDK from Xcode
To build and use the macOS SDK from Xcode, [osxcross](https://github.com/tpoechtrager/osxcross) will be used.
Download osxcross:
```bash
git clone https://github.com/tpoechtrager/osxcross.git
```
Extract macOS SDK from Xcode (see [here](https://github.com/tpoechtrager/osxcross?tab=readme-ov-file#packing-the-sdk-on-linux---method-1-xcode--80)):
```bash
<path/to>/osxcross/tools/gen_sdk_package_pbzx.sh <path/to>/Xcode_8.3.3.xip
```
Hint: This method may require up to 45 GB of free disk space. An SSD is recommended for this method.
Copy or move the SDK into the `<path/to>/osxcross/tarballs/` directory.
Run:
```bash
UNATTENDED=yes OSX_VERSION_MIN=10.12 ./build.sh
```
to create the macOS cross toolchain.
Add the target/bin folder to your PATH environment variable:
```bash
PATH="<path/to>/osxcross/target/bin:$PATH"
```
#### Build the Project
Clone the project and within the project directory, run:
```bash
make
```
to start the build.
The compiled warp-packer files are in the folder:
```bash
<path/to>/warp/target/<target>/release/warp-packer
```
e.g.
```bash
warp/target/aarch64-unknown-linux-gnu/release/warp-packer
```

28
CHANGELOG.md Normal file
View File

@ -0,0 +1,28 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [1.0.0] - 2024-05-18
### Changed
- Changed the default invocation to `warp-packer pack <argument1> <argument2> ...`.
For more details, see the [README](./README.md#changes-in-v100).
### Added
- Support for native execution on aarch64-linux platforms, e.g., Raspberry Pi 4.
- New options for `warp-packer`.
- `BUILD.md` with instructions on how to compile warp-packer.
- `INSTALL.md` with instructions on how to run the application on Linux, macOS, and Windows systems.
## [0.1.0 - 0.3.0] - 2018-10-30
### Changed
- For changes see origin repository: https://github.com/dgiagio/warp/releases
[unreleased]: https://git.phoenix.ipv64.de/public/warp/compare/master...HEAD
[1.0.0]: https://git.phoenix.ipv64.de/public/warp/compare/0.3.0...1.0.0
[0.1.0 - 0.3.0]: https://github.com/dgiagio/warp/releases

859
Cargo.lock generated Normal file
View File

@ -0,0 +1,859 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "anstream"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
[[package]]
name = "anstyle-parse"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
dependencies = [
"anstyle",
"windows-sys 0.52.0",
]
[[package]]
name = "anyhow"
version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27a4bd113ab6da4cd0f521068a6e2ee1065eab54107266a11835d02c8ec86a37"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "colorchoice"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]]
name = "colored"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8"
dependencies = [
"lazy_static",
"windows-sys 0.48.0",
]
[[package]]
name = "crc32fast"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
]
[[package]]
name = "dirs"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "either"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
[[package]]
name = "errno"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "filetime"
version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"windows-sys 0.52.0",
]
[[package]]
name = "flate2"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "is_terminal_polyfill"
version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libredox"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.5.0",
"libc",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "memmem"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15"
[[package]]
name = "miniz_oxide"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
dependencies = [
"adler",
]
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "num_threads"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
dependencies = [
"libc",
]
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "proc-macro2"
version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
dependencies = [
"fuchsia-cprng",
"libc",
"rand_core 0.3.1",
"rdrand",
"winapi",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rayon"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_users"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891"
dependencies = [
"getrandom",
"libredox",
"thiserror",
]
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "remove_dir_all"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "882f368737489ea543bc5c340e6f3d34a28c39980bd9a979e47322b26f60ac40"
dependencies = [
"libc",
"log",
"num_cpus",
"rayon",
"winapi",
]
[[package]]
name = "rustix"
version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [
"bitflags 2.5.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
]
[[package]]
name = "serde"
version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "simple_logger"
version = "4.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e7e46c8c90251d47d08b28b8a419ffb4aede0f87c2eea95e17d1d5bacbf3ef1"
dependencies = [
"colored",
"log",
"time",
"windows-sys 0.48.0",
]
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tar"
version = "0.4.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb"
dependencies = [
"filetime",
"libc",
"xattr",
]
[[package]]
name = "tempdir"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
dependencies = [
"rand",
"remove_dir_all 0.5.3",
]
[[package]]
name = "thiserror"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "time"
version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
"deranged",
"itoa",
"libc",
"num-conv",
"num_threads",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "uuid"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
dependencies = [
"getrandom",
]
[[package]]
name = "warp-args"
version = "0.1.0"
dependencies = [
"bincode",
"serde",
]
[[package]]
name = "warp-packer"
version = "0.4.0"
dependencies = [
"bincode",
"clap",
"flate2",
"lazy_static",
"tar",
"tempdir",
"uuid",
"warp-args",
]
[[package]]
name = "warp-runner"
version = "0.4.0"
dependencies = [
"anyhow",
"bincode",
"dirs",
"flate2",
"log",
"memmem",
"remove_dir_all 0.7.0",
"simple_logger",
"tar",
"warp-args",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.5",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
"windows_aarch64_gnullvm 0.52.5",
"windows_aarch64_msvc 0.52.5",
"windows_i686_gnu 0.52.5",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.5",
"windows_x86_64_gnu 0.52.5",
"windows_x86_64_gnullvm 0.52.5",
"windows_x86_64_msvc 0.52.5",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]]
name = "xattr"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f"
dependencies = [
"libc",
"linux-raw-sys",
"rustix",
]

View File

@ -1,2 +1,3 @@
[workspace]
members = ["warp-runner", "warp-packer"]
members = ["warp-args", "warp-runner", "warp-packer"]
resolver = "2"

83
INSTALL.md Normal file
View File

@ -0,0 +1,83 @@
# Installation Instructions
Instructions for installing the warp-packer executable on Linux, Mac, and Windows.
## Table of Contents
- [Installation Instructions](#installation-instructions)
- [Table of Contents](#table-of-contents)
- [Linux](#linux)
- [Mac](#mac)
- [Windows](#windows)
## Linux
1. **Copy the warp-packer executable to a directory in your PATH:**
For example, you can copy it to `/usr/local/bin`:
```sh
sudo cp /path/to/warp-packer /usr/local/bin/
```
2. **Ensure the warp-packer executable has the correct permissions:**
Make the file executable:
```sh
sudo chmod +x /usr/local/bin/warp-packer
```
3. **Verify the installation:**
Check that the executable is in your PATH and works correctly:
```sh
warp-packer --version
```
## Mac
1. **Copy the warp-packer executable to a directory in your PATH:**
For example, you can copy it to `/usr/local/bin`:
```sh
sudo cp /path/to/warp-packer /usr/local/bin/
```
2. **Ensure the warp-packer executable has the correct permissions:**
Make the file executable:
```sh
sudo chmod +x /usr/local/bin/warp-packer
```
3. **Verify the installation:**
Check that the executable is in your PATH and works correctly:
```sh
warp-packer --version
```
## Windows
1. **Copy the warp-packer executable to a directory in your PATH:**
For example, you can copy it to `C:\Program Files\warp-packer`:
```powershell
Copy-Item -Path "C:\path\to\warp-packer.exe" -Destination "C:\Program Files\warp-packer\"
```
2. **Add the directory to your PATH environment variable:**
- Open the Start Search, type in "env", and select "Edit the system environment variables".
- In the System Properties window, click on the "Environment Variables..." button.
- In the Environment Variables window, under "System variables", find the `Path` variable, select it, and click "Edit...".
- In the Edit Environment Variable window, click "New" and add the path to the directory where you copied the warp-packer executable (`C:\Program Files\warp-packer\`).
- Click "OK" to close all windows.
3. **Verify the installation:**
Open a new Command Prompt and check that the executable is in your PATH and works correctly:
```cmd
warp-packer --version
```
By following these steps, you will have the warp-packer executable installed and ready to use on Linux, Mac, and Windows.

View File

@ -5,8 +5,11 @@ build:
cargo build -p warp-runner --release --target x86_64-unknown-linux-gnu
strip target/x86_64-unknown-linux-gnu/release/warp-runner
CC=x86_64-apple-darwin15-clang cargo build -p warp-runner --release --target x86_64-apple-darwin
x86_64-apple-darwin15-strip target/x86_64-apple-darwin/release/warp-runner
cargo build -p warp-runner --release --target aarch64-unknown-linux-gnu
aarch64-linux-gnu-strip target/aarch64-unknown-linux-gnu/release/warp-runner
cargo build -p warp-runner --release --target x86_64-apple-darwin
x86_64-apple-darwin16-strip target/x86_64-apple-darwin/release/warp-runner
cargo build -p warp-runner --release --target x86_64-pc-windows-gnu
strip target/x86_64-pc-windows-gnu/release/warp-runner.exe
@ -14,8 +17,11 @@ build:
cargo build -p warp-packer --release --target x86_64-unknown-linux-gnu
strip target/x86_64-unknown-linux-gnu/release/warp-packer
CC=x86_64-apple-darwin15-clang cargo build -p warp-packer --release --target x86_64-apple-darwin
x86_64-apple-darwin15-strip target/x86_64-apple-darwin/release/warp-packer
cargo build -p warp-packer --release --target aarch64-unknown-linux-gnu
aarch64-linux-gnu-strip target/aarch64-unknown-linux-gnu/release/warp-packer
cargo build -p warp-packer --release --target x86_64-apple-darwin
x86_64-apple-darwin16-strip target/x86_64-apple-darwin/release/warp-packer
cargo build -p warp-packer --release --target x86_64-pc-windows-gnu
strip target/x86_64-pc-windows-gnu/release/warp-packer.exe

View File

@ -17,6 +17,7 @@ Warp is written in Rust and is supported on Linux, Windows and macOS.
+ [Performance](#performance)
+ [Packages cache location](#packages-cache-location)
+ [Runners cache location](#runners-cache-location)
* [Changes in v1.0.0](#changes-in-v100)
* [Authors](#authors)
* [License](#license)
@ -85,7 +86,7 @@ dgiagio@X1:~/Devel$ chmod +x warp-packer
**Create your self-contained application**
```sh
dgiagio@X1:~/Devel$ ./warp-packer --arch linux-x64 --input_dir myapp --exec launch --output myapp.bin
dgiagio@X1:~/Devel$ ./warp-packer pack --arch linux-x64 --input-dir myapp --exec launch --output myapp.bin
dgiagio@X1:~/Devel$ chmod +x myapp.bin
```
@ -170,7 +171,7 @@ Diegos-iMac:Devel dgiagio$ chmod +x warp-packer
**Create your self-contained application**
```sh
Diegos-iMac:Devel dgiagio$ ./warp-packer --arch macos-x64 --input_dir myapp --exec launch --output myapp.bin
Diegos-iMac:Devel dgiagio$ ./warp-packer pack --arch macos-x64 --input-dir myapp --exec launch --output myapp.bin
Diegos-iMac:Devel dgiagio$ chmod +x myapp.bin
```
@ -250,7 +251,7 @@ PS C:\Users\Diego\Devel> [Net.ServicePointManager]::SecurityProtocol = "tls12, t
**Create your self-contained application**
```powershell
PS C:\Users\Diego\Devel> .\warp-packer --arch windows-x64 --input_dir .\myapp\ --exec launch.cmd --output myapp.exe
PS C:\Users\Diego\Devel> .\warp-packer --arch windows-x64 --input-dir .\myapp\ --exec launch.cmd --output myapp.exe
```
**Run your self-contained application**
@ -299,7 +300,7 @@ dgiagio@X1:~/Devel/myapp$ chmod +x warp-packer
**Create your self-contained application**
```sh
dgiagio@X1:~/Devel/myapp$ ./warp-packer --arch linux-x64 --input_dir bin/Release/netcoreapp2.1/linux-x64/publish --exec myapp --output myapp
dgiagio@X1:~/Devel/myapp$ ./warp-packer pack --arch linux-x64 --input-dir bin/Release/netcoreapp2.1/linux-x64/publish --exec myapp --output myapp
dgiagio@X1:~/Devel/myapp$ chmod +x myapp
```
@ -351,7 +352,7 @@ Diegos-iMac:myapp dgiagio$ chmod +x warp-packer
**Create your self-contained application**
```sh
Diegos-iMac:myapp dgiagio$ ./warp-packer --arch macos-x64 --input_dir bin/Release/netcoreapp2.1/osx-x64/publish --exec myapp --output myapp
Diegos-iMac:myapp dgiagio$ ./warp-packer pack --arch macos-x64 --input-dir bin/Release/netcoreapp2.1/osx-x64/publish --exec myapp --output myapp
Diegos-iMac:myapp dgiagio$ chmod +x myapp
```
@ -402,7 +403,7 @@ PS C:\Users\Diego\Devel\myapp> [Net.ServicePointManager]::SecurityProtocol = "tl
**Create your self-contained application**
```powershell
PS C:\Users\Diego\Devel\myapp> .\warp-packer --arch windows-x64 --input_dir bin/Release/netcoreapp2.1/win10-x64/publish --exec myapp.exe --output myapp.exe
PS C:\Users\Diego\Devel\myapp> .\warp-packer --arch windows-x64 --input-dir bin/Release/netcoreapp2.1/win10-x64/publish --exec myapp.exe --output myapp.exe
```
**Run your self-contained application**
@ -456,18 +457,18 @@ Hello, world.
**Download a JRE**
There are prebuilt JREs over on [AdoptOpenJDK](https://adoptopenjdk.net).
There are prebuilt JREs over on [AdoptOpenJDK](https://adoptium.net).
Here we use JRE 8:
```
wget -N https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u202-b08/OpenJDK8U-jre_x64_linux_hotspot_8u202b08.tar.gz
wget -N https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u412-b08/OpenJDK8U-jre_x64_linux_hotspot_8u412b08.tar.gz
```
Unpack it:
```
tar -xvf OpenJDK8U-jre_x64_linux_hotspot_8u202b08.tar.gz
tar -xvf OpenJDK8U-jre_x64_linux_hotspot_8u412b08.tar.gz
```
**Create a bundle**
@ -476,7 +477,7 @@ We need to create a folder containing: our compiled code, the JRE and a launch s
```
mkdir bundle
cp -r ./jdk8u202-b08-jre ./bundle/jre
cp -r ./jdk8u412-b08-jre ./bundle/jre
cp app.jar ./bundle/app.jar
touch bundle/run.sh
chmod +x ./bundle/run.sh
@ -513,7 +514,7 @@ $ chmod +x ./warp-packer
**Create your self-contained application**
```bash
$ ./warp-packer --arch linux-x64 --input_dir bundle --exec run.sh --output app.bin
$ ./warp-packer pack --arch linux-x64 --input-dir bundle --exec run.sh --output app.bin
$ chmod +x app.bin
```
@ -542,7 +543,7 @@ The performance characteristics of the generated self-contained application is r
### Packages cache location
- Linux: `$HOME/.local/share/warp/packages`
- macOS: `$HOME/Library/Application Support/warp/packges`
- macOS: `$HOME/Library/Application Support/warp/packages`
- Windows: `%LOCALAPPDATA%\warp\packages`
### Runners cache location
@ -550,6 +551,39 @@ The performance characteristics of the generated self-contained application is r
- macOS: `$HOME/Library/Application Support/warp/runners`
- Windows: `%LOCALAPPDATA%\warp\runners`
## Changes in v1.0.0
Version 1.0.0 introduces several breaking changes and new features, implemented via a cherry-pick from the [forked project](https://github.com/Reisz/warp). You can see the detailed differences in the [comparison](https://github.com/dgiagio/warp/compare/master...Reisz:warp:master).
### Breaking Changes
Until version 0.3.0, the default invocation of the program was:
```sh
warp-packer <argument1> <argument2> ...
```
From version 1.0.0 onwards, the default invocation has changed to:
```sh
warp-packer pack <argument1> <argument2> ...
```
### New Options in 1.0.0
Version 1.0.0 introduces the following new options:
```sh
-i, --input-dir <INPUT_DIR> Sets the input directory containing the application and dependencies
-q, --unique-id Generate a unique ID for each package build
-p, --prefix <PREFIX> Use a prefix instead of the single-file executable name
-n, --no-clean When using unique-id, do not clean obsolete versions with the same prefix from the cache
```
### Detailed Explanation of New Options
- **`-i, --input-dir <INPUT_DIR>`**: In previous versions, this option was specified as `--input_dir`. It sets the directory containing the application and its dependencies.
- **`-q, --unique-id`**: Instead of using a static folder name for the extracted application, a UUID will be used as the folder name. This is useful for shipping or testing different versions of your application without overwriting the old one. For example, `<cache_location>/warp/packages/<jar_name>/<unique_uuid>`.
- **`-p, --prefix <PREFIX>`**: This option allows you to use a specified prefix as the folder name in the cache location where the application will be extracted. For example, `<cache_location>/warp/packages/<PREFIX>/`.
- **`-n, --no-clean`**: By default, the folder with the autogenerated UUID and its content will be replaced with the new extracted files. If this option is set, the executable application will not delete the old extracted files in the cache location.
## Authors
- Diego Giagio `<diego@giagio.com>`

10
warp-args/Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "warp-args"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bincode = "1.3"
serde = { version = "1.0", features = ["derive"] }

22
warp-args/src/lib.rs Normal file
View File

@ -0,0 +1,22 @@
use std::path::PathBuf;
use bincode::Options;
use serde::{Deserialize, Serialize};
pub const WARP_ARGS_MAGIC: &[u8] = b"DR1PWsJsM6KxNbng9Y38";
#[derive(Serialize, Deserialize, Debug)]
pub struct Args {
pub target_file_name: PathBuf,
pub prefix: Option<PathBuf>,
pub uid: Option<String>,
pub clean: bool,
}
pub fn bincode_options() -> impl bincode::Options {
bincode::DefaultOptions::new()
.with_fixint_encoding()
.allow_trailing_bytes()
// Make sure bincode does not trust all size prefixes while scanning the binary
.with_limit(1_000_000)
}

View File

@ -1,13 +1,15 @@
[package]
name = "warp-packer"
version = "0.3.0"
version = "0.4.0"
authors = ["Diego Giagio <diego@giagio.com>"]
edition = "2021"
[dependencies]
clap = "2.32.0"
dirs = "1.0.4"
reqwest = "0.9.2"
tempdir = "0.3.7"
bincode = "1.3"
clap = { version = "4.0", features = ["derive"] }
flate2 = "1.0"
tar = "0.4"
lazy_static = "1.1.0"
tar = "0.4"
tempdir = "0.3.7"
uuid = { version = "1.2", features = ["v4"] }
warp-args = { path = "../warp-args" }

47
warp-packer/src/cli.rs Normal file
View File

@ -0,0 +1,47 @@
use std::path::PathBuf;
use clap::{Args, Parser, Subcommand};
#[derive(Parser, Debug)]
#[command(author, version, about)]
pub struct Cli {
#[command(subcommand)]
pub command: Command,
}
#[derive(Subcommand, Debug)]
pub enum Command {
Pack(PackArgs),
List,
}
#[derive(Args, Debug)]
pub struct PackArgs {
/// Sets the architecture. Use list subcommand to get possible options.
#[arg(short, long)]
pub arch: String,
/// Sets the input directory containing the application and dependencies
#[arg(short, long)]
pub input_dir: PathBuf,
/// Sets the application executable file name
#[arg(short, long)]
pub exec: PathBuf,
/// Sets the resulting self-contained application file name
#[arg(short, long)]
pub output: PathBuf,
/// Generate unique id for each package build
#[arg(short = 'q', long, default_value_t = false)]
pub unique_id: bool,
/// Prefix to use instead of single-file executable name
#[arg(short, long)]
pub prefix: Option<PathBuf>,
/// When using unique-id, do not look for and clean obsolete versions with the same prefix from cache
#[arg(short = 'n', long = "no-clean", action = clap::ArgAction::SetFalse)]
pub clean: bool,
}

View File

@ -1,42 +1,41 @@
extern crate clap;
extern crate dirs;
extern crate flate2;
#[macro_use]
extern crate lazy_static;
extern crate reqwest;
extern crate tar;
extern crate tempdir;
mod cli;
use clap::{App, AppSettings, Arg};
use flate2::Compression;
use bincode::Options;
use clap::Parser;
use flate2::write::GzEncoder;
use std::collections::HashMap;
use flate2::Compression;
use lazy_static::lazy_static;
use std::error::Error;
use std::fs;
use std::fs::File;
use std::io;
use std::io::copy;
use std::io::Write;
use std::io::{self, Write};
use std::path::Path;
use std::process;
use tempdir::TempDir;
use std::{collections::HashMap, io::BufWriter};
use uuid::Uuid;
use warp_args::{bincode_options, Args, WARP_ARGS_MAGIC};
const APP_NAME: &str = env!("CARGO_PKG_NAME");
const AUTHOR: &str = env!("CARGO_PKG_AUTHORS");
const VERSION: &str = env!("CARGO_PKG_VERSION");
const RUNNER_MAGIC: &[u8] = b"tVQhhsFFlGGD3oWV4lEPST8I8FEPP54IM0q7daes4E1y3p2U2wlJRYmWmjPYfkhZ0PlT14Ls0j8fdDkoj33f2BlRJavLj3mWGibJsGt5uLAtrCDtvxikZ8UX2mQDCrgE\0";
const RUNNER_LINUX_X64: &[u8] = include_bytes!("../../target/x86_64-unknown-linux-gnu/release/warp-runner");
const RUNNER_MACOS_X64: &[u8] = include_bytes!("../../target/x86_64-apple-darwin/release/warp-runner");
const RUNNER_WINDOWS_X64: &[u8] = include_bytes!("../../target/x86_64-pc-windows-gnu/release/warp-runner.exe");
use crate::cli::Command;
lazy_static! {
static ref RUNNER_BY_ARCH: HashMap<&'static str, &'static [u8]> = {
let mut m = HashMap::new();
m.insert("linux-x64", RUNNER_LINUX_X64);
m.insert("macos-x64", RUNNER_MACOS_X64);
m.insert("windows-x64", RUNNER_WINDOWS_X64);
m.insert(
"linux-x64",
include_bytes!("../../target/x86_64-unknown-linux-gnu/release/warp-runner").as_slice(),
);
m.insert(
"linux-aarch64",
include_bytes!("../../target/aarch64-unknown-linux-gnu/release/warp-runner").as_slice(),
);
m.insert(
"macos-x64",
include_bytes!("../../target/x86_64-apple-darwin/release/warp-runner").as_slice(),
);
m.insert(
"windows-x64",
include_bytes!("../../target/x86_64-pc-windows-gnu/release/warp-runner.exe").as_slice(),
);
m
};
}
@ -50,43 +49,16 @@ macro_rules! bail {
})
}
fn patch_runner(arch: &str, exec_name: &str) -> io::Result<Vec<u8>> {
// Read runner executable in memory
let runner_contents = RUNNER_BY_ARCH.get(arch).unwrap();
let mut buf = runner_contents.to_vec();
// Set the correct target executable name into the local magic buffer
let magic_len = RUNNER_MAGIC.len();
let mut new_magic = vec![0; magic_len];
new_magic[..exec_name.len()].clone_from_slice(exec_name.as_bytes());
// Find the magic buffer offset inside the runner executable
let mut offs_opt = None;
for (i, chunk) in buf.windows(magic_len).enumerate() {
if chunk == RUNNER_MAGIC {
offs_opt = Some(i);
break;
}
}
if offs_opt.is_none() {
return Err(io::Error::new(io::ErrorKind::Other, "no magic found inside runner"));
}
// Replace the magic with the new one that points to the target executable
let offs = offs_opt.unwrap();
buf[offs..offs + magic_len].clone_from_slice(&new_magic);
Ok(buf)
}
fn create_tgz(dir: &Path, out: &Path) -> io::Result<()> {
let f = fs::File::create(out)?;
fn append_tgz(f: &mut impl io::Write, dir: &Path) -> io::Result<()> {
let gz = GzEncoder::new(f, Compression::best());
let mut tar = tar::Builder::new(gz);
tar.follow_symlinks(false);
tar.append_dir_all(".", dir)?;
Ok(())
tar.append_dir_all(".", dir)
}
fn append_args(f: &mut impl io::Write, args: &Args) {
f.write_all(WARP_ARGS_MAGIC).unwrap();
bincode_options().serialize_into(f, args).unwrap();
}
#[cfg(target_family = "unix")]
@ -102,76 +74,38 @@ fn create_app_file(out: &Path) -> io::Result<File> {
#[cfg(target_family = "windows")]
fn create_app_file(out: &Path) -> io::Result<File> {
fs::OpenOptions::new()
.create(true)
.write(true)
.open(out)
fs::OpenOptions::new().create(true).write(true).open(out)
}
fn create_app(runner_buf: &Vec<u8>, tgz_path: &Path, out: &Path) -> io::Result<()> {
let mut outf = create_app_file(out)?;
let mut tgzf = fs::File::open(tgz_path)?;
outf.write_all(runner_buf)?;
copy(&mut tgzf, &mut outf)?;
Ok(())
}
fn main() -> Result<(), Box<dyn Error>> {
let args = cli::Cli::parse();
fn main() -> Result<(), Box<Error>> {
let args = App::new(APP_NAME)
.settings(&[AppSettings::ArgRequiredElseHelp, AppSettings::ColoredHelp])
.version(VERSION)
.author(AUTHOR)
.about("Create self-contained single binary application")
.arg(Arg::with_name("arch")
.short("a")
.long("arch")
.value_name("arch")
.help(&format!("Sets the architecture. Supported: {:?}", RUNNER_BY_ARCH.keys()))
.display_order(1)
.takes_value(true)
.required(true))
.arg(Arg::with_name("input_dir")
.short("i")
.long("input_dir")
.value_name("input_dir")
.help("Sets the input directory containing the application and dependencies")
.display_order(2)
.takes_value(true)
.required(true))
.arg(Arg::with_name("exec")
.short("e")
.long("exec")
.value_name("exec")
.help("Sets the application executable file name")
.display_order(3)
.takes_value(true)
.required(true))
.arg(Arg::with_name("output")
.short("o")
.long("output")
.value_name("output")
.help("Sets the resulting self-contained application file name")
.display_order(4)
.takes_value(true)
.required(true))
.get_matches();
let args = match args.command {
Command::List => {
for arch in RUNNER_BY_ARCH.keys() {
println!("{arch}");
}
return Ok(());
}
Command::Pack(args) => args,
};
let arch = args.value_of("arch").unwrap();
if !RUNNER_BY_ARCH.contains_key(&arch) {
bail!("Unknown architecture specified: {}, supported: {:?}", arch, RUNNER_BY_ARCH.keys());
if !RUNNER_BY_ARCH.contains_key(&args.arch.as_str()) {
bail!(
"Unknown architecture specified: {}, supported: {:?}",
args.arch,
RUNNER_BY_ARCH.keys()
);
}
let input_dir = Path::new(args.value_of("input_dir").unwrap());
if fs::metadata(input_dir).is_err() {
bail!("Cannot access specified input directory {:?}", input_dir);
if fs::metadata(&args.input_dir).is_err() {
bail!(
"Cannot access specified input directory {:?}",
args.input_dir
);
}
let exec_name = args.value_of("exec").unwrap();
if exec_name.len() >= RUNNER_MAGIC.len() {
bail!("Executable name is too long, please consider using a shorter name");
}
let exec_path = Path::new(input_dir).join(exec_name);
let exec_path = args.input_dir.join(&args.exec);
match fs::metadata(&exec_path) {
Err(_) => {
bail!("Cannot find file {:?}", exec_path);
@ -183,16 +117,24 @@ fn main() -> Result<(), Box<Error>> {
}
}
let runner_buf = patch_runner(&arch, &exec_name)?;
println!(
"Creating self-contained application binary {:?}...",
args.exec
);
let mut output = BufWriter::new(create_app_file(&args.output).unwrap());
output.write_all(RUNNER_BY_ARCH.get(&args.arch.as_str()).unwrap())?;
append_args(
&mut output,
&Args {
target_file_name: args.exec,
prefix: args.prefix,
uid: args.unique_id.then(|| format!("{}", Uuid::new_v4())),
clean: args.clean,
},
);
println!("Compressing input directory {:?}...", input_dir);
let tmp_dir = TempDir::new(APP_NAME)?;
let tgz_path = tmp_dir.path().join("input.tgz");
create_tgz(&input_dir, &tgz_path)?;
let exec_name = Path::new(args.value_of("output").unwrap());
println!("Creating self-contained application binary {:?}...", exec_name);
create_app(&runner_buf, &tgz_path, &exec_name)?;
println!("Compressing input directory {:?}...", args.input_dir);
append_tgz(&mut output, &args.input_dir).unwrap();
println!("All done");
Ok(())

View File

@ -1,13 +1,17 @@
[package]
name = "warp-runner"
version = "0.3.0"
version = "0.4.0"
authors = ["Diego Giagio <diego@giagio.com>"]
edition = "2021"
[dependencies]
memmem = "0.1.1"
anyhow = "1.0"
bincode = "1.3"
dirs = "4.0"
flate2 = "1.0"
tar = "0.4"
dirs = "1.0.4"
winapi = "0.3.6"
log = "0.4.5"
simple_logger = "1.0.1"
memmem = "0.1.1"
remove_dir_all = "0.7"
simple_logger = "4.0"
tar = "0.4"
warp-args = { path = "../warp-args" }

View File

@ -1,9 +1,10 @@
use log::trace;
use std::env;
use std::io;
#[cfg(target_family = "unix")]
use std::fs;
#[cfg(target_family = "unix")]
use std::fs::Permissions;
use std::io;
#[cfg(target_family = "unix")]
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
@ -36,17 +37,21 @@ fn do_execute(target: &Path, args: &[String]) -> io::Result<i32> {
.stderr(Stdio::inherit())
.spawn()?
.wait()?
.code().unwrap_or(1))
.code()
.unwrap_or(1))
}
#[cfg(target_family = "windows")]
fn is_script(target: &Path) -> bool {
const SCRIPT_EXTENSIONS: &[&str] = &["bat", "cmd"];
SCRIPT_EXTENSIONS.contains(
&target.extension()
&target
.extension()
.unwrap_or_default()
.to_string_lossy()
.to_lowercase().as_str())
.to_lowercase()
.as_str(),
)
}
#[cfg(target_family = "windows")]
@ -66,7 +71,8 @@ fn do_execute(target: &Path, args: &[String]) -> io::Result<i32> {
.stderr(Stdio::inherit())
.spawn()?
.wait()?
.code().unwrap_or(1))
.code()
.unwrap_or(1))
} else {
Ok(Command::new(target)
.args(args)
@ -75,6 +81,7 @@ fn do_execute(target: &Path, args: &[String]) -> io::Result<i32> {
.stderr(Stdio::inherit())
.spawn()?
.wait()?
.code().unwrap_or(1))
.code()
.unwrap_or(1))
}
}

View File

@ -1,14 +1,14 @@
extern crate flate2;
extern crate memmem;
extern crate tar;
use self::flate2::read::GzDecoder;
use self::memmem::{Searcher, TwoWaySearcher};
use self::tar::Archive;
use anyhow::{anyhow, Context, Result};
use bincode::Options;
use flate2::read::GzDecoder;
use log::trace;
use memmem::{Searcher, TwoWaySearcher};
use std::fs::File;
use std::io;
use std::io::{BufReader, Read, Seek, SeekFrom};
use std::path::Path;
use tar::Archive;
use warp_args::{bincode_options, Args, WARP_ARGS_MAGIC};
struct FileSearcher<'a> {
buf_reader: BufReader<File>,
@ -36,7 +36,7 @@ impl<'a> Iterator for FileSearcher<'a> {
match self.buf_reader.seek(SeekFrom::Start(self.offs as u64)) {
Ok(_) => {}
Err(e) => return Some(Err(e))
Err(e) => return Some(Err(e)),
}
loop {
@ -53,7 +53,7 @@ impl<'a> Iterator for FileSearcher<'a> {
self.offs += 1; // one past the match so we can try again if necessary
break;
}
None => self.offs += n
None => self.offs += n,
}
}
Err(e) => {
@ -68,32 +68,53 @@ impl<'a> Iterator for FileSearcher<'a> {
const GZIP_MAGIC: &[u8] = b"\x1f\x8b\x08";
pub fn extract_to(src: &Path, dst: &Path) -> io::Result<()> {
let mut found = false;
let searcher = FileSearcher::new(src, GZIP_MAGIC)?;
for result in searcher {
let offs = result?;
if extract_at_offset(src, offs, dst).is_ok() {
trace!("tarball found at offset {} was extracted successfully", offs);
found = true;
break;
}
}
if found {
Ok(())
} else {
Err(io::Error::new(io::ErrorKind::Other, "no tarball found inside binary"))
}
pub fn extract_to(src: &Path, dst: &Path) -> Result<()> {
FileSearcher::new(src, GZIP_MAGIC)
.context("failed searching own binary")?
.map(Result::unwrap)
.find(|offs| extract_at_offset(src, *offs, dst).unwrap())
.ok_or_else(|| anyhow!("No tarball found inside binary file {}", src.display()))
.map(|offs| {
trace!(
"tarball found at offset {} was extracted successfully",
offs
);
})
}
fn extract_at_offset(src: &Path, offs: usize, dst: &Path) -> io::Result<()> {
let mut f = File::open(src)?;
f.seek(SeekFrom::Start(offs as u64))?;
fn extract_at_offset(src: &Path, offs: usize, dst: &Path) -> Result<bool> {
let mut f = File::open(src)
.with_context(|| format!("Failed to open file to extract from: {}", src.display()))?;
f.seek(SeekFrom::Start(offs as u64))
.with_context(|| format!("Failed to read file to extract from: {}", src.display()))?;
let gz = GzDecoder::new(f);
let mut tar = Archive::new(gz);
tar.unpack(dst)?;
Ok(())
Ok(tar.unpack(dst).is_ok())
}
pub fn get_args(src: &Path) -> Result<Args> {
FileSearcher::new(src, WARP_ARGS_MAGIC)
.context("failed searching own binary")?
.map(Result::unwrap)
.find_map(|offs| {
Some((
offs,
extract_args_at_offset(src, offs + WARP_ARGS_MAGIC.len()).unwrap()?,
))
})
.ok_or_else(|| anyhow!("No arguments found inside binary file {}", src.display()))
.map(|(offs, args)| {
trace!("args found at offset {} was extracted successfully", offs);
args
})
}
fn extract_args_at_offset(src: &Path, offs: usize) -> Result<Option<Args>> {
let mut f = File::open(src)
.with_context(|| format!("Failed to open file to extract from: {}", src.display()))?;
f.seek(SeekFrom::Start(offs as u64))
.with_context(|| format!("Failed to read file to extract from: {}", src.display()))?;
Ok(bincode_options().deserialize_from(f).ok())
}

View File

@ -1,82 +1,133 @@
extern crate dirs;
#[macro_use]
extern crate log;
extern crate simple_logger;
use log::Level;
use anyhow::Context;
use anyhow::{anyhow, Result};
use log::{trace, Level};
use remove_dir_all::remove_dir_all;
use std::env;
use std::error::Error;
use std::ffi::*;
use std::ffi::OsStr;
use std::fs;
use std::io;
use std::path::*;
use std::path::{Path, PathBuf};
use std::process;
use warp_args::Args;
use crate::extractor::get_args;
mod extractor;
mod executor;
mod extractor;
static TARGET_FILE_NAME_BUF: &'static [u8] = b"tVQhhsFFlGGD3oWV4lEPST8I8FEPP54IM0q7daes4E1y3p2U2wlJRYmWmjPYfkhZ0PlT14Ls0j8fdDkoj33f2BlRJavLj3mWGibJsGt5uLAtrCDtvxikZ8UX2mQDCrgE\0";
static STATIC_SUBFOLDER_NAME: &str = "static";
fn target_file_name() -> &'static str {
let nul_pos = TARGET_FILE_NAME_BUF.iter()
.position(|elem| *elem == b'\0')
.expect("TARGET_FILE_NAME_BUF has no NUL terminator");
let slice = &TARGET_FILE_NAME_BUF[..(nul_pos + 1)];
CStr::from_bytes_with_nul(slice)
.expect("Can't convert TARGET_FILE_NAME_BUF slice to CStr")
.to_str()
.expect("Can't convert TARGET_FILE_NAME_BUF CStr to str")
}
fn cache_path(target: &str) -> PathBuf {
dirs::data_local_dir()
.expect("No data local dir found")
fn cache_path(target: &str) -> Result<PathBuf> {
Ok(dirs::data_local_dir()
.ok_or_else(|| anyhow!("No data local dir found"))?
.join("warp")
.join("packages")
.join(target)
.join(target))
}
fn extract(exe_path: &Path, cache_path: &Path) -> io::Result<()> {
fs::remove_dir_all(cache_path).ok();
extractor::extract_to(&exe_path, &cache_path)?;
fn extract(exe_path: &Path, cache_path: &Path) -> Result<()> {
if cache_path.exists() {
remove_dir_all(cache_path)
.with_context(|| format!("Failed to remove directory {}", cache_path.display()))?;
}
extractor::extract_to(exe_path, cache_path).with_context(|| {
format!(
"Failed to extract {} to {}",
exe_path.display(),
cache_path.display()
)
})
}
fn create_cache_folder(self_path: &Path, args: &Args) -> Result<PathBuf> {
let prefix = args
.prefix
.as_deref()
.unwrap_or_else(|| Path::new(self_path.file_name().unwrap()));
let cache_path = cache_path(&prefix.to_string_lossy())?;
trace!("self_path={:?}", self_path);
trace!("prefix={:?}", prefix);
trace!("cache_path={:?}", cache_path);
if cache_path.exists() && !fs::metadata(&cache_path)?.is_dir() {
return Err(anyhow!("cache at {:?} is not a directory", &cache_path));
} else {
fs::create_dir_all(&cache_path)?;
}
Ok(cache_path)
}
fn clean_cache(cache_folder: &Path, self_path: &Path, args: &Args) -> Result<()> {
if args.uid.is_none() {
let subfolder = cache_folder.join(STATIC_SUBFOLDER_NAME);
if subfolder.exists()
&& fs::metadata(&subfolder)?.modified()? < fs::metadata(self_path)?.modified()?
{
trace!("static cache older than source, removing");
remove_dir_all(subfolder)?;
}
return Ok(());
}
if !args.clean {
return Ok(());
}
let uid = OsStr::new(args.uid.as_ref().unwrap()); // Checked above
let static_folder = OsStr::new(STATIC_SUBFOLDER_NAME);
trace!("cleaning cache");
for entry in fs::read_dir(cache_folder)? {
let entry = entry?;
if entry.file_name() == static_folder {
trace!("skipped static subfolder {:?}", static_folder);
continue;
}
if entry.file_name() == uid {
trace!("skipped own uid {:?}", uid);
continue;
}
trace!("removing entry {:?}", entry);
if let Err(err) = remove_dir_all(entry.path()) {
eprintln!(
"Error while attempting to remove directory {:?}: {err}",
entry.path()
);
}
}
Ok(())
}
fn main() -> Result<(), Box<Error>> {
fn main() -> Result<()> {
if env::var("WARP_TRACE").is_ok() {
simple_logger::init_with_level(Level::Trace)?;
}
let self_path = env::current_exe()?;
let self_file_name = self_path.file_name().unwrap();
let cache_path = cache_path(&self_file_name.to_string_lossy());
let args = get_args(&self_path).unwrap();
trace!("args = {:?}", args);
trace!("self_path={:?}", self_path);
trace!("self_file_name={:?}", self_file_name);
trace!("cache_path={:?}", cache_path);
let cache_path = create_cache_folder(&self_path, &args)?;
clean_cache(&cache_path, &self_path, &args)?;
let target_file_name = target_file_name();
let target_path = cache_path.join(target_file_name);
let subfolder = args.uid.as_deref().unwrap_or(STATIC_SUBFOLDER_NAME);
let cache_path = cache_path.join(subfolder);
trace!("target_exec={:?}", target_file_name);
let target_path = cache_path.join(&args.target_file_name);
trace!("target_exec={:?}", args.target_file_name);
trace!("target_path={:?}", target_path);
match fs::metadata(&cache_path) {
Ok(cache) => {
if cache.modified()? >= fs::metadata(&self_path)?.modified()? {
trace!("cache is up-to-date");
} else {
trace!("cache is outdated");
extract(&self_path, &cache_path)?;
}
}
Err(_) => {
trace!("cache not found");
extract(&self_path, &cache_path)?;
}
if !cache_path.exists() {
trace!("cache empty, extracting");
extract(&self_path, &cache_path)?;
}
let exit_code = executor::execute(&target_path)?;
process::exit(exit_code);
process::exit(executor::execute(&target_path)?);
}

View File

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="RUST_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/benches" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/warp-packer/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/warp-packer/examples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/warp-packer/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/warp-packer/benches" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/warp-runner/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/warp-runner/examples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/warp-runner/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/warp-runner/benches" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
<excludeFolder url="file://$MODULE_DIR$/warp-packer/target" />
<excludeFolder url="file://$MODULE_DIR$/warp-runner/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>