问题
在Windows上使用scons编译Android动态库时,在链接动态库时报错:
D:\android\android-sdk\ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/bin/clang++ --target=aarch64-linux-android21 -march=armv8-a -shared -o src\android\ddsnative.so … -Wl,–out-implib,src\android\libddsnative.a
=====
ld: error: unknown argument ‘–out-implib’
对应Scons脚本:
if env["platform"] == "android":
if host_platform == "windows":
# Don't Clone the environment. Because otherwise, SCons will pick up msvc stuff.
env = Environment(ENV=os.environ, tools=["mingw"])
opts.Update(env)
...
library = None
library = env.SharedLibrary(target=env["target_path"] + "/" + env["platform"] + "/" + env["target_name"], source=sources)
Default(library)
倒数第二句“env.SharedLibrary()”是触发链接命令及相关参数的关键。
链接Android动态库时不需要象Windows动态库那样生成一个导入库,因此也不接受相应的命令行参数“-Wl,–out-implib”。
调查
- 如果将代码第四行Environment()参数中的mingw换成其它clangxx之类,会报错:
AttributeError: ‘SConsEnvironment’ object has no attribute ‘SharedLibrary’
副作用很大,改起来太麻烦。
- 检查Scons代码,确认是在\Python3\Lib\site-packages\SCons\Tool\mingw.py中的shlib_generator()函数添加了”-Wl,–out-implib“命令行参数:
def shlib_generator(target, source, env, for_signature):
...
implib = env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX')
if implib: cmd.append('-Wl,--out-implib,' + implib.get_string(for_signature))
直接改mingw.py不可取,修改LIBPREFIX或LIBSUFFIX对结果也没有影响。
- 偶然发现mingw.py中有这段代码:
def shlib_emitter(target, source, env):
dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX')
no_import_lib = env.get('no_import_lib', 0)
...
if not no_import_lib and \
not env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX'):
如果通过no_import_lib禁止生成导入库,就不会有多余的命令行参数了吧?
解决办法
修改Scons脚本:
env = Environment(ENV=os.environ, tools=["mingw"])
+ env["no_import_lib"] = True
opts.Update(env)
另外,也可以添加scons命令行参数“no_import_lib=yes”,利用“opts.Update(env)”语句设置env环境变量的功能来解决这个问题。