feat(core): create packager for Windows portable mode and move scripts to separate files
This commit is contained in:
parent
fd2f385858
commit
a4b9b30cdf
139
Makefile.toml
139
Makefile.toml
|
@ -19,109 +19,24 @@ EXEC_PATH = "target/release/espanso"
|
|||
# This one was written in Rust instead of bash because it has to run on Windows as well
|
||||
[tasks.build-binary]
|
||||
script_runner = "@rust"
|
||||
script = '''
|
||||
//! ```cargo
|
||||
//! [dependencies]
|
||||
//! envmnt = "*"
|
||||
//! ```
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum Profile {
|
||||
Debug,
|
||||
Release,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let profile = if envmnt::get_or_panic("RELEASE") == "true" {
|
||||
Profile::Release
|
||||
} else {
|
||||
Profile::Debug
|
||||
};
|
||||
|
||||
println!("Using profile: {:?}", profile);
|
||||
|
||||
let wayland = envmnt::get_or("NO_X11", "false") == "true";
|
||||
if wayland {
|
||||
println!("Using Wayland feature");
|
||||
}
|
||||
|
||||
let avoid_modulo = envmnt::get_or("NO_MODULO", "false") == "true";
|
||||
if avoid_modulo {
|
||||
println!("Skipping modulo feature");
|
||||
}
|
||||
|
||||
let mut args = Vec::new();
|
||||
args.push("build");
|
||||
|
||||
if profile == Profile::Release {
|
||||
args.push("--release");
|
||||
}
|
||||
|
||||
args.push("--manifest-path");
|
||||
args.push("espanso/Cargo.toml");
|
||||
|
||||
let mut features = Vec::new();
|
||||
if wayland {
|
||||
features.push("wayland");
|
||||
}
|
||||
if !avoid_modulo {
|
||||
features.push("modulo");
|
||||
}
|
||||
|
||||
let features_flag = features.join(" ");
|
||||
|
||||
args.push("-p");
|
||||
args.push("espanso");
|
||||
args.push("--no-default-features");
|
||||
args.push("--features");
|
||||
args.push(&features_flag);
|
||||
|
||||
println!("Calling with args: {:?}", args);
|
||||
|
||||
let mut cmd = Command::new("cargo");
|
||||
cmd.args(&args);
|
||||
|
||||
// Remove cargo/rust-specific env variables, as otherwise they mess up the
|
||||
// nested cargo build call.
|
||||
let all_vars = envmnt::vars();
|
||||
for (key, _) in all_vars {
|
||||
if key.starts_with("CARGO") || key.starts_with("RUST") {
|
||||
//println!("Removing {}", key);
|
||||
cmd.env_remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
let mut handle = cmd.spawn().expect("cargo build failed");
|
||||
handle.wait();
|
||||
}
|
||||
'''
|
||||
script = { file = "scripts/build_binary.rs" }
|
||||
|
||||
[tasks.run-binary]
|
||||
command = "${EXEC_PATH}"
|
||||
args = ["${@}"]
|
||||
dependencies = ["build-binary"]
|
||||
|
||||
# Windows
|
||||
|
||||
[tasks.build-windows-portable]
|
||||
script_runner = "@rust"
|
||||
script = { file = "scripts/build_windows_portable.rs" }
|
||||
dependencies = ["build-binary"]
|
||||
|
||||
# macOS
|
||||
|
||||
[tasks.create-bundle]
|
||||
script = '''
|
||||
TARGET_DIR=target/mac/Espanso.app
|
||||
|
||||
rm -Rf $TARGET_DIR
|
||||
|
||||
VERSION=$(cat espanso/Cargo.toml | grep version | head -1 | awk -F '"' '{ print $2 }')
|
||||
|
||||
mkdir -p $TARGET_DIR/Contents
|
||||
mkdir -p $TARGET_DIR/Contents/MacOS
|
||||
mkdir -p $TARGET_DIR/Contents/Resources
|
||||
|
||||
sed -e "s/VERSION/$VERSION/" espanso/src/res/macos/Info.plist > $TARGET_DIR/Contents/Info.plist
|
||||
|
||||
/bin/echo "APPL????" > $TARGET_DIR/Contents/PkgInfo
|
||||
|
||||
cp -f espanso/src/res/macos/icon.icns $TARGET_DIR/Contents/Resources/icon.icns
|
||||
cp -f $EXEC_PATH $TARGET_DIR/Contents/MacOS/espanso
|
||||
'''
|
||||
script = { file = "scripts/create_bundle.sh" }
|
||||
dependencies=["build-binary"]
|
||||
|
||||
[tasks.run-bundle]
|
||||
|
@ -129,36 +44,10 @@ command="target/mac/Espanso.app/Contents/MacOS/espanso"
|
|||
args=["${@}"]
|
||||
dependencies=["create-bundle"]
|
||||
|
||||
# Linux
|
||||
|
||||
[tasks.create-app-image]
|
||||
script = '''
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
TOOL_DIR=$(pwd)/target/linux/linuxdeploy
|
||||
TARGET_DIR=$(pwd)/target/linux/AppImage
|
||||
BUILD_DIR=$TARGET_DIR/build
|
||||
OUTPUT_DIR=$TARGET_DIR/out
|
||||
BASE_DIR=$(pwd)
|
||||
|
||||
mkdir -p $TOOL_DIR
|
||||
|
||||
if ls $TOOL_DIR/*.AppImage 1> /dev/null 2>&1; then
|
||||
echo "Skipping download of linuxdeploy"
|
||||
else
|
||||
echo "Downloading linuxdeploy tool"
|
||||
wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage -P "$TOOL_DIR"
|
||||
chmod +x $TOOL_DIR/linuxdeploy*.AppImage
|
||||
fi
|
||||
|
||||
rm -Rf "$TARGET_DIR"
|
||||
mkdir -p $OUTPUT_DIR
|
||||
mkdir -p $BUILD_DIR
|
||||
|
||||
echo Building AppImage into $OUTPUT_DIR
|
||||
pushd $OUTPUT_DIR
|
||||
$TOOL_DIR/linuxdeploy*.AppImage --appimage-extract-and-run -e "$BASE_DIR/$EXEC_PATH" -d "$BASE_DIR/espanso/src/res/linux/espanso.desktop" -i "$BASE_DIR/espanso/src/res/linux/icon.png" --appdir $BUILD_DIR --output appimage
|
||||
chmod +x ./Espanso*.AppImage
|
||||
popd
|
||||
'''
|
||||
script = { file = "scripts/create_app_image.sh" }
|
||||
dependencies=["build-binary"]
|
||||
|
||||
[tasks.run-app-image]
|
||||
|
|
76
scripts/build_binary.rs
Normal file
76
scripts/build_binary.rs
Normal file
|
@ -0,0 +1,76 @@
|
|||
//! ```cargo
|
||||
//! [dependencies]
|
||||
//! envmnt = "*"
|
||||
//! ```
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum Profile {
|
||||
Debug,
|
||||
Release,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let profile = if envmnt::get_or_panic("RELEASE") == "true" {
|
||||
Profile::Release
|
||||
} else {
|
||||
Profile::Debug
|
||||
};
|
||||
|
||||
println!("Using profile: {:?}", profile);
|
||||
|
||||
let wayland = envmnt::get_or("NO_X11", "false") == "true";
|
||||
if wayland {
|
||||
println!("Using Wayland feature");
|
||||
}
|
||||
|
||||
let avoid_modulo = envmnt::get_or("NO_MODULO", "false") == "true";
|
||||
if avoid_modulo {
|
||||
println!("Skipping modulo feature");
|
||||
}
|
||||
|
||||
let mut args = Vec::new();
|
||||
args.push("build");
|
||||
|
||||
if profile == Profile::Release {
|
||||
args.push("--release");
|
||||
}
|
||||
|
||||
args.push("--manifest-path");
|
||||
args.push("espanso/Cargo.toml");
|
||||
|
||||
let mut features = Vec::new();
|
||||
if wayland {
|
||||
features.push("wayland");
|
||||
}
|
||||
if !avoid_modulo {
|
||||
features.push("modulo");
|
||||
}
|
||||
|
||||
let features_flag = features.join(" ");
|
||||
|
||||
args.push("-p");
|
||||
args.push("espanso");
|
||||
args.push("--no-default-features");
|
||||
args.push("--features");
|
||||
args.push(&features_flag);
|
||||
|
||||
println!("Calling with args: {:?}", args);
|
||||
|
||||
let mut cmd = Command::new("cargo");
|
||||
cmd.args(&args);
|
||||
|
||||
// Remove cargo/rust-specific env variables, as otherwise they mess up the
|
||||
// nested cargo build call.
|
||||
let all_vars = envmnt::vars();
|
||||
for (key, _) in all_vars {
|
||||
if key.starts_with("CARGO") || key.starts_with("RUST") {
|
||||
//println!("Removing {}", key);
|
||||
cmd.env_remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
let mut handle = cmd.spawn().expect("cargo build failed");
|
||||
handle.wait();
|
||||
}
|
108
scripts/build_windows_portable.rs
Normal file
108
scripts/build_windows_portable.rs
Normal file
|
@ -0,0 +1,108 @@
|
|||
//! ```cargo
|
||||
//! [dependencies]
|
||||
//! cc = "1.0.66"
|
||||
//! glob = "0.3.0"
|
||||
//! envmnt = "*"
|
||||
//! ```
|
||||
|
||||
use std::process::Command;
|
||||
use std::path::PathBuf;
|
||||
|
||||
const TARGET_DIR: &str = "target/windows/portable";
|
||||
|
||||
fn main() {
|
||||
// Clean the target directory
|
||||
std::fs::remove_dir_all(TARGET_DIR);
|
||||
// Create the target directory
|
||||
std::fs::create_dir_all(TARGET_DIR).expect("unable to create target directory");
|
||||
let target_dir = PathBuf::from(TARGET_DIR);
|
||||
if !target_dir.is_dir() {
|
||||
panic!("expected target directory, found none");
|
||||
}
|
||||
|
||||
// We first need to find all the DLLs to redistribute with the binary
|
||||
// These are found inside the MSVC compiler directory, usually in a place like:
|
||||
// C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Redist\MSVC\14.28.29910\x64\Microsoft.VC142.CRT
|
||||
// and they include files like vcruntime140.dll and msvcp140.dll
|
||||
|
||||
// First, we try to find the directory containing the various versions:
|
||||
// C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Redist\MSVC\
|
||||
let tool = cc::windows_registry::find_tool("msvc", "msbuild")
|
||||
.expect("unable to locate MSVC compiler, did you install Visual Studio?");
|
||||
let mut versions_dir = None;
|
||||
let mut current_root = tool.path();
|
||||
while let Some(parent) = current_root.parent() {
|
||||
let target = parent.join("VC").join("Redist").join("MSVC");
|
||||
if target.exists() {
|
||||
versions_dir = Some(target);
|
||||
break;
|
||||
}
|
||||
current_root = parent;
|
||||
}
|
||||
let versions_dir = versions_dir.expect(
|
||||
r"unable to find path: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Redist\MSVC",
|
||||
);
|
||||
|
||||
// Then we try to find a suitable directory containing the required DLLs
|
||||
// C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Redist\MSVC\14.28.29910\x64\Microsoft.VC142.CRT
|
||||
let glob_pattern = format!(
|
||||
r"{}\*\x64\Microsoft.*\vcruntime140_1.dll",
|
||||
versions_dir.to_string_lossy().to_string()
|
||||
);
|
||||
println!("glob_pattern: {}", glob_pattern);
|
||||
let mut target_file = glob::glob(&glob_pattern)
|
||||
.expect("failed to read glob pattern")
|
||||
.next()
|
||||
.expect("unable to find vcruntime140_1.dll file")
|
||||
.expect("unable to extract path of vcruntime140_1.dll file");
|
||||
|
||||
// Copy the DLLs in the target directory
|
||||
let parent_dir = target_file.parent().expect("unable to obtain directory containing DLLs");
|
||||
for entry in glob::glob(&format!(r"{}\*.dll", parent_dir.to_string_lossy().to_string())).expect("unable to glob over DLLs") {
|
||||
let entry = entry.expect("unable to unwrap DLL entry");
|
||||
let filename = entry.file_name().expect("unable to obtain filename");
|
||||
std::fs::copy(&entry, target_dir.join(filename));
|
||||
}
|
||||
|
||||
// Copy the executable
|
||||
let exec_path = envmnt::get_or_panic("EXEC_PATH");
|
||||
let exec_file = PathBuf::from(&format!("{}.exe", exec_path));
|
||||
if !exec_file.is_file() {
|
||||
panic!("expected espanso binary, found none in {:?}", exec_file);
|
||||
}
|
||||
std::fs::copy(exec_file, target_dir.join("espansod.exe"));
|
||||
|
||||
// Create the CLI wrapper
|
||||
std::fs::write(target_dir.join("espanso.cmd"), r#"@"%~dp0espansod.exe" %*"#).unwrap();
|
||||
|
||||
// Create the launcher
|
||||
std::fs::write(target_dir.join("START_ESPANSO.bat"), r#"start espansod.exe launcher"#).unwrap();
|
||||
|
||||
// Create the necessary folders
|
||||
std::fs::create_dir_all(target_dir.join(".espanso")).expect("unable to create data directory");
|
||||
std::fs::create_dir_all(target_dir.join(".espanso-runtime")).expect("unable to create runtime directory");
|
||||
|
||||
std::fs::write(target_dir.join("README.txt"), r##"Welcome to Espanso (Portable edition)!
|
||||
|
||||
To start espanso, you can double click on "START_ESPANSO.bat"
|
||||
|
||||
After the first run, you will see some files in the ".espanso" directory.
|
||||
This is where your snippets and configurations should be defined.
|
||||
|
||||
For more information, please visit the official documentation:
|
||||
https://espanso.org/docs/
|
||||
|
||||
IMPORTANT: Don't delete any file or directory, otherwise espanso won't work.
|
||||
|
||||
|
||||
FOR ADVANCED USERS:
|
||||
|
||||
Espanso also offers a rich CLI interface. To start it from the terminal, cd into the
|
||||
current directory and run "espanso start". You can also run "espanso --help" for more information.
|
||||
|
||||
You might have noticed that the directory contains both an "espansod.exe" and an "espanso.cmd" file.
|
||||
You should generally avoid running "espansod.exe" directly, and instead use the "espanso.cmd"
|
||||
wrapper (which can simply be run as "espanso" in the terminal). This is needed to correctly manage
|
||||
STD console handles on Windows.
|
||||
"##).unwrap();
|
||||
}
|
27
scripts/create_app_image.sh
Normal file
27
scripts/create_app_image.sh
Normal file
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
TOOL_DIR=$(pwd)/target/linux/linuxdeploy
|
||||
TARGET_DIR=$(pwd)/target/linux/AppImage
|
||||
BUILD_DIR=$TARGET_DIR/build
|
||||
OUTPUT_DIR=$TARGET_DIR/out
|
||||
BASE_DIR=$(pwd)
|
||||
|
||||
mkdir -p $TOOL_DIR
|
||||
|
||||
if ls $TOOL_DIR/*.AppImage 1> /dev/null 2>&1; then
|
||||
echo "Skipping download of linuxdeploy"
|
||||
else
|
||||
echo "Downloading linuxdeploy tool"
|
||||
wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage -P "$TOOL_DIR"
|
||||
chmod +x $TOOL_DIR/linuxdeploy*.AppImage
|
||||
fi
|
||||
|
||||
rm -Rf "$TARGET_DIR"
|
||||
mkdir -p $OUTPUT_DIR
|
||||
mkdir -p $BUILD_DIR
|
||||
|
||||
echo Building AppImage into $OUTPUT_DIR
|
||||
pushd $OUTPUT_DIR
|
||||
$TOOL_DIR/linuxdeploy*.AppImage --appimage-extract-and-run -e "$BASE_DIR/$EXEC_PATH" -d "$BASE_DIR/espanso/src/res/linux/espanso.desktop" -i "$BASE_DIR/espanso/src/res/linux/icon.png" --appdir $BUILD_DIR --output appimage
|
||||
chmod +x ./Espanso*.AppImage
|
||||
popd
|
16
scripts/create_bundle.sh
Normal file
16
scripts/create_bundle.sh
Normal file
|
@ -0,0 +1,16 @@
|
|||
TARGET_DIR=target/mac/Espanso.app
|
||||
|
||||
rm -Rf $TARGET_DIR
|
||||
|
||||
VERSION=$(cat espanso/Cargo.toml | grep version | head -1 | awk -F '"' '{ print $2 }')
|
||||
|
||||
mkdir -p $TARGET_DIR/Contents
|
||||
mkdir -p $TARGET_DIR/Contents/MacOS
|
||||
mkdir -p $TARGET_DIR/Contents/Resources
|
||||
|
||||
sed -e "s/VERSION/$VERSION/" espanso/src/res/macos/Info.plist > $TARGET_DIR/Contents/Info.plist
|
||||
|
||||
/bin/echo "APPL????" > $TARGET_DIR/Contents/PkgInfo
|
||||
|
||||
cp -f espanso/src/res/macos/icon.icns $TARGET_DIR/Contents/Resources/icon.icns
|
||||
cp -f $EXEC_PATH $TARGET_DIR/Contents/MacOS/espanso
|
Loading…
Reference in New Issue
Block a user