1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
#!/usr/bin/env python3
import argparse
import os
import re
import subprocess
import sys
# Parse arguments
parser = argparse.ArgumentParser(
description="Generate a std compatibility module"
)
parser.add_argument("--src", help=(
"Specify the location of the rust source code. The default is "
"`$(rustc --print sysroot)/lib/rustlib/src/rust/src`"
))
args = parser.parse_args()
if args.src is None:
output = subprocess.run(["rustc", "--print", "sysroot"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
args.src = os.path.join(output.stdout.decode("utf-8").strip(),
"lib", "rustlib", "src", "rust", "src")
# Read files
modules_regex = re.compile(
r"^(?:\S.*)?pub\s+(?:mod\s+|use\s+(?:[a-zA-Z_][a-zA-Z0-9_]*::)*)"
r"([a-zA-Z_][a-zA-Z0-9_]*);",
re.MULTILINE
)
def modules(crate):
root = os.path.join(args.src, crate)
lib = os.path.join(root, "lib.rs")
with open(lib) as f:
contents = f.read()
modules = dict()
for match in modules_regex.finditer(contents):
module = match.group(1)
unstable = False
path = os.path.join(root, module + ".rs")
if not os.path.isfile(path):
path = os.path.join(root, module, "mod.rs")
try:
with open(path, "r") as f:
unstable = "#![unstable" in f.read()
if unstable:
print(
f"Module '{module}' from '{crate}' appears unstable",
file=sys.stderr
)
except OSError:
pass
modules[module] = unstable
return modules
def generate(module, unstable, *namespaces):
out = f"pub mod {module} {{\n"
if module == "prelude":
return None
for namespace in namespaces:
out += " "
cfgs = []
if namespace != "core":
cfgs.append(f"feature = \"{namespace}\"")
if unstable:
cfgs.append("feature = \"unstable\"")
if len(cfgs) == 1:
out += f"#[cfg({cfgs[0]})] "
elif len(cfgs) > 1:
out += "#[cfg(all(" + ", ".join(cfgs) + "))] "
out += f"pub use __{namespace}::{module}::*;\n"
if module == "collections":
prefix = (
" #[cfg(all("
"feature = \"alloc\", "
"feature = \"compat_hash\""
"))] pub use hashbrown::"
)
out += (
prefix + "HashMap;\n" +
prefix + "HashSet;\n"
)
elif module == "sync":
prefix = (
" #[cfg(all("
"feature = \"alloc\", "
"feature = \"compat_sync\""
"))] pub use spin::"
)
out += (
prefix + "Mutex;\n" +
prefix + "MutexGuard;\n" +
prefix + "Once;\n" +
prefix + "RwLock;\n" +
prefix + "RwLockReadGuard;\n" +
prefix + "RwLockWriteGuard;\n"
)
out += "}"
return out
core = modules("libcore")
alloc = modules("liballoc")
generated = {}
core_keys = set(core.keys())
alloc_keys = set(alloc.keys())
for module in core_keys & alloc_keys:
# TODO: separate these
unstable = core[module] or alloc[module]
generated[module] = generate(module, unstable, "core", "alloc")
for module in core_keys - alloc_keys:
unstable = core[module]
generated[module] = generate(module, unstable, "core")
for module in alloc_keys - core_keys:
unstable = alloc[module]
generated[module] = generate(module, unstable, "alloc")
generated["prelude"] = """pub mod prelude {
pub mod v1 {
// Prelude
pub use __core::prelude::v1::*;
#[cfg(all(feature = "alloc", feature = "unstable"))]
pub use __alloc::prelude::v1::*;
#[cfg(all(feature = "alloc", not(feature = "unstable")))]
pub use __alloc::{
borrow::ToOwned,
boxed::Box,
// UNSTABLE: slice::SliceConcatExt,
string::String,
string::ToString,
vec::Vec,
};
// Other imports
#[cfg(feature = "alloc")]
pub use __alloc::{format, vec};
#[cfg(feature = "compat_macros")]
pub use crate::{print, println, eprint, eprintln, dbg};
}
}"""
print("""//! Generated by generate.py located at the repository root
//! ./generate.py > src/generated.rs""")
for module in sorted(generated.items(), key=lambda i: i[0]):
print(module[1])
|