[Development] better compile-time os detection

EXT Tim Blechmann tim.blechmann at qt.io
Tue Jul 21 06:45:02 CEST 2026


working on some way of OS detection without preprocessor, there are a 
few shortcomings of QOperatingSystemVersion::OSType: most notably, it's 
impossible to dispatch linux-specific code, as there is no OSType::Linux 
(by design, as Android/OHOS are linux based as well). thiago recommended 
to discuss this on the list.

some options:

----

A: extending the current state
Add OSType::Linux (which implies, not Android / OHOS). easiest, least 
amount of code touched

----

B: map OS defines to constexpr bool variables
qt's preprocessor defines can only be used on the preprocessor, but we 
could map all Q_OS_XXX defines. easily done, we'd get something like:
```
namespace Qt::Cfg::Os {
inline constexpr bool isLinux = true;
inline constexpr bool isAndroid = true;
}
```
would also work for other preprocessor defines
----

C: separate "OS" from "Platform"
one could treat Android or OHOS as "platform" rather than "operating 
system". this is how boost.predef handles android for example:
https://www.boost.org/doc/libs/latest/libs/predef/doc/index.html#_using_the_predefs

----

D: separate "OS" from "OS family"
if we introduce a concept of "OS family", one could group, e.g. linux, 
android, ohos as one "linux family", like one could treat 
ios/ipados/visionos/tvos/watchos as "ios family"

----

E: tag hierarchy
as extension to the "os family" idea, we could introduce some form of 
hierarchical tag structs:
```
namespace Qt::Cfg::Os {

struct Unix_t{};
constexpr Unix_t Unix;

struct Linux_t : Unix_t{};
constexpr Unix_t Unix;

struct Android_t : Linux_{};
constexpr Android_t Android;

struct OHOS_t : Linux_{};
constexpr OHOS_t OHOS;

#if Q_OS_ANDROID
constexpr Current = Android;
using Current_t = Android_t;
[snip]
#endif

constexpr bool isLinux = std::is_base_of<Linux, Current_t>;
}
```
tag hierarchies have the advantage that they can express more complex 
hierarchies. downstream code would could use those within `if 
constexpr`, but could also use them to dispatch via template args 
(`makeOsSpecific<Cfg::Os::Current_t>()`) or tag arguments 
(`makeOsSpecific(Cfg::Os::Current)`). it's a bit more complex to 
maintain, though

----

thoughts?


More information about the Development mailing list