gcc编译出现 undefined reference to 的问题
2014-08-13 17:39
579 查看
今天去腾迅面试,虽然失败了,不过有些问题还是总结一下。
之前在用GCC编译Mysql的代码时发现一个奇怪的问题,后来调整了一下参数的顺序就好了,也没有想原因。
代码很简单:
点击(此处)折叠或打开
#include <mysql/my_global.h>
#include <mysql/mysql.h>
int main(int argc, char
**argv)
{
printf("MySQL client version: %s\n", mysql_get_client_info());
exit(0);
}
对应的Makefile文件:
点击(此处)折叠或打开
TARGET=main
CFLAGS=-Wall $(shell mysql_config --cflags --libs)
HEADER=$(mysql_config --cflags)
CC=gcc
Object=progname.c
main:$(Object)
$(CC) $(CFLAGS) -o $(TARGET) $(Object)
clean:
rm -f $(TARGET)
关键是这句:$(CC) $(CFLAGS) -o $(TARGET) $(Object),CFLAGS 放到了Object 的前面,结果编译的时候出现:
gcc -Wall -I/usr/include/mysql -DBIG_JOINS=1 -fno-strict-aliasing -g -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -lrt -ldl -o main progname.c
/tmp/ccSTALlC.o: In function `main':
/home/ufisher/Documents/tmp/mysql/progname.c:6: undefined reference to `mysql_get_client_info'
collect2: ld returned 1 exit status
make: *** [main] Error 1
如果把这句改成 $(CC) -o $(TARGET) $(Object) $(CFLAGS), 结果就对了:
gcc -o main progname.c -Wall -I/usr/include/mysql -DBIG_JOINS=1 -fno-strict-aliasing -g -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -lrt -ldl
后来看了这个链接才发现问题:http://hi.baidu.com/whiteprincer/item/d5c4e8e339d134d5eb34c9f0
main.c
点击(此处)折叠或打开
#include <stdio.h>
#include "test.h"
int main()
{
test();
return 0;
}
test.c
点击(此处)折叠或打开
#include "test.h"
#include "func.h"
void test()
{
func();
}
func.c
点击(此处)折叠或打开
#include "func.h"
void func()
{
}
这里面的调用关系为:main()->test()->func()
将test.c func.c 两个文件编译成静态库:
Makefile
点击(此处)折叠或打开
TARGET=main
main:test.a func.a main.o
gcc main.o -o $(TARGET)
func.a test.a
func.a:func.o
ar -rc func.a func.o
test.a:test.o
ar -rc test.a test.o
main.o:main.c
gcc -c main.c
test.o:test.c
gcc -c test.c
func.o:func.c
gcc -c func.c
clean:
rm -f $(TARGET) *.o *.a
注意第四句的静态库的顺序,这样执行Make的时候同样会出现 undefined reference to 问题
简单翻译一下,编译就是把C/C++的高级语言翻译成机器语言指令,编译过程是对独立的文件,并不检查函数的定义放在什么地方,也不会生成可以执行的文件,通常是生成.o(.obj)这样的文件。
而链接则要根据.o文件生成可执行的程序或库。函数未定义这样的错误都是在链接过程中产生的。编译过程如果找不到一个函数的定义,它会认为这个函数的定义放在其它文件,而链接则一定要找到第个函数的定义。
这样多个库文件在链接时就有了依赖性的问题。
再看上面的问题,由于是从.o文件生成了静态库,最后两个静态库的顺序是func.a test.a, 当链接func.a时找到func函数,它并不依赖于其它的库,但链接到test.a时找到test函数,它依赖于func,结果出现了,
从这里可以判断Gcc的链接顺序是 被依赖的库放在其它库的后面,比如test依赖func,则func.a应该放到test.a的后面。
因此把上面Makefile中的第4行改成 gcc main.o -o $(TARGET) test.a
func.a 就没有问题了。
再来看 Mysql那个示例的问题,展开的的编译命令是这样的:
gcc -o main progname.c -Wall -I/usr/include/mysql -DBIG_JOINS=1 -fno-strict-aliasing -g -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -lrt -ldl
在链接的时候 progname里面用到了动态库的函数,所以引入动态库的参数应该放在后面,反之如果放在前面,progname中的mysql_get_client_info() 就会找不到定义。
当然上面说的顺序问题都是存在于库中,包括动态库和静态库,如果把所有文件都编译成.o文件,然后直接链接成最终的程序,也不会有问题。
但对于Mysql这样的示例,有时候就需要外部的库,因此还是需要了解gcc编译的默认规则。
之前在用GCC编译Mysql的代码时发现一个奇怪的问题,后来调整了一下参数的顺序就好了,也没有想原因。
代码很简单:
点击(此处)折叠或打开
#include <mysql/my_global.h>
#include <mysql/mysql.h>
int main(int argc, char
**argv)
{
printf("MySQL client version: %s\n", mysql_get_client_info());
exit(0);
}
对应的Makefile文件:
点击(此处)折叠或打开
TARGET=main
CFLAGS=-Wall $(shell mysql_config --cflags --libs)
HEADER=$(mysql_config --cflags)
CC=gcc
Object=progname.c
main:$(Object)
$(CC) $(CFLAGS) -o $(TARGET) $(Object)
clean:
rm -f $(TARGET)
关键是这句:$(CC) $(CFLAGS) -o $(TARGET) $(Object),CFLAGS 放到了Object 的前面,结果编译的时候出现:
gcc -Wall -I/usr/include/mysql -DBIG_JOINS=1 -fno-strict-aliasing -g -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -lrt -ldl -o main progname.c
/tmp/ccSTALlC.o: In function `main':
/home/ufisher/Documents/tmp/mysql/progname.c:6: undefined reference to `mysql_get_client_info'
collect2: ld returned 1 exit status
make: *** [main] Error 1
如果把这句改成 $(CC) -o $(TARGET) $(Object) $(CFLAGS), 结果就对了:
gcc -o main progname.c -Wall -I/usr/include/mysql -DBIG_JOINS=1 -fno-strict-aliasing -g -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -lrt -ldl
后来看了这个链接才发现问题:http://hi.baidu.com/whiteprincer/item/d5c4e8e339d134d5eb34c9f0
先看一下标准的示例吧
这个链接里面已经说得很清楚了,就拿一个比较容易的例子说明:main.c
点击(此处)折叠或打开
#include <stdio.h>
#include "test.h"
int main()
{
test();
return 0;
}
test.c
点击(此处)折叠或打开
#include "test.h"
#include "func.h"
void test()
{
func();
}
func.c
点击(此处)折叠或打开
#include "func.h"
void func()
{
}
这里面的调用关系为:main()->test()->func()
将test.c func.c 两个文件编译成静态库:
Makefile
点击(此处)折叠或打开
TARGET=main
main:test.a func.a main.o
gcc main.o -o $(TARGET)
func.a test.a
func.a:func.o
ar -rc func.a func.o
test.a:test.o
ar -rc test.a test.o
main.o:main.c
gcc -c main.c
test.o:test.c
gcc -c test.c
func.o:func.c
gcc -c func.c
clean:
rm -f $(TARGET) *.o *.a
注意第四句的静态库的顺序,这样执行Make的时候同样会出现 undefined reference to 问题
什么是编译,链接
参看这个说明http://www.cprogramming.com/compilingandlinking.html简单翻译一下,编译就是把C/C++的高级语言翻译成机器语言指令,编译过程是对独立的文件,并不检查函数的定义放在什么地方,也不会生成可以执行的文件,通常是生成.o(.obj)这样的文件。
而链接则要根据.o文件生成可执行的程序或库。函数未定义这样的错误都是在链接过程中产生的。编译过程如果找不到一个函数的定义,它会认为这个函数的定义放在其它文件,而链接则一定要找到第个函数的定义。
这样多个库文件在链接时就有了依赖性的问题。
再看上面的问题,由于是从.o文件生成了静态库,最后两个静态库的顺序是func.a test.a, 当链接func.a时找到func函数,它并不依赖于其它的库,但链接到test.a时找到test函数,它依赖于func,结果出现了,
从这里可以判断Gcc的链接顺序是 被依赖的库放在其它库的后面,比如test依赖func,则func.a应该放到test.a的后面。
因此把上面Makefile中的第4行改成 gcc main.o -o $(TARGET) test.a
func.a 就没有问题了。
再来看 Mysql那个示例的问题,展开的的编译命令是这样的:
gcc -o main progname.c -Wall -I/usr/include/mysql -DBIG_JOINS=1 -fno-strict-aliasing -g -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -lrt -ldl
在链接的时候 progname里面用到了动态库的函数,所以引入动态库的参数应该放在后面,反之如果放在前面,progname中的mysql_get_client_info() 就会找不到定义。
当然上面说的顺序问题都是存在于库中,包括动态库和静态库,如果把所有文件都编译成.o文件,然后直接链接成最终的程序,也不会有问题。
但对于Mysql这样的示例,有时候就需要外部的库,因此还是需要了解gcc编译的默认规则。
相关文章推荐
- ubuntu下 GCC编译程序出现 undefined reference to `std::ios_base::Init::Init()'问题——gcc编译C++代码
- 用gcc编译.cpp文件可能出现"undefined reference to `__gxx_personality_v0'"问题的解决
- ubuntu下 GCC编译程序出现 undefined reference to `std::ios_base::Init::Init()'问题
- GCC编译程序出现 undefined reference to `std::ios_base::Init::Init()'问题
- ubuntu下 GCC编译程序出现 undefined reference to `std::ios_base::Init::Init()'问题
- ubuntu下 GCC编译程序出现 undefined reference to `std::ios_base::Init::Init()'问题
- ubuntu下 GCC编译程序出现 undefined reference to `std::ios_base::Init::Init()'问题
- ubuntu下 GCC编译程序出现 undefined reference to `std::ios_base::Init::Init()'问题
- 用gcc编译.cpp文件可能出现"undefined reference to `__gxx_personality_v0'"问题
- 用gcc编译.cpp文件可能出现"undefined reference to `__gxx_personality_v0'"问题的解决
- gcc编译出现undefined reference to 的问题
- Qt4.8.5编译qvfb出现undefined reference to `png_create_write_struct'问题解决办法
- 用gcc-none-arm 编译出现undefined reference to `_sbrk'
- linux 下安装opencv3.0在编译时出现的问题undefined reference to `parallel_pthreads_set_threads_num(int)'
- gcc 编译出现undefined reference to‘pthread_create’的错误
- NiosII timestamp使用时编译出现undefined reference to `alt_timestamp问题
- linux下开发,解决cocos2d-x中编译出现的一个小问题, undefined reference to symbol 'pthread_create@@GLIBC_2.2.5'
- gcc编译出现”undefined reference to `pcap_parse’”
- STM32 GCC 使用 USB 库出现”undefined reference to _sbrk”问题解决
- 编译内核出现问题: undefined reference to `__gnu_mcount_nc'