Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scons copy header files to build directory

Tags:

python

scons

I'm trying to copy a number of headers files from my source directories to an 'includes' directory inside my build directory using scons. My target is a static library and I want to distribute it together with its relevant headers. The expected end result:

build
|-- objects -> .o output files for constructing libmclib.a
|-- includes
|   |-- foo.h
|   `-- bar.h
`-- libmclib.a

My SConstruct:

#!python
target = 'mock'

env = Environment(LINKCOM = "$LINK -o $TARGET $SOURCES $LINKFLAGS $CCFLAGS")
Export('env', 'target')

build_base = 'build'
SConscript('SConscript', variant_dir=build_base, duplicate=0)

# remove build directory
if GetOption('clean'):
    import subprocess
    subprocess.call(['rm', '-rf', build_base])

My SConscript:

#!python
Import('env')

# ...
# other stuff to build 'mclib_target'
# ...

def copy_header_files(target, source, env):
    Mkdir(target)
    header_files = []
    for d in env['CPPPATH']:
        header_files += Glob(d + "/*.h")
    for f in header_files:
        Copy(target, f)

# copy all relevant header files
env.Command("includes", mclib_target, copy_header_files)

Scons does call 'copy_header_files' with arguments '["build/includes"], ["build/libmclib.a"]', but for some reason 'Mkdir' doesn't create the includes directory. Also 'Copy' seems to do nothing. If I however call Mkdir like this:

env.Command("includes", mclib_target, [Mkdir('$TARGET')])

it seems to work well. How to fix/work around this? I'm also quite new to Scons so any alternative for doing this task are welcome. I'm using scons 2.5.0.

like image 874
MaartenVds Avatar asked Jan 05 '23 10:01

MaartenVds


2 Answers

You probably want to use "Install()" instead of "Copy()". Also the Mkdir() shouldn't be necessary, SCons creates all intermediate folders for its targets automatically.

Finally, allow me some comments about your general approach: I'd rather not mix "building" with "installing/preparing for packaging". The "variant_dir" option is there to help you with building several "variants" (release, optimized, debug, ARM-specific,...) from the same source files (let's say you have a folder named "src"). By passing the name of the current "build" directory into your "src" SConscript you're embedding variant-specific knowledge into your local build description, meaning that you'll have to touch it with every variant that you add. Instead, you should move the "Install/Package" steps into the top-level SConstruct...where you have global knowledge about which variants get built. From there you can copy (= Install) the final files to a separate subfolder, e.g. distribution, and archive that one instead.

For a simple example of how to handle variants right in SCons, check out the repo https://bitbucket.org/dirkbaechle/scons_talks and there the "pyconde_2013/examples/exvar" folder.

like image 155
dirkbaechle Avatar answered Jan 13 '23 10:01

dirkbaechle


The Mkdir and Copy operations that you are using are Action factories for use in Command definitions, described in Platform-Independent File System Manipulation:

SCons provides a number of platform-independent functions, called factories, that perform common file system manipulations like copying, moving or deleting files and directories, or making directories. These functions are factories because they don't perform the action at the time they're called, they each return an Action object that can be executed at the appropriate time.

I have always had problems trying to use these functions within my own action functions. Perhaps I am missing something, but I don't think these functions can be used outside of the immediate list of operations in the Command builder.

Instead I use the platform-independent functions in python for creating directories and copying files, such as os.makedirs and shutil.copy.

like image 26
Dave Bacher Avatar answered Jan 13 '23 09:01

Dave Bacher