【问题标题】:SCons: how to add cpp files to source listSCons:如何将 cpp 文件添加到源列表
【发布时间】:2015-03-06 21:03:52
【问题描述】:

在 SCons 中,我有一个生成未知数量文件的预构建步骤。生成这些文件后,我需要能够将 cpp 文件添加到我的源列表中。我是 SCons 的绝对初学者,我不确定正确的路径是什么。这样做的最佳方法是什么?

原文: 基本/原始构建步骤如下:

fpmFile = Dir('#').Dir('src').entry_abspath("FabricKINECT.fpm.json")
# The next step generates a bunch of source files
cppHeader = env.Command(
  [env.File(target + '.h')],
  klSources,
  [[kl2edkBin, fpmFile, "-o", hdir, "-c", cppdir]]
  )
env.Depends(cppSources, cppHeader)

# We pass in the supplied filelist to the build command
# however, this list does not include the cpp files generated above
# Currently I am hard-coding the generated files into
# the cppSources list, but I want to add them in dynamically
return env.SharedLibrary(
  '-'.join([target, buildOS, buildArch]),
  cppSources
  )

我的尝试 我尝试了几个不同的角度:

http://www.scons.org/wiki/DynamicSourceGenerator,但据我所知,这会为每个文件创建单独的构建目标,而我希望它们都包含在我的库构建中

使用发射器:SCons to generate variable number of targets,但我似乎无法解决依赖关系 - 无论我如何分配依赖关系,我的扫描仪都会先运行

我尝试制作另一个命令来收集文件列表 -

def gatherGenCpp(target, source, env):
  allFiles = Glob('generated/cpp/*.cpp')
  # clear dummy target
  del target[:]
  for f in allFiles:
    target.append(f)

genSources = env.Command(['#dummy-file'], cppdir, gatherGenCpp)
env.Depends(genSources, cppSources)

allSources = genSources + cppSources
return env.SharedLibrary(
  '-'.join([target, buildOS, buildArch]),
  allSources
  )

然而,这失败了

致命错误 LNK1181:无法打开输入文件 'dummy-file.obj'

我猜是因为即使我从命令的目标中清除了虚拟文件条目,这也会发生在它向构建系统注册之后(并且生成了预期的目标。

所有这一切 - 你将如何实现以下内容:

  • 一个命令生成一堆 CPP 文件
  • 这些文件被添加到传入的文件列表中
  • 我们根据这个 cpp 文件列表构建一个 dll。

有什么建议吗?

【问题讨论】:

    标签: python scons


    【解决方案1】:

    如果您想告诉 SCons 某些文件是使用他不知道的工具生成的,请使用 Builders

    即:

    env = DefaultEnvironment()
    
    # Create a builder that uses sed to replace all of occurrences
    # of `lion` word to `tiger`
    BigCatBuilder = Builder(action = Action('sed "s/lion/tiger/g" $SOURCE > $TARGET'))
    env.Append(BUILDERS = {'BigCatBuilder': BigCatBuilder})
    
    # Create tiger.c from pre/lion.c
    tiger_c = env.BigCatBuilder('tiger.c', 'pre/lion.c')
    
    # tiger.c is globbed by Glob('*.c')
    Program('tiger', Glob('*.c'))
    

    【讨论】:

    • 这似乎不起作用 - 在我的情况下,在构建步骤之前没有调用该操作。另外 - 构建器的工作是向构建系统提供文件,还是只是执行“generateFiles”步骤?据我所知,这只是这一步中收集文件的全局。如果构建步骤尚未运行,则没有要收集的文件。
    • @FrozenKiwi。您应该注意,调用env.Command 以及使用构建器不会直接调用该命令,它只是告诉SCons 如何构建目标('tiger.c'),如果他必须这样做。在评估 SConstruct 之后,它会构建依赖关系树(可以使用 --tree=all 转储),并根据先前构建的依赖关系调用命令。
    • 好的,我想我明白了。 Glob 将获取 pre/lion.c 文件,并在构建它时调用 BigCatBuilder 构建器。构建器将狮子转换为老虎,并将其返回到构建系统。如果我将我的 fpm 文件传递​​给 Program 调用,那么当它开始构建它时,它将触发我的构建器,然后生成所有 cpp 文件。然后我可以收集所有生成的文件并将它们返回到构建系统?
    • 不太正确。 BigCatBuilder 被显式调用,它会导致 tiger.c 文件的创建,因此 SCons 注意到并保存在其“虚拟文件系统”上。当Glob('*.c') 被调用时,它会从那个“virt.文件系统”(tiger.c)中挑选文件,所以要构建程序,它需要首先运行你的构建器。
    • 我无法事先知道将生成哪些文件,因此我无法从构建步骤中返回它们(至少在构建步骤运行之前)。
    【解决方案2】:

    正如 myaut 正确指出的那样,在您的情况下使用的方法是定义一个自定义 Builder。它应该将您当前的命令字符串作为操作,然后您可能还必须定义一个自定义发射器。有关如何将所有“点放在 i 上”的更详细说明,请参阅 http://www.scons.org/wiki/ToolsForFools。 Emitter 很重要,因为它在您的构建脚本被解析时运行,因此在调用 env.BigCatBuilder 时。它的返回值是实际构建步骤(将来)将产生的目标列表。 SCons 将这些目标作为节点存储在一个内部结构中,它在其中跟踪以下信息:此节点是否具有隐式依赖关系?它的子节点之一是否不是最新的,因此目标需要重建?... Glob() 调用将在本地文件系统中搜索,但也会遍历提到的“虚拟文件树”......并且像这样,能够跟踪对实际不存在的文件的依赖关系。 您不必管理生成文件的列表并将它们传递给不同的构建器。 Glob() 通常会为您完成大部分工作...

    【讨论】:

    • 问题是 - 在构建步骤运行之前,我不知道创建了哪些文件。我无法返回创建的文件。
    • 但是创建您生成的源文件的工具确实知道,对吧?这是一个确定性的过程,这意味着使用相同的输入,您将获得与输出完全相同数量的文件(包括相同的名称和相同的内容)。您必须弄清楚这方面的基本规则,并在您的 Builder/Emitter 中重新实现它们。这是正确的路径,以及所有更复杂的 SCons 工具的基本工作原理……例如,对 Qt4/Qt5 或 SWIG Builder 的 MOC 支持。
    • 哎呀 - 这些工具旨在成为 2 种不同语言之间的互操作。确定将创建哪些文件在许多方面与为文件创建词法解析器相同。还有其他方法吗?我可以将构建器的输出数组作为输入传递给命令并在那里修改吗?该数组是在 python 中通过引用传递的,因此在那里修改应该在任何地方修改它。或者一旦输入列表已经运行,scons 会不会善待我修改输入列表? (我已经花了几个小时试图让它工作,所以我想答案是......不)
    • 也许最好的办法是调用 sys 并执行文件生成器,而不是尝试通过 scons 运行它。一旦完成,我就可以抓取文件列表,一切都从那里愉快地流动。
    • 你当然可以做后者,但是你不再跟踪依赖关系了。关于 Builders/Emitter 的问题和影响,您可能想查看我们用户邮件列表中的线程 pairlist4.pair.net/pipermail/scons-users/2014-December/…pairlist4.pair.net/pipermail/scons-users/2014-December/…。他们在某种程度上更详细地解释了潜在的机制。
    【解决方案3】:

    最后,我只是在 scons 中运行了一个 exec 语句来生成文件。有时,最短的路径是最好的:)

    【讨论】:

      猜你喜欢
      • 2019-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-14
      • 1970-01-01
      相关资源
      最近更新 更多