mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Add odin report command to help with bug reports.
Add new Odin command, `odin report`, which prints information helpful to resolving or reporting a bug. ``` W:\Odin> odin report Where to find more information and get into contact when you encounter a bug: Website: https://odin-lang.org GitHub: https://github.com/odin-lang/Odin/issues Useful information to add to a bug report: Odin: dev-2021-10:256bebfe OS: Windows 10 Professional (version: 20H2), build 19042.1266 CPU: AMD Ryzen 7 1800X Eight-Core Processor RAM: 65469 MiB W:\Odin> TODO: - CPU name on ARM/ARM64 ```
This commit is contained in:
@@ -13,6 +13,9 @@ jobs:
|
|||||||
- name: Odin version
|
- name: Odin version
|
||||||
run: ./odin version
|
run: ./odin version
|
||||||
timeout-minutes: 1
|
timeout-minutes: 1
|
||||||
|
- name: Odin report
|
||||||
|
run: ./odin report
|
||||||
|
timeout-minutes: 1
|
||||||
- name: Odin check
|
- name: Odin check
|
||||||
run: ./odin check examples/demo/demo.odin -vet
|
run: ./odin check examples/demo/demo.odin -vet
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
@@ -39,6 +42,9 @@ jobs:
|
|||||||
- name: Odin version
|
- name: Odin version
|
||||||
run: ./odin version
|
run: ./odin version
|
||||||
timeout-minutes: 1
|
timeout-minutes: 1
|
||||||
|
- name: Odin report
|
||||||
|
run: ./odin report
|
||||||
|
timeout-minutes: 1
|
||||||
- name: Odin check
|
- name: Odin check
|
||||||
run: ./odin check examples/demo/demo.odin -vet
|
run: ./odin check examples/demo/demo.odin -vet
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
@@ -57,6 +63,9 @@ jobs:
|
|||||||
- name: Odin version
|
- name: Odin version
|
||||||
run: ./odin version
|
run: ./odin version
|
||||||
timeout-minutes: 1
|
timeout-minutes: 1
|
||||||
|
- name: Odin report
|
||||||
|
run: ./odin report
|
||||||
|
timeout-minutes: 1
|
||||||
- name: Odin check
|
- name: Odin check
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ all: debug demo
|
|||||||
demo:
|
demo:
|
||||||
./odin run examples/demo/demo.odin
|
./odin run examples/demo/demo.odin
|
||||||
|
|
||||||
|
report:
|
||||||
|
./odin report
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
$(CC) src/main.cpp src/libtommath.cpp $(DISABLED_WARNINGS) $(CFLAGS) -g $(LDFLAGS) -o odin
|
$(CC) src/main.cpp src/libtommath.cpp $(DISABLED_WARNINGS) $(CFLAGS) -g $(LDFLAGS) -o odin
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,641 @@
|
|||||||
|
/*
|
||||||
|
Gather and print platform and version info to help with reporting Odin bugs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(GB_COMPILER_MSVC)
|
||||||
|
#if defined(GB_CPU_X86)
|
||||||
|
#include <cpuid.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GB_SYSTEM_LINUX)
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <sys/sysinfo.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GB_SYSTEM_OSX)
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE(Jeroen): This prints the Windows product edition only, to be called from `print_platform_details`.
|
||||||
|
*/
|
||||||
|
#if defined(GB_SYSTEM_WINDOWS)
|
||||||
|
void report_windows_product_type(DWORD ProductType) {
|
||||||
|
switch (ProductType) {
|
||||||
|
case PRODUCT_ULTIMATE:
|
||||||
|
gb_printf("Ultimate");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_HOME_BASIC:
|
||||||
|
gb_printf("Home Basic");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_HOME_PREMIUM:
|
||||||
|
gb_printf("Home Premium");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_ENTERPRISE:
|
||||||
|
gb_printf("Enterprise");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_HOME_BASIC_N:
|
||||||
|
gb_printf("Home Basic N");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_BUSINESS:
|
||||||
|
gb_printf("Business");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_STANDARD_SERVER:
|
||||||
|
gb_printf("Standard Server");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_DATACENTER_SERVER:
|
||||||
|
gb_printf("Datacenter");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_SMALLBUSINESS_SERVER:
|
||||||
|
gb_printf("Windows Small Business Server");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_ENTERPRISE_SERVER:
|
||||||
|
gb_printf("Enterprise Server");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_STARTER:
|
||||||
|
gb_printf("Starter");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_DATACENTER_SERVER_CORE:
|
||||||
|
gb_printf("Datacenter Server Core");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_STANDARD_SERVER_CORE:
|
||||||
|
gb_printf("Server Standard Core");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_ENTERPRISE_SERVER_CORE:
|
||||||
|
gb_printf("Enterprise Server Core");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_BUSINESS_N:
|
||||||
|
gb_printf("Business N");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_HOME_SERVER:
|
||||||
|
gb_printf("Home Server");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_SERVER_FOR_SMALLBUSINESS:
|
||||||
|
gb_printf("Windows Server 2008 for Windows Essential Server Solutions");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
|
||||||
|
gb_printf("Small Business Server Premium");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_HOME_PREMIUM_N:
|
||||||
|
gb_printf("Home Premium N");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_ENTERPRISE_N:
|
||||||
|
gb_printf("Enterprise N");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_ULTIMATE_N:
|
||||||
|
gb_printf("Ultimate N");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_HYPERV:
|
||||||
|
gb_printf("HyperV");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_STARTER_N:
|
||||||
|
gb_printf("Starter N");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_PROFESSIONAL:
|
||||||
|
gb_printf("Professional");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_PROFESSIONAL_N:
|
||||||
|
gb_printf("Professional N");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRODUCT_UNLICENSED:
|
||||||
|
gb_printf("Unlicensed");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
gb_printf("Unknown Edition (%08x)", ProductType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void odin_cpuid(int leaf, int result[]) {
|
||||||
|
#if defined(GB_COMPILER_MSVC)
|
||||||
|
__cpuid(result, leaf);
|
||||||
|
#else
|
||||||
|
__get_cpuid(leaf, (unsigned int*)&result[0], (unsigned int*)&result[1], (unsigned int*)&result[2], (unsigned int*)&result[3]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_cpu_info() {
|
||||||
|
gb_printf("\tCPU: ");
|
||||||
|
|
||||||
|
#if defined(GB_CPU_X86)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get extended leaf info
|
||||||
|
*/
|
||||||
|
int cpu[4];
|
||||||
|
|
||||||
|
odin_cpuid(0x80000000, &cpu[0]);
|
||||||
|
int number_of_extended_ids = cpu[0];
|
||||||
|
|
||||||
|
int brand[0x12] = {};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Read CPU brand if supported.
|
||||||
|
*/
|
||||||
|
if (number_of_extended_ids >= 0x80000004) {
|
||||||
|
odin_cpuid(0x80000002, &brand[0]);
|
||||||
|
odin_cpuid(0x80000003, &brand[4]);
|
||||||
|
odin_cpuid(0x80000004, &brand[8]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Some CPUs like ` Intel(R) Xeon(R) CPU E5-1650 v2 @ 3.50GHz` may include leading spaces. Trim them.
|
||||||
|
*/
|
||||||
|
char * brand_name = (char *)&brand[0];
|
||||||
|
for (; brand_name[0] == ' '; brand_name++) {}
|
||||||
|
|
||||||
|
gb_printf("%s\n", brand_name);
|
||||||
|
} else {
|
||||||
|
gb_printf("Unable to retrieve.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(GB_CPU_ARM)
|
||||||
|
/*
|
||||||
|
TODO(Jeroen): On *nix, perhaps query `/proc/cpuinfo`.
|
||||||
|
*/
|
||||||
|
#if defined(GB_ARCH_64_BIT)
|
||||||
|
gb_printf("ARM64\n");
|
||||||
|
#else
|
||||||
|
gb_printf("ARM\n");
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
gb_printf("Unknown\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Report the amount of installed RAM.
|
||||||
|
*/
|
||||||
|
void report_ram_info() {
|
||||||
|
|
||||||
|
gb_printf("\tRAM: ");
|
||||||
|
|
||||||
|
#if defined(GB_SYSTEM_WINDOWS)
|
||||||
|
MEMORYSTATUSEX statex;
|
||||||
|
statex.dwLength = sizeof(statex);
|
||||||
|
GlobalMemoryStatusEx (&statex);
|
||||||
|
|
||||||
|
gb_printf("%lld MiB\n", statex.ullTotalPhys / gb_megabytes(1));
|
||||||
|
|
||||||
|
#elif defined(GB_SYSTEM_LINUX)
|
||||||
|
/*
|
||||||
|
Retrieve RAM info using `sysinfo()`,
|
||||||
|
*/
|
||||||
|
struct sysinfo info;
|
||||||
|
int result = sysinfo(&info);
|
||||||
|
|
||||||
|
if (result == 0x0) {
|
||||||
|
gb_printf("%lu MiB\n", info.totalram * info.mem_unit / gb_megabytes(1));
|
||||||
|
} else {
|
||||||
|
gb_printf("Unknown.\n");
|
||||||
|
}
|
||||||
|
#elif defined(GB_SYSTEM_OSX)
|
||||||
|
uint64_t ram_amount;
|
||||||
|
size_t val_size = sizeof(ram_amount);
|
||||||
|
|
||||||
|
int sysctls[] = { CTL_HW, HW_MEMSIZE };
|
||||||
|
if (sysctl(sysctls, 2, &ram_amount, &val_size, NULL, 0) != -1) {
|
||||||
|
gb_printf("%lld MiB\n", ram_amount / gb_megabytes(1));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
gb_printf("Unknown.\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE(Jeroen): `odin report` prints some system information for easier bug reporting.
|
||||||
|
*/
|
||||||
|
void print_bug_report_help() {
|
||||||
|
gb_printf("Where to find more information and get into contact when you encounter a bug:\n\n");
|
||||||
|
gb_printf("\tWebsite: https://odin-lang.org\n");
|
||||||
|
gb_printf("\tGitHub: https://github.com/odin-lang/Odin/issues\n");
|
||||||
|
/*
|
||||||
|
Uncomment and update URL once we have a Discord vanity URL. For now people can get here from the site.
|
||||||
|
gb_printf("\tDiscord: https://discord.com/invite/sVBPHEv\n");
|
||||||
|
*/
|
||||||
|
gb_printf("\n\n");
|
||||||
|
|
||||||
|
gb_printf("Useful information to add to a bug report:\n\n");
|
||||||
|
|
||||||
|
gb_printf("\tOdin: %.*s", LIT(ODIN_VERSION));
|
||||||
|
|
||||||
|
#ifdef NIGHTLY
|
||||||
|
gb_printf("-nightly");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GIT_SHA
|
||||||
|
gb_printf(":%s", GIT_SHA);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gb_printf("\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
Print OS information.
|
||||||
|
*/
|
||||||
|
gb_printf("\tOS: ");
|
||||||
|
|
||||||
|
#if defined(GB_SYSTEM_WINDOWS)
|
||||||
|
/*
|
||||||
|
NOTE(Jeroen):
|
||||||
|
`GetVersionEx` will return 6.2 for Windows 10 unless the program is manifested for Windows 10.
|
||||||
|
`RtlGetVersion` will return the true version.
|
||||||
|
|
||||||
|
Rather than include the WinDDK, we ask the kernel directly.
|
||||||
|
|
||||||
|
`HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion` is for the minor build version (Update Build Release)
|
||||||
|
|
||||||
|
*/
|
||||||
|
OSVERSIONINFOEXW osvi;
|
||||||
|
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXW));
|
||||||
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
|
||||||
|
|
||||||
|
typedef NTSTATUS (WINAPI* RtlGetVersionPtr)(OSVERSIONINFOW*);
|
||||||
|
typedef BOOL (WINAPI* GetProductInfoPtr)(DWORD dwOSMajorVersion, DWORD dwOSMinorVersion, DWORD dwSpMajorVersion, DWORD dwSpMinorVersion, PDWORD pdwReturnedProductType);
|
||||||
|
|
||||||
|
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlgetversion
|
||||||
|
RtlGetVersionPtr RtlGetVersion = (RtlGetVersionPtr)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "RtlGetVersion");
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getproductinfo
|
||||||
|
GetProductInfoPtr GetProductInfo = (GetProductInfoPtr)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo");
|
||||||
|
|
||||||
|
NTSTATUS status = {};
|
||||||
|
DWORD ProductType = {};
|
||||||
|
if (RtlGetVersion != nullptr) {
|
||||||
|
status = RtlGetVersion((OSVERSIONINFOW*)&osvi);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RtlGetVersion == nullptr || status != 0x0) {
|
||||||
|
gb_printf("Windows (Unknown Version)");
|
||||||
|
} else {
|
||||||
|
if (GetProductInfo != nullptr) {
|
||||||
|
GetProductInfo(osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.wServicePackMajor, osvi.wServicePackMinor, &ProductType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false) {
|
||||||
|
gb_printf("dwMajorVersion: %d\n", osvi.dwMajorVersion);
|
||||||
|
gb_printf("dwMinorVersion: %d\n", osvi.dwMinorVersion);
|
||||||
|
gb_printf("dwBuildNumber: %d\n", osvi.dwBuildNumber);
|
||||||
|
gb_printf("dwPlatformId: %d\n", osvi.dwPlatformId);
|
||||||
|
gb_printf("wServicePackMajor: %d\n", osvi.wServicePackMajor);
|
||||||
|
gb_printf("wServicePackMinor: %d\n", osvi.wServicePackMinor);
|
||||||
|
gb_printf("wSuiteMask: %d\n", osvi.wSuiteMask);
|
||||||
|
gb_printf("wProductType: %d\n", osvi.wProductType);
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_printf("Windows ");
|
||||||
|
|
||||||
|
switch (osvi.dwMajorVersion) {
|
||||||
|
case 10:
|
||||||
|
/*
|
||||||
|
Windows 10 (Pro), Windows 2016 Server, Windows 2019 Server, Windows 2022 Server
|
||||||
|
*/
|
||||||
|
switch (osvi.wProductType) {
|
||||||
|
case VER_NT_WORKSTATION: // Workstation
|
||||||
|
if (osvi.dwBuildNumber < 22000) {
|
||||||
|
gb_printf("10 ");
|
||||||
|
} else {
|
||||||
|
gb_printf("11 ");
|
||||||
|
}
|
||||||
|
|
||||||
|
report_windows_product_type(ProductType);
|
||||||
|
|
||||||
|
break;
|
||||||
|
default: // Server or Domain Controller
|
||||||
|
switch(osvi.dwBuildNumber) {
|
||||||
|
case 14393:
|
||||||
|
gb_printf("2016 Server");
|
||||||
|
break;
|
||||||
|
case 17763:
|
||||||
|
gb_printf("2019 Server");
|
||||||
|
break;
|
||||||
|
case 20348:
|
||||||
|
gb_printf("2022 Server");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gb_printf("Unknown Server");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
switch (osvi.dwMinorVersion) {
|
||||||
|
case 0:
|
||||||
|
switch (osvi.wProductType) {
|
||||||
|
case VER_NT_WORKSTATION:
|
||||||
|
gb_printf("Windows Vista ");
|
||||||
|
report_windows_product_type(ProductType);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
gb_printf("Windows Server 2008");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
switch (osvi.wProductType) {
|
||||||
|
case VER_NT_WORKSTATION:
|
||||||
|
gb_printf("Windows 7 ");
|
||||||
|
report_windows_product_type(ProductType);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
gb_printf("Windows Server 2008 R2");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
switch (osvi.wProductType) {
|
||||||
|
case VER_NT_WORKSTATION:
|
||||||
|
gb_printf("Windows 8 ");
|
||||||
|
report_windows_product_type(ProductType);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
gb_printf("Windows Server 2012");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
switch (osvi.wProductType) {
|
||||||
|
case VER_NT_WORKSTATION:
|
||||||
|
gb_printf("Windows 8.1 ");
|
||||||
|
report_windows_product_type(ProductType);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
gb_printf("Windows Server 2012 R2");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
switch (osvi.dwMinorVersion) {
|
||||||
|
case 0:
|
||||||
|
gb_printf("Windows 2000");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
gb_printf("Windows XP");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
gb_printf("Windows Server 2003");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Grab Windows DisplayVersion (like 20H02)
|
||||||
|
*/
|
||||||
|
LPDWORD ValueType = {};
|
||||||
|
DWORD UBR;
|
||||||
|
char DisplayVersion[256];
|
||||||
|
DWORD ValueSize = 256;
|
||||||
|
|
||||||
|
status = RegGetValue(
|
||||||
|
HKEY_LOCAL_MACHINE,
|
||||||
|
TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"),
|
||||||
|
TEXT("DisplayVersion"),
|
||||||
|
RRF_RT_REG_SZ,
|
||||||
|
ValueType,
|
||||||
|
&DisplayVersion,
|
||||||
|
&ValueSize
|
||||||
|
);
|
||||||
|
|
||||||
|
if (status == 0x0) {
|
||||||
|
gb_printf(" (version: %s)", &DisplayVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Now print build number.
|
||||||
|
*/
|
||||||
|
gb_printf(", build %d", osvi.dwBuildNumber);
|
||||||
|
|
||||||
|
ValueSize = sizeof(UBR);
|
||||||
|
status = RegGetValue(
|
||||||
|
HKEY_LOCAL_MACHINE,
|
||||||
|
TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"),
|
||||||
|
TEXT("UBR"),
|
||||||
|
RRF_RT_REG_DWORD,
|
||||||
|
ValueType,
|
||||||
|
&UBR,
|
||||||
|
&ValueSize
|
||||||
|
);
|
||||||
|
|
||||||
|
if (status == 0x0) {
|
||||||
|
gb_printf(".%d", UBR);
|
||||||
|
}
|
||||||
|
gb_printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(GB_SYSTEM_LINUX)
|
||||||
|
/*
|
||||||
|
Try to parse `/usr/lib/os-release` for `PRETTY_NAME="Ubuntu 20.04.3 LTS`
|
||||||
|
*/
|
||||||
|
gbAllocator a = heap_allocator();
|
||||||
|
|
||||||
|
gbFileContents release = gb_file_read_contents(a, 1, "/usr/lib/os-release");
|
||||||
|
defer (gb_file_free_contents(&release));
|
||||||
|
|
||||||
|
b32 found = 0;
|
||||||
|
if (release.size) {
|
||||||
|
char *start = (char *)release.data;
|
||||||
|
char *end = (char *)release.data + release.size;
|
||||||
|
const char *needle = "PRETTY_NAME=\"";
|
||||||
|
isize needle_len = gb_strlen((needle));
|
||||||
|
|
||||||
|
char *c = start;
|
||||||
|
for (; c < end; c++) {
|
||||||
|
if (gb_strncmp(c, needle, needle_len) == 0) {
|
||||||
|
found = 1;
|
||||||
|
start = c + needle_len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
for (c = start; c < end; c++) {
|
||||||
|
if (*c == '"') {
|
||||||
|
// Found the closing quote. Replace it with \0
|
||||||
|
*c = 0;
|
||||||
|
gb_printf("%s", (char *)start);
|
||||||
|
break;
|
||||||
|
} else if (*c == '\n') {
|
||||||
|
found = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
gb_printf("Unknown Linux Distro");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Print kernel info using `uname()` syscall, https://linux.die.net/man/2/uname
|
||||||
|
*/
|
||||||
|
char buffer[1024];
|
||||||
|
uname((struct utsname *)&buffer[0]);
|
||||||
|
|
||||||
|
struct utsname *info;
|
||||||
|
info = (struct utsname *)&buffer[0];
|
||||||
|
|
||||||
|
gb_printf(", %s %s\n", info->sysname, info->release);
|
||||||
|
|
||||||
|
#elif defined(GB_SYSTEM_OSX)
|
||||||
|
b32 found = 1;
|
||||||
|
uint32_t major, minor;
|
||||||
|
|
||||||
|
#define osx_version_buffer 100
|
||||||
|
char buffer[osx_version_buffer];
|
||||||
|
size_t buffer_size = osx_version_buffer - 1;
|
||||||
|
#undef osx_version_buffer
|
||||||
|
|
||||||
|
int sysctls[] = { CTL_KERN, KERN_OSRELEASE };
|
||||||
|
if (sysctl(sysctls, 2, buffer, &buffer_size, NULL, 0) == -1) {
|
||||||
|
found = 0;
|
||||||
|
} else {
|
||||||
|
if (sscanf(buffer, "%u.%u", &major, &minor) != 2) {
|
||||||
|
found = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
switch (major) {
|
||||||
|
case 21:
|
||||||
|
/*
|
||||||
|
macOS Big Sur and newer
|
||||||
|
*/
|
||||||
|
major -= 9;
|
||||||
|
|
||||||
|
gb_printf("macOS 12.0.%d Monterey\n", minor);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
/*
|
||||||
|
macOS Big Sur and newer
|
||||||
|
*/
|
||||||
|
major -= 9;
|
||||||
|
|
||||||
|
gb_printf("macOS 11.%d Big Sur\n", minor);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
/*
|
||||||
|
macOS 10.1.1 and newer
|
||||||
|
*/
|
||||||
|
major -= 4;
|
||||||
|
|
||||||
|
switch (minor) {
|
||||||
|
case 1:
|
||||||
|
gb_printf("macOS Puma 10.1\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
gb_printf("macOS Jaguar 10.2\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
gb_printf("macOS Panther 10.3\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
gb_printf("macOS Tiger 10.4\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
gb_printf("macOS Leopard 10.5\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
gb_printf("macOS Snow Leopard 10.6\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
gb_printf("macOS Lion 10.7\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
gb_printf("macOS Mountain Lion 10.8\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 9:
|
||||||
|
gb_printf("macOS Mavericks 10.9\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
gb_printf("macOS Yosemite 10.10\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 11:
|
||||||
|
gb_printf("macOS El Capitan 10.11\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 12:
|
||||||
|
gb_printf("macOS Sierra 10.12\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 13:
|
||||||
|
gb_printf("macOS High Sierra 10.13\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 14:
|
||||||
|
gb_printf("macOS Mojave 10.14\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 15:
|
||||||
|
gb_printf("macOS Catalina 10.15\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
gb_printf("macOS %d.%d\n", major, minor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gb_printf("macOS Unknown (kernel version %d.%d)\n", major, minor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gb_printf("macOS: Unknown\n");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
gb_printf("Unknown\n");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Now print CPU info.
|
||||||
|
*/
|
||||||
|
report_cpu_info();
|
||||||
|
|
||||||
|
/*
|
||||||
|
And RAM info.
|
||||||
|
*/
|
||||||
|
report_ram_info();
|
||||||
|
}
|
||||||
@@ -113,15 +113,16 @@ enum BuildModeKind {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum CommandKind : u32 {
|
enum CommandKind : u32 {
|
||||||
Command_run = 1<<0,
|
Command_run = 1<<0,
|
||||||
Command_build = 1<<1,
|
Command_build = 1<<1,
|
||||||
Command_check = 1<<3,
|
Command_check = 1<<3,
|
||||||
Command_query = 1<<4,
|
Command_query = 1<<4,
|
||||||
Command_doc = 1<<5,
|
Command_doc = 1<<5,
|
||||||
Command_version = 1<<6,
|
Command_version = 1<<6,
|
||||||
Command_test = 1<<7,
|
Command_test = 1<<7,
|
||||||
|
|
||||||
Command_strip_semicolon = 1<<8,
|
Command_strip_semicolon = 1<<8,
|
||||||
|
Command_bug_report = 1<<9,
|
||||||
|
|
||||||
Command__does_check = Command_run|Command_build|Command_check|Command_query|Command_doc|Command_test|Command_strip_semicolon,
|
Command__does_check = Command_run|Command_build|Command_check|Command_query|Command_doc|Command_test|Command_strip_semicolon,
|
||||||
Command__does_build = Command_run|Command_build|Command_test,
|
Command__does_build = Command_run|Command_build|Command_test,
|
||||||
|
|||||||
+17
-14
@@ -64,6 +64,8 @@ gb_global Timings global_timings = {0};
|
|||||||
#include "microsoft_craziness.h"
|
#include "microsoft_craziness.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "bug_report.cpp"
|
||||||
|
|
||||||
|
|
||||||
// NOTE(bill): 'name' is used in debugging and profiling modes
|
// NOTE(bill): 'name' is used in debugging and profiling modes
|
||||||
i32 system_exec_command_line_app(char const *name, char const *fmt, ...) {
|
i32 system_exec_command_line_app(char const *name, char const *fmt, ...) {
|
||||||
@@ -96,8 +98,8 @@ i32 system_exec_command_line_app(char const *name, char const *fmt, ...) {
|
|||||||
|
|
||||||
wcmd = string_to_string16(permanent_allocator(), make_string(cast(u8 *)cmd_line, cmd_len-1));
|
wcmd = string_to_string16(permanent_allocator(), make_string(cast(u8 *)cmd_line, cmd_len-1));
|
||||||
if (CreateProcessW(nullptr, wcmd.text,
|
if (CreateProcessW(nullptr, wcmd.text,
|
||||||
nullptr, nullptr, true, 0, nullptr, nullptr,
|
nullptr, nullptr, true, 0, nullptr, nullptr,
|
||||||
&start_info, &pi)) {
|
&start_info, &pi)) {
|
||||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||||
GetExitCodeProcess(pi.hProcess, cast(DWORD *)&exit_code);
|
GetExitCodeProcess(pi.hProcess, cast(DWORD *)&exit_code);
|
||||||
|
|
||||||
@@ -212,7 +214,7 @@ i32 linker_stage(lbGenerator *gen) {
|
|||||||
String lib = m->foreign_library_paths[i];
|
String lib = m->foreign_library_paths[i];
|
||||||
GB_ASSERT(lib.len < gb_count_of(lib_str_buf)-1);
|
GB_ASSERT(lib.len < gb_count_of(lib_str_buf)-1);
|
||||||
gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
||||||
" \"%.*s\"", LIT(lib));
|
" \"%.*s\"", LIT(lib));
|
||||||
lib_str = gb_string_appendc(lib_str, lib_str_buf);
|
lib_str = gb_string_appendc(lib_str, lib_str_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,7 +223,7 @@ i32 linker_stage(lbGenerator *gen) {
|
|||||||
String lib = gen->default_module.foreign_library_paths[i];
|
String lib = gen->default_module.foreign_library_paths[i];
|
||||||
GB_ASSERT(lib.len < gb_count_of(lib_str_buf)-1);
|
GB_ASSERT(lib.len < gb_count_of(lib_str_buf)-1);
|
||||||
gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
||||||
" \"%.*s\"", LIT(lib));
|
" \"%.*s\"", LIT(lib));
|
||||||
lib_str = gb_string_appendc(lib_str, lib_str_buf);
|
lib_str = gb_string_appendc(lib_str, lib_str_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,7 +322,7 @@ i32 linker_stage(lbGenerator *gen) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -513,10 +515,6 @@ Array<String> setup_args(int argc, char const **argv) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void print_usage_line(i32 indent, char const *fmt, ...) {
|
void print_usage_line(i32 indent, char const *fmt, ...) {
|
||||||
while (indent --> 0) {
|
while (indent --> 0) {
|
||||||
gb_printf_err("\t");
|
gb_printf_err("\t");
|
||||||
@@ -540,6 +538,7 @@ void usage(String argv0) {
|
|||||||
print_usage_line(1, "query parse, type check, and output a .json file containing information about the program");
|
print_usage_line(1, "query parse, type check, and output a .json file containing information about the program");
|
||||||
print_usage_line(1, "doc generate documentation .odin file, or directory of .odin files");
|
print_usage_line(1, "doc generate documentation .odin file, or directory of .odin files");
|
||||||
print_usage_line(1, "version print version");
|
print_usage_line(1, "version print version");
|
||||||
|
print_usage_line(1, "report print information useful to reporting a bug");
|
||||||
print_usage_line(0, "");
|
print_usage_line(0, "");
|
||||||
print_usage_line(0, "For more information of flags, apply the flag to see what is possible");
|
print_usage_line(0, "For more information of flags, apply the flag to see what is possible");
|
||||||
print_usage_line(1, "-help");
|
print_usage_line(1, "-help");
|
||||||
@@ -856,12 +855,12 @@ bool parse_build_flags(Array<String> args) {
|
|||||||
break;
|
break;
|
||||||
case BuildFlagParam_Boolean: {
|
case BuildFlagParam_Boolean: {
|
||||||
if (str_eq_ignore_case(param, str_lit("t")) ||
|
if (str_eq_ignore_case(param, str_lit("t")) ||
|
||||||
str_eq_ignore_case(param, str_lit("true")) ||
|
str_eq_ignore_case(param, str_lit("true")) ||
|
||||||
param == "1") {
|
param == "1") {
|
||||||
value = exact_value_bool(true);
|
value = exact_value_bool(true);
|
||||||
} else if (str_eq_ignore_case(param, str_lit("f")) ||
|
} else if (str_eq_ignore_case(param, str_lit("f")) ||
|
||||||
str_eq_ignore_case(param, str_lit("false")) ||
|
str_eq_ignore_case(param, str_lit("false")) ||
|
||||||
param == "0") {
|
param == "0") {
|
||||||
value = exact_value_bool(false);
|
value = exact_value_bool(false);
|
||||||
} else {
|
} else {
|
||||||
gb_printf_err("Invalid flag parameter for '%.*s' : '%.*s'\n", LIT(name), LIT(param));
|
gb_printf_err("Invalid flag parameter for '%.*s' : '%.*s'\n", LIT(name), LIT(param));
|
||||||
@@ -2373,6 +2372,10 @@ int main(int arg_count, char const **arg_ptr) {
|
|||||||
|
|
||||||
gb_printf("\n");
|
gb_printf("\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
} else if (command == "report") {
|
||||||
|
build_context.command_kind = Command_bug_report;
|
||||||
|
print_bug_report_help();
|
||||||
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
usage(args[0]);
|
usage(args[0]);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -2396,7 +2399,7 @@ int main(int arg_count, char const **arg_ptr) {
|
|||||||
// NOTE(bill): add 'shared' directory if it is not already set
|
// NOTE(bill): add 'shared' directory if it is not already set
|
||||||
if (!find_library_collection_path(str_lit("shared"), nullptr)) {
|
if (!find_library_collection_path(str_lit("shared"), nullptr)) {
|
||||||
add_library_collection(str_lit("shared"),
|
add_library_collection(str_lit("shared"),
|
||||||
get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("shared")));
|
get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("shared")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user