[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