blob: f548d3206643c706da4f95c898092137aa70a338 [file] [log] [blame] [edit]
#
# Copyright 2016 The Cobalt Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Functionality to enumerate and represent starboard ports."""
import logging
import os
import re
import _env # pylint: disable=unused-import
from starboard.tools import environment
# The list of files that must be present in a directory to allow it to be
# considered a valid platform.
_PLATFORM_FILES = [
'gyp_configuration.gypi',
'gyp_configuration.py',
'starboard_platform.gyp',
'configuration_public.h',
'atomic_public.h',
'thread_types_public.h',
]
# Whether to emit warnings if it finds a directory that almost has a platform.
# TODO: Enable when tree is clean.
_WARN_ON_ALMOST = False
def _IsValidPlatformFilenameList(directory, filenames):
"""Determines if |filenames| contains the required files for a valid port."""
missing = set(_PLATFORM_FILES) - set(filenames)
if missing:
if len(missing) < (len(_PLATFORM_FILES) / 2) and _WARN_ON_ALMOST:
logging.warning('Directory %s contains several files needed for a '
'platform, but not all of them. In particular, it is '
'missing: %s', directory, ', '.join(missing))
return not missing
def _GetPlatformName(root, directory):
"""Gets the name of a platform found at |directory| off of |root|."""
assert directory.startswith(root)
start = len(root) + 1 # Remove the trailing slash from the root.
assert start < len(directory)
# Calculate the name based on relative path from search root to directory.
return re.sub(r'[^a-zA-Z0-9_]', r'-', directory[start:])
def _EnumeratePlatforms(root_path, exclusion_set=None):
"""Generator that iterates over Starboard platforms found under |path|."""
if not exclusion_set:
exclusion_set = set()
for current_path, directories, filenames in os.walk(root_path):
# Don't walk into any directories in the exclusion set.
directories[:] = (x for x in directories
if os.path.join(current_path, x) not in exclusion_set)
# Determine if the current directory is a valid port directory.
if _IsValidPlatformFilenameList(current_path, filenames):
if current_path == root_path:
logging.warning('Found platform at search path root: %s', current_path)
name = _GetPlatformName(root_path, current_path)
yield PlatformInfo(name, current_path)
def _FindAllPlatforms():
"""Search the filesystem for all valid Starboard platforms.
Returns:
A Mapping of name->PlatformInfo.
"""
result = {}
search_path = environment.GetStarboardPortRoots()
# Ignore search path directories inside other search path directories.
exclusion_set = set(search_path)
for entry in search_path:
if not os.path.isdir(entry):
continue
for platform_info in _EnumeratePlatforms(entry, exclusion_set):
if platform_info.name in result:
logging.error('Found duplicate port name "%s" at "%s" and "%s"',
platform_info.name, result[platform_info.name],
platform_info.path)
result[platform_info.name] = platform_info
return result
# Cache of name->PlatformInfo mapping.
_INFO_MAP = None
def _GetInfoMap():
"""Gets mapping of platform names to PlatformInfo objects."""
global _INFO_MAP
if not _INFO_MAP:
_INFO_MAP = _FindAllPlatforms()
return _INFO_MAP
# Cache of the sorted list of all platform names.
_ALL = None
def GetAll():
"""Gets a sorted list of all valid Starboard platform names."""
global _ALL
if not _ALL:
_ALL = sorted(_GetInfoMap().keys())
return _ALL
def Get(platform_name):
"""Gets the PlatformInfo for the given platform name, or None."""
return _GetInfoMap().get(platform_name)
def GetAllInfos():
"""Gets a sorted sequence of PlatformInfo objects for all valid platforms."""
return (Get(p) for p in GetAll())
def IsValid(platform_name):
"""Determines whether the given platform name is valid."""
return platform_name in _GetInfoMap()
class PlatformInfo(object):
"""Information about a specific Starboard platform."""
def __init__(self, name, path):
self.name = name
self.path = path