You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

run.rs 8.4 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. use eyre::{bail, Context};
  2. use std::{
  3. env::consts::{DLL_PREFIX, DLL_SUFFIX, EXE_SUFFIX},
  4. path::Path,
  5. };
  6. use tracing::metadata::LevelFilter;
  7. use tracing_subscriber::Layer;
  8. #[derive(Debug, Clone, clap::Parser)]
  9. pub struct Args {
  10. #[clap(long)]
  11. pub run_dora_runtime: bool,
  12. }
  13. #[tokio::main]
  14. async fn main() -> eyre::Result<()> {
  15. let Args { run_dora_runtime } = clap::Parser::parse();
  16. if run_dora_runtime {
  17. return tokio::task::block_in_place(dora_daemon::run_dora_runtime);
  18. }
  19. set_up_tracing().wrap_err("failed to set up tracing")?;
  20. if cfg!(windows) {
  21. tracing::error!(
  22. "The c++ example does not work on Windows currently because of a linker error"
  23. );
  24. return Ok(());
  25. }
  26. let root = Path::new(env!("CARGO_MANIFEST_DIR"));
  27. let target = root.join("target");
  28. std::env::set_current_dir(root.join(file!()).parent().unwrap())
  29. .wrap_err("failed to set working dir")?;
  30. tokio::fs::create_dir_all("build").await?;
  31. let build_dir = Path::new("build");
  32. build_package("dora-node-api-cxx").await?;
  33. let node_cxxbridge = target
  34. .join("cxxbridge")
  35. .join("dora-node-api-cxx")
  36. .join("src");
  37. tokio::fs::copy(
  38. node_cxxbridge.join("lib.rs.cc"),
  39. build_dir.join("node-bridge.cc"),
  40. )
  41. .await?;
  42. tokio::fs::copy(
  43. node_cxxbridge.join("lib.rs.h"),
  44. build_dir.join("dora-node-api.h"),
  45. )
  46. .await?;
  47. tokio::fs::write(
  48. build_dir.join("operator.h"),
  49. r###"#include "../operator-rust-api/operator.h""###,
  50. )
  51. .await?;
  52. build_package("dora-operator-api-cxx").await?;
  53. let operator_cxxbridge = target
  54. .join("cxxbridge")
  55. .join("dora-operator-api-cxx")
  56. .join("src");
  57. tokio::fs::copy(
  58. operator_cxxbridge.join("lib.rs.cc"),
  59. build_dir.join("operator-bridge.cc"),
  60. )
  61. .await?;
  62. tokio::fs::copy(
  63. operator_cxxbridge.join("lib.rs.h"),
  64. build_dir.join("dora-operator-api.h"),
  65. )
  66. .await?;
  67. build_package("dora-node-api-c").await?;
  68. build_package("dora-operator-api-c").await?;
  69. build_cxx_node(
  70. root,
  71. &[
  72. &dunce::canonicalize(Path::new("node-rust-api").join("main.cc"))?,
  73. &dunce::canonicalize(build_dir.join("node-bridge.cc"))?,
  74. ],
  75. "node_rust_api",
  76. &["-l", "dora_node_api_cxx"],
  77. )
  78. .await?;
  79. build_cxx_node(
  80. root,
  81. &[&dunce::canonicalize(
  82. Path::new("node-c-api").join("main.cc"),
  83. )?],
  84. "node_c_api",
  85. &["-l", "dora_node_api_c"],
  86. )
  87. .await?;
  88. build_cxx_operator(
  89. &[
  90. &dunce::canonicalize(Path::new("operator-rust-api").join("operator.cc"))?,
  91. &dunce::canonicalize(build_dir.join("operator-bridge.cc"))?,
  92. ],
  93. "operator_rust_api",
  94. &[
  95. "-l",
  96. "dora_operator_api_cxx",
  97. "-L",
  98. root.join("target").join("debug").to_str().unwrap(),
  99. ],
  100. )
  101. .await?;
  102. build_cxx_operator(
  103. &[&dunce::canonicalize(
  104. Path::new("operator-c-api").join("operator.cc"),
  105. )?],
  106. "operator_c_api",
  107. &[],
  108. )
  109. .await?;
  110. let dataflow = Path::new("dataflow.yml").to_owned();
  111. build_package("dora-runtime").await?;
  112. dora_daemon::Daemon::run_dataflow(&dataflow, false).await?;
  113. Ok(())
  114. }
  115. async fn build_package(package: &str) -> eyre::Result<()> {
  116. let cargo = std::env::var("CARGO").unwrap();
  117. let mut cmd = tokio::process::Command::new(&cargo);
  118. cmd.arg("build");
  119. cmd.arg("--package").arg(package);
  120. if !cmd.status().await?.success() {
  121. bail!("failed to build {package}");
  122. };
  123. Ok(())
  124. }
  125. async fn build_cxx_node(
  126. root: &Path,
  127. paths: &[&Path],
  128. out_name: &str,
  129. args: &[&str],
  130. ) -> eyre::Result<()> {
  131. let mut clang = tokio::process::Command::new("clang++");
  132. clang.args(paths);
  133. clang.arg("-std=c++17");
  134. #[cfg(target_os = "linux")]
  135. {
  136. clang.arg("-l").arg("m");
  137. clang.arg("-l").arg("rt");
  138. clang.arg("-l").arg("dl");
  139. clang.arg("-pthread");
  140. }
  141. #[cfg(target_os = "windows")]
  142. {
  143. clang.arg("-ladvapi32");
  144. clang.arg("-luserenv");
  145. clang.arg("-lkernel32");
  146. clang.arg("-lws2_32");
  147. clang.arg("-lbcrypt");
  148. clang.arg("-lncrypt");
  149. clang.arg("-lschannel");
  150. clang.arg("-lntdll");
  151. clang.arg("-liphlpapi");
  152. clang.arg("-lcfgmgr32");
  153. clang.arg("-lcredui");
  154. clang.arg("-lcrypt32");
  155. clang.arg("-lcryptnet");
  156. clang.arg("-lfwpuclnt");
  157. clang.arg("-lgdi32");
  158. clang.arg("-lmsimg32");
  159. clang.arg("-lmswsock");
  160. clang.arg("-lole32");
  161. clang.arg("-lopengl32");
  162. clang.arg("-lsecur32");
  163. clang.arg("-lshell32");
  164. clang.arg("-lsynchronization");
  165. clang.arg("-luser32");
  166. clang.arg("-lwinspool");
  167. clang.arg("-Wl,-nodefaultlib:libcmt");
  168. clang.arg("-D_DLL");
  169. clang.arg("-lmsvcrt");
  170. }
  171. #[cfg(target_os = "macos")]
  172. {
  173. clang.arg("-framework").arg("CoreServices");
  174. clang.arg("-framework").arg("Security");
  175. clang.arg("-l").arg("System");
  176. clang.arg("-l").arg("resolv");
  177. clang.arg("-l").arg("pthread");
  178. clang.arg("-l").arg("c");
  179. clang.arg("-l").arg("m");
  180. }
  181. clang.args(args);
  182. clang.arg("-L").arg(root.join("target").join("debug"));
  183. clang
  184. .arg("--output")
  185. .arg(Path::new("../build").join(format!("{out_name}{EXE_SUFFIX}")));
  186. if let Some(parent) = paths[0].parent() {
  187. clang.current_dir(parent);
  188. }
  189. if !clang.status().await?.success() {
  190. bail!("failed to compile c++ node");
  191. };
  192. Ok(())
  193. }
  194. async fn build_cxx_operator(
  195. paths: &[&Path],
  196. out_name: &str,
  197. link_args: &[&str],
  198. ) -> eyre::Result<()> {
  199. let mut object_file_paths = Vec::new();
  200. for path in paths {
  201. let mut compile = tokio::process::Command::new("clang++");
  202. compile.arg("-c").arg(path);
  203. compile.arg("-std=c++17");
  204. let object_file_path = path.with_extension("o");
  205. compile.arg("-o").arg(&object_file_path);
  206. #[cfg(unix)]
  207. compile.arg("-fPIC");
  208. if let Some(parent) = path.parent() {
  209. compile.current_dir(parent);
  210. }
  211. if !compile.status().await?.success() {
  212. bail!("failed to compile cxx operator");
  213. };
  214. object_file_paths.push(object_file_path);
  215. }
  216. let mut link = tokio::process::Command::new("clang++");
  217. link.arg("-shared").args(&object_file_paths);
  218. link.args(link_args);
  219. #[cfg(target_os = "windows")]
  220. {
  221. link.arg("-ladvapi32");
  222. link.arg("-luserenv");
  223. link.arg("-lkernel32");
  224. link.arg("-lws2_32");
  225. link.arg("-lbcrypt");
  226. link.arg("-lncrypt");
  227. link.arg("-lschannel");
  228. link.arg("-lntdll");
  229. link.arg("-liphlpapi");
  230. link.arg("-lcfgmgr32");
  231. link.arg("-lcredui");
  232. link.arg("-lcrypt32");
  233. link.arg("-lcryptnet");
  234. link.arg("-lfwpuclnt");
  235. link.arg("-lgdi32");
  236. link.arg("-lmsimg32");
  237. link.arg("-lmswsock");
  238. link.arg("-lole32");
  239. link.arg("-lopengl32");
  240. link.arg("-lsecur32");
  241. link.arg("-lshell32");
  242. link.arg("-lsynchronization");
  243. link.arg("-luser32");
  244. link.arg("-lwinspool");
  245. link.arg("-Wl,-nodefaultlib:libcmt");
  246. link.arg("-D_DLL");
  247. link.arg("-lmsvcrt");
  248. link.arg("-fms-runtime-lib=static");
  249. }
  250. link.arg("-o")
  251. .arg(Path::new("../build").join(format!("{DLL_PREFIX}{out_name}{DLL_SUFFIX}")));
  252. if let Some(parent) = paths[0].parent() {
  253. link.current_dir(parent);
  254. }
  255. if !link.status().await?.success() {
  256. bail!("failed to create shared library from cxx operator (c api)");
  257. };
  258. Ok(())
  259. }
  260. fn set_up_tracing() -> eyre::Result<()> {
  261. use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt;
  262. let stdout_log = tracing_subscriber::fmt::layer()
  263. .pretty()
  264. .with_filter(LevelFilter::DEBUG);
  265. let subscriber = tracing_subscriber::Registry::default().with(stdout_log);
  266. tracing::subscriber::set_global_default(subscriber)
  267. .context("failed to set tracing global subscriber")
  268. }

DORA (Dataflow-Oriented Robotic Architecture) is middleware designed to streamline and simplify the creation of AI-based robotic applications. It offers low latency, composable, and distributed datafl