2011-12-10 43 views
0

我得到一個鏈接器錯誤我似乎無法解決... 我使用Qt 4.7版與i686-apple-darwin10-g ++ - 4.2.1編譯器在Mac OS X上10.6.8鏈接器錯誤讓我頭痛

我似乎無法找到問題,但我敢肯定它只是一個愚蠢的錯誤歸因於我自己的天真......

我張貼的編譯器輸出和所涉及的2個文件(大部分他們)只是爲了確保我不會漏掉一些重要的東西。

編譯器提供了以下的輸出:

Linking CXX executable GLBall 
Undefined symbols: 
    "BallGLWidget::resizeGL(int, int)", referenced from: 
     vtable for BallGLWidgetin moc_DesktopMain.cxx.o 
    "_main", referenced from: 
     start in crt1.10.6.o 
    "BallGLWidget::paintGL()", referenced from: 
     vtable for BallGLWidgetin moc_DesktopMain.cxx.o 
    "BallGLWidget::~BallGLWidget()", referenced from: 
     vtable for BallGLWidgetin moc_DesktopMain.cxx.o 
    "BallGLWidget::~BallGLWidget()", referenced from: 
     vtable for BallGLWidgetin moc_DesktopMain.cxx.o 
    "non-virtual thunk to BallWindow::~BallWindow()", referenced from: 
     vtable for BallWindowin moc_DesktopMain.cxx.o 
    "non-virtual thunk to BallGLWidget::~BallGLWidget()", referenced from: 
     vtable for BallGLWidgetin moc_DesktopMain.cxx.o 
    "non-virtual thunk to BallWindow::~BallWindow()", referenced from: 
     vtable for BallWindowin moc_DesktopMain.cxx.o 
    "BallWindow::~BallWindow()", referenced from: 
     vtable for BallWindowin moc_DesktopMain.cxx.o 
    "non-virtual thunk to BallGLWidget::~BallGLWidget()", referenced from: 
     vtable for BallGLWidgetin moc_DesktopMain.cxx.o 
    "BallGLWidget::initializeGL()", referenced from: 
     vtable for BallGLWidgetin moc_DesktopMain.cxx.o 
    "BallWindow::~BallWindow()", referenced from: 
     vtable for BallWindowin moc_DesktopMain.cxx.o 
ld: symbol(s) not found 
collect2: ld returned 1 exit status 
make[2]: *** [GLBall] Error 1 
make[1]: *** [CMakeFiles/GLBall.dir/all] Error 2 
make: *** [all] Error 2 

這裏的DesktopMain.cpp:(注:標題略去了)

//----------------------------------------- 
//FILE-SCOPE POINTERS 
//----------------------------------------- 

static BallWindow* mainwindow; 
//----------------------------------------- 

//----------------------------------------- 
//class BallGLWidget IMPLEMENTATIONS 
//----------------------------------------- 

void BallGLWidget::initializeShaders() 
{ 
    char* vs, fs; 

    vertexShaderHandle = glCreateShader(GL_VERTEX_SHADER); 
    fragmentShaderHandle = glCreateShader(GL_FRAGMENT_SHADER); 

    vs = readFile(VERTEX_SHADER_FILE_NAME); 
    fs = readFile(FRAGMENT_SHADER_FILE_NAME); 

    const char* vv = vs, *ff = fs; 

    glShaderSource(vertexShaderHandle , 1, &vv, NULL); 
    glShaderSource(fragmentShaderHandle, 1, &ff, NULL); 

    delete[] vs; delete[] fs; 

    glCompileShader(vertexShaderHandle); 
    glCompileShader(fragmentShaderHandle); 

    programHandle = createProgram(); 

    glAttachShader(programHandle, vertexShaderHandle); 
    glAttachShader(programHandle, fragmentShaderHandle); 

    glLinkProgram(programHandle); 
    glUseProgram(programHandle); 
} 

void BallGLWidget::deleteShaders() 
{ 
    glDetachShader(programHandle, vertexShaderHandle); 
    glDetachShader(programHandle, fragmentShaderHandle); 

    glDeleteShader(vertexShaderHandle); 
    glDeleteShader(fragmentShaderHandle); 

    glDeleteProgram(programHandle); 
} 

