Search code examples
pythoncscons

How to link with static libraries using SCons?


I'm trying to link with static libraries created with SCons in the following way:

//LIBSUFFIX and PREFIX are already set
env.Replace(LINKCOM = '$LINK $LINKOPTFILE $LINKMIXEDOPTIONS $LINKERR $LINKMAPFILE $SOURCES $LINKFILE $_LIBDIRFLAGS $_LIBFLAGS -o $TARGET')
env.Library('libraryname', ['file1.o','file2.o'])
env.Program(target = '', LIBS = 'libraryname', LIBPATH = 'path', source = Glob(*.c))

My problem is the following: In LINKCOM the library is added without its location ex: libraryname.a . Also files that are already included in the library are passed to the linker command (like SCons doesn't recognize I am creating a library from them)

ex: I have to create a program from the following sources: main.c s1.c s2.c s3.c and Library library_s.a from s1.o and s2.o .

Linker command passed by SCons:

linker.exe linkerflags s1.o s2.o s3.o library_s.a -o target.exe

How to concatenate each dir in _LIBDIRFLAGS with its correspoding library and also how to make SCons aware that I am creating libraries from some source files ?

EDIT: This is how the linker command should look like:

'linker.exe' linkerflags s3.o pathtolibrary/library_s.a -o target.exe

Remark: since library_s.a was created from s1.o and s2.o I expect SCons to pass only s3.o and the library


Solution

  • You can simply add the fully required path of your lib to the Program() call:

    lib_a = env.Library('libraryname', ['file1.c','file2.c'])
    env.Program('target', ['main.c', 's3.c', 'pathtolibrary/' + str(lib_a[0])])
    

    If you tell Glob() to find all C files ("*.c") it will return the full list. If that's not what you want, you have to filter the results of the Glob call, either manually or by using the "exclude" option which is available since v2.3.5 (works for VariantDirs only starting with a corresponding fix in v2.4.1!).

    Your expectations about how SCons operates, regarding the automatic detection of dependencies between the source files of the lib and the target, don't match the reality...unfortunately. What one would usually do is to restructure the build, such that all C files for the lib are in a separate subfolder from the main sources. Then you can use Glob(*.c) again and won't have interfering source lists. Note, how adding an object file like s2.o a second time to the final linking step might actually make sense, e.g. in the case of cyclic dependencies...so SCons (or any other build system) wouldn't be able to figure this out all by itself anyway. The input of the user would always be required to resolve these kind of issues.