mirror of
https://github.com/google/cpu_features.git
synced 2025-04-27 15:12:30 +02:00
Merge pull request #33 from google/json_output2
Add JSON output. Fixes #24
This commit is contained in:
commit
7eca4a7a39
@ -74,7 +74,7 @@ add_library(CpuFeature::cpu_features ALIAS cpu_features)
|
||||
# program : list_cpu_features
|
||||
#
|
||||
|
||||
add_executable(list_cpu_features src/list_cpu_features.c)
|
||||
add_executable(list_cpu_features src/utils/list_cpu_features.c)
|
||||
target_link_libraries(list_cpu_features PRIVATE cpu_features)
|
||||
add_executable(CpuFeature::list_cpu_features ALIAS list_cpu_features)
|
||||
|
||||
|
@ -121,7 +121,12 @@ family : 6 (0x06)
|
||||
model : 45 (0x2D)
|
||||
stepping : 7 (0x07)
|
||||
uarch : INTEL_SNB
|
||||
flags : aes, avx, sse4_1, sse4_2, ssse3
|
||||
flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3
|
||||
```
|
||||
|
||||
```shell
|
||||
% ./build/list_cpu_features --json
|
||||
{"arch":"x86","brand":" Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz","family":6,"model":45,"stepping":7,"uarch":"INTEL_SNB","flags":["aes","avx","cx16","smx","sse4_1","sse4_2","ssse3"]}
|
||||
```
|
||||
|
||||
<a name="support"></a>
|
||||
|
@ -1,108 +0,0 @@
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cpu_features_macros.h"
|
||||
#include "cpuinfo_aarch64.h"
|
||||
#include "cpuinfo_arm.h"
|
||||
#include "cpuinfo_mips.h"
|
||||
#include "cpuinfo_x86.h"
|
||||
|
||||
// Prints a named numeric value in both decimal and hexadecimal.
|
||||
void PrintN(const char* field, int value) {
|
||||
printf("%-15s : %3d (0x%02X)\n", field, value, value);
|
||||
}
|
||||
|
||||
// Prints a named string.
|
||||
void PrintS(const char* field, const char* value) {
|
||||
printf("%-15s : %s\n", field, value);
|
||||
}
|
||||
|
||||
static int cmp(const void* p1, const void* p2) {
|
||||
return strcmp(*(const char* const*)p1, *(const char* const*)p2);
|
||||
}
|
||||
|
||||
#define DEFINE_PRINT_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \
|
||||
void PrintFlags(const FeatureType* features) { \
|
||||
size_t i; \
|
||||
const char* ptrs[LastEnum] = {0}; \
|
||||
size_t count = 0; \
|
||||
for (i = 0; i < LastEnum; ++i) { \
|
||||
if (HasFeature(features, i)) { \
|
||||
ptrs[count] = FeatureName(i); \
|
||||
++count; \
|
||||
} \
|
||||
} \
|
||||
qsort(ptrs, count, sizeof(char*), cmp); \
|
||||
printf("%-15s : ", "flags"); \
|
||||
for (i = 0; i < count; ++i) { \
|
||||
if (i > 0) printf(", "); \
|
||||
printf("%s", ptrs[i]); \
|
||||
} \
|
||||
printf("\n"); \
|
||||
}
|
||||
|
||||
#if defined(CPU_FEATURES_ARCH_X86)
|
||||
DEFINE_PRINT_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features,
|
||||
X86_LAST_)
|
||||
#elif defined(CPU_FEATURES_ARCH_ARM)
|
||||
DEFINE_PRINT_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures,
|
||||
ARM_LAST_)
|
||||
#elif defined(CPU_FEATURES_ARCH_AARCH64)
|
||||
DEFINE_PRINT_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName,
|
||||
Aarch64Features, AARCH64_LAST_)
|
||||
#elif defined(CPU_FEATURES_ARCH_MIPS)
|
||||
DEFINE_PRINT_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName,
|
||||
MipsFeatures, MIPS_LAST_)
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
#if defined(CPU_FEATURES_ARCH_X86)
|
||||
char brand_string[49];
|
||||
const X86Info info = GetX86Info();
|
||||
FillX86BrandString(brand_string);
|
||||
PrintS("arch", "x86");
|
||||
PrintS("brand", brand_string);
|
||||
PrintN("family", info.family);
|
||||
PrintN("model", info.model);
|
||||
PrintN("stepping", info.stepping);
|
||||
PrintS("uarch", GetX86MicroarchitectureName(GetX86Microarchitecture(&info)));
|
||||
PrintFlags(&info.features);
|
||||
#elif defined(CPU_FEATURES_ARCH_ARM)
|
||||
const ArmInfo info = GetArmInfo();
|
||||
PrintS("arch", "ARM");
|
||||
PrintN("implementer", info.implementer);
|
||||
PrintN("architecture", info.architecture);
|
||||
PrintN("variant", info.variant);
|
||||
PrintN("part", info.part);
|
||||
PrintN("revision", info.revision);
|
||||
PrintFlags(&info.features);
|
||||
#elif defined(CPU_FEATURES_ARCH_AARCH64)
|
||||
const Aarch64Info info = GetAarch64Info();
|
||||
PrintS("arch", "aarch64");
|
||||
PrintN("implementer", info.implementer);
|
||||
PrintN("variant", info.variant);
|
||||
PrintN("part", info.part);
|
||||
PrintN("revision", info.revision);
|
||||
PrintFlags(&info.features);
|
||||
#elif defined(CPU_FEATURES_ARCH_MIPS)
|
||||
const MipsInfo info = GetMipsInfo();
|
||||
PrintS("arch", "mips");
|
||||
PrintFlags(&info.features);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
222
src/utils/list_cpu_features.c
Normal file
222
src/utils/list_cpu_features.c
Normal file
@ -0,0 +1,222 @@
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cpu_features_macros.h"
|
||||
#include "cpuinfo_aarch64.h"
|
||||
#include "cpuinfo_arm.h"
|
||||
#include "cpuinfo_mips.h"
|
||||
#include "cpuinfo_x86.h"
|
||||
|
||||
static void PrintEscapedAscii(const char* str) {
|
||||
putchar('"');
|
||||
for (; str && *str; ++str) {
|
||||
switch (*str) {
|
||||
case '\"':
|
||||
case '\\':
|
||||
case '/':
|
||||
case '\b':
|
||||
case '\f':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\t':
|
||||
putchar('\\');
|
||||
}
|
||||
putchar(*str);
|
||||
}
|
||||
putchar('"');
|
||||
}
|
||||
|
||||
static void PrintVoid(void) {}
|
||||
static void PrintComma(void) { putchar(','); }
|
||||
static void PrintLineFeed(void) { putchar('\n'); }
|
||||
static void PrintOpenBrace(void) { putchar('{'); }
|
||||
static void PrintCloseBrace(void) { putchar('}'); }
|
||||
static void PrintOpenBracket(void) { putchar('['); }
|
||||
static void PrintCloseBracket(void) { putchar(']'); }
|
||||
static void PrintString(const char* field) { printf("%s", field); }
|
||||
static void PrintAlignedHeader(const char* field) { printf("%-15s : ", field); }
|
||||
static void PrintIntValue(int value) { printf("%d", value); }
|
||||
static void PrintDecHexValue(int value) {
|
||||
printf("%3d (0x%02X)", value, value);
|
||||
}
|
||||
static void PrintJsonHeader(const char* field) {
|
||||
PrintEscapedAscii(field);
|
||||
putchar(':');
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
void (*Start)(void);
|
||||
void (*ArrayStart)(void);
|
||||
void (*ArraySeparator)(void);
|
||||
void (*ArrayEnd)(void);
|
||||
void (*PrintString)(const char* value);
|
||||
void (*PrintValue)(int value);
|
||||
void (*EndField)(void);
|
||||
void (*StartField)(const char* field);
|
||||
void (*End)(void);
|
||||
} Printer;
|
||||
|
||||
static Printer getJsonPrinter(void) {
|
||||
return (Printer){
|
||||
.Start = &PrintOpenBrace,
|
||||
.ArrayStart = &PrintOpenBracket,
|
||||
.ArraySeparator = &PrintComma,
|
||||
.ArrayEnd = &PrintCloseBracket,
|
||||
.PrintString = &PrintEscapedAscii,
|
||||
.PrintValue = &PrintIntValue,
|
||||
.EndField = &PrintComma,
|
||||
.StartField = &PrintJsonHeader,
|
||||
.End = &PrintCloseBrace,
|
||||
};
|
||||
}
|
||||
|
||||
static Printer getTextPrinter(void) {
|
||||
return (Printer){
|
||||
.Start = &PrintVoid,
|
||||
.ArrayStart = &PrintVoid,
|
||||
.ArraySeparator = &PrintComma,
|
||||
.ArrayEnd = &PrintVoid,
|
||||
.PrintString = &PrintString,
|
||||
.PrintValue = &PrintDecHexValue,
|
||||
.EndField = &PrintLineFeed,
|
||||
.StartField = &PrintAlignedHeader,
|
||||
.End = &PrintVoid,
|
||||
};
|
||||
}
|
||||
|
||||
// Prints a named numeric value in both decimal and hexadecimal.
|
||||
static void PrintN(const Printer p, const char* field, int value) {
|
||||
p.StartField(field);
|
||||
p.PrintValue(value);
|
||||
p.EndField();
|
||||
}
|
||||
|
||||
// Prints a named string.
|
||||
static void PrintS(const Printer p, const char* field, const char* value) {
|
||||
p.StartField(field);
|
||||
p.PrintString(value);
|
||||
p.EndField();
|
||||
}
|
||||
|
||||
static int cmp(const void* p1, const void* p2) {
|
||||
return strcmp(*(const char* const*)p1, *(const char* const*)p2);
|
||||
}
|
||||
|
||||
#define DEFINE_PRINT_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \
|
||||
static void PrintFlags(const Printer p, const FeatureType* features) { \
|
||||
size_t i; \
|
||||
const char* ptrs[LastEnum] = {0}; \
|
||||
size_t count = 0; \
|
||||
for (i = 0; i < LastEnum; ++i) { \
|
||||
if (HasFeature(features, i)) { \
|
||||
ptrs[count] = FeatureName(i); \
|
||||
++count; \
|
||||
} \
|
||||
} \
|
||||
qsort(ptrs, count, sizeof(char*), cmp); \
|
||||
p.StartField("flags"); \
|
||||
p.ArrayStart(); \
|
||||
for (i = 0; i < count; ++i) { \
|
||||
if (i > 0) p.ArraySeparator(); \
|
||||
p.PrintString(ptrs[i]); \
|
||||
} \
|
||||
p.ArrayEnd(); \
|
||||
}
|
||||
|
||||
#if defined(CPU_FEATURES_ARCH_X86)
|
||||
DEFINE_PRINT_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features,
|
||||
X86_LAST_)
|
||||
#elif defined(CPU_FEATURES_ARCH_ARM)
|
||||
DEFINE_PRINT_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures,
|
||||
ARM_LAST_)
|
||||
#elif defined(CPU_FEATURES_ARCH_AARCH64)
|
||||
DEFINE_PRINT_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName,
|
||||
Aarch64Features, AARCH64_LAST_)
|
||||
#elif defined(CPU_FEATURES_ARCH_MIPS)
|
||||
DEFINE_PRINT_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName,
|
||||
MipsFeatures, MIPS_LAST_)
|
||||
#endif
|
||||
|
||||
static void PrintFeatures(const Printer printer) {
|
||||
#if defined(CPU_FEATURES_ARCH_X86)
|
||||
char brand_string[49];
|
||||
const X86Info info = GetX86Info();
|
||||
FillX86BrandString(brand_string);
|
||||
PrintS(printer, "arch", "x86");
|
||||
PrintS(printer, "brand", brand_string);
|
||||
PrintN(printer, "family", info.family);
|
||||
PrintN(printer, "model", info.model);
|
||||
PrintN(printer, "stepping", info.stepping);
|
||||
PrintS(printer, "uarch",
|
||||
GetX86MicroarchitectureName(GetX86Microarchitecture(&info)));
|
||||
PrintFlags(printer, &info.features);
|
||||
#elif defined(CPU_FEATURES_ARCH_ARM)
|
||||
const ArmInfo info = GetArmInfo();
|
||||
PrintS(printer, "arch", "ARM");
|
||||
PrintN(printer, "implementer", info.implementer);
|
||||
PrintN(printer, "architecture", info.architecture);
|
||||
PrintN(printer, "variant", info.variant);
|
||||
PrintN(printer, "part", info.part);
|
||||
PrintN(printer, "revision", info.revision);
|
||||
PrintFlags(printer, &info.features);
|
||||
#elif defined(CPU_FEATURES_ARCH_AARCH64)
|
||||
const Aarch64Info info = GetAarch64Info();
|
||||
PrintS(printer, "arch", "aarch64");
|
||||
PrintN(printer, "implementer", info.implementer);
|
||||
PrintN(printer, "variant", info.variant);
|
||||
PrintN(printer, "part", info.part);
|
||||
PrintN(printer, "revision", info.revision);
|
||||
PrintFlags(printer, &info.features);
|
||||
#elif defined(CPU_FEATURES_ARCH_MIPS)
|
||||
const MipsInfo info = GetMipsInfo();
|
||||
PrintS(printer, "arch", "mips");
|
||||
PrintFlags(printer, &info.features);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void showUsage(const char* name) {
|
||||
printf(
|
||||
"\n"
|
||||
"Usage: %s [options]\n"
|
||||
" Options:\n"
|
||||
" -h | --help Show help message.\n"
|
||||
" -j | --json Format output as json instead of plain text.\n"
|
||||
"\n",
|
||||
name);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Printer printer = getTextPrinter();
|
||||
int i = 1;
|
||||
for (; i < argc; ++i) {
|
||||
const char* arg = argv[i];
|
||||
if (strcmp(arg, "-j") == 0 || strcmp(arg, "--json") == 0) {
|
||||
printer = getJsonPrinter();
|
||||
} else {
|
||||
showUsage(argv[0]);
|
||||
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0)
|
||||
return EXIT_SUCCESS;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
printer.Start();
|
||||
PrintFeatures(printer);
|
||||
printer.End();
|
||||
PrintLineFeed();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user