我知道.OBJ是编译一个编译单元的结果,而.LIB是一个静态库,可以从几个.OBJ创建,但这种差异似乎只是在编译单元的数量.还有其他区别吗?是相同还是不同的文件格式?
当想知道在链接到最终可执行文件期间是否合并了两个(或更多).LIB中定义的相同静态变量时,我遇到了这个问题.对于.OBJ,变量是合并的.但是在.LIBs中它是一样的吗?
g ++(Ubuntu/Linaro 4.4.4-14ubuntu5)4.4.5
我有以下名为sdpAPI.a的静态库.我在尝试将其与我的测试应用程序链接时遇到问题.只是想知道我是否做错了什么.静态库是用g ++构建的;
我的目录如下:
/projects/unit_test/main.c
/projects/unit_test/sdp/inc/sdpAPH.h
/projects/unit_test/sdp/lib/sdpAPI.a
Run Code Online (Sandbox Code Playgroud)
我的源代码是这样的:
#include <stdio.h>
#include "sdpAPI.h"
int main(void)
{
printf("----- TEST SDP ------\n");
try {
sdpSessionDescription sdp;
sdp.clear();
}
catch(...) {
printf("----- TEST FAILED --------\n");
return 0;
}
printf("------ TEST SUCCESSFULL ------\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的Makefile是这样的:
OBJECT_FILES = main.o
CC = g++
CFLAGS = -Wall -Wextra -Wunreachable-code -ggdb -O0
TARGET = sdp_demo
INC_PATH = -I sdp/inc
LIB_PATH = -L sdp/lib/sdpAPI.a
$(TARGET): $(OBJECT_FILES)
$(CC) $(CFLAGS) $(INC_PATH) $(LIB_PATH) $(OBJECT_FILES) -o $(TARGET)
main.o: main.c
$(CC) …Run Code Online (Sandbox Code Playgroud) 我正在使用Visual Studio 2008 SP1(专业版,适用于32位和64位版本).我正在寻找一种解决方法,我认为这是Visual Studio中一个非常无益的" 限制 ".
我觉得很奇怪,在Visual Studio连接器和编译器不以DLL文件的创建时间这一权利,自动扫描所有导出的符号所有指定的静态库中所示的相同的方式构建一个导入库和导出文件,并在一StackOverflow评论.我确认仅仅在组成静态库的文件中应用__declspec(dllexport)和__declspec(dllimport)属性类,函数和数据声明是不够的
.
链接器不扫描导出符号的所有静态库,因此不会将它们拉入DLL文件(符号必须由.objDLL链接命令行上的文件或我在下面显示的其他方式引用).如果没有对每个导出符号的显式引用,仍可能会创建DLL文件,但不会创建其关联的导入库文件.
根据我的收集,Microsoft建议使用LIB.EXE 来创建DEF文件,但不幸的是,LIB.EXE页面应用了一个约束:
请注意,如果您在创建导入库之前创建导入库,则在构建导入库时,必须在构建导入库时
.dll传递相同的目标文件集.dll.
鉴于我在新的构建环境中也使用了CMake,这是一个不幸的约束.CMake隐藏了实际传递给链接器的细节(我认为这在99%的时间里都是好事),但在这种情况下我需要在CMake执行时访问一些信息,而不是然后使用手工制作的脚本或其他脆弱的skulduggery.
如何强制DLL链接器解析构成DLL文件的所有静态库中的所有导出符号,这不会导致脆弱性和额外的构建逻辑维护工作?在这里考虑全自动化,并记住我需要多次为多个不同的DLL执行此操作.
我的问题是:
如何仅使用CMake语法获取最终DLL链接命令行上使用的目标文件和静态库集?
有没有更好的方法来解决这个问题,在调用最终链接之前不需要调用单独的实用程序,例如LIB.EXE ?我担心LIB.EXE链接本身之外的额外构建开销会再次重新扫描所有静态库 ,即使它只是在单独的执行中写出来.
以下是我现在无法考虑的解决方案:
在原始文件.h或.cpp文件之外的任何地方手动指定未引用的符号,因为每次开发人员忘记更新列出(很可能是名称错位的)符号名称的文件时,这样做会中断.并且它将打破关于未解析符号的非用户友好链接器错误,这对于开发人员来说将是昂贵的调试.这个非答案包括以下方法:
明确地将.obj文件添加到DLL链接命令行中(其中的变体包括添加"假" .obj文件,这些文件具有对未引用但导出的符号的虚拟引用(并注意这是我的旧构建环境今天所做的,并且它很臭) ),和,
手工制作DEF文件以包含未引用但导出的符号,以及 …
我有一个共享库,由我无法控制的另一个应用程序使用,需要*.so对象.我的库使用sqlite3,它需要与它静态链接(我绝对需要一个自包含的二进制文件).
当我尝试编译和链接我的库时:
-fpic -flto -pthread -m64
-flto -static -shared
Run Code Online (Sandbox Code Playgroud)
我最终得到以下错误:
/usr/bin/ld: /usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.6.1/crtbeginT.o: relocation R_X86_64_32 against `__DTOR_END__' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.6.1/crtbeginT.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
什么是与-fPIC相关的重新编译?我的代码还是CRT?
我已经尝试用-fPIC编译我的对象,结果相同.
谢谢.
编辑:
这个问题似乎与SQLite3无关.
我写了一个简单的单行无用库,它编译和链接如下:
g++ -c -fPIC -o bar.o bar.cpp
g++ -shared -o bar.so bar.o
Run Code Online (Sandbox Code Playgroud)
但不是这样的:
g++ -c -fPIC -o bar.o bar.cpp
g++ -static -shared -o bar.so bar.o
Run Code Online (Sandbox Code Playgroud)
问题似乎与CRT(crtbeginT.o)有关.我应该重新编译GCC - 用pic还是其他什么?
我不可能是唯一遇到这种情况的人.
我有一个C++应用程序需要链接到SDK中的一个第三方和另一个静态库集.出于某些令人沮丧的原因,SDK将相同的第三方库的子集重新编译为它们自己的(重命名的)lib,尽管这些符号本身的名称相同,并且它们未封装在命名空间中.我的应用程序本身依赖于相同的第三方库.
我考虑了一些选择,但也许我错过了一些东西,希望新面貌能帮到我.也许我很亲密,有人会知道其中一个的下一步.到目前为止,我将列举我尝试过的内容以及每个解决方案的缺点:
与两者联系.我得到大约2500行符号重新定义/大小更改警告和错误.这是我第一次发现他们定义了相同的符号.我正在尝试用g ++重新编译OpenSSL并将其放入命名空间...请参阅下面的编辑...
仅与SDK链接.我得到了我自己的代码所依赖的未定义符号 - 这是我发现他们重新编译第三方库是一个子集,或者至少配置了一个模块被禁用.
仅与第三方lib链接.我在SDK上报告了一些未定义的符号 - 其中一个实际上是第三方库中头文件中的#define,因此第三方lib中的所有引用都解析为定义,但外部引用却没有.我把它移到c文件中,这解决了这个问题,但是我仍然有两个我在任何地方都找不到的未解决的函数.这是我到目前为止最接近的.
从两个lib和链接中删除冲突的符号.到目前为止,这还没有奏效.它可能是SDK中静态链接的lib与我尝试使用第三方库的版本之间的版本问题,但看起来某些函数在符号之间移动,因此通过删除符号,我无意中删除了我在其他地方需要的功能.SDK中的符号中的函数与第三方lib中的符号中的函数之间似乎没有完美的映射.剥离功能而不必手动调整地址是否合理?
我一直在用libs检查符号:
nm -C --defined-only lib<name>.a
Run Code Online (Sandbox Code Playgroud)
并提取整个对象:
ar -x lib<name>.a <objname>.o
Run Code Online (Sandbox Code Playgroud)
希望这也将帮助那些不得不与彼此冲突的第三方库链接的其他人.为了具体细节,第三方lib是OpenSSL,SDK是Opsec - libcpopenssl.a是Opsec中令人讨厌的lib.
**编辑 - 可能的后期入口解决方法可能是使用g ++重新编译OpenSSL并将整个内容放在命名空间中,然后链接两个库.我现在正在尝试......更多来......
我无法使用Cocoapods正确编译我的工作区.工作区中有3个项目,每个项目都有自己的目标:
libCommon和myApp都需要libPods的外部依赖项.最初我认为它会像这样工作:
在这种情况下,libCommon"拥有"pod,然后myApp只链接libCommon,就像我一直在做Cocoapods之前...但显然静态库不喜欢与静态库链接(我得到了一堆动态库错误).我在某个地方阅读github问题,而不是我应该构建libPods和libCommon,然后myApp应该链接到两个库.现在我的podfile看起来像这样:
workspace 'MyApp.xcworkspace'
platform :ios, '5.0'
link_with ['Common', 'MyApp']
target 'MyApp' do
xcodeproj 'MyApp.xcodeproj'
pod 'AFNetworking', '1.1.0'
pod 'TTTAttributedLabel', '1.6.0'
pod 'JSONKit', '1.5pre'
pod 'Reachability', '3.1.0'
end
Run Code Online (Sandbox Code Playgroud)
通过此设置,myApp拥有所有pod,然后在libCommon构建设置中指定pod标头的路径.这构建正常,直到我尝试使用libCommon中的一个类.一旦我这样做,我得到其中一个_OBJC_CLASS_$_Blah错误(告诉我虽然标题可用,但它仍然没有正确链接).当我尝试在"Build Phases"中手动链接libCommon时,我得到了一堆重复的符号错误(让我相信它已经链接了?).有没有搞错?
有什么方法可以正确地做到这一点,我的podfile应该是什么样子?
我正在构建一个静态库.构建设置的架构设置为: $(ARCHS_STANDARD)显示为Standard Architectures (armv7, armv7s, arm64)我构建lib选择iOS Device AND然后使用模拟器(例如iPhone Retina).
现在我有两个构建(一个在内部Debug-iphoneos,另一个在内部Debug-iphonesimulator,我lipo -create用来创建聚合的lib:
lipo -create path/to/first/lib /path/to/second/lib -o MyLib.a
Run Code Online (Sandbox Code Playgroud)
如果我在另一个项目中使用这个库来模拟任何具有64位架构的iOS设备,它会给出symbol(s) not found for architecture x86_64.是什么让我如此愤怒,以至于lib项目本身位于工作区内,另一个项目使用lib.我可以在64位iOS模拟器上模拟!(在所有模拟器和设备上).我究竟做错了什么?
笔记:
我有一个非常类似于cmake邮件列表中描述的问题,我们有一个依赖于许多静态库的项目(所有静态库都是从各个子模块中的源代码构建的,每个子模块都有自己的CMakeLists.txt描述每个库的构建过程)我想组合成一个静态库,以便向消费者发布.我的库的依赖性可能会发生变化,我不想让开发人员在这些变化的后面进一步负担.简洁的解决方案是将所有lib捆绑到一个单独的lib中.
有趣的是,target_link_libraries在设置目标mylib和使用它时,该命令不会结合所有静态..
target_link_libraries(mylib a b c d)
Run Code Online (Sandbox Code Playgroud)
但是,奇怪的是,如果我将mylib项目作为可执行项目的子模块,并且只mylib在顶级可执行文件CMAkeLists.txt中链接,那么该库似乎确实是组合在一起的.即,当我将目标设置为仅构建时,mylib为27 MB,而不是3 MB mylib.
有一些解决方案描述了将lib解压缩到目标文件并重新组合(这里和这里),但是当CMake看起来完全能够自动合并lib时,这似乎非常笨拙,如上例所述.它有一个我失踪的神奇命令,或推荐的优雅方式制作发布库?
假设我们有一个名为"my_app"的主要可执行文件,它使用了其他几个库:3个库是静态链接的,其他3个是动态链接的.它们应该以哪种顺序与"my_app"相关联?
但这些顺序应该以哪种顺序联系起来?
假设我们得到了依赖于libSB的libSA(如在静态A中),以及依赖于libSB的libSC:
libSA -> libSB -> libSC
Run Code Online (Sandbox Code Playgroud)
和三个动态链接库:libDA -> libDB -> libDC(libDA是基本的,libDC是最高的)
这些顺序应该链接在哪?第一个还是最后一个?
g++ ... -g libSA libSB libSC -lDA -lDB -lDC -o my_app
Run Code Online (Sandbox Code Playgroud)
看起来像现在的顺序,但是这样吗?如果任何动态库与静态库或其他方式之间存在依赖关系,该怎么办?
c++ linker shared-libraries dynamic-linking static-libraries
我知道.o是目标文件,.a是静态库,.so是动态库吗?它们的物理意义是什么?我何时可以使用,何时不使用?