使用 g++ 链接对象时的问题

Posted

技术标签:

【中文标题】使用 g++ 链接对象时的问题【英文标题】:problems when linking objects with g++ 【发布时间】:2012-05-06 04:31:56 【问题描述】:

我正在尝试用 c++ 中的 opengl 制作一个简单的 obj 加载器。 用一个命令编译一切都很好,

g++ -o main main.cpp timer.cpp screen.cpp obj_loader.cpp `sdl-config --cflags --libs` `pkg-config --cflags --libs glu`

不返回错误。

单独编译对象也可以正常工作,

g++ main.cpp -o main.o -c -Wall `sdl-config --cflags --libs` `pkg-config glu --cflags --libs`
g++ obj_loader.cpp -o obj_loader.o -c -Wall `sdl-config --cflags --libs` `pkg-config glu --cflags --libs`
g++ timer.cpp -o timer.o -c -Wall `sdl-config --cflags --libs` `pkg-config glu --cflags --libs`
g++ screen.cpp -o screen.o -c -Wall `sdl-config --cflags --libs` `pkg-config glu --cflags --libs`

也不返回任何错误。

但是,在运行决赛时

g++ main.o obj_loader.o timer.o screen.o -o main

我收到一堆未定义的引用错误:

main.o: In function `draw()':
main.cpp:(.text+0x1d): undefined reference to `glColor3f'
main.cpp:(.text+0x27): undefined reference to `glBegin'
main.cpp:(.text+0x36): undefined reference to `glVertex2i'
main.cpp:(.text+0x45): undefined reference to `glVertex2i'
main.cpp:(.text+0x54): undefined reference to `glVertex2i'
main.cpp:(.text+0x63): undefined reference to `glVertex2i'
main.cpp:(.text+0x68): undefined reference to `glEnd'
main.o: In function `main':
main.cpp:(.text+0xf8): undefined reference to `SDL_PollEvent'
main.cpp:(.text+0x10b): undefined reference to `glClear'
main.cpp:(.text+0x115): undefined reference to `SDL_GL_SwapBuffers'
main.cpp:(.text+0x11a): undefined reference to `glFinish'
main.cpp:(.text+0x14e): undefined reference to `SDL_Delay'
timer.o: In function `Timer::start()':
timer.cpp:(.text+0x4d): undefined reference to `SDL_GetTicks'
timer.o: In function `Timer::pause()':
timer.cpp:(.text+0xa6): undefined reference to `SDL_GetTicks'
timer.o: In function `Timer::unpause()':
timer.cpp:(.text+0xe5): undefined reference to `SDL_GetTicks'
timer.o: In function `Timer::tick()':
timer.cpp:(.text+0x136): undefined reference to `SDL_GetTicks'
timer.o: In function `Timer::get_ticks()':
timer.cpp:(.text+0x172): undefined reference to `SDL_GetTicks'
screen.o: In function `init()':
screen.cpp:(.text+0xa): undefined reference to `SDL_Init'
screen.cpp:(.text+0x31): undefined reference to `SDL_SetVideoMode'
screen.cpp:(.text+0x64): undefined reference to `SDL_WM_SetCaption'
screen.o: In function `init_GL()':
screen.cpp:(.text+0x80): undefined reference to `glClearColor'
screen.cpp:(.text+0x8a): undefined reference to `glMatrixMode'
screen.cpp:(.text+0x8f): undefined reference to `glLoadIdentity'
screen.cpp:(.text+0xc0): undefined reference to `glOrtho'
screen.cpp:(.text+0xca): undefined reference to `glMatrixMode'
screen.cpp:(.text+0xcf): undefined reference to `glLoadIdentity'
screen.cpp:(.text+0xd4): undefined reference to `glGetError'
screen.o: In function `clean_up()':
screen.cpp:(.text+0xf4): undefined reference to `SDL_Quit'
collect2: ld returned 1 exit status

我包含的库是:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

#include "SDL/SDL.h"
#include "SDL/SDL_opengl.h"

