在WinCE里面,编译和链接的必备文件sources,做过WinCE BSP开发的一定都很熟悉,其中有2个关键字,targetlibs和sourcelibs,一直让我对其中的区别很感兴趣,故查阅了一些资料,与大家分享。
其实只要搜索以下就会得到一些基本的答案,比如:
TARGETLIBS,如果一个库以DLL的形式提供给调用者,就需要用TARGETLIBS,它只链接一个函数地址,系统执行时会将被链接的库加载。比如coredll.lib就是这样的库文件。即动态链接。
SOURCELIBS,将库中的函数实体链接进来。即静态链接,用到的函数会在我们的文件中形成一份拷贝。
这个答案已经基本解决问题了,但是这个答案让我们能看到更深入的东西:
This is componentization feature of Windows CE.
The link has two steps. First, whatever is in SOURCELIBS gets combined in a
signle library yourproductname_ALL.lib. In the second step, executable
module is linked from that library and all the targetlibs.
This is done to allow stubs to be conditionally linked: if the function is
defined into your source already, stubs get excluded. If it is not there,
stubbed version (returning ERROR_NOT_IMPLEMENTED or something to that
effect) gets linked in instead.
If the link were to be performed in just one step, it would be impossible to
predict which version (real or stub) would get included. As it is,
implemented functions have a priority over stubs.
--
Sergey Solyanik
Windows CE Core OS
总的来说就是先编译了你自己在sources里指定的源文件,在链接阶段,先将所有的sourcelibs链接在一起成为一个lib,然后与targetlibs指定的lib一起参与链接。
当然这里targetlibs指定的可以是dll的lib文件,在CE的帮助文件中,有说明targetlibs可以使用import libraries or static libraries。但是sourcelibs说明中指出一般用在把许多小的lib合并为一个大的lib。
还有关于用法的一些说明:
EXEs
Only TARGETLIBS get linked, anything in SOURCELIBS is ignored
DLLs
SOURCELIBS and TARGETLIBS get linked, in that order
LIBs
Only SOURCELIBS get linked, anything in TARGETLIBS is ignored
Google groups 上Steve Maillet一直在回答相关的问题,并且强调只是一些link的顺序问题,可以参看makefile.def。
为了把问题弄清楚,看了下makefile.def因为很少接触makefile文件,所以凭有限的makefile知识,来解读下(MS的全自动化编译工具害人啊)
注:由于对makefile了解有限,如果分析有错误的地方请大家指出
1. 关于LIBS的link
!IF "$(TARGETTYPE)" == "LIBRARY"
$(_RELEASELIBDIR)\$(TARGETNAME).lib: $(TARGETOBJFILES) $(SOURCELIBS)
@echo BUILD_MARKER:LINK_STATIC_LIBRARY_START Linking $@
$(LIBRARIAN) -out:$(_RELEASELIBDIR)\$(TARGETNAME).lib $(MACHINEOPTION) @<<
-ignore:4001
$(LIBDEFINES)
-nologo
-nodefaultlib
$(LINKER_SUBSYSTEM)
$(TARGETOBJFILES)
$(SOURCELIBS)
<<NOKEEP
可以看出,是忽略了TARGETLIBS的东西
2. 关于DLL
有些条件判断,但是链接顺序都是
$(TARGETOBJFILES)
$(SOURCELIBS)
$(TARGETLIBS)
3. 关于EXE
$(TARGETOBJFILES)
$(TARGETLIBS)
$(SOURCELIBS)
由此对
EXEs
Only TARGETLIBS get linked, anything in SOURCELIBS is ignored
产生了一些质疑
关于链接顺序:
在我的印象里,应该是出现同样的symbol,优先链接第一个出现的(查了半天也没有找到文档作为证明,不过我用bcc试了一下,默认是链接第一个出现的)。
这样就说明了链接顺序带来的影响,比如你的源文件里有一个func这个函数的实现,但是在sourcelibs里包含的func1.lib里面也有同样函数的实现,这时候会使用你的源文件里面的func实现,而不是func1.lib里面的,同样对应于targetlibs
这样做可以使用一些stub,比如KITL.c在BSP的两个地方实现Src\Kernel\Kern和Src\Kernel\Oal,而kern下的就是个stub,里面什么也没做,用来关闭KITL功能,OAL下的才是功能实体,在链接过程中,kern下使用TARGETLIBS来引入oal.lib,但是OAL下KITL.c里面的函数实现都已经被kern下的KITL.c替换了,这个生成的kern.exe后续会在common.bib里面被加入NK.exe(关闭KITL的时候)。而Src\Kernel\Kernkitl下生成的kernkitl.exe也引入了oal.lib,由于自身没有KITL的实现函数,所以实现代码就是OAL里面的代码,在打开KITL的时候就会加入NK.exe。
以下是common.bib的关于KITL的片断:
IF IMGNOKITL
nk.exe $(_FLATRELEASEDIR)\kern.exe NK SHXL
ENDIF IMGNOKITL
IF IMGNOKITL !
nk.exe $(_FLATRELEASEDIR)\kernkitl.exe NK SHXL
ENDIF IMGNOKITL !
这里也就说明了KITL开关的原理(build层面的关闭)
从上面的说明,我们是否可以得到以下结论:
1. 对于LIBS,targetlibs是没有使用的, 对于DLL和EXE,只是链接顺序的不同
2. 在build DLL和EXE时需要小心相同函数的覆盖关系