Finish auto-converting most of the gyp files.
I've also started writing down which ones need manual work.
Change-Id: I442782e1e3352e0de32b612f1bd2c167f231495a
diff --git a/doc/gyp_to_bazel.py b/doc/gyp_to_bazel.py
index b3da95b..85f7835 100755
--- a/doc/gyp_to_bazel.py
+++ b/doc/gyp_to_bazel.py
@@ -15,6 +15,7 @@
import os
import yaml
import collections
+import re
'''Converts a Gyp filename to its Bazel equivalent.
@@ -60,8 +61,24 @@
if target[0] == ':':
return target
+ # These thin wrappers won't be copied.
if target == '<(AOS)/build/aos.gyp:logging':
return '//aos/common/logging'
+ if target == '<(AOS)/build/aos.gyp:logging_interface':
+ return '//aos/common/logging:logging_interface'
+
+ # These are getting moved to the right place manually.
+ if target == '<(AOS)/common/common.gyp:condition':
+ return '//aos/linux_code/ipc_lib:condition'
+ if target == '<(AOS)/common/common.gyp:mutex':
+ return '//aos/linux_code/ipc_lib:mutex'
+ if target == '<(AOS)/common/common.gyp:event':
+ return '//aos/linux_code/ipc_lib:event'
+
+ # By building ..., we can mostly ignore these.
+ if (target == '<(AOS)/build/aos_all.gyp:Prime' or
+ target == '../../frc971/frc971.gyp:All'):
+ return '//aos:prime_binaries'
split = target.split(':')
if len(split) != 2:
@@ -95,6 +112,9 @@
def add_dep(self, bazel_dep):
self.__deps.append(bazel_dep)
+ def _type(self):
+ return self.__type
+
'''Returns a collections.OrderedDict with all of the attributes on the
Bazel rule this represents.
@@ -144,17 +164,30 @@
super(CcBuildTarget, self).__init__(type, name)
self.__srcs = []
+ self.__hdrs = []
self.__deps = []
+ self.__tags = []
def add_src(self, src):
self.__srcs.append(src)
+ def add_hdr(self, hdr):
+ self.__hdrs.append(hdr)
+
def add_dep(self, dep):
self.__deps.append(dep)
+ def add_tag(self, tag):
+ if self._type() != 'cc_test':
+ raise RuntimeError(
+ 'Trying to add tag %s to non-test type %s' % (tag, self._type()))
+ self.__tags.append(tag)
+
def attrs(self):
r = super(CcBuildTarget, self).attrs();
r['srcs'] = self.__srcs
+ r['hdrs'] = self.__hdrs
+ r['tags'] = self.__tags
r['deps'] = self.__deps
return r
@@ -179,18 +212,29 @@
super(QueueTarget, self).__init__('queue_library', name)
self.__srcs = []
+ self.__deps = []
def add_src(self, src):
self.__srcs.append(src)
+ def add_dep(self, dep):
+ self.__deps.append(dep)
+
def loads(self):
- return set((('aos/build/queues', 'queue_library'),))
+ return set((('/aos/build/queues', 'queue_library'),))
def attrs(self):
r = super(QueueTarget, self).attrs();
r['srcs'] = self.__srcs
+ r['deps'] = self.__deps
return r
+def _warn_attr(keys_to_handle, name, gyp_file_name, attr):
+ if attr in keys_to_handle:
+ print('Target %s in %s has %s' % (name, gyp_file_name, attr),
+ file=sys.stderr)
+ keys_to_handle.remove(attr)
+
def main(argv):
for d in argv:
build_targets = []
@@ -208,32 +252,96 @@
targets = gyp['targets']
for gyp_target in targets:
target = None
+ keys_to_handle = set(gyp_target.keys())
+ if 'export_dependent_settings' in gyp_target:
+ keys_to_handle.remove('export_dependent_settings')
name = gyp_target['target_name']
+ keys_to_handle.remove('target_name')
+ _warn_attr(keys_to_handle, name, gyp_file_name, 'actions')
+ _warn_attr(keys_to_handle, name, gyp_file_name, 'conditions')
+ _warn_attr(keys_to_handle, name, gyp_file_name, 'copies')
+ _warn_attr(keys_to_handle, name, gyp_file_name, 'hard_dependency')
+ _warn_attr(keys_to_handle, name, gyp_file_name,
+ 'direct_dependent_settings')
+
+ # These are getting moved to the right place manually.
+ if gyp_file_name == 'aos/common/common.gyp':
+ if name == 'condition' or name == 'mutex' or name == 'event':
+ continue
+ # By building ..., this becomes irrelevant.
+ if gyp_file_name == 'frc971/frc971.gyp':
+ if name == 'All':
+ continue
+
+ if 'variables' in gyp_target:
+ if 'no_rsync' in gyp_target['variables']:
+ del gyp_target['variables']['no_rsync']
+
type = gyp_target['type']
+ keys_to_handle.remove('type')
if (type in ['static_library', 'executable'] and
not 'includes' in gyp_target):
cc_type = {
'static_library': 'cc_library',
'executable': 'cc_binary',
}[type]
+ if re.match('.*_test$', name) and cc_type == 'cc_binary':
+ cc_type = 'cc_test'
target = CcBuildTarget(cc_type, name)
- for dep in gyp_target['dependencies']:
- target.add_dep(gyp_target_to_bazel(gyp_file_name, dep))
- for src in gyp_target['sources']:
- target.add_src(src)
+ if 'dependencies' in gyp_target:
+ for dep in gyp_target['dependencies']:
+ target.add_dep(gyp_target_to_bazel(gyp_file_name, dep))
+ keys_to_handle.remove('dependencies')
+ if 'sources' in gyp_target:
+ for src in gyp_target['sources']:
+ # In //aos/common:queue_types, this will get dealt with manually
+ # along with the actions.
+ if src == '<(print_field_cc)':
+ continue
+
+ if '/' in src:
+ raise RuntimeError(
+ 'Bad folder for %s in target %s in %s' % (src, name,
+ gyp_file_name))
+
+ target.add_src(src)
+
+ # This is sort of a heuristic: if there's a header file matching
+ # the source file, add it as an hdr. This is going to require some
+ # manual cleanup, but it'll be close.
+ src_filename = os.path.join(os.path.dirname(gyp_file_name), src)
+ if not os.path.exists(src_filename):
+ raise RuntimeError(
+ 'Can not find source %s in target %s' % (src_filename,
+ name))
+ header = src_filename.rsplit('.', 2)[0] + '.h'
+ if os.path.exists(header):
+ target.add_hdr(src.rsplit('.', 2)[0] + '.h')
+ keys_to_handle.remove('sources')
+ if 'variables' in gyp_target:
+ vars = gyp_target['variables']
+ if 'is_special_test' in vars:
+ if vars['is_special_test'] != 1:
+ raise RuntimeError(
+ 'Unexpected is_special_test value in target %s' % name)
+ target.add_tag('manual')
+ del vars['is_special_test']
elif type == 'none':
target = FilegroupTarget(name)
for dep in gyp_target['dependencies']:
target.add_src(gyp_target_to_bazel(gyp_file_name, dep))
+ keys_to_handle.remove('dependencies')
elif 'includes' in gyp_target:
includes = gyp_target['includes']
+ keys_to_handle.remove('includes')
if len(includes) != 1:
raise RuntimeError(
'Not sure how to handle multiple includes in %s' % gyp_target)
include = gyp_file_to_bazel(gyp_file_name, includes[0])
if include == '//aos/build/queues.gypi':
vars = gyp_target['variables']
+ keys_to_handle.remove('variables')
if 'header_path' not in vars:
raise RuntimeError(
'No header_path for target %s in %s' % (name, gyp_file_name))
@@ -253,6 +361,11 @@
name,
gyp_file_name))
target.add_src(src)
+ keys_to_handle.remove('sources')
+ if 'dependencies' in gyp_target:
+ for dep in gyp_target['dependencies']:
+ target.add_dep(gyp_target_to_bazel(gyp_file_name, dep))
+ keys_to_handle.remove('dependencies')
else:
raise RuntimeError(
'Unknown include %s for target %s in %s' % (include, name,
@@ -263,8 +376,31 @@
if not target:
raise
+
+ if (gyp_file_name == 'y2015/http_status/http_status.gyp' and
+ name == 'http_status'):
+ # We'll handle these manually.
+ keys_to_handle.remove('include_dirs')
+ if (gyp_file_name == 'aos/common/common.gyp' and
+ name == 'queue_types'):
+ # These will get handled manually as part of dealing with the
+ # actions.
+ keys_to_handle.remove('variables')
+
+ # If there were variables but they all got deleted, then we don't
+ # actually have any more to handle.
+ if 'variables' in keys_to_handle and not gyp_target['variables']:
+ keys_to_handle.remove('variables')
+ if keys_to_handle:
+ raise RuntimeError(
+ 'Unhandled keys for target %s in %s: %s' % (name, gyp_file_name,
+ keys_to_handle))
build_targets.append(target)
+ if not build_targets:
+ print('No output targets for %s' % d, file=sys.stderr)
+ continue
+
with open(os.path.join(d, 'BUILD'), 'w') as build_file:
build_file.write(
'package(default_visibility = [\'//visibility:public\'])\n')