按照OpenGL编程指南的建议,我决定看一下Nate Robin的OpenGL教程,更确切地说,是编译运行该教程给出的transformation.c。虽然该教程已经给出了可以在windows下直接运行的exe文件,但是,请相信我,离开windows,在linux下用OpenGL会有不一样的感受。
其实,我是来帮你消灭bug的。
曾经以为,编译这个transformation.c是一件很简单的事情:gcc -lglut transformation.c。结果警告和错误一堆:
wy@wy-Vostro-260s:/media/d/wy/opengl/tutor/tutor$ gcc -lglut transformation.c transformation.c: 在函数‘main’中: transformation.c:710:5: 警告: 传递‘glutKeyboardFunc’的第 1 个参数时在不兼容的指针类型间转换 [默认启用] /usr/include/GL/freeglut_std.h:467:26: 附注: 需要类型‘void (*)(unsigned char, int, int)’,但实参的类型为‘void (*)(char, int, int)’ transformation.c:715:5: 警告: 传递‘glutKeyboardFunc’的第 1 个参数时在不兼容的指针类型间转换 [默认启用] /usr/include/GL/freeglut_std.h:467:26: 附注: 需要类型‘void (*)(unsigned char, int, int)’,但实参的类型为‘void (*)(char, int, int)’ transformation.c:723:5: 警告: 传递‘glutKeyboardFunc’的第 1 个参数时在不兼容的指针类型间转换 [默认启用] /usr/include/GL/freeglut_std.h:467:26: 附注: 需要类型‘void (*)(unsigned char, int, int)’,但实参的类型为‘void (*)(char, int, int)’ transformation.c:741:5: 警告: 传递‘glutKeyboardFunc’的第 1 个参数时在不兼容的指针类型间转换 [默认启用] /usr/include/GL/freeglut_std.h:467:26: 附注: 需要类型‘void (*)(unsigned char, int, int)’,但实参的类型为‘void (*)(char, int, int)’ /tmp/cc7rpOXR.o: In function `setfont': transformation.c:(.text+0xb): undefined reference to `glutBitmapHelvetica10' transformation.c:(.text+0x43): undefined reference to `glutBitmapHelvetica12' transformation.c:(.text+0x5c): undefined reference to `glutBitmapHelvetica18' transformation.c:(.text+0x93): undefined reference to `glutBitmapTimesRoman10' transformation.c:(.text+0xa3): undefined reference to `glutBitmapTimesRoman24' transformation.c:(.text+0xd7): undefined reference to `glutBitmap8By13' transformation.c:(.text+0x10b): undefined reference to `glutBitmap9By15' /tmp/cc7rpOXR.o: In function `drawstr': transformation.c:(.text+0x16b): undefined reference to `glRasterPos2i' transformation.c:(.text+0x196): undefined reference to `glutBitmapCharacter' /tmp/cc7rpOXR.o: In function `cell_draw': transformation.c:(.text+0x1df): undefined reference to `glColor3ub' transformation.c:(.text+0x209): undefined reference to `glColor3ub' transformation.c:(.text+0x243): undefined reference to `glColor3ub' /tmp/cc7rpOXR.o: In function `drawmodel': transformation.c:(.text+0x37e): undefined reference to `glmReadOBJ' transformation.c:(.text+0x3a5): undefined reference to `glmUnitize' transformation.c:(.text+0x3b4): undefined reference to `glmFacetNormals' transformation.c:(.text+0x3ca): undefined reference to `glmVertexNormals' transformation.c:(.text+0x3df): undefined reference to `glmDraw' /tmp/cc7rpOXR.o: In function `drawaxes': transformation.c:(.text+0x403): undefined reference to `glColor3ub' transformation.c:(.text+0x40f): undefined reference to `glBegin' transformation.c:(.text+0x42e): undefined reference to `glVertex3f' transformation.c:(.text+0x44d): undefined reference to `glVertex3f' transformation.c:(.text+0x46c): undefined reference to `glVertex3f' transformation.c:(.text+0x48b): undefined reference to `glVertex3f' transformation.c:(.text+0x4aa): undefined reference to `glVertex3f' /tmp/cc7rpOXR.o:transformation.c:(.text+0x4c9): more undefined references to `glVertex3f' follow /tmp/cc7rpOXR.o: In function `drawaxes': transformation.c:(.text+0x50c): undefined reference to `glEnd' transformation.c:(.text+0x518): undefined reference to `glBegin' transformation.c:(.text+0x537): undefined reference to `glVertex3f' transformation.c:(.text+0x556): undefined reference to `glVertex3f' transformation.c:(.text+0x575): undefined reference to `glVertex3f' transformation.c:(.text+0x594): undefined reference to `glVertex3f' transformation.c:(.text+0x5b3): undefined reference to `glVertex3f' /tmp/cc7rpOXR.o:transformation.c:(.text+0x5d2): more undefined references to `glVertex3f' follow /tmp/cc7rpOXR.o: In function `drawaxes': transformation.c:(.text+0x615): undefined reference to `glEnd' transformation.c:(.text+0x621): undefined reference to `glBegin' transformation.c:(.text+0x640): undefined reference to `glVertex3f' transformation.c:(.text+0x65f): undefined reference to `glVertex3f' transformation.c:(.text+0x67e): undefined reference to `glVertex3f' transformation.c:(.text+0x69d): undefined reference to `glVertex3f' transformation.c:(.text+0x6bc): undefined reference to `glVertex3f' /tmp/cc7rpOXR.o:transformation.c:(.text+0x6db): more undefined references to `glVertex3f' follow /tmp/cc7rpOXR.o: In function `drawaxes': transformation.c:(.text+0x71e): undefined reference to `glEnd' transformation.c:(.text+0x73a): undefined reference to `glColor3ub' transformation.c:(.text+0x759): undefined reference to `glRasterPos3f' transformation.c:(.text+0x768): undefined reference to `glutBitmapHelvetica12' transformation.c:(.text+0x76d): undefined reference to `glutBitmapCharacter' transformation.c:(.text+0x78c): undefined reference to `glRasterPos3f' transformation.c:(.text+0x79b): undefined reference to `glutBitmapHelvetica12' transformation.c:(.text+0x7a0): undefined reference to `glutBitmapCharacter' transformation.c:(.text+0x7bf): undefined reference to `glRasterPos3f' transformation.c:(.text+0x7ce): undefined reference to `glutBitmapHelvetica12' transformation.c:(.text+0x7d3): undefined reference to `glutBitmapCharacter' /tmp/cc7rpOXR.o: In function `normalize': transformation.c:(.text+0xbb2): undefined reference to `sqrt' /tmp/cc7rpOXR.o: In function `main_reshape': transformation.c:(.text+0xc1f): undefined reference to `glViewport' transformation.c:(.text+0xc2b): undefined reference to `glMatrixMode' transformation.c:(.text+0xc30): undefined reference to `glLoadIdentity' transformation.c:(.text+0xc50): undefined reference to `gluOrtho2D' transformation.c:(.text+0xc5c): undefined reference to `glMatrixMode' transformation.c:(.text+0xc61): undefined reference to `glLoadIdentity' transformation.c:(.text+0xccb): undefined reference to `glutSetWindow' transformation.c:(.text+0xcdf): undefined reference to `glutPositionWindow' transformation.c:(.text+0xcf7): undefined reference to `glutReshapeWindow' transformation.c:(.text+0xd04): undefined reference to `glutSetWindow' transformation.c:(.text+0xd1c): undefined reference to `glutPositionWindow' transformation.c:(.text+0xd34): undefined reference to `glutReshapeWindow' transformation.c:(.text+0xd41): undefined reference to `glutSetWindow' transformation.c:(.text+0xd59): undefined reference to `glutPositionWindow' transformation.c:(.text+0xd7c): undefined reference to `glutReshapeWindow' /tmp/cc7rpOXR.o: In function `main_display': transformation.c:(.text+0xdac): undefined reference to `glClearColor' transformation.c:(.text+0xdb8): undefined reference to `glClear' transformation.c:(.text+0xdd4): undefined reference to `glColor3ub' transformation.c:(.text+0xe49): undefined reference to `glutSwapBuffers' /tmp/cc7rpOXR.o: In function `world_reshape': transformation.c:(.text+0xf23): undefined reference to `glViewport' transformation.c:(.text+0xf2f): undefined reference to `glMatrixMode' transformation.c:(.text+0xf34): undefined reference to `glLoadIdentity' transformation.c:(.text+0xf62): undefined reference to `gluPerspective' transformation.c:(.text+0xf6e): undefined reference to `glMatrixMode' transformation.c:(.text+0xf73): undefined reference to `glLoadIdentity' transformation.c:(.text+0xf92): undefined reference to `glTranslatef' transformation.c:(.text+0xfba): undefined reference to `glRotatef' transformation.c:(.text+0xfe2): undefined reference to `glClearColor' transformation.c:(.text+0xfee): undefined reference to `glEnable' transformation.c:(.text+0xffa): undefined reference to `glEnable' /tmp/cc7rpOXR.o: In function `world_display': transformation.c:(.text+0x1083): undefined reference to `glClear' transformation.c:(.text+0x109a): undefined reference to `glEnable' transformation.c:(.text+0x109f): undefined reference to `glPushMatrix' transformation.c:(.text+0x10ab): undefined reference to `glMultMatrixd' transformation.c:(.text+0x10c6): undefined reference to `glLightfv' transformation.c:(.text+0x10cb): undefined reference to `glPopMatrix' transformation.c:(.text+0x10dc): undefined reference to `glDisable' transformation.c:(.text+0x10e1): undefined reference to `glPushMatrix' transformation.c:(.text+0x10ed): undefined reference to `glMultMatrixd' transformation.c:(.text+0x1108): undefined reference to `glLightfv' transformation.c:(.text+0x110d): undefined reference to `glPushMatrix' transformation.c:(.text+0x1129): undefined reference to `glColor3ub' transformation.c:(.text+0x1135): undefined reference to `glBegin' transformation.c:(.text+0x1154): undefined reference to `glVertex3f' transformation.c:(.text+0x1179): undefined reference to `glVertex3f' transformation.c:(.text+0x11a4): undefined reference to `glVertex3f' transformation.c:(.text+0x11cf): undefined reference to `glVertex3f' transformation.c:(.text+0x11f4): undefined reference to `glVertex3f' /tmp/cc7rpOXR.o:transformation.c:(.text+0x121f): more undefined references to `glVertex3f' follow /tmp/cc7rpOXR.o: In function `world_display': transformation.c:(.text+0x1274): undefined reference to `glEnd' transformation.c:(.text+0x1290): undefined reference to `glColor3ub' transformation.c:(.text+0x12bb): undefined reference to `glRasterPos3f' transformation.c:(.text+0x12ca): undefined reference to `glutBitmapHelvetica12' transformation.c:(.text+0x12cf): undefined reference to `glutBitmapCharacter' transformation.c:(.text+0x12eb): undefined reference to `glColor3ub' transformation.c:(.text+0x130a): undefined reference to `glScalef' transformation.c:(.text+0x1314): undefined reference to `glPopMatrix' transformation.c:(.text+0x1334): undefined reference to `glMultMatrixd' transformation.c:(.text+0x1353): undefined reference to `glColor3f' transformation.c:(.text+0x135f): undefined reference to `glBegin' transformation.c:(.text+0x137b): undefined reference to `glVertex3i' transformation.c:(.text+0x1397): undefined reference to `glVertex3i' transformation.c:(.text+0x13b3): undefined reference to `glVertex3i' transformation.c:(.text+0x13cf): undefined reference to `glVertex3i' transformation.c:(.text+0x13d4): undefined reference to `glEnd' transformation.c:(.text+0x13f0): undefined reference to `glColor3ub' transformation.c:(.text+0x13fc): undefined reference to `glBegin' transformation.c:(.text+0x1418): undefined reference to `glVertex3i' transformation.c:(.text+0x1434): undefined reference to `glVertex3i' transformation.c:(.text+0x1450): undefined reference to `glVertex3i' transformation.c:(.text+0x146c): undefined reference to `glVertex3i' transformation.c:(.text+0x1488): undefined reference to `glVertex3i' /tmp/cc7rpOXR.o:transformation.c:(.text+0x14a4): more undefined references to `glVertex3i' follow /tmp/cc7rpOXR.o: In function `world_display': transformation.c:(.text+0x14e1): undefined reference to `glEnd' transformation.c:(.text+0x14ed): undefined reference to `glEnable' transformation.c:(.text+0x1501): undefined reference to `glBlendFunc' transformation.c:(.text+0x1529): undefined reference to `glColor4f' transformation.c:(.text+0x1535): undefined reference to `glBegin' transformation.c:(.text+0x1551): undefined reference to `glVertex3i' transformation.c:(.text+0x156d): undefined reference to `glVertex3i' transformation.c:(.text+0x1589): undefined reference to `glVertex3i' transformation.c:(.text+0x15a5): undefined reference to `glVertex3i' transformation.c:(.text+0x15aa): undefined reference to `glEnd' transformation.c:(.text+0x15b6): undefined reference to `glDisable' transformation.c:(.text+0x15bb): undefined reference to `glPopMatrix' transformation.c:(.text+0x15c0): undefined reference to `glutSwapBuffers' /tmp/cc7rpOXR.o: In function `screen_reshape': transformation.c:(.text+0x1612): undefined reference to `glViewport' transformation.c:(.text+0x161e): undefined reference to `glMatrixMode' transformation.c:(.text+0x1623): undefined reference to `glLoadIdentity' transformation.c:(.text+0x1651): undefined reference to `gluPerspective' transformation.c:(.text+0x1665): undefined reference to `glGetDoublev' transformation.c:(.text+0x1671): undefined reference to `glMatrixMode' transformation.c:(.text+0x1676): undefined reference to `glLoadIdentity' transformation.c:(.text+0x16e6): undefined reference to `gluLookAt' transformation.c:(.text+0x171c): undefined reference to `glRotatef' transformation.c:(.text+0x173d): undefined reference to `glTranslatef' transformation.c:(.text+0x1760): undefined reference to `glTranslatef' transformation.c:(.text+0x178b): undefined reference to `glRotatef' transformation.c:(.text+0x17ac): undefined reference to `glScalef' transformation.c:(.text+0x17c0): undefined reference to `glGetDoublev' transformation.c:(.text+0x17e8): undefined reference to `glClearColor' transformation.c:(.text+0x17f4): undefined reference to `glEnable' transformation.c:(.text+0x1800): undefined reference to `glEnable' transformation.c:(.text+0x180c): undefined reference to `glEnable' /tmp/cc7rpOXR.o: In function `screen_display': transformation.c:(.text+0x1824): undefined reference to `glClear' transformation.c:(.text+0x182e): undefined reference to `glutSwapBuffers' /tmp/cc7rpOXR.o: In function `screen_menu': transformation.c:(.text+0x18a0): undefined reference to `glmReadOBJ' transformation.c:(.text+0x18c7): undefined reference to `glmUnitize' transformation.c:(.text+0x18d6): undefined reference to `glmFacetNormals' transformation.c:(.text+0x18ec): undefined reference to `glmVertexNormals' /tmp/cc7rpOXR.o: In function `command_reshape': transformation.c:(.text+0x191b): undefined reference to `glViewport' transformation.c:(.text+0x1927): undefined reference to `glMatrixMode' transformation.c:(.text+0x192c): undefined reference to `glLoadIdentity' transformation.c:(.text+0x194c): undefined reference to `gluOrtho2D' transformation.c:(.text+0x1958): undefined reference to `glMatrixMode' transformation.c:(.text+0x195d): undefined reference to `glLoadIdentity' transformation.c:(.text+0x1985): undefined reference to `glClearColor' /tmp/cc7rpOXR.o: In function `command_display': transformation.c:(.text+0x1999): undefined reference to `glClear' transformation.c:(.text+0x1a4e): undefined reference to `glColor3ub' transformation.c:(.text+0x1cac): undefined reference to `glColor3ub' transformation.c:(.text+0x1ccd): undefined reference to `glutSwapBuffers' /tmp/cc7rpOXR.o: In function `redisplay_all': transformation.c:(.text+0x1fbc): undefined reference to `glutSetWindow' transformation.c:(.text+0x1fc1): undefined reference to `glutPostRedisplay' transformation.c:(.text+0x1fce): undefined reference to `glutSetWindow' transformation.c:(.text+0x1feb): undefined reference to `glutPostRedisplay' transformation.c:(.text+0x1ff8): undefined reference to `glutSetWindow' transformation.c:(.text+0x2015): undefined reference to `glutPostRedisplay' /tmp/cc7rpOXR.o: In function `main': transformation.c:(.text+0x202c): undefined reference to `glutInitDisplayMode' transformation.c:(.text+0x2040): undefined reference to `glutInitWindowSize' transformation.c:(.text+0x2054): undefined reference to `glutInitWindowPosition' transformation.c:(.text+0x2066): undefined reference to `glutInit' transformation.c:(.text+0x2072): undefined reference to `glutCreateWindow' transformation.c:(.text+0x2083): undefined reference to `glutReshapeFunc' transformation.c:(.text+0x208f): undefined reference to `glutDisplayFunc' transformation.c:(.text+0x209c): undefined reference to `glutKeyboardFunc' transformation.c:(.text+0x20c9): undefined reference to `glutCreateSubWindow' transformation.c:(.text+0x20da): undefined reference to `glutReshapeFunc' transformation.c:(.text+0x20e6): undefined reference to `glutDisplayFunc' transformation.c:(.text+0x20f3): undefined reference to `glutKeyboardFunc' transformation.c:(.text+0x20ff): undefined reference to `glutCreateMenu' transformation.c:(.text+0x2113): undefined reference to `glutAddMenuEntry' transformation.c:(.text+0x211f): undefined reference to `glutAttachMenu' transformation.c:(.text+0x214c): undefined reference to `glutCreateSubWindow' transformation.c:(.text+0x215d): undefined reference to `glutReshapeFunc' transformation.c:(.text+0x2169): undefined reference to `glutDisplayFunc' transformation.c:(.text+0x2176): undefined reference to `glutKeyboardFunc' transformation.c:(.text+0x2182): undefined reference to `glutCreateMenu' transformation.c:(.text+0x2196): undefined reference to `glutAddMenuEntry' transformation.c:(.text+0x21aa): undefined reference to `glutAddMenuEntry' transformation.c:(.text+0x21be): undefined reference to `glutAddMenuEntry' transformation.c:(.text+0x21d2): undefined reference to `glutAddMenuEntry' transformation.c:(.text+0x21e6): undefined reference to `glutAddMenuEntry' /tmp/cc7rpOXR.o:transformation.c:(.text+0x21fa): more undefined references to `glutAddMenuEntry' follow /tmp/cc7rpOXR.o: In function `main': transformation.c:(.text+0x2242): undefined reference to `glutAttachMenu' transformation.c:(.text+0x226f): undefined reference to `glutCreateSubWindow' transformation.c:(.text+0x2280): undefined reference to `glutReshapeFunc' transformation.c:(.text+0x228c): undefined reference to `glutDisplayFunc' transformation.c:(.text+0x2298): undefined reference to `glutMotionFunc' transformation.c:(.text+0x22a4): undefined reference to `glutMouseFunc' transformation.c:(.text+0x22b1): undefined reference to `glutKeyboardFunc' transformation.c:(.text+0x22bd): undefined reference to `glutCreateMenu' transformation.c:(.text+0x22d1): undefined reference to `glutAddMenuEntry' transformation.c:(.text+0x22e5): undefined reference to `glutAddMenuEntry' transformation.c:(.text+0x22f9): undefined reference to `glutAddMenuEntry' transformation.c:(.text+0x230d): undefined reference to `glutAddMenuEntry' transformation.c:(.text+0x2321): undefined reference to `glutAddMenuEntry' /tmp/cc7rpOXR.o:transformation.c:(.text+0x2335): more undefined references to `glutAddMenuEntry' follow /tmp/cc7rpOXR.o: In function `main': transformation.c:(.text+0x2341): undefined reference to `glutAttachMenu' transformation.c:(.text+0x234b): undefined reference to `glutMainLoop' /tmp/cc7rpOXR.o:(.data+0x1b0): undefined reference to `glutBitmapTimesRoman10' collect2: ld 返回 1
遭受如此打击,是不是感觉不会再爱了?说时迟那时快,神武的gcc文档出现了!同学们,请打开gcc官方文档Using the GNU Compiler Collection的第154页,3.13节,Options for Linking!请你双目直视-l选项的解释,发现这样一段话:
“It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file ‘foo.o’ but before ‘bar.o’. If ‘bar.o’ refers to functions in ‘z’, those functions may not be loaded.”
这段话告诉我们,-l选项的位置是有讲究的:如果目标文件bar.o中引用了库z中的函数,那么这些函数是不会被加载的。但是,如果foo.o中引用了库z中的函数,那就没有问题。假设foo.o和bar.o都引用了库z中的函数func,链接过程应该是这样的:foo.o中遇到无法解析的函数符号func,因而向右查找链接库,发现选项lz,于是到z中查找,发现函数func,函数符号顺利解析;bar.o中同样遇到无法解析的函数符号func,向右查找链接库,未发现可用链接库,函数符号解析失败。
根据上述理论,编译链接transformation.c的命令行貌似应该这样写:gcc transformation.c -lglut -lGL -lGLU。于是得到下面的结果:
transformation.c: 在函数‘main’中: transformation.c:710:5: 警告: 传递‘glutKeyboardFunc’的第 1 个参数时在不兼容的指针类型间转换 [默认启用] /usr/include/GL/freeglut_std.h:467:26: 附注: 需要类型‘void (*)(unsigned char, int, int)’,但实参的类型为‘void (*)(char, int, int)’ transformation.c:715:5: 警告: 传递‘glutKeyboardFunc’的第 1 个参数时在不兼容的指针类型间转换 [默认启用] /usr/include/GL/freeglut_std.h:467:26: 附注: 需要类型‘void (*)(unsigned char, int, int)’,但实参的类型为‘void (*)(char, int, int)’ transformation.c:723:5: 警告: 传递‘glutKeyboardFunc’的第 1 个参数时在不兼容的指针类型间转换 [默认启用] /usr/include/GL/freeglut_std.h:467:26: 附注: 需要类型‘void (*)(unsigned char, int, int)’,但实参的类型为‘void (*)(char, int, int)’ transformation.c:741:5: 警告: 传递‘glutKeyboardFunc’的第 1 个参数时在不兼容的指针类型间转换 [默认启用] /usr/include/GL/freeglut_std.h:467:26: 附注: 需要类型‘void (*)(unsigned char, int, int)’,但实参的类型为‘void (*)(char, int, int)’ /tmp/ccZaUWwu.o: In function `drawmodel': transformation.c:(.text+0x37e): undefined reference to `glmReadOBJ' transformation.c:(.text+0x3a5): undefined reference to `glmUnitize' transformation.c:(.text+0x3b4): undefined reference to `glmFacetNormals' transformation.c:(.text+0x3ca): undefined reference to `glmVertexNormals' transformation.c:(.text+0x3df): undefined reference to `glmDraw' /tmp/ccZaUWwu.o: In function `screen_menu': transformation.c:(.text+0x18a0): undefined reference to `glmReadOBJ' transformation.c:(.text+0x18c7): undefined reference to `glmUnitize' transformation.c:(.text+0x18d6): undefined reference to `glmFacetNormals' transformation.c:(.text+0x18ec): undefined reference to `glmVertexNormals' collect2: ld 返回 1