Repository: kythe/kythe
Pull request #5355 (2022-08-16 18:19:11)

chore(rust_common): upgrade to clap v3


Patch:
diff --git a/Cargo.Bazel.lock b/Cargo.Bazel.lock
index da534ad0c..bc05c69ca 100644
--- a/Cargo.Bazel.lock
+++ b/Cargo.Bazel.lock
@@ -17,20 +17,11 @@ dependencies = [
  "memchr",
 ]
 
-[[package]]
-name = "ansi_term"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
-dependencies = [
- "winapi",
-]
-
 [[package]]
 name = "anyhow"
-version = "1.0.59"
+version = "1.0.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c91f1f46651137be86f3a2b9a8359f9ab421d04d941c62b5982e1ca21113adf9"
+checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142"
 
 [[package]]
 name = "atty"
@@ -117,17 +108,41 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "clap"
-version = "2.34.0"
+version = "3.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
+checksum = "a3dbbb6653e7c55cc8595ad3e1f7be8f32aba4eb7ff7f0fd1163d4f3d137c0a9"
 dependencies = [
- "ansi_term",
  "atty",
  "bitflags",
+ "clap_derive",
+ "clap_lex",
+ "indexmap",
+ "once_cell",
  "strsim",
+ "termcolor",
  "textwrap",
- "unicode-width",
- "vec_map",
+]
+
+[[package]]
+name = "clap_derive"
+version = "3.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ba52acd3b0a5c33aeada5cdaa3267cdc7c594a98731d4268cdc1532f4264cb4"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
+dependencies = [
+ "os_str_bytes",
 ]
 
 [[package]]
