我正在尝试做的是遵循在waf git repo中找到的 dynamic_build3示例,创建一个生成CMake的工具,并在成功构建之后,执行安装到waf的输出子目录中:
@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',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
我想生成该工具,然后将waf目标链接到已安装的库,我通过调用bld.read_shlib()使用“假库”机制执行:
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')])
我觉得这很*非常*因为:
>只有在最终目标的链接阶段才需要使用chipmunk库,没有理由阻止整个构建(通过使用Build.POST_LAZY模式和bld.add_group()),尽管解锁它会使read_shlib()失败.想象一下,如果之前还有某种git clone任务……
>在build()命令中调用read_shlib()意味着调用者知道工具安装文件的方式和位置.我希望工具本身能够执行对read_shlib()的调用(如果需要的话).但是我在run()和runnable_status()中没有这样做,正如Waf Book部分关于Custom tasks的第11.4.2段建议的那样,似乎我必须以某种方式封装在另一个任务中调用read_shlib()并将其放入未记录的more_tasks属性.
还有一些问题:
>如何在任务中封装read_shlib()调用,由CMake任务生成?
>是否有可能让任务以非阻塞的方式并行执行其他任务(假设一个项目有2个或3个这些CMake依赖项,这些将由远程repos中的git获取)?
解决方法
read_shlib只创建一个虚假的任务,假装构建一个已经存在的lib.在你的情况下,你真的构建了lib,所以你真的不需要read_shlib.你可以在某个地方使用你的cmake任务生成器,因为你已经设置了正确的参数.
关键字use可识别使用的任务生成器中的一些参数:
> export_includes
> export_defines
如果使用的任务生成器具有link_task,它还管理库和任务顺序.
因此,您只需在cmake任务生成器中正确设置export_includes和export_defines,并设置引用cmake_task属性的link_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,]) bld.program(source="main.cpp",use="chipmunk")
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。