diff --git a/openscad.pro b/openscad.pro index cf374a44..d745c708 100644 --- a/openscad.pro +++ b/openscad.pro @@ -116,7 +116,6 @@ macx { win* { RC_FILE = openscad_win32.rc - QTPLUGIN += qtaccessiblewidgets } CONFIG += qt @@ -130,8 +129,6 @@ unix:!macx { QMAKE_LIBS_OPENGL *= -lX11 } -#QTPLUGIN += qtaccessiblewidgets - netbsd* { QMAKE_LFLAGS += -L/usr/X11R7/lib QMAKE_LFLAGS += -Wl,-R/usr/X11R7/lib diff --git a/src/LibraryInfo.cc b/src/LibraryInfo.cc index 83f3875c..52facbb1 100644 --- a/src/LibraryInfo.cc +++ b/src/LibraryInfo.cc @@ -29,12 +29,20 @@ std::string LibraryInfo::info() { std::stringstream s; +#if defined(__x86_64__) || defined(_M_X64) + std::string bits(" 64bit"); +#elif defined(__i386) || defined(_M_IX86) + std::string bits(" 32bit"); +#else + std::string bits(""); +#endif + #if defined(__GNUG__) && !defined(__clang__) - std::string compiler_info( "GCC " + std::string(TOSTRING(__VERSION__)) ); + std::string compiler_info( "GCC " + std::string(TOSTRING(__VERSION__)) + bits); #elif defined(_MSC_VER) - std::string compiler_info( "MSVC " + std::string(TOSTRING(_MSC_FULL_VER)) ); + std::string compiler_info( "MSVC " + std::string(TOSTRING(_MSC_FULL_VER)) + bits); #elif defined(__clang__) - std::string compiler_info( "Clang " + std::string(TOSTRING(__clang_version__)) ); + std::string compiler_info( "Clang " + std::string(TOSTRING(__clang_version__)) + bits); #else std::string compiler_info( "unknown compiler" ); #endif @@ -80,6 +88,7 @@ std::string LibraryInfo::info() const char *env_font_path = getenv("OPENSCAD_FONT_PATH"); s << "OpenSCAD Version: " << TOSTRING(OPENSCAD_VERSION) + << "\nSystem information: " << PlatformUtils::sysinfo() << "\nCompiler, build date: " << compiler_info << ", " << __DATE__ << "\nBoost version: " << BOOST_LIB_VERSION << "\nEigen version: " << EIGEN_WORLD_VERSION << "." << EIGEN_MAJOR_VERSION << "." << EIGEN_MINOR_VERSION diff --git a/src/PlatformUtils-mac.mm b/src/PlatformUtils-mac.mm index cb93e522..45157921 100644 --- a/src/PlatformUtils-mac.mm +++ b/src/PlatformUtils-mac.mm @@ -1,5 +1,8 @@ #include "PlatformUtils.h" #import +#include +#include +#include std::string PlatformUtils::pathSeparatorChar() { @@ -35,5 +38,33 @@ unsigned long PlatformUtils::stackLimit() return STACK_LIMIT_DEFAULT; } +std::string PlatformUtils::sysinfo() +{ + std::string result; + + result += "Mac OS X "; + result += [[[NSProcessInfo processInfo] operatingSystemVersionString] UTF8String]; + + int mib[2]; + int64_t physical_memory; + int32_t numcpu; + size_t length64 = sizeof(int64_t); + size_t length32 = sizeof(int32_t);; + + sysctlbyname("hw.memsize", &physical_memory, &length64, NULL, 0); + sysctlbyname("hw.physicalcpu", &numcpu, &length32, NULL, 0); + + result += " "; + result += boost::lexical_cast(numcpu); + result += " CPU"; + if (numcpu > 1) result += "s"; + + result += " "; + result += PlatformUtils::toMemorySizeString(physical_memory, 2); + result += " RAM"; + + return result; +} + void PlatformUtils::ensureStdIO(void) {} diff --git a/src/PlatformUtils-posix.cc b/src/PlatformUtils-posix.cc index 3854a5e7..c3767fa7 100644 --- a/src/PlatformUtils-posix.cc +++ b/src/PlatformUtils-posix.cc @@ -1,4 +1,13 @@ +#include +#include +#include +#include #include +#include + +#include +#include +#include #include "PlatformUtils.h" #include "boosty.h" @@ -60,5 +69,109 @@ unsigned long PlatformUtils::stackLimit() return STACK_LIMIT_DEFAULT; } +static std::string readText(const std::string &path) +{ + std::ifstream s(path.c_str()); + s.seekg(0, std::ios::end); + if (s.fail() || s.tellg() > 4096) { + return ""; + } + s.seekg(0, std::ios::beg); + + std::string text((std::istreambuf_iterator(s)), std::istreambuf_iterator()); + return text; +} + +/** + * Check /etc/os-release as defined by systemd. + * @see http://0pointer.de/blog/projects/os-release.html + * @see http://www.freedesktop.org/software/systemd/man/os-release.html + * @return the PRETTY_NAME from the os-release file or an empty string. + */ +static std::string checkOsRelease() +{ + std::string os_release(readText("/etc/os-release")); + + boost::smatch results; + boost::regex pretty_name("^PRETTY_NAME=\"([^\"]+)\""); + if (boost::regex_search(os_release, results, pretty_name)) { + return results[1]; + } + + return ""; +} + +static std::string checkEtcIssue() +{ + std::string issue(readText("/etc/issue")); + + boost::regex nl("\n.*$"); + issue = boost::regex_replace(issue, nl, ""); + boost::regex esc("\\\\."); + issue = boost::regex_replace(issue, esc, ""); + boost::algorithm::trim(issue); + + return issue; +} + +static std::string detectDistribution() +{ + std::string osrelease = checkOsRelease(); + if (!osrelease.empty()) { + return osrelease; + } + + std::string etcissue = checkEtcIssue(); + if (!etcissue.empty()) { + return etcissue; + } + + return ""; +} + +std::string PlatformUtils::sysinfo() +{ + std::string result; + + struct utsname osinfo; + if (uname(&osinfo) == 0) { + result += osinfo.sysname; + result += " "; + result += osinfo.release; + result += " "; + result += osinfo.version; + result += " "; + result += osinfo.machine; + } else { + result += "Unknown Linux"; + } + + long numcpu = sysconf(_SC_NPROCESSORS_ONLN); + if (numcpu > 0) { + result += " "; + result += boost::lexical_cast(numcpu); + result += " CPU"; + if (numcpu > 1) { + result += "s"; + } + } + + long pages = sysconf(_SC_PHYS_PAGES); + long pagesize = sysconf(_SC_PAGE_SIZE); + if ((pages > 0) && (pagesize > 0)) { + result += " "; + result += PlatformUtils::toMemorySizeString(pages * pagesize, 2); + result += " RAM"; + } + + std::string distribution = detectDistribution(); + if (!distribution.empty()) { + result += " "; + result += distribution; + } + + return result; +} + void PlatformUtils::ensureStdIO(void) {} diff --git a/src/PlatformUtils-win.cc b/src/PlatformUtils-win.cc index c83855d0..1f07b683 100644 --- a/src/PlatformUtils-win.cc +++ b/src/PlatformUtils-win.cc @@ -98,6 +98,96 @@ unsigned long PlatformUtils::stackLimit() return STACK_LIMIT_DEFAULT; } +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); + +// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms684139%28v=vs.85%29.aspx +static BOOL IsWow64() +{ + BOOL bIsWow64 = FALSE; + + //IsWow64Process is not available on all supported versions of Windows. + //Use GetModuleHandle to get a handle to the DLL that contains the function + //and GetProcAddress to get a pointer to the function if available. + LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process"); + + if (NULL != fnIsWow64Process) { + if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) + { + return false; + } + } + return bIsWow64; +} + +std::string PlatformUtils::sysinfo() +{ + std::string result; + + OSVERSIONINFOEX osinfo; + osinfo.dwOSVersionInfoSize = sizeof(osinfo); + if (GetVersionEx((OSVERSIONINFO*)&osinfo) == 0) { + result += "Unknown Windows"; + } else { + unsigned int version = osinfo.dwMajorVersion * 1000 + osinfo.dwMinorVersion; + if (osinfo.dwPlatformId == VER_PLATFORM_WIN32_NT) { + switch (version) { + case 5000: + result += "Windows 2000"; + break; + case 5001: + result += "Windows XP"; + break; + case 5002: + result += "Windows Server 2003"; + break; + case 6000: + result += (osinfo.wProductType == VER_NT_WORKSTATION ? "Windows Vista" : "Windows Server 2008"); + break; + case 6001: + result += (osinfo.wProductType == VER_NT_WORKSTATION ? "Windows 7" : "Windows Server 2008 R2"); + break; + case 6002: + result += (osinfo.wProductType == VER_NT_WORKSTATION ? "Windows 8" : "Windows Server 2012"); + break; + case 6003: + // For applications that have been manifested for Windows 8.1. + result += (osinfo.wProductType == VER_NT_WORKSTATION ? "Windows 8.1" : "Windows Server 2012 R2"); + break; + } + boost::format fmt(" (v%d.%d)"); + fmt % osinfo.dwMajorVersion % osinfo.dwMinorVersion; + result += fmt.str(); + } else { + boost::format fmt("Unknown Windows (dwPlatformId = %d, dwMajorVersion = %d, dwMinorVersion = %d"); + fmt % osinfo.dwPlatformId % osinfo.dwMajorVersion % osinfo.dwMinorVersion; + result += fmt.str(); + } + } + + SYSTEM_INFO systeminfo; + bool isWow64 = IsWow64(); + if (isWow64) { + GetNativeSystemInfo(&systeminfo); + } else { + GetSystemInfo(&systeminfo); + } + + int numcpu = systeminfo.dwNumberOfProcessors; + boost::format fmt(" %d CPU%s%s"); + fmt % numcpu % (numcpu > 1 ? "s" : "") % (isWow64 ? " WOW64" : ""); + result += fmt.str(); + + MEMORYSTATUSEX memoryinfo; + memoryinfo.dwLength = sizeof(memoryinfo); + if (GlobalMemoryStatusEx(&memoryinfo) != 0) { + result += " "; + result += PlatformUtils::toMemorySizeString(memoryinfo.ullTotalPhys, 2); + result += " RAM"; + } + + return result; +} + #include #include #include diff --git a/src/PlatformUtils.cc b/src/PlatformUtils.cc index 2ebc9950..a15a0a3c 100644 --- a/src/PlatformUtils.cc +++ b/src/PlatformUtils.cc @@ -1,4 +1,5 @@ #include +#include #include "PlatformUtils.h" @@ -190,3 +191,25 @@ int PlatformUtils::setenv(const char *name, const char *value, int overwrite) return ::setenv(name, value, overwrite); #endif } + +std::string PlatformUtils::toMemorySizeString(unsigned long bytes, int digits) +{ + static const char *units[] = { "B", "kB", "MB", "GB", "TB", NULL }; + + int idx = 0; + double val = bytes; + while (true) { + if (val < 1024.0) { + break; + } + if (units[idx + 1] == NULL) { + break; + } + idx++; + val /= 1024.0; + } + + boost::format fmt("%f %s"); + fmt % boost::io::group(std::setprecision(digits), val) % units[idx]; + return fmt.str(); +} diff --git a/src/PlatformUtils.h b/src/PlatformUtils.h index a5c2ec91..5210dc85 100644 --- a/src/PlatformUtils.h +++ b/src/PlatformUtils.h @@ -34,6 +34,20 @@ namespace PlatformUtils { std::string backupPath(); bool createBackupPath(); + /** + * Return a human readable text describing the operating system + * the application is currently running on. This is mainly intended + * to provide information for bug reports (e.g. to be included in + * the LibraryInfoDialog). + * + * If there is some error to retrieve the details, at least the + * OS type is reported based on what platform the application was + * built for. + * + * @return system information. + */ + std::string sysinfo(); + /** * Platform abstraction to set environment variables. Windows/MinGW * does not support setenv(), but needs _putenv(). @@ -65,4 +79,10 @@ namespace PlatformUtils { * Currently limited to MS Windows GUI application console only. */ void ensureStdIO(void); + + /** + * Convert the number of bytes to a human readable string with + * a given number of digits. + */ + std::string toMemorySizeString(unsigned long bytes, int digits); }