GLuint BallGLWidget::loadTexture(const char* fptr) 
{ 
    QImage* img = new QImage(); 
    if(!img->load(fptr)) 
    { 
     //error loading image, handle error 
    } 

    //bind the texture to the current context 
    GLuint texHandle = bindTexture(&img); 

    delete img; 

    return texHandle; 
} 

void BallGLWidget::initializeGL() 
{ 
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 

    initializeShaders(); 

    glBindAttribLocation(VERTEX_POS_NUM, VERTEX_POS_ATTRIB_NAME); 
    glBindAttribLocation(TEX_POS_NUM, TEX_COORD_ATTRIB_NAME); 
    glBindAttribLocation(COLOR_POS_NUM, COLOR_ATTRIB_NAME); 

    glEnableVertexArray(VERTEX_POS_NAME); 
    glEnableVertexArray(TEX_POS_NUM); 
    glEnableVertexArray(COLOR_POS_NUM); 

    ball_texture_handle = loadTexture(BALL_IMAGE_PATH); 

    samplerUniformLocation = 
      glGetUniformLocation(programHandle, BALL_SAMPLER_NAME); 

    glActiveTexture(GL_TEXTURE0 + samplerUniformLocation); 

    //bind it in initialization because we're only using 
    //1 texture in the program 
    glBindTexture(GL_TEXTURE_2D, ball_texture_handle); 

    //construct C++ objects 
    ball = new Ball(BALL_DIAMETER); 
    colorTrail = new ColorTrail(programHandle); 
} 

void BallGLWidget::paintGL() 
{ 
    glClear(GL_COLOR_BUFFER_BIT); 

    ball  ->draw(); 
    colorTrail->add_segment(ball->getTopLeftCornerCoord(), 
          ball->getLeftCornerCoord()); 

    ball->updatePhysics(); 
} 

void BallGLWidget::resizeGL(int width, int height) 
{ 
    //should this be the constants or the parameters? 
    //where are the camera functions in OpenGL ES 2... 
    glViewport(0, 0, BOX_WIDTH, BOX_HEIGHT); 
} 

void BallGLWidget::cleanupGL() 
{ 
    deleteShaders(); 
} 

BallGLWidget::BallGLWidget(QWidget *parent = 0) 
{ 

} 

BallGLWidget::~BallGLWidget() 
{ 
    cleanupGL(); 
    delete ball; 
    delete colorTrail; 
} 

//----------------------------------------- 
//class BallWindow IMPLEMENTATIONS 
//----------------------------------------- 

void BallWindow::createWindow() 
{ 
    //minimum size is defined in GlobalConstants.h 
    setMinimumSize(QSize(BOX_WIDTH, BOX_HEIGHT)); 

    BallGLWidget* glWidget = new BallGLWidget; 

    setAttribute(Qt::WA_DeleteOnClose); 

    setCentralWidget(glWidget); 
} 

BallWindow::BallWindow(QWidget * parent = 0) 
{ 
    createWindow(); 
} 

BallWindow::~BallWindow() 
{ 

} 


//----------------------------------------- 
//main FUNCTION 
//----------------------------------------- 
int main(int argc, const char* argv[]) 
{ 
    QApplication application(argc, argv); 
    mainwindow = new BallWindow(); 
    BallWindow->show(); 

    return application.exec(); 
} 

DesktopMain.h:

class BallGLWidget : public QGLWidget 
{ 
    Q_OBJECT 

private: 
    //---------------------------- 
    //HANDLES 
    //---------------------------- 
    GLuint ball_texture_handle; 
    GLuint vertexShaderHandle, fragmentShaderHandle; 
    GLuint programHandle; 
    GLuint samplerUniformLocation; 

    //---------------------------- 
    //PRIVATE VARIABLES 
    //---------------------------- 
    Ball*  ball; 
    ColorTrail* colorTrail; 

//---------------------------- 
//PRIVATE METHODS 
//---------------------------- 
void initializeShaders(); 
void deleteShaders(); 

GLuint loadTexture(const char* fptr); 


protected: 
    void initializeGL(); 
    void paintGL(); 
    void resizeGL(int width, int height); 
    void cleanupGL(); 

public: 
    BallGLWidget(QWidget *parent = 0); 
    virtual ~BallGLWidget(); 
}; 


