python – 将Waf目标链接到由外部构建系统(CMake)生成的库
我的waf项目有两个依赖项,用CMake构建.
我正在尝试做的是遵循在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任务…… 还有一些问题: >如何在任务中封装read_shlib()调用,由CMake任务生成? 解决方法
事实上,你已经完成了大部分工作:)
read_shlib只创建一个虚假的任务,假装构建一个已经存在的lib.在你的情况下,你真的构建了lib,所以你真的不需要read_shlib.你可以在某个地方使用你的cmake任务生成器,因为你已经设置了正确的参数. 关键字use可识别使用的任务生成器中的一些参数: > export_includes 如果使用的任务生成器具有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") 您当然可以简化/分解代码.我认为add_target不应该在任务中,它主要管理任务生成器属性. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |