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
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.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ libc = "0.2"
# 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.5", default-features = false }
pkg-config = "0.3"

[target.'cfg(windows)'.build-dependencies]
winresource = { version = "0.1.22", default-features = false }
Expand Down
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,41 @@ You can install the latest version with WinGet:
winget install Microsoft.Edit
```

### Linux

You can install the latest version 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
```
<!--

Before this becomes live, these can be used instead.


To to this directory:
```sh
git clone [email protected]:microsoft/edit.git
cd edit
```

Then from there:

To install:
```sh
curl -fsSL file://"$PWD/tools/install.sh" | bash
```

To uninstall:
```sh
sudo ./tools/uninstall.sh
```

-->

## Build Instructions

* [Install Rust](https://www.rust-lang.org/tools/install)
Expand Down
93 changes: 93 additions & 0 deletions build/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#![allow(irrefutable_let_patterns)]

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

mod helpers;
mod i18n;
Expand All @@ -15,13 +18,103 @@ 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() {
let target_os = match env_opt("CARGO_CFG_TARGET_OS").as_str() {
"windows" => TargetOs::Windows,
"macos" | "ios" => TargetOs::MacOS,
_ => TargetOs::Unix,
};

// Always produce ICU ldpath artifact for installer & source builds
write_icu_ldpath_artifact();
compile_i18n();
configure_icu(target_os);
#[cfg(windows)]
Expand Down
Loading