Skip to content

Commit

Permalink
Much better error management and better libs management
Browse files Browse the repository at this point in the history
  • Loading branch information
StratusFearMe21 committed Oct 24, 2021
1 parent 6f421c7 commit 61fdd8e
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 53 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cargo-appimage"
version = "1.1.0"
version = "1.2.0"
authors = ["Isaac Mills <[email protected]>", "Jim Hessin <[email protected]>"]
edition = "2018"
license = "GPL-3.0"
Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,19 @@ cargo install cargo-appimage
assets = ["images", "sounds"]
```

5. (optional) By default, cargo-appimage will embed all the shared objects your executable uses into the appimage. To not do this, create a section in your Cargo.toml similar to the following
with:
5. (optional) If you are using external crates that use other programs or are not written in pure rust, you may want to check if you need to embed some shared libraries into your AppImage:

1. Running `cargo appimage` with this option in your Cargo.toml will automatically make a libs folder and put all of the shared objects your rust program uses in their respective directories.

```toml
[package.metadata.appimage]
link_deps = false
auto_link = true
```

2. AppImages aren't supposed to have EVERY library that your executable links to inside of the AppImage, so delete the libraries that you expect will be on every linux system (libc, libgcc, libpthread, ld-linux, libdl, etc.)

3. Remove the Cargo.toml option above and run `cargo appimage` again, now only the libs you want should be embedded in the Appimage

6. run this command

```shell
Expand Down
1 change: 1 addition & 0 deletions libs/ld-linux-x86-64.so.2
164 changes: 116 additions & 48 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use anyhow::{bail, Context, Result};
use anyhow::{Context, Result};
use cargo_toml::Value;
use fs_extra::dir::CopyOptions;
use std::{
Expand All @@ -10,15 +10,12 @@ const APPDIRPATH: &str = "target/cargo-appimage.AppDir/";

fn main() -> Result<()> {
let appdirpath = std::path::Path::new(APPDIRPATH);
match Command::new("cargo")
Command::new("cargo")
.arg("build")
.arg("--release")
.args(std::env::args().nth(2))
.status()
{
Ok(_) => {}
Err(_) => bail!("Failed to build package"),
}
.context("Failed to build package")?;

if !std::path::Path::new("./icon.png").exists() {
std::fs::write("./icon.png", &[]).context("Failed to generate icon.png")?;
Expand All @@ -31,55 +28,71 @@ fn main() -> Result<()> {
let assets;
let link_deps;

match meta
.metadata
.unwrap_or_else(|| Value::Array(Vec::with_capacity(0)))
{
Value::Table(t) => match t.get("appimage") {
Some(Value::Table(t)) => {
match t.get("assets") {
Some(Value::Array(v)) => {
assets = v
.to_vec()
.into_iter()
.filter_map(|v| match v {
Value::String(s) => Some(s),
_ => None,
})
.collect()
if let Some(meta) = meta.metadata.as_ref() {
match meta {
Value::Table(t) => match t.get("appimage") {
Some(Value::Table(t)) => {
match t.get("assets") {
Some(Value::Array(v)) => {
assets = v
.to_vec()
.into_iter()
.filter_map(|v| match v {
Value::String(s) => Some(s),
_ => None,
})
.collect()
}
_ => assets = Vec::with_capacity(0),
}
match t.get("auto_link") {
Some(Value::Boolean(v)) => link_deps = v.to_owned(),
_ => link_deps = false,
}
_ => assets = Vec::with_capacity(0),
}
match t.get("link_deps") {
Some(Value::Boolean(v)) => link_deps = v.to_owned(),
_ => link_deps = true,
_ => {
assets = Vec::with_capacity(0);
link_deps = false
}
}
},
_ => {
assets = Vec::with_capacity(0);
link_deps = true
link_deps = false
}
},
_ => {
assets = Vec::with_capacity(0);
link_deps = true
}
};
};
} else {
assets = Vec::with_capacity(0);
link_deps = false;
}

fs_extra::dir::create_all(appdirpath.join("usr"), true)
.with_context(|| format!("Error creating {}", appdirpath.join("usr").display()))?;

fs_extra::dir::create_all(appdirpath.join("usr/bin"), false)?;
fs_extra::dir::create_all(appdirpath.join("usr/bin"), true)
.with_context(|| format!("Error creating {}", appdirpath.join("usr/bin").display()))?;
if link_deps {
if !std::path::Path::new("libs").exists() {
std::fs::create_dir("libs").context("Could not create libs directory")?;
}
let awk = std::process::Command::new("awk")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.arg("NF == 4 {print $3}; NF == 2 {print $1}")
.spawn()?;
.spawn()
.context("Could not start awk")?;

awk.stdin
.context("Make sure you have awk on your system")?
.write_all(
&std::process::Command::new("ldd")
.arg(format!("target/release/{}", meta.name))
.output()?
.output()
.with_context(|| {
format!(
"Failed to run ldd on {}",
format!("target/release/{}", meta.name)
)
})?
.stdout,
)?;

Expand All @@ -88,20 +101,60 @@ fn main() -> Result<()> {
.context("Unknown error ocurred while running awk")?
.read_to_string(&mut linkedlibs)?;

fs_extra::dir::create("libs", true).context("Failed to create libs dir")?;

for line in linkedlibs.lines() {
if line.starts_with("/") {
fs_extra::dir::create_all(
appdirpath.join(
std::path::Path::new(&line[1..])
.parent()
.context("Lib has no parent path")?,
),
false,
)?;
std::fs::copy(line, appdirpath.join(&line[1..]))?;
if !std::path::Path::new("libs").join(&line[1..]).exists() {
std::os::unix::fs::symlink(
line,
std::path::Path::new("libs").join(
std::path::Path::new(line)
.file_name()
.with_context(|| format!("No filename for {}", line))?,
),
)
.with_context(|| {
format!(
"Error symlinking {} to {}",
line,
std::path::Path::new("libs").join(&line[1..]).display()
)
})?;
}
}
}
}

if std::path::Path::new("libs").exists() {
for i in std::fs::read_dir("libs").context("Could not read libs dir")? {
let ref path = i?.path();
let link = std::fs::read_link(path)
.with_context(|| format!("Error reading link in libs {}", path.display()))?;

if fs_extra::dir::create_all(
appdirpath.join(
&link
.parent()
.with_context(|| format!("Lib {} has no parent dir", &link.display()))?
.to_str()
.with_context(|| format!("{} is not valid Unicode", link.display()))?[1..],
),
false,
)
.is_err()
{}
let dest = appdirpath.join(
&link
.to_str()
.with_context(|| format!("{} is not valid Unicode", link.display()))?[1..],
);
std::fs::copy(&link, &dest).with_context(|| {
format!("Error copying {} to {}", &link.display(), dest.display())
})?;
}
}

std::fs::copy(
format!("target/release/{}", meta.name),
appdirpath.join("usr/bin/bin"),
Expand All @@ -125,11 +178,26 @@ fn main() -> Result<()> {
"[Desktop Entry]\nName={}\nExec=bin\nIcon=icon\nType=Application\nCategories=Utility;",
meta.name
),
)?;
)
.with_context(|| {
format!(
"Error writing desktop file {}",
appdirpath.join("cargo-appimage.desktop").display()
)
})?;
std::fs::copy(
std::path::PathBuf::from(std::env::var("HOME")?).join(".cargo/bin/cargo-appimage-runner"),
appdirpath.join("AppRun"),
)?;
)
.with_context(|| {
format!(
"Error copying {} to {}",
std::path::PathBuf::from(std::env::var("HOME").unwrap())
.join(".cargo/bin/cargo-appimage-runner")
.display(),
appdirpath.join("AppRun").display()
)
})?;

Command::new("appimagetool")
.arg(appdirpath)
Expand Down

0 comments on commit 61fdd8e

Please sign in to comment.