对于 IAR 出现的 Error[Li005] 链接错误,网上已经给出了比较详尽的解决方法,而对于这次记录,主要是记录解决问题的思路。
网上给出的方法:http://blog.csdn.net/yueniaoshi/article/details/7844653
问题的本质都是一样的,这在问题给出的描述中已经说的很清楚了,是某个函数或者变量没有定义。
新来的同事在将一个工程从keil移植到iar时,出现了上述的连接错误,第一次遇到这样的文体,我也很纳闷,因为根据提示 是有两个库函数没有定义,可是定位到相应的库函数,发现都有定义和实现,对应的头文件也都包含了。在网上搜索到了类似的问题,按照网上找到的方法无法解决。想到是工程移植,会不会是文件路径不对?于是就尝试着去更改头文件的路径,当我删掉第一个头文件的路径后,工程竟然编译连接成功了;当我恢复这个路径,工程又出现刚才的连接错误;如果把这个路径放在最后面,工程竟也能编译连接成功。
问题解决了,知其然当知其所以然,进入到删掉的头文件路径(工程路径)下,里面只有一个头文件 lpc17xx_libcfg.h,而这个头文件在另一个路径(drivers\include)中也存在,include路径下的头文件才是正版的,但这个正版的在工程中并没有被应用。下面进入到本次博文的正题:
1.lpc17xx_libcfg.h 与上述连接错误的关系
追根溯源,iar给出的错误是:Error[Li005]:no define for "GPIO_SetDir",意思就是说GPIO_SetDir()这个函数没有定义,而根据搜索的信息显示GPIO_SetDir()这个函数是在lpc17xx_gpio.c中定义和实现的,在lpc17xx_gpio.h申明,这两个文件都在编译文件中,但是问题是lpc17xx_gpio.c被编译需要一个条件 #ifdef _GPIO,而这个条件需要在lpc17xx_libcfg.h中给出,工程路径下的lpc17xx_libcfg.h是原始的头文件外围功能相关的宏都是被注释了,所以lpc17xx_gpio.c并没有被编译。如果要正常使用外围功能,应该是这样的一个流程:lpc17xx_libcfg.h 放开需要的外围功能宏注释(如_GPIO),相关外围功能库文件(.c文件)编译条件成立被成功编译(如lpc17xx_gpio.c)
2.工程路径下的lpc17xx_libcfg.h 在前和在后的区别
在前面我们说过,当这个路径在前面时,连接是不成功的,但是放在最后面连接是可以通过的。这就关系到连接器在遇到同名的头文件是的处理方式,一般在我们的程序中都使用了#include来包含我们可能会使用到的头文件,当编译完成,连接的时候,连接器会首先从我们提供的路径中去搜索需要的头文件,如果没有找到就会去默认路径下搜索头文件;如果找到了,就中止该文件的搜索行为,忽略后面的路径。
其实可以把文件连接看作是填坑。