我的waf項目有兩個依賴項,使用CMake構建。 我想要做的,是繼在WAF git倉庫發現dynamic_build3例如,創建一個工具,它派生CMake和編譯成功後,執行安裝到WAF的輸出子目錄:將Waf目標鏈接到由外部構建系統生成的庫(CMake)
@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()
WAF的目標鏈接到安裝的庫,這是我執行使用「假庫」機制:
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')])
我覺得這是* 非常難看 *因爲:
- 在最終目標的鏈接階段的花栗鼠庫需要ONLY,沒有理由阻止整個構建(通過使用
Build.POST_LAZY
模式和bld.add_group()
),但疏通它使read_shlib()
失敗。想象一下,如果在此之前還有某種git clone
任務... - 在
build()
命令中調用read_shlib()
命令意味着調用者知道工具如何以及在何處安裝文件。我希望工具本身執行read_shlib()
的調用(如有必要)。但我失敗在run()
和runnable_status()
這樣做,作爲建議書WAF節第11.4.2約Custom tasks,看來我必須以某種方式incapsulate調用read_shlib()
在ANOTHER任務,並把它裏面的無證more_tasks
屬性。
而且有問題:
- 我怎樣才能incapsulate的
read_shlib()
呼叫任務,由CMake的任務被催生? - 是否可以讓任務以非阻塞方式並行進行其他任務(假設項目中有2個或3個這些CMake依賴關係,這些依賴關係將由遠程回購提供
git
)?