Skip to content

Commit 99494dd

Browse files
authored
Merge pull request github#18012 from github/revert-18011-revert-17937-redsun82/rust-cargo-options
Revert "Revert "Rust: allow to specify more cargo configuration options""
2 parents e2f17c6 + 8377ee5 commit 99494dd

35 files changed

+385
-36
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

MODULE.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ use_repo(py_deps, "vendor__anyhow-1.0.44", "vendor__cc-1.0.70", "vendor__clap-2.
6868
# deps for ruby+rust
6969
# keep in sync by running `misc/bazel/3rdparty/update_cargo_deps.sh`
7070
tree_sitter_extractors_deps = use_extension("//misc/bazel/3rdparty:tree_sitter_extractors_extension.bzl", "r")
71-
use_repo(tree_sitter_extractors_deps, "vendor__anyhow-1.0.93", "vendor__argfile-0.2.1", "vendor__chrono-0.4.38", "vendor__clap-4.5.20", "vendor__encoding-0.2.33", "vendor__figment-0.10.19", "vendor__flate2-1.0.34", "vendor__glob-0.3.1", "vendor__globset-0.4.15", "vendor__itertools-0.10.5", "vendor__itertools-0.13.0", "vendor__lazy_static-1.5.0", "vendor__log-0.4.22", "vendor__num-traits-0.2.19", "vendor__num_cpus-1.16.0", "vendor__proc-macro2-1.0.89", "vendor__quote-1.0.37", "vendor__ra_ap_base_db-0.0.232", "vendor__ra_ap_hir-0.0.232", "vendor__ra_ap_hir_def-0.0.232", "vendor__ra_ap_hir_expand-0.0.232", "vendor__ra_ap_ide_db-0.0.232", "vendor__ra_ap_load-cargo-0.0.232", "vendor__ra_ap_parser-0.0.232", "vendor__ra_ap_paths-0.0.232", "vendor__ra_ap_project_model-0.0.232", "vendor__ra_ap_span-0.0.232", "vendor__ra_ap_syntax-0.0.232", "vendor__ra_ap_vfs-0.0.232", "vendor__rand-0.8.5", "vendor__rayon-1.10.0", "vendor__regex-1.11.1", "vendor__serde-1.0.214", "vendor__serde_json-1.0.132", "vendor__serde_with-3.11.0", "vendor__stderrlog-0.6.0", "vendor__syn-2.0.87", "vendor__tracing-0.1.40", "vendor__tracing-subscriber-0.3.18", "vendor__tree-sitter-0.24.4", "vendor__tree-sitter-embedded-template-0.23.2", "vendor__tree-sitter-json-0.24.8", "vendor__tree-sitter-ql-0.23.1", "vendor__tree-sitter-ruby-0.23.1", "vendor__triomphe-0.1.14", "vendor__ungrammar-1.16.1")
71+
use_repo(tree_sitter_extractors_deps, "vendor__anyhow-1.0.93", "vendor__argfile-0.2.1", "vendor__chrono-0.4.38", "vendor__clap-4.5.20", "vendor__encoding-0.2.33", "vendor__figment-0.10.19", "vendor__flate2-1.0.34", "vendor__glob-0.3.1", "vendor__globset-0.4.15", "vendor__itertools-0.10.5", "vendor__itertools-0.13.0", "vendor__lazy_static-1.5.0", "vendor__log-0.4.22", "vendor__num-traits-0.2.19", "vendor__num_cpus-1.16.0", "vendor__proc-macro2-1.0.89", "vendor__quote-1.0.37", "vendor__ra_ap_base_db-0.0.232", "vendor__ra_ap_cfg-0.0.232", "vendor__ra_ap_hir-0.0.232", "vendor__ra_ap_hir_def-0.0.232", "vendor__ra_ap_hir_expand-0.0.232", "vendor__ra_ap_ide_db-0.0.232", "vendor__ra_ap_intern-0.0.232", "vendor__ra_ap_load-cargo-0.0.232", "vendor__ra_ap_parser-0.0.232", "vendor__ra_ap_paths-0.0.232", "vendor__ra_ap_project_model-0.0.232", "vendor__ra_ap_span-0.0.232", "vendor__ra_ap_syntax-0.0.232", "vendor__ra_ap_vfs-0.0.232", "vendor__rand-0.8.5", "vendor__rayon-1.10.0", "vendor__regex-1.11.1", "vendor__serde-1.0.214", "vendor__serde_json-1.0.132", "vendor__serde_with-3.11.0", "vendor__stderrlog-0.6.0", "vendor__syn-2.0.87", "vendor__tracing-0.1.40", "vendor__tracing-subscriber-0.3.18", "vendor__tree-sitter-0.24.4", "vendor__tree-sitter-embedded-template-0.23.2", "vendor__tree-sitter-json-0.24.8", "vendor__tree-sitter-ql-0.23.1", "vendor__tree-sitter-ruby-0.23.1", "vendor__triomphe-0.1.14", "vendor__ungrammar-1.16.1")
7272

7373
dotnet = use_extension("@rules_dotnet//dotnet:extensions.bzl", "dotnet")
7474
dotnet.toolchain(dotnet_version = "8.0.101")

misc/bazel/3rdparty/tree_sitter_extractors_deps/BUILD.bazel

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

misc/bazel/3rdparty/tree_sitter_extractors_deps/defs.bzl

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/ast-generator/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "ast-generator"
33
version = "0.1.0"
44
edition = "2021"
55

6-
# When updating these dependencies, run `misc/bazel/3rdparty/update_cargo_deps.sh`
6+
# When updating these dependencies, run `rust/update_cargo_deps.sh`
77
[dependencies]
88
ungrammar = "1.16.1"
99
proc-macro2 = "1.0.33"

rust/codeql-extractor.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,22 @@ options:
3535
reduce execution time of consecutive extractor runs. By default, a new scratch
3636
directory is used for each run.
3737
type: string
38+
cargo_target:
39+
title: Target architecture
40+
description: >
41+
Target architecture to use for analysis, analogous to `cargo --target`. By
42+
default the host architecture is used.
43+
type: string
44+
cargo_features:
45+
title: Cargo features to turn on
46+
description: >
47+
Comma-separated list of features to turn on. If any value is `*` all features
48+
are turned on. By default only default cargo features are enabled. Can be
49+
repeated.
50+
type: array
51+
cargo_cfg_overrides:
52+
title: Cargo cfg overrides
53+
description: >
54+
Comma-separated list of cfg settings to enable, or disable if prefixed with `-`.
55+
Can be repeated.
56+
type: array

rust/extractor/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "codeql-rust"
33
version = "0.1.0"
44
edition = "2021"
55

6-
# When updating these dependencies, run `misc/bazel/3rdparty/update_cargo_deps.sh`
6+
# When updating these dependencies, run `rust/update_cargo_deps.sh`
77
[dependencies]
88
anyhow = "1.0.86"
99
clap = { version = "4.5.16", features = ["derive"] }
@@ -22,6 +22,8 @@ ra_ap_syntax = "0.0.232"
2222
ra_ap_vfs = "0.0.232"
2323
ra_ap_parser = "0.0.232"
2424
ra_ap_span = "0.0.232"
25+
ra_ap_cfg = "0.0.232"
26+
ra_ap_intern = "0.0.232"
2527
serde = "1.0.209"
2628
serde_with = "3.9.0"
2729
stderrlog = "0.6.0"

rust/extractor/macros/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ edition = "2021"
66
[lib]
77
proc-macro = true
88

9-
# When updating these dependencies, run `misc/bazel/3rdparty/update_cargo_deps.sh`
9+
# When updating these dependencies, run `rust/update_cargo_deps.sh`
1010
[dependencies]
1111
quote = "1.0.37"
1212
syn = { version = "2.0.77", features = ["full"] }

rust/extractor/macros/src/lib.rs

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,74 @@
11
use proc_macro::TokenStream;
22
use quote::{format_ident, quote};
3+
use syn::{Ident, Type};
4+
5+
fn get_type_tip(t: &Type) -> Option<&Ident> {
6+
let syn::Type::Path(path) = t else {
7+
return None;
8+
};
9+
let segment = path.path.segments.last()?;
10+
Some(&segment.ident)
11+
}
312

413
/// Allow all fields in the extractor config to be also overrideable by extractor CLI flags
514
#[proc_macro_attribute]
615
pub fn extractor_cli_config(_attr: TokenStream, item: TokenStream) -> TokenStream {
716
let ast = syn::parse_macro_input!(item as syn::ItemStruct);
817
let name = &ast.ident;
18+
let fields = ast
19+
.fields
20+
.iter()
21+
.map(|f| {
22+
if f.ident.as_ref().is_some_and(|i| i != "inputs")
23+
&& get_type_tip(&f.ty).is_some_and(|i| i == "Vec")
24+
{
25+
quote! {
26+
#[serde(deserialize_with="deserialize_newline_or_comma_separated")]
27+
#f
28+
}
29+
} else {
30+
quote! { #f }
31+
}
32+
})
33+
.collect::<Vec<_>>();
934
let cli_name = format_ident!("Cli{}", name);
1035
let cli_fields = ast
1136
.fields
1237
.iter()
1338
.map(|f| {
1439
let id = f.ident.as_ref().unwrap();
1540
let ty = &f.ty;
16-
if let syn::Type::Path(p) = ty {
17-
if p.path.is_ident(&format_ident!("bool")) {
18-
return quote! {
19-
#[arg(long)]
20-
#[serde(skip_serializing_if="<&bool>::not")]
21-
#id: bool,
22-
};
41+
let type_tip = get_type_tip(ty);
42+
if type_tip.is_some_and(|i| i == "bool") {
43+
quote! {
44+
#[arg(long)]
45+
#[serde(skip_serializing_if="<&bool>::not")]
46+
#id: bool
2347
}
24-
if p.path.segments.len() == 1 && p.path.segments[0].ident == "Option" {
25-
return quote! {
26-
#[arg(long)]
27-
#id: #ty,
28-
};
48+
} else if type_tip.is_some_and(|i| i == "Option") {
49+
quote! {
50+
#[arg(long)]
51+
#f
2952
}
30-
}
31-
if id == &format_ident!("verbose") {
53+
} else if id == &format_ident!("verbose") {
3254
quote! {
3355
#[arg(long, short, action=clap::ArgAction::Count)]
3456
#[serde(skip_serializing_if="u8::is_zero")]
35-
#id: u8,
57+
#id: u8
3658
}
3759
} else if id == &format_ident!("inputs") {
3860
quote! {
39-
#id: #ty,
61+
#f
62+
}
63+
} else if type_tip.is_some_and(|i| i == "Vec") {
64+
quote! {
65+
#[arg(long)]
66+
#id: Option<String>
4067
}
4168
} else {
4269
quote! {
4370
#[arg(long)]
44-
#id: Option<#ty>,
71+
#id: Option<#ty>
4572
}
4673
}
4774
})
@@ -66,7 +93,9 @@ pub fn extractor_cli_config(_attr: TokenStream, item: TokenStream) -> TokenStrea
6693
let gen = quote! {
6794
#[serde_with::apply(_ => #[serde(default)])]
6895
#[derive(Deserialize, Default)]
69-
#ast
96+
pub struct #name {
97+
#(#fields),*
98+
}
7099

71100
impl Debug for #name {
72101
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -80,7 +109,7 @@ pub fn extractor_cli_config(_attr: TokenStream, item: TokenStream) -> TokenStrea
80109
#[derive(clap::Parser, Serialize)]
81110
#[command(about, long_about = None)]
82111
struct #cli_name {
83-
#(#cli_fields)*
112+
#(#cli_fields),*
84113
}
85114
};
86115
gen.into()

rust/extractor/src/config.rs

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1+
mod deserialize_vec;
2+
13
use anyhow::Context;
24
use clap::Parser;
35
use codeql_extractor::trap;
6+
use deserialize_vec::deserialize_newline_or_comma_separated;
47
use figment::{
58
providers::{Env, Format, Serialized, Yaml},
69
value::Value,
710
Figment,
811
};
912
use itertools::Itertools;
13+
use log::warn;
1014
use num_traits::Zero;
15+
use ra_ap_cfg::{CfgAtom, CfgDiff};
16+
use ra_ap_intern::Symbol;
17+
use ra_ap_paths::Utf8PathBuf;
18+
use ra_ap_project_model::{CargoConfig, CargoFeatures, CfgOverrides, RustLibSource};
1119
use rust_extractor_macros::extractor_cli_config;
1220
use serde::{Deserialize, Serialize};
1321
use std::fmt::Debug;
@@ -38,6 +46,9 @@ pub struct Config {
3846
pub trap_dir: PathBuf,
3947
pub source_archive_dir: PathBuf,
4048
pub cargo_target_dir: Option<PathBuf>,
49+
pub cargo_target: Option<String>,
50+
pub cargo_features: Vec<String>,
51+
pub cargo_cfg_overrides: Vec<String>,
4152
pub verbose: u8,
4253
pub compression: Compression,
4354
pub inputs: Vec<PathBuf>,
@@ -52,7 +63,7 @@ impl Config {
5263
.context("expanding parameter files")?;
5364
let cli_args = CliConfig::parse_from(args);
5465
let mut figment = Figment::new()
55-
.merge(Env::prefixed("CODEQL_"))
66+
.merge(Env::raw().only(["CODEQL_VERBOSE"].as_slice()))
5667
.merge(Env::prefixed("CODEQL_EXTRACTOR_RUST_"))
5768
.merge(Env::prefixed("CODEQL_EXTRACTOR_RUST_OPTION_"))
5869
.merge(Serialized::defaults(cli_args));
@@ -72,4 +83,81 @@ impl Config {
7283
}
7384
figment.extract().context("loading configuration")
7485
}
86+
87+
pub fn to_cargo_config(&self) -> CargoConfig {
88+
let sysroot = Some(RustLibSource::Discover);
89+
90+
let target_dir = self
91+
.cargo_target_dir
92+
.clone()
93+
.unwrap_or_else(|| self.scratch_dir.join("target"));
94+
let target_dir = Utf8PathBuf::from_path_buf(target_dir).ok();
95+
96+
let features = if self.cargo_features.is_empty() {
97+
Default::default()
98+
} else if self.cargo_features.contains(&"*".to_string()) {
99+
CargoFeatures::All
100+
} else {
101+
CargoFeatures::Selected {
102+
features: self.cargo_features.clone(),
103+
no_default_features: false,
104+
}
105+
};
106+
107+
let target = self.cargo_target.clone();
108+
109+
let cfg_overrides = to_cfg_overrides(&self.cargo_cfg_overrides);
110+
111+
CargoConfig {
112+
sysroot,
113+
target_dir,
114+
features,
115+
target,
116+
cfg_overrides,
117+
..Default::default()
118+
}
119+
}
120+
}
121+
122+
fn to_cfg_override(spec: &str) -> CfgAtom {
123+
if let Some((key, value)) = spec.split_once("=") {
124+
CfgAtom::KeyValue {
125+
key: Symbol::intern(key),
126+
value: Symbol::intern(value),
127+
}
128+
} else {
129+
CfgAtom::Flag(Symbol::intern(spec))
130+
}
131+
}
132+
133+
fn to_cfg_overrides(specs: &Vec<String>) -> CfgOverrides {
134+
let mut enabled_cfgs = Vec::new();
135+
let mut disabled_cfgs = Vec::new();
136+
let mut has_test_explicitly_enabled = false;
137+
for spec in specs {
138+
if spec.starts_with("-") {
139+
disabled_cfgs.push(to_cfg_override(&spec[1..]));
140+
} else {
141+
enabled_cfgs.push(to_cfg_override(spec));
142+
if spec == "test" {
143+
has_test_explicitly_enabled = true;
144+
}
145+
}
146+
}
147+
if !has_test_explicitly_enabled {
148+
disabled_cfgs.push(to_cfg_override("test"));
149+
}
150+
if let Some(global) = CfgDiff::new(enabled_cfgs, disabled_cfgs) {
151+
CfgOverrides {
152+
global,
153+
..Default::default()
154+
}
155+
} else {
156+
warn!("non-disjoint cfg overrides, ignoring: {}", specs.join(", "));
157+
CfgOverrides {
158+
global: CfgDiff::new(Vec::new(), vec![to_cfg_override("test")])
159+
.expect("disabling one cfg should always succeed"),
160+
..Default::default()
161+
}
162+
}
75163
}

0 commit comments

Comments
 (0)