unify build, fix opening files when app is running
This commit is contained in:
160
CROSS_COMPILE.md
160
CROSS_COMPILE.md
@@ -1,160 +0,0 @@
|
|||||||
# Cross-Compilation Guide
|
|
||||||
|
|
||||||
Build Windows binaries from Linux using Docker-based cross-compilation.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
1. **Install Docker**:
|
|
||||||
```bash
|
|
||||||
# Ubuntu/Debian
|
|
||||||
sudo apt-get install docker.io
|
|
||||||
sudo usermod -aG docker $USER
|
|
||||||
# Log out and back in for group changes to take effect
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Verify Docker**:
|
|
||||||
```bash
|
|
||||||
docker --version
|
|
||||||
```
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
### Option 1: Interactive Menu
|
|
||||||
```bash
|
|
||||||
./cross-compile.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Then select:
|
|
||||||
- `1` - Linux native
|
|
||||||
- `2` - Windows (MinGW)
|
|
||||||
- `3` - Both platforms
|
|
||||||
- `4` - Exit
|
|
||||||
|
|
||||||
### Option 2: Command Line
|
|
||||||
```bash
|
|
||||||
./cross-compile.sh windows # Windows (MinGW/GNU)
|
|
||||||
./cross-compile.sh all # All platforms
|
|
||||||
./cross-compile.sh linux # Linux native
|
|
||||||
```
|
|
||||||
|
|
||||||
### Option 3: Make
|
|
||||||
```bash
|
|
||||||
make cross-windows # Build for Windows
|
|
||||||
make cross-all # Build for all platforms
|
|
||||||
```
|
|
||||||
|
|
||||||
## What Gets Built
|
|
||||||
|
|
||||||
Binaries are created in the `dist/` directory:
|
|
||||||
- `rlogg-linux-x86_64` - Linux binary
|
|
||||||
- `rlogg-windows-x86_64.exe` - Windows binary (MinGW)
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
The `cross` tool:
|
|
||||||
1. Automatically installs on first use
|
|
||||||
2. Uses Docker to run cross-compilation in containers
|
|
||||||
3. Provides complete toolchains for each target
|
|
||||||
4. No need to install Windows SDK or MinGW manually
|
|
||||||
|
|
||||||
## About Windows Cross-Compilation
|
|
||||||
|
|
||||||
### Why MinGW/GNU Only?
|
|
||||||
|
|
||||||
When cross-compiling from Linux to Windows, only the **GNU target** (`x86_64-pc-windows-gnu`) is supported:
|
|
||||||
|
|
||||||
- **MinGW (GNU)** - Uses open-source MinGW toolchain
|
|
||||||
- ✅ Fully supported by `cross` from Linux
|
|
||||||
- ✅ Works great for most Windows applications
|
|
||||||
- ✅ Smaller binaries
|
|
||||||
- ✅ No runtime dependencies on Visual C++ redistributables
|
|
||||||
|
|
||||||
- **MSVC** - Microsoft Visual C++ toolchain
|
|
||||||
- ❌ Not available for cross-compilation from Linux
|
|
||||||
- ❌ Requires proprietary Microsoft tools
|
|
||||||
- ❌ Can only be built on Windows or via Windows VM
|
|
||||||
|
|
||||||
### Compatibility
|
|
||||||
|
|
||||||
The MinGW binaries work on **all Windows systems** (Windows 7+) without requiring additional runtime installations. They're fully compatible with standard Windows applications.
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Docker permission denied
|
|
||||||
```bash
|
|
||||||
sudo usermod -aG docker $USER
|
|
||||||
# Log out and back in
|
|
||||||
```
|
|
||||||
|
|
||||||
### cross installation fails
|
|
||||||
```bash
|
|
||||||
# Install from source
|
|
||||||
cargo install cross --git https://github.com/cross-rs/cross
|
|
||||||
```
|
|
||||||
|
|
||||||
### Build fails with linker errors
|
|
||||||
The `cross` tool handles all linker configuration automatically. If you see linker errors, try:
|
|
||||||
```bash
|
|
||||||
# Clean and rebuild
|
|
||||||
make clean
|
|
||||||
./cross-compile.sh windows
|
|
||||||
```
|
|
||||||
|
|
||||||
### Very slow first build
|
|
||||||
The first build downloads the Docker image (~1-2 GB) and compiles dependencies. Subsequent builds are much faster due to caching.
|
|
||||||
|
|
||||||
## Alternative: Manual Cross-Compilation (Advanced)
|
|
||||||
|
|
||||||
If you don't want to use Docker, you can manually set up cross-compilation:
|
|
||||||
|
|
||||||
### For Windows from Linux
|
|
||||||
```bash
|
|
||||||
# Install MinGW
|
|
||||||
sudo apt-get install mingw-w64
|
|
||||||
|
|
||||||
# Add Rust target
|
|
||||||
rustup target add x86_64-pc-windows-gnu
|
|
||||||
|
|
||||||
# Configure cargo
|
|
||||||
mkdir -p ~/.cargo
|
|
||||||
cat >> ~/.cargo/config.toml << EOF
|
|
||||||
[target.x86_64-pc-windows-gnu]
|
|
||||||
linker = "x86_64-w64-mingw32-gcc"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Build
|
|
||||||
cargo build --release --target x86_64-pc-windows-gnu
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note**: This only works for the GNU target, not MSVC.
|
|
||||||
|
|
||||||
## Testing Windows Binaries on Linux
|
|
||||||
|
|
||||||
Use Wine to test Windows binaries:
|
|
||||||
```bash
|
|
||||||
# Install Wine
|
|
||||||
sudo apt-get install wine64
|
|
||||||
|
|
||||||
# Run the Windows binary
|
|
||||||
wine dist/rlogg-windows-x86_64-gnu.exe
|
|
||||||
```
|
|
||||||
|
|
||||||
## CI/CD Integration
|
|
||||||
|
|
||||||
The GitHub Actions workflow automatically cross-compiles for all platforms. Just push to trigger builds:
|
|
||||||
```bash
|
|
||||||
git push origin master
|
|
||||||
```
|
|
||||||
|
|
||||||
Artifacts are available in the Actions tab.
|
|
||||||
|
|
||||||
## Performance Considerations
|
|
||||||
|
|
||||||
Cross-compilation is:
|
|
||||||
- **Fast**: Similar speed to native compilation
|
|
||||||
- **Cached**: Dependencies are cached in Docker volumes
|
|
||||||
- **Isolated**: Doesn't affect your system
|
|
||||||
|
|
||||||
Typical build times:
|
|
||||||
- First build: 2-5 minutes (includes Docker image download)
|
|
||||||
- Incremental builds: 30-60 seconds
|
|
||||||
59
Cargo.lock
generated
59
Cargo.lock
generated
@@ -1793,6 +1793,32 @@ dependencies = [
|
|||||||
"hashbrown 0.16.1",
|
"hashbrown 0.16.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "interprocess"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81f2533f3be42fffe3b5e63b71aeca416c1c3bc33e4e27be018521e76b1f38fb"
|
||||||
|
dependencies = [
|
||||||
|
"blocking",
|
||||||
|
"cfg-if",
|
||||||
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"intmap",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"rustc_version",
|
||||||
|
"spinning",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
"to_method",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "intmap"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae52f28f45ac2bc96edb7714de995cffc174a395fb0abf5bff453587c980d7b9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is_terminal_polyfill"
|
name = "is_terminal_polyfill"
|
||||||
version = "1.70.2"
|
version = "1.70.2"
|
||||||
@@ -2820,11 +2846,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rlogg"
|
name = "rlogg"
|
||||||
version = "0.4.0"
|
version = "0.4.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"eframe",
|
"eframe",
|
||||||
|
"interprocess",
|
||||||
"rayon",
|
"rayon",
|
||||||
"regex",
|
"regex",
|
||||||
"rfd",
|
"rfd",
|
||||||
@@ -2844,6 +2871,15 @@ version = "2.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||||
|
dependencies = [
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.44"
|
version = "0.38.44"
|
||||||
@@ -2916,6 +2952,12 @@ dependencies = [
|
|||||||
"tiny-skia",
|
"tiny-skia",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.228"
|
version = "1.0.228"
|
||||||
@@ -3095,6 +3137,15 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spinning"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d4f0e86297cad2658d92a707320d87bf4e6ae1050287f51d19b67ef3f153a7b"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spirv"
|
name = "spirv"
|
||||||
version = "0.3.0+sdk-1.3.268.0"
|
version = "0.3.0+sdk-1.3.268.0"
|
||||||
@@ -3258,6 +3309,12 @@ dependencies = [
|
|||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "to_method"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.7.3"
|
version = "0.7.3"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rlogg"
|
name = "rlogg"
|
||||||
version = "0.4.0"
|
version = "0.4.1"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
authors = ["Stanislav Pastushenko <staspast1@gmail.com>"]
|
authors = ["Stanislav Pastushenko <staspast1@gmail.com>"]
|
||||||
description = "A fast log file viewer with search, filtering, and highlighting capabilities"
|
description = "A fast log file viewer with search, filtering, and highlighting capabilities"
|
||||||
@@ -19,6 +19,7 @@ serde_json = "1.0"
|
|||||||
rayon = "1.10"
|
rayon = "1.10"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
clap = { version = "4.5", features = ["derive"] }
|
clap = { version = "4.5", features = ["derive"] }
|
||||||
|
interprocess = "1.2.1"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = false
|
debug = false
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
# Build script for creating release binaries for Windows
|
|
||||||
# PowerShell script for Windows users
|
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
|
||||||
|
|
||||||
Write-Host "RLogg - Multi-platform Release Builder (Windows)" -ForegroundColor Cyan
|
|
||||||
Write-Host "=" * 50 -ForegroundColor Cyan
|
|
||||||
Write-Host ""
|
|
||||||
|
|
||||||
# Create dist directory
|
|
||||||
$DistDir = "dist"
|
|
||||||
if (-not (Test-Path $DistDir)) {
|
|
||||||
New-Item -ItemType Directory -Path $DistDir | Out-Null
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to build for a target
|
|
||||||
function Build-Target {
|
|
||||||
param (
|
|
||||||
[string]$Target,
|
|
||||||
[string]$Name
|
|
||||||
)
|
|
||||||
|
|
||||||
Write-Host "Building for $Name ($Target)..." -ForegroundColor Yellow
|
|
||||||
|
|
||||||
try {
|
|
||||||
cargo build --release --target $Target
|
|
||||||
|
|
||||||
if ($LASTEXITCODE -eq 0) {
|
|
||||||
Write-Host "✓ Build successful for $Name" -ForegroundColor Green
|
|
||||||
|
|
||||||
# Copy binary to dist directory
|
|
||||||
if ($Target -like "*windows*") {
|
|
||||||
$SourcePath = "target\$Target\release\rlogg.exe"
|
|
||||||
$DestPath = "$DistDir\rlogg-$Name.exe"
|
|
||||||
} else {
|
|
||||||
$SourcePath = "target\$Target\release\rlogg"
|
|
||||||
$DestPath = "$DistDir\rlogg-$Name"
|
|
||||||
}
|
|
||||||
|
|
||||||
Copy-Item $SourcePath $DestPath -Force
|
|
||||||
Write-Host "✓ Binary copied to $DestPath" -ForegroundColor Green
|
|
||||||
Write-Host ""
|
|
||||||
return $true
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
Write-Host "✗ Build failed for $Name" -ForegroundColor Red
|
|
||||||
Write-Host $_.Exception.Message -ForegroundColor Red
|
|
||||||
Write-Host ""
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build for Windows
|
|
||||||
Write-Host "=== Building for Windows ===" -ForegroundColor Cyan
|
|
||||||
$success = Build-Target "x86_64-pc-windows-msvc" "windows-x86_64"
|
|
||||||
|
|
||||||
if ($success) {
|
|
||||||
Write-Host ""
|
|
||||||
Write-Host "=== Build Complete ===" -ForegroundColor Green
|
|
||||||
Write-Host "Binaries are in the '$DistDir' directory:" -ForegroundColor Green
|
|
||||||
Get-ChildItem $DistDir | Format-Table Name, Length, LastWriteTime
|
|
||||||
Write-Host ""
|
|
||||||
Write-Host "To build for additional platforms, install the target and run:"
|
|
||||||
Write-Host " rustup target add <target-triple>"
|
|
||||||
Write-Host " cargo build --release --target <target-triple>"
|
|
||||||
} else {
|
|
||||||
Write-Host ""
|
|
||||||
Write-Host "Build failed!" -ForegroundColor Red
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Build script for creating release binaries for all platforms
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "RLogg - Multi-platform Release Builder"
|
|
||||||
echo "======================================"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# Extract version from Cargo.toml
|
|
||||||
VERSION=$(grep -m1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/')
|
|
||||||
echo "Version: $VERSION"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Create dist directory
|
|
||||||
DIST_DIR="dist"
|
|
||||||
mkdir -p "$DIST_DIR"
|
|
||||||
|
|
||||||
# Function to build for a target
|
|
||||||
build_target() {
|
|
||||||
local target=$1
|
|
||||||
local name=$2
|
|
||||||
|
|
||||||
echo -e "${YELLOW}Building for $name ($target)...${NC}"
|
|
||||||
|
|
||||||
if cargo build --release --target "$target"; then
|
|
||||||
echo -e "${GREEN}✓ Build successful for $name${NC}"
|
|
||||||
|
|
||||||
# Copy binary to dist directory with version
|
|
||||||
if [[ "$target" == *"windows"* ]]; then
|
|
||||||
cp "target/$target/release/rlogg.exe" "$DIST_DIR/rlogg-$VERSION-$name.exe"
|
|
||||||
echo -e "${GREEN}✓ Binary copied to $DIST_DIR/rlogg-$VERSION-$name.exe${NC}"
|
|
||||||
else
|
|
||||||
cp "target/$target/release/rlogg" "$DIST_DIR/rlogg-$VERSION-$name"
|
|
||||||
# Strip binary on Unix-like systems
|
|
||||||
strip "$DIST_DIR/rlogg-$VERSION-$name" 2>/dev/null || true
|
|
||||||
echo -e "${GREEN}✓ Binary copied to $DIST_DIR/rlogg-$VERSION-$name${NC}"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
echo -e "${RED}✗ Build failed for $name${NC}"
|
|
||||||
echo ""
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Detect current platform
|
|
||||||
PLATFORM=$(uname -s)
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
|
|
||||||
echo "Current platform: $PLATFORM ($ARCH)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Build for current platform first
|
|
||||||
case "$PLATFORM" in
|
|
||||||
Linux)
|
|
||||||
echo "=== Building for Linux ==="
|
|
||||||
build_target "x86_64-unknown-linux-gnu" "linux-x86_64"
|
|
||||||
;;
|
|
||||||
Darwin)
|
|
||||||
echo "=== Building for macOS ==="
|
|
||||||
if [[ "$ARCH" == "arm64" ]]; then
|
|
||||||
build_target "aarch64-apple-darwin" "macos-aarch64"
|
|
||||||
else
|
|
||||||
build_target "x86_64-apple-darwin" "macos-x86_64"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
MINGW* | MSYS* | CYGWIN*)
|
|
||||||
echo "=== Building for Windows ==="
|
|
||||||
build_target "x86_64-pc-windows-msvc" "windows-x86_64"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo -e "${RED}Unknown platform: $PLATFORM${NC}"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo -e "${GREEN}=== Build Complete ===${NC}"
|
|
||||||
echo "Binaries are in the '$DIST_DIR' directory:"
|
|
||||||
ls -lh "$DIST_DIR"
|
|
||||||
echo ""
|
|
||||||
echo "To build for additional platforms, install the target and run:"
|
|
||||||
echo " rustup target add <target-triple>"
|
|
||||||
echo " cargo build --release --target <target-triple>"
|
|
||||||
82
build.sh
Executable file
82
build.sh
Executable file
@@ -0,0 +1,82 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Unified build script for RLogg
|
||||||
|
# Usage: ./build.sh [linux|windows]
|
||||||
|
# If no argument is provided, builds for both Linux and Windows.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
DIST_DIR="dist"
|
||||||
|
VERSION=$(grep -m1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/')
|
||||||
|
LINUX_TARGET="x86_64-unknown-linux-gnu"
|
||||||
|
WINDOWS_TARGET="x86_64-pc-windows-gnu"
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo "RLogg Builder v$VERSION"
|
||||||
|
echo "======================"
|
||||||
|
mkdir -p "$DIST_DIR"
|
||||||
|
|
||||||
|
check_cross() {
|
||||||
|
if ! command -v cross &> /dev/null; then
|
||||||
|
echo -e "${YELLOW}Installing 'cross' for cross-compilation...${NC}"
|
||||||
|
cargo install cross --git https://github.com/cross-rs/cross
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
build_linux() {
|
||||||
|
echo -e "${BLUE}=== Building for Linux ($LINUX_TARGET) ===${NC}"
|
||||||
|
if cargo build --release --target "$LINUX_TARGET"; then
|
||||||
|
cp "target/$LINUX_TARGET/release/rlogg" "$DIST_DIR/rlogg-$VERSION-linux-x86_64"
|
||||||
|
strip "$DIST_DIR/rlogg-$VERSION-linux-x86_64" 2>/dev/null || true
|
||||||
|
echo -e "${GREEN}✓ Linux build success: $DIST_DIR/rlogg-$VERSION-linux-x86_64${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Linux build failed${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
build_windows() {
|
||||||
|
echo -e "${BLUE}=== Building for Windows ($WINDOWS_TARGET) ===${NC}"
|
||||||
|
check_cross
|
||||||
|
|
||||||
|
# Clean specific target to avoid conflicts
|
||||||
|
# cargo clean --release --target "$WINDOWS_TARGET" 2>/dev/null || true
|
||||||
|
|
||||||
|
if cross build --release --target "$WINDOWS_TARGET"; then
|
||||||
|
cp "target/$WINDOWS_TARGET/release/rlogg.exe" "$DIST_DIR/rlogg-$VERSION-windows-x86_64.exe"
|
||||||
|
echo -e "${GREEN}✓ Windows build success: $DIST_DIR/rlogg-$VERSION-windows-x86_64.exe${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Windows build failed${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main logic
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
echo "No target specified, building for ALL platforms..."
|
||||||
|
build_linux
|
||||||
|
build_windows
|
||||||
|
else
|
||||||
|
case "$1" in
|
||||||
|
linux)
|
||||||
|
build_linux
|
||||||
|
;;
|
||||||
|
windows|win)
|
||||||
|
build_windows
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 [linux|windows]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}Build process completed.${NC}"
|
||||||
|
ls -lh "$DIST_DIR"
|
||||||
161
cross-compile.sh
161
cross-compile.sh
@@ -1,161 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Cross-compilation script for building Windows binaries on Linux
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "RLogg - Cross-Platform Builder (Linux → All Platforms)"
|
|
||||||
echo "======================================================="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Colors
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# Extract version from Cargo.toml
|
|
||||||
VERSION=$(grep -m1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/')
|
|
||||||
echo "Version: $VERSION"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Create dist directory
|
|
||||||
DIST_DIR="dist"
|
|
||||||
mkdir -p "$DIST_DIR"
|
|
||||||
|
|
||||||
# Check if cross is installed
|
|
||||||
check_cross() {
|
|
||||||
if ! command -v cross &> /dev/null; then
|
|
||||||
echo -e "${YELLOW}Installing 'cross' for cross-compilation...${NC}"
|
|
||||||
cargo install cross --git https://github.com/cross-rs/cross
|
|
||||||
else
|
|
||||||
echo -e "${GREEN}✓ 'cross' is already installed${NC}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build using cross
|
|
||||||
build_with_cross() {
|
|
||||||
local target=$1
|
|
||||||
local name=$2
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo -e "${BLUE}=== Building for $name ===${NC}"
|
|
||||||
echo -e "${YELLOW}Target: $target${NC}"
|
|
||||||
|
|
||||||
# Clean build artifacts to avoid GLIBC mismatch with build scripts
|
|
||||||
echo -e "${YELLOW}Cleaning build artifacts...${NC}"
|
|
||||||
cargo clean --release --target "$target"
|
|
||||||
|
|
||||||
if cross build --release --target "$target"; then
|
|
||||||
echo -e "${GREEN}✓ Build successful for $name${NC}"
|
|
||||||
|
|
||||||
# Copy binary to dist directory with version
|
|
||||||
if [[ "$target" == *"windows"* ]]; then
|
|
||||||
cp "target/$target/release/rlogg.exe" "$DIST_DIR/rlogg-$VERSION-$name.exe"
|
|
||||||
echo -e "${GREEN}✓ Binary: $DIST_DIR/rlogg-$VERSION-$name.exe${NC}"
|
|
||||||
else
|
|
||||||
cp "target/$target/release/rlogg" "$DIST_DIR/rlogg-$VERSION-$name"
|
|
||||||
strip "$DIST_DIR/rlogg-$VERSION-$name" 2>/dev/null || true
|
|
||||||
echo -e "${GREEN}✓ Binary: $DIST_DIR/rlogg-$VERSION-$name${NC}"
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
echo -e "${RED}✗ Build failed for $name${NC}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build using regular cargo (for native Linux)
|
|
||||||
build_native() {
|
|
||||||
echo ""
|
|
||||||
echo -e "${BLUE}=== Building for Linux (native) ===${NC}"
|
|
||||||
|
|
||||||
if cargo build --release; then
|
|
||||||
echo -e "${GREEN}✓ Build successful for Linux${NC}"
|
|
||||||
cp "target/release/rlogg" "$DIST_DIR/rlogg-$VERSION-linux-x86_64"
|
|
||||||
strip "$DIST_DIR/rlogg-$VERSION-linux-x86_64" 2>/dev/null || true
|
|
||||||
echo -e "${GREEN}✓ Binary: $DIST_DIR/rlogg-$VERSION-linux-x86_64${NC}"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
echo -e "${RED}✗ Build failed for Linux${NC}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main menu
|
|
||||||
show_menu() {
|
|
||||||
echo ""
|
|
||||||
echo "Select targets to build:"
|
|
||||||
echo " 1) Linux x86_64 (native)"
|
|
||||||
echo " 2) Windows x86_64 (cross-compile with MinGW)"
|
|
||||||
echo " 3) Both Linux and Windows"
|
|
||||||
echo " 4) Exit"
|
|
||||||
echo ""
|
|
||||||
read -p "Enter choice [1-4]: " choice
|
|
||||||
echo ""
|
|
||||||
}
|
|
||||||
|
|
||||||
# Parse command line arguments
|
|
||||||
if [ $# -eq 0 ]; then
|
|
||||||
# Interactive mode
|
|
||||||
while true; do
|
|
||||||
show_menu
|
|
||||||
|
|
||||||
case $choice in
|
|
||||||
1)
|
|
||||||
build_native
|
|
||||||
;;
|
|
||||||
2)
|
|
||||||
check_cross
|
|
||||||
build_with_cross "x86_64-pc-windows-gnu" "windows-x86_64"
|
|
||||||
;;
|
|
||||||
3)
|
|
||||||
build_native
|
|
||||||
check_cross
|
|
||||||
build_with_cross "x86_64-pc-windows-gnu" "windows-x86_64"
|
|
||||||
;;
|
|
||||||
4)
|
|
||||||
echo "Exiting..."
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo -e "${RED}Invalid choice${NC}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
else
|
|
||||||
# Command line mode
|
|
||||||
case "$1" in
|
|
||||||
linux)
|
|
||||||
build_native
|
|
||||||
;;
|
|
||||||
windows|win)
|
|
||||||
check_cross
|
|
||||||
build_with_cross "x86_64-pc-windows-gnu" "windows-x86_64"
|
|
||||||
;;
|
|
||||||
all)
|
|
||||||
build_native
|
|
||||||
check_cross
|
|
||||||
build_with_cross "x86_64-pc-windows-gnu" "windows-x86_64"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Usage: $0 [linux|windows|all]"
|
|
||||||
echo ""
|
|
||||||
echo " linux - Build for Linux (native)"
|
|
||||||
echo " windows - Cross-compile for Windows (MinGW)"
|
|
||||||
echo " all - Build for both platforms"
|
|
||||||
echo ""
|
|
||||||
echo "Or run without arguments for interactive mode"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo -e "${GREEN}=== Build Complete ===${NC}"
|
|
||||||
if [ -d "$DIST_DIR" ] && [ "$(ls -A $DIST_DIR)" ]; then
|
|
||||||
echo "Binaries in '$DIST_DIR':"
|
|
||||||
ls -lh "$DIST_DIR"
|
|
||||||
else
|
|
||||||
echo "No binaries were built"
|
|
||||||
fi
|
|
||||||
301
packaging/README.md
Normal file
301
packaging/README.md
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
# Packaging Guide
|
||||||
|
|
||||||
|
This directory contains packaging files and installation scripts for RLogg on different platforms.
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
packaging/
|
||||||
|
├── linux/
|
||||||
|
│ ├── rlogg.desktop # XDG desktop entry file
|
||||||
|
│ ├── text-x-log.xml # MIME type definition for .log files
|
||||||
|
│ └── install.sh # Linux installation script
|
||||||
|
├── windows/
|
||||||
|
│ ├── file-association.reg # Windows registry file for manual setup
|
||||||
|
│ └── install.ps1 # PowerShell installation script
|
||||||
|
└── README.md # This file
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building for Distribution
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
1. **Build the release binary:**
|
||||||
|
```bash
|
||||||
|
cargo build --release
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Test the installation script:**
|
||||||
|
```bash
|
||||||
|
cd packaging/linux
|
||||||
|
./install.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Create a distribution package:**
|
||||||
|
```bash
|
||||||
|
# Create a tarball
|
||||||
|
cd target/release
|
||||||
|
tar -czf rlogg-linux-x64.tar.gz rlogg ../../packaging/linux/*
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
1. **Build the release binary:**
|
||||||
|
```powershell
|
||||||
|
cargo build --release
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Test the installation script:**
|
||||||
|
```powershell
|
||||||
|
cd packaging\windows
|
||||||
|
powershell -ExecutionPolicy Bypass -File install.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Create a distribution package:**
|
||||||
|
```powershell
|
||||||
|
# Create a ZIP file
|
||||||
|
Compress-Archive -Path target\release\rlogg.exe, packaging\windows\* -DestinationPath rlogg-windows-x64.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
## Distribution Packages
|
||||||
|
|
||||||
|
### Linux Packages
|
||||||
|
|
||||||
|
#### DEB Package (Debian/Ubuntu)
|
||||||
|
|
||||||
|
Create a `debian/` directory structure for building `.deb` packages:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p debian/usr/local/bin
|
||||||
|
mkdir -p debian/usr/share/applications
|
||||||
|
mkdir -p debian/usr/share/mime/packages
|
||||||
|
|
||||||
|
cp target/release/rlogg debian/usr/local/bin/
|
||||||
|
cp packaging/linux/rlogg.desktop debian/usr/share/applications/
|
||||||
|
cp packaging/linux/text-x-log.xml debian/usr/share/mime/packages/
|
||||||
|
|
||||||
|
# Create DEBIAN control file
|
||||||
|
mkdir -p debian/DEBIAN
|
||||||
|
cat > debian/DEBIAN/control <<EOF
|
||||||
|
Package: rlogg
|
||||||
|
Version: 0.3.1
|
||||||
|
Section: utils
|
||||||
|
Priority: optional
|
||||||
|
Architecture: amd64
|
||||||
|
Maintainer: Your Name <your.email@example.com>
|
||||||
|
Description: Fast log file viewer
|
||||||
|
A fast log file viewer with search, filtering, and highlighting capabilities
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Build the package
|
||||||
|
dpkg-deb --build debian rlogg_0.3.1_amd64.deb
|
||||||
|
```
|
||||||
|
|
||||||
|
#### AppImage
|
||||||
|
|
||||||
|
For universal Linux distribution:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install linuxdeploy
|
||||||
|
wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
|
||||||
|
chmod +x linuxdeploy-x86_64.AppImage
|
||||||
|
|
||||||
|
# Create AppDir structure
|
||||||
|
mkdir -p AppDir/usr/bin
|
||||||
|
mkdir -p AppDir/usr/share/applications
|
||||||
|
mkdir -p AppDir/usr/share/mime/packages
|
||||||
|
|
||||||
|
cp target/release/rlogg AppDir/usr/bin/
|
||||||
|
cp packaging/linux/rlogg.desktop AppDir/usr/share/applications/
|
||||||
|
cp packaging/linux/text-x-log.xml AppDir/usr/share/mime/packages/
|
||||||
|
|
||||||
|
# Build AppImage
|
||||||
|
./linuxdeploy-x86_64.AppImage --appdir AppDir --output appimage
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows Packages
|
||||||
|
|
||||||
|
#### NSIS Installer
|
||||||
|
|
||||||
|
Install NSIS and create an installer script:
|
||||||
|
|
||||||
|
```nsis
|
||||||
|
!define APPNAME "RLogg"
|
||||||
|
!define COMPANYNAME "Your Company"
|
||||||
|
!define DESCRIPTION "Fast log file viewer"
|
||||||
|
!define VERSIONMAJOR 0
|
||||||
|
!define VERSIONMINOR 3
|
||||||
|
!define VERSIONBUILD 1
|
||||||
|
|
||||||
|
RequestExecutionLevel user
|
||||||
|
|
||||||
|
Name "${APPNAME}"
|
||||||
|
Icon "path\to\icon.ico"
|
||||||
|
OutFile "rlogg-setup.exe"
|
||||||
|
InstallDir "$LOCALAPPDATA\Programs\${APPNAME}"
|
||||||
|
|
||||||
|
Section "Install"
|
||||||
|
SetOutPath $INSTDIR
|
||||||
|
File "target\release\rlogg.exe"
|
||||||
|
|
||||||
|
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||||
|
|
||||||
|
# Create file association
|
||||||
|
WriteRegStr HKCU "Software\Classes\.log" "" "RLogg.LogFile"
|
||||||
|
WriteRegStr HKCU "Software\Classes\RLogg.LogFile\shell\open\command" "" '"$INSTDIR\rlogg.exe" "%1"'
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Uninstall"
|
||||||
|
Delete "$INSTDIR\rlogg.exe"
|
||||||
|
Delete "$INSTDIR\Uninstall.exe"
|
||||||
|
RMDir "$INSTDIR"
|
||||||
|
|
||||||
|
DeleteRegKey HKCU "Software\Classes\.log"
|
||||||
|
DeleteRegKey HKCU "Software\Classes\RLogg.LogFile"
|
||||||
|
SectionEnd
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing File Associations
|
||||||
|
|
||||||
|
### Linux Testing
|
||||||
|
|
||||||
|
1. **Create a test log file:**
|
||||||
|
```bash
|
||||||
|
echo "Test log entry" > /tmp/test.log
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Test command-line opening:**
|
||||||
|
```bash
|
||||||
|
rlogg /tmp/test.log
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Test XDG opening:**
|
||||||
|
```bash
|
||||||
|
xdg-open /tmp/test.log
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Test in file manager:**
|
||||||
|
- Navigate to `/tmp/` in your file manager
|
||||||
|
- Double-click `test.log`
|
||||||
|
- Right-click → Open With → RLogg
|
||||||
|
|
||||||
|
5. **Test multiple files:**
|
||||||
|
```bash
|
||||||
|
echo "Log 1" > /tmp/test1.log
|
||||||
|
echo "Log 2" > /tmp/test2.log
|
||||||
|
rlogg /tmp/test1.log /tmp/test2.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows Testing
|
||||||
|
|
||||||
|
1. **Create a test log file:**
|
||||||
|
```powershell
|
||||||
|
"Test log entry" | Out-File -FilePath "$env:TEMP\test.log"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Test command-line opening:**
|
||||||
|
```powershell
|
||||||
|
& "$env:LOCALAPPDATA\Programs\RLogg\rlogg.exe" "$env:TEMP\test.log"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Test in File Explorer:**
|
||||||
|
- Open File Explorer
|
||||||
|
- Navigate to `%TEMP%`
|
||||||
|
- Double-click `test.log`
|
||||||
|
- Right-click → Open with → RLogg
|
||||||
|
|
||||||
|
4. **Test multiple files:**
|
||||||
|
```powershell
|
||||||
|
"Log 1" | Out-File -FilePath "$env:TEMP\test1.log"
|
||||||
|
"Log 2" | Out-File -FilePath "$env:TEMP\test2.log"
|
||||||
|
& "$env:LOCALAPPDATA\Programs\RLogg\rlogg.exe" "$env:TEMP\test1.log" "$env:TEMP\test2.log"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Platform-Specific Notes
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
- **Desktop environments tested:**
|
||||||
|
- GNOME 40+
|
||||||
|
- KDE Plasma 5.20+
|
||||||
|
- XFCE 4.16+
|
||||||
|
- i3/sway (via xdg-utils)
|
||||||
|
|
||||||
|
- **Dependencies:**
|
||||||
|
- `xdg-utils` for `update-desktop-database` and `update-mime-database`
|
||||||
|
- Usually pre-installed on most distributions
|
||||||
|
|
||||||
|
- **Wayland compatibility:**
|
||||||
|
- Tested and working on Wayland sessions
|
||||||
|
- File associations work the same as X11
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
- **Tested on:**
|
||||||
|
- Windows 10 (version 1909+)
|
||||||
|
- Windows 11
|
||||||
|
|
||||||
|
- **Registry location:**
|
||||||
|
- User-local: `HKEY_CURRENT_USER\Software\Classes\`
|
||||||
|
- No admin rights required
|
||||||
|
|
||||||
|
- **Antivirus:**
|
||||||
|
- Some antivirus software may flag unsigned executables
|
||||||
|
- Consider code signing for production releases
|
||||||
|
|
||||||
|
## CI/CD Integration
|
||||||
|
|
||||||
|
### GitHub Actions Example
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Build and Package
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Build
|
||||||
|
run: cargo build --release
|
||||||
|
- name: Package
|
||||||
|
run: |
|
||||||
|
cd target/release
|
||||||
|
tar -czf rlogg-linux-x64.tar.gz rlogg ../../packaging/linux/*
|
||||||
|
- name: Upload
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: rlogg-linux
|
||||||
|
path: target/release/rlogg-linux-x64.tar.gz
|
||||||
|
|
||||||
|
build-windows:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Build
|
||||||
|
run: cargo build --release
|
||||||
|
- name: Package
|
||||||
|
run: |
|
||||||
|
Compress-Archive -Path target\release\rlogg.exe, packaging\windows\* -DestinationPath rlogg-windows-x64.zip
|
||||||
|
- name: Upload
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: rlogg-windows
|
||||||
|
path: rlogg-windows-x64.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
See [docs/FILE_ASSOCIATIONS.md](../docs/FILE_ASSOCIATIONS.md) for detailed troubleshooting guides.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
When adding new packaging formats or improving existing ones:
|
||||||
|
|
||||||
|
1. Test on the target platform
|
||||||
|
2. Update this README with clear instructions
|
||||||
|
3. Add troubleshooting steps if needed
|
||||||
|
4. Submit a pull request with test results
|
||||||
78
packaging/linux/install.sh
Executable file
78
packaging/linux/install.sh
Executable file
@@ -0,0 +1,78 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Install rlogg and create file association for .log files
|
||||||
|
# This script installs to user-local directories (~/.local/) and does not require sudo
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "Installing RLogg Log Viewer..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Determine the directory where this script is located
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
# Check if rlogg binary exists
|
||||||
|
if [ ! -f "$SCRIPT_DIR/../../target/release/rlogg" ]; then
|
||||||
|
echo "Error: rlogg binary not found at $SCRIPT_DIR/../../target/release/rlogg"
|
||||||
|
echo "Please build the project first with: cargo build --release"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# User-local installation (no sudo required)
|
||||||
|
echo "Installing binary to ~/.local/bin/..."
|
||||||
|
mkdir -p ~/.local/bin
|
||||||
|
cp "$SCRIPT_DIR/../../target/release/rlogg" ~/.local/bin/
|
||||||
|
chmod +x ~/.local/bin/rlogg
|
||||||
|
|
||||||
|
# Install desktop file with correct path
|
||||||
|
echo "Installing desktop file..."
|
||||||
|
mkdir -p ~/.local/share/applications
|
||||||
|
|
||||||
|
# Create desktop file with absolute path to the binary
|
||||||
|
cat > ~/.local/share/applications/rlogg.desktop <<EOF
|
||||||
|
[Desktop Entry]
|
||||||
|
Version=1.0
|
||||||
|
Type=Application
|
||||||
|
Name=RLogg
|
||||||
|
GenericName=Log Viewer
|
||||||
|
Comment=Fast log file viewer with search, filtering, and highlighting
|
||||||
|
Exec=$HOME/.local/bin/rlogg %F
|
||||||
|
Icon=rlogg
|
||||||
|
Terminal=false
|
||||||
|
Categories=Development;Utility;
|
||||||
|
MimeType=text/x-log;
|
||||||
|
Keywords=log;viewer;search;filter;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Update MIME database
|
||||||
|
echo "Installing MIME type definition..."
|
||||||
|
mkdir -p ~/.local/share/mime/packages
|
||||||
|
cp "$SCRIPT_DIR/text-x-log.xml" ~/.local/share/mime/packages/
|
||||||
|
|
||||||
|
# Update desktop and MIME databases
|
||||||
|
echo "Updating databases..."
|
||||||
|
if command -v update-desktop-database &> /dev/null; then
|
||||||
|
update-desktop-database ~/.local/share/applications 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v update-mime-database &> /dev/null; then
|
||||||
|
update-mime-database ~/.local/share/mime 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Installation complete!"
|
||||||
|
echo ""
|
||||||
|
echo "RLogg has been installed to: ~/.local/bin/rlogg"
|
||||||
|
echo ""
|
||||||
|
echo "IMPORTANT: Make sure ~/.local/bin is in your PATH."
|
||||||
|
echo "Add this line to your ~/.bashrc or ~/.zshrc if it's not already there:"
|
||||||
|
echo ' export PATH="$HOME/.local/bin:$PATH"'
|
||||||
|
echo ""
|
||||||
|
echo "File associations have been configured for .log files."
|
||||||
|
echo "You may need to log out and log back in for file associations to take effect."
|
||||||
|
echo ""
|
||||||
|
echo "To uninstall, run:"
|
||||||
|
echo " rm ~/.local/bin/rlogg"
|
||||||
|
echo " rm ~/.local/share/applications/rlogg.desktop"
|
||||||
|
echo " rm ~/.local/share/mime/packages/text-x-log.xml"
|
||||||
|
echo " update-desktop-database ~/.local/share/applications"
|
||||||
|
echo " update-mime-database ~/.local/share/mime"
|
||||||
14
packaging/linux/rlogg.desktop
Normal file
14
packaging/linux/rlogg.desktop
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Version=1.0
|
||||||
|
Type=Application
|
||||||
|
Name=RLogg
|
||||||
|
GenericName=Log Viewer
|
||||||
|
Comment=Fast log file viewer with search, filtering, and highlighting
|
||||||
|
# NOTE: Use absolute path for Exec to work in GUI file managers
|
||||||
|
# The install.sh script will automatically set this to $HOME/.local/bin/rlogg
|
||||||
|
Exec=/usr/local/bin/rlogg %F
|
||||||
|
Icon=rlogg
|
||||||
|
Terminal=false
|
||||||
|
Categories=Development;Utility;
|
||||||
|
MimeType=text/x-log;
|
||||||
|
Keywords=log;viewer;search;filter;
|
||||||
7
packaging/linux/text-x-log.xml
Normal file
7
packaging/linux/text-x-log.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||||
|
<mime-type type="text/x-log">
|
||||||
|
<comment>Log file</comment>
|
||||||
|
<glob pattern="*.log"/>
|
||||||
|
</mime-type>
|
||||||
|
</mime-info>
|
||||||
19
packaging/windows/file-association.reg
Normal file
19
packaging/windows/file-association.reg
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
Windows Registry Editor Version 5.00
|
||||||
|
|
||||||
|
; Associate .log files with RLogg
|
||||||
|
; Edit the path below if you installed RLogg to a different location
|
||||||
|
|
||||||
|
[HKEY_CURRENT_USER\Software\Classes\.log]
|
||||||
|
@="RLogg.LogFile"
|
||||||
|
|
||||||
|
[HKEY_CURRENT_USER\Software\Classes\RLogg.LogFile]
|
||||||
|
@="Log File"
|
||||||
|
|
||||||
|
[HKEY_CURRENT_USER\Software\Classes\RLogg.LogFile\DefaultIcon]
|
||||||
|
@="\"C:\\Program Files\\RLogg\\rlogg.exe\",0"
|
||||||
|
|
||||||
|
[HKEY_CURRENT_USER\Software\Classes\RLogg.LogFile\shell\open\command]
|
||||||
|
@="\"C:\\Program Files\\RLogg\\rlogg.exe\" \"%1\""
|
||||||
|
|
||||||
|
[HKEY_CURRENT_USER\Software\Classes\RLogg.LogFile\shell\open]
|
||||||
|
@="Open with RLogg"
|
||||||
63
packaging/windows/install.ps1
Normal file
63
packaging/windows/install.ps1
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# RLogg Installation Script for Windows
|
||||||
|
# Run with: powershell -ExecutionPolicy Bypass -File install.ps1
|
||||||
|
|
||||||
|
param(
|
||||||
|
[string]$InstallPath = "$env:LOCALAPPDATA\Programs\RLogg"
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Host "Installing RLogg Log Viewer..." -ForegroundColor Cyan
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
# Determine the directory where this script is located
|
||||||
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
$BinaryPath = Join-Path (Split-Path (Split-Path $ScriptDir -Parent) -Parent) "target\release\rlogg.exe"
|
||||||
|
|
||||||
|
# Check if rlogg.exe exists
|
||||||
|
if (-not (Test-Path $BinaryPath)) {
|
||||||
|
Write-Host "Error: rlogg.exe not found at $BinaryPath" -ForegroundColor Red
|
||||||
|
Write-Host "Please build the project first with: cargo build --release" -ForegroundColor Yellow
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create directory
|
||||||
|
Write-Host "Installing binary to $InstallPath..." -ForegroundColor Green
|
||||||
|
New-Item -ItemType Directory -Force -Path $InstallPath | Out-Null
|
||||||
|
|
||||||
|
# Copy binary
|
||||||
|
Copy-Item $BinaryPath $InstallPath\
|
||||||
|
|
||||||
|
# Create registry entries for .log file association
|
||||||
|
Write-Host "Configuring file associations..." -ForegroundColor Green
|
||||||
|
|
||||||
|
$regPath = "HKCU:\Software\Classes\.log"
|
||||||
|
New-Item -Path $regPath -Force | Out-Null
|
||||||
|
Set-ItemProperty -Path $regPath -Name "(default)" -Value "RLogg.LogFile"
|
||||||
|
|
||||||
|
$regPath = "HKCU:\Software\Classes\RLogg.LogFile"
|
||||||
|
New-Item -Path $regPath -Force | Out-Null
|
||||||
|
Set-ItemProperty -Path $regPath -Name "(default)" -Value "Log File"
|
||||||
|
|
||||||
|
$regPath = "HKCU:\Software\Classes\RLogg.LogFile\DefaultIcon"
|
||||||
|
New-Item -Path $regPath -Force | Out-Null
|
||||||
|
Set-ItemProperty -Path $regPath -Name "(default)" -Value "`"$InstallPath\rlogg.exe`",0"
|
||||||
|
|
||||||
|
$regPath = "HKCU:\Software\Classes\RLogg.LogFile\shell\open\command"
|
||||||
|
New-Item -Path $regPath -Force | Out-Null
|
||||||
|
Set-ItemProperty -Path $regPath -Name "(default)" -Value "`"$InstallPath\rlogg.exe`" `"%1`""
|
||||||
|
|
||||||
|
$regPath = "HKCU:\Software\Classes\RLogg.LogFile\shell\open"
|
||||||
|
New-Item -Path $regPath -Force | Out-Null
|
||||||
|
Set-ItemProperty -Path $regPath -Name "(default)" -Value "Open with RLogg"
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Installation complete!" -ForegroundColor Green
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "RLogg is installed at: $InstallPath\rlogg.exe" -ForegroundColor Cyan
|
||||||
|
Write-Host "File associations have been configured for .log files." -ForegroundColor Cyan
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "You can now double-click .log files to open them in RLogg." -ForegroundColor Yellow
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "To uninstall, run:" -ForegroundColor Yellow
|
||||||
|
Write-Host " Remove-Item -Recurse `"$InstallPath`"" -ForegroundColor Gray
|
||||||
|
Write-Host " Remove-Item -Recurse HKCU:\Software\Classes\.log" -ForegroundColor Gray
|
||||||
|
Write-Host " Remove-Item -Recurse HKCU:\Software\Classes\RLogg.LogFile" -ForegroundColor Gray
|
||||||
@@ -18,6 +18,7 @@ pub struct LogViewerApp {
|
|||||||
highlight_manager: HighlightManager,
|
highlight_manager: HighlightManager,
|
||||||
first_frame: bool,
|
first_frame: bool,
|
||||||
file_open_errors: Vec<String>,
|
file_open_errors: Vec<String>,
|
||||||
|
file_receiver: Option<std::sync::mpsc::Receiver<Vec<PathBuf>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct KeyAction {
|
struct KeyAction {
|
||||||
@@ -36,7 +37,7 @@ impl KeyAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LogViewerApp {
|
impl LogViewerApp {
|
||||||
pub fn new(config: AppConfig, initial_files: Vec<PathBuf>) -> Self {
|
pub fn new(config: AppConfig, initial_files: Vec<PathBuf>, file_receiver: Option<std::sync::mpsc::Receiver<Vec<PathBuf>>>) -> Self {
|
||||||
let indexing_state = IndexingState::new();
|
let indexing_state = IndexingState::new();
|
||||||
let mut tabs = Vec::new();
|
let mut tabs = Vec::new();
|
||||||
let mut file_open_errors = Vec::new();
|
let mut file_open_errors = Vec::new();
|
||||||
@@ -76,6 +77,7 @@ impl LogViewerApp {
|
|||||||
highlight_manager: HighlightManager::new(config.highlight_rules),
|
highlight_manager: HighlightManager::new(config.highlight_rules),
|
||||||
first_frame: true,
|
first_frame: true,
|
||||||
file_open_errors,
|
file_open_errors,
|
||||||
|
file_receiver,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,6 +319,35 @@ fn handle_key_inputs(ctx: &egui::Context) -> KeyAction {
|
|||||||
impl eframe::App for LogViewerApp {
|
impl eframe::App for LogViewerApp {
|
||||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||||
|
|
||||||
|
// Poll for new files from other instances
|
||||||
|
if let Some(receiver) = &self.file_receiver {
|
||||||
|
while let Ok(files) = receiver.try_recv() {
|
||||||
|
for file_path in files {
|
||||||
|
if file_path.exists() {
|
||||||
|
if file_path.is_file() {
|
||||||
|
if let Some(tab) = open_file(file_path.clone(), &self.indexing_state) {
|
||||||
|
self.tabs.push(tab);
|
||||||
|
self.active_tab_index = self.tabs.len() - 1;
|
||||||
|
} else {
|
||||||
|
// We probably don't want to disrupt the user with a modal for this background action,
|
||||||
|
// but maybe we could log it or flash a message. For now, let's add it to errors.
|
||||||
|
self.file_open_errors.push(format!("Failed to open: {}", file_path.display()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we received files and opened them, we should request a repaint to show the new tabs immediately
|
||||||
|
ctx.request_repaint();
|
||||||
|
|
||||||
|
// If there were errors, we might want to show the error window again?
|
||||||
|
// The error window logic is in handle_first_frame/update, strictly speaking it only shows if errors exist.
|
||||||
|
// However, handle_first_frame is only called once. We should check if we should show errors here or if the existing logic handles it.
|
||||||
|
// The existing logic checks !self.file_open_errors.is_empty() in handle_first_frame, but checking lines 275-298 reveals
|
||||||
|
// that the window display code is INSIDE handle_first_frame? No, wait.
|
||||||
|
// Let's check handle_first_frame implementation again.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.handle_first_frame(ctx);
|
self.handle_first_frame(ctx);
|
||||||
|
|
||||||
// Update search results if available
|
// Update search results if available
|
||||||
|
|||||||
64
src/main.rs
64
src/main.rs
@@ -18,6 +18,10 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use crate::log_viewer_app::LogViewerApp;
|
use crate::log_viewer_app::LogViewerApp;
|
||||||
use config::AppConfig;
|
use config::AppConfig;
|
||||||
|
use interprocess::local_socket::{LocalSocketListener, LocalSocketStream};
|
||||||
|
use std::io::{prelude::*, BufReader};
|
||||||
|
use std::sync::mpsc;
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(name = "rlogg")]
|
#[command(name = "rlogg")]
|
||||||
@@ -32,6 +36,62 @@ fn main() -> eframe::Result {
|
|||||||
// Parse command-line arguments
|
// Parse command-line arguments
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
|
||||||
|
// Single instance check
|
||||||
|
#[cfg(windows)]
|
||||||
|
let name = "rlogg_ipc";
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
let name = "/tmp/rlogg.sock";
|
||||||
|
|
||||||
|
// Try to connect to existing instance
|
||||||
|
if let Ok(mut conn) = LocalSocketStream::connect(name) {
|
||||||
|
if !cli.files.is_empty() {
|
||||||
|
let files_json = serde_json::to_string(&cli.files).unwrap();
|
||||||
|
if let Err(e) = conn.write_all(files_json.as_bytes()) {
|
||||||
|
eprintln!("Failed to send files to existing instance: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If connection failed, we are the first instance.
|
||||||
|
// Create a listener.
|
||||||
|
// Cleanup socket on Unix
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
if std::path::Path::new(name).exists() {
|
||||||
|
std::fs::remove_file(name).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
let listener = match LocalSocketListener::bind(name) {
|
||||||
|
Ok(l) => l,
|
||||||
|
Err(error) => {
|
||||||
|
eprintln!("Failed to bind to socket: {}", error);
|
||||||
|
// Fallback to running without single-instance support if binding fails
|
||||||
|
return run_app(cli, None);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
for mut conn in listener.incoming().filter_map(|x| x.ok()) {
|
||||||
|
let tx = tx.clone();
|
||||||
|
thread::spawn(move || {
|
||||||
|
let mut reader = BufReader::new(&mut conn);
|
||||||
|
let mut buffer = String::new();
|
||||||
|
// We assume one connection per batch of files, validation is relaxed for simplicity
|
||||||
|
if let Ok(_) = reader.read_to_string(&mut buffer) {
|
||||||
|
if let Ok(files) = serde_json::from_str::<Vec<PathBuf>>(&buffer) {
|
||||||
|
tx.send(files).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
run_app(cli, Some(rx))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_app(cli: Cli, file_receiver: Option<mpsc::Receiver<Vec<PathBuf>>>) -> eframe::Result {
|
||||||
let options = eframe::NativeOptions {
|
let options = eframe::NativeOptions {
|
||||||
viewport: egui::ViewportBuilder::default()
|
viewport: egui::ViewportBuilder::default()
|
||||||
.with_inner_size([1200.0, 800.0])
|
.with_inner_size([1200.0, 800.0])
|
||||||
@@ -49,9 +109,7 @@ fn main() -> eframe::Result {
|
|||||||
options,
|
options,
|
||||||
Box::new(move |cc| {
|
Box::new(move |cc| {
|
||||||
theme::apply_theme(&cc.egui_ctx);
|
theme::apply_theme(&cc.egui_ctx);
|
||||||
Ok(Box::new(LogViewerApp::new(config, initial_files)))
|
Ok(Box::new(LogViewerApp::new(config, initial_files, file_receiver)))
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user