2019-04-26 04:54:24 +03:00
#! /usr/bin/env python3
assert __name__ == ' __main__ '
'''
To update ANGLE in Gecko , use Windows with git - bash , and setup depot_tools , python2 , and
python3 . Because depot_tools expects ` python ` to be ` python2 ` ( shame ! ) , python2 must come
before python3 in your path .
Upstream : https : / / chromium . googlesource . com / angle / angle
Our repo : https : / / github . com / mozilla / angle
It has branches like ' firefox-60 ' which is the branch we use for pulling into
Gecko with this script .
This script leaves a record of the merge - base and cherry - picks that we pull into
Gecko . ( gfx / angle / cherries . log )
ANGLE < - > Chrome version mappings are here : https : / / omahaproxy . appspot . com /
An easy choice is to grab Chrome ' s Beta ' s ANGLE branch .
## Usage
Prepare your env :
~ ~ ~
export PATH = " $PATH:/path/to/depot_tools "
~ ~ ~
If this is a new repo , don ' t forget:
~ ~ ~
# In the angle repo:
. / scripts / bootstrap . py
gclient sync
~ ~ ~
Update : ( in the angle repo )
~ ~ ~
# In the angle repo:
/ path / to / gecko / gfx / angle / update - angle . py origin / chromium / XXXX
git push moz # Push the firefox-XX branch to github.com/mozilla/angle
~ ~ ~ ~
'''
import json
import os
import pathlib
import re
import shutil
import subprocess
import sys
from typing import * # mypy annotations
2021-11-26 23:21:43 +03:00
SCRIPT_DIR = os . path . dirname ( __file__ )
2019-04-26 04:54:24 +03:00
GN_ENV = dict ( os . environ )
2019-09-12 03:26:00 +03:00
# We need to set DEPOT_TOOLS_WIN_TOOLCHAIN to 0 for non-Googlers, but otherwise
# leave it unset since vs_toolchain.py assumes that the user is a Googler with
# the Visual Studio files in depot_tools if DEPOT_TOOLS_WIN_TOOLCHAIN is not
# explicitly set to 0.
vs_found = False
2021-11-26 23:21:43 +03:00
vs_dir = os . path . join ( SCRIPT_DIR , ' .. ' , ' third_party ' , ' depot_tools ' , ' win_toolchain ' , ' vs_files ' )
if not os . path . isdir ( vs_dir ) :
2019-09-12 03:26:00 +03:00
GN_ENV [ ' DEPOT_TOOLS_WIN_TOOLCHAIN ' ] = ' 0 '
2019-04-26 04:54:24 +03:00
2019-11-02 16:58:51 +03:00
if len ( sys . argv ) < 3 :
sys . exit ( ' Usage: export_targets.py OUT_DIR ROOTS... ' )
2019-04-26 04:54:24 +03:00
( OUT_DIR , * ROOTS ) = sys . argv [ 1 : ]
for x in ROOTS :
assert x . startswith ( ' //: ' )
# ------------------------------------------------------------------------------
def run_checked ( * args , * * kwargs ) :
print ( ' ' , args , file = sys . stderr )
sys . stderr . flush ( )
return subprocess . run ( args , check = True , * * kwargs )
def sortedi ( x ) :
return sorted ( x , key = str . lower )
def dag_traverse ( root_keys : Sequence [ str ] , pre_recurse_func : Callable [ [ str ] , list ] ) :
visited_keys : Set [ str ] = set ( )
def recurse ( key ) :
if key in visited_keys :
return
visited_keys . add ( key )
t = pre_recurse_func ( key )
try :
( next_keys , post_recurse_func ) = t
except ValueError :
( next_keys , ) = t
post_recurse_func = None
for x in next_keys :
recurse ( x )
if post_recurse_func :
post_recurse_func ( key )
return
for x in root_keys :
recurse ( x )
return
# ------------------------------------------------------------------------------
print ( ' Importing graph ' , file = sys . stderr )
try :
p = run_checked ( ' gn ' , ' desc ' , ' --format=json ' , str ( OUT_DIR ) , ' * ' , stdout = subprocess . PIPE ,
2019-09-12 03:26:00 +03:00
env = GN_ENV , shell = ( True if sys . platform == ' win32 ' else False ) )
2019-04-26 04:54:24 +03:00
except subprocess . CalledProcessError :
2019-11-02 16:58:51 +03:00
sys . stderr . buffer . write ( b ' " gn desc " failed. Is depot_tools in your PATH? \n ' )
2019-04-26 04:54:24 +03:00
exit ( 1 )
# -
print ( ' \n Processing graph ' , file = sys . stderr )
descs = json . loads ( p . stdout . decode ( ) )
# Ready to traverse
# ------------------------------------------------------------------------------
LIBRARY_TYPES = ( ' shared_library ' , ' static_library ' )
def flattened_target ( target_name : str , descs : dict , stop_at_lib : bool = True ) - > dict :
flattened = dict ( descs [ target_name ] )
EXPECTED_TYPES = LIBRARY_TYPES + ( ' source_set ' , ' group ' , ' action ' )
def pre ( k ) :
dep = descs [ k ]
dep_type = dep [ ' type ' ]
deps = dep [ ' deps ' ]
if stop_at_lib and dep_type in LIBRARY_TYPES :
return ( ( ) , )
if dep_type == ' copy ' :
2021-06-28 21:02:42 +03:00
assert not deps , ( target_name , dep [ ' deps ' ] )
2019-04-26 04:54:24 +03:00
else :
assert dep_type in EXPECTED_TYPES , ( k , dep_type )
for ( k , v ) in dep . items ( ) :
if type ( v ) in ( list , tuple , set ) :
2020-08-28 00:43:23 +03:00
# This is a workaround for
# https://bugs.chromium.org/p/gn/issues/detail?id=196, where
# the value of "public" can be a string instead of a list.
existing = flattened . get ( k , [ ] )
if isinstance ( existing , str ) :
existing = [ existing ]
flattened [ k ] = sortedi ( set ( existing + v ) )
2019-04-26 04:54:24 +03:00
else :
#flattened.setdefault(k, v)
pass
return ( deps , )
dag_traverse ( descs [ target_name ] [ ' deps ' ] , pre )
return flattened
# ------------------------------------------------------------------------------
# Check that includes are valid. (gn's version of this check doesn't seem to work!)
INCLUDE_REGEX = re . compile ( b ' (?:^| \\ n) *# *include +([< " ])([^> " ]+)[> " ] ' )
assert INCLUDE_REGEX . match ( b ' #include " foo " ' )
assert INCLUDE_REGEX . match ( b ' \n #include " foo " ' )
2019-09-12 03:26:00 +03:00
# Most of these are ignored because this script does not currently handle
# #includes in #ifdefs properly, so they will erroneously be marked as being
# included, but not part of the source list.
2019-04-26 04:54:24 +03:00
IGNORED_INCLUDES = {
2020-07-24 20:58:45 +03:00
b ' absl/container/flat_hash_map.h ' ,
2021-07-29 22:54:26 +03:00
b ' absl/container/flat_hash_set.h ' ,
2019-09-12 03:26:00 +03:00
b ' compiler/translator/TranslatorESSL.h ' ,
b ' compiler/translator/TranslatorGLSL.h ' ,
b ' compiler/translator/TranslatorHLSL.h ' ,
2019-10-09 19:44:01 +03:00
b ' compiler/translator/TranslatorMetal.h ' ,
2021-04-27 02:56:15 +03:00
b ' compiler/translator/TranslatorMetalDirect.h ' ,
2019-04-26 04:54:24 +03:00
b ' compiler/translator/TranslatorVulkan.h ' ,
2020-08-29 17:48:28 +03:00
b ' contrib/optimizations/slide_hash_neon.h ' ,
2020-08-31 16:10:36 +03:00
b ' dirent_on_windows.h ' ,
2020-10-21 17:59:43 +03:00
b ' dlopen_fuchsia.h ' ,
2020-08-31 16:10:36 +03:00
b ' kernel/image.h ' ,
b ' libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h ' ,
2019-09-12 03:26:00 +03:00
b ' libANGLE/renderer/d3d/DeviceD3D.h ' ,
b ' libANGLE/renderer/d3d/DisplayD3D.h ' ,
b ' libANGLE/renderer/d3d/RenderTargetD3D.h ' ,
2020-11-04 03:22:19 +03:00
b ' libANGLE/renderer/gl/apple/DisplayApple_api.h ' ,
2019-04-26 04:54:24 +03:00
b ' libANGLE/renderer/gl/cgl/DisplayCGL.h ' ,
2020-01-04 03:40:06 +03:00
b ' libANGLE/renderer/gl/eagl/DisplayEAGL.h ' ,
2019-04-26 04:54:24 +03:00
b ' libANGLE/renderer/gl/egl/android/DisplayAndroid.h ' ,
2020-03-13 20:41:57 +03:00
b ' libANGLE/renderer/gl/egl/DisplayEGL.h ' ,
2020-05-21 13:17:21 +03:00
b ' libANGLE/renderer/gl/egl/gbm/DisplayGbm.h ' ,
2020-03-13 20:41:57 +03:00
b ' libANGLE/renderer/gl/glx/DisplayGLX.h ' ,
2019-04-26 04:54:24 +03:00
b ' libANGLE/renderer/gl/wgl/DisplayWGL.h ' ,
2019-10-29 13:38:53 +03:00
b ' libANGLE/renderer/metal/DisplayMtl_api.h ' ,
2019-04-26 04:54:24 +03:00
b ' libANGLE/renderer/null/DisplayNULL.h ' ,
2021-01-27 04:06:24 +03:00
b ' libANGLE/renderer/vulkan/android/AHBFunctions.h ' ,
2019-04-26 04:54:24 +03:00
b ' libANGLE/renderer/vulkan/android/DisplayVkAndroid.h ' ,
2021-07-17 04:05:36 +03:00
b ' libANGLE/renderer/vulkan/DisplayVk_api.h ' ,
2019-04-26 04:54:24 +03:00
b ' libANGLE/renderer/vulkan/fuchsia/DisplayVkFuchsia.h ' ,
2019-11-04 23:20:18 +03:00
b ' libANGLE/renderer/vulkan/ggp/DisplayVkGGP.h ' ,
2019-10-25 19:53:40 +03:00
b ' libANGLE/renderer/vulkan/mac/DisplayVkMac.h ' ,
2019-04-26 04:54:24 +03:00
b ' libANGLE/renderer/vulkan/win32/DisplayVkWin32.h ' ,
b ' libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h ' ,
2021-12-09 18:52:35 +03:00
b ' libANGLE/renderer/vulkan/wayland/DisplayVkWayland.h ' ,
2020-08-31 16:10:36 +03:00
b ' loader_cmake_config.h ' ,
2022-01-18 17:22:36 +03:00
b ' loader_linux.h ' ,
2021-09-30 21:33:04 +03:00
b ' loader_windows.h ' ,
2021-01-06 19:35:53 +03:00
b ' optick.h ' ,
2020-11-03 23:36:11 +03:00
b ' spirv-tools/libspirv.h ' ,
2020-03-13 20:56:47 +03:00
b ' third_party/volk/volk.h ' ,
2020-08-31 16:10:36 +03:00
b ' vk_loader_extensions.c ' ,
b ' vk_snippets.h ' ,
b ' vulkan_android.h ' ,
b ' vulkan_beta.h ' ,
b ' vulkan_directfb.h ' ,
b ' vulkan_fuchsia.h ' ,
b ' vulkan_ggp.h ' ,
b ' vulkan_ios.h ' ,
b ' vulkan_macos.h ' ,
b ' vulkan_metal.h ' ,
b ' vulkan_vi.h ' ,
b ' vulkan_wayland.h ' ,
b ' vulkan_win32.h ' ,
b ' vulkan_xcb.h ' ,
b ' vulkan_xlib.h ' ,
b ' vulkan_xlib_xrandr.h ' ,
2022-08-22 22:09:40 +03:00
# rapidjson adds these include stubs into their documentation
# comments. Since the script doesn't skip comments they are
# erroneously marked as valid includes
2021-03-17 15:48:16 +03:00
b ' rapidjson/... ' ,
2021-03-24 17:42:54 +03:00
# Validation layers support building with robin hood hashing, but we are not enabling that
# See http://anglebug.com/5791
b ' robin_hood.h ' ,
2023-01-13 15:15:01 +03:00
# Validation layers optionally use mimalloc
b ' mimalloc-new-delete.h ' ,
2021-10-01 21:56:19 +03:00
# From the Vulkan-Loader
b ' winres.h ' ,
2022-07-21 19:38:47 +03:00
# From the ANGLE desktop GL frontend, since it is only enabled conditionally
b ' libGLESv2/entry_points_gl_1_autogen.h ' ,
b ' libGLESv2/entry_points_gl_2_autogen.h ' ,
b ' libGLESv2/entry_points_gl_3_autogen.h ' ,
b ' libGLESv2/entry_points_gl_4_autogen.h ' ,
b ' libGLESv2/entry_points_wgl.h ' ,
2022-08-22 22:09:40 +03:00
# From a comment in vulkan-validation-layers/src/layers/vk_mem_alloc.h
b ' my_custom_assert.h ' ,
b ' my_custom_min.h ' ,
2022-11-09 15:18:57 +03:00
# https://bugs.chromium.org/p/gn/issues/detail?id=311
b ' spirv/unified1/spirv.hpp11 ' ,
2019-04-26 04:54:24 +03:00
}
IGNORED_INCLUDE_PREFIXES = {
b ' android ' ,
b ' Carbon ' ,
b ' CoreFoundation ' ,
b ' CoreServices ' ,
b ' IOSurface ' ,
b ' mach ' ,
b ' mach-o ' ,
b ' OpenGL ' ,
b ' pci ' ,
b ' sys ' ,
b ' wrl ' ,
b ' X11 ' ,
}
2019-09-12 03:26:00 +03:00
IGNORED_DIRECTORIES = {
2020-09-16 21:39:09 +03:00
' //buildtools/third_party/libc++ ' ,
2020-07-24 20:58:45 +03:00
' //third_party/abseil-cpp ' ,
2019-09-12 03:26:00 +03:00
' //third_party/SwiftShader ' ,
}
2019-04-26 04:54:24 +03:00
def has_all_includes ( target_name : str , descs : dict ) - > bool :
2019-09-12 03:26:00 +03:00
for ignored_directory in IGNORED_DIRECTORIES :
if target_name . startswith ( ignored_directory ) :
return True
2019-04-26 04:54:24 +03:00
flat = flattened_target ( target_name , descs , stop_at_lib = False )
acceptable_sources = flat . get ( ' sources ' , [ ] ) + flat . get ( ' outputs ' , [ ] )
acceptable_sources = { x . rsplit ( ' / ' , 1 ) [ - 1 ] . encode ( ) for x in acceptable_sources }
ret = True
desc = descs [ target_name ]
for cur_file in desc . get ( ' sources ' , [ ] ) :
assert cur_file . startswith ( ' / ' ) , cur_file
if not cur_file . startswith ( ' // ' ) :
continue
cur_file = pathlib . Path ( cur_file [ 2 : ] )
text = cur_file . read_bytes ( )
for m in INCLUDE_REGEX . finditer ( text ) :
if m . group ( 1 ) == b ' < ' :
continue
include = m . group ( 2 )
if include in IGNORED_INCLUDES :
continue
try :
( prefix , _ ) = include . split ( b ' / ' , 1 )
if prefix in IGNORED_INCLUDE_PREFIXES :
continue
except ValueError :
pass
include_file = include . rsplit ( b ' / ' , 1 ) [ - 1 ]
if include_file not in acceptable_sources :
#print(' acceptable_sources:')
#for x in sorted(acceptable_sources):
# print(' ', x)
2021-12-15 02:22:57 +03:00
print ( ' Warning in {} : {} : Included file must be listed in the GN target or its public dependency: {} ' . format ( target_name , cur_file , include ) , file = sys . stderr )
2019-04-26 04:54:24 +03:00
ret = False
#print('Looks valid:', m.group())
continue
return ret
# -
# Gather real targets:
def gather_libraries ( roots : Sequence [ str ] , descs : dict ) - > Set [ str ] :
libraries = set ( )
def fn ( target_name ) :
cur = descs [ target_name ]
print ( ' ' + cur [ ' type ' ] , target_name , file = sys . stderr )
assert has_all_includes ( target_name , descs ) , target_name
if cur [ ' type ' ] in ( ' shared_library ' , ' static_library ' ) :
libraries . add ( target_name )
return ( cur [ ' deps ' ] , )
dag_traverse ( roots , fn )
return libraries
# -
libraries = gather_libraries ( ROOTS , descs )
print ( f ' \n { len ( libraries ) } libraries: ' , file = sys . stderr )
for k in libraries :
print ( f ' { k } ' , file = sys . stderr )
print ( ' \n stdout begins: ' , file = sys . stderr )
sys . stderr . flush ( )
# ------------------------------------------------------------------------------
# Output
out = { k : flattened_target ( k , descs ) for k in libraries }
for ( k , desc ) in out . items ( ) :
dep_libs : Set [ str ] = set ( )
for dep_name in set ( desc [ ' deps ' ] ) :
dep = descs [ dep_name ]
if dep [ ' type ' ] in LIBRARY_TYPES :
2021-07-17 04:05:36 +03:00
dep_libs . add ( dep_name )
desc [ ' dep_libs ' ] = sortedi ( dep_libs )
2019-04-26 04:54:24 +03:00
json . dump ( out , sys . stdout , indent = ' ' )
exit ( 0 )