SCons含部分生成源码的变体构建:如何正确配置依赖关系
解决方案:SCons多变体共享生成源码的正确姿势
核心思路
利用SCons的VariantDir特性+显式指定目标文件路径,结合依赖链确保构建顺序,避免生成文件复制冲突与更新识别失效问题。
1. 父脚本(scons.1)提前锚定生成文件的构建优先级
在调用子SConscript前,先完成生成文件的规则定义,确保生成动作优先调度,同时传递全局节点而非路径:
# scons.1 env = Environment() # 先生成cpp_list,明确生成文件的构建规则 cpp_list = env.MyGenerator(...) # 循环初始化变体构建环境并调用子脚本 variants = ["debug", "release"] for variant in variants: variant_env = env.Clone() # 设置变体专属编译参数(如宏定义、优化等级) variant_env.Append(CPPDEFINES=[f"BUILD_{variant.upper()}"]) SConscript( "scons.2", variant_dir=f"build/{variant}", duplicate=0, exports={"env": variant_env, "shared_cpp": cpp_list} )
2. 子脚本(scons.2)显式分离源文件编译路径
不直接将生成文件传入库构建器,而是通过Object构建器单独编译生成文件,指定输出到当前变体目录,再合并目标文件构建库:
# scons.2 Import("env", "shared_cpp") # 处理本地源文件,自动在variant_dir生成目标文件 local_objs = env.Object(["a.cpp", "b.cpp"]) # 处理共享生成的cpp文件,强制目标文件输出到变体目录 shared_objs = [] for cpp in shared_cpp: # 生成变体目录下的目标文件路径 obj_path = env.File(cpp.name).get_path(env.Dir(".")) obj = env.Object(obj_path, cpp) shared_objs.append(obj) # 合并所有目标文件构建共享库 env.MySharedLibrary("foo", local_objs + shared_objs)
3. 修复依赖顺序与更新识别
- 父脚本中
cpp_list = env.MyGenerator(...)已建立生成文件的依赖链,子脚本引用这些节点时,SCons会自动感知生成文件的更新,触发对应目标文件的重编译。 - 若仍存在顺序问题,在子脚本中添加显式依赖:
# scons.2 中追加 env.Depends(shared_objs, shared_cpp)
确保生成文件完全生成后,才启动对应目标文件的编译。
4. 关键注意事项
绝对不要复制生成文件到变体目录,直接引用父目录的生成文件作为编译源,通过Object构建器指定输出路径即可。这样既保证生成文件仅生成一次,又让每个变体拥有独立的目标文件,彻底避免冲突。
内容的提问来源于stack exchange,提问作者Mtm 3.14
相关产品推荐
相关产品推荐

