Я в своих мелких проектах пишу примерно так (система сборки qbs):
Group {
name: "cpp_os_specific"
prefix: "src/cpp/utils/"
files: {
if (qbs.targetOS.contains("windows"))
return ["utils_windows.cpp", "utils.h"];
if (qbs.targetOS.contains("linux"))
return ["utils_linux.cpp", "utils.h"];
}
}
Соответственно при сборке на разных платформах просто используются разные файлы, никаких разных имён классов или
#if defined не нужно.
Насколько это может быть удобно/неудобно на больших проектах не знаю.
P.S.
По поводу qbs, к сожалению генератора проектов из Qt Creator, нет. По крайней мере раньше не было, я давно туда не заглядывал. Но если написать файл проекта руками то он нормально открывается в Qt Creator (qbs плагин обычно включён по умолчанию).
Пример файла сборки qbs:
spoilerimport qbs 1.0
Product {
type: "application"
name: "timer_qml"
consoleApplication: false
Group {
name: "cpp"
prefix: "src/cpp/"
files: ["*.cpp", "*.h"]
}
Group {
name: "cpp_os_specific"
prefix: "src/cpp/utils/"
files: {
if (qbs.targetOS.contains("windows"))
return ["utils_windows.cpp", "utils.h"];
if (qbs.targetOS.contains("linux"))
return ["utils_linux.cpp", "utils.h"];
}
}
Group {
name: "resources_and_qml"
prefix: "src/qrc/"
files: ["*.qrc", "*.qml"]
}
Depends {
name: "Qt"
submodules: {
if (qbs.targetOS.contains("windows"))
return ["core", "widgets", "gui", "sql", "quick", "qml"];
if (qbs.targetOS.contains("linux"))
return ["core", "widgets", "gui", "sql", "quick", "qml", "x11extras"];
}
}
Depends {
name: "cpp"
}
cpp.staticLibraries: {
if (qbs.targetOS.contains("windows"))
return ["user32"];
else
return [];
}
cpp.cxxFlags: {
if (qbs.toolchain.contains("gcc") || qbs.toolchain.contains("mingw"))
return ["-std=c++11"];
else
return [];
}
cpp.dynamicLibraries: {
if (qbs.targetOS.contains("linux"))
return ["Xss", "X11"];
else
return [];
}
Group {
name: "App itself"
fileTagsFilter: parent.type
qbs.install: true
qbs.installDir: "bin"
}
}
По официальной
документации можно за пару вечеров освоить.