xref: /aosp_15_r20/external/cpu_features/scripts/generate_badges.d (revision eca53ba6d2e951e174b64682eaf56a36b8204c89)
1 #!/usr/bin/env -S docker run --rm -v ${PWD}/scripts:/scripts -v ${PWD}/.github/workflows:/.github/workflows dlanguage/dmd dmd -run /scripts/generate_badges.d
2 
3 // To run this script:
4 // cd /path/to/cpu_features
5 // ./scripts/generate_badges.d
6 
7 import std.algorithm : each, map, cartesianProduct, filter, joiner, sort, uniq;
8 import std.array;
9 import std.base64 : Base64;
10 import std.conv : to;
11 import std.file : exists;
12 import std.format;
13 import std.range : chain, only;
14 import std.stdio;
15 import std.string : representation;
16 import std.traits : EnumMembers;
17 
18 immutable string bazel_svg = `<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M6 .16l5.786 5.786L6 11.732.214 5.946 6 .161zM0 6.214V12l5.786 5.786V12L0 6.214zM18 .16l5.786 5.786L18 11.732l-5.786-5.786L18 .161zM24 6.214V12l-5.786 5.786V12L24 6.214zM12 6.16l5.786 5.786L12 17.732l-5.786-5.786L12 6.161zM11.84 18.054v5.785l-5.786-5.785v-5.786l5.785 5.786zM12.16 18.054l5.786-5.786v5.786l-5.785 5.785v-5.785z" stroke="transparent" fill="white"/></svg>`;
19 const string bazel_svg_base64 = Base64.encode(representation(bazel_svg));
20 
21 enum BuildSystem
22 {
23     CMake,
24     Bazel
25 }
26 
27 enum Cpu
28 {
29     amd64,
30     AArch64,
31     ARM,
32     MIPS,
33     POWER,
34     RISCV,
35     LOONGARCH,
36     s390x,
37 }
38 
39 enum Os
40 {
41     Linux,
42     FreeBSD,
43     MacOS,
44     Windows,
45 }
46 
47 struct Badge
48 {
49 const:
50 
51     Cpu cpu;
52     Os os;
53     BuildSystem build_system;
54 
55 private:
id()56     string id()
57     {
58         return format("%d%c%d", cast(uint)(os) + 1, cast(char)('a' + cpu),
59             cast(uint)(build_system));
60     }
61 
link_ref()62     string link_ref()
63     {
64         return format("[l%s]", id());
65     }
66 
image_ref()67     string image_ref()
68     {
69         return format("[i%s]", id());
70     }
71 
filename()72     string filename()
73     {
74         import std.uni : toLower;
75 
76         return toLower(format("%s_%s_%s.yml", cpu, os, build_system));
77     }
78 
enabled()79     bool enabled()
80     {
81         return exists("../.github/workflows/" ~ filename());
82     }
83 
append_logo(string url)84     string append_logo(string url)
85     {
86         final switch (build_system)
87         {
88         case BuildSystem.CMake:
89             return url ~ "&logo=cmake";
90         case BuildSystem.Bazel:
91             return url ~ "&logo=data:image/svg%2bxml;base64," ~ bazel_svg_base64;
92         }
93     }
94 
95 public:
96 
disabled_image_ref()97     string disabled_image_ref()
98     {
99         return format("[d%d]", cast(uint)(build_system));
100     }
101 
text()102     string text()
103     {
104         if (enabled())
105             return format("[![%s]%s]%s", build_system, image_ref, link_ref);
106         return format("![%s]%s", build_system, disabled_image_ref);
107     }
108 
disabled_image_link()109     string disabled_image_link()
110     {
111         return append_logo(format("%s: https://img.shields.io/badge/n%%2Fa-lightgrey?",
112                 disabled_image_ref));
113     }
114 
link_decl()115     string link_decl()
116     {
117         return format("%s: https://github.com/google/cpu_features/actions/workflows/%s",
118             link_ref, filename());
119     }
120 
image_decl()121     string image_decl()
122     {
123         return append_logo(format("%s: https://img.shields.io/github/actions/workflow/status/google/cpu_features/%s?branch=main&event=push&label=",
124                 image_ref, filename()));
125     }
126 
127 }
128 
tableHeader(in Os[]oses)129 auto tableHeader(in Os[] oses)
130 {
131     return chain(only(""), oses.map!(to!string)).array;
132 }
133 
tableAlignment(in Os[]oses)134 auto tableAlignment(in Os[] oses)
135 {
136     return chain(only(":--"), oses.map!(v => "--:")).array;
137 }
138 
tableCell(Range)139 auto tableCell(Range)(in Os os, in Cpu cpu, Range badges)
140 {
141     return badges.filter!(b => b.cpu == cpu && b.os == os)
142         .map!(b => b.text())
143         .joiner("<br/>").to!string;
144 }
145 
tableRow(Range)146 auto tableRow(Range)(in Cpu cpu, in Os[] oses, Range badges)
147 {
148     return chain(only(cpu.to!string), oses.map!(os => tableCell(os, cpu, badges))).array;
149 }
150 
tableRows(Range)151 auto tableRows(Range)(in Os[] oses, in Cpu[] cpus, Range badges)
152 {
153     return cpus.map!(cpu => tableRow(cpu, oses, badges)).array;
154 }
155 
table(Range)156 auto table(Range)(in Os[] oses, in Cpu[] cpus, Range badges)
157 {
158     return chain(only(tableHeader(oses)), only(tableAlignment(oses)),
159         tableRows(oses, cpus, badges));
160 }
161 
main()162 void main()
163 {
164     immutable allCpus = [EnumMembers!Cpu];
165     immutable allOses = [EnumMembers!Os];
166     immutable allBuildSystems = [EnumMembers!BuildSystem];
167     auto badges = cartesianProduct(allCpus, allOses, allBuildSystems).map!(
168         t => Badge(t[0], t[1], t[2]));
169     writefln("%(|%-( %s |%) |\n%) |", table(allOses, allCpus, badges));
170     writeln();
171     badges.filter!(b => !b.enabled)
172         .map!(b => b.disabled_image_link())
173         .array
174         .sort
175         .uniq
176         .each!writeln;
177     badges.filter!(b => b.enabled)
178         .map!(b => [b.link_decl(), b.image_decl()])
179         .joiner().array.sort.uniq.each!writeln;
180 }
181