0x00 前言
文章中的文字可能存在语法错误以及标点错误,请谅解;
如果在文章中发现代码错误或其它问题请告知,感谢!
Linux发行版本 (#cat /etc/issue
):Ubuntu 14.04.1 LTS \n \l
Linux内核信息 (#cat /proc/version
):Linux version 3.13.0-32-generic (buildd@kissel) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC 2014
0x01 问题描述
在编写含有sqrt()
函数的代码C程序时,使用gcc编译工具编译的时候发现报错提示为undefined reference to 'sqrt'
:
例如一个含有sqrt()
函数程序代码tutorial.c
:
#include<stdio.h>
#include<stdlib.h>
#include<math.h> //头文件math.h已经包含
int main(int argc, char *argv[])
{
if(argc < 2)
{
printf("Usage:%s number\n", argv[0]);
return -1;
}
double inputValue = atof(argv[1]);
double outputValue = sqrt(inputValue); //该行使用sqrt()
printf("The square root of %g is %g\n",inputValue, outputValue);
return 0;
}
现在想要使用gcc编译成一个名为Tutorial
的可执行文件,正常情况下,使用#gcc -o Tutorial tutorial.c
编译生成Tutorial
,不过在编译过程中提示了tutorial.c:(.text+0x63): undefined reference to 'sqrt'
报错信息:
明明使用sqrt()
函数时我们已经引用了头文件:#include <math.h>
,编译器还是提示找不到对应的库函数。
0x02 原因分析:
包含了math.h头文件也报错,是因为gcc默认指定头文件对应的库文件中不包括math库,即math库不是gcc默认指定的库文件,编译时需要将gcc手动指定到math库。
0x03 解决方案:
我们分别从gcc编译,cmake文件、makefile中解决编译中出现的undefined reference to ‘sqrt‘
问题。
1 gcc直接编译
gcc编译的时候可以直接加上-lm
选项,-l为指定库,m为math库。例如将 tutorial.c
编译成可执行文件Tutorial
,则完整编译语句为:gcc -o Tutorial tutorial.c -lm
:
2 使用cmake
可能每个CMakeLists.txt
文件编写都或许有些差别,总的来说需要在CMakeLists.txt
文件的add_executable(XXX)
位置前添加LINK_LIBRARIES(m)
指定连接的math库,例如:
cmake_minimum_required(VERSION 3.1)
project(Tutorial)
LINK_LIBRARIES(m)
add_executable(Tutorial tutorial.c)
3 使用makefile
同上,每个makefile
文件编写都或许有些差别,可以在要指定库的变量后添加-lm
即可,例如下面makefile
中LDLIBS
后添加-lm
指定库文件 :
CC = gcc
DIR_BIN = ./bin
DIR_SRC = ./src
DIR_OBJ = ./obj
DIR_INC = ./Include
Targit = Tutorial
BIN_Targit =$(DIR_BIN)/$(Targit)
SRC = $(wildcard $(DIR_SRC)/*.c)
Objects = $(patsubst %.c,$(DIR_OBJ)/%.o,$(notdir ${SRC}))
CFLAGS += -g -Wall -w
INCLUDE += -I./$(DIR_INC) -I./$(DIR_SRC)
LDLIBS += -L./usrLib -lm
build:$(Targit)
$(Targit):$(Objects)
$(CC) $(CFLAGS) $(INCLUDE) -o $(BIN_Targit) $(Objects) $(LDLIBS)
$(DIR_OBJ)/%.o:$(DIR_SRC)/%.c
$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
.PHONY = clean
clean :
-rm -rf $(Objects) $(BIN_Targit)
以上。
参考文档:
1.https://blog.csdn.net/qq_37600027/article/details/103341570