You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写支持拷贝本缓存与调用检测的COBOL SCons构建器

问题解答

A、需求实现方案

1. copybooks扫描缓存实现

直接复用SCons原生的Scanner机制即可,不需要自行实现缓存逻辑:

  • SCons的自定义扫描器默认会将扫描结果和源文件的哈希值绑定存储在.sconsign文件中,只有当源文件内容发生变更时才会重新执行扫描,和C语言头文件的默认处理逻辑完全一致。
  • 只需要把原有的getCopyBooks逻辑封装为扫描器函数,关联到.cbl后缀的源文件即可。

2. 自动检测CALL语句添加构建目标实现

通过SCons的Emitter机制实现:

  • Emitter会在构建器执行前处理目标和依赖关系,你可以在Emitter中扫描当前COBOL源文件的CALL语句,自动为每个被调用的程序生成对应的构建目标,并添加到当前目标的依赖链中。
  • 新增全局目标缓存字典,避免重复创建相同的构建目标,同时可兼容循环调用的场景。

以下是完整的实现代码:

import re
from SCons.Scanner import Scanner
from SCons.Builder import Builder
Import('env')

# 全局配置,可根据项目实际路径调整
COBOL_TARGET_CACHE = {}
COBOL_SRC_SEARCH_PATHS = ['src/cbl', 'src/bat']
COPYBOOK_SEARCH_PATHS = ['src/cpy']
TARGET_OUTPUT_DIR = 'lib'

# COPYBOOK扫描函数
def scan_copybooks(node, env, path):
    copybooks = []
    regex = r'^......\s*COPY\s*[\'"]?([A-Z0-9]+)[\'"]?\.?$'
    with open(node.get_abspath(), 'r', encoding='utf-8') as f:
        for line in f:
            m = re.match(regex, line.rstrip(), re.I)
            if m:
                cb_name = m.group(1).upper()
                for search_path in path:
                    cb_node = env.FindFile(f"{cb_name}.cpy", search_path)
                    if cb_node:
                        copybooks.append(cb_node)
                        break
    return copybooks

# 定义COPYBOOK扫描器,自动处理缓存
cobol_copybook_scanner = Scanner(
    function=scan_copybooks,
    skeys=['.cbl'],
    path_function=lambda env, dir, target: env['COPYBOOKPATH'],
    recursive=True
)

# Emitter:处理CALL依赖,自动生成被调用程序的构建目标
def cobol_program_emitter(target, source, env):
    src_path = source[0].get_abspath()
    regex = r'^......\s*CALL\s*[\'"]?([A-Z0-9]+)[\'"]?\.?$'
    call_progs = []
    with open(src_path, 'r', encoding='utf-8') as f:
        for line in f:
            m = re.match(regex, line.rstrip(), re.I)
            if m:
                call_progs.append(m.group(1).upper())
    
    for prog_name in call_progs:
        lib_target = f"{env['TARGET_OUTPUT_DIR']}/{prog_name}.so"
        if lib_target not in env['COBOL_TARGET_CACHE']:
            # 查找被调用程序的源文件
            prog_src = None
            for search_path in env['COBOL_SRC_SEARCH_PATHS']:
                prog_src = env.FindFile(f"{prog_name}.cbl", search_path)
                if prog_src:
                    break
            if prog_src:
                # 自动创建构建目标
                env.CobolProgram(lib_target, prog_src)
                env['COBOL_TARGET_CACHE'][lib_target] = True
        # 添加依赖保证被调用程序先构建
        env.Depends(target[0], lib_target)
    return target, source

# 定义COBOL构建器
cobol_builder = Builder(
    action='cobc -o $TARGET $COPYBOOK_FLAGS $SOURCE',
    emitter=cobol_program_emitter,
    source_scanner=cobol_copybook_scanner
)

# 环境变量配置
env.Append(
    BUILDERS={'CobolProgram': cobol_builder},
    COPYBOOKPATH=COPYBOOK_SEARCH_PATHS,
    COPYBOOK_FLAGS=[f"-I{p}" for p in COPYBOOK_SEARCH_PATHS],
    COBOL_SRC_SEARCH_PATHS=COBOL_SRC_SEARCH_PATHS,
    TARGET_OUTPUT_DIR=TARGET_OUTPUT_DIR,
    COBOL_TARGET_CACHE=COBOL_TARGET_CACHE
)

# 使用示例,无需手动添加COPYBOOK依赖和PROG2的构建规则
env.CobolProgram('lib/PROG1.so', 'src/bat/PROG1.cbl')

B、可参考的示例

  1. SCons官方用户指南中自定义Builder、自定义Scanner、自定义Emitter的官方示例,逻辑完全通用。
  2. SCons内置的Fortran语言构建器实现,同样需要处理INCLUDE文件扫描和模块依赖,和COBOL的COPYBOOK、CALL依赖的处理逻辑高度相似。
  3. 开源的第三方SCons扩展构建器(如Rust、Go语言构建器)的实现,可参考依赖扫描和自动目标生成的通用逻辑。

内容的提问来源于stack exchange,提问作者Be Kind To New Users

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 22:15:01