Search code examples
cwindowsdllscons

SCons linking DLL cause a dependency cycle


Here is a minimal example of my library. I have a library lib.c and an application app.c which use the library. And I'm using Scons to compile both the lib and the app. (the script is below)

  • Initially, I was compiling the lib as a static library with lib = env.Library(...) and append the library to the env env.Prepend(LIBS=[lib]) compile the app env.Program(...), and everything working fine and no dependency errors.
  • Now I try to compile my lib as a shared library. I added __declspec(dllxxxx) and compile the library with lib = env.SharedLibrary(...) and like before append the library to the env env.Prepend(LIBS=[lib]) compile the app env.Program(...) and now I'm getting this dependency error
scons: *** Found dependency cycle(s):
  lib.dll -> lib.lib -> lib.exp -> lib.dll
  lib.lib -> lib.lib
  lib.exp -> lib.lib -> lib.exp

what am I doing wrong, and how to solve this?

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;
}

SConstruct

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')

Solution

  • I've added your example (modified to function as I beleive you're trying to achieve).

    See notes in the SConstruct below. Note that

    env=DefaultEnvironment() 
    

    Is not the recommended usage. Please use

    env=Environment()
    

    Also on my machine with freshly installed MSVC 2019, SCons found the compiler and by default produced X86_64 binaries. (SCons should default to the "native" arch if the compiler has support for that arch, otherwise it would try x86)

    The msvc debug output from

    set SCONS_MSCOMMON_DEBUG=%TEMP%\SCONS_MSVS_DEBUG.log
    

    Would help to determine why you're having issues with SCons' native ability to find the MSVC install and configure it properly. Also please consider joining us at https://discord.gg/bXVpWAy for further assistance.

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

    SConstruct

    # 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;
    }