From 2b7027df9a1d074b8caaaf23e8f5948932c1499f Mon Sep 17 00:00:00 2001 From: Dave Patrick Caberto Date: Mon, 18 Dec 2023 13:47:10 +0800 Subject: [PATCH] test --- Cargo.lock | 240 +++++++++++++++++++ Cargo.toml | 1 + build-aux/io.github.seadve.Dagger.Devel.json | 31 ++- graphviz-sys/Cargo.toml | 13 + graphviz-sys/build.rs | 45 ++++ graphviz-sys/src/lib.rs | 8 + graphviz-sys/wrapper.h | 1 + src/graphviz.rs | 50 ++++ src/main.rs | 5 + 9 files changed, 383 insertions(+), 11 deletions(-) create mode 100644 graphviz-sys/Cargo.toml create mode 100644 graphviz-sys/build.rs create mode 100644 graphviz-sys/src/lib.rs create mode 100644 graphviz-sys/wrapper.h create mode 100644 src/graphviz.rs diff --git a/Cargo.lock b/Cargo.lock index 6a22544..048e35e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,6 +40,29 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bindgen" +version = "0.69.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.41", + "which", +] + [[package]] name = "bitflags" version = "2.4.1" @@ -86,6 +109,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-expr" version = "0.15.5" @@ -102,6 +134,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clang-sys" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "concurrent-queue" version = "2.4.0" @@ -129,6 +172,7 @@ dependencies = [ "futures-channel", "futures-util", "gettext-rs", + "graphviz-sys", "gsettings-macro", "gtk4", "libadwaita", @@ -180,12 +224,28 @@ dependencies = [ "syn 2.0.41", ] +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "event-listener" version = "4.0.0" @@ -439,6 +499,12 @@ dependencies = [ "system-deps", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "gobject-sys" version = "0.18.0" @@ -473,6 +539,14 @@ dependencies = [ "system-deps", ] +[[package]] +name = "graphviz-sys" +version = "0.1.0" +dependencies = [ + "bindgen", + "system-deps", +] + [[package]] name = "gsettings-macro" version = "0.1.20" @@ -586,6 +660,15 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys", +] + [[package]] name = "if_chain" version = "1.0.2" @@ -631,6 +714,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libadwaita" version = "0.5.3" @@ -669,6 +758,22 @@ version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + [[package]] name = "locale_config" version = "0.3.0" @@ -712,6 +817,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -794,6 +915,12 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -812,6 +939,16 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2", + "syn 2.0.41", +] + [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -913,6 +1050,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.4.0" @@ -922,6 +1065,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "semver" version = "1.0.20" @@ -966,6 +1122,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" + [[package]] name = "slab" version = "0.4.9" @@ -1285,6 +1447,18 @@ dependencies = [ "system-deps", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1307,6 +1481,72 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winnow" version = "0.5.28" diff --git a/Cargo.toml b/Cargo.toml index 3ab0df9..ac46f04 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ async-lock = "3.2" futures-util = { version = "0.3.29", features = ["io"] } futures-channel = "0.3.29" gettext-rs = { version = "0.7", features = ["gettext-system"] } +graphviz-sys = { path = "graphviz-sys" } gsettings-macro = "0.1.20" gtk = { version = "0.7", package = "gtk4", features = ["gnome_45"] } gtk_source = { package = "sourceview5", version = "0.7", features = ["v5_10"] } diff --git a/build-aux/io.github.seadve.Dagger.Devel.json b/build-aux/io.github.seadve.Dagger.Devel.json index 101eccb..5e140b9 100644 --- a/build-aux/io.github.seadve.Dagger.Devel.json +++ b/build-aux/io.github.seadve.Dagger.Devel.json @@ -34,20 +34,29 @@ }, "modules": [ { - "name": "d3-graphviz", - "buildsystem": "simple", - "build-commands": [ - "npm install", - "npm run build", - "mkdir -p $FLATPAK_DEST/src/dagger/graph_view/d3-graphviz", - "cp -r node_modules $FLATPAK_DEST/src/dagger/graph_view/d3-graphviz", - "cp -r build $FLATPAK_DEST/src/dagger/graph_view/d3-graphviz" + "name": "graphviz", + "buildsystem": "autotools", + "cleanup": [ + "/share/man", + "/share/graphviz", + "/bin" + ], + "config-opts": [ + "--without-x", + "--with-qt=no", + "--with-gtk=no", + "--enable-swig=no", + "--with-webp=no", + "--with-rsvg=no", + "--with-visio=no", + "--with-gdk-pixbuf=no", + "--with-pangocairo=no" ], "sources": [ { - "type": "git", - "url": "https://github.com/magjac/d3-graphviz.git", - "tag": "v5.2.0" + "type": "archive", + "url": "https://gitlab.com/api/v4/projects/4207231/packages/generic/graphviz-releases/9.0.0/graphviz-9.0.0.tar.xz", + "sha256": "6c9afda06a732af7658c2619ee713d2545818c3ff19b7b8fd48effcd06d57bf6" } ] }, diff --git a/graphviz-sys/Cargo.toml b/graphviz-sys/Cargo.toml new file mode 100644 index 0000000..99e45f3 --- /dev/null +++ b/graphviz-sys/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "graphviz-sys" +version = "0.1.0" +edition = "2021" + +[package.metadata.system-deps] +libgvc = "9.0.0" +libcgraph = "9.0.0" +libcdt = "9.0.0" + +[build-dependencies] +bindgen = "0.69" +system-deps = "6" diff --git a/graphviz-sys/build.rs b/graphviz-sys/build.rs new file mode 100644 index 0000000..bb58f12 --- /dev/null +++ b/graphviz-sys/build.rs @@ -0,0 +1,45 @@ +use bindgen::callbacks::{MacroParsingBehavior, ParseCallbacks}; + +use std::collections::HashSet; +use std::env; +use std::path::PathBuf; + +#[derive(Debug)] +struct IgnoreMacros<'a>(HashSet<&'a str>); + +impl ParseCallbacks for IgnoreMacros<'_> { + fn will_parse_macro(&self, name: &str) -> MacroParsingBehavior { + if self.0.contains(name) { + MacroParsingBehavior::Ignore + } else { + MacroParsingBehavior::Default + } + } +} + +fn main() { + let libs = system_deps::Config::new().probe().unwrap(); + + let headers = libs.all_include_paths(); + + let mut builder = bindgen::builder() + .header("wrapper.h") + .parse_callbacks(Box::new(IgnoreMacros(HashSet::from_iter([ + "FP_INFINITE", + "FP_NAN", + "FP_NORMAL", + "FP_SUBNORMAL", + "FP_ZERO", + ])))); + + for header in headers { + builder = builder.clang_arg("-I").clang_arg(header.to_str().unwrap()); + } + + let bindings = builder.generate().unwrap(); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .unwrap(); +} diff --git a/graphviz-sys/src/lib.rs b/graphviz-sys/src/lib.rs new file mode 100644 index 0000000..77c6231 --- /dev/null +++ b/graphviz-sys/src/lib.rs @@ -0,0 +1,8 @@ +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + improper_ctypes // See https://github.com/rust-lang/rust/issues/54341 +)] + +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/graphviz-sys/wrapper.h b/graphviz-sys/wrapper.h new file mode 100644 index 0000000..f6200d4 --- /dev/null +++ b/graphviz-sys/wrapper.h @@ -0,0 +1 @@ +#include "graphviz/gvc.h" diff --git a/src/graphviz.rs b/src/graphviz.rs new file mode 100644 index 0000000..9d4b191 --- /dev/null +++ b/src/graphviz.rs @@ -0,0 +1,50 @@ +use std::ffi::{c_char, c_int, c_uint, CString}; + +use anyhow::{ensure, Context, Result}; + +pub fn render(dot_str: &str, layout: &str, format: &str) -> Result> { + use graphviz_sys::*; + + let dot_str = CString::new(dot_str).context("Failed to convert dot_str to cstring")?; + let layout = CString::new(layout).context("Failed to convert layout to cstring")?; + let format = CString::new(format).context("Failed to convert format to cstring")?; + + unsafe { + let gvc = gvContext(); + + ensure!(!gvc.is_null(), "Failed to create context"); + + let graph = agmemread(dot_str.as_ptr()); + + ensure!(!graph.is_null(), "Failed to parse"); + + gvLayout(gvc, graph, layout.as_ptr()).to_res("Failed to layout")?; + + let mut buffer_ptr: *mut c_char = std::ptr::null_mut(); + let mut data_size: c_uint = 0; + gvRenderData(gvc, graph, format.as_ptr(), &mut buffer_ptr, &mut data_size) + .to_res("Failed to render data")?; + + gvFreeLayout(gvc, graph).to_res("Failed to free layout")?; + agclose(graph).to_res("Failed to close graph")?; + gvFreeContext(gvc).to_res("Failed to free context")?; + + Ok(Vec::from_raw_parts( + buffer_ptr as *mut u8, + data_size as usize, + data_size as usize, + )) + } +} + +trait ToResult { + fn to_res(&self, message: &'static str) -> Result<()>; +} + +impl ToResult for c_int { + fn to_res(&self, message: &'static str) -> Result<()> { + ensure!(*self == 0, message); + + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index f16b603..2e224dd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,6 +29,7 @@ mod document; mod drag_overlay; mod error_gutter_renderer; mod graph_view; +mod graphviz; mod i18n; mod settings; mod utils; @@ -57,6 +58,10 @@ fn main() -> glib::ExitCode { let res = gio::Resource::load(RESOURCES_FILE).expect("Could not load gresource file"); gio::resources_register(&res); + dbg!(std::str::from_utf8( + &graphviz::render("digraph { ", "dot", "svg").unwrap() + )); + let app = Application::default(); app.run() }