Jack Bryan
Jack Bryan

Reputation: 1

C++ Linker error undefined reference to a class definition and its member functions on Linux

I am trying to install QScintilla-gpl-2.7.1 on Linux 2.6.32-279. #1 SMP 2012 x86_64 x86_64 x86_64 GNU/Linux

I have solved the problem in my previous post. But, I got a new problem of linker error:

It cost me a week but still cannot find the reason.

The old posts cannot help me even though I have tried them. Any help will be appreciated.

The link command:

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

OBJECTS       = ListBoxQt.o \
    PlatQt.o \
    qsciabstractapis.o \
    qsciapis.o \
    ..........

 LIBS          = -L/home/user/myPath/qt483/qt-everywhere-opensource-src-4.8.3/lib
 LFLAGS        = -Wl,-O1
 LINK          = g++
 LIBS_SUFFIX   = -lQtCore -lQtGui -lQt3Support -lQtCLucene -lQtDeclarative -lQtDesigner  -lQtDesignerComponents -    lQtHelp -lQtMultimedia -lQtNetwork -lQtOpenGL -lQtScript - lQtScriptTools -lQtSql -lQtSvg -lQtTest -lQtWebKit -lQtXml -lQtXmlPatterns -lpthread
 OBJCOMP is not defined. 

Thanks

The error:

