diff --git a/build/build.py b/build/build.py index cbeb1e6e3..3f8c4ef54 100755 --- a/build/build.py +++ b/build/build.py @@ -71,7 +71,8 @@ common_closure_opts = [ shakaBuildHelpers.cygwin_safe_path(shakaBuildHelpers.get_source_base())), '--generate_exports', - +] +common_closure_defines = [ '-D', 'COMPILED=true', '-D', 'goog.STRICT_MODE_COMPATIBLE=true', '-D', 'goog.ENABLE_DEBUG_LOADER=false', @@ -80,8 +81,9 @@ common_closure_opts = [ debug_closure_opts = [ # Don't use a wrapper script in debug mode so all the internals are visible # on the global object. - '-O', 'SIMPLE', +] +debug_closure_defines = [ '-D', 'goog.DEBUG=true', '-D', 'goog.asserts.ENABLE_ASSERTS=true', '-D', 'shaka.log.MAX_LOG_LEVEL=4', # shaka.log.Level.DEBUG @@ -89,8 +91,9 @@ debug_closure_opts = [ release_closure_opts = [ ('--output_wrapper_file=%s/build/wrapper.template.js' % shakaBuildHelpers.cygwin_safe_path(shakaBuildHelpers.get_source_base())), - '-O', 'ADVANCED', +] +release_closure_defines = [ '-D', 'goog.DEBUG=false', '-D', 'goog.asserts.ENABLE_ASSERTS=false', '-D', 'shaka.log.MAX_LOG_LEVEL=0', @@ -233,12 +236,11 @@ class Build(object): return True - def build_raw(self, extra_opts, is_debug): + def build_raw(self, closure_opts): """Builds the files in |self.include| using the given extra Closure options. Args: - extra_opts: An array of extra options to give to Closure. - is_debug: True to compile for debugging, false for release. + closure_opts: An array of options to give to Closure. Returns: True on success; False on failure. @@ -249,12 +251,7 @@ class Build(object): files = [shakaBuildHelpers.cygwin_safe_path(f) for f in self.include] files.sort() - if is_debug: - closure_opts = common_closure_opts + debug_closure_opts - else: - closure_opts = common_closure_opts + release_closure_opts - - cmd_line = ['java', '-jar', jar] + closure_opts + extra_opts + files + cmd_line = ['java', '-jar', jar] + closure_opts + files if shakaBuildHelpers.execute_get_code(cmd_line) != 0: logging.error('Build failed') return False @@ -325,9 +322,17 @@ class Build(object): 'to override.') return True - opts = ['--create_source_map', result_map, '--js_output_file', result_file, - '--source_map_location_mapping', source_base + '|..'] - if not self.build_raw(opts, is_debug): + closure_opts = common_closure_opts + common_closure_defines + if is_debug: + closure_opts += debug_closure_opts + debug_closure_defines + else: + closure_opts += release_closure_opts + release_closure_defines + + closure_opts += [ + '--create_source_map', result_map, '--js_output_file', result_file, + '--source_map_location_mapping', source_base + '|..' + ] + if not self.build_raw(closure_opts): return False # Add a special source-mapping comment so that Chrome and Firefox can map diff --git a/build/check.py b/build/check.py index 830bb1385..fef2ef7b2 100755 --- a/build/check.py +++ b/build/check.py @@ -128,11 +128,63 @@ def check_tests(): get('third_party', 'closure')) test_build = build.Build(set(files)) + closure_opts = build.common_closure_opts + build.common_closure_defines + closure_opts += build.debug_closure_opts + build.debug_closure_defines + # Ignore missing goog.require since we assume the whole library is # already included. - opts = ['--jscomp_off=missingRequire', '--jscomp_off=strictMissingRequire', - '--checks-only', '-O', 'SIMPLE'] - return test_build.build_raw(opts, is_debug=True) + closure_opts += [ + '--jscomp_off=missingRequire', '--jscomp_off=strictMissingRequire', + '--checks-only', '-O', 'SIMPLE' + ] + return test_build.build_raw(closure_opts) + + +def check_externs(): + """Runs an extra compile pass over the generated externs to ensure that they + are usable. + + Returns: + True on success, False on failure. + """ + logging.info('Checking the usability of generated externs...') + + # Create a complete "build" object. + externs_build = build.Build() + if not externs_build.parse_build(['+@complete'], os.getcwd()): + return False + externs_build.add_core() + + # Use it to generate externs for the next check. + if not externs_build.generate_externs('check'): + return False + + # Create a custom "build" object, add all manually-written externs, then add + # the generated externs we just generated. + source_base = shakaBuildHelpers.get_source_base() + manual_externs = shakaBuildHelpers.get_all_files( + os.path.join(source_base, 'externs'), re.compile(r'.*\.js$')) + generated_externs = os.path.join( + source_base, 'dist', 'shaka-player.check.externs.js') + + check_build = build.Build() + check_build.include = set(manual_externs) + check_build.include.add(generated_externs) + + # Build with the complete set of externs, but without any application code. + # This will help find issues in the generated externs, independent of the app. + # Since we have no app, don't use the defines. Unused defines cause a + # compilation error. + closure_opts = build.common_closure_opts + build.debug_closure_opts + [ + '--checks-only', '-O', 'SIMPLE' + ] + ok = check_build.build_raw(closure_opts) + + # Clean up the temporary externs we just generated. + os.unlink(generated_externs) + + # Return the success/failure of the build above. + return ok def usage(): @@ -151,16 +203,17 @@ def main(args): usage() return 1 - if not check_lint(): - return 1 - elif not check_html_lint(): - return 1 - elif not check_complete(): - return 1 - elif not check_tests(): - return 1 - else: - return 0 + steps = [ + check_lint, + check_html_lint, + check_complete, + check_tests, + check_externs, + ] + for step in steps: + if not step(): + return 1 + return 0 if __name__ == '__main__':