class BallWindow : public QMainWindow 
{ 
    Q_OBJECT 
private: 
    void createWindow(); 
public: 
    BallWindow(QWidget *parent = 0); 
    ~BallWindow(); 
}; 

//void onProgramExit(); 

int main(int argc, const char* argv[]); 

編輯:我爲這個項目使用CMake。對不起忘了在原來的問題中發佈這個!

這裏的的CMakeLists.txt:

cmake_minimum_required(VERSION 2.6) 

project(GLBall) 

SET(ENV{SOURCES} src/Ball.cpp src/Ball.h src/ColorTrail.cpp src/ColorTrail.h src/DesktopMain.h src/DesktopMain.cpp src/GlobalConstants.h src/ShaderOps.h) 

FIND_PACKAGE(Qt4 REQUIRED) 
FIND_PACKAGE(OpenGL REQUIRED) 

SET(QT_USE_QTOPENGL TRUE) 

QT4_WRAP_CPP(HEADERS_MOC src/DesktopMain.h) 

INCLUDE(${QT_USE_FILE}) 

INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) 

ADD_DEFINITIONS(${QT_DEFINITIONS}) 

SET(CMAKE_EXE_COMPILER_FLAGS -g -v) 

ADD_EXECUTABLE(GLBall ${SOURCES} ${HEADERS_MOC}) 

TARGET_LINK_LIBRARIES(GLBall ${QT_LIBRARIES}) 
+0

我開始賞金,因爲我忘了在原始問題中包含我正在使用CMake來構建這個項目,所以我沒有太多直接控制qmake(據我所知) – Prime

回答

2

我相信

SET(ENV{SOURCES} src/Ball.cpp src/Ball.h src/ColorTrail.cpp src/ColorTrail.h src/DesktopMain.h src/DesktopMain.cpp src/GlobalConstants.h src/ShaderOps.h) 

應該

SET(SOURCES src/Ball.cpp src/Ball.h src/ColorTrail.cpp src/ColorTrail.h src/DesktopMain.h src/DesktopMain.cpp src/GlobalConstants.h src/ShaderOps.h) 

因爲你引用${SOURCES}後,沒有一個環境變量。這當然可以做到。實際上,「sources」不應該包含頭文件(像你在做的那樣將頭文件與Q_OBJECT宏一起傳遞給qt4_wrap_cpp)。下面是修改後的文件:

cmake_minimum_required(VERSION 2.6) 

project(GLBall) 

set(SOURCES src/Ball.cpp src/ColorTrail.cpp src/DesktopMain.cpp) 

find_package(Qt4 REQUIRED) 
find_package(OpenGL REQUIRED) 
set(QT_USE_QTOPENGL TRUE) 
include(${QT_USE_FILE}) 

include_directories(${CMAKE_CURRENT_BINARY_DIR}) 

add_definitions(${QT_DEFINITIONS}) 

set(CMAKE_EXE_COMPILER_FLAGS -g -v) 

qt4_wrap_cpp(HEADERS_MOC src/DesktopMain.h) 

add_executable(GLBall ${SOURCES} ${HEADERS_MOC}) 
target_link_libraries(GLBall ${QT_LIBRARIES}) 

此外,而不是手動設置編譯器標誌,你可以改變CMAKE_BUILD_TYPE爲「Debug」(或「發行」)當您運行ccmakecmake-gui


可能有無關,但爲了以防萬一,我通常把qt4_wrap_cpp電話include(${QT_USE_FILE})後。

+0

謝謝!那就是訣竅 – Prime

1

嘗試清理項目運行的qmake。然後重建。

2

像盧卡說,請確保您正常運行的qmake,這裏是通常的步驟 -

$ qmake -project 
$ qmake 
$ make 

($是shell提示符)

如果不解決這個問題,也許你應該讓我們知道你的目錄結構。

+0

嗯哦 我忘了一個重要的細節!我正在運行CMake 我對此非常抱歉 – Prime

+0

我應該發佈CMakeLists.txt嗎? – Prime

+0

後來看到你得到了答案;) 順便說一句當我需要檢查我的CMake + Qt的時候,我發現這個頁面很有幫助http://developer.qt.nokia.com/quarterly/view/using_cmake_to_build_qt_projects –