【问题标题】:SCons linking DLL cause a dependency cycleSCons 链接 DLL 导致依赖循环
【发布时间】:2021-05-01 00:52:06
【问题描述】:

这是我的库的一个最小示例。我有一个库lib.c 和一个使用该库的应用程序app.c。我正在使用Scons 来编译库和应用程序。 (脚本如下)

  • 最初,我使用 lib = env.Library(...) 将库编译为静态库,并将库附加到环境 env.Prepend(LIBS=[lib]) 编译应用程序 env.Program(...),一切正常,没有依赖错误。
  • 现在我尝试将我的库编译为共享库。我添加了__declspec(dllxxxx) 并使用lib = env.SharedLibrary(...) 编译库,就像在将库附加到环境env.Prepend(LIBS=[lib]) 之前编译应用程序env.Program(...) 一样,现在我得到了这个依赖错误
scons: *** Found dependency cycle(s):
  lib.dll -> lib.lib -> lib.exp -> lib.dll
  lib.lib -> lib.lib
  lib.exp -> lib.lib -> lib.exp

我做错了什么,如何解决?

lib.c

__declspec(dllexport) int add(int a, int b);

int add(int a, int b) {
    return a + b;
}

app.c

#include<stdio.h>
__declspec(dllimport) int add(int a, int b);

int main() {
    printf("%i\n", add(1, 2));
    return 0;
}

S构造

import os

env = DefaultEnvironment(TARGET_ARCH = 'x86_64')
os.environ['PATH'] = env['ENV']['PATH'] ## for "cl.exe"

lib = env.SharedLibrary(
    target = 'lib',
    source = 'lib.c')
    
env.Prepend(LIBS=[lib])

env.Program(
    target = 'app',
    source = 'app.c')

【问题讨论】:

  • 为什么要这样做 "os.environ['PATH'] = env['ENV']['PATH'] ## for "cl.exe" "... 应该不需要?请在上面的描述中添加您正在使用的 msvc 版本、python 版本以及 SCons 版本。
  • 我可以重现这个,但是发生了一些非常奇怪的事情。即使退回到Library 而不是SharedLibrary,我也会在输出中看到一条意外的行:Creating library app.lib and object app.exp。为什么会这样做?
  • @bdbaddog 我正在使用 VS2019 和 python 3.7 。 scons 似乎没有找到与this question 类似的cl.exe 案例,如果您知道更好的方法,请告诉我
  • 我使用的是 Scons v4.0.1
  • SCons 应该在没有它的情况下找到它。请按照我在其他问题中的帖子执行此操作并附上结果.. set SCONS_MSCOMMON_DEBUG=%TEMP%\SCONS_MSVS_DEBUG.log 这将输出有关 SCons 如何尝试查找 MSVC 的信息,以便我们找出失败的原因。

标签: c windows dll scons


【解决方案1】:

我已经添加了您的示例(修改为我相信您正在尝试实现的功能)。

请参阅下面的 SConstruct 中的注释。 请注意

env=DefaultEnvironment() 

不是推荐的用法。 请使用

env=Environment()

同样在我刚安装 MSVC 2019 的机器上,SCons 找到了编译器,并默认生成了 X86_64 二进制文件。 (如果编译器支持该架构,SCons 应该默认为“本机”架构,否则它将尝试 x86)

来自

的 msvc 调试输出
set SCONS_MSCOMMON_DEBUG=%TEMP%\SCONS_MSVS_DEBUG.log

有助于确定您在 SCons 查找 MSVC 安装并正确配置它的本机能力方面遇到问题的原因。 也请考虑通过https://discord.gg/bXVpWAy 加入我们以获得进一步的帮助。

见: https://github.com/SCons/scons-examples/tree/master/shared-lib-program

S构造

# Skip initializing any tools in the DefaultEnvironment 
# as we're not using it.
DefaultEnvironment(tools=[])

env = Environment()

lib = env.SharedLibrary(
    target = 'a',
    source = 'lib.c')
    
# We list the library by it's base name 'a' and not a.dll, or liba.a because SCons
# will expand this to the appropriate platform/compiler dependent file name 
# and use the correct arguments to the linker to link against the shared library 'a'
# NOTE: We use LIBS here instead of env['LIBS']=['a'] as we're also building the
#       shared library above with the same Environment().
#       Having env.Prepend(LIBS=['a']) would cause the SharedLibrary() above to ALSO
#       try to link against shared library a. (Or on win32 file 'a.lib') and fail.
env.Program(
    target = 'app',
    source = 'app.c',
    LIBS=['a',])

app.c

#include<stdio.h>
__declspec(dllimport) int add(int a, int b);

int main() {
    printf("%i\n", add(1, 2));
    return 0;
}

lib.c

__declspec(dllexport) int add(int a, int b);

int add(int a, int b) {
    return a + b;
}

【讨论】:

  • 谢谢,它有效。 cl.exe 与 scons 一起使用。这不是去年,所以我在我的环境中添加了cl.exe 并添加了env.Append(ENV=os.environ) 来克服。现在这是我代码中的一个错误,我删除了该行并在没有它的情况下进行构建。
  • 啊。我敢打赌,您一年前使用的版本无法识别 VS2019。我认为 2019 年还有一些更新破坏了 scons msvc 检测。很高兴这有效!
【解决方案2】:

循环来自获取SharedLibrary 的结果并将其添加到LIBS:调用的返回是一个NodeList - 包含三个文件lib.dlllib.lib、@987654325 的节点表示@。您可以打印lib 的值来查看。

【讨论】:

  • 您可以将库的名称附加到LIBS...env.Prepend(LIBS="lib")
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-28
  • 1970-01-01
  • 2021-09-27
  • 2015-06-08
  • 2018-07-22
相关资源
最近更新 更多