Results 1 to 4 of 4

Thread: Link fails using CMake if Q_OBJECT is present

  1. #1
    Join Date
    Jul 2017
    Posts
    37
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Link fails using CMake if Q_OBJECT is present

    This is jwidget.h:
    Qt Code:
    1. #include <QtWidgets>
    2. #include "dotcanvas.h"
    3. #include "juliaset.h"
    4.  
    5. class JuliaWidget: public QWidget
    6. {
    7. Q_OBJECT
    8. public:
    9. JuliaWidget(QWidget *parent=0);
    10. ~JuliaWidget();
    11. public slots:
    12. void setAngle(int newAngle);
    13. void setSpeed(int sliderPos);
    14. void stepAngle();
    15. private:
    16. DotCanvas *dotcanvas;
    17. QSlider *speedSlider;
    18. QVBoxLayout *layout;
    19. QTimer *jTimer;
    20. JuliaSet jset;
    21. int speed,angle;
    22. QTime lastTime;
    23. };
    To copy to clipboard, switch view to plain text mode 
    This is jwidget.cpp:
    Qt Code:
    1. #include <iostream>
    2. #include <cmath>
    3. #include "jwidget.h"
    4. #include "angle.h"
    5. #include "pncode.h"
    6. using namespace std;
    7.  
    8. JuliaWidget::JuliaWidget(QWidget *parent):QWidget(parent)
    9. {
    10. resize(320,240);
    11. setWindowTitle(tr("Julia Skein"));
    12. show();
    13. layout=new QVBoxLayout;
    14. dotcanvas=new DotCanvas(this);
    15. speedSlider=new QSlider(Qt::Horizontal,this);
    16. jTimer=new QTimer(this);
    17. speedSlider->setRange(0,21*12*16); // 21 octaves, highest speed is about 1 Hz
    18. speedSlider->setSingleStep(16);
    19. speedSlider->setPageStep(12*16);
    20. jTimer->start(1000);
    21. lastTime.start();
    22. layout->addWidget(speedSlider);
    23. layout->addWidget(dotcanvas);
    24. setLayout(layout);
    25. speedSlider->show();
    26. dotcanvas->show();
    27. setAngle(DEG120);
    28. connect(speedSlider,&QSlider::valueChanged,this,&JuliaWidget::setSpeed);
    29. connect(jTimer,&QTimer::timeout,this,&JuliaWidget::stepAngle);
    30. }
    31.  
    32. JuliaWidget::~JuliaWidget()
    33. {
    34. delete jTimer;
    35. delete speedSlider;
    36. delete dotcanvas;
    37. delete layout;
    38. }
    39.  
    40. void JuliaWidget::setAngle(int newAngle)
    41. {
    42. vector<complex<double> > dots;
    43. int i;
    44. jset.setAngle(newAngle);
    45. while (!jset.isReady())
    46. jset.step();
    47. for (i=0;i<PNLEN;i++)
    48. {
    49. jset.step();
    50. dots.push_back(jset.getZ());
    51. }
    52. dotcanvas->setDots(dots);
    53. dotcanvas->update();
    54. }
    55.  
    56. void JuliaWidget::setSpeed(int sliderPos)
    57. {
    58. double rSpeed;
    59. rSpeed=exp2(sliderPos/192.);
    60. if (rSpeed>2147483647)
    61. rSpeed=2147483647;
    62. if (rSpeed<1)
    63. rSpeed=1;
    64. speed=rint(rSpeed);
    65. cout<<"sliderPos "<<sliderPos<<" speed "<<speed<<endl;
    66. rSpeed=exp2(10-sliderPos/384.);
    67. if (rSpeed>2000)
    68. rSpeed=2000;
    69. jTimer->setInterval(rint(rSpeed));
    70. }
    71.  
    72. void JuliaWidget::stepAngle()
    73. {
    74. angle+=lastTime.restart()*speed;
    75. setAngle(angle);
    76. }
    To copy to clipboard, switch view to plain text mode 
    This is CMakeLists.txt:
    Qt Code:
    1. project(juliaskein)
    2. cmake_minimum_required(VERSION 2.8.11)
    3. add_executable(juliaskein juliaskein.cpp jwidget.cpp dotcanvas.cpp xy.cpp
    4. angle.cpp juliaset.cpp pncode.cpp)
    5. target_link_libraries(juliaskein Qt5::Widgets)
    6.  
    7. include(CheckTypeSize)
    8.  
    9. set(CMAKE_INCLUDE_CURRENT_DIR ON)
    10. set(CMAKE_AUTOMOC ON)
    11.  
    12. find_package(Qt5Widgets)
    13.  
    14. set(CMAKE_CXX_FLAGS "-std=c++11")
    15. install(TARGETS juliaskein DESTINATION bin)
    16.  
    17. set(JULIASKEIN_MAJOR_VERSION 0)
    18. set(JULIASKEIN_MINOR_VERSION 1)
    19. set(JULIASKEIN_PATCH_VERSION 0)
    20. set(JULIASKEIN_VERSION ${JULIASKEIN_MAJOR_VERSION}.${JULIASKEIN_MINOR_VERSION}.${JULIASKEIN_PATCH_VERSION})
    21.  
    22. include_directories(${PROJECT_BINARY_DIR})
    23. configure_file (config.h.in config.h)
    24.  
    25. set(CPACK_PACKAGE_VERSION_MAJOR ${JULIASKEIN_MAJOR_VERSION})
    26. set(CPACK_PACKAGE_VERSION_MINOR ${JULIASKEIN_MINOR_VERSION})
    27. set(CPACK_PACKAGE_VERSION_PATCH ${JULIASKEIN_PATCH_VERSION})
    28. set(CPACK_SOURCE_IGNORE_FILES /\\\\.git;.*~)
    29. include(CPack)
    To copy to clipboard, switch view to plain text mode 
    If I compile, I get this:
    Qt Code:
    1. CMakeFiles/juliaskein.dir/jwidget.cpp.o: In function `JuliaWidget::JuliaWidget(QWidget*)':
    2. /home/phma/src/juliaskein/jwidget.cpp:8: undefined reference to `vtable for JuliaWidget'
    3. /home/phma/src/juliaskein/jwidget.cpp:8: undefined reference to `vtable for JuliaWidget'
    4. CMakeFiles/juliaskein.dir/jwidget.cpp.o: In function `JuliaWidget::~JuliaWidget()':
    5. /home/phma/src/juliaskein/jwidget.cpp:32: undefined reference to `vtable for JuliaWidget'
    6. /home/phma/src/juliaskein/jwidget.cpp:32: undefined reference to `vtable for JuliaWidget'
    7. CMakeFiles/juliaskein.dir/jwidget.cpp.o: In function `JuliaWidget::tr(char const*, char const*, int)':
    8. /home/phma/src/juliaskein/jwidget.h:7: undefined reference to `JuliaWidget::staticMetaObject'
    9. collect2: error: ld returned 1 exit status
    10. CMakeFiles/juliaskein.dir/build.make:253: recipe for target 'juliaskein' failed
    11. make[2]: *** [juliaskein] Error 1
    12. CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/juliaskein.dir/all' failed
    13. make[1]: *** [CMakeFiles/juliaskein.dir/all] Error 2
    14. Makefile:149: recipe for target 'all' failed
    15. make: *** [all] Error 2
    To copy to clipboard, switch view to plain text mode 
    The program compiles and runs fine if the Q_OBJECT line is removed. What am I missing?

  2. #2
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Link fails using CMake if Q_OBJECT is present

    You are not moc'ing your QObject headers (in this case the JuliaWidget header).
    You have to add moc'ing to your CMakeLists.txt, and, the resulting cpp files to the build.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  3. #3
    Join Date
    Jul 2017
    Posts
    37
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Link fails using CMake if Q_OBJECT is present

    But I already had an automoc line — why wasn't it moccing?
    I appear to have figured it out. I rearranged CMakeLists to this:
    Qt Code:
    1. cmake_minimum_required(VERSION 3.1.0)
    2. project(juliaskein)
    3.  
    4. include(CheckTypeSize)
    5.  
    6. set(CMAKE_INCLUDE_CURRENT_DIR ON)
    7. set(CMAKE_AUTOMOC ON)
    8.  
    9. find_package(Qt5Widgets)
    10.  
    11. add_executable(juliaskein juliaskein.cpp jwidget.cpp dotcanvas.cpp xy.cpp
    12. angle.cpp juliaset.cpp pncode.cpp)
    13. target_link_libraries(juliaskein Qt5::Widgets)
    14.  
    15. set(CMAKE_CXX_FLAGS "-std=c++11")
    16. install(TARGETS juliaskein DESTINATION bin)
    17.  
    18. set(JULIASKEIN_MAJOR_VERSION 0)
    19. set(JULIASKEIN_MINOR_VERSION 1)
    20. set(JULIASKEIN_PATCH_VERSION 0)
    21. set(JULIASKEIN_VERSION ${JULIASKEIN_MAJOR_VERSION}.${JULIASKEIN_MINOR_VERSION}.${JULIASKEIN_PATCH_VERSION})
    22.  
    23. include_directories(${PROJECT_BINARY_DIR})
    24. configure_file (config.h.in config.h)
    25.  
    26. set(CPACK_PACKAGE_VERSION_MAJOR ${JULIASKEIN_MAJOR_VERSION})
    27. set(CPACK_PACKAGE_VERSION_MINOR ${JULIASKEIN_MINOR_VERSION})
    28. set(CPACK_PACKAGE_VERSION_PATCH ${JULIASKEIN_PATCH_VERSION})
    29. set(CPACK_SOURCE_IGNORE_FILES /\\\\.git;.*~)
    30. include(CPack)
    To copy to clipboard, switch view to plain text mode 
    And I got these lines when compiling:
    Qt Code:
    1. Scanning dependencies of target juliaskein_automoc
    2. [ 10%] Automatic moc for target juliaskein
    3. Generating moc_jwidget.cpp
    4. [ 10%] Built target juliaskein_automoc
    To copy to clipboard, switch view to plain text mode 
    which weren't there before.

    So why was the program running without moc and without the Q_OBJECT line? The program's window consists of two widgets. One displays an animated Julia set consisting of dots that move around; the other is a slider that controls the speed. The two widgets are connected by a signal and slot, which was working even without Q_OBJECT.

  4. #4
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Link fails using CMake if Q_OBJECT is present

    I admit I didn't notice the automoc line in your CMakeLists.txt, it was just clear to me that the problem was with moc'ing based on the symptoms.
    Maybe the moc was running, but the results are not integrated in your build?
    AUOTMOC doc says:
    The global property AUTOGEN_TARGETS_FOLDER can be used to group the automoc targets together in an IDE, e.g. in MSVS.
    Check to see if this var is set, if not set it, see if it helps.

    So why was the program running without moc and without the Q_OBJECT line?
    This as you describe as such is not possible.
    If the problem was running and the signal and slots were working, then Q_OBJECT was being compiled, and the code was moc'ed.
    It is more likely that what you think you had as a setup was wrong.

    If the program build and runs with out Q_OBJECT and without mocing, simply continue programming without the Q_OBJECT and moc'ing, your error will show it self soon enough to explain why you thought it was working without them.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

Similar Threads

  1. Link error with Q_OBJECT
    By psarangi in forum Qt Programming
    Replies: 1
    Last Post: 7th February 2014, 16:05
  2. CMake fails on Windows 7 64-bit
    By IndigoJo in forum Qt Programming
    Replies: 5
    Last Post: 12th September 2011, 22:15
  3. link error LNK2001 with Q_OBJECT
    By mioan in forum Newbie
    Replies: 3
    Last Post: 18th May 2009, 00:52
  4. Q_OBJECT does'nt link
    By bnilsson in forum Qt Programming
    Replies: 2
    Last Post: 16th July 2008, 21:22
  5. Q_OBJECT macro and link errors
    By pscheven in forum Qt Programming
    Replies: 4
    Last Post: 21st March 2008, 14:23

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.