PDA

View Full Version : Statically linked program doesn't load QImage from file.



badjer1024
16th March 2009, 16:52
I have a small C++ program that works correctly when it is dynamically linked with Qt-4.4.3. However, when it is statically linked with Qt-4.4.3 it fails to load the image from a file into a QImage object.

I am also using the open source Exiv2 (http://www.exiv2.org/) library to access the image's header data.

Given and image filename the program first opens and reads the metadata with the following line (where filename is a QString):


_imageMetaData = Exiv2::ImageFactory::open(filename.toStdString());

Then sometime later is actually reads the image data with this line:


// Load image from file into _currentImage.
if (!_currentImage.load(filename)) {
std::cout << "\nFailed to load image from file" << std::endl;
}


I have linked the program to Qt-4.4.3 both dynamically with Qmake and with a simplified makefile and statically with Qmake and a simplified makefile. The results were the same (the statically linked versions do not load the image). I have installed both a dynamically linked version of Qt-4.4.3 (/usr/local/Trolltech/Qt-4.4.3) and a statically linked version (/usr/local/Trolltech/Qt-4.4.3-Static). Also, I set PATH to the statically linked version's bin directory before invoking qmake.

Any thoughts or other experiments I can try? The .pro and makefile files follow.

Thanks for your help,

badjer1024

This is the .pro file:


TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .
LIBS += -lexiv2
# Input
HEADERS += iMage_filearea.hpp \
iMage_imagearea.hpp \
iMage_imageheader.hpp \
iMage_orientationdialog.hpp \
iMage_picturearea.hpp \
iMage_workarea.hpp
SOURCES += iMage_filearea.cpp \
iMage_imagearea.cpp \
iMage_imageheader.cpp \
iMage_main.cpp \
iMage_orientationdialog.cpp \
iMage_picturearea.cpp \
iMage_workarea.cpp

and this is plagerized makefile:


####### Compiler, tools and options


DEFINES = -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB

CXX = g++
CXXFLAGS = -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES)

INCPATH = -I/usr/local/Trolltech/Qt-4.4.3-Static/include \
-I/usr/local/Trolltech/Qt-4.4.3-Static/include/QtCore \
-I/usr/local/Trolltech/Qt-4.4.3-Static/include/QtGui

LINK = g++
LFLAGS = -pthread

LIBS = -L/usr/X11R6/lib -L/usr/local/Trolltech/Qt-4.4.3-Static/lib \
-Wl,-Bstatic -lexiv2 -lQtGui -lQtCore \
-Wl,-Bdynamic -lpng -lSM -lICE -lXi -lXrender \
-lXrandr -lfreetype -lfontconfig -lXext -lX11 -lz -lm \
-lgthread-2.0 -lrt -lglib-2.0 -ldl -lpthread

DEL_FILE = rm -f


####### Files

SOURCES = iMage_filearea.cpp \
iMage_imagearea.cpp \
iMage_imageheader.cpp \
iMage_main.cpp \
iMage_orientationdialog.cpp \
iMage_picturearea.cpp \
iMage_workarea.cpp \
moc_iMage_filearea.cpp \
moc_iMage_imagearea.cpp \
moc_iMage_orientationdialog.cpp \
moc_iMage_workarea.cpp

OBJECTS = iMage_filearea.o \
iMage_imagearea.o \
iMage_imageheader.o \
iMage_main.o \
iMage_orientationdialog.o \
iMage_picturearea.o \
iMage_workarea.o \
moc_iMage_filearea.o \
moc_iMage_imagearea.o \
moc_iMage_orientationdialog.o \
moc_iMage_workarea.o

TARGET = iMage


####### Build rules

all: Makefile $(TARGET)

clean:
-$(DEL_FILE) $(OBJECTS)
-$(DEL_FILE) *~ core *.core

####### Link

$(TARGET): $(OBJECTS)
$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS)


####### Compile

iMage_filearea.o: iMage_filearea.cpp iMage_filearea.hpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o iMage_filearea.o iMage_filearea.cpp

