我对使用库很陌生,并且正在尝试了解有关静态库和目标文件的一些细节。
概括
我注意到的行为是我可以链接多个对象以毫无问题地生成可执行文件,但如果我采取将这些对象组合到静态库中的中间步骤,我无法在不额外指定的情况下链接这些静态库以生成可执行文件链接命令中需要 C 运行时库。
另外,或者记录,我正在从命令行使用 Visual Studio 2010 进行编译/链接。我正在遵循的过程的更多详细信息如下。
首先,假设我在一个项目中有四个源文件:main.c
、util1.c
、util2.c
和util3.c
.
什么有效
我可以使用以下命令编译这些源
cl -c main.c util1.c util2.c util3.c
文件: 结果,我现在有四个目标文件:main.obj
、util1.obj
、util2.obj
和util3.obj
. 这些目标文件中的每一个都包含一个 DEFAULTLIB 语句,旨在通知链接器在链接这些目标文件时,它应该另外检查静态 C 运行时库 libcmt.lib 中是否存在任何未解决的外部依赖项。我可以通过使用以下命令链接这些对象来创建一个名为“app_objs.exe”的可执行文件:
link -out:app_objs.exe main.obj util1.obj util2.obj util3.obj
如步骤 1 中所述,由于编译器向对象添加默认库语句的步骤,链接器使用了运行时库。
我困惑的地方
假设我想要一个将这些对象组合到静态库中的中间步骤,然后链接这些生成的 LIB 文件以创建我的可执行文件。首先,我可以使用以下命令创建这些库:
link -lib -out:main.lib main.obj
link -lib -out:util.lib util1.obj util2.obj util3.obj现在,我最初的想法是,我可以简单地链接这些库并拥有我在“什么有效”的第 2 步中创建的相同可执行文件。我尝试了以下命令并收到链接器错误 LNK1561,它指出需要指定入口点:
link -out:app_libs.exe main.lib util.lib
从 Microsoft 的文档中,很明显,链接没有任何目标文件的库可能需要指定入口点,因此我修改了命令以将子系统设置为“控制台”以指定可执行文件旨在成为控制台应用程序(这似乎暗示某些入口点,从而解决该错误):
link -out:app_libs.exe -subsystem:console main.lib util.lib
不幸的是,现在我收到一个链接器错误,指出 mainCRTStartup 是一个未解析的外部符号。我知道这是在 C 运行时库中定义的,因此我可以通过手动指定要链接到 libcmt.lib 来解决此问题,这为我提供了一个正常运行的可执行文件:link -out:app_libs.exe -subsystem:console main.lib util.lib libcmt.lib
我不明白的是为什么编译器放置在每个目标文件中的默认库信息不能用于解决对 libcmt.lib 的依赖关系。如果我可以在不明确声明我想要 libcmt.lib 的情况下链接目标文件,并且我创建了作为目标文件容器的静态库,为什么我不能在不明确声明我想要 libcmt.lib 的情况下链接这些静态库?事情就是这样,还是有什么方法可以创建静态库,以便链接器知道在运行时库中检查未解析的符号?
谢谢你的帮助。如果我在这里有一些根本不正确的想法,我会喜欢关于好的参考的建议,以正确学习所有这些。