mathcalc-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +150 -0
- package/bin/calculator-linux-x64 +0 -0
- package/bin/calculator_windows-x86-64.exe +0 -0
- package/index.js +40 -0
- package/package.json +41 -0
- package/scripts/build-binaries.js +482 -0
- package/scripts/fix-wsl-build.sh +148 -0
- package/scripts/install.js +265 -0
- package/scripts/postinstall.js +27 -0
- package/scripts/setup-wsl.js +112 -0
- package/scripts/test.js +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Mcas-996
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Calculator CLI
|
|
2
|
+
|
|
3
|
+
A lightweight Rust command-line calculator capable of evaluating real/complex expressions, solving equations (with exact symbolic output up to quintics), and processing small systems of linear equations.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
1. Clone the project: `git clone https://github.com/allen/calculator-cli && cd calculator-cli`.
|
|
8
|
+
2. Build a Release binary: `cargo build --release`.
|
|
9
|
+
3. Run an expression straight from your shell: `./target/release/calculator "x^2-5x+6=0"`.
|
|
10
|
+
|
|
11
|
+
## NPM Installation
|
|
12
|
+
|
|
13
|
+
### For x64 Systems (Windows, macOS Intel, Linux x64)
|
|
14
|
+
The easiest way to install calculator-cli is via npm:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g calculator-cli
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Once installed, you can run:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
calculator "2 + 2"
|
|
24
|
+
calculator "x^2-5x+6=0"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### For ARM Systems (Apple Silicon, ARM64 Linux)
|
|
28
|
+
The npm package includes precompiled binaries only for x64 systems. For ARM systems:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# 1. Install Rust if you haven't already:
|
|
32
|
+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
|
33
|
+
source ~/.cargo/env
|
|
34
|
+
|
|
35
|
+
# 2. Install calculator-cli from source:
|
|
36
|
+
cargo install calculator
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Platform Support
|
|
40
|
+
| Platform | Architecture | Installation Method |
|
|
41
|
+
|----------|-------------|--------------------|
|
|
42
|
+
| Windows | x64 | npm install |
|
|
43
|
+
| macOS | x64 (Intel) | npm install |
|
|
44
|
+
| macOS | ARM (Apple Silicon) | cargo install |
|
|
45
|
+
| Linux | x64 | npm install |
|
|
46
|
+
| Linux | ARM64 | cargo install |
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
### Expression Engine
|
|
51
|
+
- Addition, subtraction, multiplication, division, exponentiation.
|
|
52
|
+
- Percentages (`50% * 200`), parentheses, unary minus.
|
|
53
|
+
- Constants `pi`, `e`, imaginary unit `i`, and decimal or fractional inputs (fractions auto-simplify in output).
|
|
54
|
+
- Square root `sqrt()`, absolute value `abs()`, trigonometric functions in radians `sin()/cos()` and degree variants `sind()/cosd()`.
|
|
55
|
+
- Full complex-number arithmetic, e.g. `sqrt(-4)`, `(3+2i)*(1-i)`, `cosd(60+i)`.
|
|
56
|
+
|
|
57
|
+
### Equation Solving
|
|
58
|
+
- Linear equations: `2x+5=0`
|
|
59
|
+
- Quadratic equations: `x^2-5x+6=0` (real or complex roots)
|
|
60
|
+
- Cubic equations: `x^3-6x^2+11x-6=0`
|
|
61
|
+
- Quartic equations: `x^4-2=0` (symbolic roots via `sqrt`/`cbrt`, numeric Durand–Kerner fallback)
|
|
62
|
+
- Quintic equations: `x^5+2x^4+...=0` → numeric approximation via Durand-Kerner method
|
|
63
|
+
- Systems of linear equations (up to 3 variables): `x+y=5, x-y=1`
|
|
64
|
+
|
|
65
|
+
### Output Formatting
|
|
66
|
+
- Results favor exact fractions when possible (e.g. `1/3` stays rational) and fall back to decimals only when necessary.
|
|
67
|
+
- Complex numbers print as `a + bi`, with simplified `i`/`-i`.
|
|
68
|
+
- Multiple output formats: ASCII, Unicode, and LaTeX.
|
|
69
|
+
|
|
70
|
+
## Usage
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Basic usage (expression as CLI argument)
|
|
74
|
+
./target/release/calculator "3 + 5 * (2 - 8)^2"
|
|
75
|
+
|
|
76
|
+
# Complex numbers
|
|
77
|
+
./target/release/calculator "(3+2i) * (1 - i)"
|
|
78
|
+
./target/release/calculator "sqrt(-9)" # -> 3i
|
|
79
|
+
|
|
80
|
+
# Trigonometry
|
|
81
|
+
./target/release/calculator "sin(pi / 6)" # radians
|
|
82
|
+
./target/release/calculator "sind(30)" # degrees
|
|
83
|
+
|
|
84
|
+
# Equation solving
|
|
85
|
+
./target/release/calculator "x^2-5x+6=0"
|
|
86
|
+
./target/release/calculator "x+y=5, x-y=1"
|
|
87
|
+
|
|
88
|
+
# Output formatting
|
|
89
|
+
./target/release/calculator --unicode "sqrt(16)"
|
|
90
|
+
./target/release/calculator --latex "pi"
|
|
91
|
+
./target/release/calculator --ascii "3 + 4"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Passing `--help` or `--version` prints CLI info. Without an argument, the program enters interactive mode.
|
|
95
|
+
|
|
96
|
+
## Building
|
|
97
|
+
|
|
98
|
+
The project uses Rust and Cargo.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Build in release mode
|
|
102
|
+
cargo build --release
|
|
103
|
+
|
|
104
|
+
# Run tests
|
|
105
|
+
cargo test
|
|
106
|
+
|
|
107
|
+
# Run with clippy for additional checks
|
|
108
|
+
cargo clippy
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- Rust 1.75.0 or later is required
|
|
112
|
+
- Cargo handles all dependencies automatically
|
|
113
|
+
- The binary will be available at `target/release/calculator`
|
|
114
|
+
|
|
115
|
+
## Interactive Mode
|
|
116
|
+
|
|
117
|
+
Run the calculator without arguments to enter interactive mode:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
./target/release/calculator
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Type expressions and press Enter to evaluate. Type `exit` or `quit` to exit, or press Ctrl+D.
|
|
124
|
+
|
|
125
|
+
## Project Structure
|
|
126
|
+
|
|
127
|
+
- `src/core/` - Core data types (ComplexNumber, Fraction, Expression)
|
|
128
|
+
- `src/parser/` - Expression parser and tokenizer
|
|
129
|
+
- `src/solver/` - Equation solvers (linear, quadratic, cubic, quartic, quintic)
|
|
130
|
+
- `src/output/` - Output formatters (ASCII, Unicode, LaTeX)
|
|
131
|
+
- `src/main.rs` - CLI entry point
|
|
132
|
+
|
|
133
|
+
## Troubleshooting
|
|
134
|
+
|
|
135
|
+
- **Cargo not found**: Install Rust from https://rustup.rs/
|
|
136
|
+
- **Build fails**: Ensure you have Rust 1.75.0 or later
|
|
137
|
+
- **Locale-dependent parsing issues**: force the C locale before running (`LC_ALL=C ./calculator`)
|
|
138
|
+
|
|
139
|
+
## License
|
|
140
|
+
|
|
141
|
+
MIT License - See LICENSE file for details
|
|
142
|
+
|
|
143
|
+
## Migration from C++ Version
|
|
144
|
+
|
|
145
|
+
This calculator was originally implemented in C++20 with SymEngine. The Rust version provides:
|
|
146
|
+
- Faster build times (seconds instead of minutes)
|
|
147
|
+
- No external dependencies (no 374MB SymEngine vendored code)
|
|
148
|
+
- Memory safety without garbage collection
|
|
149
|
+
- Smaller binary size
|
|
150
|
+
- Better cross-platform support
|
|
Binary file
|
|
Binary file
|
package/index.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// Entry point for the calculator-cli npm package
|
|
4
|
+
// This is a minimal wrapper that delegates to the compiled binary
|
|
5
|
+
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const { spawnSync } = require("child_process");
|
|
8
|
+
const os = require("os");
|
|
9
|
+
|
|
10
|
+
// Determine the appropriate binary based on platform
|
|
11
|
+
const platform = os.platform();
|
|
12
|
+
const isWindows = platform === "win32";
|
|
13
|
+
|
|
14
|
+
// Binary file names
|
|
15
|
+
const binaryName = isWindows
|
|
16
|
+
? "calculator_windows-x86-64.exe"
|
|
17
|
+
: "calculator_linux-x64";
|
|
18
|
+
const binaryPath = path.join(__dirname, "bin", binaryName);
|
|
19
|
+
|
|
20
|
+
function runCalculator(args) {
|
|
21
|
+
if (!require("fs").existsSync(binaryPath)) {
|
|
22
|
+
console.error(`Error: Calculator binary not found for ${platform}`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const result = spawnSync(binaryPath, args, { stdio: "inherit" });
|
|
28
|
+
process.exit(result.status);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error(`Error: ${error.message}`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// If called from npm scripts, pass all arguments to the binary
|
|
36
|
+
if (require.main === module) {
|
|
37
|
+
runCalculator(process.argv.slice(2));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = { runCalculator };
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mathcalc-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A command-line calculator with symbolic math support",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"calculator": "bin/calculator_linux-x64"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"preinstall": "node scripts/install.js",
|
|
11
|
+
"postinstall": "node scripts/postinstall.js",
|
|
12
|
+
"test": "node scripts/test.js"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/anomalyco/calculator-cli.git"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"calculator",
|
|
20
|
+
"math",
|
|
21
|
+
"cli",
|
|
22
|
+
"command-line",
|
|
23
|
+
"equations"
|
|
24
|
+
],
|
|
25
|
+
"author": "Allen <anomalyco@github.com>",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"os": [
|
|
28
|
+
"linux",
|
|
29
|
+
"win32"
|
|
30
|
+
],
|
|
31
|
+
"cpu": [
|
|
32
|
+
"x64"
|
|
33
|
+
],
|
|
34
|
+
"files": [
|
|
35
|
+
"bin/",
|
|
36
|
+
"scripts/"
|
|
37
|
+
],
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=12.0.0"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Local build script for generating platform-specific binaries for npm distribution
|
|
5
|
+
* This script is designed for local compilation across multiple platforms
|
|
6
|
+
*
|
|
7
|
+
* To build for all platforms locally, you'll need:
|
|
8
|
+
* - Rust toolchains: x86_64-pc-windows-gnu, x86_64-apple-darwin, x86_64-unknown-linux-gnu
|
|
9
|
+
* - Cross-compilation tools for Windows (mingw-w64) on Linux/macOS
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const path = require("path");
|
|
13
|
+
const { execSync } = require("child_process");
|
|
14
|
+
const fs = require("fs");
|
|
15
|
+
|
|
16
|
+
// Target platforms and their output files
|
|
17
|
+
const platforms = [
|
|
18
|
+
{
|
|
19
|
+
target: "x86_64-unknown-linux-gnu",
|
|
20
|
+
outputFile: "calculator-linux-x64",
|
|
21
|
+
canBuildOn: ["linux"],
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
target: "x86_64-pc-windows-gnu",
|
|
25
|
+
outputFile: "calculator-win32-x64.exe",
|
|
26
|
+
canBuildOn: ["linux", "macos", "windows"],
|
|
27
|
+
requires: {
|
|
28
|
+
linux: "x86_64-w64-mingw32-gcc",
|
|
29
|
+
macos: "x86_64-w64-mingw32-gcc",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
target: "x86_64-apple-darwin",
|
|
34
|
+
outputFile: "calculator-darwin-x64",
|
|
35
|
+
canBuildOn: ["macos"],
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
console.log("🔨 Building calculator-cli binaries for npm distribution...\n");
|
|
40
|
+
|
|
41
|
+
// Check if Cargo.toml exists
|
|
42
|
+
const projectRoot = path.join(__dirname, "..");
|
|
43
|
+
if (!fs.existsSync(path.join(projectRoot, "Cargo.toml"))) {
|
|
44
|
+
console.error("❌ Cargo.toml not found in project root");
|
|
45
|
+
console.log("Make sure this script is run from the correct directory");
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Detect current platform and WSL environment
|
|
50
|
+
const detectCurrentPlatform = () => {
|
|
51
|
+
const platform = process.platform;
|
|
52
|
+
if (platform === "linux") return "linux";
|
|
53
|
+
if (platform === "darwin") return "macos";
|
|
54
|
+
if (platform === "win32") return "windows";
|
|
55
|
+
return "unknown";
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Check if running in WSL
|
|
59
|
+
const isWSL = () => {
|
|
60
|
+
try {
|
|
61
|
+
return (
|
|
62
|
+
fs
|
|
63
|
+
.readFileSync("/proc/version", "utf8")
|
|
64
|
+
.toLowerCase()
|
|
65
|
+
.includes("microsoft") ||
|
|
66
|
+
process.env.WSL_DISTRO_NAME !== undefined
|
|
67
|
+
);
|
|
68
|
+
} catch (e) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const currentPlatform = detectCurrentPlatform();
|
|
74
|
+
const inWSL = currentPlatform === "linux" && isWSL();
|
|
75
|
+
console.log(
|
|
76
|
+
`📍 Detected current platform: ${currentPlatform}${inWSL ? " (in WSL)" : ""}\n`,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
// Helper function to check if a command is available
|
|
80
|
+
const commandExists = (command) => {
|
|
81
|
+
try {
|
|
82
|
+
execSync(`which ${command}`, { stdio: "ignore" });
|
|
83
|
+
return true;
|
|
84
|
+
} catch (e) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Helper function to check if a target is installed
|
|
90
|
+
const isTargetInstalled = (target) => {
|
|
91
|
+
try {
|
|
92
|
+
const list = execSync("rustup target list --installed", {
|
|
93
|
+
encoding: "utf8",
|
|
94
|
+
});
|
|
95
|
+
return list.includes(target);
|
|
96
|
+
} catch (e) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
// Get version from Cargo.toml
|
|
103
|
+
const cargoContent = fs.readFileSync(
|
|
104
|
+
path.join(projectRoot, "Cargo.toml"),
|
|
105
|
+
"utf8",
|
|
106
|
+
);
|
|
107
|
+
const versionMatch = cargoContent.match(/^version\s*=\s*"([^"]+)"/m);
|
|
108
|
+
const version = versionMatch ? versionMatch[1] : "2.0.0";
|
|
109
|
+
console.log(`Found version: ${version}\n`);
|
|
110
|
+
|
|
111
|
+
// Create bin directory if it doesn't exist
|
|
112
|
+
const binDir = path.join(projectRoot, "bin");
|
|
113
|
+
if (!fs.existsSync(binDir)) {
|
|
114
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
115
|
+
console.log(`Created bin directory: ${binDir}\n`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Filter platforms that can be built on current platform
|
|
119
|
+
const buildablePlatforms = platforms.filter((platform) =>
|
|
120
|
+
platform.canBuildOn.includes(currentPlatform),
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
if (buildablePlatforms.length === 0) {
|
|
124
|
+
console.log(`⚠️ No platforms can be built on ${currentPlatform}`);
|
|
125
|
+
console.log("This script supports:");
|
|
126
|
+
|
|
127
|
+
platforms.forEach((platform) => {
|
|
128
|
+
console.log(
|
|
129
|
+
`- ${platform.target}: ${platform.canBuildOn.join(", ")}`,
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
console.log("\n💡 Consider using a different platform or a CI service");
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let successfulBuilds = 0;
|
|
138
|
+
|
|
139
|
+
// Build for each buildable target platform
|
|
140
|
+
for (const platform of buildablePlatforms) {
|
|
141
|
+
console.log(`📦 Building for ${platform.target}...`);
|
|
142
|
+
|
|
143
|
+
// Check if the target is installed
|
|
144
|
+
if (!isTargetInstalled(platform.target)) {
|
|
145
|
+
console.log(`❌ Rust target '${platform.target}' not installed`);
|
|
146
|
+
console.log(`💡 Installing target now...`);
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
execSync(`rustup target add ${platform.target}`, {
|
|
150
|
+
stdio: "inherit",
|
|
151
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
152
|
+
});
|
|
153
|
+
console.log(
|
|
154
|
+
`✅ Target '${platform.target}' installed successfully\n`,
|
|
155
|
+
);
|
|
156
|
+
} catch (error) {
|
|
157
|
+
console.log(`❌ Failed to install target: ${error.message}`);
|
|
158
|
+
console.log(
|
|
159
|
+
`💡 Please install manually: rustup target add ${platform.target}\n`,
|
|
160
|
+
);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Check for required tools
|
|
166
|
+
if (platform.requires && platform.requires[currentPlatform]) {
|
|
167
|
+
const requiredTool = platform.requires[currentPlatform];
|
|
168
|
+
if (!commandExists(requiredTool)) {
|
|
169
|
+
console.log(`❌ Required tool '${requiredTool}' not found`);
|
|
170
|
+
|
|
171
|
+
// Provide installation instructions
|
|
172
|
+
if (
|
|
173
|
+
currentPlatform === "linux" &&
|
|
174
|
+
platform.target.includes("windows")
|
|
175
|
+
) {
|
|
176
|
+
console.log("💡 To install on Linux/Ubuntu:");
|
|
177
|
+
console.log(" sudo apt-get update");
|
|
178
|
+
console.log(" sudo apt-get install mingw-w64");
|
|
179
|
+
console.log(" # For Debian:");
|
|
180
|
+
console.log(" sudo apt-get install gcc-mingw-w64-x86-64");
|
|
181
|
+
} else if (
|
|
182
|
+
currentPlatform === "macos" &&
|
|
183
|
+
platform.target.includes("windows")
|
|
184
|
+
) {
|
|
185
|
+
console.log("💡 To install on macOS:");
|
|
186
|
+
console.log(" brew install mingw-w64");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
console.log("");
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
// Set environment variables for cross-compilation if needed
|
|
196
|
+
const env = { ...process.env };
|
|
197
|
+
|
|
198
|
+
// Configure environment for cross-compilation
|
|
199
|
+
const env = { ...process.env };
|
|
200
|
+
if (
|
|
201
|
+
platform.target === "x86_64-pc-windows-gnu" &&
|
|
202
|
+
currentPlatform !== "windows"
|
|
203
|
+
) {
|
|
204
|
+
// Set the linker for Windows cross-compilation
|
|
205
|
+
env.CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER =
|
|
206
|
+
"x86_64-w64-mingw32-gcc";
|
|
207
|
+
env.CC_x86_64_pc_windows_gnu = "x86_64-w64-mingw32-gcc";
|
|
208
|
+
env.CXX_x86_64_pc_windows_gnu = "x86_64-w64-mingw32-g++";
|
|
209
|
+
|
|
210
|
+
// WSL-specific settings
|
|
211
|
+
if (inWSL) {
|
|
212
|
+
console.log(
|
|
213
|
+
" 🐧 Applying WSL-specific settings for Windows target",
|
|
214
|
+
);
|
|
215
|
+
// Additional linker flags for WSL
|
|
216
|
+
env.CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUSTFLAGS =
|
|
217
|
+
"-C link-arg=-Wl,--subsystem,console -C link-arg=-static";
|
|
218
|
+
|
|
219
|
+
// Try alternative linking strategy for WSL
|
|
220
|
+
if (process.env.USE_MSVC_TOOLCHAIN) {
|
|
221
|
+
console.log(
|
|
222
|
+
" Using MSVC toolchain for Windows target",
|
|
223
|
+
);
|
|
224
|
+
env.RUSTUP_TOOLCHAIN = "stable-x86_64-pc-windows-msvc";
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Build the binary
|
|
230
|
+
const buildCmd = `cargo build --release --target ${platform.target}`;
|
|
231
|
+
console.log(` Running: ${buildCmd}`);
|
|
232
|
+
|
|
233
|
+
// Use inherit stdio and increased buffer to avoid ENOBUFS errors
|
|
234
|
+
execSync(buildCmd, {
|
|
235
|
+
stdio: "inherit",
|
|
236
|
+
env,
|
|
237
|
+
cwd: projectRoot,
|
|
238
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB buffer
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// Copy the binary to the bin directory
|
|
242
|
+
const sourcePath = path.join(
|
|
243
|
+
projectRoot,
|
|
244
|
+
"target",
|
|
245
|
+
platform.target,
|
|
246
|
+
"release",
|
|
247
|
+
"calculator",
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
// For Windows, the binary has .exe extension
|
|
251
|
+
const windowsSourcePath = path.join(
|
|
252
|
+
projectRoot,
|
|
253
|
+
"target",
|
|
254
|
+
platform.target,
|
|
255
|
+
"release",
|
|
256
|
+
"calculator.exe",
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
const finalSourcePath = platform.target.includes("windows")
|
|
260
|
+
? windowsSourcePath
|
|
261
|
+
: sourcePath;
|
|
262
|
+
const destPath = path.join(binDir, platform.outputFile);
|
|
263
|
+
|
|
264
|
+
// Verify source exists
|
|
265
|
+
if (!fs.existsSync(finalSourcePath)) {
|
|
266
|
+
throw new Error(
|
|
267
|
+
`Binary not found at expected path: ${finalSourcePath}`,
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Copy binary
|
|
272
|
+
fs.copyFileSync(finalSourcePath, destPath);
|
|
273
|
+
|
|
274
|
+
// On Unix-like systems, make sure the binary is executable
|
|
275
|
+
if (!platform.target.includes("windows")) {
|
|
276
|
+
try {
|
|
277
|
+
fs.chmodSync(destPath, "755");
|
|
278
|
+
} catch (error) {
|
|
279
|
+
console.warn(
|
|
280
|
+
`Warning: Could not set executable permissions: ${error.message}`,
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
console.log(`✅ Built and copied to: ${destPath}\n`);
|
|
286
|
+
successfulBuilds++;
|
|
287
|
+
} catch (error) {
|
|
288
|
+
console.error(
|
|
289
|
+
`❌ Failed to build for ${platform.target}: ${error.message}`,
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
// Provide specific help for common errors
|
|
293
|
+
if (
|
|
294
|
+
error.message.includes("E0425") ||
|
|
295
|
+
error.message.includes("E0431") ||
|
|
296
|
+
error.message.includes("linker") ||
|
|
297
|
+
error.message.includes("undefined reference")
|
|
298
|
+
) {
|
|
299
|
+
console.log("");
|
|
300
|
+
console.log(
|
|
301
|
+
"💡 This appears to be a linker error (E0425/E0431). Solutions:",
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
if (platform.target.includes("windows")) {
|
|
305
|
+
console.log("1. For WSL MinGW issues, try these steps:");
|
|
306
|
+
if (inWSL) {
|
|
307
|
+
console.log(" 🐧 WSL-specific solutions:");
|
|
308
|
+
console.log(" a) Install complete MinGW toolchain:");
|
|
309
|
+
console.log(
|
|
310
|
+
" sudo apt-get update && sudo apt-get install mingw-w64 gcc-mingw-w64-x86-64",
|
|
311
|
+
);
|
|
312
|
+
console.log("");
|
|
313
|
+
console.log(" b) Set environment variables for WSL:");
|
|
314
|
+
console.log(
|
|
315
|
+
" export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc",
|
|
316
|
+
);
|
|
317
|
+
console.log(
|
|
318
|
+
" export CC_x86_64_pc_windows_gnu=x86_64-w64-mingw32-gcc",
|
|
319
|
+
);
|
|
320
|
+
console.log(
|
|
321
|
+
" export CXX_x86_64_pc_windows_gnu=x86_64-w64-mingw32-g++",
|
|
322
|
+
);
|
|
323
|
+
console.log("");
|
|
324
|
+
console.log(
|
|
325
|
+
" c) Alternative: Use Windows native Rust:",
|
|
326
|
+
);
|
|
327
|
+
console.log(
|
|
328
|
+
" rustup toolchain install stable-x86_64-pc-windows-msvc",
|
|
329
|
+
);
|
|
330
|
+
console.log(
|
|
331
|
+
" rustup default stable-x86_64-pc-windows-msvc",
|
|
332
|
+
);
|
|
333
|
+
console.log(
|
|
334
|
+
" rustup target add x86_64-pc-windows-msvc",
|
|
335
|
+
);
|
|
336
|
+
console.log("");
|
|
337
|
+
console.log(
|
|
338
|
+
" d) For persistent configuration, add to ~/.bashrc:",
|
|
339
|
+
);
|
|
340
|
+
console.log(" [target.x86_64-pc-windows-gnu]");
|
|
341
|
+
console.log(" linker = 'x86_64-w64-mingw32-gcc'");
|
|
342
|
+
console.log(" ");
|
|
343
|
+
console.log(" [target.x86_64-pc-windows-msvc]");
|
|
344
|
+
console.log(" linker = 'lld-link'");
|
|
345
|
+
} else {
|
|
346
|
+
console.log(
|
|
347
|
+
" sudo apt-get update && sudo apt-get install mingw-w64",
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
console.log("");
|
|
352
|
+
console.log(
|
|
353
|
+
"2. Try reinstalling and reconfiguring Rust targets:",
|
|
354
|
+
);
|
|
355
|
+
console.log(
|
|
356
|
+
" rustup target remove --toolchain stable x86_64-pc-windows-gnu",
|
|
357
|
+
);
|
|
358
|
+
console.log(
|
|
359
|
+
" rustup target add --toolchain stable x86_64-pc-windows-gnu",
|
|
360
|
+
);
|
|
361
|
+
console.log(" # Or try MSVC target:");
|
|
362
|
+
console.log(" rustup target add x86_64-pc-windows-msvc");
|
|
363
|
+
|
|
364
|
+
if (inWSL) {
|
|
365
|
+
console.log("");
|
|
366
|
+
console.log("🐧 WSL Specific Tips:");
|
|
367
|
+
console.log(
|
|
368
|
+
" - WSL MinGW builds can be tricky. Consider using:",
|
|
369
|
+
);
|
|
370
|
+
console.log(
|
|
371
|
+
" * Windows Subsystem for Linux with Windows Rust installed in Windows",
|
|
372
|
+
);
|
|
373
|
+
console.log(
|
|
374
|
+
" * The MSVC target which might be more stable in WSL",
|
|
375
|
+
);
|
|
376
|
+
console.log(
|
|
377
|
+
" * Running the build directly in Windows instead of WSL",
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
console.log("");
|
|
382
|
+
console.log("3. Alternative approaches:");
|
|
383
|
+
console.log(" - Build in native Windows environment");
|
|
384
|
+
console.log(
|
|
385
|
+
" - Use GitHub Actions or another CI service",
|
|
386
|
+
);
|
|
387
|
+
console.log(
|
|
388
|
+
" - Focus on platforms that build successfully",
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
} else if (error.message.includes("could not find")) {
|
|
392
|
+
console.log("");
|
|
393
|
+
console.log(`💡 Rust target not found. To install:`);
|
|
394
|
+
console.log(` rustup target add ${platform.target}`);
|
|
395
|
+
console.log("");
|
|
396
|
+
console.log("To see all installed targets:");
|
|
397
|
+
console.log(" rustup target list --installed");
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
console.log("");
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// Build summary
|
|
405
|
+
console.log("📋 Build Summary:");
|
|
406
|
+
platforms.forEach((platform) => {
|
|
407
|
+
const destPath = path.join(binDir, platform.outputFile);
|
|
408
|
+
if (fs.existsSync(destPath)) {
|
|
409
|
+
console.log(`✅ ${platform.outputFile}`);
|
|
410
|
+
} else {
|
|
411
|
+
const canBuild = platform.canBuildOn.includes(currentPlatform)
|
|
412
|
+
? "buildable"
|
|
413
|
+
: "requires different platform";
|
|
414
|
+
console.log(`❌ ${platform.outputFile} (${canBuild})`);
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
console.log(
|
|
419
|
+
`\nSuccessfully built ${successfulBuilds} out of ${buildablePlatforms.length} platforms`,
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
if (successfulBuilds === 0) {
|
|
423
|
+
console.log("\n❌ No binaries were built successfully");
|
|
424
|
+
console.log("\n💡 Troubleshooting:");
|
|
425
|
+
console.log("1. Install missing Rust targets:");
|
|
426
|
+
buildablePlatforms.forEach((platform) => {
|
|
427
|
+
console.log(` rustup target add ${platform.target}`);
|
|
428
|
+
});
|
|
429
|
+
console.log("\n2. Install cross-compilation tools:");
|
|
430
|
+
if (currentPlatform === "linux") {
|
|
431
|
+
console.log(
|
|
432
|
+
" sudo apt-get update && sudo apt-get install mingw-w64",
|
|
433
|
+
);
|
|
434
|
+
} else if (currentPlatform === "macos") {
|
|
435
|
+
console.log(" brew install mingw-w64");
|
|
436
|
+
}
|
|
437
|
+
console.log("\n3. See LOCAL_BUILD_GUIDE.md for detailed instructions");
|
|
438
|
+
console.log("\n4. Consider building only for your current platform");
|
|
439
|
+
} else {
|
|
440
|
+
console.log("\n✅ Build completed successfully!");
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
console.log("\n📦 Next steps:");
|
|
444
|
+
if (successfulBuilds > 0) {
|
|
445
|
+
console.log("1. Test the package: node test-package.js");
|
|
446
|
+
console.log("2. Create package: npm run prepare-package");
|
|
447
|
+
console.log("3. Test locally: npm run local-test");
|
|
448
|
+
console.log("4. Publish to npm: npm publish");
|
|
449
|
+
console.log(
|
|
450
|
+
"\n💡 Remember to update the version number in Cargo.toml before publishing!",
|
|
451
|
+
);
|
|
452
|
+
|
|
453
|
+
if (inWSL) {
|
|
454
|
+
console.log("\n🐧 WSL-Specific Tips:");
|
|
455
|
+
console.log("- Windows binaries are accessible from Windows at:");
|
|
456
|
+
console.log(
|
|
457
|
+
` \\\\wsl$\\$(hostname)\\${path
|
|
458
|
+
.resolve(projectRoot)
|
|
459
|
+
.replace(/^\/mnt\//, "")
|
|
460
|
+
.replace(/\//g, "\\")}\\bin`,
|
|
461
|
+
);
|
|
462
|
+
console.log(
|
|
463
|
+
"- Test Windows binaries directly in Windows Command Prompt or PowerShell",
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
} else {
|
|
467
|
+
console.log("1. Fix the build issues shown above");
|
|
468
|
+
console.log("2. Try building for fewer platforms");
|
|
469
|
+
console.log("3. Consider building only for your current platform");
|
|
470
|
+
|
|
471
|
+
if (inWSL) {
|
|
472
|
+
console.log("\n🐧 WSL-Specific Tips:");
|
|
473
|
+
console.log("- Ensure you have the latest mingw-w64 packages");
|
|
474
|
+
console.log(
|
|
475
|
+
"- Try running the build script from /mnt/c/ to avoid WSL path limitations",
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
} catch (error) {
|
|
480
|
+
console.error(`❌ Build process failed: ${error.message}`);
|
|
481
|
+
process.exit(1);
|
|
482
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# WSL Windows Build Fix Script
|
|
4
|
+
# This script helps resolve E4025 and E4031 linker errors when building Windows binaries in WSL
|
|
5
|
+
|
|
6
|
+
echo "🐧 WSL Windows Build Fix Script"
|
|
7
|
+
echo "================================"
|
|
8
|
+
echo ""
|
|
9
|
+
|
|
10
|
+
# Check if we're in WSL
|
|
11
|
+
if ! grep -qi microsoft /proc/version; then
|
|
12
|
+
echo "⚠️ This script is optimized for WSL but can run on other Linux systems"
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
# Install complete MinGW toolchain
|
|
16
|
+
echo "🔧 Installing complete MinGW toolchain..."
|
|
17
|
+
sudo apt-get update
|
|
18
|
+
sudo apt-get install -y \
|
|
19
|
+
mingw-w64 \
|
|
20
|
+
gcc-mingw-w64-x86-64 \
|
|
21
|
+
gcc-mingw-w64-i686 \
|
|
22
|
+
binutils-mingw-w64-x86-64 \
|
|
23
|
+
binutils-mingw-w64-i686 \
|
|
24
|
+
mingw-w64-tools \
|
|
25
|
+
mingw-w64-x86-64-dev \
|
|
26
|
+
g++-mingw-w64-x86-64
|
|
27
|
+
|
|
28
|
+
# Create Cargo config directory if it doesn't exist
|
|
29
|
+
echo ""
|
|
30
|
+
echo "📝 Configuring Cargo for cross-compilation..."
|
|
31
|
+
mkdir -p ~/.cargo
|
|
32
|
+
|
|
33
|
+
# Create or update Cargo config.toml
|
|
34
|
+
cat > ~/.cargo/config.toml << 'EOF'
|
|
35
|
+
[target.x86_64-pc-windows-gnu]
|
|
36
|
+
linker = "x86_64-w64-mingw32-gcc"
|
|
37
|
+
ar = "x86_64-w64-mingw32-ar"
|
|
38
|
+
|
|
39
|
+
[target.x86_64-pc-windows-gnu.env]
|
|
40
|
+
CC_x86_64_pc_windows_gnu = "x86_64-w64-mingw32-gcc"
|
|
41
|
+
CXX_x86_64_pc_windows_gnu = "x86_64-w64-mingw32-g++"
|
|
42
|
+
AR_x86_64_pc_windows_gnu = "x86_64-w64-mingw32-ar"
|
|
43
|
+
|
|
44
|
+
[target.i686-pc-windows-gnu]
|
|
45
|
+
linker = "i686-w64-mingw32-gcc"
|
|
46
|
+
ar = "i686-w64-mingw32-ar"
|
|
47
|
+
|
|
48
|
+
[target.i686-pc-windows-gnu.env]
|
|
49
|
+
CC_i686_pc_windows_gnu = "i686-w64-mingw32-gcc"
|
|
50
|
+
CXX_i686_pc_windows_gnu = "i686-w64-mingw32-g++"
|
|
51
|
+
AR_i686_pc_windows_gnu = "i686-w64-mingw32-ar"
|
|
52
|
+
EOF
|
|
53
|
+
|
|
54
|
+
# Set environment variables for current session
|
|
55
|
+
echo ""
|
|
56
|
+
echo "🔧 Setting environment variables..."
|
|
57
|
+
export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc
|
|
58
|
+
export CC_x86_64_pc_windows_gnu=x86_64-w64-mingw32-gcc
|
|
59
|
+
export CXX_x86_64_pc_windows_gnu=x86_64-w64-mingw32-g++
|
|
60
|
+
export AR_x86_64_pc_windows_gnu=x86_64-w64-mingw32-ar
|
|
61
|
+
|
|
62
|
+
# Add to ~/.bashrc for persistence
|
|
63
|
+
echo ""
|
|
64
|
+
echo "💾 Adding environment variables to ~/.bashrc..."
|
|
65
|
+
cat >> ~/.bashrc << 'EOF'
|
|
66
|
+
|
|
67
|
+
# Rust cross-compilation for Windows in WSL
|
|
68
|
+
export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc
|
|
69
|
+
export CC_x86_64_pc_windows_gnu=x86_64-w64-mingw32-gcc
|
|
70
|
+
export CXX_x86_64_pc_windows_gnu=x86_64-w64-mingw32-g++
|
|
71
|
+
export AR_x86_64_pc_windows_gnu=x86_64-w64-mingw32-ar
|
|
72
|
+
EOF
|
|
73
|
+
|
|
74
|
+
# Add to ~/.zshrc if zsh is used
|
|
75
|
+
if [ -f ~/.zshrc ]; then
|
|
76
|
+
echo ""
|
|
77
|
+
echo "💾 Adding environment variables to ~/.zshrc..."
|
|
78
|
+
cat >> ~/.zshrc << 'EOF'
|
|
79
|
+
|
|
80
|
+
# Rust cross-compilation for Windows in WSL
|
|
81
|
+
export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc
|
|
82
|
+
export CC_x86_64_pc_windows_gnu=x86_64-w64-mingw32-gcc
|
|
83
|
+
export CXX_x86_64_pc_windows_gnu=x86_64-w64-mingw32-g++
|
|
84
|
+
export AR_x86_64_pc_windows_gnu=x86_64-w64-mingw32-ar
|
|
85
|
+
EOF
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# Verify installation
|
|
89
|
+
echo ""
|
|
90
|
+
echo "🔍 Verifying installation..."
|
|
91
|
+
if command -v x86_64-w64-mingw32-gcc &> /dev/null; then
|
|
92
|
+
echo "✅ MinGW GCC found"
|
|
93
|
+
echo " Version: $(x86_64-w64-mingw32-gcc --version | head -1)"
|
|
94
|
+
else
|
|
95
|
+
echo "❌ MinGW GCC not found"
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
if command -v x86_64-w64-mingw32-ar &> /dev/null; then
|
|
99
|
+
echo "✅ MinGW AR found"
|
|
100
|
+
else
|
|
101
|
+
echo "❌ MinGW AR not found"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# Install or update Rust targets
|
|
105
|
+
echo ""
|
|
106
|
+
echo "🔧 Installing Rust targets..."
|
|
107
|
+
rustup target add x86_64-pc-windows-gnu
|
|
108
|
+
rustup target add i686-pc-windows-gnu
|
|
109
|
+
|
|
110
|
+
# Test compilation with a simple C program
|
|
111
|
+
echo ""
|
|
112
|
+
echo "🧪 Testing MinGW with a simple program..."
|
|
113
|
+
cat > test_minGW.c << 'EOF'
|
|
114
|
+
#include <stdio.h>
|
|
115
|
+
|
|
116
|
+
int main() {
|
|
117
|
+
printf("Hello from Windows binary built in WSL!\n");
|
|
118
|
+
return 0;
|
|
119
|
+
}
|
|
120
|
+
EOF
|
|
121
|
+
|
|
122
|
+
# Compile with MinGW
|
|
123
|
+
if x86_64-w64-mingw32-gcc -o test_minGW.exe test_minGW.c 2>/dev/null; then
|
|
124
|
+
echo "✅ MinGW test compilation successful"
|
|
125
|
+
echo " Output: $(./test_minGW.exe 2>/dev/null || echo 'Binary created, needs Windows to run')"
|
|
126
|
+
rm -f test_minGW.exe test_minGW.c
|
|
127
|
+
else
|
|
128
|
+
echo "❌ MinGW test compilation failed"
|
|
129
|
+
echo " You may need to restart your terminal or source your shell configuration"
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
# Clean up
|
|
133
|
+
rm -f test_minGW.c
|
|
134
|
+
|
|
135
|
+
echo ""
|
|
136
|
+
echo "🎉 WSL Windows build fix completed!"
|
|
137
|
+
echo ""
|
|
138
|
+
echo "📋 Next steps:"
|
|
139
|
+
echo "1. Restart your terminal or run: source ~/.bashrc"
|
|
140
|
+
echo "2. Try building Windows binary: npm run build-windows"
|
|
141
|
+
echo "3. If you still have issues, try: npm run build-windows-static"
|
|
142
|
+
echo ""
|
|
143
|
+
echo "🔧 Additional options if problems persist:"
|
|
144
|
+
echo "- Use MSVC toolchain: rustup toolchain install stable-x86_64-pc-windows-msvc"
|
|
145
|
+
echo "- Build in native Windows environment"
|
|
146
|
+
echo "- Use GitHub Actions for automated builds"
|
|
147
|
+
echo ""
|
|
148
|
+
echo "💡 For more help, see: WSL_BUILD_GUIDE.md"
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
|
|
7
|
+
// Platform detection
|
|
8
|
+
const platform = os.platform();
|
|
9
|
+
console.log(`Detected platform: ${platform}`);
|
|
10
|
+
console.log(`Detected architecture: ${os.arch()}`);
|
|
11
|
+
|
|
12
|
+
// Map platforms to binary files
|
|
13
|
+
const binaries = {
|
|
14
|
+
'win32': 'calculator_windows-x86-64.exe',
|
|
15
|
+
'linux': 'calculator_linux-x64'
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Check if platform is supported
|
|
19
|
+
if (!binaries[platform]) {
|
|
20
|
+
console.error(`
|
|
21
|
+
❌ Platform ${platform} is not supported by calculator-cli v0.1.0
|
|
22
|
+
|
|
23
|
+
Supported platforms:
|
|
24
|
+
- Windows (x64)
|
|
25
|
+
- Linux (x64)
|
|
26
|
+
|
|
27
|
+
For other platforms, please build from source:
|
|
28
|
+
git clone https://github.com/anomalyco/calculator-cli.git
|
|
29
|
+
cd calculator-cli
|
|
30
|
+
cargo build --release
|
|
31
|
+
`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Binary path
|
|
36
|
+
const binaryName = binaries[platform];
|
|
37
|
+
const binaryPath = path.join(__dirname, '..', 'bin', binaryName);
|
|
38
|
+
|
|
39
|
+
// Verify binary exists
|
|
40
|
+
if (!fs.existsSync(binaryPath)) {
|
|
41
|
+
console.error(`❌ Binary not found: ${binaryPath}`);
|
|
42
|
+
console.error('Please ensure the binary files are present in the bin directory.');
|
|
43
|
+
console.error('For Windows users: Place calculator_windows-x86-64.exe in bin/');
|
|
44
|
+
console.error('For Linux users: Place calculator_linux-x64 in bin/');
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Create symlink or wrapper for node_modules/.bin
|
|
49
|
+
const targetDir = path.join(__dirname, '..', 'node_modules', '.bin');
|
|
50
|
+
const targetPath = path.join(targetDir, 'calculator');
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
// Ensure .bin directory exists
|
|
54
|
+
if (!fs.existsSync(targetDir)) {
|
|
55
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (platform === 'win32') {
|
|
59
|
+
// Create a batch file wrapper for Windows
|
|
60
|
+
const batchContent = `@echo off
|
|
61
|
+
"${binaryPath}" %*`;
|
|
62
|
+
fs.writeFileSync(`${targetPath}.cmd`, batchContent);
|
|
63
|
+
console.log('✅ Created Windows batch file');
|
|
64
|
+
} else {
|
|
65
|
+
// Create symbolic link for Unix-like systems
|
|
66
|
+
if (fs.existsSync(targetPath)) {
|
|
67
|
+
fs.unlinkSync(targetPath);
|
|
68
|
+
}
|
|
69
|
+
fs.symlinkSync(binaryPath, targetPath);
|
|
70
|
+
// Ensure executable permissions
|
|
71
|
+
fs.chmodSync(targetPath, '755');
|
|
72
|
+
console.log('✅ Created symbolic link with executable permissions');
|
|
73
|
+
}
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error(`❌ Failed to create command link: ${error.message}`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
console.log('✅ Installation complete!');
|
|
80
|
+
console.log(`You can now run 'calculator' in your terminal.`);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
<file_path>
|
|
84
|
+
calculator-cli/scripts/postinstall.js
|
|
85
|
+
</file_path>
|
|
86
|
+
|
|
87
|
+
<edit_description>
|
|
88
|
+
Create postinstall validation script
|
|
89
|
+
</edit_description>
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
#!/usr/bin/env node
|
|
93
|
+
|
|
94
|
+
const path = require('path');
|
|
95
|
+
const fs = require('fs');
|
|
96
|
+
const os = require('os');
|
|
97
|
+
|
|
98
|
+
console.log('✅ Validating calculator-cli installation...');
|
|
99
|
+
|
|
100
|
+
// Check for proper binary based on platform
|
|
101
|
+
const platform = os.platform();
|
|
102
|
+
const expectedBinary = platform === 'win32'
|
|
103
|
+
? 'calculator_windows-x86-64.exe'
|
|
104
|
+
: 'calculator_linux-x64';
|
|
105
|
+
|
|
106
|
+
const binaryPath = path.join(__dirname, '..', 'bin', expectedBinary);
|
|
107
|
+
|
|
108
|
+
if (fs.existsSync(binaryPath)) {
|
|
109
|
+
console.log(`✅ Binary found: ${expectedBinary}`);
|
|
110
|
+
} else {
|
|
111
|
+
console.error(`❌ Binary not found: ${expectedBinary}`);
|
|
112
|
+
console.error('Please ensure the binary files are present in the bin directory.');
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Verify command is accessible
|
|
117
|
+
const targetPath = path.join(__dirname, '..', 'node_modules', '.bin');
|
|
118
|
+
const commandPath = platform === 'win32'
|
|
119
|
+
? path.join(targetPath, 'calculator.cmd')
|
|
120
|
+
: path.join(targetPath, 'calculator');
|
|
121
|
+
|
|
122
|
+
if (fs.existsSync(commandPath)) {
|
|
123
|
+
console.log('✅ Command link created successfully');
|
|
124
|
+
} else {
|
|
125
|
+
console.error('❌ Command link not found');
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
console.log('✅ Installation validated successfully!');
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
<file_path>
|
|
133
|
+
calculator-cli/scripts/test.js
|
|
134
|
+
</file_path>
|
|
135
|
+
|
|
136
|
+
<edit_description>
|
|
137
|
+
Create test script to validate the binary
|
|
138
|
+
</edit_description>
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
#!/usr/bin/env node
|
|
142
|
+
|
|
143
|
+
const path = require('path');
|
|
144
|
+
const fs = require('fs');
|
|
145
|
+
const os = require('os');
|
|
146
|
+
const { execSync } = require('child_process');
|
|
147
|
+
|
|
148
|
+
console.log('🧪 Testing calculator-cli binary...');
|
|
149
|
+
|
|
150
|
+
// Platform detection
|
|
151
|
+
const platform = os.platform();
|
|
152
|
+
const binaryName = platform === 'win32'
|
|
153
|
+
? 'calculator_windows-x86-64.exe'
|
|
154
|
+
: 'calculator_linux-x64';
|
|
155
|
+
|
|
156
|
+
const binaryPath = path.join(__dirname, '..', 'bin', binaryName);
|
|
157
|
+
|
|
158
|
+
// Check if binary exists
|
|
159
|
+
if (!fs.existsSync(binaryPath)) {
|
|
160
|
+
console.error(`❌ Binary not found: ${binaryName}`);
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Test basic calculation
|
|
165
|
+
try {
|
|
166
|
+
console.log('🧮 Testing basic calculation: 2 + 2');
|
|
167
|
+
const result = execSync(`"${binaryPath}" "2 + 2"`, { encoding: 'utf8' }).trim();
|
|
168
|
+
|
|
169
|
+
if (result && result.includes('4')) {
|
|
170
|
+
console.log(`✅ Basic calculation test passed: ${result}`);
|
|
171
|
+
} else {
|
|
172
|
+
console.log(`❌ Unexpected result: ${result}`);
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
} catch (error) {
|
|
176
|
+
console.error(`❌ Failed to run binary: ${error.message}`);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Test equation solving
|
|
181
|
+
try {
|
|
182
|
+
console.log('🧮 Testing equation solving: x^2-4=0');
|
|
183
|
+
const equationResult = execSync(`"${binaryPath}" "x^2-4=0"`, { encoding: 'utf8' }).trim();
|
|
184
|
+
|
|
185
|
+
console.log(`✅ Equation solving result: ${equationResult}`);
|
|
186
|
+
} catch (error) {
|
|
187
|
+
console.error(`❌ Failed to solve equation: ${error.message}`);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
console.log('🎉 All tests passed! Calculator CLI is working correctly.');
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
<file_path>
|
|
195
|
+
calculator-cli/index.js
|
|
196
|
+
</file_path>
|
|
197
|
+
|
|
198
|
+
<edit_description>
|
|
199
|
+
Create simple entry point
|
|
200
|
+
</edit_description>
|
|
201
|
+
|
|
202
|
+
```javascript
|
|
203
|
+
#!/usr/bin/env node
|
|
204
|
+
|
|
205
|
+
// Entry point for the calculator-cli npm package
|
|
206
|
+
// This file is minimal because the actual binary handles all functionality
|
|
207
|
+
|
|
208
|
+
console.log('calculator-cli v0.1.0');
|
|
209
|
+
console.log('Run "calculator <expression>" to use the calculator');
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
<file_path>
|
|
213
|
+
calculator-cli/README.md
|
|
214
|
+
</file_path>
|
|
215
|
+
|
|
216
|
+
<edit_description>
|
|
217
|
+
Create simple README for v0.1 release
|
|
218
|
+
</edit_description>
|
|
219
|
+
|
|
220
|
+
```markdown
|
|
221
|
+
# Calculator CLI v0.1.0
|
|
222
|
+
|
|
223
|
+
A lightweight command-line calculator with symbolic math support, available for Windows and Linux x64 platforms.
|
|
224
|
+
|
|
225
|
+
## Quick Start
|
|
226
|
+
|
|
227
|
+
1. Install: `npm install -g calculator-cli`
|
|
228
|
+
2. Run: `calculator "2 + 2"` or `calculator "x^2-4=0"`
|
|
229
|
+
3. For interactive mode: `calculator` (no arguments)
|
|
230
|
+
|
|
231
|
+
## Features
|
|
232
|
+
|
|
233
|
+
- Basic arithmetic operations
|
|
234
|
+
- Equation solving
|
|
235
|
+
- Complex number support
|
|
236
|
+
- Fraction and symbolic output when possible
|
|
237
|
+
|
|
238
|
+
## Supported Platforms
|
|
239
|
+
|
|
240
|
+
- Windows (x64)
|
|
241
|
+
- Linux (x64)
|
|
242
|
+
|
|
243
|
+
## Usage Examples
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
# Basic calculations
|
|
247
|
+
calculator "2 + 2"
|
|
248
|
+
calculator "3 * (4 + 5)"
|
|
249
|
+
|
|
250
|
+
# Equation solving
|
|
251
|
+
calculator "x^2-4=0"
|
|
252
|
+
calculator "x+y=5, x-y=1"
|
|
253
|
+
|
|
254
|
+
# Complex numbers
|
|
255
|
+
calculator "sqrt(-4)"
|
|
256
|
+
calculator "(3+2i) * (1-i)"
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Installation Notes
|
|
260
|
+
|
|
261
|
+
This package includes precompiled binaries for Windows and Linux x64. No Rust toolchain is required.
|
|
262
|
+
|
|
263
|
+
## License
|
|
264
|
+
|
|
265
|
+
MIT License
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const os = require("os");
|
|
6
|
+
|
|
7
|
+
console.log("🔍 Validating calculator-cli installation...");
|
|
8
|
+
|
|
9
|
+
// Platform detection
|
|
10
|
+
const platform = os.platform();
|
|
11
|
+
const expectedBinary =
|
|
12
|
+
platform === "win32"
|
|
13
|
+
? "calculator_windows-x86-64.exe"
|
|
14
|
+
: "calculator_linux-x64";
|
|
15
|
+
|
|
16
|
+
const binaryPath = path.join(__dirname, "..", "bin", expectedBinary);
|
|
17
|
+
|
|
18
|
+
if (!fs.existsSync(binaryPath)) {
|
|
19
|
+
console.error(`❌ Required binary not found: ${expectedBinary}`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!os.arch().includes("64")) {
|
|
24
|
+
console.warn("⚠️ Warning: 64-bit architecture recommended");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
console.log("✅ Calculator CLI v0.1.0 is ready!");
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* WSL Setup Script for calculator-cli
|
|
5
|
+
* This script installs all necessary tools and dependencies for building in WSL
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { execSync } = require("child_process");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
|
|
11
|
+
console.log("🐧 Setting up calculator-cli build environment in WSL...\n");
|
|
12
|
+
|
|
13
|
+
// Function to run a command and display its output
|
|
14
|
+
function runCommand(command, description) {
|
|
15
|
+
console.log(`🔧 ${description}...`);
|
|
16
|
+
try {
|
|
17
|
+
execSync(command, { stdio: "inherit" });
|
|
18
|
+
console.log("✅ Success\n");
|
|
19
|
+
return true;
|
|
20
|
+
} catch (error) {
|
|
21
|
+
console.log(`❌ Failed: ${error.message}\n`);
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Update package lists
|
|
27
|
+
runCommand("sudo apt-get update", "Updating package lists");
|
|
28
|
+
|
|
29
|
+
// Install build tools
|
|
30
|
+
runCommand("sudo apt-get install -y build-essential", "Installing build tools");
|
|
31
|
+
|
|
32
|
+
// Install mingw-w64 for Windows cross-compilation
|
|
33
|
+
runCommand("sudo apt-get install -y mingw-w64", "Installing mingw-w64");
|
|
34
|
+
|
|
35
|
+
// Try installing additional mingw packages if needed
|
|
36
|
+
runCommand(
|
|
37
|
+
"sudo apt-get install -y gcc-mingw-w64-x86-64",
|
|
38
|
+
"Installing additional mingw packages",
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
// Install Rust targets
|
|
42
|
+
console.log("🔧 Installing Rust target platforms...");
|
|
43
|
+
try {
|
|
44
|
+
// Windows target
|
|
45
|
+
runCommand("rustup target add x86_64-pc-windows-gnu", {
|
|
46
|
+
stdio: "inherit",
|
|
47
|
+
maxBuffer: 1024 * 1024,
|
|
48
|
+
});
|
|
49
|
+
console.log("✅ Added x86_64-pc-windows-gnu target");
|
|
50
|
+
|
|
51
|
+
// Linux target (usually already installed)
|
|
52
|
+
try {
|
|
53
|
+
execSync("rustup target add x86_64-unknown-linux-gnu", {
|
|
54
|
+
stdio: "inherit",
|
|
55
|
+
maxBuffer: 1024 * 1024,
|
|
56
|
+
});
|
|
57
|
+
console.log("✅ Added x86_64-unknown-linux-gnu target");
|
|
58
|
+
} catch (e) {
|
|
59
|
+
console.log("ℹ️ Linux target may already be installed");
|
|
60
|
+
}
|
|
61
|
+
console.log("✅ Rust targets installed\n");
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.log(`❌ Failed to install Rust targets: ${error.message}\n`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Set up environment variables for cross-compilation
|
|
67
|
+
console.log("💡 Setting up environment variables...");
|
|
68
|
+
console.log(`
|
|
69
|
+
Add these lines to your ~/.bashrc or ~/.zshrc:
|
|
70
|
+
export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc
|
|
71
|
+
export CC_x86_64_pc_windows_gnu=x86_64-w64-mingw32-gcc
|
|
72
|
+
export CXX_x86_64_pc_windows_gnu=x86_64-w64-mingw32-g++
|
|
73
|
+
|
|
74
|
+
Then run: source ~/.bashrc or source ~/.zshrc
|
|
75
|
+
`);
|
|
76
|
+
|
|
77
|
+
// Verify installation
|
|
78
|
+
console.log("🔍 Verifying installation...");
|
|
79
|
+
try {
|
|
80
|
+
// Check mingw installation
|
|
81
|
+
execSync("x86_64-w64-mingw32-gcc --version", {
|
|
82
|
+
stdio: "inherit",
|
|
83
|
+
maxBuffer: 1024 * 1024,
|
|
84
|
+
});
|
|
85
|
+
console.log("✅ MinGW-w64 is properly installed");
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.log(
|
|
88
|
+
"⚠️ MinGW-w64 verification failed, but installation may have succeeded",
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
// Check Rust targets
|
|
94
|
+
const targets = execSync("rustup target list --installed", {
|
|
95
|
+
encoding: "utf8",
|
|
96
|
+
maxBuffer: 1024 * 1024,
|
|
97
|
+
});
|
|
98
|
+
if (targets.includes("x86_64-pc-windows-gnu")) {
|
|
99
|
+
console.log("✅ Windows target is installed");
|
|
100
|
+
} else {
|
|
101
|
+
console.log("⚠️ Windows target may not be properly installed");
|
|
102
|
+
}
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.log("⚠️ Could not verify Rust targets");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
console.log("\n🎉 WSL setup completed!");
|
|
108
|
+
console.log("\n📦 Next steps:");
|
|
109
|
+
console.log("1. Set up environment variables (see instructions above)");
|
|
110
|
+
console.log("2. Run: npm run build-binaries");
|
|
111
|
+
console.log("3. Test the built binaries");
|
|
112
|
+
console.log("\n💡 For more information, see WSL_BUILD_GUIDE.md");
|
package/scripts/test.js
ADDED
|
File without changes
|