iMage_imagearea.o: iMage_imagearea.cpp iMage_imagearea.hpp \
iMage_workarea.hpp \
iMage_imageheader.hpp \
iMage_orientationdialog.hpp \
iMage_picturearea.hpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o iMage_imagearea.o iMage_imagearea.cpp

iMage_imageheader.o: iMage_imageheader.cpp iMage_imageheader.hpp \
iMage_orientationdialog.hpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o iMage_imageheader.o iMage_imageheader.cpp

iMage_main.o: iMage_main.cpp iMage_workarea.hpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o iMage_main.o iMage_main.cpp

iMage_orientationdialog.o: iMage_orientationdialog.cpp iMage_orientationdialog.hpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o iMage_orientationdialog.o iMage_orientationdialog.cpp

iMage_picturearea.o: iMage_picturearea.cpp iMage_picturearea.hpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o iMage_picturearea.o iMage_picturearea.cpp

iMage_workarea.o: iMage_workarea.cpp iMage_workarea.hpp \
iMage_filearea.hpp \
iMage_imagearea.hpp \
iMage_imageheader.hpp \
iMage_orientationdialog.hpp \
iMage_picturearea.hpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o iMage_workarea.o iMage_workarea.cpp

moc_iMage_filearea.o: moc_iMage_filearea.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_iMage_filearea.o moc_iMage_filearea.cpp

moc_iMage_imagearea.o: moc_iMage_imagearea.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_iMage_imagearea.o moc_iMage_imagearea.cpp

moc_iMage_orientationdialog.o: moc_iMage_orientationdialog.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_iMage_orientationdialog.o moc_iMage_orientationdialog.cpp

moc_iMage_workarea.o: moc_iMage_workarea.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_iMage_workarea.o moc_iMage_workarea.cpp

######## End of Makefile

pckoster
17th March 2009, 08:56
Did you compile-in the plugins of the various image formats as well in your static version?

Might just not recognize the format if they are omitted as the static version cannot load plugins: http://doc.trolltech.com/4.4/plugins-howto.html#static-plugins

badjer1024
18th March 2009, 16:47
Thanks for the pointer to the plugins that QImage uses.

I edited the .pro file as instructed.

TEMPLATE = app
TARGET = iMage
DEPENDPATH += .
INCLUDEPATH += .
QTPLUGIN += qjpeg
LIBS += -lexiv2 \

# Input
HEADERS += iMage_filearea.hpp \
iMage_imagearea.hpp \
iMage_imageheader.hpp \
iMage_orientationdialog.hpp \
iMage_picturearea.hpp \
iMage_workarea.hpp
SOURCES += iMage_filearea.cpp \
iMage_imagearea.cpp \
iMage_imageheader.cpp \
iMage_main.cpp \
iMage_orientationdialog.cpp \
iMage_picturearea.cpp \
iMage_workarea.cpp


And the modified main.cpp is:


#include <QApplication>
#include <QtPlugin>
#include <iostream>

Q_IMPORT_PLUGIN(qjpeg)

#include "iMage_workarea.hpp"

int main(int argc, char *argv[])
{

QApplication app(argc, argv);

WorkArea *workarea = new WorkArea (argv[1]);

return app.exec();
}

Then I ran:
make clean
/usr/local/Troltech/Qt4.4.3-Static/bin/qmake

Everything compiled without error but the linker reported the following:


