Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Setup QMake for a Qt library



  • Hello guys

    I am enjoying developing programs in Qt.
    After almost 2 years improving my design and sending programs out to customers I feel the need to start developing a library for commonly used functions.
    Making and using a library is easy enough using the wizard in Qt Creator, but I wish something more advance.

    I am using Qwt for several projects and I wish something like that. Multiple libraries that is compiled into a single .dll file, but the whole setup of QMake files seems complicated and I hoped for a simpler solution.

    Anyone who has any tips/guide or code examples that I can work from?

    Regards
    Sebastian Aslund


  • Lifetime Qt Champion

    Hi,

    Do you mean you would like to have a Qt module for your common stuff to use like e.g. QtGui ?



  • Heĺlo SGaist

    Yes, that would be the ideal goal. :)



  • Hello everyone

    I followed the qmake files in Qwt and I managed, I think, to make what I want. The only issue I have right now is that it seems to be a pain to add new project folder to the setup.
    Is my setup okay or could it be done better?

    What I want to avoid compared to Qwt is to have all my source and header files in one folder. I prefer every class to has it own sub-folder.

    My eeqt.pro file:

    ################################################################
    # EEQT Widget Library
    ################################################################
    
    include( eeqtconfig.pri )
    
    TEMPLATE = subdirs
    CONFIG += ordered
    
    SUBDIRS = \
    	src \
    	
    eeqtspec.files = eeqtconfig.pri eeqtfunctions.pri eeqt.prf
    eeqtspec.path = $${EEQT_INSTALL_FEATURES}
    
    INSTALLS += eeqtspec
    

    eeqtconfig.pri:

    ################################################################
    # EEQT Widget Library
    ################################################################
    
    EEQT_VER_MAJ			= 0
    EEQT_VER_MIN			= 0
    EEQT_VER_PAT			= 1
    EEQT_VERSION			= $${EEQT_VER_MAJ}.$${EEQT_VER_MIN}.$${EEQT_VER_PAT}
    
    ######################################################################
    # Install paths
    ######################################################################
    
    EEQT_INSTALL_PREFIX		= $$[QT_INSTALL_PREFIX]
    
    win32 {
            EEQT_INSTALL_PREFIX	= C:/EEQT-$${EEQT_VERSION}
    }
    
    EEQT_INSTALL_DOCS		= $${EEQT_INSTALL_PREFIX}/doc
    EEQT_INSTALL_HEADERS            = $${EEQT_INSTALL_PREFIX}/include
    EEQT_INSTALL_LIBS		= $${EEQT_INSTALL_PREFIX}/lib
    
    ######################################################################
    # Add features
    ######################################################################
    
    EEQT_INSTALL_FEATURES	= $${EEQT_INSTALL_PREFIX}/features
    
    ######################################################################
    # Add dynamic linking
    ######################################################################
    
    EEQT_CONFIG				+= EEQtDLL
    
    ######################################################################
    # Add EEQwtWidget
    ######################################################################
    
    EEQT_CONFIG				+= EEQwtWidget
    

    eeqtfunctions.pri:

    ################################################################
    # EEQT Widget Library
    ################################################################
    
    # Copied and modified from qwtfunctions.pri
    
    defineReplace(eeqtLibraryTarget) {
    
        unset(LIBRARY_NAME)
        LIBRARY_NAME = $$1
    
        contains(TEMPLATE, .*lib):CONFIG(debug, debug|release) {
    
            !debug_and_release|build_pass {
    
                mac:RET = $$member(LIBRARY_NAME, 0)_debug
                win32:RET = $$member(LIBRARY_NAME, 0)d
            }
        }
    
        isEmpty(RET):RET = $$LIBRARY_NAME
        return($$RET)
    }
    
    defineTest(eeqtAddLibrary) {
    
        LIB_PATH = $$1
        LIB_NAME = $$2
    
        mac:contains(QWT_CONFIG, QwtFramework) {
    
            LIBS      *= -F$${LIB_PATH}
        }
        else {
    
            unix:lessThan(QT_MAJOR_VERSION, 5) {
    
                # Many Linux distributions install Qwt in the same directory
                # as the Qt libs and thus we need to prepend the path for the local build
                # to avoid conflicting with the installed version.
                # Qt5 qmake appends ( instead of prepending ) the path to the Qt libs
                # to LIBS, but for Qt4 we need to use the QMAKE_LIBDIR_FLAGS.
    
                QMAKE_LIBDIR_FLAGS *= -L$${LIB_PATH}
            }
            else {
                LIBS *= -L$${LIB_PATH}
            }
        }
    
        unset(LINKAGE)
    
        isEmpty(LINKAGE) {
    
            if(!debug_and_release|build_pass):CONFIG(debug, debug|release) {
    
                mac:LINKAGE = -l$${LIB_NAME}_debug
                win32:LINKAGE = -l$${LIB_NAME}d
            }
        }
    
        isEmpty(LINKAGE) {
    
            LINKAGE = -l$${LIB_NAME}
        }
    
        !isEmpty(QMAKE_LSB) {
    
            QMAKE_LFLAGS *= --lsb-shared-libs=$${LIB_NAME}
        }
    
        LIBS += $$LINKAGE
        export(LIBS)
        export(QMAKE_LFLAGS)
        export(QMAKE_LIBDIR_FLAGS)
    
        return(true)
    }
    

    eeqt.prf:

    ################################################################
    # EEQT Widget Library
    ################################################################
    
    include ( ./eeqtconfig.pri )
    include ( ./eeqtfunctions.pri )
    
    contains(EEQT_CONFIG, EEQtDll) {
    
        DEFINES *= EEQT_DLL
    }
    
    INCLUDEPATH *= $${EEQT_INSTALL_HEADERS}
    
    qwtAddLibrary($${EEQT_INSTALL_LIBS}, eeqt)
    

    src.pro

    ################################################################
    # EEQT Widget Library
    ################################################################
    
    EEQT_ROOT		= $${PWD}/..
    include($${EEQT_ROOT}/eeqtconfig.pri)
    include($${EEQT_ROOT}/eeqtbuild.pri)
    include($${EEQT_ROOT}/eeqtfunctions.pri)
    
    EEQT_OUT_ROOT = $${OUT_PWD}/..
    
    TEMPLATE		= lib
    TARGET			= $$eeqtLibraryTarget(eeqt)
    
    contains(EEQT_CONFIG, EEQtDLL) {
    
    	CONFIG += dll
    	win32: DEFINES += QT_DLL EEQT_DLL EEQT_MAKEDLL
    }
    
    contains(EEQT_CONFIG, EEQwtWidget) {
    
        include($${PWD}/EEQwtWidget/eeqwtwidget.pri)
    }
    
    target.path    = $${EEQT_INSTALL_LIBS}
    INSTALLS       = target 
    
    headers.files  = $${HEADERS}
    headers.path   = $${EEQT_INSTALL_HEADERS}
    INSTALLS += headers
    

    eeqwtwidget.pri:

    HEADERS += \
    		EEQwtWidget/eeqwtwidget.h \
            eeqt_global.h \
    		EEQwtWidget/customscaledraw.h
    		
    SOURCES += \
    		EEQwtWidget/eeqwtwidget.cpp \
    		EEQwtWidget/customscaledraw.cpp
    

  • Lifetime Qt Champion

    One subfolder by class ? Isn't that a bit too much ?

    Usually it's rather one subfolder per "logical block"



  • Hello SGaist

    Yea, I came to the same conclusion. To much work making all these separate folders.
    But how would you add these "logical blocks"?

    headers.files  = $${HEADERS}
    headers.path   = $${EEQT_INSTALL_HEADERS}
    INSTALLS += headers
    

    Here all headers will be installed at the same level. If the idea of logical blocks should work then different headers should go into different sub-folders. Whats the best approach here?


  • Qt Champions 2019

    @Aslund

    HEADERS += \
    		module_1/class_1.h \
                    module_2/class_1.h \
                    ...
    		
    SOURCES += \
    		module_1/class_1.cpp \
                    module_2/class_1.cpp \
    

  • Lifetime Qt Champion

    Or add a .pri file per module that extends these variables and include them in your main .pro file.


Log in to reply