SCons 链接 DLL 导致依赖循环 lib.capp.cS构造

问题描述

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

  • 最初,我使用 lib = env.Library(...) 将 lib 编译为静态库,并将库附加到 env env.Prepend(LIBS=[lib]) 编译应用程序 env.Program(...),一切正常,没有依赖项错误
  • 现在我尝试将我的库编译为共享库。我添加__declspec(dllxxxx) 并使用 lib = env.SharedLibrary(...) 编译库,并且在将库附加到 env 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')

解决方法

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

请参阅下面 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;
}
,

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