Làm cách nào để xác định nền tảng / trình biên dịch từ các macro tiền xử lý?


115

Tôi đang viết mã đa nền tảng, mã này sẽ được biên dịch trên linux, windows, Mac OS. Trên windows, tôi phải hỗ trợ visual studio và mingw.

Có một số đoạn mã dành riêng cho nền tảng mà tôi nên đặt trong #ifdef .. #endifmôi trường. Ví dụ, ở đây tôi đã đặt mã cụ thể của win32:

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

Nhưng làm cách nào để nhận ra Linux và mac OS? Tôi nên sử dụng tên định nghĩa (hoặc v.v.) là gì?



Bản dupe có một câu trả lời được chấp nhận tốt hơn nhiều.
rubenvb

1
Câu hỏi trùng lặp được đề xuất KHÔNG phải là câu hỏi tương tự. Câu hỏi đó chỉ hỏi về việc xác định hệ điều hành, trong khi câu hỏi này cũng hỏi về việc xác định trình biên dịch, một điều rất khác.
JB Bentley

@JB Bentley tuy nhiên câu trả lời được chấp nhận thậm chí không đề cập đến trình biên dịch và chỉ nói về hệ điều hành (và một "nền tảng"). Chưa kể đó là một câu trả lời khủng khiếp so với những gì mà bản dupe phải cung cấp.
rubenvb

1
@rubenvb Sau đó, liên kết câu hỏi khác dưới dạng nhận xét. Chỉ vì nó có một câu trả lời tốt hơn, không làm cho nó bị trùng lặp. Câu hỏi là yếu tố quyết định xem nó có trùng lặp hay không, không phải là các câu trả lời. Việc đóng câu hỏi này chỉ đảm bảo rằng chúng tôi sẽ không bao giờ nhận được câu trả lời chất lượng tốt cho phần liên quan đến trình biên dịch của câu hỏi, điều mà cái gọi là "bản sao" không bao giờ có thể trả lời.
JB Bentley

Câu trả lời:


133

Đối với Mac OS :

#ifdef __APPLE__

Đối với MingW trên Windows:

#ifdef __MINGW32__

Đối với Linux :

#ifdef __linux__

Đối với các trình biên dịch Windows khác, hãy kiểm tra luồng nàyđiều này cho một số trình biên dịch và kiến ​​trúc khác.


2
__APPLE__phân biệt giữa OSX và iOS không?
gman

14
__APPLE__được đặt cho cả OS X và iOS. Bạn có thể #include <TargetConditionals.h>bên trong #ifdef __APPLE__, mà sau đó cung cấp cho bạn một TARGET_OS_IPHONE #define.
Ted Mielczarek

2
__MINGW64__cũng có sẵn khi một công dụng mingw64
bánh nướng

2
__MINGW64__được tham chiếu, nên nghĩ rằng _MSC_VERWindows / MSVC đáng được đề cập (cũng có thể được sử dụng để kiểm tra Phiên bản MSVC).
ideaman42

Tôi xin lỗi, nhưng câu trả lời này khá sai trên tất cả các tài khoản và thậm chí không trả lời câu hỏi.
rubenvb

59

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

Dự án này cung cấp một danh sách toàn diện hợp lý #definesvề nhiều hệ điều hành, trình biên dịch, các tiêu chuẩn ngôn ngữ và nền tảng cũng như các thư viện tiêu chuẩn.


5
Kể từ phiên bản 1.55, Predef hiện đã được đưa vào Thư viện Boost C ++ .
rvalue

Tôi biết các quy tắc khác nhau khi bạn đăng bài này, nhưng tôi sẽ phải yêu cầu bạn chỉnh sửa bài đăng này để bao gồm các chi tiết phù hợp hơn. Hiện tại, các câu trả lời chỉ liên kết trong một ngày rất không được khuyến khích và tôi muốn cho bạn cơ hội lưu bài đăng này trước khi xóa nó.
Mick MacCallum

1
Vì đây là câu trả lời duy nhất thực sự trả lời cho câu hỏi như đã nêu trong tiêu đề và câu hỏi rất chung chung và có liên quan, tôi thực sự khuyên bạn không nên xóa nó. Tôi cũng sẽ không gọi đó là câu trả lời "chỉ liên kết".
hobb

2
@ 0x7fffffff: Mọi người sẽ có lợi gì khi sao chép nội dung của các câu trả lời khác vào câu trả lời này? Nếu bạn tin rằng việc có một câu trả lời dứt khoát thực sự quan trọng, thì có lẽ bạn nên tự tạo một câu trả lời như vậy (không khó lắm: chỉ cần kết hợp các câu trả lời hiện có lại với nhau theo một số thứ tự hợp lý). Cá nhân tôi có nhiều việc tốt hơn để làm với thời gian của mình, nhưng với tư cách là một người điều hành rõ ràng SO quan trọng với bạn hơn đối với tôi.
John Bartholomew

47

Đây là những gì tôi sử dụng:

#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

CHỈNH SỬA: Mặc dù những điều trên có thể phù hợp với những điều cơ bản, hãy nhớ xác minh xem bạn muốn kiểm tra macro nào bằng cách xem các trang tham khảo Boost.Predef . Hoặc chỉ sử dụng Boost.Predef trực tiếp.


4
sử dụng __linux __ thay vào đó, linux không được xác định khi biên dịch với GCC với phần mở rộng GNU bị tắt (tức là -std = c ++ 0x)
Erbureth cho biết Phục hồi Monica

1
@Erbureth Đã sửa, nhưng người ta thực sự nên sử dụng predef.sourceforge.net/index.php như trong câu trả lời được xếp hạng cao nhất.
rubenvb

@rubenvb: đúng vậy. Và nó vẫn còn quá ít phiếu bầu, tôi nghĩ vậy :) ... Tôi đã vào trang của họ rất nhiều lần.
0xC0000022L

Đối với tính nhất quán (có lẽ hơi phức tạp): #ifcâu hỏi đầu tiên nếu được định nghĩa, những câu hỏi khác kiểm tra giá trị. Tôi nghĩ nếu có thể làm nhất quán hơn #elif defined(__unix__) , v.v.
leonbloy

20

Nếu bạn đang viết C ++, tôi không thể khuyên bạn nên sử dụng các thư viện Boost đủ mạnh.

Phiên bản mới nhất (1.55) bao gồm một thư viện Predef mới bao gồm chính xác những gì bạn đang tìm kiếm , cùng với hàng chục macro nhận dạng nền tảng và kiến ​​trúc khác.

#include <boost/predef.h>

// ...

#if BOOST_OS_WINDOWS

#elif BOOST_OS_LINUX

#elif BOOST_OS_MACOS

#endif

Cho rằng đây là sự thúc đẩy, giải pháp này sẽ hoạt động trên các nền tảng / hệ điều hành khác nhau VÀ các trình biên dịch khác nhau.
Trevor Boyd Smith

3
"Tôi không thể khuyên bạn nên sử dụng các thư viện Boost đủ mạnh ...." - Tôi đã đánh giá Boost ba lần. Nó không thể vượt qua đánh giá ... Hầu hết các báo cáo lỗi đều may mắn nếu chúng được công nhận. Thiếu sự thừa nhận chỉ ra các vấn đề sâu hơn trong quá trình kỹ thuật. Tôi tin rằng macro của bộ xử lý trước và được xây dựng trong Thư viện chuẩn C ++ là lựa chọn an toàn hơn.
jww
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.