4

I'm quite new to CMake and I'm trying to use it to build a little KDE application. I've to use QTXml module, my program compile with no problem but during the linking phase, ld fail to find QXml components...

main.cpp

#include "test.h"

int main(int argc, char **argv)
{
    return 0;
}

test.h

#ifndef TEST_H
#define TEST_H

#include <QXmlResultItems>
#include <QString>
#include <QBuffer>
#include <QXmlQuery>

class test {
public:
    test(){}
    ~test(){}
    QXmlResultItems* find ( const QString& node, const QString& xpath );
private:
    QBuffer device_;
};

#endif // TEST_H

test.cpp

#include "test.h"

QXmlResultItems* test::find ( const QString& node, const QString& xpath )
{
    QXmlResultItems* result = new QXmlResultItems;
    QXmlQuery query;
    query.bindVariable ( "device",&device_ );
    query.setQuery ( "doc($device)/"+node+"/"+xpath );
    query.evaluateTo ( result );
    return result;
}

CMakeLists.cmake

project(qtcmakepb)

find_package(KDE4 REQUIRED)
include (KDE4Defaults)

include_directories( ${KDE4_INCLUDES} ${QT_INCLUDES} )
#Supposed to be useless because of KDE4 REQUIRED and ${QT_INCLUDES}
find_package(Qt4 COMPONENTS QtCore QtXml REQUIRED )


# In this CMakeLists.txt we define which files
# are used to compile the application
set(qtcmakepb_SRCS main.cpp test.cpp)


# Set the name of the application
kde4_add_executable(qtcmakepb ${qtcmakepb_SRCS})

# Select which libraries we need to link to
target_link_libraries(qtcmakepb ${KDE4_KDEUI_LIBS})
target_link_libraries(qtcmakepb ${QT_QTCORE_LIBS})
target_link_libraries(qtcmakepb ${QT_QTXML_LIBS})

# Tell cmake to install the application binary
install(TARGETS qtcmakepb ${INSTALL_TARGETS_DEFAULT_ARGS})

# Install the .desktop file
install( PROGRAMS qtcmakepb.desktop  DESTINATION ${XDG_APPS_INSTALL_DIR} )

output for make :

