mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-03-03 12:14:10 -04:00
waf: cmake: add Waf tool
This commit is contained in:
parent
38da32853a
commit
e883242c31
184
Tools/ardupilotwaf/cmake.py
Normal file
184
Tools/ardupilotwaf/cmake.py
Normal file
@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
# Copyright (C) 2015-2016 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# This file is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This file is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Waf tool for external builds with cmake. This tool defines two features:
|
||||
- cmake_configure: for defining task generators that do cmake build
|
||||
configuration, i.e., build system generation.
|
||||
- cmake_build: for actual build through the cmake interface.
|
||||
|
||||
Example::
|
||||
|
||||
def build(bld):
|
||||
# cmake configuration
|
||||
foo = bld(
|
||||
features='cmake_configure',
|
||||
name='foo',
|
||||
cmake_src='path/to/foosrc', # where is the source tree
|
||||
cmake_bld='path/to/foobld', # where to generate the build system
|
||||
cmake_vars=dict(
|
||||
CMAKE_BUILD_TYPE='Release',
|
||||
...
|
||||
),
|
||||
)
|
||||
|
||||
# cmake build for target (cmake target) 'bar'
|
||||
bld(
|
||||
features='cmake_build',
|
||||
cmake_config='foo', # this build depends on the cmake generation above defined
|
||||
cmake_target='bar', # what to pass to option --target of cmake
|
||||
)
|
||||
|
||||
# cmake build for target 'baz' (syntactic sugar)
|
||||
foo.cmake_build('baz')
|
||||
|
||||
There may be cases when you want to stablish dependency between other tasks and
|
||||
the external build system's products (headers and libraries, for example). In
|
||||
that case, you can specify the specific files in the option 'target' of your
|
||||
cmake_build task generator. In general, that feature is supposed to be used by
|
||||
other tools rather than by wscripts. Example::
|
||||
|
||||
def build(bld):
|
||||
...
|
||||
|
||||
# declaring on target only what I'm interested in
|
||||
foo.cmake_build('baz', target='path/to/foobld/include/baz.h')
|
||||
|
||||
@feature('myfeature')
|
||||
def process_myfeature(self):
|
||||
baz_taskgen = self.bld.get_tgen_by_name('baz')
|
||||
baz_taskgen.post()
|
||||
|
||||
# every cmake_build taskgen stores its task in cmake_build_task
|
||||
baz_task = baz_taskgen.cmake_build_task
|
||||
|
||||
tsk = self.create_task('mytask')
|
||||
|
||||
tsk.set_run_after(baz_task)
|
||||
|
||||
# tsk is run whenever baz_task changes its outputs, namely,
|
||||
# path/to/foobld/include/baz.h
|
||||
tsk.dep_nodes.extend(baz_task.outputs)
|
||||
"""
|
||||
|
||||
from waflib import Node, Task, Utils
|
||||
from waflib.TaskGen import feature, taskgen_method
|
||||
|
||||
class cmake_configure_task(Task.Task):
|
||||
run_str = '${CMAKE} ${CMAKE_SRC_DIR} ${CMAKE_VARS} ${CMAKE_GENERATOR_OPTION}'
|
||||
|
||||
def runnable_status(self):
|
||||
if not self.generator.cmake_bld.find_node('CMakeCache.txt'):
|
||||
return Task.RUN_ME
|
||||
return Task.SKIP_ME
|
||||
|
||||
def __str__(self):
|
||||
return self.generator.name
|
||||
|
||||
def keyword(self):
|
||||
return 'CMake Configure'
|
||||
|
||||
class cmake_build_task(Task.Task):
|
||||
run_str = '${CMAKE} --build ${CMAKE_BLD_DIR} --target ${CMAKE_TARGET}'
|
||||
|
||||
def __str__(self):
|
||||
config_name = self.generator.config_taskgen.name
|
||||
target = self.generator.cmake_target
|
||||
return '%s %s' % (config_name, target)
|
||||
|
||||
def keyword(self):
|
||||
return 'CMake Build'
|
||||
|
||||
# allow tasks to depend on possible headers or other resources if the user
|
||||
# declares outputs for the cmake build
|
||||
cmake_build_task = Task.update_outputs(cmake_build_task)
|
||||
|
||||
# the cmake-generated build system is responsible of managing its own
|
||||
# dependencies
|
||||
cmake_build_task = Task.always_run(cmake_build_task)
|
||||
|
||||
@feature('cmake_configure')
|
||||
def process_cmake_configure(self):
|
||||
if not hasattr(self, 'name'):
|
||||
self.bld.fatal('cmake_configure: taskgen is missing name')
|
||||
if not hasattr(self, 'cmake_src'):
|
||||
self.bld.fatal('cmake_configure: taskgen is missing cmake_src')
|
||||
|
||||
if not isinstance(self.cmake_src, Node.Node):
|
||||
self.cmake_src = self.bld.path.find_dir(self.cmake_src)
|
||||
|
||||
if not hasattr(self, 'cmake_bld'):
|
||||
self.cmake_bld = self.cmake_src.get_bld()
|
||||
elif not isinstance(self.cmake_bld, Node.Node):
|
||||
self.cmake_bld = self.bld.bldnode.make_node(self.cmake_bld)
|
||||
self.cmake_bld.mkdir()
|
||||
|
||||
self.cmake_vars = getattr(self, 'cmake_vars', {})
|
||||
|
||||
# NOTE: we'll probably need to use the full class name in waf 1.9
|
||||
tsk = self.cmake_config_task = self.create_task('cmake_configure')
|
||||
tsk.cwd = self.cmake_bld.abspath()
|
||||
tsk.env.CMAKE_SRC_DIR = self.cmake_src.abspath()
|
||||
tsk.env.CMAKE_VARS = ["-D%s='%s'" % item for item in self.cmake_vars.items()]
|
||||
|
||||
@feature('cmake_build')
|
||||
def process_cmake_build(self):
|
||||
if not hasattr(self, 'cmake_target'):
|
||||
self.bld.fatal('cmake_build: taskgen is missing cmake_target')
|
||||
if not hasattr(self, 'cmake_config'):
|
||||
self.bld.fatal('cmake_build: taskgen is missing cmake_config')
|
||||
|
||||
self.config_taskgen = self.bld.get_tgen_by_name(self.cmake_config)
|
||||
|
||||
if not getattr(self.config_taskgen, 'posted', False):
|
||||
self.config_taskgen.post()
|
||||
|
||||
# NOTE: we'll probably need to use the full class name in waf 1.9
|
||||
tsk = self.cmake_build_task = self.create_task('cmake_build')
|
||||
tsk.env.CMAKE_BLD_DIR = self.config_taskgen.cmake_bld.abspath()
|
||||
tsk.env.CMAKE_TARGET = self.cmake_target
|
||||
tsk.set_run_after(self.config_taskgen.cmake_config_task)
|
||||
|
||||
outputs = Utils.to_list(getattr(self, 'target', ''))
|
||||
for o in outputs:
|
||||
if not isinstance(o, Node.Node):
|
||||
o = self.path.find_or_declare(o)
|
||||
tsk.set_outputs(o)
|
||||
|
||||
@taskgen_method
|
||||
def cmake_build(self, cmake_target, **kw):
|
||||
if not 'cmake_configure' in self.features:
|
||||
self.bld.fatal('cmake_build: this is not a cmake_configure taskgen')
|
||||
|
||||
kw['cmake_config'] = self.name
|
||||
kw['cmake_target'] = cmake_target
|
||||
|
||||
if 'name' not in kw:
|
||||
kw['name'] = '%s_%s' % (self.name, cmake_target)
|
||||
|
||||
kw['features'] = Utils.to_list(kw.get('features', []))
|
||||
kw['features'].append('cmake_build')
|
||||
|
||||
return self.bld(**kw)
|
||||
|
||||
def configure(cfg):
|
||||
cfg.find_program('cmake')
|
||||
cfg.find_program(['ninja', 'ninja-build'], var='NINJA', mandatory=False)
|
||||
cfg.env.CMAKE_GENERATOR_OPTION = ''
|
||||
if cfg.env.NINJA:
|
||||
cfg.env.CMAKE_GENERATOR_OPTION = '-GNinja'
|
Loading…
Reference in New Issue
Block a user