qscintilla2/QScintilla-gpl-2.7.1/src/Indicator.o: In function `Indicator::Draw(Surface*, PRectangle const&, PRectangle const&)':
Indicator.cpp:(.text+0x409): undefined reference to `RGBAImage::RGBAImage(int, int,    float, unsigned char const*)'
Indicator.cpp:(.text+0x43d): undefined reference to `RGBAImage::SetPixel(int, int, ColourDesired, int)'
Indicator.cpp:(.text+0x456): undefined reference to `RGBAImage::SetPixel(int, int, ColourDesired, int)'
Indicator.cpp:(.text+0x47a): undefined reference to `RGBAImage::SetPixel(int, int, ColourDesired, int)'
Indicator.cpp:(.text+0x493): undefined reference to `RGBAImage::SetPixel(int, int, ColourDesired, int)'
Indicator.cpp:(.text+0x4ac): undefined reference to `RGBAImage::SetPixel(int, int, ColourDesired, int)'
Indicator.cpp:(.text+0x4c7): undefined reference to `RGBAImage::Pixels() const'
Indicator.cpp:(.text+0x50f): undefined reference to `RGBAImage::~RGBAImage()'
Indicator.cpp:(.text+0x900): undefined reference to `RGBAImage::RGBAImage(int, int, float, unsigned char const*)'
Indicator.cpp:(.text+0x94e): undefined reference to `RGBAImage::SetPixel(int, int, ColourDesired, int)'
Indicator.cpp:(.text+0x9f9): undefined reference to `RGBAImage::SetPixel(int, int, ColourDesired, int)'
Indicator.cpp:(.text+0xa4b): undefined reference to `RGBAImage::Pixels() const'
Indicator.cpp:(.text+0xac7): undefined reference to `RGBAImage::~RGBAImage()'
/qscintilla2/QScintilla-gpl-2.7.1/src/LineMarker.o: In function  `LineMarker::Draw(Surface*, PRectangle&, Font&, LineMarker::typeOfFold, int)':
LineMarker.cpp:(.text+0x2fd): undefined reference to `RGBAImage::Pixels() const'
LineMarker.cpp:(.text+0x3e3): undefined reference to `XPM::Draw(Surface*, PRectangle&)'
qscintilla2/QScintilla-gpl-2.7.1/src/LineMarker.o: In function  `LineMarker::SetRGBAImage(Point, float, unsigned char const*)':
LineMarker.cpp:(.text+0x1648): undefined reference to `RGBAImage::RGBAImage(int, int,  float, unsigned char const*)'
qscintilla2/QScintilla-gpl-2.7.1/src/LineMarker.o: In function `LineMarker::SetXPM(char const* const*)':
LineMarker.cpp:(.text+0x16c6): undefined reference to `XPM::XPM(char const* const*)'
qscintilla2/QScintilla-gpl-2.7.1/src/LineMarker.o: In function `LineMarker::SetXPM(char const*)':
LineMarker.cpp:(.text+0x1746): undefined reference to `XPM::XPM(char const*)'
collect2: ld returned 1 exit status

make: * [Qt4Qt5] Error 1

The definition of class RGBAImage in src/XPM.h.

No compile errors , but the linker cannot find the RGBAImage defined in XPM.h, which has been included in Indicator.cpp and Indicator.cpp.

In Makefile, the Indicator.o and Indicator.o can be generated w/o problems and they have been put into linker input argument list, but the linker errors still are there. There is no XPM.cpp file. But I got the same error even though I created a XPM.cpp file to include XPM.h and got XPM.o .

#include <vector>
#include <map>

#include "Platform.h"

#include "Scintilla.h"
#include "XPM.h" // RGBAImage is defined here
#include "Indicator.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static PRectangle PixelGridAlign(const PRectangle &rc) {
// Move left and right side to nearest pixel to avoid blurry visuals
return PRectangle(int(rc.left + 0.5), rc.top, int(rc.right + 0.5), rc.bottom);
}

void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine)     
{
surface->PenColour(fore);
int ymid = (rc.bottom + rc.top) / 2;
if (style == INDIC_SQUIGGLE) {
    int x = int(rc.left+0.5);
    int xLast = int(rc.right+0.5);
    int y = 0;
    surface->MoveTo(x, rc.top + y);
    while (x < xLast) {
        if ((x + 2) > xLast) {
            if (xLast > x)
                y = 1;
            x = xLast;
        } else {
            x += 2;
            y = 2 - y;
        }
        surface->LineTo(x, rc.top + y);
    }
} else if (style == INDIC_SQUIGGLEPIXMAP) {
    PRectangle rcSquiggle = PixelGridAlign(rc);

    int width = Platform::Minimum(4000, rcSquiggle.Width());
    RGBAImage image(width, 3, 1.0, 0);
    enum { alphaFull = 0xff, alphaSide = 0x2f, alphaSide2=0x5f };
    for (int x = 0; x < width; x++) {
        if (x%2) {
            // Two halfway columns have a full pixel in middle flanked by light pixels
            image.SetPixel(x, 0, fore, alphaSide);
            image.SetPixel(x, 1, fore, alphaFull);
            image.SetPixel(x, 2, fore, alphaSide);
        } else {
            // Extreme columns have a full pixel at bottom or top and a mid-tone pixel in centre
            image.SetPixel(x, (x%4) ? 0 : 2, fore, alphaFull);
            image.SetPixel(x, 1, fore, alphaSide2);
        }
    }
    surface->DrawRGBAImage(rcSquiggle, image.GetWidth(), image.GetHeight(), image.Pixels());
} else if (style == INDIC_SQUIGGLELOW) {
    surface->MoveTo(rc.left, rc.top);
    int x = rc.left + 3;
    int y = 0;
    while (x < rc.right) {
        surface->LineTo(x-1, rc.top + y);
        y = 1 - y;
        surface->LineTo(x, rc.top + y);
        x += 3;
    }
    surface->LineTo(rc.right, rc.top + y);  // Finish the line
} else if (style == INDIC_TT) {
    surface->MoveTo(rc.left, ymid);
    int x = rc.left + 5;
    while (x < rc.right) {
        surface->LineTo(x, ymid);
        surface->MoveTo(x-3, ymid);
        surface->LineTo(x-3, ymid+2);
        x++;
        surface->MoveTo(x, ymid);
        x += 5;
    }
    surface->LineTo(rc.right, ymid);    // Finish the line
    if (x - 3 <= rc.right) {
        surface->MoveTo(x-3, ymid);
        surface->LineTo(x-3, ymid+2);
    }
} else if (style == INDIC_DIAGONAL) {
    int x = rc.left;
    while (x < rc.right) {
        surface->MoveTo(x, rc.top+2);
        int endX = x+3;
        int endY = rc.top - 1;
        if (endX > rc.right) {
            endY += endX - rc.right;
            endX = rc.right;
        } 
                    surface->LineTo(endX, endY);
                    x += 4;
           }
    } else if (style == INDIC_STRIKE) {
            surface->MoveTo(rc.left, rc.top - 4);
            surface->LineTo(rc.right, rc.top - 4);
    } else if (style == INDIC_HIDDEN) {
            // Draw nothing
    } else if (style == INDIC_BOX) {
            surface->MoveTo(rc.left, ymid+1);
            surface->LineTo(rc.right, ymid+1);
            surface->LineTo(rc.right, rcLine.top+1);
            surface->LineTo(rc.left, rcLine.top+1);
            surface->LineTo(rc.left, ymid+1);
    } else if (style == INDIC_ROUNDBOX || style == INDIC_STRAIGHTBOX) {
            PRectangle rcBox = rcLine;
            rcBox.top = rcLine.top + 1;
            rcBox.left = rc.left;
            rcBox.right = rc.right;
            surface->AlphaRectangle(rcBox, (style == INDIC_ROUNDBOX) ? 1 : 0, fore, fillAlpha, fore, outlineAlpha, 0);
        } else if (style == INDIC_DOTBOX) {
            PRectangle rcBox = PixelGridAlign(rc);
            rcBox.top = rcLine.top + 1;
            rcBox.bottom = rcLine.bottom;
            // Cap width at 4000 to avoid large allocations when mistakes made
            int width = Platform::Minimum(rcBox.Width(), 4000);
            RGBAImage image(width, rcBox.Height(), 1.0, 0);
            // Draw horizontal lines top and bottom
            for (int x=0; x<width; x++) {
               for (int y=0; y<rcBox.Height(); y += rcBox.Height()-1) {
                    image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha);
                }
            }
            // Draw vertical lines left and right
            for (int y=1; y<rcBox.Height(); y++) {
                  for (int x=0; x<width; x += width-1) {
                       image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha);
                  }
             }
            surface->DrawRGBAImage(rcBox, image.GetWidth(), image.GetHeight(), image.Pixels());
           } else if (style == INDIC_DASH) {
           int x = rc.left;
           while (x < rc.right) {
                    surface->MoveTo(x, ymid);
                    surface->LineTo(Platform::Minimum(x + 4, rc.right), ymid);
                    x += 7; 
           }
       } else if (style == INDIC_DOTS) {
           int x = rc.left;
           while (x < rc.right) 
           {
                    PRectangle rcDot(x, ymid, x+1, ymid+1);
                    surface->FillRectangle(rcDot, fore);
                    x += 2;
             }
    } 
    else 
    {   // Either INDIC_PLAIN or unknown
    surface->MoveTo(rc.left, ymid);
    surface->LineTo(rc.right, ymid);
    }
 }

 ----------------------------------
 XPM.h

 # pragma once
 #include "Platform.h"
 #if defined(PLAT_QT)
 #include <qimage.h>
 #include <qpixmap.h>
 #endif

 #ifdef SCI_NAMESPACE
 namespace Scintilla {
 #endif

 /**
 * Hold a pixmap in XPM format.
 */
class XPM {
#if defined(PLAT_QT)
QPixmap qpm;

public:

XPM(const char *textForm);
XPM(const char *const *linesForm);
~XPM() {}

void Draw(Surface *surface, PRectangle &rc);
int GetHeight() const {return qpm.height();}

const QPixmap &Pixmap() const {return qpm;}
#else
int pid;        // Assigned by container
int height;
int width;
int nColours;
char *data;
char codeTransparent;
char *codes;
ColourDesired *colours;
ColourDesired ColourDesiredFromCode(int ch) const;
ColourDesired ColourFromCode(int ch) const;
void FillRun(Surface *surface, int code, int startX, int y, int x);
char **lines;
ColourDesired *colourCodeTable[256];

 public:
XPM(const char *textForm);
XPM(const char *const *linesForm);
~XPM();
void Init(const char *textForm);
void Init(const char *const *linesForm);
void Clear();
/// Decompose image into runs and use FillRectangle for each run
void Draw(Surface *surface, PRectangle &rc);
char **InLinesForm() { return lines; }
void SetId(int pid_) { pid = pid_; }
int GetId() const { return pid; }
int GetHeight() const { return height; }
int GetWidth() const { return width; }
void PixelAt(int x, int y, ColourDesired &colour, bool &transparent) const;
static const char **LinesFormFromTextForm(const char *textForm);
#endif
};

#if !defined(PLAT_QT)

/**
 * A collection of pixmaps indexed by integer id.
 */
class XPMSet {
XPM **set;  ///< The stored XPMs.
int len;    ///< Current number of XPMs.
int maximum;    ///< Current maximum number of XPMs, increased by steps if reached.
int height; ///< Memorize largest height of the set.
int width;  ///< Memorize largest width of the set.
 public:
XPMSet();
~XPMSet();
/// Remove all XPMs.
void Clear();
/// Add a XPM.
void Add(int ident, const char *textForm);
/// Get XPM by id.
XPM *Get(int ident);
/// Give the largest height of the set.
int GetHeight();
/// Give the largest width of the set.
int GetWidth();
 };

 #endif

 /**
  * An translucent image stoed as a sequence of RGBA bytes.
 */
class RGBAImage {
    // Private so RGBAImage objects can not be copied
    RGBAImage(const RGBAImage &);
    RGBAImage &operator=(const RGBAImage &);
    int height;
    int width;
    float scale;
   #if defined(PLAT_QT)
      QImage *qim;
    #else
    std::vector<unsigned char> pixelBytes;
   #endif
 public:
    //   RGBAImage has been defined here, why still linker error ??? 
    RGBAImage(int width_, int height_, float scale_, unsigned char const *pixels_);
    RGBAImage(const XPM &xpm);
    virtual ~RGBAImage();
    int GetHeight() const { return height; }
    int GetWidth() const { return width; }
    float GetScale() const { return scale; }
    float GetScaledHeight() const { return height / scale; }
    float GetScaledWidth() const { return width / scale; }
#if !defined(PLAT_QT)
    int CountBytes() const;
#endif
    const unsigned char *Pixels() const;
    //  SetPixel has been defined here, why still linker error ??? 
   void SetPixel(int x, int y, ColourDesired colour, int alpha=0xff); 
};

#if !defined(PLAT_QT)

 /**
 * A collection of RGBAImage pixmaps indexed by integer id.
 */
class RGBAImageSet {
    typedef std::map<int, RGBAImage*> ImageMap;
    ImageMap images;
    mutable int height; ///< Memorize largest height of the set.
    mutable int width;  ///< Memorize largest width of the set.
public:
     RGBAImageSet();
    ~RGBAImageSet();
   /// Remove all images.
   void Clear();
   /// Add an image.
   void Add(int ident, RGBAImage *image);
   /// Get image by id.
  RGBAImage *Get(int ident);
   /// Give the largest height of the set.
   int GetHeight() const;
   /// Give the largest width of the set.
   int GetWidth() const;
  };
 #endif    
 #ifdef SCI_NAMESPACE
 }

#endif

I extracted the tar ball again and found XMP.cpp and also run qmake (4.8.3) qscintilla.proa and got Makefile. But I got a lot of compile errors. e.g.
Qsci/qsciscintilla.h:34:21: error: qobject.h: No such file or directory. I have updated my post.

   [~/qscintilla2/QScintilla-gpl-2.7.1_new/QScintilla-gpl-2.7.1/Qt4Qt5] $ make
   g++ -c -pipe -O2 -D_REENTRANT -w -fPIC -DQSCINTILLA_MAKE_DLL -DQT -DSCI_LEXER -  DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I../../../../qt483/qt-everywhere-opensource-src- 4.8.3/mkspecs/linux-g++ -I. -I/home/user//qt483/include/QtCore - I/home/user/qt483/include/QtGui -I/home/user/qt483/include -I. -I../include - I../lexlib -I../src -I. -o qsciscintilla.o qsciscintilla.cpp
   In file included from qsciscintilla.cpp:28:
  Qsci/qsciscintilla.h:34:21: error: qobject.h: No such file or directory
  Qsci/qsciscintilla.h:35:25: error: qstringlist.h: No such file or directory
  Qsci/qsciscintilla.h:37:22: error: QByteArray: No such file or directory
  Qsci/qsciscintilla.h:38:17: error: QList: No such file or directory
  Qsci/qsciscintilla.h:39:20: error: QPointer: No such file or directory
  In file included from Qsci/qsciscintilla.h:41,
              from qsciscintilla.cpp:28:
  ./Qsci/qsciglobal.h:33:21: error: qglobal.h: No such file or directory
  In file included from Qsci/qsciscintilla.h:42,
              from qsciscintilla.cpp:28:
  ./Qsci/qscicommand.h:33:21: error: qstring.h: No such file or directory
  In file included from ./Qsci/qscicommand.h:36,
               from Qsci/qsciscintilla.h:42,
             from qsciscintilla.cpp:28:
  ./Qsci/qsciscintillabase.h:35:31: error: QAbstractScrollArea: No such file or directory
  ./Qsci/qsciscintillabase.h:37:20: error: qpoint.h: No such file or directory
  ./Qsci/qsciscintillabase.h:38:20: error: qtimer.h: No such file or directory
    qsciscintilla.cpp:31:21: error: qaction.h: No such file or directory
    qsciscintilla.cpp:32:26: error: qapplication.h: No such file or directory
   qsciscintilla.cpp:33:20: error: qcolor.h: No such file or directory
   qsciscintilla.cpp:34:20: error: qevent.h: No such file or directory
   qsciscintilla.cpp:35:20: error: qimage.h: No such file or directory
   qsciscintilla.cpp:36:23: error: qiodevice.h: No such file or directory
   qsciscintilla.cpp:37:26: error: qkeysequence.h: No such file or directory
   qsciscintilla.cpp:40:19: error: qmenu.h: No such file or directory

  In file included from qsciscintilla.cpp:44:
   Qsci/qscilexer.h:34:19: error: qfont.h: No such file or directory
   Qsci/qscilexer.h:35:18: error: qmap.h: No such file or directory
  In file included from ./Qsci/qscicommand.h:36,
             from Qsci/qsciscintilla.h:42,
             from qsciscintilla.cpp:28:
  ./Qsci/qsciscintillabase.h:69: error: expected class-name before '{' token
  ./Qsci/qsciscintillabase.h:70: error: ISO C++ forbids declaration of 'Q_OBJECT' with  no type
  ./Qsci/qsciscintillabase.h:72: error: expected ';' before 'public'
  ./Qsci/qsciscintillabase.h:3011: error: expected ')' before '*' token

After updating Makefile's lib path and following the install instructions on QScintilla-gpl-2.7.1/doc/html-Qt4Qt5/index.html, I have compiled and installed QScintilla-gpl-2.7.1 w/o errors.

But, I got new errors when I run example-Qt4Qt5/application:

  ~/qscintilla2/QScintilla-gpl-2.7.1_new/QScintilla-gpl-2.7.1/example-Qt4Qt5] $   ./application

 Unable to load library icui18n "Cannot load library icui18n: (icui18n: cannot open shared object file: No such file or directory)"

Upvotes: 0

Views: 2727

Answers (1)

Jonathan Wakely
Jonathan Wakely

Reputation: 171403

The definition of class RGBAImage in src/XPM.h.

The linker isn't complaining about the definition of the class, it's complaining about the definitions of the class' member functions, which are defined in XPM.cpp

That should be in the tarball, so you must have done something wrong when extracting the code.

Upvotes: 1

Related Questions