From 9716ef73a0cf48194dd0b349105ca0735277b8d4 Mon Sep 17 00:00:00 2001 From: KongQun Yang Date: Fri, 23 Mar 2018 18:08:00 -0700 Subject: [PATCH] Collect and generate license notice Under flag --licenses Bug: 74447460 Change-Id: If99c4e927431ce08158e3734428e3b4d23d62c75 --- packager/app/mpd_generator.cc | 10 ++ packager/app/packager_main.cc | 7 + packager/packager.gyp | 2 + packager/tools/generate_license_notice.py | 162 ++++++++++++++++++++++ packager/tools/license_notice.gyp | 34 +++++ 5 files changed, 215 insertions(+) create mode 100755 packager/tools/generate_license_notice.py create mode 100644 packager/tools/license_notice.gyp diff --git a/packager/app/mpd_generator.cc b/packager/app/mpd_generator.cc index 52ada27356..a30b4fdb84 100644 --- a/packager/app/mpd_generator.cc +++ b/packager/app/mpd_generator.cc @@ -4,6 +4,8 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#include + #include "packager/app/mpd_generator_flags.h" #include "packager/app/vlog_flags.h" #include "packager/base/at_exit.h" @@ -12,6 +14,7 @@ #include "packager/base/strings/string_split.h" #include "packager/base/strings/stringprintf.h" #include "packager/mpd/util/mpd_writer.h" +#include "packager/tools/license_notice.h" #include "packager/version/version.h" #if defined(OS_WIN) @@ -20,6 +23,8 @@ #include #endif // defined(OS_WIN) +DEFINE_bool(licenses, false, "Dump licenses."); + namespace shaka { namespace { const char kUsage[] = @@ -100,6 +105,11 @@ int MpdMain(int argc, char** argv) { google::SetVersionString(GetPackagerVersion()); google::SetUsageMessage(base::StringPrintf(kUsage, argv[0])); google::ParseCommandLineFlags(&argc, &argv, true); + if (FLAGS_licenses) { + for (const char* line : kLicenseNotice) + std::cout << line << std::endl; + return kSuccess; + } ExitStatus status = CheckRequiredFlags(); if (status != kSuccess) { diff --git a/packager/app/packager_main.cc b/packager/app/packager_main.cc index b49749be2e..94c553158c 100644 --- a/packager/app/packager_main.cc +++ b/packager/app/packager_main.cc @@ -28,6 +28,7 @@ #include "packager/base/strings/stringprintf.h" #include "packager/file/file.h" #include "packager/packager.h" +#include "packager/tools/license_notice.h" #if defined(OS_WIN) #include @@ -36,6 +37,7 @@ #endif // defined(OS_WIN) DEFINE_bool(dump_stream_info, false, "Dump demuxed stream info."); +DEFINE_bool(licenses, false, "Dump licenses."); DEFINE_bool(use_fake_clock_for_muxer, false, "Set to true to use a fake clock for muxer. With this flag set, " @@ -436,6 +438,11 @@ int PackagerMain(int argc, char** argv) { google::SetVersionString(shaka::Packager::GetLibraryVersion()); google::SetUsageMessage(base::StringPrintf(kUsage, argv[0])); google::ParseCommandLineFlags(&argc, &argv, true); + if (FLAGS_licenses) { + for (const char* line : kLicenseNotice) + std::cout << line << std::endl; + return kSuccess; + } if (argc < 2) { google::ShowUsageWithFlags("Usage"); return kSuccess; diff --git a/packager/packager.gyp b/packager/packager.gyp index 95e5d4a312..cd08134e61 100644 --- a/packager/packager.gyp +++ b/packager/packager.gyp @@ -97,6 +97,7 @@ 'file/file.gyp:file', 'libpackager', 'third_party/gflags/gflags.gyp:gflags', + 'tools/license_notice.gyp:license_notice', ], 'conditions': [ ['profiling==1', { @@ -119,6 +120,7 @@ 'base/base.gyp:base', 'mpd/mpd.gyp:mpd_util', 'third_party/gflags/gflags.gyp:gflags', + 'tools/license_notice.gyp:license_notice', ], }, { diff --git a/packager/tools/generate_license_notice.py b/packager/tools/generate_license_notice.py new file mode 100755 index 0000000000..1a6f87ec21 --- /dev/null +++ b/packager/tools/generate_license_notice.py @@ -0,0 +1,162 @@ +#!/usr/bin/python +# +# Copyright 2018 Google Inc. All rights reserved. +# +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file or at +# https://developers.google.com/open-source/licenses/bsd +"""This script is used to generate license notice string for packager.""" + +import argparse +import os +import sys + +LICENSE_FILES = set(['LICENSE', 'LICENSE.TXT', 'COPYING']) +PRUNE_PATHS = [ + # Identical to third_party/icu. + os.path.join('base', 'third_party', 'icu'), + + # Comes with Chromium base, not used in packager. + os.path.join('base', 'third_party', 'libevent'), + os.path.join('base', 'third_party', 'nspr'), + os.path.join('base', 'third_party', 'superfasthash'), + os.path.join('base', 'third_party', 'xdg_mime'), + os.path.join('base', 'third_party', 'xdg_user_dirs'), + + # Used for development and test, not in the binary build. + os.path.join('buildtools', 'third_party', 'libc++', 'trunk', 'utils', + 'google-benchmark'), + os.path.join('testing', 'gmock'), + os.path.join('testing', 'gtest'), + os.path.join('third_party', 'binutils'), + os.path.join('third_party', 'boringssl', 'src', 'third_party', + 'googletest'), + os.path.join('third_party', 'gold'), + os.path.join('tools', 'gyp'), + + # Comes with Boringssl, not used in packager. + os.path.join('third_party', 'boringssl', 'src', 'third_party', + 'android-cmake'), + # Comes with ICU, not used in packager. + os.path.join('third_party', 'icu', 'scripts'), + # Required by Chromium base, but not used in packager. + os.path.join('third_party', 'libevent'), +] + +CC_FILE_TEMPLATE = """ +// Generated by tools/generate_license_notice.py. Do not modify. + +namespace shaka {{ + +const char* kLicenseNotice[] = {{ +{} +}}; + +}} // namespace shaka""" + +H_FILE_TEMPLATE = """ +// Generated by tools/generate_license_notice.py. Do not modify. + +#ifndef PACKAGER_TOOLS_LICENSE_NOTICE_H_ +#define PACKAGER_TOOLS_LICENSE_NOTICE_H_ + +namespace shaka {{ +extern const char* kLicenseNotice[{}]; +}} // namespace shaka + +#endif // PACKAGER_TOOLS_LICENSE_NOTICE_H_""" + + +def _FindLicenseFiles(root): + """Finds and returns all license files.""" + result = [] + for path, dirs, files in os.walk(root): + path = path[len(root) + 1:] # Change to relative path. + + if path in PRUNE_PATHS: + dirs[:] = [] + continue + + license_files = LICENSE_FILES.intersection(files) + if license_files: + result.append(os.path.join(path, license_files.pop())) + return result + + +def _GetModuleName(path): + """Find third_party module name from file path.""" + while True: + path = os.path.dirname(path) + base_name = os.path.basename(path) + if base_name not in ['src', 'source', 'trunk']: + return base_name + + +def _ReadFile(path): + """Reads a file from disk.""" + with open(path, 'rb') as f: + return f.read().splitlines() + + +def GenerateLicenseNotice(output_dir, output_license_file_name): + """Generate plain-text license notice embedded in C++ code. + + The output file contains licenses of both Shaka Packager and third-party + libraries used in Shaka Packager. + + Args: + output_dir: Output directory path. If not specified, no output is produced. + output_license_file_name: Whether to output license file names. + """ + + script_dir = os.path.dirname(os.path.realpath(__file__)) + packager_dir = os.path.abspath(os.path.join(script_dir, os.pardir)) + + license_files = _FindLicenseFiles(packager_dir) + license_files.sort() + + if output_license_file_name: + print 'Num License Files: {}\n'.format(len(license_files)) + for license_file in license_files: + print license_file + + # Include the main license file. + content = _ReadFile(os.path.join(packager_dir, os.pardir, 'LICENSE')) + for license_file in license_files: + content.append('-' * 20) + content.append(_GetModuleName(license_file)) + content.append('-' * 20) + content.extend(_ReadFile(os.path.join(packager_dir, license_file))) + + # MSVC does not like long strings (Error C2026, C1091), so we have to break + # them into multiple strings. + content_array_text = '\n'.join(map(' R"shaka({})shaka",'.format, content)) + + if output_dir: + cc_file_path = os.path.join(output_dir, 'license_notice.cc') + with open(cc_file_path, 'w') as output: + output.write(CC_FILE_TEMPLATE.format(content_array_text)) + + h_file_path = os.path.join(output_dir, 'license_notice.h') + with open(h_file_path, 'w') as output: + output.write(H_FILE_TEMPLATE.format(len(content))) + + +def main(): + parser = argparse.ArgumentParser() + + parser.add_argument( + '--output-license-file-name', + dest='output_license_file_name', + action='store_true') + parser.set_defaults(output_license_file_name=False) + + parser.add_argument('output_dir', nargs='?') + args = parser.parse_args() + + GenerateLicenseNotice(args.output_dir, args.output_license_file_name) + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/packager/tools/license_notice.gyp b/packager/tools/license_notice.gyp new file mode 100644 index 0000000000..ee37e214ce --- /dev/null +++ b/packager/tools/license_notice.gyp @@ -0,0 +1,34 @@ +# Copyright 2018 Google Inc. All rights reserved. +# +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file or at +# https://developers.google.com/open-source/licenses/bsd + +{ + 'targets': [ + { + 'target_name': 'license_notice', + 'type': 'static_library', + 'variables': { + 'generated_dir': '<(SHARED_INTERMEDIATE_DIR)/packager/tools', + }, + 'actions': [ + { + 'action_name': 'generate_license_notice', + 'inputs': [ + 'generate_license_notice.py', + ], + 'outputs': [ + '<(generated_dir)/license_notice.cc', + '<(generated_dir)/license_notice.h', + ], + 'action': [ + 'python', 'generate_license_notice.py', '<(generated_dir)', + ], + 'process_outputs_as_sources': 1, + 'message': 'Generating embeddable license', + }, + ], + }, + ], +}