From 9e7eab53c17441436199214bc2450eed4657d528 Mon Sep 17 00:00:00 2001 From: Jaekyun Seok Date: Wed, 19 Apr 2017 15:26:47 +0900 Subject: [PATCH] Split vendor license notices into vendor partition Xml files will be generated instead of html files, and then Settings will generate html file on runtime from xml files of partitions. Test: build succeeded and tested on sailfish Bug: 37099941 Merged-In: Id7899381a537b1947cbb6164ed2b4a98492334af Change-Id: Id7899381a537b1947cbb6164ed2b4a98492334af (cherry picked from commit 3b7560bf881e6cd4579b984d3a1ebd9669513319) --- core/Makefile | 84 +++++++++++++++----- core/main.mk | 4 +- tools/generate-notice-files.py | 141 +++++++++++++++++++++++++-------- 3 files changed, 175 insertions(+), 54 deletions(-) diff --git a/core/Makefile b/core/Makefile index 5d449548e..b4a2fde5b 100644 --- a/core/Makefile +++ b/core/Makefile @@ -653,13 +653,14 @@ endif .PHONY: notice_files -# Create the rule to combine the files into text and html forms -# $(1) - Plain text output file -# $(2) - HTML output file -# $(3) - File title -# $(4) - Directory to use. Notice files are all $(4)/src. Other +# Create the rule to combine the files into text and html/xml forms +# $(1) - xml_excluded_vendor|xml_vendor|html +# $(2) - Plain text output file +# $(3) - HTML/XML output file +# $(4) - File title +# $(5) - Directory to use. Notice files are all $(4)/src. Other # directories in there will be used for scratch -# $(5) - Dependencies for the output files +# $(6) - Dependencies for the output files # # The algorithm here is that we go collect a hash for each of the notice # files and write the names of the files that match that hash. Then @@ -673,12 +674,16 @@ endif # original notice files instead of making rules to copy them somwehere. # Then we could traverse that without quite as much bash drama. define combine-notice-files -$(1) $(2): PRIVATE_MESSAGE := $(3) -$(1) $(2): PRIVATE_DIR := $(4) -$(1) : $(2) -$(2) : $(5) $(BUILD_SYSTEM)/Makefile build/tools/generate-notice-files.py - build/tools/generate-notice-files.py $(1) $(2) $$(PRIVATE_MESSAGE) $$(PRIVATE_DIR)/src -notice_files: $(1) $(2) +$(2) $(3): PRIVATE_MESSAGE := $(4) +$(2) $(3): PRIVATE_DIR := $(5) +$(2) : $(3) +$(3) : $(6) $(BUILD_SYSTEM)/Makefile build/tools/generate-notice-files.py + build/tools/generate-notice-files.py --text-output $(2) \ + $(if $(filter $(1),xml_excluded_vendor),-e vendor --xml-output, \ + $(if $(filter $(1),xml_vendor),-i vendor --xml-output, \ + --html-output)) $(3) \ + -t $$(PRIVATE_MESSAGE) -s $$(PRIVATE_DIR)/src +notice_files: $(2) $(3) endef # TODO These intermediate NOTICE.txt/NOTICE.html files should go into @@ -686,24 +691,51 @@ endef # the src subdirectory. target_notice_file_txt := $(TARGET_OUT_INTERMEDIATES)/NOTICE.txt -target_notice_file_html := $(TARGET_OUT_INTERMEDIATES)/NOTICE.html -target_notice_file_html_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE.html.gz +target_notice_file_html_or_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE.html +target_notice_file_html_or_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE.html.gz +installed_notice_html_or_xml_gz := $(TARGET_OUT)/etc/NOTICE.html.gz tools_notice_file_txt := $(HOST_OUT_INTERMEDIATES)/NOTICE.txt tools_notice_file_html := $(HOST_OUT_INTERMEDIATES)/NOTICE.html +ifeq ($(PRODUCT_FULL_TREBLE),true) +target_notice_file_html_or_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE.xml +target_notice_file_html_or_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE.xml.gz +installed_notice_html_or_xml_gz := $(TARGET_OUT)/etc/NOTICE.xml.gz + +target_vendor_notice_file_txt := $(TARGET_OUT_INTERMEDIATES)/NOTICE_VENDOR.txt +target_vendor_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE_VENDOR.xml +target_vendor_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE_VENDOR.xml.gz +installed_vendor_notice_xml_gz := $(TARGET_OUT_VENDOR)/etc/NOTICE.xml.gz +endif + ifndef TARGET_BUILD_APPS kernel_notice_file := $(TARGET_OUT_NOTICE_FILES)/src/kernel.txt winpthreads_notice_file := $(TARGET_OUT_NOTICE_FILES)/src/winpthreads.txt pdk_fusion_notice_files := $(filter $(TARGET_OUT_NOTICE_FILES)/%, $(ALL_PDK_FUSION_FILES)) -$(eval $(call combine-notice-files, \ +ifdef target_vendor_notice_file_xml_gz +$(eval $(call combine-notice-files, xml_excluded_vendor, \ $(target_notice_file_txt), \ - $(target_notice_file_html), \ + $(target_notice_file_html_or_xml), \ "Notices for files contained in the filesystem images in this directory:", \ $(TARGET_OUT_NOTICE_FILES), \ $(ALL_DEFAULT_INSTALLED_MODULES) $(kernel_notice_file) $(pdk_fusion_notice_files))) +$(eval $(call combine-notice-files, xml_vendor, \ + $(target_vendor_notice_file_txt), \ + $(target_vendor_notice_file_xml), \ + "Notices for files contained in the vendor filesystem image in this directory:", \ + $(TARGET_OUT_NOTICE_FILES), \ + $(target_notice_file_html_or_xml))) +else +$(eval $(call combine-notice-files, html, \ + $(target_notice_file_txt), \ + $(target_notice_file_html_or_xml), \ + "Notices for files contained in the filesystem images in this directory:", \ + $(TARGET_OUT_NOTICE_FILES), \ + $(ALL_DEFAULT_INSTALLED_MODULES) $(kernel_notice_file) $(pdk_fusion_notice_files))) +endif -$(eval $(call combine-notice-files, \ +$(eval $(call combine-notice-files, html, \ $(tools_notice_file_txt), \ $(tools_notice_file_html), \ "Notices for files contained in the tools directory:", \ @@ -716,15 +748,25 @@ $(eval $(call combine-notice-files, \ # the module processing has already been done -- in fact, we used the # fact that all that has been done to get the list of modules that we # need notice files for. -$(target_notice_file_html_gz): $(target_notice_file_html) | $(MINIGZIP) +$(target_notice_file_html_or_xml_gz): $(target_notice_file_html_or_xml) | $(MINIGZIP) $(hide) $(MINIGZIP) -9 < $< > $@ -installed_notice_html_gz := $(TARGET_OUT)/etc/NOTICE.html.gz -$(installed_notice_html_gz): $(target_notice_file_html_gz) +$(installed_notice_html_or_xml_gz): $(target_notice_file_html_or_xml_gz) $(copy-file-to-target) +ifdef target_vendor_notice_file_xml_gz +# Install the vendor html file at /vendor/etc/NOTICE.xml.gz. +$(target_vendor_notice_file_xml_gz): $(target_vendor_notice_file_xml) | $(MINIGZIP) + $(hide) $(MINIGZIP) -9 < $< > $@ +$(installed_vendor_notice_xml_gz): $(target_vendor_notice_file_xml_gz) + $(copy-file-to-target) +endif + # if we've been run my mm, mmm, etc, don't reinstall this every time ifeq ($(ONE_SHOT_MAKEFILE),) -ALL_DEFAULT_INSTALLED_MODULES += $(installed_notice_html_gz) + ALL_DEFAULT_INSTALLED_MODULES += $(installed_notice_html_or_xml_gz) + ifdef target_vendor_notice_file_xml_gz + ALL_DEFAULT_INSTALLED_MODULES += $(installed_vendor_notice_xml_gz) + endif endif endif # TARGET_BUILD_APPS diff --git a/core/main.mk b/core/main.mk index 4e9a90131..eb75e5f0c 100644 --- a/core/main.mk +++ b/core/main.mk @@ -1171,9 +1171,9 @@ apps_only: $(unbundled_build_modules) droid_targets: apps_only # Combine the NOTICE files for a apps_only build -$(eval $(call combine-notice-files, \ +$(eval $(call combine-notice-files, html, \ $(target_notice_file_txt), \ - $(target_notice_file_html), \ + $(target_notice_file_html_or_xml), \ "Notices for files for apps:", \ $(TARGET_OUT_NOTICE_FILES), \ $(apps_only_installed_files))) diff --git a/tools/generate-notice-files.py b/tools/generate-notice-files.py index 5b13bf53d..adbf7c231 100755 --- a/tools/generate-notice-files.py +++ b/tools/generate-notice-files.py @@ -14,14 +14,17 @@ # See the License for the specific language governing permissions and # limitations under the License. """ -Usage: generate-notice-files [plain text output file] [html output file] [file title] [directory of notices] +Usage: generate-notice-files --text-output [plain text output file] \ + --html-output [html output file] \ + --xml-output [xml output file] \ + -t [file title] -s [directory of notices] Generate the Android notice files, including both text and html files. -h to display this usage message and exit. """ from collections import defaultdict -import getopt +import argparse import hashlib import itertools import os @@ -38,26 +41,6 @@ HTML_ESCAPE_TABLE = { "<": "<", } -try: - opts, args = getopt.getopt(sys.argv[1:], "h") -except getopt.GetoptError, err: - print str(err) - print __doc__ - sys.exit(2) - -for o, a in opts: - if o == "-h": - print __doc__ - sys.exit(2) - else: - print >> sys.stderr, "unhandled option %s" % (o,) - -if len(args) != 4: - print """need exactly four arguments, the two output files, the file title - and the directory containing notices, not %d""" % (len(args),) - print __doc__ - sys.exit(1) - def hexify(s): return ("%02x"*len(s)) % tuple(map(ord, s)) @@ -163,27 +146,123 @@ def combine_notice_files_text(file_hash, input_dir, output_filename, file_title) print >> output_file, open(value[0]).read() output_file.close() -def main(args): - txt_output_file = args[0] - html_output_file = args[1] - file_title = args[2] +def combine_notice_files_xml(files_with_same_hash, input_dir, output_filename): + """Combine notice files in FILE_HASH and output a XML version to OUTPUT_FILENAME.""" + + SRC_DIR_STRIP_RE = re.compile(input_dir + "(/.*).txt") + + # Set up a filename to row id table (anchors inside tables don't work in + # most browsers, but href's to table row ids do) + id_table = {} + for file_key in files_with_same_hash.keys(): + for filename in files_with_same_hash[file_key]: + id_table[filename] = file_key + + # Open the output file, and output the header pieces + output_file = open(output_filename, "wb") + + print >> output_file, '' + print >> output_file, "" + + # Flatten the list of lists into a single list of filenames + sorted_filenames = sorted(id_table.keys()) + + # Print out a nice table of contents + for filename in sorted_filenames: + stripped_filename = SRC_DIR_STRIP_RE.sub(r"\1", filename) + print >> output_file, '%s' % (id_table.get(filename), stripped_filename) + + print >> output_file + print >> output_file + + processed_file_keys = [] + # Output the individual notice file lists + for filename in sorted_filenames: + file_key = id_table.get(filename) + if file_key in processed_file_keys: + continue + processed_file_keys.append(file_key) + + print >> output_file, '' % (file_key, html_escape(open(filename).read())) + print >> output_file + + # Finish off the file output + print >> output_file, "" + output_file.close() + +def get_args(): + parser = argparse.ArgumentParser() + parser.add_argument( + '--text-output', required=True, + help='The text output file path.') + parser.add_argument( + '--html-output', + help='The html output file path.') + parser.add_argument( + '--xml-output', + help='The xml output file path.') + parser.add_argument( + '-t', '--title', required=True, + help='The file title.') + parser.add_argument( + '-s', '--source-dir', required=True, + help='The directory containing notices.') + parser.add_argument( + '-i', '--included-subdirs', action='append', + help='The sub directories which should be included.') + parser.add_argument( + '-e', '--excluded-subdirs', action='append', + help='The sub directories which should be excluded.') + return parser.parse_args() + +def main(argv): + args = get_args() + + txt_output_file = args.text_output + html_output_file = args.html_output + xml_output_file = args.xml_output + file_title = args.title + included_subdirs = [] + excluded_subdirs = [] + if args.included_subdirs is not None: + included_subdirs = args.included_subdirs + if args.excluded_subdirs is not None: + excluded_subdirs = args.excluded_subdirs # Find all the notice files and md5 them - input_dir = os.path.normpath(args[3]) + input_dir = os.path.normpath(args.source_dir) files_with_same_hash = defaultdict(list) for root, dir, files in os.walk(input_dir): for file in files: - if file.endswith(".txt"): + matched = True + if len(included_subdirs) > 0: + matched = False + for subdir in included_subdirs: + if root.startswith(input_dir + '/' + subdir): + matched = True + break + elif len(excluded_subdirs) > 0: + for subdir in excluded_subdirs: + if root.startswith(input_dir + '/' + subdir): + matched = False + break + if matched and file.endswith(".txt"): filename = os.path.join(root, file) file_md5sum = md5sum(filename) files_with_same_hash[file_md5sum].append(filename) filesets = [sorted(files_with_same_hash[md5]) for md5 in sorted(files_with_same_hash.keys())] - print "Combining NOTICE files into HTML" - combine_notice_files_html(filesets, input_dir, html_output_file) print "Combining NOTICE files into text" combine_notice_files_text(filesets, input_dir, txt_output_file, file_title) + if html_output_file is not None: + print "Combining NOTICE files into HTML" + combine_notice_files_html(filesets, input_dir, html_output_file) + + if xml_output_file is not None: + print "Combining NOTICE files into XML" + combine_notice_files_xml(files_with_same_hash, input_dir, xml_output_file) + if __name__ == "__main__": - main(args) + main(sys.argv)