Compare commits
No commits in common. "windows-native" and "main" have entirely different histories.
windows-na
...
main
|
|
@ -3,7 +3,6 @@ build/ffi/
|
||||||
*.o
|
*.o
|
||||||
wavs/
|
wavs/
|
||||||
*.a
|
*.a
|
||||||
build/
|
|
||||||
target/
|
target/
|
||||||
examples/vids/
|
examples/vids/
|
||||||
assets/old/
|
assets/old/
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,3 @@ tokio = { version = "1", features = ["rt", "rt-multi-thread"] }
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
tiny-skia = "0.11"
|
tiny-skia = "0.11"
|
||||||
roxmltree = "0.20"
|
roxmltree = "0.20"
|
||||||
|
|
||||||
[target.'cfg(windows)'.build-dependencies]
|
|
||||||
winresource = "0.1"
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
fn main() {
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
embed_windows_icon();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
fn embed_windows_icon() {
|
|
||||||
let manifest = std::path::PathBuf::from(std::env::var_os("CARGO_MANIFEST_DIR").unwrap());
|
|
||||||
let repo_root = manifest.parent().unwrap().parent().unwrap();
|
|
||||||
let icon = repo_root.join("build").join("assets").join("femm.ico");
|
|
||||||
println!("cargo:rerun-if-changed={}", icon.display());
|
|
||||||
if !icon.is_file() {
|
|
||||||
println!("cargo:warning=femm.ico not found at {} - skipping icon embed (run scripts/windows/build.ps1 to generate)", icon.display());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut res = winresource::WindowsResource::new();
|
|
||||||
res.set_icon(icon.to_str().expect("non-utf8 icon path"));
|
|
||||||
res.compile().expect("winresource compile failed");
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
//! iced shell entry point for the FEMM 4.2 port.
|
//! iced shell entry point for the FEMM 4.2 port.
|
||||||
|
|
||||||
#![cfg_attr(all(target_os = "windows", not(debug_assertions)), windows_subsystem = "windows")]
|
|
||||||
|
|
||||||
mod doc_canvas;
|
mod doc_canvas;
|
||||||
mod export;
|
mod export;
|
||||||
mod kinematic;
|
mod kinematic;
|
||||||
|
|
@ -382,7 +380,7 @@ impl App {
|
||||||
.pick_file();
|
.pick_file();
|
||||||
let Some(path) = picked else { return Task::none(); };
|
let Some(path) = picked else { return Task::none(); };
|
||||||
match svg_io::import_svg(&path) {
|
match svg_io::import_svg(&path) {
|
||||||
Ok((doc, warnings)) => {
|
Ok(doc) => {
|
||||||
self.doc = doc;
|
self.doc = doc;
|
||||||
self.mesh = None;
|
self.mesh = None;
|
||||||
self.solution = None;
|
self.solution = None;
|
||||||
|
|
@ -390,9 +388,8 @@ impl App {
|
||||||
self.simulation = None;
|
self.simulation = None;
|
||||||
self.source_label = path.file_name().and_then(|s| s.to_str()).unwrap_or("?").to_string();
|
self.source_label = path.file_name().and_then(|s| s.to_str()).unwrap_or("?").to_string();
|
||||||
self.source_path = Some(path.clone());
|
self.source_path = Some(path.clone());
|
||||||
let suffix = if warnings.is_empty() { String::new() } else { format!(" ({})", warnings.join("; ")) };
|
|
||||||
self.status = format!(
|
self.status = format!(
|
||||||
"imported {}: {} nodes, {} segs, {} arcs, {} labels{suffix}",
|
"imported {}: {} nodes, {} segs, {} arcs, {} labels",
|
||||||
path.display(),
|
path.display(),
|
||||||
self.doc.nodes.len(),
|
self.doc.nodes.len(),
|
||||||
self.doc.segments.len(),
|
self.doc.segments.len(),
|
||||||
|
|
@ -2068,7 +2065,7 @@ fn compute_frame(base: FemmDoc, tracks: Vec<kinematic::Track>, frame_idx: i64, d
|
||||||
title: String::from("frame save .pbc failed"),
|
title: String::from("frame save .pbc failed"),
|
||||||
body: format!("{pbc_path:?}\n\n{e}"),
|
body: format!("{pbc_path:?}\n\n{e}"),
|
||||||
})?;
|
})?;
|
||||||
let tri_out = quiet_command(&triangle)
|
let tri_out = std::process::Command::new(&triangle)
|
||||||
.args([
|
.args([
|
||||||
"-p", "-P", "-e", "-A", "-a", "-z", "-Q", "-I",
|
"-p", "-P", "-e", "-A", "-a", "-z", "-Q", "-I",
|
||||||
&format!("-q{min_angle}"),
|
&format!("-q{min_angle}"),
|
||||||
|
|
@ -2107,7 +2104,7 @@ fn compute_frame(base: FemmDoc, tracks: Vec<kinematic::Track>, frame_idx: i64, d
|
||||||
title: String::from("femm-mag-solve binary missing"),
|
title: String::from("femm-mag-solve binary missing"),
|
||||||
body: String::from("run `cargo xtask install`"),
|
body: String::from("run `cargo xtask install`"),
|
||||||
})?;
|
})?;
|
||||||
let solver_out = quiet_command(&helper)
|
let solver_out = std::process::Command::new(&helper)
|
||||||
.arg(&stem_str)
|
.arg(&stem_str)
|
||||||
.output()
|
.output()
|
||||||
.map_err(|e| ErrorReport {
|
.map_err(|e| ErrorReport {
|
||||||
|
|
@ -2441,7 +2438,7 @@ fn run_mesh(doc: &FemmDoc) -> Result<Mesh, ErrorReport> {
|
||||||
|
|
||||||
let triangle = locate_triangle().ok_or_else(|| ErrorReport {
|
let triangle = locate_triangle().ok_or_else(|| ErrorReport {
|
||||||
title: String::from("triangle binary missing"),
|
title: String::from("triangle binary missing"),
|
||||||
body: String::from("run `cargo xtask install` (or set $FEMM_TRIANGLE to the triangle executable)"),
|
body: String::from("expected triangle next to femm.app/Contents/MacOS/triangle, or under build/triangle/triangle, or at $FEMM_TRIANGLE - run scripts/macos/build_triangle.sh"),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let stem_str = stem.to_str().ok_or_else(|| ErrorReport {
|
let stem_str = stem.to_str().ok_or_else(|| ErrorReport {
|
||||||
|
|
@ -2449,7 +2446,7 @@ fn run_mesh(doc: &FemmDoc) -> Result<Mesh, ErrorReport> {
|
||||||
body: format!("{stem:?}"),
|
body: format!("{stem:?}"),
|
||||||
})?;
|
})?;
|
||||||
let min_angle = if doc.min_angle > 0.0 { doc.min_angle } else { MIN_ANGLE_DEG };
|
let min_angle = if doc.min_angle > 0.0 { doc.min_angle } else { MIN_ANGLE_DEG };
|
||||||
let output = quiet_command(&triangle)
|
let output = std::process::Command::new(&triangle)
|
||||||
.args([
|
.args([
|
||||||
"-p", "-P", "-e", "-A", "-a", "-z", "-Q", "-I",
|
"-p", "-P", "-e", "-A", "-a", "-z", "-Q", "-I",
|
||||||
&format!("-q{min_angle}"),
|
&format!("-q{min_angle}"),
|
||||||
|
|
@ -2486,10 +2483,10 @@ fn run_solve(stem: &Path) -> Result<(), ErrorReport> {
|
||||||
|
|
||||||
let helper = locate_mag_solver().ok_or_else(|| ErrorReport {
|
let helper = locate_mag_solver().ok_or_else(|| ErrorReport {
|
||||||
title: String::from("femm-mag-solve binary missing"),
|
title: String::from("femm-mag-solve binary missing"),
|
||||||
body: String::from("run `cargo xtask install` (or set $FEMM_MAG_SOLVE to the femm-mag-solve executable)"),
|
body: String::from("expected femm-mag-solve next to femm.app/Contents/MacOS/, or under target/release/, or at $FEMM_MAG_SOLVE - run `cargo xtask install`"),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let output = quiet_command(&helper)
|
let output = std::process::Command::new(&helper)
|
||||||
.arg(stem_str)
|
.arg(stem_str)
|
||||||
.output()
|
.output()
|
||||||
.map_err(|e| ErrorReport {
|
.map_err(|e| ErrorReport {
|
||||||
|
|
@ -2547,24 +2544,16 @@ fn unix_signal(status: &std::process::ExitStatus) -> Option<i32> {
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
fn unix_signal(_status: &std::process::ExitStatus) -> Option<i32> { None }
|
fn unix_signal(_status: &std::process::ExitStatus) -> Option<i32> { None }
|
||||||
|
|
||||||
fn quiet_command(program: &std::path::Path) -> std::process::Command {
|
/// resolves the femm-mag-solve helper path from the bundled .app, the dev target dir, or $FEMM_MAG_SOLVE.
|
||||||
let mut cmd = std::process::Command::new(program);
|
|
||||||
#[cfg(windows)]
|
|
||||||
{
|
|
||||||
use std::os::windows::process::CommandExt;
|
|
||||||
const CREATE_NO_WINDOW: u32 = 0x0800_0000;
|
|
||||||
cmd.creation_flags(CREATE_NO_WINDOW);
|
|
||||||
}
|
|
||||||
cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
/// resolves the femm-mag-solve helper path from the bundled app, the dev target dir, or $FEMM_MAG_SOLVE.
|
|
||||||
fn locate_mag_solver() -> Option<std::path::PathBuf> {
|
fn locate_mag_solver() -> Option<std::path::PathBuf> {
|
||||||
let exe_name = format!("femm-mag-solve{}", std::env::consts::EXE_SUFFIX);
|
|
||||||
if let Ok(exe) = std::env::current_exe() {
|
if let Ok(exe) = std::env::current_exe() {
|
||||||
if let Some(parent) = exe.parent() {
|
if let Some(parent) = exe.parent() {
|
||||||
let bundled = parent.join(&exe_name);
|
let bundled = parent.join("femm-mag-solve");
|
||||||
if bundled.is_file() { return Some(bundled); }
|
if bundled.is_file() { return Some(bundled); }
|
||||||
|
let dev = parent.join("femm-mag-solve");
|
||||||
|
if let Ok(canon) = dev.canonicalize() {
|
||||||
|
if canon.is_file() { return Some(canon); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Ok(env_path) = std::env::var("FEMM_MAG_SOLVE") {
|
if let Ok(env_path) = std::env::var("FEMM_MAG_SOLVE") {
|
||||||
|
|
@ -2585,16 +2574,15 @@ fn panic_payload_text(payload: &Box<dyn std::any::Any + Send>) -> String {
|
||||||
String::from("panic payload was not a string")
|
String::from("panic payload was not a string")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// resolves the Triangle binary path from the bundled app, the dev build dir, or $FEMM_TRIANGLE.
|
/// resolves the Triangle binary path from the bundled .app, the dev build dir, or $FEMM_TRIANGLE.
|
||||||
fn locate_triangle() -> Option<std::path::PathBuf> {
|
fn locate_triangle() -> Option<std::path::PathBuf> {
|
||||||
let exe_name = format!("triangle{}", std::env::consts::EXE_SUFFIX);
|
|
||||||
if let Ok(exe) = std::env::current_exe() {
|
if let Ok(exe) = std::env::current_exe() {
|
||||||
if let Some(parent) = exe.parent() {
|
if let Some(parent) = exe.parent() {
|
||||||
let bundled = parent.join(&exe_name);
|
let bundled = parent.join("triangle");
|
||||||
if bundled.is_file() { return Some(bundled); }
|
if bundled.is_file() { return Some(bundled); }
|
||||||
for ancestor in parent.ancestors().take(6) {
|
let dev = parent.join("../../build/triangle/triangle");
|
||||||
let dev = ancestor.join("build").join("triangle").join(&exe_name);
|
if let Ok(canon) = dev.canonicalize() {
|
||||||
if dev.is_file() { return Some(dev); }
|
if canon.is_file() { return Some(canon); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,42 +9,58 @@ use femm_doc_mag::{
|
||||||
|
|
||||||
const NODE_MERGE_TOL: f64 = 1e-3;
|
const NODE_MERGE_TOL: f64 = 1e-3;
|
||||||
|
|
||||||
/// produces a fresh FemmDoc from the SVG at path, returning any non-fatal warnings (bezier approximation, missing materials, etc.) alongside the doc.
|
/// produces a fresh FemmDoc from the SVG at path, prompting (via rfd) to convert any non-circular ellipse into a circle on ambiguous radii.
|
||||||
pub fn import_svg(path: &Path) -> Result<(FemmDoc, Vec<String>), String> {
|
pub fn import_svg(path: &Path) -> Result<FemmDoc, String> {
|
||||||
let raw = std::fs::read_to_string(path).map_err(|e| format!("read svg: {e}"))?;
|
let raw = std::fs::read_to_string(path).map_err(|e| format!("read svg: {e}"))?;
|
||||||
parse_svg_text_with_warnings(&raw)
|
parse_svg_text(&raw, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// parses an SVG text buffer into a FemmDoc; non-circular ellipses are silently converted to circles (average radius). the `_prompt_for_ellipse` argument is accepted for backwards compatibility but ignored.
|
/// parses an SVG text buffer into a FemmDoc; if prompt_for_ellipse is true and any non-circular ellipse is found, asks the user (rfd dialog) whether to convert.
|
||||||
pub fn parse_svg_text(src: &str, _prompt_for_ellipse: bool) -> Result<FemmDoc, String> {
|
pub fn parse_svg_text(src: &str, prompt_for_ellipse: bool) -> Result<FemmDoc, String> {
|
||||||
let (doc, _) = parse_svg_text_with_warnings(src)?;
|
|
||||||
Ok(doc)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// like parse_svg_text but also returns a list of human-readable warnings the caller can surface (bezier approximation, shapes missing material, etc.).
|
|
||||||
pub fn parse_svg_text_with_warnings(src: &str) -> Result<(FemmDoc, Vec<String>), String> {
|
|
||||||
let xml = Document::parse(src).map_err(|e| format!("svg parse: {e}"))?;
|
let xml = Document::parse(src).map_err(|e| format!("svg parse: {e}"))?;
|
||||||
let mut builder = Builder::new();
|
let mut builder = Builder::new();
|
||||||
let mut warnings = Warnings::default();
|
let mut warnings = Warnings::default();
|
||||||
walk(xml.root_element(), Mat3::identity(), &mut builder, &mut warnings)?;
|
walk(xml.root_element(), Mat3::identity(), &mut builder, &mut warnings)?;
|
||||||
|
|
||||||
let mut messages = Vec::new();
|
let convert_ellipses = if warnings.has_ellipses() && prompt_for_ellipse {
|
||||||
if warnings.has_ellipses() {
|
let r = rfd::MessageDialog::new()
|
||||||
messages.push(format!("converted {} non-circular ellipse(s) to circles", warnings.ellipse_count));
|
.set_title("Non-circular ellipses detected")
|
||||||
}
|
.set_description(&format!(
|
||||||
|
"Found {} non-circular ellipse(s). Converting to circles (average radius) keeps the mesh clean and avoids the polygon-approximation penalty. Convert?",
|
||||||
|
warnings.ellipse_count
|
||||||
|
))
|
||||||
|
.set_buttons(rfd::MessageButtons::YesNo)
|
||||||
|
.show();
|
||||||
|
matches!(r, rfd::MessageDialogResult::Yes)
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
};
|
||||||
|
|
||||||
if !warnings.bezier_paths.is_empty() {
|
if !warnings.bezier_paths.is_empty() {
|
||||||
messages.push(format!("approximated {} bezier curve(s) with polylines", warnings.bezier_paths.len()));
|
rfd::MessageDialog::new()
|
||||||
}
|
.set_title("Bezier curves approximated")
|
||||||
if !warnings.no_material_shapes.is_empty() {
|
.set_description(&format!(
|
||||||
messages.push(format!(
|
"{} bezier curve(s) approximated with straight-line polylines. For smooth curves, replace with circles or arc paths.",
|
||||||
"{} shape(s) missing material (add <title>MaterialName</title>): {}",
|
warnings.bezier_paths.len(),
|
||||||
warnings.no_material_shapes.len(),
|
))
|
||||||
warnings.no_material_shapes.join(", "),
|
.set_buttons(rfd::MessageButtons::Ok)
|
||||||
));
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
let doc = builder.finalize(true);
|
if !warnings.no_material_shapes.is_empty() {
|
||||||
Ok((doc, messages))
|
let ids = warnings.no_material_shapes.join(", ");
|
||||||
|
rfd::MessageDialog::new()
|
||||||
|
.set_title("Shapes missing material")
|
||||||
|
.set_description(&format!(
|
||||||
|
"{} shape(s) have a recognized class (Block/Segment/Toroid/Disc) but no material name. Add a <title> child like <title>Steel</title> so the importer can label the region. Affected: {ids}",
|
||||||
|
warnings.no_material_shapes.len(),
|
||||||
|
))
|
||||||
|
.set_buttons(rfd::MessageButtons::Ok)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
let doc = builder.finalize(convert_ellipses);
|
||||||
|
Ok(doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// emits an SVG containing every node (as `<circle>`), segment (as `<line>`), arc (as `<path>`), and block label (as `<g><circle><text>`); writes y-flipped so it renders right-side-up in any viewer.
|
/// emits an SVG containing every node (as `<circle>`), segment (as `<line>`), arc (as `<path>`), and block label (as `<g><circle><text>`); writes y-flipped so it renders right-side-up in any viewer.
|
||||||
|
|
|
||||||
|
|
@ -13,34 +13,20 @@ fn main() {
|
||||||
// re-run on changes to any FFI header, build script, or solver source dir.
|
// re-run on changes to any FFI header, build script, or solver source dir.
|
||||||
println!("cargo:rerun-if-changed={}", ffi_dir.display());
|
println!("cargo:rerun-if-changed={}", ffi_dir.display());
|
||||||
println!("cargo:rerun-if-changed={}", repo_root.join("scripts/macos/build_ffi.sh").display());
|
println!("cargo:rerun-if-changed={}", repo_root.join("scripts/macos/build_ffi.sh").display());
|
||||||
println!("cargo:rerun-if-changed={}", repo_root.join("scripts/windows/build_ffi.ps1").display());
|
|
||||||
println!("cargo:rerun-if-changed={}", repo_root.join("scripts/windows/_toolchain.ps1").display());
|
|
||||||
for engine in ["fkn", "belasolv", "csolv", "hsolv", "liblua", "compat"] {
|
for engine in ["fkn", "belasolv", "csolv", "hsolv", "liblua", "compat"] {
|
||||||
println!("cargo:rerun-if-changed={}", repo_root.join(engine).display());
|
println!("cargo:rerun-if-changed={}", repo_root.join(engine).display());
|
||||||
}
|
}
|
||||||
|
|
||||||
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
|
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
|
||||||
let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default();
|
let script = match target_os.as_str() {
|
||||||
let status = match target_os.as_str() {
|
"macos" => repo_root.join("scripts/macos/build_ffi.sh"),
|
||||||
"macos" => Command::new("bash")
|
|
||||||
.arg(repo_root.join("scripts/macos/build_ffi.sh"))
|
|
||||||
.status()
|
|
||||||
.expect("failed to invoke bash for engine build script"),
|
|
||||||
"windows" => {
|
|
||||||
let script = repo_root.join("scripts/windows/build_ffi.ps1");
|
|
||||||
Command::new("pwsh")
|
|
||||||
.args([
|
|
||||||
"-NoProfile",
|
|
||||||
"-ExecutionPolicy",
|
|
||||||
"Bypass",
|
|
||||||
"-File",
|
|
||||||
])
|
|
||||||
.arg(&script)
|
|
||||||
.status()
|
|
||||||
.expect("failed to invoke pwsh for engine build script")
|
|
||||||
}
|
|
||||||
other => panic!("femm-sys: no engine build script wired up for target_os={other}"),
|
other => panic!("femm-sys: no engine build script wired up for target_os={other}"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let status = Command::new("bash")
|
||||||
|
.arg(&script)
|
||||||
|
.status()
|
||||||
|
.expect("failed to invoke bash for engine build script");
|
||||||
if !status.success() {
|
if !status.success() {
|
||||||
panic!("engine build script exited with {status}");
|
panic!("engine build script exited with {status}");
|
||||||
}
|
}
|
||||||
|
|
@ -49,13 +35,7 @@ fn main() {
|
||||||
for lib in ["femm_mag", "femm_elec", "femm_heat", "femm_curr"] {
|
for lib in ["femm_mag", "femm_elec", "femm_heat", "femm_curr"] {
|
||||||
println!("cargo:rustc-link-lib=static={lib}");
|
println!("cargo:rustc-link-lib=static={lib}");
|
||||||
}
|
}
|
||||||
match (target_os.as_str(), target_env.as_str()) {
|
println!("cargo:rustc-link-lib=dylib=c++");
|
||||||
("macos", _) => println!("cargo:rustc-link-lib=dylib=c++"),
|
|
||||||
("windows", "gnu") => println!("cargo:rustc-link-lib=dylib=stdc++"),
|
|
||||||
("windows", "gnullvm") => println!("cargo:rustc-link-lib=dylib=c++"),
|
|
||||||
("windows", "msvc") => { /* MSVC links the C++ runtime automatically */ }
|
|
||||||
_ => println!("cargo:rustc-link-lib=dylib=stdc++"),
|
|
||||||
}
|
|
||||||
|
|
||||||
let bindings = bindgen::Builder::default()
|
let bindings = bindgen::Builder::default()
|
||||||
.header(manifest.join("wrapper.h").to_str().unwrap())
|
.header(manifest.join("wrapper.h").to_str().unwrap())
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -59,7 +58,7 @@ typedef unsigned long lint32; /* unsigned int with at least 32 bits */
|
||||||
** conversion of pointer to int (for hashing only)
|
** conversion of pointer to int (for hashing only)
|
||||||
** (the shift removes bits that are usually 0 because of alignment)
|
** (the shift removes bits that are usually 0 because of alignment)
|
||||||
*/
|
*/
|
||||||
#define IntPoint(p) (((uintptr_t)(p)) >> 3)
|
#define IntPoint(p) (((unsigned long)(p)) >> 3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,119 +0,0 @@
|
||||||
# Toolchain detection. Picks a backend appropriate for the host arch:
|
|
||||||
# x64 host -> MSVC (x64) or MinGW (x86_64), Rust target = host default or x86_64-pc-windows-gnu
|
|
||||||
# ARM64 host -> CLANGARM64 (msys2) or MinGW (x86_64, emulated, warned), Rust target = aarch64-pc-windows-gnullvm
|
|
||||||
# Dot-source this file: . "$PSScriptRoot\_toolchain.ps1"
|
|
||||||
|
|
||||||
$ErrorActionPreference = 'Stop'
|
|
||||||
|
|
||||||
function Get-HostArch {
|
|
||||||
if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64' -or $env:PROCESSOR_ARCHITEW6432 -eq 'ARM64') { return 'arm64' }
|
|
||||||
return 'x64'
|
|
||||||
}
|
|
||||||
|
|
||||||
function Initialize-VsEnv {
|
|
||||||
param([string]$VcVars)
|
|
||||||
$tmp = New-TemporaryFile
|
|
||||||
try {
|
|
||||||
cmd /c "`"$VcVars`" x64 >NUL && set" | Out-File -FilePath $tmp -Encoding ascii
|
|
||||||
foreach ($line in Get-Content $tmp) {
|
|
||||||
if ($line -match '^([^=]+)=(.*)$') {
|
|
||||||
Set-Item -Path "env:$($Matches[1])" -Value $Matches[2]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
Remove-Item $tmp -Force -ErrorAction SilentlyContinue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Find-VsInstall {
|
|
||||||
$vswhere = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe'
|
|
||||||
if (-not (Test-Path $vswhere)) {
|
|
||||||
$vswhere = Join-Path $env:ProgramFiles 'Microsoft Visual Studio\Installer\vswhere.exe'
|
|
||||||
}
|
|
||||||
if (-not (Test-Path $vswhere)) { return $null }
|
|
||||||
|
|
||||||
$install = & $vswhere -latest -products * `
|
|
||||||
-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 `
|
|
||||||
-property installationPath 2>$null
|
|
||||||
if (-not $install) { return $null }
|
|
||||||
|
|
||||||
$vcvars = Join-Path $install 'VC\Auxiliary\Build\vcvars64.bat'
|
|
||||||
if (Test-Path $vcvars) { return $vcvars }
|
|
||||||
return $null
|
|
||||||
}
|
|
||||||
|
|
||||||
function Find-MingwBin {
|
|
||||||
if ($env:MINGW_PREFIX -and (Test-Path (Join-Path $env:MINGW_PREFIX 'g++.exe'))) {
|
|
||||||
return $env:MINGW_PREFIX
|
|
||||||
}
|
|
||||||
$gxx = Get-Command g++.exe -ErrorAction SilentlyContinue
|
|
||||||
if ($gxx) { return (Split-Path $gxx.Source -Parent) }
|
|
||||||
foreach ($p in @(
|
|
||||||
'C:\msys64\mingw64\bin',
|
|
||||||
'C:\msys64\ucrt64\bin',
|
|
||||||
'C:\mingw64\bin',
|
|
||||||
'C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin'
|
|
||||||
)) {
|
|
||||||
if (Test-Path (Join-Path $p 'g++.exe')) { return $p }
|
|
||||||
}
|
|
||||||
return $null
|
|
||||||
}
|
|
||||||
|
|
||||||
function Find-ClangArm64Bin {
|
|
||||||
if ($env:CLANGARM64_PREFIX -and (Test-Path (Join-Path $env:CLANGARM64_PREFIX 'clang++.exe'))) {
|
|
||||||
return $env:CLANGARM64_PREFIX
|
|
||||||
}
|
|
||||||
foreach ($p in @('C:\msys64\clangarm64\bin')) {
|
|
||||||
if (Test-Path (Join-Path $p 'clang++.exe')) { return $p }
|
|
||||||
}
|
|
||||||
return $null
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-Toolchain {
|
|
||||||
$hostArch = Get-HostArch
|
|
||||||
|
|
||||||
if ($hostArch -eq 'arm64') {
|
|
||||||
$clangBin = Find-ClangArm64Bin
|
|
||||||
if ($clangBin) {
|
|
||||||
return [pscustomobject]@{
|
|
||||||
Kind = 'clangarm64'
|
|
||||||
Ready = $true
|
|
||||||
Bin = $clangBin
|
|
||||||
CargoTarget = 'aarch64-pc-windows-gnullvm'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$mingw = Find-MingwBin
|
|
||||||
if ($mingw) {
|
|
||||||
Write-Warning "ARM64 host but only x86_64 MinGW found; resulting binaries will run under emulation and may crash at startup. Install msys2 CLANGARM64 (pacman -S mingw-w64-clang-aarch64-toolchain)."
|
|
||||||
return [pscustomobject]@{ Kind = 'mingw'; Ready = $true; MingwBin = $mingw; CargoTarget = 'x86_64-pc-windows-gnu' }
|
|
||||||
}
|
|
||||||
throw "No ARM64 C++ toolchain found. Install msys2 CLANGARM64 (pacman -S mingw-w64-clang-aarch64-toolchain) or Visual Studio ARM64 C++ tools."
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Get-Command cl.exe -ErrorAction SilentlyContinue) {
|
|
||||||
return [pscustomobject]@{ Kind = 'msvc'; Ready = $true; VcVars = $null; CargoTarget = '' }
|
|
||||||
}
|
|
||||||
$vcvars = Find-VsInstall
|
|
||||||
if ($vcvars) {
|
|
||||||
return [pscustomobject]@{ Kind = 'msvc'; Ready = $false; VcVars = $vcvars; CargoTarget = '' }
|
|
||||||
}
|
|
||||||
$mingw = Find-MingwBin
|
|
||||||
if ($mingw) {
|
|
||||||
return [pscustomobject]@{ Kind = 'mingw'; Ready = $true; MingwBin = $mingw; CargoTarget = 'x86_64-pc-windows-gnu' }
|
|
||||||
}
|
|
||||||
throw "No C++ toolchain found. Install Visual Studio Build Tools (with the C++ workload) or MinGW-w64."
|
|
||||||
}
|
|
||||||
|
|
||||||
function Initialize-Toolchain {
|
|
||||||
param([pscustomobject]$Toolchain)
|
|
||||||
if ($Toolchain.Kind -eq 'msvc' -and -not $Toolchain.Ready) {
|
|
||||||
Write-Host "Importing MSVC environment from $($Toolchain.VcVars)"
|
|
||||||
Initialize-VsEnv -VcVars $Toolchain.VcVars
|
|
||||||
}
|
|
||||||
if ($Toolchain.Kind -eq 'mingw' -and $Toolchain.MingwBin -and ($env:PATH -notlike "*$($Toolchain.MingwBin)*")) {
|
|
||||||
$env:PATH = "$($Toolchain.MingwBin);$env:PATH"
|
|
||||||
}
|
|
||||||
if ($Toolchain.Kind -eq 'clangarm64' -and $Toolchain.Bin -and ($env:PATH -notlike "*$($Toolchain.Bin)*")) {
|
|
||||||
$env:PATH = "$($Toolchain.Bin);$env:PATH"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
#requires -Version 7
|
|
||||||
# Top-level Windows release build. Mirrors scripts/macos/build.sh.
|
|
||||||
|
|
||||||
$ErrorActionPreference = 'Stop'
|
|
||||||
|
|
||||||
$Root = Resolve-Path (Join-Path $PSScriptRoot '..\..')
|
|
||||||
Set-Location $Root
|
|
||||||
|
|
||||||
if (-not $IsWindows) {
|
|
||||||
Write-Error "wrong platform: $($PSVersionTable.OS) - use cargo xtask build"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
. (Join-Path $PSScriptRoot '_toolchain.ps1')
|
|
||||||
$tc = Get-Toolchain
|
|
||||||
Initialize-Toolchain $tc
|
|
||||||
Write-Host "toolchain: $($tc.Kind)"
|
|
||||||
|
|
||||||
$env:PROFILE = 'release'
|
|
||||||
|
|
||||||
$Build = Join-Path $Root 'build'
|
|
||||||
$BinDir = Join-Path $Build 'bin\femm'
|
|
||||||
|
|
||||||
Write-Host 'Building Triangle...'
|
|
||||||
& (Join-Path $PSScriptRoot 'build_triangle.ps1')
|
|
||||||
|
|
||||||
$tri = Join-Path $Root 'build\triangle\triangle.exe'
|
|
||||||
if (-not (Test-Path $tri)) { Write-Error "triangle binary missing at $tri"; exit 1 }
|
|
||||||
|
|
||||||
# femm-app/build.rs embeds this into femm.exe, so it must exist before cargo build.
|
|
||||||
$svg = Join-Path $Root 'assets\femm.svg'
|
|
||||||
$icoOut = Join-Path $Build 'assets\femm.ico'
|
|
||||||
New-Item -ItemType Directory -Force -Path (Split-Path $icoOut) | Out-Null
|
|
||||||
if (Test-Path $svg) {
|
|
||||||
$magick = Get-Command magick.exe -ErrorAction SilentlyContinue
|
|
||||||
if ($magick) {
|
|
||||||
& $magick.Source -background none $svg -define icon:auto-resize=16,32,48,64,128,256 $icoOut
|
|
||||||
if ($LASTEXITCODE -ne 0) { Write-Warning "magick failed to build $icoOut ($LASTEXITCODE)" }
|
|
||||||
} else {
|
|
||||||
Write-Warning 'magick not found - femm.exe will be built without an embedded icon'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host 'Building Rust workspace (release)...'
|
|
||||||
$cargoArgs = @('build','--release','-p','femm-app','-p','femm-mag-solve')
|
|
||||||
if ($tc.CargoTarget) {
|
|
||||||
$cargoArgs += @('--target',$tc.CargoTarget)
|
|
||||||
}
|
|
||||||
& cargo @cargoArgs
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw "cargo build failed ($LASTEXITCODE)" }
|
|
||||||
|
|
||||||
$targetDir = if ($tc.CargoTarget) {
|
|
||||||
Join-Path $Root "target\$($tc.CargoTarget)\release"
|
|
||||||
} else {
|
|
||||||
Join-Path $Root 'target\release'
|
|
||||||
}
|
|
||||||
$bin = Join-Path $targetDir 'femm.exe'
|
|
||||||
$solve = Join-Path $targetDir 'femm-mag-solve.exe'
|
|
||||||
foreach ($p in @($bin, $solve)) {
|
|
||||||
if (-not (Test-Path $p)) { Write-Error "missing build output: $p"; exit 1 }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Test-Path $BinDir) { Remove-Item $BinDir -Recurse -Force }
|
|
||||||
New-Item -ItemType Directory -Force -Path $BinDir | Out-Null
|
|
||||||
|
|
||||||
Copy-Item $bin (Join-Path $BinDir 'femm.exe')
|
|
||||||
Copy-Item $solve (Join-Path $BinDir 'femm-mag-solve.exe')
|
|
||||||
Copy-Item $tri (Join-Path $BinDir 'triangle.exe')
|
|
||||||
|
|
||||||
if (Test-Path $icoOut) {
|
|
||||||
Copy-Item $icoOut (Join-Path $BinDir 'femm.ico')
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "Built: $BinDir"
|
|
||||||
|
|
@ -1,227 +0,0 @@
|
||||||
#requires -Version 7
|
|
||||||
# Per-engine static archives for mag/elec/heat/curr.
|
|
||||||
# MSVC: cl /c + lib /OUT (no inter-engine symbol localization yet).
|
|
||||||
# MinGW: g++ -c + ld -r + objcopy --keep-global-symbols + ar — mirrors scripts/macos/build_ffi.sh.
|
|
||||||
|
|
||||||
$ErrorActionPreference = 'Stop'
|
|
||||||
|
|
||||||
$Root = Resolve-Path (Join-Path $PSScriptRoot '..\..')
|
|
||||||
$Build = if ($env:BUILD) { $env:BUILD } else { Join-Path $Root 'build\ffi' }
|
|
||||||
|
|
||||||
. (Join-Path $PSScriptRoot '_toolchain.ps1')
|
|
||||||
$tc = Get-Toolchain
|
|
||||||
Initialize-Toolchain $tc
|
|
||||||
|
|
||||||
$buildProfile = if ($env:PROFILE) { $env:PROFILE } else { 'release' }
|
|
||||||
|
|
||||||
foreach ($d in @('fkn','liblua','belasolv','csolv','hsolv','ffi','exports')) {
|
|
||||||
New-Item -ItemType Directory -Force -Path (Join-Path $Build $d) | Out-Null
|
|
||||||
}
|
|
||||||
|
|
||||||
function Compile-Many {
|
|
||||||
param(
|
|
||||||
[string[]]$Includes,
|
|
||||||
[string]$OutDir,
|
|
||||||
[string[]]$Sources
|
|
||||||
)
|
|
||||||
foreach ($src in $Sources) {
|
|
||||||
$base = [IO.Path]::GetFileNameWithoutExtension($src)
|
|
||||||
if ($tc.Kind -eq 'msvc') {
|
|
||||||
$obj = Join-Path $OutDir "$base.obj"
|
|
||||||
$cxxflags = if ($buildProfile -eq 'release') {
|
|
||||||
@('/nologo','/std:c++17','/EHs-c-','/GR-','/O2','/DNDEBUG','/W0','/D_CRT_SECURE_NO_WARNINGS')
|
|
||||||
} else {
|
|
||||||
@('/nologo','/std:c++17','/EHs-c-','/GR-','/Od','/Zi','/W0','/D_CRT_SECURE_NO_WARNINGS')
|
|
||||||
}
|
|
||||||
$incFlags = $Includes | ForEach-Object { "/I$_" }
|
|
||||||
& cl.exe @cxxflags @incFlags /c $src "/Fo:$obj" | Out-Null
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw "cl.exe failed on $src ($LASTEXITCODE)" }
|
|
||||||
} else {
|
|
||||||
$obj = Join-Path $OutDir "$base.o"
|
|
||||||
$cxxflags = if ($buildProfile -eq 'release') {
|
|
||||||
@('-std=c++17','-fno-exceptions','-fno-rtti','-fpermissive','-O3','-DNDEBUG','-w')
|
|
||||||
} else {
|
|
||||||
@('-std=c++17','-fno-exceptions','-fno-rtti','-fpermissive','-O0','-g','-w')
|
|
||||||
}
|
|
||||||
$incFlags = $Includes | ForEach-Object { "-I$_" }
|
|
||||||
$cxx = if ($tc.Kind -eq 'clangarm64') { Join-Path $tc.Bin 'clang++.exe' } else { 'g++.exe' }
|
|
||||||
& $cxx @cxxflags @incFlags -c $src -o $obj
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw "$cxx failed on $src ($LASTEXITCODE)" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# liblua — compiled against fkn's complex.h
|
|
||||||
Compile-Many `
|
|
||||||
-Includes @((Join-Path $Root 'fkn'), (Join-Path $Root 'liblua'), (Join-Path $Root 'compat')) `
|
|
||||||
-OutDir (Join-Path $Build 'liblua') `
|
|
||||||
-Sources @(
|
|
||||||
(Join-Path $Root 'liblua\lapi.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lauxlib.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lbaselib.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lcode.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\ldblib.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\ldebug.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\ldo.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lfunc.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lgc.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\liolib.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\llex.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lmathlib.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lmem.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lobject.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lparser.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lstate.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lstring.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lstrlib.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\ltable.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\ltests.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\ltm.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lundump.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lvm.cpp'),
|
|
||||||
(Join-Path $Root 'liblua\lzio.cpp')
|
|
||||||
)
|
|
||||||
|
|
||||||
Compile-Many `
|
|
||||||
-Includes @((Join-Path $Root 'fkn'), (Join-Path $Root 'compat')) `
|
|
||||||
-OutDir (Join-Path $Build 'fkn') `
|
|
||||||
-Sources @(
|
|
||||||
(Join-Path $Root 'fkn\complex.cpp'),
|
|
||||||
(Join-Path $Root 'fkn\cspars.cpp'),
|
|
||||||
(Join-Path $Root 'fkn\cuthill.cpp'),
|
|
||||||
(Join-Path $Root 'fkn\femmedoccore.cpp'),
|
|
||||||
(Join-Path $Root 'fkn\fullmatrix.cpp'),
|
|
||||||
(Join-Path $Root 'fkn\matprop.cpp'),
|
|
||||||
(Join-Path $Root 'fkn\prob1big.cpp'),
|
|
||||||
(Join-Path $Root 'fkn\prob2big.cpp'),
|
|
||||||
(Join-Path $Root 'fkn\prob3big.cpp'),
|
|
||||||
(Join-Path $Root 'fkn\prob4big.cpp'),
|
|
||||||
(Join-Path $Root 'fkn\spars.cpp')
|
|
||||||
)
|
|
||||||
|
|
||||||
Compile-Many `
|
|
||||||
-Includes @((Join-Path $Root 'belasolv'), (Join-Path $Root 'compat')) `
|
|
||||||
-OutDir (Join-Path $Build 'belasolv') `
|
|
||||||
-Sources @(
|
|
||||||
(Join-Path $Root 'belasolv\cuthill.cpp'),
|
|
||||||
(Join-Path $Root 'belasolv\femmedoccore.cpp'),
|
|
||||||
(Join-Path $Root 'belasolv\prob1big.cpp'),
|
|
||||||
(Join-Path $Root 'belasolv\spars.cpp')
|
|
||||||
)
|
|
||||||
|
|
||||||
Compile-Many `
|
|
||||||
-Includes @((Join-Path $Root 'csolv'), (Join-Path $Root 'compat')) `
|
|
||||||
-OutDir (Join-Path $Build 'csolv') `
|
|
||||||
-Sources @(
|
|
||||||
(Join-Path $Root 'csolv\complex.cpp'),
|
|
||||||
(Join-Path $Root 'csolv\cspars.cpp'),
|
|
||||||
(Join-Path $Root 'csolv\CUTHILL.CPP'),
|
|
||||||
(Join-Path $Root 'csolv\femmedoccore.cpp'),
|
|
||||||
(Join-Path $Root 'csolv\PROB1BIG.CPP')
|
|
||||||
)
|
|
||||||
|
|
||||||
Compile-Many `
|
|
||||||
-Includes @((Join-Path $Root 'hsolv'), (Join-Path $Root 'compat')) `
|
|
||||||
-OutDir (Join-Path $Build 'hsolv') `
|
|
||||||
-Sources @(
|
|
||||||
(Join-Path $Root 'hsolv\complex.cpp'),
|
|
||||||
(Join-Path $Root 'hsolv\CUTHILL.CPP'),
|
|
||||||
(Join-Path $Root 'hsolv\hsolvdoc.cpp'),
|
|
||||||
(Join-Path $Root 'hsolv\prob1big.cpp'),
|
|
||||||
(Join-Path $Root 'hsolv\SPARS.CPP')
|
|
||||||
)
|
|
||||||
|
|
||||||
# ffi shims — one TU per engine, plus the liblua complex-op shim.
|
|
||||||
Compile-Many -Includes @((Join-Path $Root 'fkn'), (Join-Path $Root 'compat')) -OutDir (Join-Path $Build 'ffi') -Sources @((Join-Path $Root 'ffi\femm_mag.cpp'))
|
|
||||||
Compile-Many -Includes @((Join-Path $Root 'belasolv'), (Join-Path $Root 'compat')) -OutDir (Join-Path $Build 'ffi') -Sources @((Join-Path $Root 'ffi\femm_elec.cpp'))
|
|
||||||
Compile-Many -Includes @((Join-Path $Root 'hsolv'), (Join-Path $Root 'compat')) -OutDir (Join-Path $Build 'ffi') -Sources @((Join-Path $Root 'ffi\femm_heat.cpp'))
|
|
||||||
Compile-Many -Includes @((Join-Path $Root 'csolv'), (Join-Path $Root 'compat')) -OutDir (Join-Path $Build 'ffi') -Sources @((Join-Path $Root 'ffi\femm_curr.cpp'))
|
|
||||||
Compile-Many -Includes @((Join-Path $Root 'liblua'), (Join-Path $Root 'compat')) -OutDir (Join-Path $Build 'ffi') -Sources @((Join-Path $Root 'ffi\femm_lua_complex_ops.cpp'))
|
|
||||||
|
|
||||||
if ($tc.Kind -eq 'msvc') {
|
|
||||||
# MSVC: bundle objects per engine via lib.exe. Note: inter-engine internal-symbol collisions
|
|
||||||
# (cuthill / femmedoccore / prob1big / spars all repeat across engines) are not localized here —
|
|
||||||
# if the Rust link step trips LNK2005, we'll need to merge to DLLs or namespace the C++ sources.
|
|
||||||
function Pack-Lib {
|
|
||||||
param([string]$Name, [string[]]$Objs)
|
|
||||||
$out = Join-Path $Build "$Name.lib"
|
|
||||||
if (Test-Path $out) { Remove-Item $out -Force }
|
|
||||||
& lib.exe /NOLOGO "/OUT:$out" @Objs | Out-Null
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw "lib.exe failed for $Name ($LASTEXITCODE)" }
|
|
||||||
}
|
|
||||||
Pack-Lib 'femm_mag' ((Get-ChildItem (Join-Path $Build 'fkn\*.obj') | ForEach-Object FullName) +
|
|
||||||
(Get-ChildItem (Join-Path $Build 'liblua\*.obj') | ForEach-Object FullName) +
|
|
||||||
@((Join-Path $Build 'ffi\femm_mag.obj'),
|
|
||||||
(Join-Path $Build 'ffi\femm_lua_complex_ops.obj')))
|
|
||||||
Pack-Lib 'femm_elec' ((Get-ChildItem (Join-Path $Build 'belasolv\*.obj') | ForEach-Object FullName) +
|
|
||||||
@((Join-Path $Build 'ffi\femm_elec.obj')))
|
|
||||||
Pack-Lib 'femm_heat' ((Get-ChildItem (Join-Path $Build 'hsolv\*.obj') | ForEach-Object FullName) +
|
|
||||||
@((Join-Path $Build 'ffi\femm_heat.obj')))
|
|
||||||
Pack-Lib 'femm_curr' ((Get-ChildItem (Join-Path $Build 'csolv\*.obj') | ForEach-Object FullName) +
|
|
||||||
@((Join-Path $Build 'ffi\femm_curr.obj')))
|
|
||||||
|
|
||||||
Write-Host 'built:'
|
|
||||||
Get-ChildItem (Join-Path $Build 'femm_*.lib') | ForEach-Object { Write-Host " $($_.FullName) ($([math]::Round($_.Length/1KB)) KB)" }
|
|
||||||
} else {
|
|
||||||
$binDir = if ($tc.Kind -eq 'clangarm64') { $tc.Bin } else { $tc.MingwBin }
|
|
||||||
$nmExe = Join-Path $binDir 'nm.exe'
|
|
||||||
$arExe = Join-Path $binDir 'ar.exe'
|
|
||||||
$objcopyExe = if ($tc.Kind -eq 'clangarm64') {
|
|
||||||
Join-Path $binDir 'llvm-objcopy.exe'
|
|
||||||
} else {
|
|
||||||
Join-Path $binDir 'objcopy.exe'
|
|
||||||
}
|
|
||||||
foreach ($p in @($nmExe, $arExe, $objcopyExe)) {
|
|
||||||
if (-not (Test-Path $p)) { throw "missing binutil: $p" }
|
|
||||||
}
|
|
||||||
|
|
||||||
function Pack-Engine {
|
|
||||||
param([string]$Prefix, [string[]]$Objs)
|
|
||||||
|
|
||||||
$publicRx = "^femm_${Prefix}_"
|
|
||||||
$renameSet = [System.Collections.Generic.HashSet[string]]::new()
|
|
||||||
foreach ($obj in $Objs) {
|
|
||||||
$lines = & $nmExe --defined-only -g $obj
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw "nm failed on $obj" }
|
|
||||||
foreach ($line in $lines) {
|
|
||||||
if ($line -match '^\s*(?:[0-9a-fA-F]+\s+)?([A-Z])\s+(\S+)\s*$') {
|
|
||||||
$sym = $Matches[2]
|
|
||||||
if ($sym -notmatch $publicRx) { $null = $renameSet.Add($sym) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$renameFile = Join-Path $Build "exports\${Prefix}_rename.txt"
|
|
||||||
(($renameSet | Sort-Object | ForEach-Object { "$_ __femm_${Prefix}__$_" }) -join "`n") | Set-Content -Path $renameFile -Encoding ascii
|
|
||||||
|
|
||||||
$engineDir = Join-Path $Build "engines\$Prefix"
|
|
||||||
if (Test-Path $engineDir) { Remove-Item $engineDir -Recurse -Force }
|
|
||||||
New-Item -ItemType Directory -Force -Path $engineDir | Out-Null
|
|
||||||
$renamedObjs = foreach ($obj in $Objs) {
|
|
||||||
$base = [IO.Path]::GetFileName($obj)
|
|
||||||
$newPath = Join-Path $engineDir "${Prefix}_${base}"
|
|
||||||
Copy-Item $obj $newPath -Force
|
|
||||||
& $objcopyExe "--redefine-syms=$renameFile" $newPath $newPath
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw "objcopy failed on $newPath ($LASTEXITCODE)" }
|
|
||||||
$newPath
|
|
||||||
}
|
|
||||||
|
|
||||||
$archive = Join-Path $Build "libfemm_${Prefix}.a"
|
|
||||||
if (Test-Path $archive) { Remove-Item $archive -Force }
|
|
||||||
& $arExe rcs $archive @renamedObjs
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw "ar failed for $Prefix ($LASTEXITCODE)" }
|
|
||||||
}
|
|
||||||
|
|
||||||
Pack-Engine 'mag' ((Get-ChildItem (Join-Path $Build 'fkn\*.o') | ForEach-Object FullName) +
|
|
||||||
(Get-ChildItem (Join-Path $Build 'liblua\*.o') | ForEach-Object FullName) +
|
|
||||||
@((Join-Path $Build 'ffi\femm_mag.o'),
|
|
||||||
(Join-Path $Build 'ffi\femm_lua_complex_ops.o')))
|
|
||||||
Pack-Engine 'elec' ((Get-ChildItem (Join-Path $Build 'belasolv\*.o') | ForEach-Object FullName) +
|
|
||||||
@((Join-Path $Build 'ffi\femm_elec.o')))
|
|
||||||
Pack-Engine 'heat' ((Get-ChildItem (Join-Path $Build 'hsolv\*.o') | ForEach-Object FullName) +
|
|
||||||
@((Join-Path $Build 'ffi\femm_heat.o')))
|
|
||||||
Pack-Engine 'curr' ((Get-ChildItem (Join-Path $Build 'csolv\*.o') | ForEach-Object FullName) +
|
|
||||||
@((Join-Path $Build 'ffi\femm_curr.o')))
|
|
||||||
|
|
||||||
Write-Host 'built:'
|
|
||||||
Get-ChildItem (Join-Path $Build 'libfemm_*.a') | ForEach-Object { Write-Host " $($_.FullName) ($([math]::Round($_.Length/1KB)) KB)" }
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
#requires -Version 7
|
|
||||||
# Builds the Triangle mesher into build\triangle\triangle.exe.
|
|
||||||
|
|
||||||
$ErrorActionPreference = 'Stop'
|
|
||||||
|
|
||||||
$Root = Resolve-Path (Join-Path $PSScriptRoot '..\..')
|
|
||||||
$Build = if ($env:BUILD) { $env:BUILD } else { Join-Path $Root 'build\triangle' }
|
|
||||||
New-Item -ItemType Directory -Force -Path $Build | Out-Null
|
|
||||||
|
|
||||||
. (Join-Path $PSScriptRoot '_toolchain.ps1')
|
|
||||||
$tc = Get-Toolchain
|
|
||||||
Initialize-Toolchain $tc
|
|
||||||
|
|
||||||
$buildProfile = if ($env:PROFILE) { $env:PROFILE } else { 'release' }
|
|
||||||
$src = Join-Path $Root 'triangle\triangle.c'
|
|
||||||
$out = Join-Path $Build 'triangle.exe'
|
|
||||||
|
|
||||||
if ($tc.Kind -eq 'msvc') {
|
|
||||||
$cflags = if ($buildProfile -eq 'release') { @('/nologo','/O2','/DNDEBUG','/W0') } else { @('/nologo','/Od','/Zi','/W0') }
|
|
||||||
& cl.exe @cflags $src "/Fe:$out" "/Fo:$Build\" /link /SUBSYSTEM:CONSOLE
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw "cl.exe failed building triangle ($LASTEXITCODE)" }
|
|
||||||
} elseif ($tc.Kind -eq 'clangarm64') {
|
|
||||||
$cflags = if ($buildProfile -eq 'release') { @('-std=gnu89','-O3','-DNDEBUG','-w') } else { @('-std=gnu89','-O0','-g','-w') }
|
|
||||||
& (Join-Path $tc.Bin 'clang.exe') @cflags -o $out $src -lm
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw "clang failed building triangle ($LASTEXITCODE)" }
|
|
||||||
} else {
|
|
||||||
$cflags = if ($buildProfile -eq 'release') { @('-std=gnu89','-O3','-DNDEBUG','-w') } else { @('-std=gnu89','-O0','-g','-w') }
|
|
||||||
& gcc.exe @cflags -o $out $src -lm
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw "gcc failed building triangle ($LASTEXITCODE)" }
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "built: $out"
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
#requires -Version 7
|
|
||||||
$ErrorActionPreference = 'Stop'
|
|
||||||
|
|
||||||
$Root = Resolve-Path (Join-Path $PSScriptRoot '..\..')
|
|
||||||
Set-Location $Root
|
|
||||||
|
|
||||||
if (-not $IsWindows) {
|
|
||||||
Write-Error "wrong platform: $($PSVersionTable.OS) - use cargo xtask debug"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
. (Join-Path $PSScriptRoot '_toolchain.ps1')
|
|
||||||
$tc = Get-Toolchain
|
|
||||||
Initialize-Toolchain $tc
|
|
||||||
|
|
||||||
$env:RUST_BACKTRACE = '1'
|
|
||||||
|
|
||||||
$cargoArgs = @('run','-p','femm-app')
|
|
||||||
if ($tc.CargoTarget) {
|
|
||||||
$cargoArgs += @('--target',$tc.CargoTarget)
|
|
||||||
}
|
|
||||||
$cargoArgs += '--'
|
|
||||||
$cargoArgs += $args
|
|
||||||
|
|
||||||
& cargo @cargoArgs
|
|
||||||
exit $LASTEXITCODE
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
#requires -Version 7
|
|
||||||
$ErrorActionPreference = 'Stop'
|
|
||||||
& (Join-Path $PSScriptRoot 'build_ffi.ps1') @args
|
|
||||||
exit $LASTEXITCODE
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
#requires -Version 7
|
|
||||||
$ErrorActionPreference = 'Stop'
|
|
||||||
|
|
||||||
$Root = Resolve-Path (Join-Path $PSScriptRoot '..\..')
|
|
||||||
Set-Location $Root
|
|
||||||
|
|
||||||
if (-not $IsWindows) {
|
|
||||||
Write-Error "wrong platform: $($PSVersionTable.OS) - use cargo xtask install"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
& (Join-Path $PSScriptRoot 'build.ps1')
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw "build.ps1 failed ($LASTEXITCODE)" }
|
|
||||||
|
|
||||||
$Dest = if ($env:FEMM_INSTALL_DIR) { $env:FEMM_INSTALL_DIR } else { Join-Path $env:LOCALAPPDATA 'Programs\femm' }
|
|
||||||
$Src = Join-Path $Root 'build\bin\femm'
|
|
||||||
|
|
||||||
# Stop any running instance so the copy doesn't trip on a file lock.
|
|
||||||
Get-Process -Name 'femm' -ErrorAction SilentlyContinue | ForEach-Object {
|
|
||||||
Write-Host "Stopping running femm.exe (pid $($_.Id))..."
|
|
||||||
try { $_ | Stop-Process -Force } catch {}
|
|
||||||
}
|
|
||||||
Start-Sleep -Milliseconds 200
|
|
||||||
|
|
||||||
if (Test-Path $Dest) { Remove-Item $Dest -Recurse -Force }
|
|
||||||
New-Item -ItemType Directory -Force -Path $Dest | Out-Null
|
|
||||||
Copy-Item -Path (Join-Path $Src '*') -Destination $Dest -Recurse -Force
|
|
||||||
|
|
||||||
Write-Host "Installed: $Dest"
|
|
||||||
|
|
@ -346,7 +346,6 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#ifndef NO_TIMER
|
#ifndef NO_TIMER
|
||||||
|
|
@ -832,7 +831,7 @@ struct behavior {
|
||||||
/* extracting an orientation (in the range 0 to 2) and a pointer to the */
|
/* extracting an orientation (in the range 0 to 2) and a pointer to the */
|
||||||
/* beginning of a triangle. The encode() routine compresses a pointer to a */
|
/* beginning of a triangle. The encode() routine compresses a pointer to a */
|
||||||
/* triangle and an orientation into a single pointer. My assumptions that */
|
/* triangle and an orientation into a single pointer. My assumptions that */
|
||||||
/* triangles are four-byte-aligned and that the `uintptr_t' type is */
|
/* triangles are four-byte-aligned and that the `unsigned long' type is */
|
||||||
/* long enough to hold a pointer are two of the few kludges in this program.*/
|
/* long enough to hold a pointer are two of the few kludges in this program.*/
|
||||||
/* */
|
/* */
|
||||||
/* Subsegments are manipulated similarly. A pointer to a subsegment */
|
/* Subsegments are manipulated similarly. A pointer to a subsegment */
|
||||||
|
|
@ -943,16 +942,16 @@ int minus1mod3[3] = {2, 0, 1};
|
||||||
/* extracted from the two least significant bits of the pointer. */
|
/* extracted from the two least significant bits of the pointer. */
|
||||||
|
|
||||||
#define decode(ptr, otri) \
|
#define decode(ptr, otri) \
|
||||||
(otri).orient = (int) ((uintptr_t) (ptr) & (uintptr_t) 3l); \
|
(otri).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l); \
|
||||||
(otri).tri = (triangle *) \
|
(otri).tri = (triangle *) \
|
||||||
((uintptr_t) (ptr) ^ (uintptr_t) (otri).orient)
|
((unsigned long) (ptr) ^ (unsigned long) (otri).orient)
|
||||||
|
|
||||||
/* encode() compresses an oriented triangle into a single pointer. It */
|
/* encode() compresses an oriented triangle into a single pointer. It */
|
||||||
/* relies on the assumption that all triangles are aligned to four-byte */
|
/* relies on the assumption that all triangles are aligned to four-byte */
|
||||||
/* boundaries, so the two least significant bits of (otri).tri are zero. */
|
/* boundaries, so the two least significant bits of (otri).tri are zero. */
|
||||||
|
|
||||||
#define encode(otri) \
|
#define encode(otri) \
|
||||||
(triangle) ((uintptr_t) (otri).tri | (uintptr_t) (otri).orient)
|
(triangle) ((unsigned long) (otri).tri | (unsigned long) (otri).orient)
|
||||||
|
|
||||||
/* The following handle manipulation primitives are all described by Guibas */
|
/* The following handle manipulation primitives are all described by Guibas */
|
||||||
/* and Stolfi. However, Guibas and Stolfi use an edge-based data */
|
/* and Stolfi. However, Guibas and Stolfi use an edge-based data */
|
||||||
|
|
@ -1116,16 +1115,16 @@ int minus1mod3[3] = {2, 0, 1};
|
||||||
|
|
||||||
#define infect(otri) \
|
#define infect(otri) \
|
||||||
(otri).tri[6] = (triangle) \
|
(otri).tri[6] = (triangle) \
|
||||||
((uintptr_t) (otri).tri[6] | (uintptr_t) 2l)
|
((unsigned long) (otri).tri[6] | (unsigned long) 2l)
|
||||||
|
|
||||||
#define uninfect(otri) \
|
#define uninfect(otri) \
|
||||||
(otri).tri[6] = (triangle) \
|
(otri).tri[6] = (triangle) \
|
||||||
((uintptr_t) (otri).tri[6] & ~ (uintptr_t) 2l)
|
((unsigned long) (otri).tri[6] & ~ (unsigned long) 2l)
|
||||||
|
|
||||||
/* Test a triangle for viral infection. */
|
/* Test a triangle for viral infection. */
|
||||||
|
|
||||||
#define infected(otri) \
|
#define infected(otri) \
|
||||||
(((uintptr_t) (otri).tri[6] & (uintptr_t) 2l) != 0l)
|
(((unsigned long) (otri).tri[6] & (unsigned long) 2l) != 0l)
|
||||||
|
|
||||||
/* Check or set a triangle's attributes. */
|
/* Check or set a triangle's attributes. */
|
||||||
|
|
||||||
|
|
@ -1163,16 +1162,16 @@ int minus1mod3[3] = {2, 0, 1};
|
||||||
/* are masked out to produce the real pointer. */
|
/* are masked out to produce the real pointer. */
|
||||||
|
|
||||||
#define sdecode(sptr, osub) \
|
#define sdecode(sptr, osub) \
|
||||||
(osub).ssorient = (int) ((uintptr_t) (sptr) & (uintptr_t) 1l); \
|
(osub).ssorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l); \
|
||||||
(osub).ss = (subseg *) \
|
(osub).ss = (subseg *) \
|
||||||
((uintptr_t) (sptr) & ~ (uintptr_t) 3l)
|
((unsigned long) (sptr) & ~ (unsigned long) 3l)
|
||||||
|
|
||||||
/* sencode() compresses an oriented subsegment into a single pointer. It */
|
/* sencode() compresses an oriented subsegment into a single pointer. It */
|
||||||
/* relies on the assumption that all subsegments are aligned to two-byte */
|
/* relies on the assumption that all subsegments are aligned to two-byte */
|
||||||
/* boundaries, so the least significant bit of (osub).ss is zero. */
|
/* boundaries, so the least significant bit of (osub).ss is zero. */
|
||||||
|
|
||||||
#define sencode(osub) \
|
#define sencode(osub) \
|
||||||
(subseg) ((uintptr_t) (osub).ss | (uintptr_t) (osub).ssorient)
|
(subseg) ((unsigned long) (osub).ss | (unsigned long) (osub).ssorient)
|
||||||
|
|
||||||
/* ssym() toggles the orientation of a subsegment. */
|
/* ssym() toggles the orientation of a subsegment. */
|
||||||
|
|
||||||
|
|
@ -1909,27 +1908,27 @@ struct otri *t;
|
||||||
struct osub printsh;
|
struct osub printsh;
|
||||||
vertex printvertex;
|
vertex printvertex;
|
||||||
|
|
||||||
printf("triangle x%lx with orientation %d:\n", (uintptr_t) t->tri,
|
printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
|
||||||
t->orient);
|
t->orient);
|
||||||
decode(t->tri[0], printtri);
|
decode(t->tri[0], printtri);
|
||||||
if (printtri.tri == m->dummytri) {
|
if (printtri.tri == m->dummytri) {
|
||||||
printf(" [0] = Outer space\n");
|
printf(" [0] = Outer space\n");
|
||||||
} else {
|
} else {
|
||||||
printf(" [0] = x%lx %d\n", (uintptr_t) printtri.tri,
|
printf(" [0] = x%lx %d\n", (unsigned long) printtri.tri,
|
||||||
printtri.orient);
|
printtri.orient);
|
||||||
}
|
}
|
||||||
decode(t->tri[1], printtri);
|
decode(t->tri[1], printtri);
|
||||||
if (printtri.tri == m->dummytri) {
|
if (printtri.tri == m->dummytri) {
|
||||||
printf(" [1] = Outer space\n");
|
printf(" [1] = Outer space\n");
|
||||||
} else {
|
} else {
|
||||||
printf(" [1] = x%lx %d\n", (uintptr_t) printtri.tri,
|
printf(" [1] = x%lx %d\n", (unsigned long) printtri.tri,
|
||||||
printtri.orient);
|
printtri.orient);
|
||||||
}
|
}
|
||||||
decode(t->tri[2], printtri);
|
decode(t->tri[2], printtri);
|
||||||
if (printtri.tri == m->dummytri) {
|
if (printtri.tri == m->dummytri) {
|
||||||
printf(" [2] = Outer space\n");
|
printf(" [2] = Outer space\n");
|
||||||
} else {
|
} else {
|
||||||
printf(" [2] = x%lx %d\n", (uintptr_t) printtri.tri,
|
printf(" [2] = x%lx %d\n", (unsigned long) printtri.tri,
|
||||||
printtri.orient);
|
printtri.orient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1938,37 +1937,37 @@ struct otri *t;
|
||||||
printf(" Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
|
printf(" Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
|
||||||
else
|
else
|
||||||
printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
|
printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
|
||||||
(t->orient + 1) % 3 + 3, (uintptr_t) printvertex,
|
(t->orient + 1) % 3 + 3, (unsigned long) printvertex,
|
||||||
printvertex[0], printvertex[1]);
|
printvertex[0], printvertex[1]);
|
||||||
dest(*t, printvertex);
|
dest(*t, printvertex);
|
||||||
if (printvertex == (vertex) NULL)
|
if (printvertex == (vertex) NULL)
|
||||||
printf(" Dest [%d] = NULL\n", (t->orient + 2) % 3 + 3);
|
printf(" Dest [%d] = NULL\n", (t->orient + 2) % 3 + 3);
|
||||||
else
|
else
|
||||||
printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
|
printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
|
||||||
(t->orient + 2) % 3 + 3, (uintptr_t) printvertex,
|
(t->orient + 2) % 3 + 3, (unsigned long) printvertex,
|
||||||
printvertex[0], printvertex[1]);
|
printvertex[0], printvertex[1]);
|
||||||
apex(*t, printvertex);
|
apex(*t, printvertex);
|
||||||
if (printvertex == (vertex) NULL)
|
if (printvertex == (vertex) NULL)
|
||||||
printf(" Apex [%d] = NULL\n", t->orient + 3);
|
printf(" Apex [%d] = NULL\n", t->orient + 3);
|
||||||
else
|
else
|
||||||
printf(" Apex [%d] = x%lx (%.12g, %.12g)\n",
|
printf(" Apex [%d] = x%lx (%.12g, %.12g)\n",
|
||||||
t->orient + 3, (uintptr_t) printvertex,
|
t->orient + 3, (unsigned long) printvertex,
|
||||||
printvertex[0], printvertex[1]);
|
printvertex[0], printvertex[1]);
|
||||||
|
|
||||||
if (b->usesegments) {
|
if (b->usesegments) {
|
||||||
sdecode(t->tri[6], printsh);
|
sdecode(t->tri[6], printsh);
|
||||||
if (printsh.ss != m->dummysub) {
|
if (printsh.ss != m->dummysub) {
|
||||||
printf(" [6] = x%lx %d\n", (uintptr_t) printsh.ss,
|
printf(" [6] = x%lx %d\n", (unsigned long) printsh.ss,
|
||||||
printsh.ssorient);
|
printsh.ssorient);
|
||||||
}
|
}
|
||||||
sdecode(t->tri[7], printsh);
|
sdecode(t->tri[7], printsh);
|
||||||
if (printsh.ss != m->dummysub) {
|
if (printsh.ss != m->dummysub) {
|
||||||
printf(" [7] = x%lx %d\n", (uintptr_t) printsh.ss,
|
printf(" [7] = x%lx %d\n", (unsigned long) printsh.ss,
|
||||||
printsh.ssorient);
|
printsh.ssorient);
|
||||||
}
|
}
|
||||||
sdecode(t->tri[8], printsh);
|
sdecode(t->tri[8], printsh);
|
||||||
if (printsh.ss != m->dummysub) {
|
if (printsh.ss != m->dummysub) {
|
||||||
printf(" [8] = x%lx %d\n", (uintptr_t) printsh.ss,
|
printf(" [8] = x%lx %d\n", (unsigned long) printsh.ss,
|
||||||
printsh.ssorient);
|
printsh.ssorient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2004,19 +2003,19 @@ struct osub *s;
|
||||||
vertex printvertex;
|
vertex printvertex;
|
||||||
|
|
||||||
printf("subsegment x%lx with orientation %d and mark %d:\n",
|
printf("subsegment x%lx with orientation %d and mark %d:\n",
|
||||||
(uintptr_t) s->ss, s->ssorient, mark(*s));
|
(unsigned long) s->ss, s->ssorient, mark(*s));
|
||||||
sdecode(s->ss[0], printsh);
|
sdecode(s->ss[0], printsh);
|
||||||
if (printsh.ss == m->dummysub) {
|
if (printsh.ss == m->dummysub) {
|
||||||
printf(" [0] = No subsegment\n");
|
printf(" [0] = No subsegment\n");
|
||||||
} else {
|
} else {
|
||||||
printf(" [0] = x%lx %d\n", (uintptr_t) printsh.ss,
|
printf(" [0] = x%lx %d\n", (unsigned long) printsh.ss,
|
||||||
printsh.ssorient);
|
printsh.ssorient);
|
||||||
}
|
}
|
||||||
sdecode(s->ss[1], printsh);
|
sdecode(s->ss[1], printsh);
|
||||||
if (printsh.ss == m->dummysub) {
|
if (printsh.ss == m->dummysub) {
|
||||||
printf(" [1] = No subsegment\n");
|
printf(" [1] = No subsegment\n");
|
||||||
} else {
|
} else {
|
||||||
printf(" [1] = x%lx %d\n", (uintptr_t) printsh.ss,
|
printf(" [1] = x%lx %d\n", (unsigned long) printsh.ss,
|
||||||
printsh.ssorient);
|
printsh.ssorient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2025,28 +2024,28 @@ struct osub *s;
|
||||||
printf(" Origin[%d] = NULL\n", 2 + s->ssorient);
|
printf(" Origin[%d] = NULL\n", 2 + s->ssorient);
|
||||||
else
|
else
|
||||||
printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
|
printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
|
||||||
2 + s->ssorient, (uintptr_t) printvertex,
|
2 + s->ssorient, (unsigned long) printvertex,
|
||||||
printvertex[0], printvertex[1]);
|
printvertex[0], printvertex[1]);
|
||||||
sdest(*s, printvertex);
|
sdest(*s, printvertex);
|
||||||
if (printvertex == (vertex) NULL)
|
if (printvertex == (vertex) NULL)
|
||||||
printf(" Dest [%d] = NULL\n", 3 - s->ssorient);
|
printf(" Dest [%d] = NULL\n", 3 - s->ssorient);
|
||||||
else
|
else
|
||||||
printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
|
printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
|
||||||
3 - s->ssorient, (uintptr_t) printvertex,
|
3 - s->ssorient, (unsigned long) printvertex,
|
||||||
printvertex[0], printvertex[1]);
|
printvertex[0], printvertex[1]);
|
||||||
|
|
||||||
decode(s->ss[6], printtri);
|
decode(s->ss[6], printtri);
|
||||||
if (printtri.tri == m->dummytri) {
|
if (printtri.tri == m->dummytri) {
|
||||||
printf(" [6] = Outer space\n");
|
printf(" [6] = Outer space\n");
|
||||||
} else {
|
} else {
|
||||||
printf(" [6] = x%lx %d\n", (uintptr_t) printtri.tri,
|
printf(" [6] = x%lx %d\n", (unsigned long) printtri.tri,
|
||||||
printtri.orient);
|
printtri.orient);
|
||||||
}
|
}
|
||||||
decode(s->ss[7], printtri);
|
decode(s->ss[7], printtri);
|
||||||
if (printtri.tri == m->dummytri) {
|
if (printtri.tri == m->dummytri) {
|
||||||
printf(" [7] = Outer space\n");
|
printf(" [7] = Outer space\n");
|
||||||
} else {
|
} else {
|
||||||
printf(" [7] = x%lx %d\n", (uintptr_t) printtri.tri,
|
printf(" [7] = x%lx %d\n", (unsigned long) printtri.tri,
|
||||||
printtri.orient);
|
printtri.orient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2055,14 +2054,14 @@ struct osub *s;
|
||||||
printf(" Segment origin[%d] = NULL\n", 4 + s->ssorient);
|
printf(" Segment origin[%d] = NULL\n", 4 + s->ssorient);
|
||||||
else
|
else
|
||||||
printf(" Segment origin[%d] = x%lx (%.12g, %.12g)\n",
|
printf(" Segment origin[%d] = x%lx (%.12g, %.12g)\n",
|
||||||
4 + s->ssorient, (uintptr_t) printvertex,
|
4 + s->ssorient, (unsigned long) printvertex,
|
||||||
printvertex[0], printvertex[1]);
|
printvertex[0], printvertex[1]);
|
||||||
segdest(*s, printvertex);
|
segdest(*s, printvertex);
|
||||||
if (printvertex == (vertex) NULL)
|
if (printvertex == (vertex) NULL)
|
||||||
printf(" Segment dest [%d] = NULL\n", 5 - s->ssorient);
|
printf(" Segment dest [%d] = NULL\n", 5 - s->ssorient);
|
||||||
else
|
else
|
||||||
printf(" Segment dest [%d] = x%lx (%.12g, %.12g)\n",
|
printf(" Segment dest [%d] = x%lx (%.12g, %.12g)\n",
|
||||||
5 - s->ssorient, (uintptr_t) printvertex,
|
5 - s->ssorient, (unsigned long) printvertex,
|
||||||
printvertex[0], printvertex[1]);
|
printvertex[0], printvertex[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2125,7 +2124,7 @@ struct memorypool *pool;
|
||||||
#endif /* not ANSI_DECLARATORS */
|
#endif /* not ANSI_DECLARATORS */
|
||||||
|
|
||||||
{
|
{
|
||||||
uintptr_t alignptr;
|
unsigned long alignptr;
|
||||||
|
|
||||||
pool->items = 0;
|
pool->items = 0;
|
||||||
pool->maxitems = 0;
|
pool->maxitems = 0;
|
||||||
|
|
@ -2133,11 +2132,11 @@ struct memorypool *pool;
|
||||||
/* Set the currently active block. */
|
/* Set the currently active block. */
|
||||||
pool->nowblock = pool->firstblock;
|
pool->nowblock = pool->firstblock;
|
||||||
/* Find the first item in the pool. Increment by the size of (VOID *). */
|
/* Find the first item in the pool. Increment by the size of (VOID *). */
|
||||||
alignptr = (uintptr_t) (pool->nowblock + 1);
|
alignptr = (unsigned long) (pool->nowblock + 1);
|
||||||
/* Align the item on an `alignbytes'-byte boundary. */
|
/* Align the item on an `alignbytes'-byte boundary. */
|
||||||
pool->nextitem = (VOID *)
|
pool->nextitem = (VOID *)
|
||||||
(alignptr + (uintptr_t) pool->alignbytes -
|
(alignptr + (unsigned long) pool->alignbytes -
|
||||||
(alignptr % (uintptr_t) pool->alignbytes));
|
(alignptr % (unsigned long) pool->alignbytes));
|
||||||
/* There are lots of unallocated items left in this block. */
|
/* There are lots of unallocated items left in this block. */
|
||||||
pool->unallocateditems = pool->itemsfirstblock;
|
pool->unallocateditems = pool->itemsfirstblock;
|
||||||
/* The stack of deallocated items is empty. */
|
/* The stack of deallocated items is empty. */
|
||||||
|
|
@ -2242,7 +2241,7 @@ struct memorypool *pool;
|
||||||
{
|
{
|
||||||
VOID *newitem;
|
VOID *newitem;
|
||||||
VOID **newblock;
|
VOID **newblock;
|
||||||
uintptr_t alignptr;
|
unsigned long alignptr;
|
||||||
|
|
||||||
/* First check the linked list of dead items. If the list is not */
|
/* First check the linked list of dead items. If the list is not */
|
||||||
/* empty, allocate an item from the list rather than a fresh one. */
|
/* empty, allocate an item from the list rather than a fresh one. */
|
||||||
|
|
@ -2267,11 +2266,11 @@ struct memorypool *pool;
|
||||||
pool->nowblock = (VOID **) *(pool->nowblock);
|
pool->nowblock = (VOID **) *(pool->nowblock);
|
||||||
/* Find the first item in the block. */
|
/* Find the first item in the block. */
|
||||||
/* Increment by the size of (VOID *). */
|
/* Increment by the size of (VOID *). */
|
||||||
alignptr = (uintptr_t) (pool->nowblock + 1);
|
alignptr = (unsigned long) (pool->nowblock + 1);
|
||||||
/* Align the item on an `alignbytes'-byte boundary. */
|
/* Align the item on an `alignbytes'-byte boundary. */
|
||||||
pool->nextitem = (VOID *)
|
pool->nextitem = (VOID *)
|
||||||
(alignptr + (uintptr_t) pool->alignbytes -
|
(alignptr + (unsigned long) pool->alignbytes -
|
||||||
(alignptr % (uintptr_t) pool->alignbytes));
|
(alignptr % (unsigned long) pool->alignbytes));
|
||||||
/* There are lots of unallocated items left in this block. */
|
/* There are lots of unallocated items left in this block. */
|
||||||
pool->unallocateditems = pool->itemsperblock;
|
pool->unallocateditems = pool->itemsperblock;
|
||||||
}
|
}
|
||||||
|
|
@ -2326,16 +2325,16 @@ struct memorypool *pool;
|
||||||
#endif /* not ANSI_DECLARATORS */
|
#endif /* not ANSI_DECLARATORS */
|
||||||
|
|
||||||
{
|
{
|
||||||
uintptr_t alignptr;
|
unsigned long alignptr;
|
||||||
|
|
||||||
/* Begin the traversal in the first block. */
|
/* Begin the traversal in the first block. */
|
||||||
pool->pathblock = pool->firstblock;
|
pool->pathblock = pool->firstblock;
|
||||||
/* Find the first item in the block. Increment by the size of (VOID *). */
|
/* Find the first item in the block. Increment by the size of (VOID *). */
|
||||||
alignptr = (uintptr_t) (pool->pathblock + 1);
|
alignptr = (unsigned long) (pool->pathblock + 1);
|
||||||
/* Align with item on an `alignbytes'-byte boundary. */
|
/* Align with item on an `alignbytes'-byte boundary. */
|
||||||
pool->pathitem = (VOID *)
|
pool->pathitem = (VOID *)
|
||||||
(alignptr + (uintptr_t) pool->alignbytes -
|
(alignptr + (unsigned long) pool->alignbytes -
|
||||||
(alignptr % (uintptr_t) pool->alignbytes));
|
(alignptr % (unsigned long) pool->alignbytes));
|
||||||
/* Set the number of items left in the current block. */
|
/* Set the number of items left in the current block. */
|
||||||
pool->pathitemsleft = pool->itemsfirstblock;
|
pool->pathitemsleft = pool->itemsfirstblock;
|
||||||
}
|
}
|
||||||
|
|
@ -2363,7 +2362,7 @@ struct memorypool *pool;
|
||||||
|
|
||||||
{
|
{
|
||||||
VOID *newitem;
|
VOID *newitem;
|
||||||
uintptr_t alignptr;
|
unsigned long alignptr;
|
||||||
|
|
||||||
/* Stop upon exhausting the list of items. */
|
/* Stop upon exhausting the list of items. */
|
||||||
if (pool->pathitem == pool->nextitem) {
|
if (pool->pathitem == pool->nextitem) {
|
||||||
|
|
@ -2375,11 +2374,11 @@ struct memorypool *pool;
|
||||||
/* Find the next block. */
|
/* Find the next block. */
|
||||||
pool->pathblock = (VOID **) *(pool->pathblock);
|
pool->pathblock = (VOID **) *(pool->pathblock);
|
||||||
/* Find the first item in the block. Increment by the size of (VOID *). */
|
/* Find the first item in the block. Increment by the size of (VOID *). */
|
||||||
alignptr = (uintptr_t) (pool->pathblock + 1);
|
alignptr = (unsigned long) (pool->pathblock + 1);
|
||||||
/* Align with item on an `alignbytes'-byte boundary. */
|
/* Align with item on an `alignbytes'-byte boundary. */
|
||||||
pool->pathitem = (VOID *)
|
pool->pathitem = (VOID *)
|
||||||
(alignptr + (uintptr_t) pool->alignbytes -
|
(alignptr + (unsigned long) pool->alignbytes -
|
||||||
(alignptr % (uintptr_t) pool->alignbytes));
|
(alignptr % (unsigned long) pool->alignbytes));
|
||||||
/* Set the number of items left in the current block. */
|
/* Set the number of items left in the current block. */
|
||||||
pool->pathitemsleft = pool->itemsperblock;
|
pool->pathitemsleft = pool->itemsperblock;
|
||||||
}
|
}
|
||||||
|
|
@ -2431,16 +2430,16 @@ int subsegbytes;
|
||||||
#endif /* not ANSI_DECLARATORS */
|
#endif /* not ANSI_DECLARATORS */
|
||||||
|
|
||||||
{
|
{
|
||||||
uintptr_t alignptr;
|
unsigned long alignptr;
|
||||||
|
|
||||||
/* Set up `dummytri', the `triangle' that occupies "outer space." */
|
/* Set up `dummytri', the `triangle' that occupies "outer space." */
|
||||||
m->dummytribase = (triangle *) trimalloc(trianglebytes +
|
m->dummytribase = (triangle *) trimalloc(trianglebytes +
|
||||||
m->triangles.alignbytes);
|
m->triangles.alignbytes);
|
||||||
/* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */
|
/* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */
|
||||||
alignptr = (uintptr_t) m->dummytribase;
|
alignptr = (unsigned long) m->dummytribase;
|
||||||
m->dummytri = (triangle *)
|
m->dummytri = (triangle *)
|
||||||
(alignptr + (uintptr_t) m->triangles.alignbytes -
|
(alignptr + (unsigned long) m->triangles.alignbytes -
|
||||||
(alignptr % (uintptr_t) m->triangles.alignbytes));
|
(alignptr % (unsigned long) m->triangles.alignbytes));
|
||||||
/* Initialize the three adjoining triangles to be "outer space." These */
|
/* Initialize the three adjoining triangles to be "outer space." These */
|
||||||
/* will eventually be changed by various bonding operations, but their */
|
/* will eventually be changed by various bonding operations, but their */
|
||||||
/* values don't really matter, as long as they can legally be */
|
/* values don't really matter, as long as they can legally be */
|
||||||
|
|
@ -2460,10 +2459,10 @@ int subsegbytes;
|
||||||
m->dummysubbase = (subseg *) trimalloc(subsegbytes +
|
m->dummysubbase = (subseg *) trimalloc(subsegbytes +
|
||||||
m->subsegs.alignbytes);
|
m->subsegs.alignbytes);
|
||||||
/* Align `dummysub' on a `subsegs.alignbytes'-byte boundary. */
|
/* Align `dummysub' on a `subsegs.alignbytes'-byte boundary. */
|
||||||
alignptr = (uintptr_t) m->dummysubbase;
|
alignptr = (unsigned long) m->dummysubbase;
|
||||||
m->dummysub = (subseg *)
|
m->dummysub = (subseg *)
|
||||||
(alignptr + (uintptr_t) m->subsegs.alignbytes -
|
(alignptr + (unsigned long) m->subsegs.alignbytes -
|
||||||
(alignptr % (uintptr_t) m->subsegs.alignbytes));
|
(alignptr % (unsigned long) m->subsegs.alignbytes));
|
||||||
/* Initialize the two adjoining subsegments to be the omnipresent */
|
/* Initialize the two adjoining subsegments to be the omnipresent */
|
||||||
/* subsegment. These will eventually be changed by various bonding */
|
/* subsegment. These will eventually be changed by various bonding */
|
||||||
/* operations, but their values don't really matter, as long as they */
|
/* operations, but their values don't really matter, as long as they */
|
||||||
|
|
@ -2820,7 +2819,7 @@ int number;
|
||||||
{
|
{
|
||||||
VOID **getblock;
|
VOID **getblock;
|
||||||
char *foundvertex;
|
char *foundvertex;
|
||||||
uintptr_t alignptr;
|
unsigned long alignptr;
|
||||||
int current;
|
int current;
|
||||||
|
|
||||||
getblock = m->vertices.firstblock;
|
getblock = m->vertices.firstblock;
|
||||||
|
|
@ -2837,9 +2836,9 @@ int number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now find the right vertex. */
|
/* Now find the right vertex. */
|
||||||
alignptr = (uintptr_t) (getblock + 1);
|
alignptr = (unsigned long) (getblock + 1);
|
||||||
foundvertex = (char *) (alignptr + (uintptr_t) m->vertices.alignbytes -
|
foundvertex = (char *) (alignptr + (unsigned long) m->vertices.alignbytes -
|
||||||
(alignptr % (uintptr_t) m->vertices.alignbytes));
|
(alignptr % (unsigned long) m->vertices.alignbytes));
|
||||||
return (vertex) (foundvertex + m->vertices.itembytes * (number - current));
|
return (vertex) (foundvertex + m->vertices.itembytes * (number - current));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5883,7 +5882,7 @@ struct otri *searchtri;
|
||||||
char *firsttri;
|
char *firsttri;
|
||||||
struct otri sampletri;
|
struct otri sampletri;
|
||||||
vertex torg, tdest;
|
vertex torg, tdest;
|
||||||
uintptr_t alignptr;
|
unsigned long alignptr;
|
||||||
REAL searchdist, dist;
|
REAL searchdist, dist;
|
||||||
REAL ahead;
|
REAL ahead;
|
||||||
long samplesperblock, totalsamplesleft, samplesleft;
|
long samplesperblock, totalsamplesleft, samplesleft;
|
||||||
|
|
@ -5955,11 +5954,11 @@ struct otri *searchtri;
|
||||||
population = totalpopulation;
|
population = totalpopulation;
|
||||||
}
|
}
|
||||||
/* Find a pointer to the first triangle in the block. */
|
/* Find a pointer to the first triangle in the block. */
|
||||||
alignptr = (uintptr_t) (sampleblock + 1);
|
alignptr = (unsigned long) (sampleblock + 1);
|
||||||
firsttri = (char *) (alignptr +
|
firsttri = (char *) (alignptr +
|
||||||
(uintptr_t) m->triangles.alignbytes -
|
(unsigned long) m->triangles.alignbytes -
|
||||||
(alignptr %
|
(alignptr %
|
||||||
(uintptr_t) m->triangles.alignbytes));
|
(unsigned long) m->triangles.alignbytes));
|
||||||
|
|
||||||
/* Choose `samplesleft' randomly sampled triangles in this block. */
|
/* Choose `samplesleft' randomly sampled triangles in this block. */
|
||||||
do {
|
do {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ fn main() -> ExitCode {
|
||||||
"windows" => (
|
"windows" => (
|
||||||
repo_root.join(format!("scripts/windows/{action}.ps1")),
|
repo_root.join(format!("scripts/windows/{action}.ps1")),
|
||||||
vec![
|
vec![
|
||||||
"pwsh",
|
"powershell",
|
||||||
"-NoProfile",
|
"-NoProfile",
|
||||||
"-ExecutionPolicy",
|
"-ExecutionPolicy",
|
||||||
"Bypass",
|
"Bypass",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue