将Waf目标链接到由外部构建系统(CMake)生成的库

时间:2015-09-07 13:51:04

标签: python c++ c cmake waf

我的waf项目有两个依赖项,使用CMake构建。 我正在尝试做的是遵循waf git repo中的dynamic_build3示例,创建一个生成CMake的工具,并在成功构建之后,执行安装到waf的输出子目录:< / p>

BorderLayout

我想生成该工具,然后将waf目标链接到已安装的库,我使用&#34;假库&#34;调用@extension('.txt') def spawn_cmake(self, node): if node.name == 'CMakeLists.txt': self.cmake_task = self.create_task('CMake', node) self.cmake_task.name = self.target @feature('cmake') @after_method('process_source') def update_outputs(self): self.cmake_task.add_target() class CMake(Task.Task): color = 'PINK' def keyword(self): return 'CMake' def run(self): lists_file = self.generator.source[0] bld_dir = self.generator.bld.bldnode.make_node(self.name) bld_dir.mkdir() # process args and append install prefix try: cmake_args = self.generator.cmake_args except AttributeError: cmake_args = [] cmake_args.append( '-DCMAKE_INSTALL_PREFIX={}'.format(bld_dir.abspath())) # execute CMake cmd = '{cmake} {args} {project_dir}'.format( cmake=self.env.get_flat('CMAKE'), args=' '.join(cmake_args), project_dir=lists_file.parent.abspath()) try: self.generator.bld.cmd_and_log( cmd, cwd=bld_dir.abspath(), quiet=Context.BOTH) except WafError as err: return err.stderr # execute make install try: self.generator.bld.cmd_and_log( 'make install', cwd=bld_dir.abspath(), quiet=Context.BOTH) except WafError as err: return err.stderr try: os.stat(self.outputs[0].abspath()) except: return 'library {} does not exist'.format(self.outputs[0]) # store the signature of the generated library to avoid re-running the # task without need self.generator.bld.raw_deps[self.uid()] = [self.signature()] + self.outputs def add_target(self): # override the outputs with the library file name name = self.name bld_dir = self.generator.bld.bldnode.make_node(name) lib_file = bld_dir.find_or_declare('lib/{}'.format( ( self.env.cshlib_PATTERN if self.generator.lib_type == 'shared' else self.env.cstlib_PATTERN ) % name)) self.set_outputs(lib_file) def runnable_status(self): ret = super(CMake, self).runnable_status() try: lst = self.generator.bld.raw_deps[self.uid()] if lst[0] != self.signature(): raise Exception os.stat(lst[1].abspath()) return Task.SKIP_ME except: return Task.RUN_ME return ret

的机制
bld.read_shlib()

我发现这个* 非常丑陋 *因为:

  1. 在最终目标的链接阶段, ONLY 需要花栗鼠库,没有理由阻止整个构建(使用def build(bld): bld.post_mode = Build.POST_LAZY # build 3rd-party CMake dependencies first for lists_file in bld.env.CMAKE_LISTS: if 'Chipmunk2D' in lists_file: bld( source=lists_file, features='cmake', target='chipmunk', lib_type='shared', cmake_args=[ '-DBUILD_DEMOS=OFF', '-DINSTALL_DEMOS=OFF', '-DBUILD_SHARED=ON', '-DBUILD_STATIC=OFF', '-DINSTALL_STATIC=OFF', '-Wno-dev', ]) bld.add_group() # after this, specifying `use=['chipmunk']` in the target does the job out_dir = bld.bldnode.make_node('chipmunk') bld.read_shlib( 'chipmunk', paths=[out_dir.make_node('lib')], export_includes=[out_dir.make_node('include')]) 模式和{{ 1}})虽然取消阻止,但Build.POST_LAZY失败。想象一下,如果之前还有某种bld.add_group()任务......
  2. read_shlib()命令中调用git clone意味着调用者知道该工具如何以及在何处安装文件。我希望工具本身能够执行对read_shlib()的调用(如果有必要的话)。但是我在build()read_shlib()中没有这样做,正如Waf Book部分关于Custom tasks的第11.4.2段建议的那样,似乎我必须以某种方式填充对{{{}}的调用。 1}}在另一个任务中,并将其放在未记录的 run()属性中。
  3. 还有一些问题:

    1. 我如何在任务中填充runnable_status()调用,由CMake任务生成?
    2. 是否可以让任务以非阻塞方式并行执行其他任务(假设项目中有2个或3个CMake依赖项,这些依赖项将由read_shlib()从远程repos中获取) ?

1 个答案:

答案 0 :(得分:0)

事实上,你已经完成了大部分工作:)

read_shlib只创建假冒任务,假装构建一个已经存在的lib。在你的情况下,你真的构建了lib,所以你真的不需要read_shlib。鉴于您已设置正确的参数,您可以在某处use使用您的cmake任务生成器。

关键字use识别使用的任务生成器中的一些参数:

  • export_includes
  • export_defines

如果使用的任务生成器具有link_task,则它还管理库和任务顺序。

因此,您只需在cmake任务生成器中正确设置export_includesexport_defines,并设置引用link_task属性的cmake_task属性。您还必须正确设置cmake_task输出才能使其正常工作,即列表的第一个输出必须是lib节点(您在add_target中执行的操作似乎没问题)。类似的东西:

@feature('cmake')
@after_method('update_outputs')
def export_for_use(self):
    self.link_task = self.cmake_task
    out_dir = self.bld.bldnode.make_node(self.target)
    self.export_includes = out_dir.make_node('include')

完成后,您只需在主要的wscript中写下:

def build(bld):
    for lists_file in bld.env.CMAKE_LISTS:
        if 'Chipmunk2D' in lists_file:
            bld(
                source=lists_file,
                features='cmake',
                target='chipmunk',
                lib_type='shared',
                cmake_args=[
                    '-DBUILD_DEMOS=OFF',
                    '-DINSTALL_DEMOS=OFF',
                    '-DBUILD_SHARED=ON',
                    '-DBUILD_STATIC=OFF',
                    '-DINSTALL_STATIC=OFF',
                    '-Wno-dev',
                ])

    bld.program(source="main.cpp", use="chipmunk")

您当然可以简化/分解代码。我认为add_target不应该在任务中,它主要管理任务生成器属性。