Using noweb, I would either like to generate a document file (or a source file) from a noweb input file **.nw
From hand I would do something like that:
notangle my_program.nw > my_program.cpp
g++ -c my_program.o my_program.cpp
ln -o myapp ... my_program.o ...
Now I like to ask whether I can use scons to automate this.
Imagine, my project directory is on $MYPROJECT. THere we have "$MYPROJECT/SConstruct". Now I defined a scons tool "tangle.py" (simplified from "noweb.py). Here we have "$MYPROJECT/site_scons/site_tools/tangle.py"
import SCons.Builder
def cpp_emit (target,source, env):
# I dont know what to do here ... please help
return (target,source)
# Tangle to .cpp
__noweb_tangle_builder = SCons.Builder.Builder(
action='/usr/bin/notangle $SOURCES >$TARGET',
suffix='.cpp',
src_suffix='.nw',
emitter=cpp_emit)
# -----------------------
def generate(env):
env['BUILDERS']['tangle']= __noweb_tangle_builder
def exists(env):
return 1
This tool generates a cpp-file from a nw-file.
But if I do something like
def cpp_emit (target,source, env):
new_source=target[0].name
new_target=new_source.rstrip(".cpp")+".o"
target.append(new_target)
source.append(new_source)
return (target, source)
I get into a dependency circle. SCons will find and abort with an error message.
Doing ...
def cpp_emit (target,source, env):
new_source=target[0].name
# someprogram.cpp -> someprogram.o
new_target=new_source.rstrip(".cpp")+".o"
# lets avoid dependency cycle
t = []
t.append(new_target)
source.append(new_source)
# oops, we dropped target test.cpp. It wont be generated.
return (t, source)
... the tool would stop generating a cpp file from a nw file. (Cpp target dropped)
Do you know a working way to do use scons for literate programming?
thank you for reading.
Leonard
Here is the tool that I created. Note the use of env['BUILDERS']['Object'].src_builder
to allow env.Program()
to accept noweb files.
# site_cons/site_tools/tangle.py
import SCons.Builder
__all__=['generate', 'exists']
tangle_builder = SCons.Builder.Builder(
action='$NOTANGLE $SOURCES > $TARGET',
suffix = '.cpp',
src_suffix = '.nw')
def generate(env):
env['NOTANGLE'] = exists(env)
env['BUILDERS']['Tangle'] = tangle_builder
if 'Object' in env['BUILDERS']:
env['BUILDERS']['Object'].src_builder.append('Tangle')
def exists(env):
if 'NOTANGLE' in env:
return env['NOTANGLE']
return env.WhereIs('notangle')
And its use:
# SConstruct
env = Environment(tools=['default', 'tangle'])
env.Program('my_program.nw')
Here is the output of the above SConstruct:
$ scons -Q
/usr/bin/notangle my_program.nw > my_program.cpp
g++ -o my_program.o -c my_program.cpp
g++ -o my_program my_program.o
$ scons -c
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed my_program.cpp
Removed my_program.o
Removed my_program
scons: done cleaning targets.