#include "GL/gl.h"
#include "GL/glu.h"

还有我的 Makefile:

CC=g++
SDL_FLAGS=`sdl-config --cflags --libs`
GL_FLAGS=`pkg-config glu --cflags --libs`

CFLAGS=-c -Wall

FLAGS=$(CFLAGS) $(SDL_FLAGS) $(GL_FLAGS)
LDFLAGS=

SOURCES=main.cpp obj_loader.cpp timer.cpp screen.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=main

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(OBJECTS) -o $@ $(LDFLAGS)

.cpp.o:
    $(CC) $< -o $@ $(FLAGS)

clean:
    rm -f *o main

【问题讨论】:

好吧,你给出的命令行作为例子,那个不起作用...没有显示你链接所需的库,而那个起作用的。您的 Makefile 似乎有完全相同的问题。我不希望它起作用。 【参考方案1】:

是的...--libs 返回的所有这些东西?您需要这些才能正确链接最终的可执行文件。

【讨论】:

【参考方案2】:

sdl-configpkg-config 有两个标志:--cflags--libs。当您将源文件编译为目标文件时,需要这些标志中的第一个。链接时需要这些标志中的第二个。当您使用单个命令编译所有内容时,两个阶段都由单个命令处理,因此您很自然应该同时将 --cflags--libs 传递给 sdl-configpkg-config。现在您已经分离了这些阶段,您需要在正确的时间将正确的选项传递给 sdl-configpkg-config

g++ main.cpp -o main.o -c -Wall `sdl-config --cflags` `pkg-config glu --cflags`
g++ obj_loader.cpp -o obj_loader.o -c -Wall `sdl-config --cflags` `pkg-config glu --cflags`
g++ timer.cpp -o timer.o -c -Wall `sdl-config --cflags` `pkg-config glu --cflags`
g++ screen.cpp -o screen.o -c -Wall `sdl-config --cflags` `pkg-config glu --cflags`

g++ main.o obj_loader.o timer.o screen.o -o main `sdl-config --libs` `pkg-config glu --libs`

在您的 makefile 中,这意味着按如下方式配置变量:(我还对您的 Makefile 进行了一些其他小修复)

CC=g++
LD=g++

CFLAGS=-c -Wall $(shell sdl-config --cflags) $(shell pkg-config glu --cflags)
LDFLAGS=$(shell sdl-config --libs) $(shell pkg-config glu --libs)

SOURCES=main.cpp obj_loader.cpp timer.cpp screen.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=main

all: $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(LD) $(LDFLAGS) $(OBJECTS) -o $@

.cpp.o:
    $(CC) $(CFLAGS) $< -o $@

clean:
    rm -f *.o main

关于你的 Makefile 有很多要批评的地方——你可能会在这里删除大部分的动作行,因为 GNU Make 将它们作为隐式内置的。您可能需要添加规则来指定.o 文件的依赖关系——每个.cpp 文件可能包含.h 文件,并且make 需要知道当它们所依赖的.h 文件时重新编译.cpp 文件变化。

【讨论】:

并且makefile可以使用CFLAGS:=$(shell sdl-config --cflags) etc.来避免为每个编译的.o重新运行反引号shell命令。【参考方案3】:

我没有看到任何-llibraryname 告诉 g++ 与 opengl 链接。我本来希望在构建 main 本身的 g++ 行上看到这一点(即以“main”结尾的行)。据我所知,.o 文件本身不包含有关在何处找到库以解析其引用的信息。该信息必须在命令行上以-l 开关的形式传递。

【讨论】:

以上是关于使用 g++ 链接对象时的问题的主要内容,如果未能解决你的问题,请参考以下文章

检查“与外部库链接”示例时的矛盾结果

g++ 尝试(失败)静态链接到 libstdc++ 以获取共享对象

如何在 g++ 中使用不同的 STL

如何使用 G++/LD 将库链接到共享对象

如何使用 Makefile (g++) 仅将一些文件链接到对象?

使用g ++链接共享库