diff options
-rw-r--r-- | build/common.gypi | 17 | ||||
-rw-r--r-- | chrome/chrome_exe.gypi | 15 | ||||
-rw-r--r-- | chrome/chrome_installer.gypi | 15 | ||||
-rw-r--r-- | chrome/installer/mini_installer.gyp | 10 | ||||
-rw-r--r-- | chrome/installer/setup/install_worker.cc | 20 | ||||
-rwxr-xr-x | chrome/tools/build/win/create_installer_archive.py | 121 |
6 files changed, 196 insertions, 2 deletions
diff --git a/build/common.gypi b/build/common.gypi index 3f3d972..27aa341 100644 --- a/build/common.gypi +++ b/build/common.gypi @@ -2832,6 +2832,23 @@ '_HAS_EXCEPTIONS=0', ], }], + # To support installing a component build (where the DLLs are not in + # same directory as chrome.exe and setup.exe): + # create_installer_archive.py writes custom manifests for all the + # DLLs. The setting below prevents VS from automatically generating + # the usual manifests for those DLLs which would override the custom + # external manifests. + ['component=="shared_library"', { + 'target_conditions': [ + ['_type=="shared_library"', { + 'msvs_settings': { + 'VCLinkerTool': { + 'GenerateManifest': 'false', + }, + }, + }], + ], + }], ['MSVS_VERSION=="2008"', { 'defines': [ '_HAS_TR1=0', diff --git a/chrome/chrome_exe.gypi b/chrome/chrome_exe.gypi index e638b2d..0673300 100644 --- a/chrome/chrome_exe.gypi +++ b/chrome/chrome_exe.gypi @@ -44,6 +44,21 @@ 'INFOPLIST_FILE': 'app/app-Info.plist', }, 'conditions': [ + ['component == "shared_library"', { + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)', + 'files': [ + 'app/chrome.exe.manifest', + ], + }, + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'GenerateManifest': 'false', + }, + }, + }], ['order_text_section!=""', { 'target_conditions' : [ ['_toolset=="target"', { diff --git a/chrome/chrome_installer.gypi b/chrome/chrome_installer.gypi index 852239a..6309abc 100644 --- a/chrome/chrome_installer.gypi +++ b/chrome/chrome_installer.gypi @@ -324,6 +324,21 @@ }, ], 'conditions': [ + ['component == "shared_library"', { + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)', + 'files': [ + 'installer/setup/setup.exe.manifest', + ], + }, + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'GenerateManifest': 'false', + }, + }, + }], # TODO(mark): <(branding_dir) should be defined by the # global condition block at the bottom of the file, but # this doesn't work due to the following issue: diff --git a/chrome/installer/mini_installer.gyp b/chrome/installer/mini_installer.gyp index 70a607e..e0980db 100644 --- a/chrome/installer/mini_installer.gyp +++ b/chrome/installer/mini_installer.gyp @@ -213,6 +213,15 @@ 'enable_metro_flag': '', }, }], + ['component == "shared_library"', { + 'variables': { + 'component_build_flag': '--component_build=1', + }, + }, { + 'variables': { + 'component_build_flag': '', + }, + }], ], 'inputs': [ '<(create_installer_archive_py_path)', @@ -241,6 +250,7 @@ '--resource_file_path', '<(INTERMEDIATE_DIR)/packed_files.rc', '<(enable_hidpi_flag)', '<(enable_metro_flag)', + '<(component_build_flag)', # TODO(sgk): may just use environment variables #'--distribution=$(CHROMIUM_BUILD)', '--distribution=_google_chrome', diff --git a/chrome/installer/setup/install_worker.cc b/chrome/installer/setup/install_worker.cc index 74d9a8f..f7067c5 100644 --- a/chrome/installer/setup/install_worker.cc +++ b/chrome/installer/setup/install_worker.cc @@ -794,6 +794,26 @@ void AddInstallWorkItems(const InstallationState& original_state, temp_path); } + // For the component build to work with the installer, we need to drop a + // config file and a manifest by chrome.exe. These files are only found in + // the archive if this is a component build. +#if defined(COMPONENT_BUILD) + static const FilePath::CharType kChromeExeConfig[] = + FILE_PATH_LITERAL("chrome.exe.config"); + static const FilePath::CharType kChromeExeManifest[] = + FILE_PATH_LITERAL("chrome.exe.manifest"); + install_list->AddMoveTreeWorkItem( + src_path.Append(kChromeExeConfig).value(), + target_path.Append(kChromeExeConfig).value(), + temp_path.value(), + WorkItem::ALWAYS_MOVE); + install_list->AddMoveTreeWorkItem( + src_path.Append(kChromeExeManifest).value(), + target_path.Append(kChromeExeManifest).value(), + temp_path.value(), + WorkItem::ALWAYS_MOVE); +#endif // defined(COMPONENT_BUILD) + // In the past, we copied rather than moved for system level installs so that // the permissions of %ProgramFiles% would be picked up. Now that |temp_path| // is in %ProgramFiles% for system level installs (and in %LOCALAPPDATA% diff --git a/chrome/tools/build/win/create_installer_archive.py b/chrome/tools/build/win/create_installer_archive.py index 78bc63b9..8675f17 100755 --- a/chrome/tools/build/win/create_installer_archive.py +++ b/chrome/tools/build/win/create_installer_archive.py @@ -312,6 +312,115 @@ def CreateResourceInputFile( f.write(resource_file) +# Copies component build DLLs and generates required config files and manifests +# in order for chrome.exe and setup.exe to be able to find those DLLs at +# run-time. +# This is meant for developer builds only and should never be used to package +# an official build. +def DoComponentBuildTasks(staging_dir, build_dir, current_version): + # Get the required directories for the upcoming operations. + chrome_dir = os.path.join(staging_dir, CHROME_DIR) + version_dir = os.path.join(chrome_dir, current_version) + installer_dir = os.path.join(version_dir, 'Installer') + # |installer_dir| is technically only created post-install, but we need it + # now to add setup.exe's config and manifest to the archive. + if not os.path.exists(installer_dir): + os.mkdir(installer_dir) + + # Copy all the DLLs in |build_dir| to the version directory. + dlls = glob.glob(os.path.join(build_dir, '*.dll')) + for dll in dlls: + shutil.copy(dll, version_dir) + + exe_config = ( + "<configuration>\n" + " <windows>\n" + " <assemblyBinding xmlns='urn:schemas-microsoft-com:asm.v1'>\n" + " <probing privatePath='{rel_path}'/>\n" + " </assemblyBinding>\n" + " </windows>\n" + "</configuration>") + + # Write chrome.exe.config to point to the version directory. + chrome_exe_config_file = open( + os.path.join(chrome_dir, 'chrome.exe.config'), 'w') + chrome_exe_config_file.write(exe_config.format(rel_path=current_version)) + chrome_exe_config_file.close() + + # Write setup.exe.config to point to the version directory (which is one + # level up from setup.exe post-install). + setup_exe_config_file = open( + os.path.join(installer_dir, 'setup.exe.config'), 'w') + setup_exe_config_file.write(exe_config.format(rel_path='..')) + setup_exe_config_file.close() + + # Build a list containing the name of each DLL found in |build_dir|. + dll_names = [] + for dll in dlls: + dll_names.append(os.path.splitext(os.path.basename(dll))[0]) + + # Build the manifests for chrome.exe and setup.exe in which we list all the + # DLLs as side by side assembly dependencies. + # TODO (gab): These extra properties should be merged with the existing + # chrome/app/chrome.exe.manifest and + # chrome/installer/setup/setup.exe.manifest. + exe_manifest_parts = [ + "<assembly\n" + " xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>\n" + " <trustInfo xmlns='urn:schemas-microsoft-com:asm.v3'>\n" + " <security>\n" + " <requestedPrivileges>\n" + " <requestedExecutionLevel level='asInvoker' uiAccess='false'/>\n" + " </requestedPrivileges>\n" + " </security>\n" + " </trustInfo>\n"] + + for name in dll_names: + exe_manifest_parts.append( + " <dependency>\n" + " <dependentAssembly>\n" + " <assemblyIdentity type='win32' name='chrome.{dll_basename}'\n" + " version='0.0.0.0' processorArchitecture='x86'\n" + " language='*'/>\n" + " </dependentAssembly>\n" + " </dependency>\n".format(dll_basename=name)) + + exe_manifest_parts.append("</assembly>") + exe_manifest = ''.join(exe_manifest_parts) + + # Write chrome.exe.manifest beside chrome.exe. + chrome_exe_manifest_file = open( + os.path.join(chrome_dir, 'chrome.exe.manifest'), 'w') + chrome_exe_manifest_file.write(exe_manifest) + chrome_exe_manifest_file.close() + + # Write setup.exe.manifest beside setup.exe in |version_dir|/Installer. + setup_exe_manifest_file = open( + os.path.join(installer_dir, 'setup.exe.manifest'), 'w') + setup_exe_manifest_file.write(exe_manifest) + setup_exe_manifest_file.close() + + # Write chrome.{dllname}.manifest in the version directory for each DLLs + # listed as a dependency in the previous step. + # TODO (gab): The properties should probably be merged with the existing + # chrome/app/chrome.dll.manifest which could be duplicated for every extra + # DLL in the component build. + for name in dll_names: + dll_manifest = ( + "<assembly\n" + " xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>\n" + " <assemblyIdentity name='chrome.{dll_basename}' version='0.0.0.0'\n" + " type='win32' processorArchitecture='x86'/>\n" + " <file name='{dll_basename}.dll'/>\n" + "</assembly>".format(dll_basename=name)) + + dll_manifest_file = open(os.path.join( + version_dir, + "chrome.{dll_basename}.manifest".format(dll_basename=name)), 'w') + dll_manifest_file.write(dll_manifest) + dll_manifest_file.close() + + def main(options): """Main method that reads input file, creates archive file and write resource input file. @@ -338,6 +447,9 @@ def main(options): staging_dir, options.build_dir, options.enable_hidpi, options.enable_metro) + if options.component_build == '1': + DoComponentBuildTasks(staging_dir, options.build_dir, current_version) + version_numbers = current_version.split('.') current_build_number = version_numbers[2] + '.' + version_numbers[3] prev_build_number = '' @@ -393,6 +505,8 @@ def _ParseOptions(): parser.add_option('--enable_metro', default='0', help='Whether to include resource files from the "METRO" section of the ' 'input file.') + parser.add_option('--component_build', default='0', + help='Whether this archive is packaging a component build.') options, args = parser.parse_args() if not options.build_dir: @@ -401,12 +515,15 @@ def _ParseOptions(): if not options.staging_dir: parser.error('You must provide a staging dir.') + if not options.input_file: + parser.error('You must provide an input file') + if not options.output_dir: options.output_dir = options.build_dir if not options.resource_file_path: - options.options.resource_file_path = os.path.join(options.build_dir, - MINI_INSTALLER_INPUT_FILE) + options.resource_file_path = os.path.join(options.build_dir, + MINI_INSTALLER_INPUT_FILE) return options |