Received: by 2002:a05:6358:e9c4:b0:b2:91dc:71ab with SMTP id hc4csp1877456rwb; Fri, 5 Aug 2022 09:12:05 -0700 (PDT) X-Google-Smtp-Source: AA6agR7phzIy804kr6lwhcX/U9P2y+NjGnfkgaWTcS/ADTZD2nESPGdnPjVvwUDtYqDUrLkHa8Su X-Received: by 2002:a17:90b:3511:b0:1f4:e0cd:1e04 with SMTP id ls17-20020a17090b351100b001f4e0cd1e04mr17260580pjb.154.1659715924801; Fri, 05 Aug 2022 09:12:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1659715924; cv=none; d=google.com; s=arc-20160816; b=IUp9j+0CXVilkb8yIX24hpG1wkcBkyY0owlSbfopwFNOfg7L73mC7dfkZyEywZJcnA jdZ7K4Z4nmqeXSECH8EE9kRkKvZaE3xyg4WeaRDWfDd9VLt/YT4JOagVYT11SW9lOwsv rZQnOJzWyUjokWLy9l7zFTcHh7vCLHw3+NrIs9KKPf0pGWmJ0JdZ6MheHjiHORZqA3kU KaPPtYNoA1Hw8MiqkVWlztNJUsRawlgYE2A2em3/pk9Jjwnfmr+eKSVWOsyNrJf2poc5 72hxo2s3kVEazSdYR4mXj9qzIxCHFYc5etWEM3VKcycbRy8M8iE10K6ir4TcSvPjnS2L 1iqw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=nKTQf2Coot2X8jJjU7AqceJEYXcxVFA1PhI8QvQu7r4=; b=XXoKsqacya0Zh8oNFqJg7Bn0ZeAd/9b4A9mYX4fBAkYI8I9t5dz4dyxVq4ZcEUDwk1 fbR3UCKaynb1m+sKfOEG3I9K/Z68APz6Z8vI5NEma0V4nMGp68PUgFCp6buIGYfotctB NQRZsoNWJqIaKERw6s+ujhgRhdw90lkH+hOiI2zO7M2XuvmjwLbzrvHwi1N9FmKKk8zD fp1WOMJ35dN5SzNec7pvmJReqW0DrkYwPs1omos8zHb7yCTKbMSZFmwiGLeboIOg7MIb TOWAvv3OB7cIDK7bgFWApZ1lfVhK3eo7F6e1BxSrfUzw8znBe3Cdpn+YX05XjzIWn1VP cBSA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=n33OKap5; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id h184-20020a6383c1000000b0041d0282baabsi2609024pge.784.2022.08.05.09.11.49; Fri, 05 Aug 2022 09:12:04 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=n33OKap5; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241279AbiHEPqU (ORCPT + 99 others); Fri, 5 Aug 2022 11:46:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48028 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241286AbiHEPpk (ORCPT ); Fri, 5 Aug 2022 11:45:40 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0480F66107; Fri, 5 Aug 2022 08:44:19 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 94F7161642; Fri, 5 Aug 2022 15:44:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id DBDE8C43140; Fri, 5 Aug 2022 15:44:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1659714258; bh=X6lh4WNmtZCkT50Wc3ckSm0pNtS3+5we4IFm0nIix5A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=n33OKap5HI0sHaP457m8TQx6V8F0lhENA/iuRONTMEd0dBAf9TiRE9uNftFWVK7ue loOkIUOtslXGBUxGcBDuSW/kScD2nvyvqGelKsGlrOMkatC1aRd1PEPLONBw6VPGYg xkhlbVEeHQfeXT7GtXaL4wwtFP+EHczGb/2470qy3xA6LypqCR8Vu5QoQPyybBCini ov1z1UidJ2t5rO3n4e+9RlCxyH4stgf9snAVhcmUcXt06AmM7++MG2ZtRcG2ghEB3E hbYL3uQWgKeFK7J0MUF4vWErkC1hGVMndodVFqOy9drEcVUPe3hKW+W711zCbhD9nZ pfI1xTczu/kug== From: Miguel Ojeda To: Linus Torvalds , Greg Kroah-Hartman Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, patches@lists.linux.dev, Jarkko Sakkinen , Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , David Gow , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= Subject: [PATCH v9 19/27] scripts: add `generate_rust_target.rs` Date: Fri, 5 Aug 2022 17:42:04 +0200 Message-Id: <20220805154231.31257-20-ojeda@kernel.org> In-Reply-To: <20220805154231.31257-1-ojeda@kernel.org> References: <20220805154231.31257-1-ojeda@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This script takes care of generating the custom target specification file for `rustc`, based on the kernel configuration. It also serves as an example of a Rust host program. A dummy architecture is kept in this patch so that a later patch adds x86 support on top with as few changes as possible. Co-developed-by: Alex Gaynor Signed-off-by: Alex Gaynor Co-developed-by: Wedson Almeida Filho Signed-off-by: Wedson Almeida Filho Co-developed-by: David Gow Signed-off-by: David Gow Signed-off-by: Miguel Ojeda --- scripts/.gitignore | 1 + scripts/generate_rust_target.rs | 171 ++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 scripts/generate_rust_target.rs diff --git a/scripts/.gitignore b/scripts/.gitignore index eed308bef604..b7aec8eb1bd4 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only /asn1_compiler /bin2c +/generate_rust_target /insert-sys-cert /kallsyms /module.lds diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs new file mode 100644 index 000000000000..7256c9606cf0 --- /dev/null +++ b/scripts/generate_rust_target.rs @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! The custom target specification file generator for `rustc`. +//! +//! To configure a target from scratch, a JSON-encoded file has to be passed +//! to `rustc` (introduced in [RFC 131]). These options and the file itself are +//! unstable. Eventually, `rustc` should provide a way to do this in a stable +//! manner. For instance, via command-line arguments. Therefore, this file +//! should avoid using keys which can be set via `-C` or `-Z` options. +//! +//! [RFC 131]: https://rust-lang.github.io/rfcs/0131-target-specification.html + +use std::{ + collections::HashMap, + fmt::{Display, Formatter, Result}, + io::BufRead, +}; + +enum Value { + Boolean(bool), + Number(i32), + String(String), + Object(Object), +} + +type Object = Vec<(String, Value)>; + +/// Minimal "almost JSON" generator (e.g. no `null`s, no arrays, no escaping), +/// enough for this purpose. +impl Display for Value { + fn fmt(&self, formatter: &mut Formatter<'_>) -> Result { + match self { + Value::Boolean(boolean) => write!(formatter, "{}", boolean), + Value::Number(number) => write!(formatter, "{}", number), + Value::String(string) => write!(formatter, "\"{}\"", string), + Value::Object(object) => { + formatter.write_str("{")?; + if let [ref rest @ .., ref last] = object[..] { + for (key, value) in rest { + write!(formatter, "\"{}\": {},", key, value)?; + } + write!(formatter, "\"{}\": {}", last.0, last.1)?; + } + formatter.write_str("}") + } + } + } +} + +struct TargetSpec(Object); + +impl TargetSpec { + fn new() -> TargetSpec { + TargetSpec(Vec::new()) + } +} + +trait Push { + fn push(&mut self, key: &str, value: T); +} + +impl Push for TargetSpec { + fn push(&mut self, key: &str, value: bool) { + self.0.push((key.to_string(), Value::Boolean(value))); + } +} + +impl Push for TargetSpec { + fn push(&mut self, key: &str, value: i32) { + self.0.push((key.to_string(), Value::Number(value))); + } +} + +impl Push for TargetSpec { + fn push(&mut self, key: &str, value: String) { + self.0.push((key.to_string(), Value::String(value))); + } +} + +impl Push<&str> for TargetSpec { + fn push(&mut self, key: &str, value: &str) { + self.push(key, value.to_string()); + } +} + +impl Push for TargetSpec { + fn push(&mut self, key: &str, value: Object) { + self.0.push((key.to_string(), Value::Object(value))); + } +} + +impl Display for TargetSpec { + fn fmt(&self, formatter: &mut Formatter<'_>) -> Result { + // We add some newlines for clarity. + formatter.write_str("{\n")?; + if let [ref rest @ .., ref last] = self.0[..] { + for (key, value) in rest { + write!(formatter, " \"{}\": {},\n", key, value)?; + } + write!(formatter, " \"{}\": {}\n", last.0, last.1)?; + } + formatter.write_str("}") + } +} + +struct KernelConfig(HashMap); + +impl KernelConfig { + /// Parses `include/config/auto.conf` from `stdin`. + fn from_stdin() -> KernelConfig { + let mut result = HashMap::new(); + + let stdin = std::io::stdin(); + let mut handle = stdin.lock(); + let mut line = String::new(); + + loop { + line.clear(); + + if handle.read_line(&mut line).unwrap() == 0 { + break; + } + + if line.starts_with('#') { + continue; + } + + let (key, value) = line.split_once('=').expect("Missing `=` in line."); + result.insert(key.to_string(), value.trim_end_matches('\n').to_string()); + } + + KernelConfig(result) + } + + /// Does the option exist in the configuration (any value)? + /// + /// The argument must be passed without the `CONFIG_` prefix. + /// This avoids repetition and it also avoids `fixdep` making us + /// depend on it. + fn has(&self, option: &str) -> bool { + let option = "CONFIG_".to_owned() + option; + self.0.contains_key(&option) + } +} + +fn main() { + let cfg = KernelConfig::from_stdin(); + let mut ts = TargetSpec::new(); + + // `llvm-target`s are taken from `scripts/Makefile.clang`. + if cfg.has("DUMMY_ARCH") { + ts.push("arch", "dummy_arch"); + } else { + panic!("Unsupported architecture"); + } + + ts.push("emit-debug-gdb-scripts", false); + ts.push("frame-pointer", "may-omit"); + ts.push( + "stack-probes", + vec![("kind".to_string(), Value::String("none".to_string()))], + ); + + // Everything else is LE, whether `CPU_LITTLE_ENDIAN` is declared or not + // (e.g. x86). It is also `rustc`'s default. + if cfg.has("CPU_BIG_ENDIAN") { + ts.push("target-endian", "big"); + } + + println!("{}", ts); +} -- 2.37.1