diff --git a/Cargo.lock b/Cargo.lock index 67f838b..56f9686 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,226 +1,429 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + [[package]] -name = "ansi_term" -version = "0.11.0" +name = "camino" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", ] [[package]] -name = "atty" -version = "0.2.14" +name = "cargo-mpirun" +version = "0.2.0" +dependencies = [ + "cargo_metadata", + "clap", + "thiserror", +] + +[[package]] +name = "cargo-platform" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" dependencies = [ - "hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", ] [[package]] -name = "bitflags" -version = "1.2.1" +name = "cargo_metadata" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "982a0cf6a99c350d7246035613882e376d58cebe571785abc5da4f648d53ac0a" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] [[package]] -name = "cargo-mpirun" -version = "0.1.8" +name = "cc" +version = "1.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" + +[[package]] +name = "clap" +version = "4.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0acbd8d28a0a60d7108d7ae850af6ba34cf2d1257fc646980e5f97ce14275966" dependencies = [ - "cargo_metadata 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "clap_derive", + "clap_lex", + "is-terminal", + "once_cell", + "strsim", + "termcolor", ] [[package]] -name = "cargo_metadata" -version = "0.9.1" +name = "clap_derive" +version = "4.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "clap" -version = "2.33.0" +name = "clap_lex" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "errno" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "errno-dragonfly", + "libc", + "winapi", ] +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" -version = "0.1.6" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e394faa0efb47f9f227f1cd89978f854542b318a6f64fa695489c9c993056656" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "windows-sys", +] + +[[package]] +name = "is-terminal" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae5bc6e2eb41c9def29a3e0f1306382807764b9b53112030eff57435667352d" +dependencies = [ + "hermit-abi", + "io-lifetimes", + "rustix", + "windows-sys", ] [[package]] name = "itoa" -version = "0.4.4" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "libc" -version = "0.2.66" +version = "0.2.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" + +[[package]] +name = "linux-raw-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f" + +[[package]] +name = "once_cell" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" + +[[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] [[package]] name = "proc-macro2" -version = "1.0.8" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.2" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustix" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b1fbb4dfc4eb1d390c02df47760bb19a84bb80b301ecc947ab5406394d8223e" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", ] [[package]] name = "ryu" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" [[package]] name = "semver" -version = "0.9.0" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", ] -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "serde" -version = "1.0.104" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +dependencies = [ + "serde_derive", +] [[package]] name = "serde_derive" -version = "1.0.104" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "serde_json" -version = "1.0.44" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" dependencies = [ - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa", + "ryu", + "serde", ] [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.13" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ - "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] -name = "textwrap" -version = "0.11.0" +name = "termcolor" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ - "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util", ] [[package]] -name = "unicode-width" -version = "0.1.7" +name = "thiserror" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +dependencies = [ + "thiserror-impl", +] [[package]] -name = "unicode-xid" -version = "0.2.0" +name = "thiserror-impl" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] -name = "vec_map" -version = "0.8.1" +name = "version_check" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "winapi" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "yaml-rust" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum cargo_metadata 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46e3374c604fb39d1a2f35ed5e4a4e30e60d01fab49446e08f1b3e9a90aef202" -"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772" -"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" -"checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548" -"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" -"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" -"checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +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.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" diff --git a/Cargo.toml b/Cargo.toml index 14f9699..9a4faa1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,20 +1,22 @@ [package] name = "cargo-mpirun" -version = "0.1.8" -authors = ["Andrew Gaspar "] -description = """ - `cargo mpirun` allows you to easily build and run your MPI applications in - a single command. It emulates `cargo run`, allowing you to specify a \ - target to be built and run, and cargo takes care of the rest.""" +version = "0.2.0" +authors = ["Andrew Gaspar ", +"Jed Brown ",] +description = """\ +`cargo mpirun` builds and runs your MPI applications in a single command, similar to `cargo run`.\ +""" readme = "README.md" license = "MIT" repository = "https://github.com/AndrewGaspar/cargo-mpirun" categories = ["development-tools"] keywords = ["message-passing", "parallel", "MPI", "cargo-subcommand"] +edition = "2021" [dependencies] -cargo_metadata = "0.9.1" -clap = { version = "~2.33.0", features=["yaml"] } +cargo_metadata = "0.15.2" +clap = { version = "4.0.27", features = ["cargo", "derive"] } +thiserror = "1.0.37" [badges] -travis-ci = { repository = "AndrewGaspar/cargo-mpirun", branch = "master" } \ No newline at end of file +travis-ci = { repository = "AndrewGaspar/cargo-mpirun", branch = "master" } diff --git a/README.md b/README.md index 10e1fbf..90cdc82 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,17 @@ for starting MPI jobs. cargo install cargo-mpirun ``` +### Library +To use `cargo-mpirun` as a library, skip the install command above and edit your `Cargo.toml` to include + +``` toml +[dependencies] +cargo-mpirun = "0.2.0" +``` + ## Related Projects If you're interested in writing MPI applications in Rust, take a look at -[rsmpi](https://github.com/bsteinb/rsmpi). It provides a zero-overhead, safe +[rsmpi](https://github.com/rsmpi/rsmpi). It provides a zero-overhead, safe abstraction over the C MPI APIs. ## Usage @@ -56,52 +64,92 @@ cargo mpirun --example ### Full Usage ``` -cargo-mpirun 0.1 -Andrew Gaspar -Run the main binary of the local package (src/main.rs) using mpiexec. - -USAGE: - cargo mpirun [OPTIONS] - -OPTIONS: - -n, --np Number of processes to run - -N, --npernode - Launch num_processes per node on all allocated nodes - - --oversubscribe - Nodes are allowed to be oversubscribed, even on a managed system, - and overloading of processing elements - --bin Name of the bin target to run - --example Name of the example target to run - -p, --package Package with the target to run - -j, --jobs - Number of parallel jobs, defaults to # of CPUs - - --release - Build artifacts in release mode, with optimizations - - --features ... - Space-separated list of features to also build - - --all-features Build all available features - --no-default-features Do not build the `default` feature - --target Build for the target triple - --manifest-path Path to the manifest to execute - -v, --verbose - Use verbose output (-vv very verbose/build.rs output) - - -q, --quiet No output printed to stdout - --color Coloring [values: auto, always, never] - --message-format - Error format [default: human] [values: human, json] - - --frozen - Require Cargo.lock and cache are up to date - - --locked Require Cargo.lock is up to date - -Z ... Unstable (nightly-only) flags to Cargo - -h, --help Prints help information - -V, --version Prints version information +Run a binary or example of the local package using mpiexec. + +Usage: cargo mpirun [OPTIONS] [-- ...] + +Arguments: + [ARGS]... + Arguments for mpiexec + +Options: + -n, --np + Number of processes + + -N, --npernode + Number of processes per node on all allocated nodes + + --mpiexec + Command to execute in place of `mpiexec` (see also MPIEXEC and MPI_HOME) + + --oversubscribe + Allow nodes to be oversubscribed (may cause severe performance degradation) + + --bin + Name of bin target to run + + --example + Name of example target to run + + -p, --package + Package with the target to run + + -j, --jobs + Number of parallel build jobs; default to # of CPUs + + --release + Build artifacts in release mode, with optimizations + + --offline + Build without accessing the network + + --features + Space or comma separated list of features to activate + + --all-features + Build all available features + + --no-default-features + Do not build the `default` feature + + --target + Build for the target triple + + --target-dir + Directory for all generated artifacts + + --config + Override a configuration value + + --manifest-path + Path to the manifest to execute + + -v, --verbose... + Use verbose output (`-vv` very verbose/build.rs output) + + -q, --quiet + No output printed to stdout + + --color + Possible values: + - auto: Use colored output if writing to a terminal/TTY + - always: Always use colored output + - never: Never use colored output + + --frozen + Require Cargo.lock and cache are up to date + + --locked + Require Cargo.lock is up to date + + -Z + Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details + + -h, --help + Print help information (use `-h` for a summary) + + -V, --version + Print version information If neither `--bin` nor `--example` are given, then if the project only has one bin target it will be run. Otherwise `--bin` specifies the bin target to run, @@ -109,6 +157,11 @@ and `--example` specifies the example target to run. At most one of `--bin` or `--example` can be provided. All of the trailing arguments are passed to mpiexec. If you're passing arguments -to both Cargo and the binary, the ones after `--` go to mpiexec, the ones before -go to Cargo. -``` \ No newline at end of file +to both Cargo and the binary, the ones after `--` go to mpiexec, the +ones before go to Cargo. + +Environment variables: + + MPIEXEC - Command to use for mpiexec + MPI_HOME - Find mpiexec in $MPI_HOME/bin/mpiexec +``` diff --git a/examples/pid.rs b/examples/pid.rs new file mode 100644 index 0000000..9837378 --- /dev/null +++ b/examples/pid.rs @@ -0,0 +1,4 @@ +fn main() { + let name = std::env::args().next().unwrap(); + println!("{}: {}", name, std::process::id()); +} diff --git a/src/args.rs b/src/args.rs new file mode 100644 index 0000000..2c2ad8c --- /dev/null +++ b/src/args.rs @@ -0,0 +1,108 @@ +#[derive(Debug, Default, clap::Args)] +#[command( + author, + version, + about = "Run a binary or example of the local package using mpiexec.", + after_help = "If neither `--bin` nor `--example` are given, then if the project only has one +bin target it will be run. Otherwise `--bin` specifies the bin target to run, +and `--example` specifies the example target to run. At most one of `--bin` or +`--example` can be provided. + +All of the trailing arguments are passed to mpiexec. If you're passing arguments +to both Cargo and the binary, the ones after `--` go to mpiexec, the +ones before go to Cargo. + +Environment variables: + + MPIEXEC - Command to use for mpiexec + MPI_HOME - Find mpiexec in $MPI_HOME/bin/mpiexec +" +)] +pub struct Args { + /// Number of processes + #[arg( + short = 'n', + long = "np", + // Open MPI's mpiexec uses number of physical cores by default; MPICH + // uses 1, srun uses number configured in sbatch. + value_parser = clap::value_parser!(u32).range(1..) + )] + pub num_processes: Option, + #[arg( + short = 'N', + long = "npernode", + help = "Number of processes per node on all allocated nodes", + value_parser = clap::value_parser!(u32).range(1..) + )] + pub num_processes_per_node: Option, + /// Command to execute in place of `mpiexec` (see also MPIEXEC and MPI_HOME) + #[arg(long)] + pub mpiexec: Option, + /// Allow nodes to be oversubscribed (may cause severe performance degradation) + #[arg(long)] + pub oversubscribe: bool, + /// Name of bin target to run + #[arg(long, group = "exec-args")] + pub bin: Option, + /// Name of example target to run + #[arg(long, group = "exec-args")] + pub example: Option, + /// Package with the target to run + #[arg(short = 'p', long)] + pub package: Option, + /// Number of parallel build jobs; default to # of CPUs + #[arg(short = 'j', long, value_parser = clap::value_parser!(u32).range(1..))] + pub jobs: Option, + /// Build artifacts in release mode, with optimizations + #[arg(long)] + pub release: bool, + /// Build without accessing the network + #[arg(long)] + pub offline: bool, + /// Space or comma separated list of features to activate + #[arg(long)] + pub features: Option, + /// Build all available features + #[arg(long)] + pub all_features: bool, + /// Do not build the `default` feature + #[arg(long)] + pub no_default_features: bool, + /// Build for the target triple + #[arg(long, value_name = "TRIPLE")] + pub target: Option, + /// Directory for all generated artifacts + #[arg(long, value_name = "DIRECTORY")] + pub target_dir: Option, + /// Override a configuration value + #[arg(long, value_name = "KEY=VAL")] + pub config: Vec, + /// Path to the manifest to execute + #[arg(long)] + pub manifest_path: Option, + /// Use verbose output (`-vv` very verbose/build.rs output) + #[arg( + short = 'v', + long, + action = clap::ArgAction::Count, + )] + pub verbose: u8, + /// No output printed to stdout + #[arg(short = 'q', long, conflicts_with = "verbose")] + pub quiet: bool, + + #[arg(long, value_name = "WHEN")] + pub color: Option, + /// Require Cargo.lock and cache are up to date + #[arg(long)] + pub frozen: bool, + /// Require Cargo.lock is up to date + #[arg(long)] + pub locked: bool, + /// Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details + #[arg(short = 'Z', value_name = "FLAG")] + pub unstable_flags: Vec, + /// Arguments for mpiexec + #[arg(last = true, allow_hyphen_values = true)] + pub args: Vec, +} diff --git a/src/cargo_build.rs b/src/cargo_build.rs index 80e8b03..137eb23 100644 --- a/src/cargo_build.rs +++ b/src/cargo_build.rs @@ -1,69 +1,105 @@ -use clap::ArgMatches; +use crate::MpirunError; -use std::process::{self, Command}; +use cargo_metadata::{Artifact, Message}; +use std::process::{Command, Output, Stdio}; -static CARGO_OPTIONS: &[&str] = &[ - "bin", - "example", - "package", - "jobs", - "target", - "manifest-path", - "color", - "message-format", - "Z", -]; - -static CARGO_OPTIONS_MULTIPLE_VALUES: &[&str] = &["features"]; - -static CARGO_FLAGS: &[&str] = &[ - "all-features", - "no-default-features", - "quiet", - "frozen", - "locked", - "release", -]; - -static CARGO_FLAGS_MULTIPLE: &[&str] = &["verbose"]; +/// Add Cargo options such as (`--bin`, `--features`, `--target') to `command`. +pub fn add_cargo_options(command: &mut Command, args: &crate::Args) { + if let Some(ref val) = args.bin { + command.arg("--bin").arg(val); + } + if let Some(ref val) = args.example { + command.arg("--example").arg(val); + } + if let Some(ref val) = args.package { + command.arg("--package").arg(val); + } + if let Some(ref val) = args.jobs { + command.arg("--jobs").arg(val.to_string()); + } + if args.release { + command.arg("--release"); + } + if args.offline { + command.arg("--offline"); + } + if let Some(ref val) = args.features { + command.arg("--features").arg(val); + } + if args.all_features { + command.arg("--all-features"); + } + if args.no_default_features { + command.arg("--no-default-features"); + } + if let Some(ref val) = args.target { + command.arg("--target").arg(val); + } + if let Some(ref val) = args.target_dir { + command.arg("--target-dir").arg(val); + } + for keyval in args.config.iter() { + command.arg("--config").arg(keyval); + } + if let Some(ref val) = args.manifest_path { + command.arg("--manifest-path").arg(val); + } + for _ in 1..args.verbose { + command.arg("--verbose"); + } + if args.quiet { + command.arg("--quiet"); + } + if let Some(ref val) = args.color { + command.arg("--color").arg::(val.to_string()); + } + if args.frozen { + command.arg("--frozen"); + } + if args.locked { + command.arg("--locked"); + } + for flag in args.unstable_flags.iter() { + command.arg("-Z").arg(flag); + } +} -pub fn run<'a>(matches: &ArgMatches<'a>) { +/// Invoke `cargo build` with suitable options and parse the output to return +/// executable artifacts. +pub fn build(args: &crate::Args) -> crate::Result> { let mut cargo_build = Command::new("cargo"); cargo_build.arg("build"); - - for option in CARGO_OPTIONS { - if let Some(value) = matches.value_of(option) { - cargo_build.arg("--".to_owned() + option).arg(value); - } + add_cargo_options(&mut cargo_build, args); + cargo_build.arg("--message-format=json-render-diagnostics"); + if args.verbose > 1 { + println!("Build: {:?}", cargo_build); } - - for option in CARGO_OPTIONS_MULTIPLE_VALUES { - if let Some(values) = matches.values_of(option) { - cargo_build.arg("--".to_owned() + option).args(values); - } - } - - for flag in CARGO_FLAGS { - if matches.is_present(flag) { - cargo_build.arg("--".to_owned() + flag); - } + let Output { status, stdout, .. } = cargo_build.stderr(Stdio::inherit()).output()?; + if !status.success() { + return Err(MpirunError::BuildStatus(format!( + "cargo build return {status}" + ))); } + Message::parse_stream(&*stdout) + .filter_map(|m| match m { + Ok(Message::CompilerArtifact(a)) if a.executable.is_some() => Some(Ok(a)), + _ => None, + }) + .collect() +} - for flag in CARGO_FLAGS_MULTIPLE { - for _ in 0..matches.occurrences_of(flag) { - cargo_build.arg("--".to_owned() + flag); - } +/// Like `build()`, but ensure that exactly one artifact matches +pub fn build_unique(args: &crate::Args) -> crate::Result { + let artifacts = build(&args)?; + if artifacts.len() == 0 { + return Err(MpirunError::Incompatible( + "No target found, perhaps --example is needed".to_owned(), + )); } - - let status = cargo_build - .status() - .expect("Failed to execute cargo build - is cargo in your path?"); - - if !status.success() { - let code = match status.code() { - Some(x) => x, - None => 101, - }; - process::exit(code); + if artifacts.len() > 1 { + return Err(MpirunError::Incompatible( + "Multiple targets found".to_owned(), + )); } + Ok(artifacts[0].clone()) } diff --git a/src/cli.yml b/src/cli.yml deleted file mode 100644 index 29e125a..0000000 --- a/src/cli.yml +++ /dev/null @@ -1,116 +0,0 @@ -name: cargo -bin_name: cargo -subcommands: - - mpirun: - version: 0.1.8 - author: Andrew Gaspar - about: > - Run the main binary of the local package (src/main.rs) using - mpiexec. - after_help: > - If neither `--bin` nor `--example` are given, then if the project - only has one bin target it will be run. Otherwise `--bin` specifies - the bin target to run, and `--example` specifies the example target - to run. At most one of `--bin` or `--example` can be provided. - - - All of the trailing arguments are passed to mpiexec. If you're - passing arguments to both Cargo and the binary, the ones after `--` - go to mpiexec, the ones before go to Cargo. - settings: [UnifiedHelpMessage, DeriveDisplayOrder] - args: - - num_processes: - short: n - long: np - value_name: num_processes - help: Number of processes to run - - num_processes_per_node: - short: N - long: npernode - value_name: num_processes - help: Launch num_processes per node on all allocated nodes - - oversubscribe: - long: oversubscribe - help: > - Nodes are allowed to be oversubscribed, even on a managed - system, and overloading of processing elements - - bin: - long: bin - value_name: NAME - help: Name of the bin target to run - conflicts_with: example - - example: - long: example - value_name: NAME - help: Name of the example target to run - conflicts_with: bin - - package: - short: p - long: package - value_name: NAME - help: Package with the target to run - - jobs: - short: j - long: jobs - value_name: N - help: "Number of parallel jobs, defaults to # of CPUs" - - release: - long: release - help: Build artifacts in release mode, with optimizations - - features: - long: features - value_name: FEATURE - multiple: true - help: Space-separated list of features to also build - - all-features: - long: all-features - help: Build all available features - - no-default-features: - long: no-default-features - help: Do not build the `default` feature - - target: - long: target - value_name: TRIPLE - help: Build for the target triple - - manifest-path: - long: manifest-path - value_name: PATH - help: Path to the manifest to execute - - verbose: - short: v - long: verbose - multiple: true - help: Use verbose output (-vv very verbose/build.rs output) - conflicts_with: quiet - - quiet: - short: q - long: quiet - help: No output printed to stdout - conflicts_with: verbose - - color: - long: color - value_name: WHEN - possible_values: [auto, always, never] - help: Coloring - - message-format: - long: message-format - value_name: FMT - possible_values: [human, json] - default_value: human - help: Error format - - frozen: - long: frozen - help: Require Cargo.lock and cache are up to date - - locked: - long: locked - help: Require Cargo.lock is up to date - - Z: - short: Z - value_name: FLAG - multiple: true - help: Unstable (nightly-only) flags to Cargo - - args: - last: true - allow_hyphen_values: true - multiple: true - help: Arguments for mpiexec \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..0b884cb --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,25 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum MpirunError { + #[error("cargo build failed")] + Build(#[from] std::io::Error), + #[error("cargo build status")] + BuildStatus(String), + #[error("no unique artifact")] + Incompatible(String), + #[error("mpiexec failed")] + Run(String), +} + +pub type Result = std::result::Result; + +mod args; +mod cargo_build; +mod mpirun; + +pub use self::{ + args::Args, + cargo_build::{add_cargo_options, build, build_unique}, + mpirun::run_command, +}; diff --git a/src/main.rs b/src/main.rs index 3c0c9a2..339a8ed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,147 +1,30 @@ -extern crate cargo_metadata; -#[macro_use] -extern crate clap; +use cargo_mpirun::{build_unique, run_command, Args, MpirunError, Result}; +use clap::Parser; -use clap::{App, ArgMatches}; -use std::path::*; - -mod cargo_build; -mod mpirun; - -use cargo_metadata::{Metadata, Package, Target}; - -struct ApplicableTarget<'a> { - target_type: &'static str, - target: &'a Target, -} - -fn get_applicable_target<'a>(metadata: &'a Metadata, args: &'a ArgMatches) -> ApplicableTarget<'a> { - let packages: Vec<&Package> = { - if let Some(name) = args.value_of("package") { - vec![metadata.packages.iter().find(|p| p.name == name).unwrap()] - } else { - metadata.packages.iter().collect() - } - }; - - if let Some(bin) = args.value_of("bin") { - // Validates bin actually exists - let matching_bins: Vec<_> = packages - .iter() - .flat_map(|p| p.targets.iter()) - .filter(|t| t.kind[0] == "bin" && t.name == bin) - .collect(); - - if matching_bins.len() > 1 { - println!( - "error: `cargo mpirun` can run at most one executable, but multiple were specified" - ); - std::process::exit(101); - } else if matching_bins.is_empty() { - println!("error: no bin target named `{}`", bin); - std::process::exit(101); - } - - ApplicableTarget { - target_type: "bin", - target: matching_bins[0], - } - } else if let Some(example) = args.value_of("example") { - // Validates example actually exists - let examples: Vec<_> = packages - .iter() - .flat_map(|p| p.targets.iter()) - .filter(|t| t.kind[0] == "example" && t.name == example) - .collect(); - - if examples.len() > 1 { - println!( - "error: `cargo mpirun` can run at most one executable, but multiple were specified" - ); - std::process::exit(101); - } else if examples.is_empty() { - println!("error: no example target named `{}`", example); - std::process::exit(101); - } - - ApplicableTarget { - target_type: "example", - target: examples[0], - } - } else { - // Get all bins targets in workspace - let bin_targets: Vec<_> = packages - .iter() - .flat_map(|p| p.targets.iter()) - .filter(|t| t.kind[0] == "bin") - .collect(); - - if bin_targets.is_empty() { - eprintln!("error: a bin target must be available for `cargo mpirun`"); - std::process::exit(101); - } else if bin_targets.len() > 1 { - eprintln!( - "error: `cargo mpirun` requires that a project only have one executable; use \ - the `--bin` option to specify which one to run \n\ - available binaries: {}", - bin_targets - .iter() - .map(|t| t.name.as_str()) - .collect::>() - .join(", ") - ); - std::process::exit(101); - } - - ApplicableTarget { - target_type: "bin", - target: bin_targets[0], - } - } +#[derive(Debug, Parser)] +#[command(name = "cargo", bin_name = "cargo")] +pub enum Cargo { + Mpirun(Args), } -fn find_target(metadata: &Metadata, args: &ArgMatches, target: &ApplicableTarget) -> PathBuf { - let target_directory = Path::new(&metadata.target_directory); - - let target_directory: PathBuf = if let Some(target) = args.value_of("target") { - target_directory.join(target) - } else { - target_directory.into() - }; - - let executable_path = if args.is_present("release") { - target_directory.join("release") +fn main() -> Result<()> { + let Cargo::Mpirun(args) = Cargo::parse(); + + let artifact = build_unique(&args)?; + if let Some(ref target) = artifact.executable { + let mut mpirun = run_command(target.as_std_path(), &args); + let code = match mpirun.status() { + Ok(status) => status.code().unwrap_or(-1), + Err(_) => { + eprintln!("Could not find mpiexec - is it in your user path?"); + -1 + } + }; + std::process::exit(code); } else { - target_directory.join("debug") - }; - - match target.target_type { - "bin" => executable_path.join(&target.target.name), - "example" => executable_path.join("examples").join(&target.target.name), - _ => unimplemented!(), - } -} - -fn main() -> Result<(), Box> { - let cli = load_yaml!("cli.yml"); - let matches = App::from_yaml(cli).get_matches(); - - let matches = matches - .subcommand_matches("mpirun") - .expect("Only the 'mpirun' sub-command is implemented."); - - let mut metadata_cmd = cargo_metadata::MetadataCommand::new(); - if let Some(path) = matches.value_of("manifest-path").map(Path::new) { - metadata_cmd.manifest_path(path); + return Err(MpirunError::Incompatible(format!( + "Target {} does not have executable", + artifact.target.name + ))); } - - let metadata = metadata_cmd.exec()?; - - let target = get_applicable_target(&metadata, &matches); - - cargo_build::run(&matches); - - let target = find_target(&metadata, matches, &target); - - mpirun::run(&target, matches); } diff --git a/src/mpirun.rs b/src/mpirun.rs index a2d79e4..d1f5cf9 100644 --- a/src/mpirun.rs +++ b/src/mpirun.rs @@ -1,39 +1,35 @@ -use clap::ArgMatches; use std::path::Path; -use std::process::{self, Command}; - -pub fn run(executable: &Path, matches: &ArgMatches) -> ! { - let mut mpirun = Command::new("mpiexec"); +use std::process::Command; + +/// Build command to run MPI job +pub fn run_command(executable: &Path, args: &crate::Args) -> Command { + let mpiexec = if let Some(ref c) = args.mpiexec { + c.clone() + } else if let Ok(c) = std::env::var("MPIEXEC") { + c + } else if let Ok(prefix) = std::env::var("MPI_HOME") { + format!("{prefix}/bin/mpiexec") + } else { + // assume mpiexec is in PATH + "mpiexec".to_string() + }; + let mut mpirun = Command::new(mpiexec); - if let Some(np) = matches.value_of("num_processes") { - mpirun.arg("-n").arg(np); + if let Some(n) = args.num_processes { + mpirun.arg("-n").arg(n.to_string()); } - - if let Some(n) = matches.value_of("num_processes_per_node") { - mpirun.arg("--npernode").arg(n); + if let Some(n) = args.num_processes_per_node { + mpirun.arg("--npernode").arg(n.to_string()); } - - if matches.is_present("oversubscribe") { + if args.oversubscribe { mpirun.arg("--oversubscribe"); } mpirun.arg(executable); + mpirun.args(&args.args); - if let Some(args) = matches.values_of("args") { - mpirun.args(args); - } - - if matches.is_present("verbose") { + if args.verbose > 0 { eprintln!("Running: {:?}", mpirun); } - - let code = match mpirun.status() { - Ok(status) => status.code().unwrap_or(-1), - Err(_) => { - eprintln!("Could not find mpiexec - is it in your user path?"); - -1 - } - }; - - process::exit(code) + mpirun }