How to delete intermediate object files after build in scons - scons

I want to delete the intermediate object files after creation final output binary.
For example, let's say I've two source files (a.c and b.c) and SConsruct file. In SConstruct,
Program('out_bin', source=['a.c', 'b.c'])
scons command creates three binary files ('out_bin', 'a.o', and 'b.o')
Now I only want to keep the final binary file ('out_bin') and remove 'a.o' and 'b.o' .
What I need to do in SConstruct to accomplish this?

SCons doesn't support this directly, but you can use python's atexit to run any python code after SCons completes.
Take a look at:
http://scons.tigris.org/issues/show_bug.cgi?id=2834

Related

How do I get Scons to remove unused source files from a variant directory

I have a generated file from all of my sources, and the source generator uses a glob. Since I use variant directories to build, all (and only) the source that is in this build should placed in the variant directory so I pointed the glob at that dir to scrape from. When I remove a file from the build, this fails as the .c file I removed is still in the variant dir from a previous build. Clean does not remove sources copied into variants, so even clean builds don't work, I have to remove all the directory (or at least *.c) to get a good build again. Is there a way I can either: get scons to remove the extra sources, get a list of the no-longer needed sources so I can remove them pre-generation, or .....
I can not easily change the generator to take a list of files, tho that is the obvious 'best' solution.
SConstruct
VariantDir('build','src')
Command('generated.h', ['src1.c','src2.c'], 'python scrape_sources $TARGET.dir')
scrape_sources
import glob
import sys
f = open('generated')
f.write(','.join(glob.glob(sys.args[1]+'*.c'))
f.close()
When I remove src2.c from the list, the source file is still in build from the previous run and thus scanned. I want a way to nicely remove the sources no longer in the build.

SCons: When adding a Node to the LIBS variable, how do I make it use just the file without the directory?

I have SCons code in which I am using SConscripts to build different directories separately. In my Src directory, my SConscript builds a shared library, and then returns the resulting Node as the Python variable libMyLibrary. I typically use the install option to copy this library to a directory that is on my system's LD_LIBRARY_PATH (I'm using OpenSUSE).
So far, so good. Now, in another directory, Src/Test, another SConscript imports libMyLibrary and builds some Programs using code like this:
env.Program('myProgram', 'myProgram.cpp', LIBS=[env['LIBS'], libMyLibrary])
The program then gets installed to my local bin folder. This code does track the library dependency and build the program, but the problem is that since the library is in a sub-directory (Src), that sub-directory gets included in the linker command. Here is an abbreviated example of the linker command that SCons generates:
g++ -o Src/Test/myProgram Src/Test/myProgram.o Src/libMyLibrary.so
I believe this happens because the Node,libMyLibrary, is essentially a path. The problem is that when I try to run the program, it is not looking for libMyLibrary.so in my library folder, but rather Src/libMyLibrary.so, and of course it doesn't find it.
I do NOT want the libraries I build to be installed in sub-directories of my install folder.
I already add the Src folder to LIBPATH, so SCons adds the -LSrc option to the linker command, but that doesn't solve the problem. My preference would be that when I add a Node, the path should automatically get parsed out to add the appropriate -L and -l options.
I know that I can get around this problem by adding the string 'MyLibrary' to the LIBS variable instead of the libMyLibrary Node, but then I have to explicitly tell SCons that each Program Depends() on libMyLibrary. It seems very inefficient to short-circuit SCons's built-in dependency tracking this way. Does anyone know the correct, SCons-y way to do this?
I'm referring to your latest comment: It looks to me as if this is not really a SCons problem, but more a general linker question (XY problem). Are you perhaps simply searching for RPATH? Please also check this old SO question: scons executable + shared library in project directory

SCons Output in Build directory

I'm trying to modify my SCons files so that they put the generated files into a build directory. Initially I though VariantDir could be an option but judging from all I read and the examples it does not do what I want.
Is there any easy way to force SCons to put the output in a certain directory without having to rewrite all the sources and scripts?
After struggling with VariantDir for a while (it wasn't doing anything at all), I ended up using variant_dir parameter in the top level SConscript call, which causes all downstream build outputs end up in a parallel 'build' tree:
SConscript(['subdirs/SConscript'], variant_dir='build', duplicate=0)
My build structure is a hierarchy of SConscripts in subdirs/sub-subdirs, etc. With this call the outputs end up in build/sub-subdirs at the same level as they would in the source.
This eats up one level, though (subdirs), and using "../build" does not help. The solution is to have a SConscript file at the same level as SConstruct and call SConscript(['SConscript'], variant_dir='build', duplicate=0)
See also Force Scons output (exe, obj, lib & dll) to specific build directory - it has a similar answer
Using VariantDir with duplicate=0 should work.
Facing similar frustration, I added a site_scons that added replacement builders (e.g. "Exe" instead of "Program") and specified an emitter for that builder that replaced the path portion with the build directory. This requires the use of the alternate builder throughout your SConscripts though.
Alternatively you could try to subclass Environment and rewrite the main targets to use target rewrites. Then you specify your Environment as the default (modifying Scons.Script.DefaultEnvironment or something like that). This approach kept the SConscripts static but got very messy and requires more maintenance over time as scons internals change.
You might use Install or InstallAs on target output. It works for me.
lib = env.SharedLibrary(target = "some_target", source = sources);
env.InstallAs( target = "folder/output_name.ext", source = lib );

Multiple locations within a folder hierarchy to run SCons from

So far, I've only seen examples of running SCons in the same folder as the single SConstruct file resides. Let's say my project structure is like:
src/*.(cpp|h)
tools/mytool/*.(cpp|h)
What I'd like is to be able to run 'scons' at the root and also inside tools/mytool. The latter compiles only mytool. Is this possible with SCons?
I assume it involves creating another SConstruct file. I've made another one: tools/mytool/SConstruct
I made it contain only:
SConscript('../../SConstruct')
and I was thinking of doing Import('env mytoolTarget') and calling Default(mytoolTarget), but running it with just the above runs in the current directory instead of from the root, so the include paths are broken.
What's the correct way to do this?
You can use the -u option to do this. From any subdirectory, scons -u will search upwards in the directory tree for an SConstruct file.

how can i build a static library from files autogenerated by running a perl script within the SConscript

Here is what i need to do in scons, and at present I'm not able to get this to work correctly.
Firstly I need to run perl script 1. This generates a series of cpp files.
Then I need to run perl script 2. This generates another series of cpp files.
Then I need to take the cpp files that have been created as a result of executing the 2 perl scripts and build a static library from them.
I use a custom builder to execute the perl scripts. I don't want to manually define the target list, as this can change depending on the file that the perl scripts uses to generate the source files.
ny help would be much appreciated.
Thanks,
D
For running the perl scripts you just need to use standard python code:
import subprocess
subprocess.call(['perl', ...args...])
For building static lib, try something like this:
env = Environment()
env.StaticLibrary('example', Glob('*.cpp'))
where Glob('*.cpp') generates a list of all .cpp files. If you already have some customized environment just use is instead of env in my sample.

Resources