def _create_compiler_info(self, toolset_str, target_arch): if self._sys_info.is_cray(): return self._create_cray_compiler_info(target_arch) compiler_info = CMakeCompilerInfo() if toolset_str and (toolset_str.endswith('.cmake')): # toolchain file specified -> no need to add any furter compiler details compiler_info.cmake_toolchain_file = toolset_str return compiler_info # native compiler selected or assumed, figure out details to create the build tree folder. compiler_info.target_arch = target_arch re_msvc_version = re.compile(r'msvc-(\d+\.\d+)$') re_match = re_msvc_version.match(toolset_str) if re_match: compiler_info.compiler_family = 'msvc' compiler_info.version_major_minor = ver.version_tuple_from_str(re_match.group(1)) return compiler_info else: assert not toolset_str.startswith('msvc') bb_toolset_info = bldtools.Toolset(self._sys_info, toolset_str) compiler_info.compiler_family = bb_toolset_info.get_toolset() compiler_info.version_major_minor = bb_toolset_info.get_version()[:2] # re_toolset_versioned = re.compile('([a-z]+)-(\d+\.\d+)$') if self._sys_info.get_platform() == 'linux': if toolset_str != 'gcc': compiler_info.cmake_cxx_compiler = bb_toolset_info.get_compiler_command() cxx_basename = os.path.basename(compiler_info.cmake_cxx_compiler) # print("cxx_basename: ", cxx_basename) if compiler_info.compiler_family == 'gcc': gcc_basename = cxx_basename.replace('g++', 'gcc') compiler_info.cmake_c_compiler = os.path.join(os.path.dirname(compiler_info.cmake_cxx_compiler), gcc_basename) elif compiler_info.compiler_family == 'clang': clang_basename = cxx_basename.replace('++', '') compiler_info.cmake_c_compiler = os.path.join(os.path.dirname(compiler_info.cmake_cxx_compiler), clang_basename) elif compiler_info.compiler_family == 'intel': compiler_info.cmake_c_compiler = os.path.join(os.path.dirname(compiler_info.cmake_cxx_compiler), 'icc') elif self._sys_info.get_platform() == 'macosx': # assert compiler_info.compiler_family == 'clang' if compiler_info.compiler_family == 'clang': pass elif compiler_info.compiler_family == 'intel': compiler_info.cmake_cxx_compiler = bb_toolset_info.get_compiler_command() compiler_info.cmake_c_compiler = os.path.join(os.path.dirname(compiler_info.cmake_cxx_compiler), 'icc') else: assert False elif self._sys_info.get_platform() == 'windows': if compiler_info.compiler_family == 'msvc': pass elif compiler_info.compiler_family == 'gcc': # MinGW as native compiler: 64 bit and 32 bit default targets are possible. compiler_info.mingw = bb_toolset_info.is_mingw() compiler_info.target_arch = bb_toolset_info.get_platform_info(0).get_target_arch(0) elif compiler_info.compiler_family == 'intel': compiler_info.target_arch = bb_toolset_info.get_platform_info(0).get_target_arch(0) else: assert False return compiler_info
def __call__(self): dflt_download_dir = os.path.join(self._sys_info.get_home_dir(), 'Downloads', 'CodeMeter') parser = argparse.ArgumentParser() parser.add_argument( "--download-dir", action="store", dest="download_dir", metavar="dir", default=dflt_download_dir, help= "the download directory containing CodeMeter packages [default: $HOME/Downloads/CodeMeter]" ) parser.add_argument( "--dry-run", action="store_true", dest="dry_run", default=False, help= "copy the downloaded CodeMeter files into import area but don't issue the final svn import [default: off]" ) parser.add_argument( "--cm-version", action="store", dest="cm_version", help= "overrides the CodeMeter version which is picked up from the ubuntu package file by default." ) parser.add_argument( "codemeter_version_folder", action="store", help="codemeter version folder to import into subversion.") args = parser.parse_args() if args.cm_version: # convert into a version tuple args.cm_version = ver.version_tuple_from_str(args.cm_version) cm_download_dir = os.path.abspath( os.path.join(args.download_dir, args.codemeter_version_folder)) if not os.path.exists(cm_download_dir): print("cmsvn_import.py: error: the download directory '" + cm_download_dir + "' does not exist.") sys.exit(1) print("download dir:", cm_download_dir) svn_import_dir = os.path.join(os.getcwd(), 'svn_import') svn_importer = CmSvnImporter(cm_download_dir, svn_import_dir, args.dry_run, args.cm_version) svn_importer.cm_import( "https://bslinux3.hhi.fraunhofer.de/svn/svn_CodeMeterSoftware/branches/import" )
def test_version_tuple_from_str(self): self.assertEqual((0, 1, 2, 3), ver.version_tuple_from_str('0.1.2-3beta-2')) self.assertEqual(tuple([10]), ver.version_tuple_from_str('10')) self.assertEqual(tuple([10]), ver.version_tuple_from_str('10rc2')) self.assertEqual(tuple([10]), ver.version_tuple_from_str('10-rc2')) self.assertEqual((10, 7, 4), ver.version_tuple_from_str('10.7.4')) self.assertEqual((10, 7, 4), ver.version_tuple_from_str('10.7-4')) self.assertEqual((10, 7, 4, 0), ver.version_tuple_from_str('10.7-4', 4)) self.assertEqual((10, 7, 8, 9), ver.version_tuple_from_str('10.7.8.9-4, 4', 4)) # self.assertEqual(('1.2', '3'), ver.version_str_to_rpm_version_tuple('1.2-3')) self.assertEqual(('1.2', '3'), ver.version_str_to_rpm_version_tuple('1.2.3'))
def _parse_cmake_version_retv(self, retv): version_response = retv.rstrip() lines = version_response.splitlines() # Possible version information: # cmake version 3.7.2 # cmake version 3.8.0-rc2 # cmake3 version 3.6.3 # redhat 7.x cmake3 re_version_match = re.match( r'cmake\d*\s+version\s+([0-9]+\.[0-9]+\.[0-9]+)', lines[0], re.IGNORECASE) if not re_version_match: raise Exception( "cmake has returned an unsupported version string. Please contact technical support." ) self._logger.debug("cmake version: %s", re_version_match.group(1)) return ver.version_tuple_from_str(re_version_match.group(1))
def _get_current_cmakebuild_version(self, top_dir): assert os.path.exists(top_dir) cmakebuild_top_dir = os.path.join(top_dir, 'CMakeBuild') if not os.path.exists(cmakebuild_top_dir): return None re_version_dir = re.compile(r'^\d+[0-9.]+-\d+$') version_list = [] for fname in os.listdir(cmakebuild_top_dir): if os.path.isdir(os.path.join(cmakebuild_top_dir, fname)): if re_version_dir.match(fname) and os.path.exists(os.path.join(cmakebuild_top_dir, fname, 'CMakeBuild', 'bin', 'cmake.py')): version_list.append(ver.version_tuple_from_str(fname)) if not version_list: return None if len(version_list) > 1: raise InvalidInputParameterError("Workspace {} contains multiple CMakeBuild versions, please update manually.".format(top_dir)) self._logger.debug("found CMakeBuild {} in {}".format(ver.version_tuple_to_str(version_list[0]), top_dir)) return version_list[0]
def _query_platforms(self, ndk_root): platforms_dir = os.path.join(ndk_root, 'platforms') assert os.path.exists(platforms_dir) re_platform = re.compile('android-(\d+)$') # enumerate installed platforms in ascending order. version_list = [ ver.version_tuple_from_str(re_platform.match(d).group(1)) for d in os.listdir(platforms_dir) if re_platform.match(d) ] if version_list: version_list = ver.version_list_sort(version_list) ndk_platforms = [ 'android-' + ver.version_tuple_to_str(version) for version in version_list ] return ndk_platforms else: assert False
def _query_ndk_version(self, ndk_root): version_file = os.path.join(ndk_root, 'source.properties') if not os.path.exists(version_file): raise Exception("Android NDK version file " + version_file + " is missing, please contact technical support.") # Pkg.Revision = 11.2.2725575 re_ndk_version = re.compile(r'Pkg\.Revision\s*=\s*([0-9.]+)', re.IGNORECASE) with open(version_file) as vf: for line in vf: re_match = re_ndk_version.match(line) if re_match: ndk_version = ver.version_tuple_from_str(re_match.group(1)) return ndk_version raise Exception( "Android NDK " + ndk_root + ": version information is missing. Please contact technical support." )
def _create_cray_compiler_info(self, target): compiler_info = CMakeCompilerInfo() compiler_info.target_arch = target version_str = None if 'CRAY_PRGENVGNU' in os.environ: compiler_info.compiler_family = 'gcc' version_str = os.environ['GCC_VERSION'] elif 'CRAY_PRGENVCRAY' in os.environ: compiler_info.compiler_family = 'cray' version_str = os.environ['CRAY_CC_VERSION'] elif 'CRAY_PRGENVINTEL' in os.environ: compiler_info.compiler_family = 'intel' version_str = os.environ['INTEL_VERSION'] else: assert False version = ver.version_tuple_from_str(version_str) assert len(version) >= 2 compiler_info.version_major_minor = version[:2] return compiler_info
def _inventory(self, cm_download_dir): if not os.path.exists(cm_download_dir): raise Exception("The CodeMeter download directory '" + cm_download_dir + " does not exist.") pkg_file_list = [] category_dict = { 'rt': 'CodeMeterRuntime', 'dev': 'CodeMeterDev', 'axrt': 'AxProtectorRuntime', 'axdev': 'AxProtectorDev' } re_version_fname = re.compile(r'codemeter6?4?_([0-9.]+)_amd64.deb') re_admin_guide = re.compile(r'CodeMeter_AdminManual') for fname in os.listdir(cm_download_dir): if os.path.isdir(os.path.join(cm_download_dir, fname)): if self._re_axprotector.match(fname): ax_download_dir = os.path.join(cm_download_dir, fname) for fname2 in os.listdir(ax_download_dir): # print("processing axprotector file " + fname2) category = self._get_file_category(fname2) if category == 'ignore': continue if os.path.isfile(os.path.join(ax_download_dir, fname2)): if category == 'doc': file_info = CmPackageFileInfo( os.path.join(ax_download_dir, fname2), os.path.join(category_dict['axdev'], 'doc')) pkg_file_list.append(file_info) else: # print("processing axprotector file " + fname2) # analyze the axprotector filename (platform, arch) = self._get_target_platform(fname2) if platform: file_info = CmPackageFileInfo( os.path.join(ax_download_dir, fname2), os.path.join(category_dict[category], platform, arch)) pkg_file_list.append(file_info) else: print( "CmSvnImporter: warning: ignoring file " + os.path.join(ax_download_dir, fname2)) else: category = self._get_file_category(fname) if category == 'ignore': continue if os.path.isfile(os.path.join(cm_download_dir, fname)): if category == 'doc': if re_admin_guide.match(fname): file_info = CmPackageFileInfo( os.path.join(cm_download_dir, fname), os.path.join(category_dict['rt'], 'doc')) else: file_info = CmPackageFileInfo( os.path.join(cm_download_dir, fname), os.path.join(category_dict['dev'], 'doc')) pkg_file_list.append(file_info) else: # analyze the codemeter filename (platform, arch) = self._get_target_platform(fname) if platform: re_match = re_version_fname.match(fname) if re_match: self._cm_version = ver.version_tuple_from_str( re_match.group(1)) # print("CmSvnImporter: inventory: " + fname + " -> " + platform + "/" + arch) # analyze the file type if platform == 'all': pass assert False else: # binary file if arch == 'any': file_info = CmPackageFileInfo( os.path.join(cm_download_dir, fname), os.path.join(category_dict[category], platform)) else: file_info = CmPackageFileInfo( os.path.join(cm_download_dir, fname), os.path.join(category_dict[category], platform, arch)) # print("file_info: " + file_info.cm_file + " -> " + file_info.dst_dir) pkg_file_list.append(file_info) else: print("CmSvnImporter: warning: ignoring file " + os.path.join(cm_download_dir, fname)) return pkg_file_list
def cmakebuild_update(self, params): initial_work_dir = os.getcwd() # (Re)create GitHelper in case the log level has been changed. self._git_helper = vcsutil.GitHelper() params = self._check_params(params) if params.top_dir is None: params.top_dir = util.get_top_dir() self._summary_lines = [] if params.update_prepare: print("{}: preparing CMakeBuild update ...".format(self._prog_name)) cmakebuild_version_current = self._get_current_cmakebuild_version(params.top_dir) if cmakebuild_version_current is None: print("{}: no existing CMakeBuild version found.".format(params.top_dir)) if not self._is_workspace_clean(params.top_dir): return if params.cmakebuild_tag is None: cmakebuild_tag = self._git_helper.get_latest_cmakebuild_tag(params.cmakebuild_repo) if cmakebuild_version_current and (ver.version_compare(cmakebuild_version_current, ver.version_tuple_from_str(cmakebuild_tag)) == 0): print("{}: CMakeBuild is up to date, nothing to be done.".format(params.top_dir)) return else: # Validate CMakeBuild tag cmakebuild_tags = self._git_helper.get_remote_tags(params.cmakebuild_repo) if params.cmakebuild_tag not in cmakebuild_tags: raise InvalidInputParameterError("requested tag {0} does not exists in {1}.".format(params.cmakebuild_tag, params.cmakebuild_repo)) cmakebuild_tag = params.cmakebuild_tag if cmakebuild_version_current and (ver.version_compare(ver.version_tuple_from_str(cmakebuild_tag), cmakebuild_version_current) <= 0): print("{}: CMakeBuild is up to date, nothing to be done.".format(params.top_dir)) return install_dir = os.path.join(params.top_dir, 'build', 'cmakebuild_update') self._install_self(install_dir) update_script = os.path.join(install_dir, self._prog_name) # Prepare execv argument vector to call self with different arguments using the current python executable. if self._sys_info.is_windows(): child_args = [self._sys_info.get_short_path(self._sys_info.get_python_executable())] else: child_args = [self._sys_info.get_python_executable()] child_args.extend([update_script, '--update']) if cmakebuild_tag: child_args.extend(['-t', cmakebuild_tag]) if params.cmakebuild_repo: child_args.extend(['--cmakebuild-repo', params.cmakebuild_repo]) # Add currrent log option to child_args[] to propagate the current log option to the child process. log_level = self._logger.getEffectiveLevel() log_level_str = None if log_level == logging.DEBUG: log_level_str = 'debug' elif log_level == logging.INFO: log_level_str = 'info' elif log_level == logging.WARNING: log_level_str = 'warning' elif log_level == logging.ERROR: log_level_str = 'error' elif log_level == logging.CRITICAL: log_level_str = 'critical' if log_level_str is not None: child_args.append('--log={}'.format(log_level_str)) child_args.append(params.top_dir) os.chdir(params.top_dir) if self._sys_info.is_windows(): # Unfortunately, there are issues with os.execv() on Windows and therefore a subprocess call is used instead. util.subproc_check_call_flushed(child_args) else: # execv() is preferred as the child is likely to remove python files just being executed # by the current python process. os.execv(child_args[0], child_args) else: try: print("{}: updating CMakeBuild in {} to {}".format(self._prog_name, params.top_dir, params.cmakebuild_tag)) os.chdir(params.top_dir) if not self._is_workspace_clean(): return self._append_item_to_summary("Git workspace:", params.top_dir) if self._list_summary: cmakebuild_version_current = self._get_current_cmakebuild_version(params.top_dir) if cmakebuild_version_current is not None: self._append_item_to_summary("Current CMakeBuild version:", "{}-{:d}".format(ver.version_tuple_to_str(cmakebuild_version_current[:3]), cmakebuild_version_current[-1])) self._append_item_to_summary("New CMakeBuild version:", params.cmakebuild_tag) # Inventory of CMakeBuild to remember existing directories to be removed later on. (git_cmakebuild_dirs, cmakebuild_dirs) = self._get_git_cmakebuild_dirs(params.top_dir) if params.cmakebuild_tag in git_cmakebuild_dirs: git_cmakebuild_dirs.remove(params.cmakebuild_tag) if params.cmakebuild_tag in cmakebuild_dirs: cmakebuild_dirs.remove(params.cmakebuild_tag) # print("found existing Git CMakeBuild subdirs:", git_cmakebuild_dirs) # print("found existing CMakeBuild subdirs:", cmakebuild_dirs) # Add new CMakeBuild subtree self._add_cmakebuild_to_git_repo(params.cmakebuild_tag, params.cmakebuild_repo) # Update .svnimportprops in case is does exist. svnimportprops_file = os.path.join(params.top_dir, '.svnimportprops') svnimportprops_modified = self._update_svnimportprops(svnimportprops_file, params.cmakebuild_tag) for dname in git_cmakebuild_dirs: git_argv = [self._git_executable, 'rm', '-r', os.path.join('CMakeBuild', dname)] util.subproc_check_call_flushed(git_argv) if svnimportprops_modified or git_cmakebuild_dirs: # Need a git commit if '.svnimportprops' has been updated or git rm -r has been launched. git_comment = [] if git_cmakebuild_dirs: git_comment.append("rm -r CMakeBuild/{}".format(','.join(git_cmakebuild_dirs))) if svnimportprops_modified: git_comment.append("modifying {}".format('.svnimportprops')) git_argv = [self._git_executable, 'commit', '-am', '{}: {}'.format(self._prog_name, ', '.join(git_comment))] util.subproc_check_call_flushed(git_argv) # Check again to get rid of any python cache files cmakebuild_dirs.extend(git_cmakebuild_dirs) for dname in cmakebuild_dirs: dname_path = os.path.join(params.top_dir, 'CMakeBuild', dname) if os.path.exists(dname_path): util.rmtree(dname_path) print("{}: finished updating CMakeBuild in {} to {}".format(self._prog_name, params.top_dir, params.cmakebuild_tag)) if self._list_summary: print("\n{0:^80}".format("Summary")) print("{0:^80}".format("=======")) for line in self._summary_lines: print(line) finally: pass os.chdir(initial_work_dir)
def test_version_compare(self): self.assertEqual( 0, ver.version_compare(ver.version_tuple_from_str('10.7.4'), ver.version_tuple_from_str('10.7.4'))) self.assertEqual( 1, ver.version_compare(ver.version_tuple_from_str('10.7.4'), ver.version_tuple_from_str('10.6.4'))) self.assertEqual( -1, ver.version_compare(ver.version_tuple_from_str('10.6.4'), ver.version_tuple_from_str('10.7.4'))) self.assertEqual( -1, ver.version_compare(ver.version_tuple_from_str('10.7'), ver.version_tuple_from_str('10.7.4'))) self.assertEqual( 1, ver.version_compare(ver.version_tuple_from_str('10.7.4'), ver.version_tuple_from_str('10.7'))) self.assertEqual( 0, ver.version_compare(ver.version_tuple_from_str('10.7.0'), ver.version_tuple_from_str('10.7')))
def _query_linux_distro_info(self): if 'CRAYOS_VERSION' in os.environ: self._os_distro = 'cray' self._os_version = ver.version_tuple_from_str( os.environ['CRAYOS_VERSION']) else: lsb_release = '/usr/bin/lsb_release' if os.path.exists(lsb_release): # use lsb_release if available and assume all options are supported and return # sensible values. # obtain a human readable description of the distribution. This should be a single word as it # may be used to generate package filenames. retv = subprocess.check_output([lsb_release, '-is'], universal_newlines=True) self._os_distro = retv.rstrip().lower() retv = subprocess.check_output([lsb_release, '-rs'], universal_newlines=True) version_str = retv.rstrip() # version_str = "4" # version_str = "4.0-rolling" # version_str = "rolling" re_match = re.match(r'([0-9.,_-]+\d+)|(\d+)', version_str) if re_match: self._os_version = ver.version_tuple_from_str( re_match.group(0)) retv = subprocess.check_output([lsb_release, '-cs'], universal_newlines=True) self._os_codename = retv.rstrip().lower() if self._os_codename == 'n/a': self._os_codename = 'none' else: # lsb_release not found -> try to guess the distro but don't try to parse the # proprietary files to figure out the remaining system info bits. if os.path.exists('/etc/fedora-release'): self._os_distro = 'fedora' elif os.path.exists('/etc/redhat-release'): self._os_distro = 'redhat' elif os.path.exists('/etc/SuSE-release'): self._os_distro = 'suse' elif os.path.exists('/etc/debian_version'): self._os_distro = 'debian' else: self._os_distro = 'unknown' # make sure os_distro and os_codename do not contain any spaces as they may become part of a # package filename. if self._os_distro is not None: self._os_distro = self._os_distro.replace(' ', '-') if self._os_codename is not None: self._os_codename = self._os_codename.replace(' ', '-') # determine the general flavor of the linux system: redhat, debian or suse if os.path.exists('/etc/redhat-release'): self._redhat_system = True elif os.path.exists('/etc/debian_version'): self._debian_system = True else: # not sure how to do this for suse, revert back to regex if re.match(r'(suse)|(opensuse)', self._os_distro): self._suse_system = True
def __init__(self): self._logger = logging.getLogger(__name__) # print("Constructing a new SystemInfo object") # check python version: it has to be 2.7 or higher self._python_version = ver.get_python_version(True) # create all attributes with default values which will be overwritten in platform specific sections later on self._python_launcher = None self._python_arch = 'x86_64' self._python_implementation = platform.python_implementation() self._os_distro = platform.platform() # self._os_distro_short = platform.platform() self._win32api_installed = False self._redhat_system = False self._debian_system = False self._suse_system = False self._pkg_fmt = None self._pkg_arch = None self._os_codename = 'unknown' self._os_arch = 'x86_64' self._os_version = (0, 0, 0) self._num_processors = 1 platform_system = platform.system().lower() self._platform_system = platform_system self._desktop_dir = None self._default_proj_home_dir = None if platform_system == 'linux': # e.g. x86_64 or i686 platform_machine = platform.machine().lower() if platform_machine != 'x86_64': assert re.match(r'i[6543]86', platform_machine, re.IGNORECASE) platform_machine = 'x86' self._os_arch = platform_machine self._python_arch = platform_machine # there's no portable way in python to obtain the linux version. self._query_linux_distro_info() # there's no portable way in python to obtain the number of installed processors. self._query_linux_num_cpus() if self.is_debian(): self._pkg_fmt = 'deb' self._pkg_arch = subprocess.check_output( ['dpkg', '--print-architecture'], universal_newlines=True).rstrip() elif (self.is_redhat() or self.is_suse()): self._pkg_fmt = 'rpm' self._pkg_arch = subprocess.check_output( ['rpm', '--eval', '%_arch'], universal_newlines=True).rstrip() else: # unknown linux system, no logic available to figure out the package format or package architecture yet. self._pkg_fmt = 'unknown' self._pkg_arch = subprocess.check_output( ['uname', '-m'], universal_newlines=True).rstrip() if self._pkg_arch == 'x86_64': self._pkg_arch = 'amd64' elif platform_system == 'windows': self._programx86_dir = None self._program_dir = None self._program_data_dir = None # obtain additional version information # windows 7: ('7', '6.1.7601', 'SP1', 'Multiprocessor Free') self._os_version = ver.version_tuple_from_str( platform.win32_ver()[1]) try: import win32api # great, win32api module is installed. self._win32api_installed = True except ImportError: # we don't have any dependencies on the win32 extensions anymore but some scripts might have and can # figure out whether the extensions are available or not. pass # Hm, win32api not installed/available -> system detection may not by accurate and includes some guessing. if platform.architecture()[0] != '64bit': self._python_arch = 'x86' self._os_arch = 'x86' if ('PROCESSOR_ARCHITEW6432' in os.environ) and ( os.getenv('PROCESSOR_ARCHITEW6432') == 'AMD64'): # 32 bit python interpreter and 64 bit windows self._os_arch = 'x86_64' if 'NUMBER_OF_PROCESSORS' in os.environ: self._num_processors = int( os.getenv('NUMBER_OF_PROCESSORS')) if self._os_arch == 'x86_64': if self._python_arch == 'x86': self._program_dir = os.getenv('PROGRAMW6432') self._programx86_dir = os.getenv('PROGRAMFILES') else: self._program_dir = os.getenv('PROGRAMFILES') self._programx86_dir = os.getenv('PROGRAMFILES(X86)') assert self._programx86_dir is not None elif self._os_arch == 'x86': self._program_dir = os.getenv('PROGRAMFILES') else: assert False assert self._program_dir is not None self._program_data_dir = os.getenv('PROGRAMDATA') if os.path.exists(os.path.join(r'C:\Windows', 'py.exe')): self._python_launcher = os.path.join( r'C:\Windows', 'py.exe') # probe the registry to ensure the shell will pass additional arguments to the # registered python interpreter. # if pywin_check: # self.check_pywin_registry() elif platform_system == 'darwin': # create a dictionary to simplify the mapping between minor version ID and codenames codename_dict = { '10.4': 'tiger', '10.5': 'leopard', '10.6': 'snow leopard', '10.7': 'lion', '10.8': 'mountain lion', '10.9': 'mavericks', '10.10': 'yosemite', '10.11': 'el capitan', '10.12': 'sierra', '10.13': 'high sierra' } # replace darwin by macosx self._platform_system = 'macosx' # e.g. ('10.7.4', ('', '', ''), 'x86_64') mac_ver = platform.mac_ver() # save the macosx version as a tuple of integers self._os_version = ver.version_tuple_from_str(mac_ver[0]) # analyze the version tuple to derive the codename: lion, mountain lion, etc major_minor_ver = str(self._os_version[0]) + '.' + str( self._os_version[1]) if major_minor_ver in codename_dict: self._os_codename = codename_dict[major_minor_ver] #e.g. x86_64 self._os_arch = mac_ver[2] # python architecture is the same as the macosx architecture self._python_arch = self._os_arch # obtain the number of processors retv = subprocess.check_output(["/usr/sbin/sysctl", "hw.ncpu"], universal_newlines=True) self._num_processors = int(retv.rstrip().split()[1], 10) else: raise Exception('unsupported platform detected: ' + platform_system) self._query_home_dir() self._query_default_proj_home_dir() self._query_desktop_dir() self._query_search_path()
def _create_user_config_content(self, toolset, platform_index, target, build_boost_mpi, build_boost_python, cppflags=None, cflags=None, lflags=None, msvc_rt=None): """Check the toolset attributes and determine whether a temporary user-config.jam is needed or not.""" lines = [] platform_info = toolset.get_platform_info(platform_index) toolset_str = toolset.get_toolset() toolset_version_str = ver.version_tuple_to_str( toolset.get_version()[:2]) cxxflags = [] compileflags = [] linkflags = [] rc = [] using_line = None setup_cmd_content = [] setup_cmd = None if cppflags: cxxflags.extend(cppflags) if cflags: compileflags.extend(cflags) if lflags: linkflags.extend(lflags) extra_cflags = platform_info.get_target_cflags(target) if extra_cflags: compileflags.extend(extra_cflags) if toolset_str == 'gcc': using_line = "using %s : %s : %s" % ( toolset_str, toolset_version_str, toolset.get_compiler_command()) if toolset.is_mingw(): if self._sys_info.is_linux(): # mingw on linux is always a prefixed compiler and it does not figure out the path to windres by default. compiler_dir = os.path.dirname( toolset.get_compiler_command()) windres = os.path.join( compiler_dir, toolset.get_compiler_prefix() + '-windres') rc.append(windres) elif toolset_str == 'clang': if platform_info.get_target_os() in ['android', 'linux']: using_line = "using %s : %s : %s" % ( toolset_str, toolset_version_str, toolset.get_compiler_command()) elif platform_info.get_target_os() in [ 'macosx', 'iphone', 'iphonesimulator' ]: using_line = "using %s : : %s" % ( toolset_str, toolset.get_compiler_command()) isysroot = platform_info.get_isysroot() assert isysroot is not None compileflags.extend(['-isysroot', isysroot]) if platform_info.get_target_os() == 'macosx': # Add 3rd party native frameworks folder compileflags.append('-F/Library/Frameworks') linkflags.append('-F/Library/Frameworks') else: arch_flags = None if platform_info.get_target_os() == 'iphone': if target in ['armv7', 'arm64']: arch_flags = ['-arch', target] elif target == 'combined': arch_flags = ['-arch', 'armv7', '-arch', 'arm64'] else: assert False elif platform_info.get_target_os() == 'iphonesimulator': if target == 'x86_64': # Assume -arch x86_64 is the default pass elif target == 'x86': arch_flags = ['-arch', 'i386'] elif target == 'combined': arch_flags = ['-arch', 'x86_64', '-arch', 'i386'] else: assert False else: assert False if arch_flags: compileflags.extend(arch_flags) linkflags.extend(arch_flags) else: assert False elif toolset_str == 'intel': if self._sys_info.is_linux() or self._sys_info.is_macosx(): using_line = "using %s : %s : %s" % ( toolset_str, toolset_version_str, toolset.get_compiler_command()) elif self._sys_info.is_windows(): compiler_cmd = os.path.normpath(toolset.get_compiler_command()) compiler_cmd_escaped = compiler_cmd.replace("\\", "\\\\") assert msvc_rt is not None re_match = re.match(r'msvc-(\d+\.\d+)$', msvc_rt) if re_match: msvc_version_str = re_match.group(1) else: assert False using_line = 'using %s : %s : "%s" :' % ( toolset_str, toolset_version_str, compiler_cmd_escaped) #using_line += ' <rewrite-setup-scripts>off' using_line += ' <compatibility>vc' + msvc_version_str else: assert False elif toolset_str == 'msvc': if toolset_version_str in ['14.0']: msvc_registry = bldtools.MsvcRegistry() if msvc_registry.is_vs2017_toolset( ver.version_tuple_from_str(toolset_version_str)): # target ... setup_cmd = os.path.normpath( os.path.join(self._sys_info.get_home_dir(), 'setup_vs2017_vc140.bat')) # replace single backslashes with double backslashes setup_cmd_escaped = setup_cmd.replace("\\", "\\\\") using_line = 'using %s : %s : : <setup>"%s"' % ( toolset_str, toolset_version_str, setup_cmd_escaped) using_line += ' <rewrite-setup-scripts>off' # call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Auxiliary\Build\vcvarsall.bat" amd64 -vcvars_ver=14.0 if target == 'x86_64': setup_cmd_target = 'amd64' elif target == 'x86': setup_cmd_target = 'amd64_x86' else: assert False setup_cmd_content.append( 'call "%s" %s -vcvars_ver=14.0' % (toolset.get_compiler_command(), setup_cmd_target)) if cxxflags or compileflags or linkflags or rc: assert using_line is not None using_line += " :" if cxxflags: using_line += ' <cxxflags>"%s"' % ' '.join(cxxflags) if compileflags: using_line += ' <compileflags>"%s"' % ' '.join(compileflags) if linkflags: using_line += ' <linkflags>"%s"' % ' '.join(linkflags) if rc: using_line += ' <rc>"%s"' % ' '.join(rc) if using_line: lines.append(using_line + " ;") if build_boost_python: python_config_file = os.path.join(self._sys_info.get_home_dir(), 'user-config-python.jam') if os.path.exists(python_config_file): with open(python_config_file) as f: for line in f: lines.append(line.rstrip()) else: python_version = self._sys_info.get_python_version() if platform_info.get_target_os() == 'windows': python_executable_short_path = self._sys_info.get_short_path_win( self._sys_info.get_python_executable()) python_executable_cstring = python_executable_short_path.replace( "\\", "\\\\") lines.append('using python : %d.%d : "%s" ;' % (python_version[0], python_version[1], python_executable_cstring)) elif platform_info.get_target_os() == 'macosx': lines.append('using python : %d.%d : %s ;' % (python_version[0], python_version[1], self._sys_info.get_python_executable())) elif platform_info.get_target_os() == 'linux': lines.append('using python : %d.%d : %s ;' % (python_version[0], python_version[1], self._sys_info.get_python_executable())) if build_boost_mpi: mpi_config_file = os.path.join(self._sys_info.get_home_dir(), 'user-config-mpi.jam') if os.path.exists(mpi_config_file): with open(mpi_config_file) as f: for line in f: lines.append(line.rstrip()) else: lines.append("using mpi ;") return lines, setup_cmd, setup_cmd_content
def _parse_command_line(self, argv): _usage_header = "%(prog)s [options] [toolset=msvc-x.y|gcc|gcc-x[.y]|clang|intel[-msvc-x.y] [target-os=iphone|iphonesimulator]" _description = """ %(prog)s builds BOOST libraries from source, use option --boost-dir to specify the location of the BOOST SDK. If the BOOST directory ends with -c++03, -c++11, -c++14, or -c++17, this suffix will be used as the c++ standard unless option --std is specified. If neither condition is true, c++11 will be used. Notes on Intel Compiler Selection: - No support for side-by-side installation of multiple Intel compilers yet - No support for 32 bit builds on any platform - On Windows the latest MSVC runtime/IDE will be used unless overridden by a suffix -msvc-x.y". """ parser = argparse.ArgumentParser(usage=_usage_header, description=_description, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument("buildprops", action="store", nargs='*', help="one or more build properties specified as key=value, e.g. toolset=msvc-12.0") parser.add_argument("--boost-dir", action="store", dest="boost_dir", required=True, help="required option to specify the location of the BOOST SDK.") parser.add_argument("--std", action="store", dest="cxx_std", choices=['c++03', 'c++11', 'c++14', 'c++17'], help="overrides the c++ standard which is deduced from the boost directory if it ends with " "one of the supported c++ standards prefixed by a hyphen.") parser.add_argument("--target", action="append", dest="targets", help="override the toolset's default target. Typically used to build 32 bit libraries on Windows; " "example: --target x86 toolset=msvc-14.0") parser.add_argument("--rebuild", action="store_true", dest="rebuild_all", default=False, help="force a rebuild of all boost libraries") group = parser.add_argument_group("MacOSX Options") g = group.add_mutually_exclusive_group() g.add_argument("--macosx-version-min", action="store", dest="macosx_version_min", help="add backward compatibility down to the given MacOSX release.") g.add_argument("--ios-version-min", action="store", dest="macosx_version_min", metavar="IOS_VERSION_MIN", help="add backward compatibility down to the given IOS release.") group = parser.add_argument_group("Advanced Options") group.add_argument("--c++-runtime", action="store", dest="cxx_runtime", choices=['shared', 'static', 'gnustl', 'libc++', 'libstdc++'], help="overrides the default c++ runtime, supported for mingw, msvc, clang and Android.") group.add_argument("--with-mpi", action="store_true", dest="build_mpi", default=False, help="enable Boost MPI (message passing interface) [default:off]") group.add_argument("--with-python", action="store_true", dest="build_python", default=False, help="enable Boost Python [default:off]. If enabled, Boost MPI may not build.") group.add_argument("--use-user-config", action="store_true", dest="use_user_config", default=False, help="enable the use of $HOME/user-config.jam [default:off].") util.app_args_add_log_level(group) group.add_argument("--dry-run", action="store_true", dest="dry_run", default=False, help="check which libraries are missing, list the update actions but don't start the build.") group.add_argument("--debug-configuration", action="store_true", dest="debug_configuration", default=False, help="invoke b2 with --debug-configuration, disables removal of temporary files.") group.add_argument("--jobs", action="store", type=int, dest="bjam_jobs", help="specifies the number of parallel bjam jobs explicitly [default: number of processors]") args = parser.parse_args(argv) # configure the python logger util.app_configure_logging(args.log_level) boost_build_params = boostbld.BoostBuildParams(self._sys_info) re_toolset = re.compile(r'toolset=(\S+)') re_address_model = re.compile(r'address-model=(\S+)') re_target_os = re.compile(r'target-os=(\S+)') for arg in args.buildprops: arg_parsed = False re_match = re_toolset.match(arg) if re_match: boost_build_params.toolset = re_match.group(1) if boost_build_params.toolset.startswith('msvc-'): boost_build_params.toolset = self._msvc_dict.transform_cmake_to_bbuild(boost_build_params.toolset) elif boost_build_params.toolset.startswith('intel-'): re_match_intel = re.match(r'intel-(msvc-\d+\.\d+)$', boost_build_params.toolset) if re_match_intel: boost_build_params.toolset = 'intel' boost_build_params.msvc_rt = re_match_intel.group(1) else: print("boost_install.py: argument", arg, " not understood, try --help to get more usage information.") sys.exit(1) arg_parsed = True re_match = re_address_model.match(arg) if re_match: arg_parsed = True if re_match.group(1) == '32': args.targets = ['x86'] elif re_match.group(1) == '64': args.targets = ['x86_64'] else: print("boost_install.py: argument", arg, " not understood, try --help to get more usage information.") sys.exit(1) re_match = re_target_os.match(arg) if re_match: arg_parsed = True if re_match.group(1) == 'iphone': boost_build_params.platform_index = 1 elif re_match.group(1) == 'iphonesimulator': boost_build_params.platform_index = 2 else: print("boost_install.py: argument", arg, " not understood, try --help to get more usage information.") sys.exit(1) if not arg_parsed: print("boost_install.py: argument", arg, " not understood, try --help to get more usage information.") sys.exit(1) boost_dir = None if args.boost_dir: # boost_dir must be transformed before changing cwd. boost_dir = util.normalize_path(os.path.abspath(args.boost_dir)) boost_build_params.targets = self._set_build_targets(boost_build_params.toolset, args.targets) if args.cxx_std: cxx_std = args.cxx_std else: cxx_std = None if args.cxx_runtime: boost_build_params.cxx_runtime = args.cxx_runtime boost_build_params.dry_run = args.dry_run boost_build_params.debug_configuration = args.debug_configuration boost_build_params.build_mpi = args.build_mpi boost_build_params.build_python = args.build_python boost_build_params.bjam_jobs = args.bjam_jobs boost_build_params.custom_user_config = args.use_user_config # options to select what to build boost_build_params.rebuild_all = args.rebuild_all if self._sys_info.is_macosx(): # handle --macosx-version-min option, it will apply to MacOSX and iOS if args.macosx_version_min is not None: boost_build_params.macosx_version_min = ver.version_tuple_from_str(args.macosx_version_min) return boost_build_params, boost_dir, cxx_std