def RunTestsOnNaCl(targets, build_args): """Run a test suite for the NaCl version.""" # Currently we can only run the limited test set which is defined as # nacl_test_targets in nacl_extension.gyp. if targets: PrintErrorAndExit('Targets [%s] are not supported.' % ', '.join(targets)) nacl_gyp = os.path.join(SRC_DIR, 'chrome', 'nacl', 'nacl_extension.gyp') (build_options, build_targets) = ParseBuildOptions( build_args + [nacl_gyp + ':run_nacl_test']) # Run the test suite in NaCl. BuildMain(build_options, build_targets)
def BuildMain(options, targets): """The main function for the 'build' command.""" if not targets: PrintErrorAndExit('No build target is specified.') # Add the mozc root directory to PYTHONPATH. original_python_path = os.environ.get('PYTHONPATH', '') depot_path = MOZC_ROOT python_path = os.pathsep.join([original_python_path, depot_path]) os.environ['PYTHONPATH'] = python_path if IsWindows(): BuildOnWindows(targets) else: BuildWithNinja(options, targets) # Revert python path. os.environ['PYTHONPATH'] = original_python_path
def GypMain(options, unused_args): """The main function for the 'gyp' command.""" # Generate a version definition file. logging.info('Generating version definition file...') template_path = '%s/%s' % (SRC_DIR, options.version_file) version_path = '%s/mozc_version.txt' % SRC_DIR if options.noqt: qt_version = '' else: qt_version = '5' GenerateVersionFile(template_path, version_path, options.target_platform, qt_version) version = GetMozcVersion() target_platform = version.GetTargetPlatform() logging.info('Version string is %s', version.GetVersionString()) # Back up the original 'PYTHONPATH' environment variable in case we change # it in this function. original_python_path = os.environ.get('PYTHONPATH', '') # 'gypdir' option allows distributors/packages to specify the location of # the system-installed version of gyp to conform their packaging policy. if options.gypdir: # When distributors/packages choose to use system-installed gyp, it is # their responsibility to make sure if 'gyp' command works well on # their environment. gyp_dir = os.path.abspath(options.gypdir) gyp_command = [os.path.join(gyp_dir, 'gyp')] else: # Use third_party/gyp/gyp unless 'gypdir' option is specified. This is # the default and official way to build Mozc. In this case, you need to # consider the case where a Python package named 'gyp' has already been # installed in the target machine. So we update PYTHONPATH so that # third_party/gyp/gyp_main.py can find its own library modules (they are # installed under 'third_party/gyp/pylib') rather than system-installed # GYP modules. gyp_dir = os.path.abspath(os.path.join(MOZC_ROOT, 'third_party', 'gyp')) gyp_main_file = os.path.join(gyp_dir, 'gyp_main.py') # Make sure |gyp_main_file| exists. if not os.path.exists(gyp_main_file): message = ( 'GYP does not exist at %s. Please run "git submodule update --init" ' 'to check out GYP. If you want to use system-installed GYP, use ' '--gypdir option to specify its location. e.g. ' '"python build_mozc.py gyp --gypdir=/usr/bin"' % gyp_main_file) PrintErrorAndExit(message) gyp_python_path = options.gyp_python_path or sys.executable gyp_command = [gyp_python_path, gyp_main_file] os.environ['PYTHONPATH'] = os.pathsep.join( [os.path.join(gyp_dir, 'pylib'), original_python_path]) # Following script tests if 'import gyp' is now available and its # location is expected one. By using this script, make sure # 'import gyp' actually loads 'third_party/gyp/pylib/gyp'. gyp_check_script = os.path.join( ABS_SCRIPT_DIR, 'build_tools', 'ensure_gyp_module_path.py') expected_gyp_module_path = os.path.join(gyp_dir, 'pylib', 'gyp') RunOrDie([gyp_python_path, gyp_check_script, '--expected=%s' % expected_gyp_module_path]) # Set the generator name. os.environ['GYP_GENERATORS'] = 'ninja' # Get and show the list of .gyp file names. gyp_file_names = GetGypFileNames(options) logging.debug('GYP files:') for file_name in gyp_file_names: logging.debug('- %s', file_name) # Build GYP command line. logging.info('Building GYP command line...') gyp_options = ['--depth=.'] if target_platform == 'Windows': gyp_options.extend(['--include=%s/gyp/common_win.gypi' % SRC_DIR]) else: gyp_options.extend(['--include=%s/gyp/common.gypi' % SRC_DIR]) gyp_options.extend(['-D', 'abs_depth=%s' % MOZC_ROOT]) gyp_options.extend(['-D', 'ext_third_party_dir=%s' % EXT_THIRD_PARTY_DIR]) if IsWindows(): gyp_options.extend(['-D', 'python="%s"' % sys.executable]) else: gyp_options.extend(['-D', 'python=%s' % sys.executable]) gyp_options.extend(gyp_file_names) gyp_options.extend(['-D', 'version=' + version.GetVersionString()]) gyp_options.extend(['-D', 'short_version=' + version.GetShortVersionString()]) if options.branding: gyp_options.extend(['-D', 'branding=%s' % options.branding]) # Qt configurations if options.noqt: gyp_options.extend(['-D', 'use_qt=NO']) gyp_options.extend(['-D', 'qt_dir=']) elif target_platform == 'Linux': gyp_options.extend(['-D', 'use_qt=YES']) gyp_options.extend(['-D', 'qt_dir=']) # Check if Qt libraries are installed. if not PkgExists('Qt5Core', 'Qt5Gui', 'Qt5Widgets'): PrintErrorAndExit('Qt is required to build GUI Tool. ' 'Specify --noqt to skip building GUI Tool.') else: gyp_options.extend(['-D', 'use_qt=YES']) if options.qtdir: gyp_options.extend(['-D', 'qt_dir=%s' % os.path.abspath(options.qtdir)]) else: gyp_options.extend(['-D', 'qt_dir=']) if target_platform == 'Windows' and options.wix_dir: gyp_options.extend(['-D', 'use_wix=YES']) gyp_options.extend(['-D', 'wix_dir=%s' % options.wix_dir]) else: gyp_options.extend(['-D', 'use_wix=NO']) gyp_options.extend(['-D', 'build_base=%s' % GetBuildBaseName(target_platform)]) gyp_options.extend(['-D', 'build_short_base=%s' % GetBuildShortBaseName(target_platform)]) if options.warn_as_error: gyp_options.extend(['-D', 'warn_as_error=1']) else: gyp_options.extend(['-D', 'warn_as_error=0']) if version.IsDevChannel(): gyp_options.extend(['-D', 'channel_dev=1']) target_platform_value = target_platform gyp_options.extend(['-D', 'target_platform=%s' % target_platform_value]) if IsWindows(): gyp_options.extend(['-G', 'msvs_version=2017']) if (target_platform == 'Linux' and '%s/unix/ibus/ibus.gyp' % SRC_DIR in gyp_file_names): gyp_options.extend(['-D', 'use_libibus=1']) if options.server_dir: gyp_options.extend([ '-D', 'server_dir=%s' % os.path.abspath(options.server_dir)]) gyp_options.extend(['--generator-output=.']) short_basename = GetBuildShortBaseName(target_platform) gyp_options.extend(['-G', 'output_dir=%s' % short_basename]) # Enable cross-compile # TODO(yukawa): Enable GYP_CROSSCOMPILE for Windows. if not IsWindows(): os.environ['GYP_CROSSCOMPILE'] = '1' # Run GYP. logging.info('Running GYP...') RunOrDie(gyp_command + gyp_options) # Restore PYTHONPATH just in case. if not original_python_path: os.environ['PYTHONPATH'] = original_python_path # Done! logging.info('Done') # For internal Ninja build on Windows, set up environment files if IsWindows(): out_dir = os.path.join(MOZC_ROOT, 'out_win') AddPythonPathToEnvironmentFilesForWindows(out_dir) # When Windows build is configured to use DLL version of Qt, copy Qt's DLLs # and debug symbols into Mozc's build directory. This is important because: # - We can easily back up all the artifacts if relevant product binaries and # debug symbols are placed at the same place. # - Some post-build tools such as bind.exe can easily look up the dependent # DLLs (QtCore4.dll and QtQui4.dll in this case). # Perhaps the following code can also be implemented in gyp, but we atopt # this ad hock workaround as a first step. # TODO(yukawa): Implement the following logic in gyp, if magically possible. abs_qtdir = os.path.abspath(options.qtdir) abs_qt_bin_dir = os.path.join(abs_qtdir, 'bin') abs_qt_lib_dir = os.path.join(abs_qtdir, 'lib') abs_out_win_dir = GetBuildBaseName(target_platform) copy_script = os.path.join( ABS_SCRIPT_DIR, 'build_tools', 'copy_dll_and_symbol.py') copy_params = [] if qt_version == '5': copy_params.append({ 'basenames': 'Qt5Cored;Qt5Guid;Qt5Widgetsd', 'dll_paths': abs_qt_bin_dir, 'pdb_paths': abs_qt_lib_dir, 'target_dir': os.path.join(abs_out_win_dir, 'DebugDynamic')}) copy_params.append({ 'basenames': 'Qt5Core;Qt5Gui;Qt5Widgets', 'dll_paths': abs_qt_bin_dir, 'pdb_paths': abs_qt_lib_dir, 'target_dir': os.path.join(abs_out_win_dir, 'ReleaseDynamic')}) copy_params.append({ 'basenames': 'qwindowsd', 'dll_paths': os.path.join(abs_qtdir, 'plugins', 'platforms'), 'pdb_paths': os.path.join(abs_qtdir, 'plugins', 'platforms'), 'target_dir': os.path.join(abs_out_win_dir, 'DebugDynamic', 'platforms')}) copy_params.append({ 'basenames': 'qwindows', 'dll_paths': os.path.join(abs_qtdir, 'plugins', 'platforms'), 'pdb_paths': os.path.join(abs_qtdir, 'plugins', 'platforms'), 'target_dir': os.path.join(abs_out_win_dir, 'ReleaseDynamic', 'platforms')}) for copy_param in copy_params: copy_commands = [ copy_script, '--basenames', copy_param['basenames'], '--dll_paths', copy_param['dll_paths'], '--pdb_paths', copy_param['pdb_paths'], '--target_dir', copy_param['target_dir'], ] RunOrDie(copy_commands)
def GetNinjaTargetName(target): """Extracts the build target name for Ninja.""" if ':' not in target: PrintErrorAndExit('Invalid target: %s' % target) (_, target_name) = target.split(':') return target_name
def GypMain(options, unused_args): """The main function for the 'gyp' command.""" # Generate a version definition file. logging.info('Generating version definition file...') template_path = '%s/%s' % (SRC_DIR, options.version_file) version_path = '%s/mozc_version.txt' % SRC_DIR if options.noqt or options.target_platform in ['Android', 'NaCl']: qt_version = '' else: qt_version = '5' GenerateVersionFile(template_path, version_path, options.target_platform, options.android_application_id, options.android_arch, qt_version) version = GetMozcVersion() target_platform = version.GetTargetPlatform() logging.info('Version string is %s', version.GetVersionString()) # Back up the original 'PYTHONPATH' environment variable in case we change # it in this function. original_python_path = os.environ.get('PYTHONPATH', '') # 'gypdir' option allows distributors/packages to specify the location of # the system-installed version of gyp to conform their packaging policy. if options.gypdir: # When distributors/packages choose to use system-installed gyp, it is # their responsibility to make sure if 'gyp' command works well on # their environment. gyp_dir = os.path.abspath(options.gypdir) gyp_command = [os.path.join(gyp_dir, 'gyp')] else: # Use third_party/gyp/gyp unless 'gypdir' option is specified. This is # the default and official way to build Mozc. In this case, you need to # consider the case where a Python package named 'gyp' has already been # installed in the target machine. So we update PYTHONPATH so that # third_party/gyp/gyp_main.py can find its own library modules (they are # installed under 'third_party/gyp/pylib') rather than system-installed # GYP modules. gyp_dir = os.path.abspath(os.path.join(MOZC_ROOT, 'third_party', 'gyp')) gyp_main_file = os.path.join(gyp_dir, 'gyp_main.py') # Make sure |gyp_main_file| exists. if not os.path.exists(gyp_main_file): message = ( 'GYP does not exist at %s. Please run "git submodule update --init" ' 'to check out GYP. If you want to use system-installed GYP, use ' '--gypdir option to specify its location. e.g. ' '"python build_mozc.py gyp --gypdir=/usr/bin"' % gyp_main_file) PrintErrorAndExit(message) gyp_command = [sys.executable, gyp_main_file] os.environ['PYTHONPATH'] = os.pathsep.join( [os.path.join(gyp_dir, 'pylib'), original_python_path]) # Following script tests if 'import gyp' is now available and its # location is expected one. By using this script, make sure # 'import gyp' actually loads 'third_party/gyp/pylib/gyp'. gyp_check_script = os.path.join( ABS_SCRIPT_DIR, 'build_tools', 'ensure_gyp_module_path.py') expected_gyp_module_path = os.path.join(gyp_dir, 'pylib', 'gyp') RunOrDie([sys.executable, gyp_check_script, '--expected=%s' % expected_gyp_module_path]) # Set the generator name. os.environ['GYP_GENERATORS'] = 'ninja' # Get and show the list of .gyp file names. gyp_file_names = GetGypFileNames(options) logging.debug('GYP files:') for file_name in gyp_file_names: logging.debug('- %s', file_name) # Build GYP command line. logging.info('Building GYP command line...') gyp_options = ['--depth=.'] if target_platform == 'Windows': gyp_options.extend(['--include=%s/gyp/common_win.gypi' % SRC_DIR]) else: gyp_options.extend(['--include=%s/gyp/common.gypi' % SRC_DIR]) gyp_options.extend(['-D', 'abs_depth=%s' % MOZC_ROOT]) gyp_options.extend(['-D', 'ext_third_party_dir=%s' % EXT_THIRD_PARTY_DIR]) gyp_options.extend(['-D', 'python_executable=%s' % sys.executable]) gyp_options.extend(gyp_file_names) if options.branding: gyp_options.extend(['-D', 'branding=%s' % options.branding]) # Qt configurations if options.noqt or target_platform in ['Android', 'NaCl']: gyp_options.extend(['-D', 'use_qt=NO']) gyp_options.extend(['-D', 'qt_dir=']) elif target_platform == 'Linux': gyp_options.extend(['-D', 'use_qt=YES']) gyp_options.extend(['-D', 'qt_dir=']) # Check if Qt libraries are installed. if not PkgExists('Qt5Core', 'Qt5Gui', 'Qt5Widgets'): PrintErrorAndExit('Qt is required to build GUI Tool. ' 'Specify --noqt to skip building GUI Tool.') else: gyp_options.extend(['-D', 'use_qt=YES']) if options.qtdir: gyp_options.extend(['-D', 'qt_dir=%s' % os.path.abspath(options.qtdir)]) else: gyp_options.extend(['-D', 'qt_dir=']) if target_platform == 'Windows' and options.wix_dir: gyp_options.extend(['-D', 'use_wix=YES']) gyp_options.extend(['-D', 'wix_dir=%s' % options.wix_dir]) else: gyp_options.extend(['-D', 'use_wix=NO']) if target_platform == 'Linux': gyp_options.extend(['-D', 'enable_gtk_renderer=1']) # Android if target_platform == 'Android': android_home = GetAndroidHome(options) android_ndk_home = GetAndroidNdkHome(options) if not android_home or not os.path.isdir(android_home): raise ValueError( 'Android Home was not found. ' 'Use --android_home option or make the home direcotry ' 'be included in PATH environment variable.') if not android_ndk_home or not os.path.isdir(android_ndk_home): raise ValueError( 'Android NDK Home was not found. ' 'Use --android_ndk_home option or make the home direcotry ' 'be included in PATH environment variable.') gyp_options.extend(['-D', 'android_home=%s' % android_home]) gyp_options.extend(['-D', 'android_arch=%s' % options.android_arch]) gyp_options.extend(['-D', 'android_ndk_home=%s' % android_ndk_home]) gyp_options.extend(['-D', 'android_application_id=%s' % options.android_application_id]) if options.android_hide_icon: gyp_options.extend(['-D', 'android_hide_icon=1']) else: gyp_options.extend(['-D', 'android_hide_icon=0']) if options.android_release_icon: gyp_options.extend(['-D', 'android_release_icon=1']) else: gyp_options.extend(['-D', 'android_release_icon=0']) gyp_options.extend(['-D', 'build_base=%s' % GetBuildBaseName(target_platform)]) gyp_options.extend(['-D', 'build_short_base=%s' % GetBuildShortBaseName(target_platform)]) if options.warn_as_error: gyp_options.extend(['-D', 'warn_as_error=1']) else: gyp_options.extend(['-D', 'warn_as_error=0']) if version.IsDevChannel(): gyp_options.extend(['-D', 'channel_dev=1']) def SetCommandLineForFeature(option_name, windows=False, mac=False, linux=False, android=False, nacl=False): """Updates an option like '--enable_foober' and add a -D argument for gyp. This function ensures an option like '--enable_foober' exists and it has a default boolean for each platform based on givem parameters. This function also sets a '-D' command line option for gyp as '-D enable_foober=0' or '-D enable_foober=1' depending on the actual value of the target option. Args: option_name: A base name of the option. If 'foobar' is given, '--enable_foober' option will be checked. windows: A boolean which replesents the default value of the target option on Windows platform. mac: A boolean which replesents the default value of the target option on MacOS X platform. linux: A boolean which replesents the default value of the target option on Linux platform. android: A boolean which replesents the default value of the target option on Android platform. nacl: A boolean which replesents the default value of the target option on NaCl. Raises: ValueError: An error occurred when 'option_name' is empty. """ if not option_name: raise ValueError('"option_name" should be specified') default_enabled = {'Windows': windows, 'Mac': mac, 'Linux': linux, 'Android': android, 'NaCl': nacl}.get(target_platform, False) enable_option_name = 'enable_%s' % option_name enabled = options.ensure_value(enable_option_name, default_enabled) gyp_options.extend(['-D', '%s=%s' % (enable_option_name, 1 if enabled else 0)]) is_official = (options.branding == 'GoogleJapaneseInput') is_official_dev = (is_official and version.IsDevChannel()) SetCommandLineForFeature(option_name='cloud_handwriting', linux=is_official_dev, windows=is_official_dev, mac=is_official_dev) target_platform_value = target_platform gyp_options.extend(['-D', 'target_platform=%s' % target_platform_value]) if IsWindows(): gyp_options.extend(['-G', 'msvs_version=2015']) if (target_platform == 'Linux' and '%s/unix/ibus/ibus.gyp' % SRC_DIR in gyp_file_names): gyp_options.extend(['-D', 'use_libibus=1']) if target_platform == 'NaCl': if options.nacl_sdk_root: nacl_sdk_root = os.path.abspath(options.nacl_sdk_root) else: nacl_sdk_root = os.path.abspath(os.path.join(EXT_THIRD_PARTY_DIR, 'nacl_sdk', 'pepper_40')) if not os.path.isdir(nacl_sdk_root): PrintErrorAndExit('The nacl_sdk_root directory (%s) does not exist.' % options.nacl_sdk_root) gyp_options.extend(['-D', 'nacl_sdk_root=%s' % nacl_sdk_root]) if options.server_dir: gyp_options.extend([ '-D', 'server_dir=%s' % os.path.abspath(options.server_dir)]) gyp_options.extend(['--generator-output=.']) short_basename = GetBuildShortBaseName(target_platform) gyp_options.extend(['-G', 'output_dir=%s' % short_basename]) # Enable cross-compile # TODO(yukawa): Enable GYP_CROSSCOMPILE for Windows. if not IsWindows(): os.environ['GYP_CROSSCOMPILE'] = '1' # Run GYP. logging.info('Running GYP...') RunOrDie(gyp_command + gyp_options) # Restore PYTHONPATH just in case. if not original_python_path: os.environ['PYTHONPATH'] = original_python_path # Done! logging.info('Done') # For internal Ninja build on Windows, set up environment files if IsWindows(): out_dir = os.path.join(MOZC_ROOT, 'out_win') AddPythonPathToEnvironmentFilesForWindows(out_dir) # When Windows build is configured to use DLL version of Qt, copy Qt's DLLs # and debug symbols into Mozc's build directory. This is important because: # - We can easily back up all the artifacts if relevant product binaries and # debug symbols are placed at the same place. # - Some post-build tools such as bind.exe can easily look up the dependent # DLLs (QtCore4.dll and QtQui4.dll in this case). # Perhaps the following code can also be implemented in gyp, but we atopt # this ad hock workaround as a first step. # TODO(yukawa): Implement the following logic in gyp, if magically possible. abs_qtdir = os.path.abspath(options.qtdir) abs_qt_bin_dir = os.path.join(abs_qtdir, 'bin') abs_qt_lib_dir = os.path.join(abs_qtdir, 'lib') abs_out_win_dir = GetBuildBaseName(target_platform) copy_script = os.path.join( ABS_SCRIPT_DIR, 'build_tools', 'copy_dll_and_symbol.py') copy_params = [] if qt_version == '5': copy_params.append({ 'basenames': 'Qt5Cored;Qt5Guid;Qt5Widgetsd', 'dll_paths': abs_qt_bin_dir, 'pdb_paths': abs_qt_lib_dir, 'target_dir': os.path.join(abs_out_win_dir, 'DebugDynamic')}) copy_params.append({ 'basenames': 'Qt5Core;Qt5Gui;Qt5Widgets', 'dll_paths': abs_qt_bin_dir, 'pdb_paths': abs_qt_lib_dir, 'target_dir': os.path.join(abs_out_win_dir, 'ReleaseDynamic')}) copy_params.append({ 'basenames': 'qwindowsd', 'dll_paths': os.path.join(abs_qtdir, 'plugins', 'platforms'), 'pdb_paths': os.path.join(abs_qtdir, 'plugins', 'platforms'), 'target_dir': os.path.join(abs_out_win_dir, 'DebugDynamic', 'platforms')}) copy_params.append({ 'basenames': 'qwindows', 'dll_paths': os.path.join(abs_qtdir, 'plugins', 'platforms'), 'pdb_paths': os.path.join(abs_qtdir, 'plugins', 'platforms'), 'target_dir': os.path.join(abs_out_win_dir, 'ReleaseDynamic', 'platforms')}) for copy_param in copy_params: copy_commands = [ copy_script, '--basenames', copy_param['basenames'], '--dll_paths', copy_param['dll_paths'], '--pdb_paths', copy_param['pdb_paths'], '--target_dir', copy_param['target_dir'], ] RunOrDie(copy_commands)