使用SCons制作一个包含静态库(.a)的共享库(.so)

10

我正在尝试让SCons生成一个共享库。其中一个要放进 .so 的项目是一个 .a 静态库。

我有一行类似于:

env_2.SharedLibrary('libstuff.so', \
  Split("""stuff.cxx mylib/libMine.a""")

运行后我收到了这个错误:

scons: *** Source file: mylib/libMine.a \
is static and is not compatible with shared target: libstuff.so

但是,我知道可以通过类似以下命令将.a文件制作成共享库:

g++ -m32 -shared -o libstuff.so stuff.o mylib/libMine.a

有没有什么想法可以让这个工作或任何解决方法将不胜感激。


相关问题:如何让scons在调用Program()时在链接命令行上添加额外的字符串-shared?如果我能做到这一点,我认为它会满足我的需求。

6个回答

13

尝试在您的SConstruct中设置env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME']=1


1
这个“神奇的巫术”对我也起作用了。我很惊讶,因为在添加到SConstruct之后,我没有看到编译命令选项有任何区别。我希望那位提出这个魔法的巫医能向我们凡人解释一下。 - Be Kind To New Users
1
SharedLibrary构建器会检查所有给定的目标文件是否是使用SharedObject构建器(因此使用了-fPIC)构建的。env ['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1可以禁用此检查。您需要自己决定这是否是一个好主意... - ElektroKraut

2
这个问题不是特定于scons。要构建共享库,您需要使用编译有位置无关代码(-fPIC)的对象。最好的方法是使用正确选项编译源文件来创建共享库。
在SCons中,您可以定义一个目标列表,用于同时构建libMine.a和libShared.so。
更新:对于您的第二个问题,SharedLibrary 构建器可能会满足您的需求。
SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])

如果没有设置,LINKFLAGS 将设置传递给链接命令的标志。

我认为你说得对,.a文件中的.o文件没有使用-fPIC选项生成。然而,g++ -m32 -shared .... 仍然以某种方式工作。 - xavjuan
1
我回去了,让进入 .a 的文件使用 -fPIC 进行编译,但似乎没有帮助。 - xavjuan

0
解决此问题的方法是使用以下代码中的“SharedObject”:
ASN1CObjectFile = envCProcesses.SharedObject(target = "OTCMsg.os",
                                             source = "OTCMsg.c",
                                             CFLAGS = envCProcesses["CFLAGS"] + ["-Wno-unused"])

并且:

OTCLibSharedLibrary = envCProcesses.SharedLibrary(env["OTC_LIBPATH"] + "/libOTCLib" + env["SHLIBSUFFIX"],
                                              ASN1CObjectFile +
                                              [ASN1AllocatorSource,
                                               "OTCLib.c"],
                                              LIBPREFIX = "")

此致敬礼,


env["OTC_LIBPATH"] + "/libOTCLib" + env["SHLIBSUFFIX"] 可以重写为 "${OTC_LIBPATH}/libOTCLib$SHLIBSUFFIX"。 - bdbaddog

0
env_2.SharedLibrary('libstuff.so', Split("""stuff.cxx"""), LIBS='libMine.a', LIBPATH='mylib')

应该可以工作。


@shoosh 是的,它确实如此。SharedLibrary 构建器使用 ProgramScanner 来搜索通过 LIBS 指定的依赖项。 - Jonathon Reinhart

0
问题出在函数SharedFlagChecker(Default.py)中,它仅检查内部的“共享”标志。SCons文档让你相信它通过后缀(SHOBJSUFFIX)保持了共享对象和静态对象之间的区别,但事实并非如此。修复很容易,在文件scons-local.../SCons/Default.py中找到SharedFlagChecker并进行编辑。
def SharedFlagChecker(source, target, env):
    same = env.subst('$STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME')
    if same == '0' or same == '' or same == 'False':
        for src in source:
            try:
                shared = src.attributes.shared
            except AttributeError:
                # Replace this line: shared = None
                shared = env.Dictionary()['SHOBJSUFFIX'] == src.suffix
            if not shared:
                raise SCons.Errors.UserError("Source file: ...") 

现在通过SharedObject生成的对象将可以在共享库中链接。

1
你应该使用env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME']=True,而不是黑客攻击代码来禁用它。这在manpage中有说明。 - bdbaddog

0

我在cygwin下遇到了同样的问题。在构建对象时,我向gcc传递了“-fPIC”选项,并得到了以下警告:

警告:目标忽略了-fPIC(所有代码都是位置无关的)

我还向链接命令传递了“-shared”。最终我得到了错误:

"***.lib是静态的,与共享目标myso.dll不兼容"

看起来scons不允许直接从obj或lib文件创建so,而是可以使用SharedLibrary()从源文件列表(使用SharedLibrary())或源文件+“LIBS”选项(如dummytaurus所说)创建so。我对此很好奇。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接