2

使用 noweb,我想从 noweb 输入文件 **.nw 生成文档文件(或源文件)

从手我会做这样的事情:

notangle my_program.nw > my_program.cpp
g++ -c my_program.o my_program.cpp
ln -o myapp ... my_program.o ...

现在我想问我是否可以使用 scons 来自动执行此操作。

想象一下,我的项目目录在 $MYPROJECT 上。这里我们有“$MYPROJECT/SConstruct”。现在我定义了一个 scons 工具“tangle.py”(从“noweb.py”简化)。这里我们有“$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

此工具从 nw 文件生成 cpp 文件。

但是如果我做类似的事情

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)

我进入了一个依赖圈。SCons 将找到并中止并显示错误消息。

正在做 ...

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) 

...该工具将停止从 nw 文件生成 cpp 文件。(Cpp 目标下降)

您知道使用 scons 进行读写编程的工作方式吗?

谢谢你的阅读。


伦纳德

4

2 回答 2

1

似乎您正在尝试添加object文件而不实际编译cpp文件。

我做了一个小例子,应该有助于澄清情况。基本上,由于您在对 Builder 的调用中配置了后缀和 src_suffix,因此 SCons 正确设置了源和目标,并且您不需要发射器。

def cpp_emit (target,source, env):
    for t in target:
        print 'Emitter target: %s' % (t)
    for s in source:
        print 'Emitter source: %s' % (s.name)

    return (target,source)

# Tangle to .cpp
builder = Builder(
    action='/home/notroot/projects/sandbox/Emitter/builder.sh $SOURCES $TARGET',
    suffix='.cc',
    src_suffix='.nw',
    emitter=cpp_emit)

env = Environment()
env['BUILDERS']['tangle'] = builder

tangleTarget = env.tangle(target='main.cc', source='main.nw')
env.Object(source=tangleTarget)

这是输出:

$ scons
scons: Reading SConscript files ...
Emitter target: main.cc
Emitter source: main.nw
scons: done reading SConscript files.
scons: Building targets ...
/home/notroot/projects/sandbox/Emitter/builder.sh main.nw main.cc
g++ -o main.o -c main.cc
scons: done building targets.

$ scons -c
scons: Reading SConscript files ...
Emitter target: main.cc
Emitter source: main.nw
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed main.cc
Removed main.o
scons: done cleaning targets.

我做了以下让Builder生成cc文件并编译它,但它没有清理object文件。

import os

def cpp_emit(target,source, env):
    for s in source:
        print 'Emitter source: %s' % (s.name)
    for t in target:
        print 'Emitter target: %s' % (t)

    return (target,source)

def build_function(target, source, env):
    # Code to build "target" from "source"
    for t in target:
        print 'Builder target: %s' % (t.name)
    for s in source:
        print 'Builder source: %s' % (s.name)

    buildStr='/home/notroot/projects/sandbox/Emitter/builder.sh %s %s' % (source[0].name, target[0].name)
    os.system(buildStr)

    trgt = env.Object(source=target[0])

    # return 0 or None upon success
    return None

# Tangle to .cc and .o
builder = Builder(
    action=build_function,
    suffix='.cc',
    src_suffix='.nw',
    emitter=cpp_emit)

env = Environment()
env['BUILDERS']['tangle'] = builder

tangleTarget = env.tangle(target='main.cc', source='main.nw')

这是输出:

$ scons
scons: Reading SConscript files ...
Emitter source: main.nw
Emitter target: main.cc
scons: done reading SConscript files.
scons: Building targets ...
build_function(["main.cc"], ["main.nw"])
Builder target: main.cc
Builder source: main.nw
scons: done building targets.

$ scons -c
scons: Reading SConscript files ...
Emitter source: main.nw
Emitter target: main.cc
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed main.cc
scons: done cleaning targets.

在第二个示例中,如果您将目标文件添加为目标,您将收到以下错误(正确)

scons: *** [main.cc] Multiple ways to build the same target were specified for: main.o  (from ['main.nw'] and from ['main.cc'])
于 2013-10-26T12:42:55.350 回答
1

这是我创建的工具。注意使用env['BUILDERS']['Object'].src_builder允许env.Program()接受 noweb 文件。

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

及其用途:

# SConstruct
env = Environment(tools=['default', 'tangle'])
env.Program('my_program.nw')

以下是上述 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.
于 2014-09-26T03:27:03.363 回答