كيف يمكنني التحقق من نظام التشغيل باستخدام توجيهات المعالج المسبق؟
-
02-07-2019 - |
سؤال
أحتاج إلى الكود الخاص بي للقيام بأشياء مختلفة بناءً على نظام التشغيل الذي يتم تجميعه عليه.أنا أبحث عن شيء مثل هذا:
#ifdef OSisWindows
// do Windows-specific stuff
#else
// do Unix-specific stuff
#endif
هل هناك طريقة للقيام بذلك؟هل هناك طريقة أفضل لفعل الشيء نفسه؟
المحلول
ال وحدات الماكرو المحددة مسبقًا لنظام التشغيل يحتوي الموقع على قائمة كاملة جدًا من الشيكات.فيما يلي عدد قليل منها، مع روابط لمكان العثور عليها:
شبابيك
_WIN32
كلا 32 بت و 64 بت
_WIN64
64 بت فقط
يونكس (لينكس، *BSD، نظام التشغيل Mac OS X)
انظر الى هذا سؤال ذو صلة على بعض مخاطر استخدام هذا الفحص.
unix
__unix
__unix__
ماك أو إس إكس
__APPLE__
__MACH__
كلاهما محدد.التحقق من أي منهما يجب أن يعمل.
لينكس
__linux__
linux
قديم (غير متوافق مع POSIX)
__linux
قديم (غير متوافق مع POSIX)
فري بي إس دي
__FreeBSD__
نصائح أخرى
عرض تعريفات مجلس التعاون الخليجي على نظام التشغيل Windows:
gcc -dM -E - <NUL:
على لينكس:
gcc -dM -E - </dev/null
وحدات الماكرو المحددة مسبقًا في MinGW:
WIN32 _WIN32 __WIN32 __WIN32__ __MINGW32__ WINNT __WINNT __WINNT__ _X86_ i386 __i386
على أنظمة التشغيل UNIX:
unix __unix__ __unix
مرتكز على com.nadeausoftware و إجابة لامدا فيري.
#include <stdio.h>
/**
* Determination a platform of an operation system
* Fully supported supported only GNU GCC/G++, partially on Clang/LLVM
*/
#if defined(_WIN32)
#define PLATFORM_NAME "windows" // Windows
#elif defined(_WIN64)
#define PLATFORM_NAME "windows" // Windows
#elif defined(__CYGWIN__) && !defined(_WIN32)
#define PLATFORM_NAME "windows" // Windows (Cygwin POSIX under Microsoft Window)
#elif defined(__ANDROID__)
#define PLATFORM_NAME "android" // Android (implies Linux, so it must come first)
#elif defined(__linux__)
#define PLATFORM_NAME "linux" // Debian, Ubuntu, Gentoo, Fedora, openSUSE, RedHat, Centos and other
#elif defined(__unix__) || defined(__APPLE__) && defined(__MACH__)
#include <sys/param.h>
#if defined(BSD)
#define PLATFORM_NAME "bsd" // FreeBSD, NetBSD, OpenBSD, DragonFly BSD
#endif
#elif defined(__hpux)
#define PLATFORM_NAME "hp-ux" // HP-UX
#elif defined(_AIX)
#define PLATFORM_NAME "aix" // IBM AIX
#elif defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR == 1
#define PLATFORM_NAME "ios" // Apple iOS
#elif TARGET_OS_IPHONE == 1
#define PLATFORM_NAME "ios" // Apple iOS
#elif TARGET_OS_MAC == 1
#define PLATFORM_NAME "osx" // Apple OSX
#endif
#elif defined(__sun) && defined(__SVR4)
#define PLATFORM_NAME "solaris" // Oracle Solaris, Open Indiana
#else
#define PLATFORM_NAME NULL
#endif
// Return a name of platform, if determined, otherwise - an empty string
char *
get_platform_name() {
return (PLATFORM_NAME == NULL) ? "" : PLATFORM_NAME;
}
int main(int argc, char *argv[]) {
puts(get_platform_name());
return 0;
}
تم اختباره مع دول مجلس التعاون الخليجي ورن على:
- ديبيان 8
- ويندوز (مينغو)
- ويندوز (سيجوين)
في معظم الحالات، من الأفضل التحقق من وجود وظيفة معينة أم لا.على سبيل المثال:إذا كانت الوظيفة pipe()
موجود أم لا.
#ifdef _WIN32
// do something for windows like include <windows.h>
#elif defined __unix__
// do something for unix like include <unistd.h>
#elif defined __APPLE__
// do something for mac
#endif
يمكن العثور على وحدات الماكرو المحددة مسبقًا لمترجم Microsoft C/C++ (MSVC) هنا:
https://docs.microsoft.com/en-us/cpp/preprocessor/preتعريف-macros
أعتقد أنك تبحث عن:
_WIN32 - يتم تعريفه على أنه 1 عندما يكون هدف التحويل البرمجي هو 32 بت ARM، أو 64 بت ARM، أو x86، أو x64.وإلا غير محدد
_WIN64 - يتم تعريفه بالرقم 1 عندما يكون هدف التحويل البرمجي هو 64 بت ARM أو x64.وإلا غير محدد.
يمكن العثور على وحدات MACROs المحددة مسبقًا لمترجم gcc هنا:
أعتقد أنك تبحث عن:
__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
قم بإجراء بحث في Google عن المترجمين المناسبين المحددين مسبقًا.
لا يوجد ماكرو قياسي تم تعيينه وفقًا لمعيار C.سيقوم بعض مترجمي لغة C بتعيين واحد على بعض الأنظمة الأساسية (على سبيل المثال.تقوم مجموعة دول مجلس التعاون الخليجي المصححة من Apple بتعيين ماكرو للإشارة إلى أنه يتم تجميعها على نظام Apple ومنصة Darwin).قد يقوم النظام الأساسي الخاص بك و/أو مترجم C الخاص بك بتعيين شيء ما أيضًا، ولكن لا توجد طريقة عامة.
كما قال Hayalci، من الأفضل تعيين وحدات الماكرو هذه في عملية الإنشاء بطريقة أو بأخرى.من السهل تحديد ماكرو باستخدام معظم المترجمين دون تعديل الكود.يمكنك ببساطة المرور -D MACRO
إلى دول مجلس التعاون الخليجي، أي.
gcc -D Windows
gcc -D UNIX
وفي الكود الخاص بك:
#if defined(Windows)
// do some cool Windows stuff
#elif defined(UNIX)
// do some cool Unix stuff
#else
# error Unsupported operating system
#endif
في MinGW، ال _WIN32
تحديد الاختيار لا يعمل.وهنا الحل:
#if defined(_WIN32) || defined(__CYGWIN__)
// Windows (x86 or x64)
// ...
#elif defined(__linux__)
// Linux
// ...
#elif defined(__APPLE__) && defined(__MACH__)
// Mac OS
// ...
#elif defined(unix) || defined(__unix__) || defined(__unix)
// Unix like OS
// ...
#else
#error Unknown environment!
#endif
لمزيد من المعلومات يرجى النظر: https://sourceforge.net/p/predef/wiki/OperatingSystems/
يستخدم #define OSsymbol
و #ifdef OSsymbol
حيث OSsymbol هو #define
'رمز قادر على تحديد نظام التشغيل المستهدف الخاص بك.
عادةً ما تقوم بتضمين ملف رأس مركزي يحدد رمز نظام التشغيل المحدد واستخدام أدلة التضمين والمكتبة الخاصة بنظام التشغيل للتجميع والإنشاء.
لم تحدد بيئة التطوير الخاصة بك، ولكنني متأكد تمامًا من أن المترجم الخاص بك يوفر تعريفات عالمية للأنظمة الأساسية وأنظمة التشغيل الشائعة.
أنظر أيضا http://en.wikibooks.org/wiki/C_Programming/Preprocessor
فقط لتلخيص كل ذلك، إليك مجموعة من الروابط المفيدة.
- وحدات الماكرو المشتركة المحددة مسبقًا في دول مجلس التعاون الخليجي
- أنظمة التشغيل SourceForge المحددة مسبقًا
- MSDN وحدات الماكرو المحددة مسبقًا
- صفحة NaudeaSoftware المرتبطة كثيرًا
- ويكيبيديا !!!
- "نظرة عامة على وحدات الماكرو الخاصة بالمترجم المحددة مسبقًا للمعايير والمترجمين وأنظمة التشغيل وهندسة الأجهزة."
- "أنظمة التشغيل المتمايزة" الخاصة بـ FreeBSD
- جميع أنواع وحدات الماكرو المحددة مسبقًا
libportable
آسف على المرجع الخارجي، ولكن أعتقد أنه مناسب لسؤالك:
نصيحة C/C++:كيفية اكتشاف نوع نظام التشغيل باستخدام وحدات الماكرو المحددة مسبقًا للمترجم
سيقوم بعض المترجمين بإنشاء تعريفات يمكن أن تساعدك في هذا الأمر.اقرأ وثائق المترجم لتحديد ماهيتها. MSVC يحدد واحد هذا __WIN32__
, مجلس التعاون الخليجي لديه بعض يمكنك أن ترى مع touch foo.h; gcc -dM foo.h
يمكنك استخدام توجيهات المعالج مثل تحذير أو خطأ للتحقق في وقت الترجمة لا تحتاج إلى ذلك يجري هذا البرنامج على الإطلاق بكل بساطة ترجمة هو - هي .
#if defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__)
#error Windows_OS
#elif defined(__linux__)
#error Linux_OS
#elif defined(__APPLE__) && defined(__MACH__)
#error Mach_OS
#elif defined(unix) || defined(__unix__) || defined(__unix)
#error Unix_OS
#else
#error Unknown_OS
#endif
#include <stdio.h>
int main(void)
{
return 0;
}
لم أجد هايكو التعريف هنا.لكي يكون كاملا، تعريف Haiku-os بسيط __HAIKU__
يمكنك استخدام Boost.Predef
والذي يحتوي على العديد من وحدات الماكرو المحددة مسبقًا للنظام الأساسي المستهدف بما في ذلك نظام التشغيل.غالبًا ما يُنظر إلى Yes Boost على أنها مكتبة C++، ولكن هذه المكتبة عبارة عن رأس معالج مسبق يعمل مع لغة C أيضًا
تحدد هذه المكتبة مجموعة من المترجمات والهندسة المعمارية ونظام التشغيل والمكتبة وأرقام الإصدارات الأخرى من المعلومات التي يمكنها جمعها من وحدات الماكرو المحددة مسبقًا لـ C وC++ وObjective C وObjective C++ أو تلك المحددة في الرؤوس المتاحة بشكل عام.نشأت فكرة هذه المكتبة من اقتراح لتوسيع مكتبة Boost Config لتوفير معلومات أكثر وأكثر اتساقًا من تعريفات الميزات التي تدعمها.وما يلي هو نسخة منقحة من هذا الاقتراح الموجز.
على سبيل المثال
#include <boost/predef.h>
#if defined(BOOST_OS_WINDOWS)
#elif defined(BOOST_OS_ANDROID)
#elif defined(BOOST_OS_LINUX)
#elif defined(BOOST_OS_BSD)
...
#endif
لقد كتبت مكتبة صغيرة للحصول على نظام التشغيل الذي تستخدمه، يمكن تثبيته باستخدام clib (مدير الحزم C)، لذلك من السهل حقًا استخدامه كتبعية لمشاريعك.
ثَبَّتَ
$ clib install abranhe/os.c
الاستخدام
#include <stdio.h>
#include "os.h"
int main()
{
printf("%s\n", operating_system());
// macOS
return 0;
}
تقوم بإرجاع سلسلة (char*
) باسم نظام التشغيل الذي تستخدمه، لمزيد من المعلومات حول هذا المشروع قم بمراجعته الوثائق على جيثب.