diff --git a/ql/Cargo.lock b/ql/Cargo.lock
index 3ae0dbd5819..3b2fdb7c89a 100644
Binary files a/ql/Cargo.lock and b/ql/Cargo.lock differ
diff --git a/ql/extractor/Cargo.toml b/ql/extractor/Cargo.toml
index b316e6bc05c..cb2070417ac 100644
--- a/ql/extractor/Cargo.toml
+++ b/ql/extractor/Cargo.toml
@@ -1,5 +1,5 @@
[package]
-name = "ql-extractor"
+name = "codeql-ql-extractor"
version = "0.1.0"
authors = ["GitHub"]
edition = "2018"
diff --git a/ql/extractor/src/bin/autobuilder.rs b/ql/extractor/src/autobuilder.rs
similarity index 88%
rename from ql/extractor/src/bin/autobuilder.rs
rename to ql/extractor/src/autobuilder.rs
index 0d9605c4c1d..a17a4916239 100644
--- a/ql/extractor/src/bin/autobuilder.rs
+++ b/ql/extractor/src/autobuilder.rs
@@ -1,8 +1,13 @@
+use clap::Args;
use std::env;
use std::path::PathBuf;
use std::process::Command;
-fn main() -> std::io::Result<()> {
+#[derive(Args)]
+// The autobuilder takes no command-line options, but this may change in the future.
+pub struct Options {}
+
+pub fn run(_: Options) -> std::io::Result<()> {
let dist = env::var("CODEQL_DIST").expect("CODEQL_DIST not set");
let db = env::var("CODEQL_EXTRACTOR_QL_WIP_DATABASE")
.expect("CODEQL_EXTRACTOR_QL_WIP_DATABASE not set");
diff --git a/ql/extractor/src/bin/extractor.rs b/ql/extractor/src/extractor.rs
similarity index 88%
rename from ql/extractor/src/bin/extractor.rs
rename to ql/extractor/src/extractor.rs
index 592c98b1b15..ca616b482c3 100644
--- a/ql/extractor/src/bin/extractor.rs
+++ b/ql/extractor/src/extractor.rs
@@ -1,3 +1,4 @@
+use clap::Args;
use rayon::prelude::*;
use std::fs;
use std::io::BufRead;
@@ -5,7 +6,22 @@ use std::path::{Path, PathBuf};
use codeql_extractor::{diagnostics, extractor, node_types, trap};
-fn main() -> std::io::Result<()> {
+#[derive(Args)]
+pub struct Options {
+ /// Sets a custom source achive folder
+ #[arg(long)]
+ source_archive_dir: PathBuf,
+
+ /// Sets a custom trap folder
+ #[arg(long)]
+ output_dir: PathBuf,
+
+ /// A text file containing the paths of the files to extract
+ #[arg(long)]
+ file_list: PathBuf,
+}
+
+pub fn run(options: Options) -> std::io::Result<()> {
tracing_subscriber::fmt()
.with_target(false)
.without_time()
@@ -58,30 +74,9 @@ fn main() -> std::io::Result<()> {
.build_global()
.unwrap();
- let matches = clap::Command::new("QL extractor")
- .version("1.0")
- .author("GitHub")
- .about("CodeQL QL extractor")
- .args(&[
- clap::arg!(--"source-archive-dir"
"Sets a custom source archive folder"),
- clap::arg!(--"output-dir" "Sets a custom trap folder"),
- clap::arg!(--"file-list" "A text file containing the paths of the files to extract"),
- ])
- .get_matches();
- let src_archive_dir = matches
- .get_one::("source-archive-dir")
- .expect("missing --source-archive-dir");
- let src_archive_dir = PathBuf::from(src_archive_dir);
-
- let trap_dir = matches
- .get_one::("output-dir")
- .expect("missing --output-dir");
- let trap_dir = PathBuf::from(trap_dir);
-
- let file_list = matches
- .get_one::("file-list")
- .expect("missing --file-list");
- let file_list = fs::File::open(file_list)?;
+ let trap_dir = options.output_dir;
+ let file_list = fs::File::open(options.file_list)?;
+ let source_archive_dir = options.source_archive_dir;
let language = tree_sitter_ql::language();
let dbscheme = tree_sitter_ql_dbscheme::language();
@@ -114,7 +109,7 @@ fn main() -> std::io::Result<()> {
return Ok(());
}
let path = PathBuf::from(line).canonicalize()?;
- let src_archive_file = path_for(&src_archive_dir, &path, "");
+ let src_archive_file = path_for(&source_archive_dir, &path, "");
let source = std::fs::read(&path)?;
let code_ranges = vec![];
let mut trap_writer = trap::Writer::new();
diff --git a/ql/extractor/src/bin/generator.rs b/ql/extractor/src/generator.rs
similarity index 54%
rename from ql/extractor/src/bin/generator.rs
rename to ql/extractor/src/generator.rs
index 45a13f6a18d..cdfdd17df4d 100644
--- a/ql/extractor/src/bin/generator.rs
+++ b/ql/extractor/src/generator.rs
@@ -1,8 +1,20 @@
+use clap::Args;
use std::path::PathBuf;
use codeql_extractor::generator::{generate, language::Language};
-fn main() -> std::io::Result<()> {
+#[derive(Args)]
+pub struct Options {
+ /// Path of the generated dbscheme file
+ #[arg(long)]
+ dbscheme: PathBuf,
+
+ /// Path of the generated QLL file
+ #[arg(long)]
+ library: PathBuf,
+}
+
+pub fn run(options: Options) -> std::io::Result<()> {
tracing_subscriber::fmt()
.with_target(false)
.without_time()
@@ -10,25 +22,6 @@ fn main() -> std::io::Result<()> {
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.init();
- let matches = clap::Command::new("QL dbscheme generator")
- .version("1.0")
- .author("GitHub")
- .about("CodeQL QL dbscheme generator")
- .args(&[
- clap::arg!(--dbscheme "Path of the generated dbscheme file"),
- clap::arg!(--library "Path of the generated QLL file"),
- ])
- .get_matches();
- let dbscheme_path = matches
- .get_one::("dbscheme")
- .expect("missing --dbscheme");
- let dbscheme_path = PathBuf::from(dbscheme_path);
-
- let ql_library_path = matches
- .get_one::("library")
- .expect("missing --library");
- let ql_library_path = PathBuf::from(ql_library_path);
-
let languages = vec![
Language {
name: "QL".to_owned(),
@@ -52,5 +45,5 @@ fn main() -> std::io::Result<()> {
},
];
- generate(languages, dbscheme_path, ql_library_path)
+ generate(languages, options.dbscheme, options.library)
}
diff --git a/ql/extractor/src/main.rs b/ql/extractor/src/main.rs
new file mode 100644
index 00000000000..0287a20c184
--- /dev/null
+++ b/ql/extractor/src/main.rs
@@ -0,0 +1,23 @@
+use clap::Parser;
+
+mod autobuilder;
+mod extractor;
+mod generator;
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+enum Cli {
+ Extract(extractor::Options),
+ Generate(generator::Options),
+ Autobuild(autobuilder::Options),
+}
+
+fn main() -> std::io::Result<()> {
+ let cli = Cli::parse();
+
+ match cli {
+ Cli::Extract(options) => extractor::run(options),
+ Cli::Generate(options) => generator::run(options),
+ Cli::Autobuild(options) => autobuilder::run(options),
+ }
+}