Linking CXX executable qtcmakepb
CMakeFiles/qtcmakepb.dir/test.o: In function `test::find(QString const&, QString const&)':
/home/zelwina/projects/QtCmakePb/src/test.cpp:5: undefined reference to `QXmlResultItems::QXmlResultItems()'
/home/zelwina/projects/QtCmakePb/src/test.cpp:6: undefined reference to `QXmlQuery::QXmlQuery()'
/home/zelwina/projects/QtCmakePb/src/test.cpp:7: undefined reference to `QXmlQuery::bindVariable(QString const&, QIODevice*)'
/home/zelwina/projects/QtCmakePb/src/test.cpp:8: undefined reference to `QXmlQuery::setQuery(QString const&, QUrl const&)'
/home/zelwina/projects/QtCmakePb/src/test.cpp:9: undefined reference to `QXmlQuery::evaluateTo(QXmlResultItems*) const'
/home/zelwina/projects/QtCmakePb/src/test.cpp:10: undefined reference to `QXmlQuery::~QXmlQuery()'
collect2: erreur: ld a retourné 1 code d'état d'exécution
make[2]: *** [src/qtcmakepb] Erreur 1
make[1]: *** [src/CMakeFiles/qtcmakepb.dir/all] Erreur 2
make: *** [all] Erreur 2

What am I doing wrong ?

Zelwina
  • 87
  • 1
  • 9

3 Answers3

3

To use CMake's FindQt4 module, do the following:

find_package(Qt4 COMPONENTS QtCore QtXml REQUIRED)
include(${QT_USE_FILE})
include_directories(${KDE4_INCLUDES} ${QT_INCLUDES})
target_link_libraries(qtcmakepb ${KDE4_KDEUI_LIBS} ${QT_LIBRARIES})

If you want to specify the individual include dirs and libraries, then replace the last 2 lines above with:

include_directories(${KDE4_INCLUDES}
                    ${QT_QTCORE_INCLUDE_DIR}
                    ${QT_QTXML_INCLUDE_DIR})
target_link_libraries(qtcmakepb
                      ${KDE4_KDEUI_LIBS}
                      ${QT_QTCORE_LIBRARY}
                      ${QT_QTXML_LIBRARY})

Your problem is that you're not calling include(${QT_USE_FILE}), and that QT_QTCORE_LIBS should be QT_QTCORE_LIBRARY (and similarly for QtXml library). Furthermore, you need to call include_directories after you've invoked the FindQt4 module and included the QT_USE_FILE.

For full info on the FindQt4 module provided with your version of CMake, run:

cmake --help-module FindQt4


EDIT

Turns out that the root cause is actually that the undefined functions are part of the QtXmlPatterns library, so the find_package call should include QtXmlPatterns in the list.

When this is done, the variables ${QT_QTXMLPATTERNS_INCLUDE_DIR} and ${QT_QTXMLPATTERNS_LIBRARY} are set by the call include(${QT_USE_FILE}) and can be added as required.

IF YOU'RE USING QT5

With Qt5, using CMake becomes simpler.

In order to include and link QtXml and QtXmlPatterns, you only need these lines:

find_package(Qt5Xml REQUIRED)
find_package(Qt5XmlPatterns REQUIRED)

And linking as follows:

target_link_libraries(qtcmakepb Qt5::Xml Qt5::XmlPatterns)
Fraser
  • 74,704
  • 20
  • 238
  • 215
  • Still can't link, I'm seriously considering giving up CMake for another auto-tools, I've been looking around the internet for almost a full day without finding a solution – Zelwina Jun 19 '12 at 16:23
  • There should be a file in the directory where you run CMake from called CMakeCache.txt. It will have paths specified for `QT_QTXML_LIBRARY` which are the locations of the release and debug QtXml libs (QtXml4.lib and QtXmld4.lib). Can you check this is the case, and that the files it specifies actually exist? – Fraser Jun 19 '12 at 17:15
  • `cat CMakeCache.txt | grep QT_QTXML_LIBRARY QT_QTXML_LIBRARY_DEBUG:FILEPATH=QT_QTXML_LIBRARY_DEBUG-NOTFOUND QT_QTXML_LIBRARY_RELEASE:FILEPATH=/usr/lib/libQtXml.so //ADVANCED property for variable: QT_QTXML_LIBRARY_DEBUG QT_QTXML_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 //ADVANCED property for variable: QT_QTXML_LIBRARY_RELEASE QT_QTXML_LIBRARY_RELEASE-ADVANCED:INTERNAL=1` – Zelwina Jun 19 '12 at 17:22
  • Looks like you've only got the release version of the QtXml library (the same is probably true of QtCore). If you try building in release mode it should work: `cmake . -D CMAKE_BUILD_TYPE=Release`. If this is the case, you need to get the debug versions of Qt. How did you install the existing Qt libs? – Fraser Jun 19 '12 at 17:43
  • I know that, I assume I don't need the debug version of Qt which is supposed to be stable. Even with CMAKE_BUILD_TYPe is set in RELEASE mode, I'm still not able to link my program. Enough for today, I give up till tomorrow – Zelwina Jun 19 '12 at 18:17
  • OK. Just for tomorrow though, you're setting the `CMAKE_BUILD_TYPE` to `Release` and not `RELEASE`? – Fraser Jun 19 '12 at 18:22
  • I'm such an idiot (and this is en auphemism) ! QXmlQuery QXmlResultItems are NOT part of the QtXml modul but the QtXmlPatterns module... By adding include and target_link to this module, my problem is solved. thanks a lot Fraser for having racked your brain with me ! It compiles fine because of include_directories(${QT_INCLUDES}= which include all default path to Qt module during compile time... – Zelwina Jun 19 '12 at 18:33
  • @Zelwina Actually, I think you should submit an answer to your own question (since none of the existing answers really identified the root cause of your linker errors) and mark yours as the correct one. It'll be easier for others with similar errors in the future to cut to the chase. – Fraser Jun 19 '12 at 18:55
0

Have you enable QT_USE_QTXML?

Try: set(QT_USE_QTXML TRUE)

Thiem Nguyen
  • 6,345
  • 7
  • 30
  • 50
echo
  • 104
  • 4
0

Don't know if this helps, but:

target_link_libraries(qtcmakepb ${QT_QTCORE_LIBS})
target_link_libraries(qtcmakepb ${QT_QTXML_LIBS})

You're expected to use this:

target_link_libraries(qtcmakepb ${QT_LIBRARIES})

This links everything which you selected with the COMPONENTS clause in find_package(Qt4). Cave-at: This won't work if you link multiple targets with different sets of Qt components.

Stefan Majewsky
  • 5,427
  • 2
  • 28
  • 51