how to include files to qt project depending on target operating system



  • Hello everyone, I have received pretty good answers the last time I posted a question so I try again :)

    What I did so far:
    I deployed a Qt console application to an Android device and therefore had to adjust some header/source files in regard to ZeroConfServices. What I want to do is to load the right files depending on the targeted operating system.

    Currently, all headers and sources are added to the project in the .pro file. For each target OS a .pri file is included for further specifications. In there I would like to header/source files. Currently I have f.e. a so_mainwindow.h for linux and a so_mainwindow_android.h for android with modifications.

    #-------------------------------------------------
    #
    # Project created by QtCreator 2015-08-05T09:13:57
    #
    #-------------------------------------------------
    
    QT       += core gui
    QT       += network widgets
    
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    TARGET = sozius-client
    TEMPLATE = app
    DEFINES = QZEROCONF_STATIC
    
    CONFIG += c++11
    CONFIG += thread
    CONFIG += warn_on
    CONFIG(debug, debug|release) {
        DESTDIR = ../build/$$QMAKE_HOST.os/debug
    
        # Enable myMessageHandler!
        DEFINES += G_DEBUG_FLAG
    }
    CONFIG(release, debug|release) {
        DESTDIR = ../build/$$QMAKE_HOST.os/release
    }
    
    OBJECTS_DIR = $$DESTDIR/.obj
    MOC_DIR = $$DESTDIR/.moc
    RCC_DIR = $$DESTDIR/.qrc
    UI_DIR = $$DESTDIR/.u
    
    SOURCES += main.cpp\
        so_mainwindow.cpp \
        so_settingsdialog.cpp \
        so_soziuscentral.cpp \
        so_sslclient.cpp \
        so_logfiledialog.cpp \
        so_comhandler.cpp \
        so_changepwdialog.cpp \
        so_pwdialog.cpp \
        chunks.cpp \
        commands.cpp \
        qhexedit.cpp \
        so_infotab.cpp \
        so_certdialog.cpp \
        so_infograph.cpp \
        so_changedevnamedialog.cpp \
        so_filetab.cpp \
        so_treebuttondelegate.cpp \
        so_serverinputbar.cpp \
        so_memdumpdialog.cpp \
        so_infograph_p.cpp \
        so_infograph_p_ios.cpp \
        so_infotabmemory.cpp \
        so_infotabenv.cpp \
        so_infotabver.cpp \
        so_infotabzynq.cpp \
        so_infotabmod.cpp \
        so_infotabsettings.cpp \
        so_iotesttab.cpp \
        so_scriptstab.cpp \
        so_dynamictab.cpp \
        so_ethernettab.cpp \
        so_qwtplot.cpp \
        so_macwidget.cpp \
        so_macwidgetdelegate.cpp \
        so_leptontab.cpp \
        so_packgenwidget.cpp \
        so_cryptowidget.cpp \
        so_cryptotab.cpp \
        so_packgenwidgetdelegate.cpp \
        so_leptondialog.cpp \
        so_leptonle.cpp \
        so_devicetab.cpp \
        so_jtagtab.cpp \
        so_helpbrowser.cpp \
        so_filetabloaddelegate.cpp \
        so_filetablocaldelegate.cpp \
        so_scannertab.cpp \
        so_prostab.cpp
    
    
    
    HEADERS  += so_mainwindow.h \
        so_settingsdialog.h \
        so_soziuscentral.h \
        so_sslclient.h \
        so_logfiledialog.h \
        so_globals.h \
        so_comhandler.h \
        so_changepwdialog.h \
        so_pwdialog.h \
        commands.h \
        qhexedit.h \
        chunks.h \
        so_infotab.h \
        so_certdialog.h \
        so_infograph.h \
        so_changedevnamedialog.h \
        so_filetab.h \
        so_treebuttondelegate.h \
        so_serverinputbar.h \
        so_memdumpdialog.h \
        so_infograph_p.h \
        so_scannertab.h \
        so_infotabmemory.h \
        so_infotabenv.h \
        so_infotabver.h \
        so_infotabzynq.h \
        so_infotabmod.h \
        so_infotabsettings.h \
        so_iotesttab.h \
        so_dynamictab.h \
        so_scriptstab.h \
        so_ethernettab.h \
        so_jtagtab.h \
        so_qwtplot.h \
        so_macwidget.h \
        so_macwidgetdelegate.h \
        so_leptontab.h \
        so_packgenwidget.h \
        so_cryptowidget.h \
        so_cryptotab.h \
        so_packgenwidgetdelegate.h \
        so_leptondialog.h \
        so_leptonle.h \
        so_devicetab.h \
        so_devicetabpos.h \
        so_helpbrowser.h \
        so_filetabloaddelegate.h \
        so_filetablocaldelegate.h \
        so_prostab.h
    
    
    RESOURCES += \
        so_resources.qrc
    
    DISTFILES += \
        protocol.proto
    
    # Includes
    include(win.pri)
    include(mac.pri)
    include(linux.pri)
    include(ios.pri)
    include(android.pri)
    PROTOS = protocol.proto
    include(protobuf.pri)
    include(qtzeroconf/qtzeroconf.pri)
    
    contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
        ANDROID_EXTRA_LIBS = \
            /media/qt5-qwt6/so_socius/aso1_dbl1/software/qt/qt55/client_withoutbonjour/../../../../../../qwt_android/qwt-6.1.3/lib/libqwt.so \
            /media/qt5-qwt6/so_socius/aso1_dbl1/software/qt/qt55/client_withoutbonjour/../../../../../../../../home/staff/Qt5.8.0/5.8/android_armv7/lib/libQt5PrintSupport.so \
            /media/qt5-qwt6/so_socius/aso1_dbl1/software/qt/qt55/client_withoutbonjour/../../../../../../../../home/staff/Qt5.8.0/5.8/android_armv7/lib/libQt5OpenGL.so \
            /media/qt5-qwt6/so_socius/aso1_dbl1/software/qt/qt55/client_withoutbonjour/../../../../../../../../home/staff/Qt5.8.0/5.8/android_armv7/lib/libQt5Concurrent.so \
            /media/qt5-qwt6/so_socius/aso1_dbl1/software/qt/qt55/client_withoutbonjour/../../../../../../../../home/staff/Desktop/protobuf/protobuf-2.5.0/dynamic/lib/libprotobuf.so \
            $$PWD/../../../../../../../../home/staff/Desktop/openssl_android/libcrypto.so \
            $$PWD/../../../../../../../../home/staff/Desktop/openssl_android/libssl.so
    }
    
    

    Here is for Linux my .pri file:

    linux {
    message(Building for Linux - $$_DATE_)
    
    #ID's
    _BUILD_ID = $$system("$$PWD/../scripts/source_id_linux.sh client_source")
    _PROTOC_ID = $$system("$$PWD/../scripts/source_id_linux.sh proto")
    
    equals(_BUILD_ID, "") {
        error("BUILD_ID not set, check source_id scripts")
    }
    equals(_PROTOC_ID, "") {
        error("PROTOC_ID not set, check source_id scripts")
    }
    
    DEFINES += "BUILD_ID=\\\"$$_BUILD_ID"\\\"
    DEFINES += "PROTOC_ID=\\\"$$_PROTOC_ID"\\\"
    
    #Add Qwt support
    include("/media/qt5-qwt6/features/qwt.prf")
    
    #Adding Bonjour/Avai support
    LIBS += -ldns_sd
    
    #Protobuf support
    LIBS += -lprotobuf
    message(Building for Linux);
    
    #Install Files (use: make install)
    INSTALLDIR = $$DESTDIR/$$QMAKE_HOST.os
    
    instA.path = $$INSTALLDIR/
    instA.files += $$[QT_INSTALL_LIBS]/libQt5Concurrent.so.5
    instA.files += $$[QT_INSTALL_LIBS]/libQt5Core.so.5
    instA.files += $$[QT_INSTALL_LIBS]/libQt5DBus.so.5
    instA.files += $$[QT_INSTALL_LIBS]/libQt5Gui.so.5
    instA.files += $$[QT_INSTALL_LIBS]/libQt5Network.so.5
    instA.files += $$[QT_INSTALL_LIBS]/libQt5OpenGL.so.5
    instA.files += $$[QT_INSTALL_LIBS]/libQt5PrintSupport.so.5
    instA.files += $$[QT_INSTALL_LIBS]/libQt5Svg.so.5
    instA.files += $$[QT_INSTALL_LIBS]/libQt5Widgets.so.5
    instA.files += $$[QT_INSTALL_LIBS]/libQt5XcbQpa.so.5
    
    instB.path += $$INSTALLDIR/platforms/
    instB.files += $$[QT_INSTALL_PLUGINS]/platforms/libqxcb.so
    
    //instC.path += $$INSTALLDIR/
    instC.files += $$QWT_INSTALL_LIBS/libqwt.so.6
    
    instD.path += $$INSTALLDIR/
    instD.files += /usr/lib64/libprotobuf.so
    
    instE.path += $$INSTALLDIR/
    instE.files += additional/sozius-client.sh
    instE.files += additional/howTo.txt
    
    instF.path = $$INSTALLDIR/doc/
    instF.files = doc/*
    
    instG.path = $$INSTALLDIR/LICENSE/
    instG.files = LICENSE/*
    
    target.path += $$INSTALLDIR/
    
    INSTALLS += instA instB instC instD instE instF instG target
    
    #Clean Files (use: make distclean)
    QMAKE_DISTCLEAN += -r $$DESTDIR
    }
    

    How can I e.g. specify different paths that files with the same file name but different content are loaded? Or can I put into the files some distinction between Android code and Linux code?

    Thank you for your ideas!


  • Lifetime Qt Champion

    Hi,

    If you have only minor changes between platforms, why not use the Q_OS_XXX macros like Q_OS_LINUX ?



  • @SGaist I have never heard of these macros before. I will try it in my code but it seems a good solution for my problem at first glance. Thank you!



  • @a_so

    I believe you can use these macros only inside of your classes and not in the project file itself. But I might be mistaken.

    To differ between OS inside the project file I usually use these:

    • win32
    • macx
    • unix

    eg:

    win32:DEFINES += QT_DLL
    
    macx:debug {
        HEADERS += debugging.h
    }
    
    win32|macx {
        HEADERS += debugging.h
    }
    

    Taken from the docu here:


  • Lifetime Qt Champion

    @J-Hilk Indeed, that's the goal of these macros. The suggestion was that you don't necessarily need to have one file per platform every time there's a small change to adapt to that platform. There should be a balance between the platform specific macros in code and write platform specific files when the code is too big or too involved to fit nicely between macro guards.



  • @SGaist ah, ok, that makes total sence now. And in fact I do use those macros myself in my classes on a regular base.

    It's just the docu about qmake could really use an update!
    Just recently I searched through there to find out, how to automatically link precompiled libaries depending on the compiler set/used for my project.

    Eventually I found that information, but it took way to long to find, for such an easy solution.


  • Lifetime Qt Champion

    Documentation can always be improved ;)

    If you find something unclear or hard to find, you can contribute an update that will make everyone's life easier. All the documentation is within Qt source tree so you're welcome to improve it and submit a patch :)



  • So far I tried the Q_OS_xxx Macros within my source and header files. It works fine! Thank you!
    However, qmake recognizes my host OS (Linux) before it actually catches that my target OS is Android. I moved Bonjour related files into the .pri files and therefore these files are added to the project although I do not want them there.
    I will try the solution from @J-Hilk the next days. I think it can solve my problems.

    I am curious, how can I remove files from a project within my .pri files?


  • Lifetime Qt Champion

    Remove ? Usually you use scopes in your .pro or .pri file to add files to build for the platforms you are currently working on.



  • My solution is:
    I added all header and source files in the .pro file and for Android I removed conflicting files in android.pri file with

    HEADERS -= ...
    SOURCES -= ...
    

    Thanks a lot for your solutions!


  • Lifetime Qt Champion

    That's pretty counter intuitive and a maintenance nightmare in the making.

    Why not just have a scope in your .pro files that includes your android specific files when working on the android platform and the other files in the else statement ? i.e.

    android {
        SOURCES += android_stuff.cpp
        HEADERS += something.h
    } else {
        SOURCES += other_stuff.cpp
        HEADERS += something_else.h
    }
    

    From a maintainer point of view, removing files from the build system really doesn't make sense.


Log in to reply