Bagaimana cara mengidentifikasi platform / kompiler dari makro preprocessor?

115

Saya sedang menulis kode lintas platform, yang harus dikompilasi di linux, windows, Mac OS. Di windows, saya harus mendukung studio visual dan mingw.

Ada beberapa bagian kode khusus platform, yang harus saya tempatkan di #ifdef .. #endiflingkungan. Misalnya, di sini saya menempatkan kode khusus win32:

#ifdef WIN32
#include <windows.h>
#endif

Tapi bagaimana cara mengenali linux dan mac OS? Apa definisi nama (atau dll.) Yang harus saya gunakan?

Arenim
sumber
3
Berikut adalah daftar definisi makro OS .
OCaml
Penipu memiliki jawaban yang lebih diterima.
rubenvb
1
Duplikat yang disarankan BUKAN pertanyaan yang sama. Pertanyaan itu hanya menanyakan tentang mengidentifikasi sistem operasi, sedangkan pertanyaan ini juga menanyakan tentang mengidentifikasi kompilator, yang merupakan hal yang sangat berbeda.
JBentley
@JBentley namun jawaban yang diterima bahkan tidak menyebutkan kompiler, dan hanya berbicara tentang OS (dan satu "platform"). Belum lagi itu jawaban yang buruk relatif terhadap apa yang ditawarkan oleh korban penipuan.
rubenvb
1
@rubenvb Kemudian tautkan pertanyaan lain sebagai komentar. Hanya karena memiliki jawaban yang lebih baik, tidak membuatnya menjadi duplikat. Pertanyaannya adalah apa yang menentukan apakah itu duplikat, bukan jawabannya. Menutup yang satu ini hanya memastikan kita tidak akan pernah mendapatkan jawaban yang berkualitas baik untuk bagian pertanyaan yang berhubungan dengan kompilator, yang disebut "duplikat" tidak akan pernah bisa menjawabnya.
JBentley

Jawaban:

133

Untuk Mac OS :

#ifdef __APPLE__

Untuk MingW di Windows:

#ifdef __MINGW32__

Untuk Linux :

#ifdef __linux__

Untuk kompiler Windows lainnya, periksa utas ini dan ini untuk beberapa kompiler dan arsitektur lainnya.

karlphillip.dll
sumber
2
Apakah __APPLE__membedakan antara OSX dan iOS?
gman
14
__APPLE__disetel untuk OS X dan iOS. Anda bisa #include <TargetConditionals.h>masuk #ifdef __APPLE__, yang kemudian memberi Anda TARGET_OS_IPHONE #define.
Ted Mielczarek
2
__MINGW64__juga tersedia jika seseorang menggunakan mingw64
scone
2
Sejak __MINGW64__direferensikan, berpikir _MSC_VERuntuk Windows / MSVC layak disebutkan (yang juga dapat digunakan untuk memeriksa Versi MSVC).
ideasman42
Maaf, tapi jawaban ini cukup salah di semua akun dan bahkan tidak menjawab pertanyaannya.
rubenvb
59

Lihat: http://predef.sourceforge.net/index.php

Proyek ini menyediakan daftar lengkap yang ditentukan sebelumnya #definesuntuk banyak sistem operasi, penyusun, standar bahasa dan platform, dan pustaka standar.

John Bartholomew
sumber
5
Mulai versi 1.55, Predef sekarang disertakan dalam Pustaka Boost C ++ .
rvalue
Saya tahu aturannya berbeda ketika Anda memposting ini, tetapi saya harus meminta Anda untuk mengedit posting ini untuk memasukkan detail yang lebih relevan. Sekarang jawaban hanya tautan hari sangat tidak disarankan, dan saya ingin menawarkan Anda kesempatan untuk menyimpan posting ini sebelum dihapus.
Mick MacCallum
1
Karena ini adalah satu-satunya jawaban yang benar-benar menjawab pertanyaan seperti yang dinyatakan dalam judul, dan pertanyaannya sangat umum dan relevan, saya sangat menyarankan untuk tidak menghapusnya. Saya juga tidak akan menyebutnya sebagai jawaban "hanya tautan".
hobb
2
@ 0x7fffffff: Apa manfaat yang mungkin bagi siapa pun jika menduplikasi konten jawaban lain menjadi jawaban ini? Jika Anda yakin sangat penting untuk memiliki satu jawaban pasti, maka mungkin Anda harus membuat jawaban seperti itu sendiri (seharusnya tidak sulit: rekatkan saja jawaban yang ada dalam beberapa urutan yang masuk akal). Secara pribadi saya memiliki hal-hal yang lebih baik untuk dilakukan dengan waktu saya, tetapi sebagai moderator jelas SO lebih penting bagi Anda daripada bagi saya.
John Bartholomew
47

Inilah yang saya gunakan:

#ifdef _WIN32 // note the underscore: without it, it's not msdn official!
    // Windows (x64 and x86)
#elif __unix__ // all unices, not all compilers
    // Unix
#elif __linux__
    // linux
#elif __APPLE__
    // Mac OS, not sure if this is covered by __posix__ and/or __unix__ though...
#endif

EDIT: Meskipun hal di atas mungkin berfungsi untuk dasar-dasar, ingatlah untuk memverifikasi makro apa yang ingin Anda periksa dengan melihat halaman referensi Boost.Predef . Atau gunakan saja Boost.Predef secara langsung.

rubenvb.dll
sumber
4
gunakan __linux __ sebagai gantinya, linux tidak ditentukan saat mengkompilasi dengan GCC dengan ekstensi GNU dinonaktifkan (yaitu -std = c ++ 0x)
Erbureth mengatakan Reinstate Monica
1
@Erbureth Fixed, tetapi seseorang harus benar-benar menggunakan predef.sourceforge.net/index.php seperti pada jawaban berperingkat tertinggi.
rubenvb
@rubenvb: memang. Dan masih terlalu sedikit voting, kurasa :) ... Aku sudah berkali-kali membuka situs mereka.
0xC0000022L
Untuk konsistensi (mungkin sedikit berlebihan): pertanyaan pertama #ifjika ditentukan, yang lain menguji nilai. Jika akan lebih konsisten untuk dilakukan #elif defined(__unix__) , dll, saya pikir.
leonbloy
20

Jika Anda menulis C ++, saya tidak bisa merekomendasikan penggunaan pustaka Boost dengan cukup kuat.

Versi terbaru (1.55) menyertakan pustaka Predef baru yang mencakup persis apa yang Anda cari , bersama dengan lusinan platform lain dan makro pengenalan arsitektur.

#include <boost/predef.h>

// ...

#if BOOST_OS_WINDOWS

#elif BOOST_OS_LINUX

#elif BOOST_OS_MACOS

#endif
rvalue
sumber
Mengingat ini adalah peningkatan, solusi ini akan berfungsi pada platform / OS yang berbeda DAN kompiler yang berbeda.
Trevor Boyd Smith
3
"Saya tidak dapat merekomendasikan penggunaan pustaka Boost dengan cukup kuat ...." - Saya telah mengevaluasi Boost tiga kali. Itu tidak bisa lulus evaluasi ... Sebagian besar laporan bug beruntung jika diakui. Kurangnya pengakuan menunjukkan masalah yang lebih dalam dalam proses rekayasa. Saya percaya makro praprosesor dan pustaka standar C ++ bawaan adalah pilihan yang lebih aman.
jww