Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,47 @@ jobs:
run: cargo test --all-features --all-targets
- name: Run clippy
run: cargo clippy --all-features --all-targets -- --no-deps --deny warnings

installer:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Install Rust
run: rustup toolchain install nightly --no-self-update --profile minimal --component rust-src
- name: Run installer tests
run: bash tools/test-installer.sh

installer-distros:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- name: ubuntu
image: ubuntu:24.04
- name: fedora
image: fedora:42
- name: archlinux
image: archlinux:latest
- name: opensuse
image: opensuse/tumbleweed:latest
container:
image: ${{ matrix.image }}
env:
CARGO_HOME: /github/home/.cargo
RUSTUP_HOME: /github/home/.rustup
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run distro installer smoke test
run: bash tools/test-installer-distro.sh
1 change: 1 addition & 0 deletions Cargo.lock

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

14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ You can install the latest version with WinGet:
winget install Microsoft.Edit
```

### Linux

You can install the latest tagged release by pasting this into the Linux terminal:
```sh
curl -fsSL https://raw.githubusercontent.com/microsoft/edit/main/tools/install.sh | bash
```
You can uninstall via:
```sh
curl -fsSL https://raw.githubusercontent.com/microsoft/edit/main/tools/uninstall.sh | bash
```
<!-- To target a specific branch, tag, or commit instead, set `EDIT_SOURCE_REF`. -->

The source installer is continuously tested on Ubuntu, Fedora, Arch Linux, and openSUSE Tumbleweed. Other Linux distributions are best-effort and may require manual dependency installation.

## Build Instructions

* [Install Rust](https://www.rust-lang.org/tools/install)
Expand Down
1 change: 1 addition & 0 deletions crates/edit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ libc = "0.2"
[build-dependencies]
stdext.workspace = true
lsh.workspace = true
pkg-config = "0.3"
# The default toml crate bundles its dependencies with bad compile times. Thanks.
# Thankfully toml-span exists. FWIW the alternative is yaml-rust (without the 2 suffix).
toml-span = { version = "0.6", default-features = false }
Expand Down
92 changes: 92 additions & 0 deletions crates/edit/build/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
use stdext::arena::scratch_arena;

use crate::helpers::env_opt;
use std::fs;
use std::io::Write;
use std::path::{Path, PathBuf};

mod helpers;
mod i18n;
Expand All @@ -17,6 +20,94 @@ enum TargetOs {
Unix,
}

// ---- ICU discovery for installer & source builds ---------------------------
fn dedup_join(mut v: Vec<PathBuf>) -> String {
v.sort();
v.dedup();
let parts: Vec<String> = v.into_iter().map(|p| p.display().to_string()).collect();
parts.join(":")
}

fn try_pkg_config() -> Vec<PathBuf> {
let mut dirs = Vec::new();
for name in ["icu-uc", "icu-i18n", "icu-data"] {
match pkg_config::Config::new().print_system_libs(false).probe(name) {
Ok(lib) => dirs.extend(lib.link_paths.clone()),
Err(_) => {}
}
}
dirs
}

fn try_fs_latest_for(stem: &str, roots: &[&str]) -> Option<PathBuf> {
// Find lib<stem>.so.* and return its parent dir
for d in roots {
let dir = Path::new(d);
if !dir.is_dir() { continue; }
// A simple lexicographic sort is good enough for .so.N versions
let mut candidates: Vec<PathBuf> = match fs::read_dir(dir) {
Ok(it) => it.filter_map(|e| e.ok().map(|e| e.path()))
.filter(|p| p.file_name()
.and_then(|s| s.to_str())
.map(|n| n.starts_with(&format!("lib{stem}.so.")))
.unwrap_or(false))
.collect(),
Err(_) => continue,
};
candidates.sort();
if let Some(path) = candidates.last() {
return path.parent().map(|p| p.to_path_buf());
}
}
None
}

fn try_fs_scan() -> Vec<PathBuf> {
let roots = [
"/usr/local/lib", "/usr/local/lib64",
"/usr/lib", "/usr/lib64", "/lib", "/lib64",
"/usr/lib32",
"/usr/lib/x86_64-linux-gnu", "/lib/x86_64-linux-gnu",
"/usr/lib/aarch64-linux-gnu", "/lib/aarch64-linux-gnu",
"/usr/lib/arm-linux-gnueabihf", "/lib/arm-linux-gnueabihf",
];
let mut dirs = Vec::new();
for stem in ["icuuc", "icui18n", "icudata"] {
if let Some(d) = try_fs_latest_for(stem, &roots) {
dirs.push(d);
}
}
dirs
}

fn write_icu_ldpath_artifact() {
// 1) gather ICU dirs (prefer pkg-config)
let mut dirs = try_pkg_config();
if dirs.is_empty() {
dirs = try_fs_scan();
}

// 2) write ${OUT_DIR}/.edit.ldpath (empty file if not found)
let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR not set");
let ldfile = Path::new(&out_dir).join(".edit.ldpath");
let joined = dedup_join(dirs);
// Create the file regardless (lets the installer detect the “not found” case)
let mut f = fs::File::create(&ldfile).expect("create .edit.ldpath");
if !joined.is_empty() {
let _ = writeln!(f, "{}", joined);
// Also export for optional runtime hints
println!("cargo:rustc-env=EDIT_BUILD_ICU_LDPATH={}", joined);
println!("cargo:warning=edit: using ICU from {}", joined);
} else {
// Leave it empty; installer will fall back to its own detection
println!("cargo:warning=edit: ICU not found by build script");
}
// Re-run if we change this file
println!("cargo:rerun-if-changed=build/main.rs");
println!("cargo:rerun-if-env-changed=PKG_CONFIG_PATH");
}


fn main() {
stdext::arena::init(128 * 1024 * 1024).unwrap();

Expand All @@ -26,6 +117,7 @@ fn main() {
_ => TargetOs::Unix,
};

write_icu_ldpath_artifact();
compile_lsh();
compile_i18n();
configure_icu(target_os);
Expand Down
Loading