@@ -306,6 +321,18 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
 
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+
+[[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.19"
@@ -321,6 +348,16 @@ version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
 
+[[package]]
+name = "indexmap"
+version = "1.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
 [[package]]
 name = "instant"
 version = "0.1.12"
@@ -422,6 +459,12 @@ version = "1.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
 
+[[package]]
+name = "os_str_bytes"
+version = "6.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4"
+
 [[package]]
 name = "parking_lot"
 version = "0.11.2"
@@ -677,18 +720,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
 [[package]]
 name = "serde"
-version = "1.0.142"
+version = "1.0.143"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e590c437916fb6b221e1d00df6e3294f3fccd70ca7e92541c475d6ed6ef5fee2"
+checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.142"
+version = "1.0.143"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34b5b8d809babe02f538c2cfec6f2c1ed10804c0e5a6a041a049a4f5588ccc2e"
+checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -749,9 +792,9 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
 
 [[package]]
 name = "strsim"
-version = "0.8.0"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
 [[package]]
 name = "syn"
@@ -775,14 +818,20 @@ dependencies = [
 ]
 
 [[package]]
-name = "textwrap"
-version = "0.11.0"
+name = "termcolor"
+version = "1.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
 dependencies = [
- "unicode-width",
+ "winapi-util",
 ]
 
+[[package]]
+name = "textwrap"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
+
 [[package]]
 name = "thiserror"
 version = "1.0.32"
@@ -826,18 +875,6 @@ version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
 
-[[package]]
-name = "unicode-width"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
-
-[[package]]
-name = "vec_map"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
-
 [[package]]
 name = "version_check"
 version = "0.9.4"
@@ -866,6 +903,15 @@ 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"
diff --git a/WORKSPACE b/WORKSPACE
index 2f3092f91..8398b9756 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -60,7 +60,8 @@ crates_repository(
             version = "0.13.0",
         ),
         "clap": crate.spec(
-            version = "2.34.0",
+            features = ["derive"],
+            version = "3.1.6",
         ),
         "colored": crate.spec(
             version = "2.0.0",
diff --git a/cargo-bazel-lock.json b/cargo-bazel-lock.json
index 371989db1..85aa00e48 100644
--- a/cargo-bazel-lock.json
+++ b/cargo-bazel-lock.json
@@ -1,5 +1,5 @@
 {
-  "checksum": "9672e74ba07f6634691bf2ca66a7508a7858c9fed1f75d55f413392ba7249ecc",
+  "checksum": "2fb71966054a34e9ce8fd5eae54be814fd7cb70604262d5be08d28184209a9fc",
   "crates": {
     "adler 1.0.2": {
       "name": "adler",
@@ -80,57 +80,13 @@
       },
       "license": "Unlicense/MIT"
     },
-    "ansi_term 0.12.1": {
-      "name": "ansi_term",
-      "version": "0.12.1",
-      "repository": {
-        "Http": {
-          "url": "https://crates.io/api/v1/crates/ansi_term/0.12.1/download",
-          "sha256": "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
-        }
-      },
-      "targets": [
-        {
-          "Library": {
-            "crate_name": "ansi_term",
-            "crate_root": "src/lib.rs",
-            "srcs": {
-              "include": [
-                "**/*.rs"
-              ],
-              "exclude": []
-            }
-          }
-        }
-      ],
-      "library_target_name": "ansi_term",
-      "common_attrs": {
-        "compile_data_glob": [
-          "**"
-        ],
-        "deps": {
-          "common": [],
-          "selects": {
-            "cfg(target_os = \"windows\")": [
-              {
-                "id": "winapi 0.3.9",
-                "target": "winapi"
-              }
-            ]
-          }
-        },
-        "edition": "2015",
-        "version": "0.12.1"
-      },
-      "license": "MIT"
-    },
-    "anyhow 1.0.59": {
+    "anyhow 1.0.60": {
       "name": "anyhow",
-      "version": "1.0.59",
+      "version": "1.0.60",
       "repository": {
         "Http": {
-          "url": "https://crates.io/api/v1/crates/anyhow/1.0.59/download",
-          "sha256": "c91f1f46651137be86f3a2b9a8359f9ab421d04d941c62b5982e1ca21113adf9"
+          "url": "https://crates.io/api/v1/crates/anyhow/1.0.60/download",
+          "sha256": "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142"
         }
       },
       "targets": [
@@ -171,14 +127,14 @@
         "deps": {
           "common": [
             {
-              "id": "anyhow 1.0.59",
+              "id": "anyhow 1.0.60",
               "target": "build_script_build"
             }
           ],
           "selects": {}
         },
         "edition": "2018",
-        "version": "1.0.59"
+        "version": "1.0.60"
       },
       "build_script_attrs": {
         "data_glob": [
@@ -666,13 +622,13 @@
       },
       "license": "MIT/Apache-2.0"
     },
-    "clap 2.34.0": {
+    "clap 3.2.16": {
       "name": "clap",
-      "version": "2.34.0",
+      "version": "3.2.16",
       "repository": {
         "Http": {
-          "url": "https://crates.io/api/v1/crates/clap/2.34.0/download",
-          "sha256": "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
+          "url": "https://crates.io/api/v1/crates/clap/3.2.16/download",
+          "sha256": "a3dbbb6653e7c55cc8595ad3e1f7be8f32aba4eb7ff7f0fd1163d4f3d137c0a9"
         }
       },
       "targets": [
@@ -687,6 +643,18 @@
               "exclude": []
             }
           }
+        },
+        {
+          "Binary": {
+            "crate_name": "stdio-fixture",
+            "crate_root": "src/bin/stdio-fixture.rs",
+            "srcs": {
+              "include": [
+                "**/*.rs"
+              ],
+              "exclude": []
+            }
+          }
         }
       ],
       "library_target_name": "clap",
@@ -695,13 +663,16 @@
           "**"
         ],
         "crate_features": [
-          "ansi_term",
           "atty",
+          "clap_derive",
           "color",
           "default",
+          "derive",
+          "once_cell",
+          "std",
           "strsim",
           "suggestions",
-          "vec_map"
+          "termcolor"
         ],
         "deps": {
           "common": [
@@ -714,35 +685,148 @@
               "target": "bitflags"
             },
             {
-              "id": "strsim 0.8.0",
+              "id": "clap_lex 0.2.4",
+              "target": "clap_lex"
+            },
+            {
+              "id": "indexmap 1.9.1",
+              "target": "indexmap"
+            },
+            {
+              "id": "once_cell 1.13.0",
+              "target": "once_cell"
+            },
+            {
+              "id": "strsim 0.10.0",
               "target": "strsim"
             },
             {
-              "id": "textwrap 0.11.0",
+              "id": "termcolor 1.1.3",
+              "target": "termcolor"
+            },
+            {
+              "id": "textwrap 0.15.0",
               "target": "textwrap"
+            }
+          ],
+          "selects": {}
+        },
+        "edition": "2021",
+        "proc_macro_deps": {
+          "common": [
+            {
+              "id": "clap_derive 3.2.15",
+              "target": "clap_derive"
+            }
+          ],
+          "selects": {}
+        },
+        "version": "3.2.16"
+      },
+      "license": "MIT OR Apache-2.0"
+    },
+    "clap_derive 3.2.15": {
+      "name": "clap_derive",
+      "version": "3.2.15",
+      "repository": {
+        "Http": {
+          "url": "https://crates.io/api/v1/crates/clap_derive/3.2.15/download",
+          "sha256": "9ba52acd3b0a5c33aeada5cdaa3267cdc7c594a98731d4268cdc1532f4264cb4"
+        }
+      },
+      "targets": [
+        {
+          "ProcMacro": {
+            "crate_name": "clap_derive",
+            "crate_root": "src/lib.rs",
+            "srcs": {
+              "include": [
+                "**/*.rs"
+              ],
+              "exclude": []
+            }
+          }
+        }
+      ],
+      "library_target_name": "clap_derive",
+      "common_attrs": {
+        "compile_data_glob": [
+          "**"
+        ],
+        "crate_features": [
+          "default"
+        ],
+        "deps": {
+          "common": [
+            {
+              "id": "heck 0.4.0",
+              "target": "heck"
             },
             {
-              "id": "unicode-width 0.1.9",
-              "target": "unicode_width"
+              "id": "proc-macro-error 1.0.4",
+              "target": "proc_macro_error"
+            },
+            {
+              "id": "proc-macro2 1.0.43",
+              "target": "proc_macro2"
+            },
+            {
+              "id": "quote 1.0.21",
+              "target": "quote"
             },
             {
-              "id": "vec_map 0.8.2",
-              "target": "vec_map"
+              "id": "syn 1.0.99",
+              "target": "syn"
             }
           ],
-          "selects": {
-            "cfg(not(windows))": [
-              {
-                "id": "ansi_term 0.12.1",
-                "target": "ansi_term"
-              }
-            ]
+          "selects": {}
+        },
+        "edition": "2021",
+        "version": "3.2.15"
+      },
+      "license": "MIT OR Apache-2.0"
+    },
+    "clap_lex 0.2.4": {
+      "name": "clap_lex",
+      "version": "0.2.4",
+      "repository": {
+        "Http": {
+          "url": "https://crates.io/api/v1/crates/clap_lex/0.2.4/download",
+          "sha256": "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
+        }
+      },
+      "targets": [
+        {
+          "Library": {
+            "crate_name": "clap_lex",
+            "crate_root": "src/lib.rs",
+            "srcs": {
+              "include": [
+                "**/*.rs"
+              ],
+              "exclude": []
+            }
           }
+        }
+      ],
+      "library_target_name": "clap_lex",
+      "common_attrs": {
+        "compile_data_glob": [
+          "**"
+        ],
+        "deps": {
+          "common": [
+            {
+              "id": "os_str_bytes 6.2.0",
+              "target": "os_str_bytes"
+            }
+          ],
+          "selects": {}
         },
-        "edition": "2018",
-        "version": "2.34.0"
+        "edition": "2021",
+        "version": "0.2.4"
       },
-      "license": "MIT"
+      "license": "MIT OR Apache-2.0"
     },
     "colored 2.0.0": {
       "name": "colored",
@@ -1374,7 +1458,7 @@
         "deps": {
           "common": [
             {
-              "id": "anyhow 1.0.59",
+              "id": "anyhow 1.0.60",
               "target": "anyhow"
             },
             {
@@ -1382,7 +1466,7 @@
               "target": "base64"
             },
             {
-              "id": "clap 2.34.0",
+              "id": "clap 3.2.16",
               "target": "clap"
             },
             {
@@ -1434,7 +1518,7 @@
               "target": "rls_data"
             },
             {
-              "id": "serde 1.0.142",
+              "id": "serde 1.0.143",
               "target": "serde"
             },
             {
@@ -1755,6 +1839,78 @@
       },
       "license": "MIT/Apache-2.0"
     },
+    "hashbrown 0.12.3": {
+      "name": "hashbrown",
+      "version": "0.12.3",
+      "repository": {
+        "Http": {
+          "url": "https://crates.io/api/v1/crates/hashbrown/0.12.3/download",
+          "sha256": "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+        }
+      },
+      "targets": [
+        {
+          "Library": {
+            "crate_name": "hashbrown",
+            "crate_root": "src/lib.rs",
+            "srcs": {
+              "include": [
+                "**/*.rs"
+              ],
+              "exclude": []
+            }
+          }
+        }
+      ],
+      "library_target_name": "hashbrown",
+      "common_attrs": {
+        "compile_data_glob": [
+          "**"
+        ],
+        "crate_features": [
+          "raw"
+        ],
+        "edition": "2021",
+        "version": "0.12.3"
+      },
+      "license": "MIT OR Apache-2.0"
+    },
+    "heck 0.4.0": {
+      "name": "heck",
+      "version": "0.4.0",
+      "repository": {
+        "Http": {
+          "url": "https://crates.io/api/v1/crates/heck/0.4.0/download",
+          "sha256": "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
+        }
+      },
+      "targets": [
+        {
+          "Library": {
+            "crate_name": "heck",
+            "crate_root": "src/lib.rs",
+            "srcs": {
+              "include": [
+                "**/*.rs"
+              ],
+              "exclude": []
+            }
+          }
+        }
+      ],
+      "library_target_name": "heck",
+      "common_attrs": {
+        "compile_data_glob": [
+          "**"
+        ],
+        "crate_features": [
+          "default"
+        ],
+        "edition": "2018",
+        "version": "0.4.0"
+      },
+      "license": "MIT OR Apache-2.0"
+    },
     "hermit-abi 0.1.19": {
       "name": "hermit-abi",
       "version": "0.1.19",
@@ -1838,6 +1994,81 @@
       },
       "license": "MIT OR Apache-2.0"
     },
+    "indexmap 1.9.1": {
+      "name": "indexmap",
+      "version": "1.9.1",
+      "repository": {
+        "Http": {
+          "url": "https://crates.io/api/v1/crates/indexmap/1.9.1/download",
+          "sha256": "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+        }
+      },
+      "targets": [
+        {
+          "Library": {
+            "crate_name": "indexmap",
+            "crate_root": "src/lib.rs",
+            "srcs": {
+              "include": [
+                "**/*.rs"
+              ],
+              "exclude": []
+            }
+          }
+        },
+        {
+          "BuildScript": {
+            "crate_name": "build_script_build",
+            "crate_root": "build.rs",
+            "srcs": {
+              "include": [
+                "**/*.rs"
+              ],
+              "exclude": []
+            }
+          }
+        }
+      ],
+      "library_target_name": "indexmap",
+      "common_attrs": {
+        "compile_data_glob": [
+          "**"
+        ],
+        "crate_features": [
+          "std"
+        ],
+        "deps": {
+          "common": [
+            {
+              "id": "hashbrown 0.12.3",
+              "target": "hashbrown"
+            },
+            {
+              "id": "indexmap 1.9.1",
+              "target": "build_script_build"
+            }
+          ],
+          "selects": {}
+        },
+        "edition": "2021",
+        "version": "1.9.1"
+      },
+      "build_script_attrs": {
+        "data_glob": [
+          "**"
+        ],
+        "deps": {
+          "common": [
+            {
+              "id": "autocfg 1.1.0",
+              "target": "autocfg"
+            }
+          ],
+          "selects": {}
+        }
+      },
+      "license": "Apache-2.0 OR MIT"
+    },
     "instant 0.1.12": {
       "name": "instant",
       "version": "0.1.12",
@@ -2489,6 +2720,42 @@
       },
       "license": "MIT OR Apache-2.0"
     },
+    "os_str_bytes 6.2.0": {
+      "name": "os_str_bytes",
+      "version": "6.2.0",
+      "repository": {
+        "Http": {
+          "url": "https://crates.io/api/v1/crates/os_str_bytes/6.2.0/download",
+          "sha256": "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4"
+        }
+      },
+      "targets": [
+        {
+          "Library": {
+            "crate_name": "os_str_bytes",
+            "crate_root": "src/lib.rs",
+            "srcs": {
+              "include": [
+                "**/*.rs"
+              ],
+              "exclude": []
+            }
+          }
+        }
+      ],
+      "library_target_name": "os_str_bytes",
+      "common_attrs": {
+        "compile_data_glob": [
+          "**"
+        ],
+        "crate_features": [
+          "raw_os_str"
+        ],
+        "edition": "2021",
+        "version": "6.2.0"
+      },
+      "license": "MIT OR Apache-2.0"
+    },
     "parking_lot 0.11.2": {
       "name": "parking_lot",
       "version": "0.11.2",
@@ -3773,7 +4040,7 @@
               "target": "rls_span"
             },
             {
-              "id": "serde 1.0.142",
+              "id": "serde 1.0.143",
               "target": "serde"
             },
             {
@@ -3836,7 +4103,7 @@
               "target": "rls_span"
             },
             {
-              "id": "serde 1.0.142",
+              "id": "serde 1.0.143",
               "target": "serde"
             }
           ],
@@ -3882,7 +4149,7 @@
         "deps": {
           "common": [
             {
-              "id": "serde 1.0.142",
+              "id": "serde 1.0.143",
               "target": "serde"
             }
           ],
@@ -4018,13 +4285,13 @@
       },
       "license": "MIT/Apache-2.0"
     },
-    "serde 1.0.142": {
+    "serde 1.0.143": {
       "name": "serde",
-      "version": "1.0.142",
+      "version": "1.0.143",
       "repository": {
         "Http": {
-          "url": "https://crates.io/api/v1/crates/serde/1.0.142/download",
-          "sha256": "e590c437916fb6b221e1d00df6e3294f3fccd70ca7e92541c475d6ed6ef5fee2"
+          "url": "https://crates.io/api/v1/crates/serde/1.0.143/download",
+          "sha256": "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"
         }
       },
       "targets": [
@@ -4067,7 +4334,7 @@
         "deps": {
           "common": [
             {
-              "id": "serde 1.0.142",
+              "id": "serde 1.0.143",
               "target": "build_script_build"
             }
           ],
@@ -4077,13 +4344,13 @@
         "proc_macro_deps": {
           "common": [
             {
-              "id": "serde_derive 1.0.142",
+              "id": "serde_derive 1.0.143",
               "target": "serde_derive"
             }
           ],
           "selects": {}
         },
-        "version": "1.0.142"
+        "version": "1.0.143"
       },
       "build_script_attrs": {
         "data_glob": [
@@ -4092,13 +4359,13 @@
       },
       "license": "MIT OR Apache-2.0"
     },
-    "serde_derive 1.0.142": {
+    "serde_derive 1.0.143": {
       "name": "serde_derive",
-      "version": "1.0.142",
+      "version": "1.0.143",
       "repository": {
         "Http": {
-          "url": "https://crates.io/api/v1/crates/serde_derive/1.0.142/download",
-          "sha256": "34b5b8d809babe02f538c2cfec6f2c1ed10804c0e5a6a041a049a4f5588ccc2e"
+          "url": "https://crates.io/api/v1/crates/serde_derive/1.0.143/download",
+          "sha256": "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"
         }
       },
       "targets": [
@@ -4146,7 +4413,7 @@
               "target": "quote"
             },
             {
-              "id": "serde_derive 1.0.142",
+              "id": "serde_derive 1.0.143",
               "target": "build_script_build"
             },
             {
@@ -4157,7 +4424,7 @@
           "selects": {}
         },
         "edition": "2015",
-        "version": "1.0.142"
+        "version": "1.0.143"
       },
       "build_script_attrs": {
         "data_glob": [
@@ -4221,7 +4488,7 @@
               "target": "ryu"
             },
             {
-              "id": "serde 1.0.142",
+              "id": "serde 1.0.143",
               "target": "serde"
             },
             {
@@ -4452,13 +4719,13 @@
       },
       "license": "MIT OR Apache-2.0"
     },
-    "strsim 0.8.0": {
+    "strsim 0.10.0": {
       "name": "strsim",
-      "version": "0.8.0",
+      "version": "0.10.0",
       "repository": {
         "Http": {
-          "url": "https://crates.io/api/v1/crates/strsim/0.8.0/download",
-          "sha256": "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+          "url": "https://crates.io/api/v1/crates/strsim/0.10.0/download",
+          "sha256": "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
         }
       },
       "targets": [
@@ -4481,7 +4748,7 @@
           "**"
         ],
         "edition": "2015",
-        "version": "0.8.0"
+        "version": "0.10.0"
       },
       "license": "MIT"
     },
@@ -4612,13 +4879,57 @@
       },
       "license": "MIT/Apache-2.0"
     },
-    "textwrap 0.11.0": {
+    "termcolor 1.1.3": {
+      "name": "termcolor",
+      "version": "1.1.3",
+      "repository": {
+        "Http": {
+          "url": "https://crates.io/api/v1/crates/termcolor/1.1.3/download",
+          "sha256": "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
+        }
+      },
+      "targets": [
+        {
+          "Library": {
+            "crate_name": "termcolor",
+            "crate_root": "src/lib.rs",
+            "srcs": {
+              "include": [
+                "**/*.rs"
+              ],
+              "exclude": []
+            }
+          }
+        }
+      ],
+      "library_target_name": "termcolor",
+      "common_attrs": {
+        "compile_data_glob": [
+          "**"
+        ],
+        "deps": {
+          "common": [],
+          "selects": {
+            "cfg(windows)": [
+              {
+                "id": "winapi-util 0.1.5",
+                "target": "winapi_util"
+              }
+            ]
+          }
+        },
+        "edition": "2018",
+        "version": "1.1.3"
+      },
+      "license": "Unlicense OR MIT"
+    },
+    "textwrap 0.15.0": {
       "name": "textwrap",
-      "version": "0.11.0",
+      "version": "0.15.0",
       "repository": {
         "Http": {
-          "url": "https://crates.io/api/v1/crates/textwrap/0.11.0/download",
-          "sha256": "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+          "url": "https://crates.io/api/v1/crates/textwrap/0.15.0/download",
+          "sha256": "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
         }
       },
       "targets": [
@@ -4640,17 +4951,8 @@
         "compile_data_glob": [
           "**"
         ],
-        "deps": {
-          "common": [
-            {
-              "id": "unicode-width 0.1.9",
-              "target": "unicode_width"
-            }
-          ],
-          "selects": {}
-        },
-        "edition": "2015",
-        "version": "0.11.0"
+        "edition": "2018",
+        "version": "0.15.0"
       },
       "license": "MIT"
     },
@@ -4893,75 +5195,6 @@
       },
       "license": "(MIT OR Apache-2.0) AND Unicode-DFS-2016"
     },
-    "unicode-width 0.1.9": {
-      "name": "unicode-width",
-      "version": "0.1.9",
-      "repository": {
-        "Http": {
-          "url": "https://crates.io/api/v1/crates/unicode-width/0.1.9/download",
-          "sha256": "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
-        }
-      },
-      "targets": [
-        {
-          "Library": {
-            "crate_name": "unicode_width",
-            "crate_root": "src/lib.rs",
-            "srcs": {
-              "include": [
-                "**/*.rs"
-              ],
-              "exclude": []
-            }
-          }
-        }
-      ],
-      "library_target_name": "unicode_width",
-      "common_attrs": {
-        "compile_data_glob": [
-          "**"
-        ],
-        "crate_features": [
-          "default"
-        ],
-        "edition": "2015",
-        "version": "0.1.9"
-      },
-      "license": "MIT/Apache-2.0"
-    },
-    "vec_map 0.8.2": {
-      "name": "vec_map",
-      "version": "0.8.2",
-      "repository": {
-        "Http": {
-          "url": "https://crates.io/api/v1/crates/vec_map/0.8.2/download",
-          "sha256": "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
-        }
-      },
-      "targets": [
-        {
-          "Library": {
-            "crate_name": "vec_map",
-            "crate_root": "src/lib.rs",
-            "srcs": {
-              "include": [
-                "**/*.rs"
-              ],
-              "exclude": []
-            }
-          }
-        }
-      ],
-      "library_target_name": "vec_map",
-      "common_attrs": {
-        "compile_data_glob": [
-          "**"
-        ],
-        "edition": "2015",
-        "version": "0.8.2"
-      },
-      "license": "MIT/Apache-2.0"
-    },
     "version_check 0.9.4": {
       "name": "version_check",
       "version": "0.9.4",
@@ -5088,6 +5321,7 @@
           "sysinfoapi",
           "timezoneapi",
           "winbase",
+          "wincon",
           "winerror",
           "winnt"
         ],
@@ -5182,6 +5416,50 @@
       },
       "license": "MIT/Apache-2.0"
     },
+    "winapi-util 0.1.5": {
+      "name": "winapi-util",
+      "version": "0.1.5",
+      "repository": {
+        "Http": {
+          "url": "https://crates.io/api/v1/crates/winapi-util/0.1.5/download",
+          "sha256": "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+        }
+      },
+      "targets": [
+        {
+          "Library": {
+            "crate_name": "winapi_util",
+            "crate_root": "src/lib.rs",
+            "srcs": {
+              "include": [
+                "**/*.rs"
+              ],
+              "exclude": []
+            }
+          }
+        }
+      ],
+      "library_target_name": "winapi_util",
+      "common_attrs": {
+        "compile_data_glob": [
+          "**"
+        ],
+        "deps": {
+          "common": [],
+          "selects": {
+            "cfg(windows)": [
+              {
+                "id": "winapi 0.3.9",
+                "target": "winapi"
+              }
+            ]
+          }
+        },
+        "edition": "2018",
+        "version": "0.1.5"
+      },
+      "license": "Unlicense/MIT"
+    },
     "winapi-x86_64-pc-windows-gnu 0.4.0": {
       "name": "winapi-x86_64-pc-windows-gnu",
       "version": "0.4.0",
@@ -5313,6 +5591,7 @@
   },
   "binary_crates": [
     "cc 1.0.73",
+    "clap 3.2.16",
     "protobuf-codegen 2.27.1"
   ],
   "workspace_members": {
@@ -5382,10 +5661,6 @@
     "cfg(target_os = \"wasi\")": [
       "wasm32-wasi"
     ],
-    "cfg(target_os = \"windows\")": [
-      "i686-pc-windows-msvc",
-      "x86_64-pc-windows-msvc"
-    ],
     "cfg(unix)": [
       "aarch64-apple-darwin",
       "aarch64-apple-ios",
diff --git a/kythe/rust/extractor/src/bin/cli.rs b/kythe/rust/extractor/src/bin/cli.rs
deleted file mode 100644
index 8c936dee5..000000000
--- a/kythe/rust/extractor/src/bin/cli.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2020 The Kythe Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-use clap::{App, Arg};
-use std::path::PathBuf;
-
-/// Contains the configuration options for the extractor
-pub struct ExtractorConfig {
-    pub extra_action_path: PathBuf,
-    pub vnames_config_path: PathBuf,
-    pub output_path: PathBuf,
-}
-
-/// Parse the command line arguments into an `ExtractorConfig`
-pub fn parse_arguments() -> ExtractorConfig {
-    let matches = App::new("Kythe Rust Extractor")
-        .arg(
-            Arg::with_name("extra_action")
-                .long("extra_action")
-                .required(true)
-                .takes_value(true)
-                .help("Path of the extra action file"),
-        )
-        .arg(
-            Arg::with_name("output")
-                .long("output")
-                .required(true)
-                .takes_value(true)
-                .help("Desired output path for the kzip"),
-        )
-        .arg(
-            Arg::with_name("vnames_config")
-                .long("vnames_config")
-                .required(true)
-                .takes_value(true)
-                .help("Location of vnames configuration file"),
-        )
-        .get_matches();
-
-    let extra_action_path = PathBuf::from(matches.value_of("extra_action").unwrap());
-    let vnames_config_path = PathBuf::from(matches.value_of("vnames_config").unwrap());
-    let output_path = PathBuf::from(matches.value_of("output").unwrap());
-    ExtractorConfig { extra_action_path, vnames_config_path, output_path }
-}
diff --git a/kythe/rust/extractor/src/bin/extractor.rs b/kythe/rust/extractor/src/bin/extractor.rs
index 32f3e41d1..b2bf4101e 100644
--- a/kythe/rust/extractor/src/bin/extractor.rs
+++ b/kythe/rust/extractor/src/bin/extractor.rs
@@ -11,14 +11,12 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
-#[macro_use]
-extern crate anyhow;
 
-mod cli;
 mod save_analysis;
 
 use analysis_rust_proto::*;
-use anyhow::{Context, Result};
+use anyhow::{anyhow, Context, Result};
+use clap::Parser;
 use extra_actions_base_rust_proto::*;
 use glob::glob;
 use kythe_rust_extractor::vname_util::VNameRule;
@@ -31,14 +29,32 @@ use std::path::{Path, PathBuf};
 use tempdir::TempDir;
 use zip::{write::FileOptions, ZipWriter};
 
+#[derive(Parser)]
+#[clap(author = "The Kythe Authors")]
+#[clap(about = "Kythe Rust Extractor", long_about = None)]
+#[clap(rename_all = "snake_case")]
+struct Args {
+    /// Path to the extra action file
+    #[clap(long, value_parser)]
+    extra_action: PathBuf,
+
+    /// Desired output path for the kzip
+    #[clap(long, value_parser, value_name = "dir")]
+    output: PathBuf,
+
+    /// Location of the vnames configuration file
+    #[clap(long, value_parser)]
+    vnames_config: PathBuf,
+}
+
 fn main() -> Result<()> {
-    let config = cli::parse_arguments();
+    let config = Args::parse();
 
     // Parse the VName configuration rules
-    let mut vname_rules = VNameRule::parse_vname_rules(config.vnames_config_path.as_path())?;
+    let mut vname_rules = VNameRule::parse_vname_rules(&config.vnames_config)?;
 
     // Retrieve the SpawnInfo from the extra action file
-    let spawn_info = get_spawn_info(&config.extra_action_path)?;
+    let spawn_info = get_spawn_info(&config.extra_action)?;
 
     // Grab the environment variables from spawn info and set them in our current
     // environment
@@ -93,8 +109,8 @@ fn main() -> Result<()> {
     )?;
 
     // Create the output kzip
-    let kzip_file = File::create(&config.output_path)
-        .with_context(|| format!("Failed to create kzip file at path {:?}", config.output_path))?;
+    let kzip_file = File::create(&config.output)
+        .with_context(|| format!("Failed to create kzip file at path {:?}", &config.output))?;
     let mut kzip = ZipWriter::new(kzip_file);
     kzip.add_directory("root/", FileOptions::default())?;
 
diff --git a/kythe/rust/extractor/src/bin/save_analysis.rs b/kythe/rust/extractor/src/bin/save_analysis.rs
index 94dd24835..ec6ce478d 100644
--- a/kythe/rust/extractor/src/bin/save_analysis.rs
+++ b/kythe/rust/extractor/src/bin/save_analysis.rs
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use anyhow::{Context, Result};
+use anyhow::{anyhow, Context, Result};
 use std::fs::File;
 use std::io::{self, BufRead};
 use std::path::{Path, PathBuf};
diff --git a/kythe/rust/extractor/src/vname_util.rs b/kythe/rust/extractor/src/vname_util.rs
index f8b42227b..f64d0dce6 100644
--- a/kythe/rust/extractor/src/vname_util.rs
+++ b/kythe/rust/extractor/src/vname_util.rs
@@ -18,7 +18,7 @@ use regex::Regex;
 use serde::Deserialize;
 use std::fs::File;
 use std::io::BufReader;
-use std::path::Path;
+use std::path::PathBuf;
 
 /// The String forms of the vname field patterns
 #[derive(Deserialize)]
@@ -66,7 +66,7 @@ pub struct VNameRule {
 
 impl VNameRule {
     /// Processed vname rules defined in files
-    pub fn parse_vname_rules(config_path: &Path) -> Result<Vec<Self>> {
+    pub fn parse_vname_rules(config_path: &PathBuf) -> Result<Vec<Self>> {
         let mut processed_rules = Vec::new();
         let file = File::open(&config_path)
             .with_context(|| format!("Failed to open file: {}", config_path.to_string_lossy()))?;
diff --git a/kythe/rust/indexer/src/bin/bazel/main.rs b/kythe/rust/indexer/src/bin/bazel/main.rs
index a21b867cc..bea55a9ef 100644
--- a/kythe/rust/indexer/src/bin/bazel/main.rs
+++ b/kythe/rust/indexer/src/bin/bazel/main.rs
@@ -15,38 +15,35 @@ extern crate kythe_rust_indexer;
 use kythe_rust_indexer::{indexer::KytheIndexer, providers::*, writer::CodedOutputStreamWriter};
 
 use anyhow::{Context, Result};
-use clap::{App, Arg};
+use clap::Parser;
 use std::fs::File;
+use std::path::PathBuf;
+
+#[derive(Parser)]
+#[clap(author = "The Kythe Authors")]
+#[clap(about = "Kythe Rust Bazel Indexer", long_about = None)]
+#[clap(rename_all = "snake_case")]
+struct Args {
+    /// The path to the kzip to be indexed
+    #[clap(value_parser)]
+    kzip_path: PathBuf,
+
+    /// Disables emitting cross references to the standard library
+    #[clap(long, action)]
+    no_emit_std_lib: bool,
+
+    /// Emits built-in types in the "std" corpus
+    #[clap(long, action)]
+    tbuiltin_std_corpus: bool,
+}
 
 fn main() -> Result<()> {
-    // Returns 0 if ok or 1 if error
-    let matches = App::new("Kythe Rust Bazel Indexer")
-        .arg(
-            Arg::with_name("kzip_path")
-                .required(true)
-                .index(1)
-                .help("The path to the kzip to be indexed"),
-        )
-        .arg(
-            Arg::with_name("no_emit_std_lib")
-                .long("no_emit_std_lib")
-                .required(false)
-                .help("Disables emitting cross references to the standard library"),
-        )
-        .arg(
-            Arg::with_name("tbuiltin_std_corpus")
-                .long("tbuiltin_std_corpus")
-                .required(false)
-                .help("Emits built-in types in the \"std\" corpus"),
-        )
-        .get_matches();
-    let emit_std_lib = !matches.is_present("no_emit_std_lib");
-    let tbuiltin_std_corpus = matches.is_present("tbuiltin_std_corpus");
+    let args = Args::parse();
+    let emit_std_lib = !args.no_emit_std_lib;
 
     // Get kzip path from argument and use it to create a KzipFileProvider
     // Unwrap is safe because the parameter is required
-    let kzip_path = matches.value_of("kzip_path").unwrap();
-    let kzip_file = File::open(kzip_path).context("Provided path does not exist")?;
+    let kzip_file = File::open(&args.kzip_path).context("Provided path does not exist")?;
     let mut kzip_provider =
         KzipFileProvider::new(kzip_file).context("Failed to open kzip archive")?;
     let compilation_units = kzip_provider
@@ -59,7 +56,7 @@ fn main() -> Result<()> {
     let mut indexer = KytheIndexer::new(&mut writer);
 
     for unit in compilation_units {
-        indexer.index_cu(&unit, &mut kzip_provider, emit_std_lib, tbuiltin_std_corpus)?;
+        indexer.index_cu(&unit, &mut kzip_provider, emit_std_lib, args.tbuiltin_std_corpus)?;
     }
     Ok(())
 }
diff --git a/kythe/rust/indexer/src/bin/proxy/main.rs b/kythe/rust/indexer/src/bin/proxy/main.rs
index 57a854620..4ad7a2a57 100644
--- a/kythe/rust/indexer/src/bin/proxy/main.rs
+++ b/kythe/rust/indexer/src/bin/proxy/main.rs
@@ -16,38 +16,38 @@ use kythe_rust_indexer::{indexer::KytheIndexer, providers::*, proxyrequests, wri
 
 use analysis_rust_proto::*;
 use anyhow::{anyhow, Context, Result};
-use clap::{App, Arg};
+use clap::Parser;
 use serde_json::Value;
 use std::io::{self, Write};
 
+#[derive(Parser)]
+#[clap(author = "The Kythe Authors")]
+#[clap(about = "Kythe Rust Proxy Indexer", long_about = None)]
+#[clap(rename_all = "snake_case")]
+struct Args {
+    /// Disables emitting cross references to the standard library
+    #[clap(long, action)]
+    no_emit_std_lib: bool,
+
+    /// Emits built-in types in the "std" corpus
+    #[clap(long, action)]
+    tbuiltin_std_corpus: bool,
+}
+
 fn main() -> Result<()> {
     let mut file_provider = ProxyFileProvider::new();
     let mut kythe_writer = ProxyWriter::new();
     let mut indexer = KytheIndexer::new(&mut kythe_writer);
 
-    let matches = App::new("Kythe Rust Proxy Indexer")
-        .arg(
-            Arg::with_name("no_emit_std_lib")
-                .long("no_emit_std_lib")
-                .required(false)
-                .help("Disables emitting cross references to the standard library"),
-        )
-        .arg(
-            Arg::with_name("tbuiltin_std_corpus")
-                .long("tbuiltin_std_corpus")
-                .required(false)
-                .help("Emits built-in types in the \"std\" corpus"),
-        )
-        .get_matches();
-    let emit_std_lib = !matches.is_present("no_emit_std_lib");
-    let tbuiltin_std_corpus = matches.is_present("tbuiltin_std_corpus");
+    let args = Args::parse();
+    let emit_std_lib = !args.no_emit_std_lib;
 
     // Request and process
     loop {
         let unit = request_compilation_unit()?;
         // Index the CompilationUnit and let the proxy know we are done
         let index_res =
-            indexer.index_cu(&unit, &mut file_provider, emit_std_lib, tbuiltin_std_corpus);
+            indexer.index_cu(&unit, &mut file_provider, emit_std_lib, args.tbuiltin_std_corpus);
         if index_res.is_ok() {
             send_done(true, String::new())?;
         } else {
diff --git a/tools/rust/extra_action/src/main.rs b/tools/rust/extra_action/src/main.rs
index 496c4ae13..c0754e89f 100644
--- a/tools/rust/extra_action/src/main.rs
+++ b/tools/rust/extra_action/src/main.rs
@@ -13,80 +13,60 @@
 // limitations under the License.
 
 use anyhow::{Context, Result};
-use clap::{App, Arg};
+use clap::Parser;
 use extra_actions_base_rust_proto::*;
 use protobuf::Message;
 use std::fs::File;
 use std::io::Write;
-use std::path::Path;
+use std::path::PathBuf;
+
+#[derive(Parser)]
+#[clap(author = "The Kythe Authors")]
+#[clap(about = "Rust Extra Action Generator", long_about = None)]
+#[clap(rename_all = "snake_case")]
+struct Args {
+    /// Comma delimited source file paths
+    #[clap(long, value_parser, value_name = "file,...")]
+    src_files: String,
+
+    /// Desired output path for the ExtraAction
+    #[clap(long, value_parser)]
+    output: PathBuf,
+
+    /// The name for the crate
+    #[clap(long, value_parser)]
+    crate_name: String,
+
+    /// The action owner
+    #[clap(long, value_parser)]
+    owner: String,
+
+    /// The path to the Rust sysroot
+    #[clap(long, value_parser)]
+    sysroot: String,
+
+    /// The path to the linker
+    #[clap(long, value_parser)]
+    linker: String,
+
+    /// The path that $OUT_DIR will be set to
+    #[clap(long, value_parser)]
+    out_dir_env: Option<String>,
+
+    /// Add \"--test\" to the compiler arguments
+    #[clap(long, action)]
+    test_lib: bool,
+}
 
 fn main() -> Result<()> {
-    let matches = App::new("Rust Extra Action Generator")
-        .arg(
-            Arg::with_name("src_files")
-                .long("src_files")
-                .required(true)
-                .takes_value(true)
-                .help("Comma delimited source file paths"),
-        )
-        .arg(
-            Arg::with_name("output")
-                .long("output")
-                .required(true)
-                .takes_value(true)
-                .help("Desired output path for the ExtraAction"),
-        )
-        .arg(
-            Arg::with_name("crate_name")
-                .long("crate_name")
-                .required(true)
-                .takes_value(true)
-                .help("The name for the crate"),
-        )
-        .arg(
-            Arg::with_name("owner")
-                .long("owner")
-                .required(true)
-                .takes_value(true)
-                .help("The action owner"),
-        )
-        .arg(
-            Arg::with_name("sysroot")
-                .long("sysroot")
-                .required(true)
-                .takes_value(true)
-                .help("The Rust sysroot"),
-        )
-        .arg(
-            Arg::with_name("linker")
-                .long("linker")
-                .required(true)
-                .takes_value(true)
-                .help("The linker path"),
-        )
-        .arg(
-            Arg::with_name("out_dir_env")
-                .long("out_dir_env")
-                .required(false)
-                .takes_value(true)
-                .help("The path that $OUT_DIR will be set to"),
-        )
-        .arg(
-            Arg::with_name("test_lib")
-                .long("test_lib")
-                .required(false)
-                .help("Add \"--test\" to the compiler arguments"),
-        )
-        .get_matches();
+    let args = Args::parse();
 
     let mut extra_action = ExtraActionInfo::new();
-    extra_action.set_owner(matches.value_of("owner").unwrap().to_string());
+    extra_action.set_owner(args.owner);
 
     // Populate SpawnInfo
     let mut spawn_info = SpawnInfo::new();
-    let source_files: Vec<String> =
-        matches.value_of("src_files").unwrap().split(',').map(String::from).collect();
-    let crate_name = matches.value_of("crate_name").unwrap();
+    let source_files: Vec<String> = args.src_files.split(',').map(String::from).collect();
     let main_source_file = if source_files.len() == 1 {
         &source_files[0]
     } else {
@@ -100,24 +80,24 @@ fn main() -> Result<()> {
         "rustc".to_string(),
         // Only the main source file gets passed to the compiler
         main_source_file.to_string(),
-        format!("-L{}", matches.value_of("sysroot").unwrap()),
-        format!("--codegen=linker={}", matches.value_of("linker").unwrap()),
-        format!("--crate-name={}", crate_name),
+        format!("-L{}", args.sysroot),
+        format!("--codegen=linker={}", args.linker),
+        format!("--crate-name={}", &args.crate_name),
         // This path gets replaced by the extractor so it doesn't matter
         "--out-dir=/tmp".to_string(),
     ];
-    if matches.is_present("test_lib") {
+    if args.test_lib {
         arguments.push("--test".to_string());
     }
     spawn_info.set_argument(protobuf::RepeatedField::from_vec(arguments));
     spawn_info.set_input_file(protobuf::RepeatedField::from_vec(source_files));
-    spawn_info.set_output_file(protobuf::RepeatedField::from_vec(vec![crate_name.to_string()]));
+    spawn_info.set_output_file(protobuf::RepeatedField::from_vec(vec![args.crate_name.clone()]));
 
     // If out_dir_env was set, set $OUT_DIR in the spawn info
-    if let Some(out_dir) = matches.value_of("out_dir_env") {
+    if let Some(out_dir) = args.out_dir_env {
         let mut env_var = EnvironmentVariable::new();
         env_var.set_name("OUT_DIR".to_string());
-        env_var.set_value(out_dir.to_string());
+        env_var.set_value(out_dir);
         spawn_info.set_variable(protobuf::RepeatedField::from_vec(vec![env_var]));
     }
 
@@ -135,8 +115,7 @@ fn main() -> Result<()> {
     let extra_action_info_bytes: Vec<u8> = extra_action
         .write_to_bytes()
         .with_context(|| "Failed to convert ExtraActionInfo to bytes".to_string())?;
-    let extra_action_path = Path::new(matches.value_of("output").unwrap());
-    let mut extra_action_file = File::create(&extra_action_path)
+    let mut extra_action_file = File::create(args.output)
         .with_context(|| "Failed to create ExtraActionInfo file".to_string())?;
     extra_action_file
         .write_all(&extra_action_info_bytes)


Test patch:
diff --git a/kythe/rust/extractor/tests/integration_test.rs b/kythe/rust/extractor/tests/integration_test.rs
index d3e6a2664..ed58ee9d2 100644
--- a/kythe/rust/extractor/tests/integration_test.rs
+++ b/kythe/rust/extractor/tests/integration_test.rs
@@ -104,21 +104,21 @@ fn main() -> Result<()> {
 fn missing_arguments_fail() {
     let extractor_path = std::env::var("EXTRACTOR_PATH").expect("Couldn't find extractor path");
     let mut output = Command::new(&extractor_path).arg("--output=/tmp/wherever").output().unwrap();
-    assert_eq!(output.status.code().unwrap(), 1);
+    assert_eq!(output.status.code().unwrap(), 2);
     assert!(
         String::from_utf8_lossy(&output.stderr)
             .starts_with("error: The following required arguments were not provided:")
     );
 
     output = Command::new(&extractor_path).arg("--extra_action=/tmp/wherever").output().unwrap();
-    assert_eq!(output.status.code().unwrap(), 1);
+    assert_eq!(output.status.code().unwrap(), 2);
     assert!(
         String::from_utf8_lossy(&output.stderr)
             .starts_with("error: The following required arguments were not provided:")
     );
 
     output = Command::new(&extractor_path).output().unwrap();
-    assert_eq!(output.status.code().unwrap(), 1);
+    assert_eq!(output.status.code().unwrap(), 2);
     assert!(
         String::from_utf8_lossy(&output.stderr)
             .starts_with("error: The following required arguments were not provided:")