g++ -Wl,-rpath,/usr/local/Trolltech/Qt-4.4.3-Static/lib -o iMage iMage_filearea.o iMage_imagearea.o iMage_imageheader.o iMage_main.o iMage_orientationdialog.o iMage_picturearea.o iMage_workarea.o moc_iMage_filearea.o moc_iMage_imagearea.o moc_iMage_orientationdialog.o moc_iMage_workarea.o -L/usr/local/Trolltech/Qt-4.4.3-Static/lib -lexiv2 -L/usr/local/Trolltech/Qt-4.4.3-Static/plugins/imageformats -lqjpeg -lQtGui -L/usr/local/Trolltech/Qt-4.4.3-Static/lib -L/usr/X11R6/lib -pthread -lpng -lSM -lICE -pthread -pthread -lXi -lXrender -lXrandr -lfreetype -lfontconfig -lXext -lX11 -lQtCore -lz -lm -pthread -lgthread-2.0 -lrt -lglib-2.0 -ldl -lpthread
/usr/local/Trolltech/Qt-4.4.3-Static/plugins/imageformats/libqjpeg.a(qjpeghandler.o): In function `write_jpeg_image(QImage const&, QIODevice*, int)':
qjpeghandler.cpp:(.text+0x414): undefined reference to `jpeg_std_error'
qjpeghandler.cpp:(.text+0x45a): undefined reference to `jpeg_CreateCompress'
qjpeghandler.cpp:(.text+0x4cc): undefined reference to `jpeg_set_defaults'
qjpeghandler.cpp:(.text+0x8b4): undefined reference to `jpeg_set_quality'
qjpeghandler.cpp:(.text+0x8ca): undefined reference to `jpeg_start_compress'
qjpeghandler.cpp:(.text+0x956): undefined reference to `jpeg_write_scanlines'
qjpeghandler.cpp:(.text+0x9e4): undefined reference to `jpeg_destroy_compress'
qjpeghandler.cpp:(.text+0xd65): undefined reference to `jpeg_finish_compress'
qjpeghandler.cpp:(.text+0xd73): undefined reference to `jpeg_destroy_compress'
/usr/local/Trolltech/Qt-4.4.3-Static/plugins/imageformats/libqjpeg.a(qjpeghandler.o): In function `read_jpeg_image(QIODevice*, QImage*, QByteArray const&, QSize, int)':
qjpeghandler.cpp:(.text+0x2bda): undefined reference to `jpeg_resync_to_restart'
qjpeghandler.cpp:(.text+0x2c15): undefined reference to `jpeg_CreateDecompress'
qjpeghandler.cpp:(.text+0x2c2f): undefined reference to `jpeg_std_error'
qjpeghandler.cpp:(.text+0x2c6d): undefined reference to `jpeg_read_header'
qjpeghandler.cpp:(.text+0x2d35): undefined reference to `jpeg_start_decompress'
qjpeghandler.cpp:(.text+0x2eba): undefined reference to `jpeg_destroy_decompress'
qjpeghandler.cpp:(.text+0x339f): undefined reference to `jpeg_read_scanlines'
qjpeghandler.cpp:(.text+0x349e): undefined reference to `jpeg_finish_decompress'
qjpeghandler.cpp:(.text+0x37a0): undefined reference to `jpeg_read_scanlines'
qjpeghandler.cpp:(.text+0x37bc): undefined reference to `jpeg_finish_decompress'
/usr/local/Trolltech/Qt-4.4.3-Static/plugins/imageformats/libqjpeg.a(qjpeghandler.o): In function `jpegSmoothScaler::scanLine(int, QImage const*)':
qjpeghandler.cpp:(.text._ZN16jpegSmoothScaler8scan LineEiPK6QImage[jpegSmoothScaler::scanLine(int, QImage const*)]+0x3b): undefined reference to `jpeg_read_scanlines'
collect2: ld returned 1 exit status

This is so tantalizingly close!
I am missing an additional library?

Thanks again for your help,

Badjer1024

badjer1024
19th March 2009, 18:45
After thinking about it I decided to run ldd against the qjpeg plugin to see what it depended on in the hope that an obvious library would be there. There was an obvious library that it needed which was libjpeg.nn.so in /usr/lib. (Note: ldd complains about static libs so I ran it against the dynamic version of qjpeg.) I checked in /usr/lib and there was also a .a version. After adding the appropriate -L and -l flags to the static portion of LFLAGS in the makefile it linked w/o errors and the statically linked program display the image!

Thanks again for your help!!!