I'm linking OpenCV into my Qt project. More samples on that later. Runtime produced this error:
"Path_to_source: error while loading shared libraries: libcv.so.2.0: cannot open shared object file: No such file or directory"
The path to the OpenCV dynamic link libraries (.so files) were not in the link library path.
Found a clue here here and here.
solution:
su root
cd /etc/ld.so.conf.d
cat > opencv-10.conf
/usr/local/lib
^c
/sbin/ldconfig -v
Showing posts with label Qt. Show all posts
Showing posts with label Qt. Show all posts
Monday, April 12, 2010
Friday, March 26, 2010
Unit Testing quirks: Why doesn't the makefile know how to build the ".moc" file.
I'm following the sample at the Qt site on how to make a unit test. But mine continually failed. Of course I'm less than comfortable with the two magic lines at the end of the source file:
That's the danger of having magic in the build system.
I've uploaded a sample unit test to my SkyDrive. So far I've not found any buildable projects on the web.
A little bitty Java has some good notes on Qt Unit Testing.
KDE TechBase has another intro here.
Here's a description of why the include's not necessary when there's both a header and cpp file in the test.
Finally, to make our test case a stand-alone executable, the following two lines are needed:
QTEST_MAIN(TestQString)
#include "testqstring.moc"
The QTEST_MAIN() macro expands to a simple main() method that runs all the test functions. Note that if both the declaration and the implementation of our test class are in a .cpp file, we also need to include the generated moc file to make Qt's introspection work.
Note the part at the end "if both the declaration and implementation ... are in a .cpp file." what's missing is that "if the declaration and implementation are in separate .h and .cpp files, then that final include is unnecessary."That's the danger of having magic in the build system.
I've uploaded a sample unit test to my SkyDrive. So far I've not found any buildable projects on the web.
A little bitty Java has some good notes on Qt Unit Testing.
KDE TechBase has another intro here.
Here's a description of why the include's not necessary when there's both a header and cpp file in the test.
Tuesday, February 16, 2010
Extending qmake builds: static libraries and automated dependencies
Adding to the previous post, in which an app is automatically rebuilt if a source file changed in the library, here is a method of simplifying and automating that dependency. Adding a second library to the project, the directory structure looks like this:
TrialSystem/TrialSystem.pro
TrialSystem/qmake_postcommon.pri
TrialSystem/trialApp/trialApp.pro
TrialSystem/trialLibA/trialLibA.pro
TrialSystem/trialLibB/trialLibB.pro
First some requirements:
Instead of specifying INCLUDEPATH, the path to the library and the name of the library in LIBS, along with the new "PRE_TARGETDEPENDS," there is simply a new variable named "LIBRARIES." I've added this variable, it is not a qmake reserved name.
The simplification of this file is enabled through the inclusion of "qmake_postcommon.pri" (Again, thanks for eating the indentation, Mr. Blogspot).
win32 {
LIBPREFIX = lib
LIBSUFFIX = .a
# http://doc.trolltech.com/4.6/qmake-function-reference.html#config-config
CONFIG(debug, debug|release) {
LIBDIR = debug
} else {
LIBDIR = release
}
}
message("----")
!isEmpty(LIBRARIES) {
for(libpath, LIBRARIES) {
libbase = $$basename(libpath)
INCLUDEPATH += $$libpath
LIBS += -L$${libpath}/$${LIBDIR}
LIBS += -l$$libbase
PRE_TARGETDEPS += $${libpath}/$${LIBDIR}/$${LIBPREFIX}$${libbase}$${LIBSUFFIX}
}
message($$INCLUDEPATH)
message($$LIBS)
message($$PRE_TARGETDEPS)
}
This include file clearly only works for Windows using mingw. I will be porting this to linux as well.
The first section of the file in the "win32" scope defines the convention for the naming and storing of the library. This is necessary for setting PRE_TARGETDEPS for proper build dependencies.
the second section inside !isempty(LIBRARIES) sets the qmake variables necessary for finding the libraries, setting the include path and handling the dependencies. The loop simply walks through the listed libraries and sets the proper values.
With this configuration, changing a source file in either trialLibA or trialLibB causes the entire system to build correctly, and the .pro files for each of the projects is radically simplified and enabled for cross-platform development.
Interestingly, for Windows, I've added a reference from trialLibA to trialLibB. trialLibB is also called from the app trialApp. With the mingw linker, all the references are handled correctly without error.
Left-click here to download a copy of the project from skydrive (the popup makes it look like a link to a zip file, but it's not. You have to click through).
TrialSystem/TrialSystem.pro
TrialSystem/qmake_postcommon.pri
TrialSystem/trialApp/trialApp.pro
TrialSystem/trialLibA/trialLibA.pro
TrialSystem/trialLibB/trialLibB.pro
First some requirements:
- The name of the library directory "trialLibA" must match the name of its library (on Windows using mingw, libtrialLibA.a).
- The header(s) for the library must be in the directory along with the library's qmake project ".pro" file.
- The library must be statically linked.
- If you don't want to use this technique for other libraries (with oddly named libraries or some other directory hierarchy), then simply don't add that library to the LIBRARIES variable mentioned below. You can still use this technique for other libs that conform to these limitations.
include(../qmake_common.pri)(Ignore, for this post, the placeholder include file "qmake_common.pri," which is empty for now)
TARGET = trialApp
TEMPLATE = app
CONFIG += link_prl
LIBRARIES = ../trialLibA ../trialLibB
SOURCES += main.cpp\
MainWindow.cpp
HEADERS += MainWindow.h
FORMS += MainWindow.ui
include(../qmake_postcommon.pri)
Instead of specifying INCLUDEPATH, the path to the library and the name of the library in LIBS, along with the new "PRE_TARGETDEPENDS," there is simply a new variable named "LIBRARIES." I've added this variable, it is not a qmake reserved name.
The simplification of this file is enabled through the inclusion of "qmake_postcommon.pri" (Again, thanks for eating the indentation, Mr. Blogspot).
win32 {
LIBPREFIX = lib
LIBSUFFIX = .a
# http://doc.trolltech.com/4.6/qmake-function-reference.html#config-config
CONFIG(debug, debug|release) {
LIBDIR = debug
} else {
LIBDIR = release
}
}
message("----")
!isEmpty(LIBRARIES) {
for(libpath, LIBRARIES) {
libbase = $$basename(libpath)
INCLUDEPATH += $$libpath
LIBS += -L$${libpath}/$${LIBDIR}
LIBS += -l$$libbase
PRE_TARGETDEPS += $${libpath}/$${LIBDIR}/$${LIBPREFIX}$${libbase}$${LIBSUFFIX}
}
message($$INCLUDEPATH)
message($$LIBS)
message($$PRE_TARGETDEPS)
}
This include file clearly only works for Windows using mingw. I will be porting this to linux as well.
The first section of the file in the "win32" scope defines the convention for the naming and storing of the library. This is necessary for setting PRE_TARGETDEPS for proper build dependencies.
the second section inside !isempty(LIBRARIES) sets the qmake variables necessary for finding the libraries, setting the include path and handling the dependencies. The loop simply walks through the listed libraries and sets the proper values.
With this configuration, changing a source file in either trialLibA or trialLibB causes the entire system to build correctly, and the .pro files for each of the projects is radically simplified and enabled for cross-platform development.
Interestingly, for Windows, I've added a reference from trialLibA to trialLibB. trialLibB is also called from the app trialApp. With the mingw linker, all the references are handled correctly without error.
Left-click here to download a copy of the project from skydrive (the popup makes it look like a link to a zip file, but it's not. You have to click through).
Friday, February 12, 2010
Qt Library Dependencies -- rebuilding dependencies with qmake
Left-click to Download the Sample Project
I modularize my projects into multiple libraries. The best reason is Separation of Concerns, but it also allows each library to link with its own unit test.
There's an app, then there are several libraries that the app depends upon.
I'll organize my system as such:
One solution to this problem uses the "subdirs" template for the TrialSystem.pro file. This solution requires the entire system to be in the same directory hierarchy, and it precludes parallel builds (if possible, the build system spins multiple threads to spread the load across multiple processors).
-- This is not possible through the menus of Qt Creator. --
First, create System.pro. It should have this content:
One nice feature of this setup is that when Qt Creator opens System.pro, it automatically shows the "app" and "libA" projects in the Projects window.
The project file trialLibA.pro has this content. This is a pretty straightforward static library:
Now, it's possible to change something down in trialLibA.cpp, hit "F5" and have the application run correctly in debug mode.
Now, these acrobatics shouldn't be necessary if qmake supported proper dependency trees automatically.
http://lists.trolltech.com/qt-interest/2007-03/thread00794-0.html
http://www.qtcentre.org/threads/28049-qmake-Project-file-has-both-debug-and-release-conditions-true
I modularize my projects into multiple libraries. The best reason is Separation of Concerns, but it also allows each library to link with its own unit test.
There's an app, then there are several libraries that the app depends upon.
I'll organize my system as such:
TrialSystem/TrialSystem.proNow, trialApp depends on trialLibA, therefore if anything changes in trialLibA, I want the build system to first rebuild trialLibA then link that newly built library into trialApp. (I'm building static libraries).
TrialSystem/trialApp/trialApp.pro
TrialSystem/trialLibA/trialLibA.pro
One solution to this problem uses the "subdirs" template for the TrialSystem.pro file. This solution requires the entire system to be in the same directory hierarchy, and it precludes parallel builds (if possible, the build system spins multiple threads to spread the load across multiple processors).
-- This is not possible through the menus of Qt Creator. --
First, create System.pro. It should have this content:
TEMPLATE = subdirsThis qmake project file builds the subdirectories "trialLibA" and "app" in that order. Now, if anything has changed in the library, the library is built first, then the app is relinked.
SUBDIRS = trialLibA trialApp
CONFIG += ordered
One nice feature of this setup is that when Qt Creator opens System.pro, it automatically shows the "app" and "libA" projects in the Projects window.
The project file trialLibA.pro has this content. This is a pretty straightforward static library:
TARGET = trialLibAThe application's project file, trialApp.pro has this content. This is a mingw build under Windows (thanks for the formatting, Mr. Blogger.com):
TEMPLATE = lib
CONFIG += staticlib
CONFIG += create_prl
SOURCES += TrialLibA.cpp
HEADERS += TrialLibA.h
TARGET = trialAppNote the addition of PRE_TARGETDEPS. This unfortunate platform-specific code (it specifies the precise name of the library along with its path) forces trialApp to relink if the library changes.
TEMPLATE = app
win32 {
CONFIG(debug, debug|release) {
LIBS += -L../trialLibA/debug
PRE_TARGETDEPS += ../trialLibA/debug/libtrialLibA.a
} else {
LIBS += -L../trialLibA/release
PRE_TARGETDEPS += ../trialLibA/release/libtrialLibA.a
}
}
INCLUDEPATH += ../trialLibA
LIBS += -ltrialLibA
SOURCES += main.cpp\
MainWindow.cpp
HEADERS += MainWindow.h
FORMS += MainWindow.ui
Now, it's possible to change something down in trialLibA.cpp, hit "F5" and have the application run correctly in debug mode.
Now, these acrobatics shouldn't be necessary if qmake supported proper dependency trees automatically.
http://lists.trolltech.com/qt-interest/2007-03/thread00794-0.html
http://www.qtcentre.org/threads/28049-qmake-Project-file-has-both-debug-and-release-conditions-true
Sunday, January 31, 2010
Cleaning Qt before rebuild on Windows.
I ran into this problem when rebuilding Qt 2010.01, but it's been around for a while.
now, to clean the system before a rebuilt:
mingw32-make clean
mingw32-make confclean
del /S *.tmp
configure -shared
mingw32-make sub-src
now, to clean the system before a rebuilt:
mingw32-make clean
mingw32-make confclean
del /S *.tmp
configure -shared
mingw32-make sub-src
Wednesday, January 27, 2010
Qt 4.6 (2009.05) fails to build: static mingw on Windows
NOTE: This build problem is fixed in 2010.01 (4.6.1). I will be testing this build today.
NOTE: The build is fixed, but I've filed a bug against Widgets due to QLabel unable to setPixmap(). I'd like to have a statically-built app (for general-purpose tools I can share with my team as exe's). Perhaps I'll move back to Qt 5.
Qt Fails to build on 4.6 (2009.05) with configure -static.
Simply leave out Phonon (the audio component) because it is not allowed with static linking mode. (This is a bug in the build system). You'd think they'd at least build all the configurations before release...
So, to build Qt 4.6 (2009.05) for a statically-linked application, cd to your qt directory (e.g. C:\Qt\2009.05\qt) and simply build it without phonon.
My system is a Dell Xeon E5540 quad-core 2.53GHZ. Windows XP. 12 Gigs RAM. 2TB RAID 5. Hoohoohaha.
NOTE: The build is fixed, but I've filed a bug against Widgets due to QLabel unable to setPixmap(). I'd like to have a statically-built app (for general-purpose tools I can share with my team as exe's). Perhaps I'll move back to Qt 5.
Qt Fails to build on 4.6 (2009.05) with configure -static.
g++ -c -g -frtti -fexceptions -mthreads -Wall -DUNICODE -DQT_LARGEFILE_SUPPORT -DPHONON_MAKE_QT_ONLY_BACKEND -DQT_STATIC
PLUGIN -DQT_PLUGIN -DQT_PHONON_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT -I"..\..\..\..\include\QtCore" -I"..\.
.\..\..\include\QtGui" -I"..\..\..\..\include\phonon" -I"..\..\..\..\include" -I"..\..\..\..\include\ActiveQt" -I"..\..\
..\..\include\phonon_compat\phonon" -I"..\..\..\..\include\phonon_compat" -I"..\..\..\..\include\phonon\Phonon" -I"tmp\m
oc\debug_static" -I"..\..\..\..\mkspecs\win32-g++" -o tmp\obj\debug_static\backend.o ..\..\..\3rdparty\phonon\ds9\backen
d.cpp
..\..\..\3rdparty\phonon\ds9\backend.cpp: In static member function 'static QMutex* Phonon::DS9::Backend::directShowMute
x()':
..\..\..\3rdparty\phonon\ds9\backend.cpp:69: error: 'qt_plugin_instance' was not declared in this scope
mingw32-make[4]: *** [tmp/obj/debug_static/backend.o] Error 1
mingw32-make[4]: Leaving directory `C:/Qt/2009.05/qt/src/plugins/phonon/ds9'
mingw32-make[3]: *** [debug-all] Error 2
mingw32-make[3]: Leaving directory `C:/Qt/2009.05/qt/src/plugins/phonon/ds9'
mingw32-make[2]: *** [sub-ds9-make_default] Error 2
mingw32-make[2]: Leaving directory `C:/Qt/2009.05/qt/src/plugins/phonon'
mingw32-make[1]: *** [sub-phonon-make_default] Error 2
mingw32-make[1]: Leaving directory `C:/Qt/2009.05/qt/src/plugins'
mingw32-make: *** [sub-plugins-sub_src_target_ordered] Error 2
Simply leave out Phonon (the audio component) because it is not allowed with static linking mode. (This is a bug in the build system). You'd think they'd at least build all the configurations before release...
So, to build Qt 4.6 (2009.05) for a statically-linked application, cd to your qt directory (e.g. C:\Qt\2009.05\qt) and simply build it without phonon.
mingw32-make distcleanThis built the Qt system, and my app ran successfully after I built it in Qt Creator. Unfortunately, now the QLabel refuses to setPixmap(). My image labels don't show on the GUI. I'll be abandoning this train of thought soon, either by downgrading to 4.5.3 or by staying with the dynamically linked 4.6.
config -confclean
configure -static -no-phonon -no-phonon-backend
mingw32-make sub-src
My system is a Dell Xeon E5540 quad-core 2.53GHZ. Windows XP. 12 Gigs RAM. 2TB RAID 5. Hoohoohaha.
Thursday, January 14, 2010
Qt 4.5.3 for Mac uninstall required before installing Qt 4.6
Here's something pretty subtle that I hadn't picked up. In the install notes, it tells how to perform the uninstall:
"You can later run the uninstall-qt.py script to uninstall the binary package."
sudo /Developer/Tools/uninstall-qt.py
I had to do this prior to installing Qt 4.6 over Qt 5.3 because Qt decided to store the app into /Developer/Applications/Qt/QtCreator without (of course) removing the old one.
In Windows, they install it directly into the C: directory, into a subdir with the version number. I'm wondering how (if?) they'll support multiple active versions on the Mac.
"You can later run the uninstall-qt.py script to uninstall the binary package."
sudo /Developer/Tools/uninstall-qt.py
I had to do this prior to installing Qt 4.6 over Qt 5.3 because Qt decided to store the app into /Developer/Applications/Qt/QtCreator without (of course) removing the old one.
In Windows, they install it directly into the C: directory, into a subdir with the version number. I'm wondering how (if?) they'll support multiple active versions on the Mac.
Wednesday, January 13, 2010
Extracting an item from a QStandardItemModel
Trial and error led me to this. I have a QListView and a QStandardItemModel. I select one of the items in the View and would like to retrieve it for use.
Need to know which row index was clicked (be sure and set the QListView selectingBehavior to "selectRows," otherwise you may get just a single item within the row). That "selectionModel()" is a tricky bit that wasn't obvious from the docs.
QModelIndexList indices = ui->treeView->selectionModel()->selectedRows();
The QListView is setup so that only a single row can be selected at a time. Verfiy that at least one row was chosen, then determine the correct row index:
if ( indices.count() == 1 )
{
QModelIndex idx = indices[0];
int row = idx.row();
Retrieve the model from the view:
QStandardItemModel *model =
dynamic_cast < QStandardItemModel* >(ui->treeView->model());
QStandardItemModel allows you to retrieve a QStandardItem using integers for row and column (I got wrapped around the axle about QModelIndex from model->data(), but the createIndex() method was protected inside QStandardItemModel. We don't need that, just the integer indices)
QStandardItem *firstColumnItem = model->item(row, 0);
Internally, the object is stored as a QVariant. My two columns contain QString and QDateTime. FYI I used Qt::DisplayRole when inserting the objects into the model.
QVariant
firstColumnVariant(firstColumnItem->data(Qt::DisplayRole));
QString
firstColumnString(firstColumnVariant.toString());
Next, I got the second column with some shorthand:
QVariant
dateTimeVariant(model->item(row,1) ->data(Qt::DisplayRole));
QDateTime
dateTime(dateTimeVariant.toDateTime());
And popped it up in a MessageBox:
QMessageBox(QMessageBox::Information, firstColumnString, dateTime).exec();
Need to know which row index was clicked (be sure and set the QListView selectingBehavior to "selectRows," otherwise you may get just a single item within the row). That "selectionModel()" is a tricky bit that wasn't obvious from the docs.
QModelIndexList indices = ui->treeView->selectionModel()->selectedRows();
The QListView is setup so that only a single row can be selected at a time. Verfiy that at least one row was chosen, then determine the correct row index:
if ( indices.count() == 1 )
{
QModelIndex idx = indices[0];
int row = idx.row();
Retrieve the model from the view:
QStandardItemModel *model =
dynamic_cast < QStandardItemModel* >(ui->treeView->model());
QStandardItemModel allows you to retrieve a QStandardItem using integers for row and column (I got wrapped around the axle about QModelIndex from model->data(), but the createIndex() method was protected inside QStandardItemModel. We don't need that, just the integer indices)
QStandardItem *firstColumnItem = model->item(row, 0);
Internally, the object is stored as a QVariant. My two columns contain QString and QDateTime. FYI I used Qt::DisplayRole when inserting the objects into the model.
QVariant
firstColumnVariant(firstColumnItem->data(Qt::DisplayRole));
QString
firstColumnString(firstColumnVariant.toString());
Next, I got the second column with some shorthand:
QVariant
dateTimeVariant(model->item(row,1) ->data(Qt::DisplayRole));
QDateTime
dateTime(dateTimeVariant.toDateTime());
And popped it up in a MessageBox:
QMessageBox(QMessageBox::Information, firstColumnString, dateTime).exec();
QTreeView (QAbstractItemView) and PageUp/PageDown
Just a note on QTreeView and PageUp/PageDown. I'm developing an app designed for fingers on a big screen, and need a button for PageUp/PageDown rather than using the scrollbar.
QTreeView.autoScroll must be set to "true" to enable PageUp/PageDown key commands to move the list.
QTreeView.autoScroll must be set to "true" to enable PageUp/PageDown key commands to move the list.
Monday, January 11, 2010
Build Error: C:\Qt\2009.05\mingw\bin\mingw32-make.exe: Interrupt/Exception caught (code = 0xc0000005, addr = 0x41f96e)
(I presume your addresses may vary, and I was building the "textobject" sample from the Getting Started screen.)
More text from the build error:
Here's a bug: http://bugreports.qt.nokia.com/browse/QTCREATORBUG-517
right-click My Computer->Properties->Advanced->Environment Variables
in the upper box, if Path doesn't exist, add Path and set it to:
c:\qt\2009.05\mingw\bin;C:\Qt\2009.05\qt\bin
Or, if Path exists, double-click on it, append a semicolon, then append that string. Also, note your installation. If you install Qt after then next release, it may install in the "2010.01" directory or something similar.
Build->Rebuild All now gives me a green bar under "Build"--Success.
More text from the build error:
This happens because the installer for the MinGW Windows release 2009.05 doesn't set the PATH environment variable. Qt cannot find the MingGW tools.
Running build steps for project textobject...
Starting: c:/qt/2009.05/qt/bin/qmake.exe C:/Qt/2009.05/qt/examples/richtext/textobject/textobject.pro -spec win32-g++ -r
Exited with code 0.
Starting: C:/Qt/2009.05/mingw/bin/mingw32-make.exe -w
mingw32-make: Entering directory `C:/Qt/2009.05/qt/examples/richtext/textobject'
C:/Qt/2009.05/mingw/bin/mingw32-make -f Makefile.Debug all
C:\Qt\2009.05\mingw\bin\mingw32-make.exe: Interrupt/Exception caught (code = 0xc0000005, addr = 0x41f96e)
Exited with code 255.
Error while building project textobject
When executing build step 'Make'
Here's a bug: http://bugreports.qt.nokia.com/browse/QTCREATORBUG-517
right-click My Computer->Properties->Advanced->Environment Variables
in the upper box, if Path doesn't exist, add Path and set it to:
c:\qt\2009.05\mingw\bin;C:\Qt\2009.05\qt\bin
Or, if Path exists, double-click on it, append a semicolon, then append that string. Also, note your installation. If you install Qt after then next release, it may install in the "2010.01" directory or something similar.
Build->Rebuild All now gives me a green bar under "Build"--Success.
Researching: best practices for sequential pages
Trying QWizard
Trying the State Machine Framework
For my applications, perhaps Model-View Programming
Trying the State Machine Framework
For my applications, perhaps Model-View Programming
Subscribe to:
Posts (Atom)