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