3 # Copyright 2013, Intel Inc.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; version 2 of the License.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Library General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 Created on 05 fevr. 2013
21 @author: ronan@fridu.net
28 RECIPES_SOURCE_DIR = os.path.dirname( os.path.realpath( __file__ ) )
29 RECIPES_DIR_DEST = os.path.join( RECIPES_SOURCE_DIR, "../meta-tizen-ivi" )
30 GIT_COMMAND = "git://%s/%s;tag=%s;nobranch=1"
35 from urllib import urlopen
36 from xml.etree import ElementTree
41 print >> sys.stderr, 'Error spec2yocto require "python-cmdln" please install it.'
56 # Very useful to debug spec2yocto, print the subprocess EXEC_COMMAND line.
59 CONFIGURATION_FILE_PATH = os.path.expanduser( os.path.join( "~", ".spec2yoctorc" ) )
61 class Spec2yoctoConfig( object ):
63 Parse the file "spec2yocto_configure",
67 self.__config_parser = ConfigParser.ConfigParser()
68 self.__config_parser.optionxform = str
70 if not os.path.isfile( CONFIGURATION_FILE_PATH ):
71 print >> sys.stderr, "Warning CONFIGURATION_FILE_PATH \"%s\" do not exist." % (CONFIGURATION_FILE_PATH)
72 print >> sys.stderr," a sample is available in directory \"proto-meta-Tizen_generic/.spec2yoctorc\""
75 self.__config_file = open( CONFIGURATION_FILE_PATH , 'rw' )
77 self.__config_parser.readfp( self.__config_file )
79 def get_current_project( self ):
81 return the list of the manifest_meta, manifest_meta can be a file or URL.
84 return self.__get_value( "project", "current" , None )
86 def get_manifest_meta_list( self, projet ):
88 return the list of the manifest_meta, manifest_meta can be a file or URL.
90 meta_manifests_res = []
91 list_of_meta_manifest = self.__get_list( projet, "manifest", [] )
92 for meta_manifest in list_of_meta_manifest:
93 meta_manifests_res.append( meta_manifest.replace( " ", "" ) )
95 return meta_manifests_res
97 def get_manifest_uri( self, meta_manifest ):
99 return the uri of the manifest.
101 res = self.__get_value( meta_manifest, "uri" , None )
102 res = os.path.expanduser( res )
103 res = os.path.expandvars( res )
106 def get_manifest_priority( self, meta_manifest ):
108 return the priority of the manifest.
110 return self.__get_value( meta_manifest, "priority" , 0 )
112 def get_manifest_default_git_src( self, meta_manifest ):
114 return the default_git_src of the manifest.
116 return self.__get_value( meta_manifest, "default_git_src" , None )
118 def is_valide_project( self, projet ):
120 check if project is configurate in the conf file.
122 return ( projet in self.__config_parser.sections() )
124 def get_project_arch( self, projet ):
126 return the default arch of the project.
128 return self.__get_value( projet, "arch", None )
130 def get_working_dir( self, projet ):
132 return the working dir of the project.
134 res = self.__get_value( projet, "working_dir", "/tmp" )
136 res = os.path.expanduser( res )
137 res = os.path.expandvars( res )
140 def get_runtime_blacklist( self, project ):
142 return the list of the blacklisted runtime package.
144 blacklist_list = self.__get_list( project, "runtime_blacklist", [] )
146 for blacklist in blacklist_list:
147 res.extend( self.__get_list( blacklist, "list", [] ) )
151 def get_whitelist( self, project ):
153 return the list of the whitelist package.
155 whitelist_list = self.__get_list( project, "whitelist", [] )
157 for whitelist in whitelist_list:
158 res.extend( self.__get_list( whitelist, "list", [] ) )
161 def get_blacklist( self, project ):
163 return the list of the blacklisted package.
165 blacklist_list = self.__get_list( project, "blacklist", [] )
167 for blacklist in blacklist_list:
168 res.extend( self.__get_list( blacklist, "list", [] ) )
172 def get_native_blacklist( self, project ):
174 return the list of the blacklisted native package.
176 blacklist_list = self.__get_list( project, "native_blacklist", [] )
178 for blacklist in blacklist_list:
179 res.extend( self.__get_list( blacklist, "list", [] ) )
182 def get_substitute( self , project = None ):
185 for package in self.__config_parser.options( "substitute" ):
186 package_replace = self.__get_value( "substitute", package, None )
187 if package_replace is not None:
188 res[package] = package_replace
191 def __get_list( self, section, option, default_value ):
193 generic fonction to get list value.
195 if ( section in self.__config_parser.sections() ) and \
196 ( option in self.__config_parser.options( section ) ):
197 tmp_res = str( self.__config_parser.get( section, option ) )
198 return tmp_res.replace( " ", "" ).split( "," )
202 def __get_value( self, section, option, default_value ):
204 generic fonction to get value.
206 if ( section in self.__config_parser.sections() ) and \
207 ( option in self.__config_parser.options( section ) ):
208 tmp_res = self.__config_parser.get( section, option )
213 def get_recipes_sources_directory( self, project ):
215 return a list of the recipes directory needed to build the image.
217 res = self.__get_value( project, 'recipes_dir_sources', None )
218 res = os.path.expanduser( res )
219 res = os.path.expandvars( res )
222 def get_recipes_group_directory( self, project ):
223 res = self.__get_value( project, 'recipes_dir_group', None )
224 res = os.path.expanduser( res )
225 res = os.path.expandvars( res )
229 def get_group( self , project = None ):
231 project = self.get_current_project()
232 return self.__get_list( project, 'group', [] )
235 def get_target_cpu( self , project = None ):
240 project = self.get_current_project()
241 return self.__get_value( project, 'arch' , None )
243 def get_bb_autoreconf_blacklist( self , project = None ):
245 return a list of package with no autoreconf.
248 project = self.get_current_project()
250 blacklist_list = self.__get_list( project, "blacklist_autoreconf", [] )
252 for blacklist in blacklist_list:
253 res.extend( self.__get_list( blacklist, "blacklist", [] ) )
257 def get_provided_extra( self , project = None ):
260 project = self.get_current_project()
262 provided_extra_list = self.__get_list( project, "provided-extra", [] )
263 provided_extra_dico={}
264 for provided_extra in provided_extra_list:
265 for package in self.__config_parser.options( provided_extra ):
266 provided_list = self.__get_list( provided_extra, package, [] )
267 provided_extra_dico[package] = provided_list
268 return provided_extra_dico
271 def get_ignore_depend( self ):
273 return the ignore package to ignore for depends (build require).
275 return self.__get_list( 'depends', 'ignore', [] )
277 def get_ignore_rdepend( self ):
279 return the ignore package to ignore for rdepends (require).
281 return self.__get_list( 'rdepends', 'ignore', [] )
283 def get_native_depend( self ):
285 some buildRequire mean depends on native package not runtime.
287 return self.__get_list( 'depends', 'native', [] )
289 def get_cross_depend( self ):
291 some buildRequire mean depends on native package not runtime.
293 return self.__get_list( 'depends', 'cross', [] )
295 def get_libtool_cross( self ):
297 some buildRequire mean depends on libtool-cross package not runtime.
299 return self.__get_list( 'depends', 'libtool_cross', [] )
301 def get_inherit_gettext( self ):
303 some buildRequire mean inherit_gettext package not depends runtime.
305 return self.__get_list( 'depends', 'inherit_gettext', [] )
307 def get_inherit_perl( self ):
309 some buildRequire mean inherit_perl package not depends runtime.
313 def get_inherit_python( self ):
315 some buildRequire mean inherit_perl package not depends runtime.
319 def get_inherit_tizen_cmake( self ):
321 some buildRequire mean inherit_cmake package not depends runtime.
325 def get_group_uri( self, project ):
327 return self.__get_value( project, 'group_uri', None )
330 SPEC2YOCTO_CONFIG = Spec2yoctoConfig()
332 # Implementation taken from http://hetland.org
333 def levenshtein( a, b ):
334 """Calculates the Levenshtein distance between a and b."""
335 n, m = len( a ), len( b )
337 # Make sure n <= m, to use O(min(n,m)) space
341 current = range( n + 1 )
342 for i in range( 1, m + 1 ):
343 previous, current = current, [i] + [0] * n
344 for j in range( 1, n + 1 ):
345 add, delete = previous[j] + 1, current[j - 1] + 1
346 change = previous[j - 1]
347 if a[j - 1] != b[i - 1]:
349 current[j] = min( add, delete, change )
353 def get_packaging_files( package_path ):
355 for tmp_res in os.listdir( package_path ):
356 if tmp_res.endswith( ".spec" ) and os.path.isfile( package_path + "/" + tmp_res ):
357 res.append( tmp_res )
360 def findBestSpecFile( package_path, package_name ):
362 Find the name of the spec file which matches best with `package_name`
365 package_spec_dir = package_path
366 package_spec_dir = os.path.expanduser( package_spec_dir )
367 package_spec_dir = os.path.expandvars( package_spec_dir )
369 specFileList = get_packaging_files( package_path )
372 if len( specFileList ) < 1:
373 # No spec file in list
375 elif len( specFileList ) == 1:
377 specFile = specFileList[0]
380 for spec in specFileList:
381 if str( spec[:-5] ) == str( package_name ):
382 # This spec file has the same name as the package
385 elif spec.startswith( package_name ):
386 # This spec file has a name which looks like the package
387 sameStart.append( spec )
390 if len( sameStart ) > 0:
391 # Sort the list of 'same start' by the Levenshtein distance
392 sameStart.sort( key = lambda x: levenshtein( x, package_name ) )
393 specFile = sameStart[0]
395 # No spec file starts with the name of the package,
396 # sort the whole spec file list by the Levenshtein distance
397 specFileList.sort( key = lambda x: levenshtein( x, package_name ) )
398 specFile = specFileList[0]
401 msg = "Found no spec file matching package name '%s'" % package_name
405 spec_full_path = os.path.join( package_spec_dir, specFile )
406 return spec_full_path
408 def findSpecPatchFiles( patch_dir_path, package_name_list ):
410 Find the name of the patch for the spec file which matches best with `package_name`
414 patch_dir_path = os.path.expanduser( patch_dir_path )
415 patch_dir_path = os.path.expandvars( patch_dir_path )
417 for patch_name in set( package_name_list ):
418 for patch_extend in ["", "-yocto"]:
419 patch_file = patch_name + patch_extend + ".spec.patch"
420 patch_path = os.path.join( patch_dir_path, patch_file )
421 if os.path.isfile( patch_path ):
422 patch_list.append( patch_path )
428 class SubprocessCrt( object ):
430 usefull class to control subprocess
432 def __init__( self ):
434 Initialize subprocess.
439 def get_last_res( self ):
441 return the last subprocess output.
443 return self.output_res
445 def __read_subprocess_output( self, outputs, f_stdout, f_stderr ):
447 read the stdout, stderr of the subprocess
451 for file_d in select.select( [f_stdout, f_stderr], [], [], select_timeout )[0]:
453 output = file_d.read()
454 if f_stdout == file_d:
455 self.output_res += output
457 if DEBUG_RUN and ( len( output ) > 0 ):
458 print "ERROR ****", output, len( output )
460 for line in output.split( "\n" ):
461 if not line == b"" or not output.endswith( "\n" ):
462 outputs[file_d]["EOF"] = False
464 if line == b"" and not output.endswith( "\n" ):
465 outputs[file_d]["EOF"] = True
467 res_clean = line.decode( "utf8", "replace" ).rstrip()
472 self.__idle_time += select_timeout
478 def exec_subprocess( self, command ):
480 Execute the "command" in a sub process,
481 the "command" must be a valid bash command.
482 _args and _kwargs are for compatibility.
487 # need Python 2.7.3 to do shlex.split(command)
488 splitted_command = shlex.split( str( command ) )
489 a_process = subprocess.Popen( splitted_command,
490 stdout = subprocess.PIPE,
491 stderr = subprocess.PIPE )
492 f_stdout = a_process.stdout
493 f_stderr = a_process.stderr
495 flags = fcntl.fcntl( f_stdout, fcntl.F_GETFL )
496 if not f_stdout.closed:
497 fcntl.fcntl( f_stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK )
499 flags = fcntl.fcntl( f_stderr, fcntl.F_GETFL )
500 if not f_stderr.closed:
501 fcntl.fcntl( f_stderr, fcntl.F_SETFL, flags | os.O_NONBLOCK )
503 outputs = {f_stdout: {"EOF": False},
504 f_stderr: {"EOF": False}}
507 while ( ( not outputs[f_stdout]["EOF"] and
508 not outputs[f_stderr]["EOF"] ) or
509 ( a_process.poll() == None ) ):
511 self.__read_subprocess_output( outputs, f_stdout, f_stderr )
512 except select.error as error:
513 # see http://bugs.python.org/issue9867
514 if error.args[0] == errno.EINTR:
515 print "Got select.error: %s" % unicode( error )
520 # maybe a_process.wait() is better ?
521 poll_res = a_process.poll()
524 return self.output_res
528 def of usefull re pattern to parse spec file.
530 pattern_patch = r'([pP]atch[\d]*)[\s]*:[\s]*.*'
531 patternUrlSourceFile = r'Source[\d]*[\s]*:[\s]*([http,ftp].*/)(.*)'
532 patternUrlPatchFile = r'Patch[\d]*[\s]*:[\s]*([http,ftp].*/)(.*)'
534 patternPatch = r'[pP]atch([\d]*)[\s]*:[\s]*(.*)'
535 patternSource = r'Source([\d]*)[\s]*:[\s]*(.*)'
537 patternPatchCommand = r'#(patch)([\d]*)(.*)'
539 patternDescription = r'^Summary:\s*(.*)'
540 patternUrl = r'^Url:\s*(.*)'
541 patternGroup = r'^Group:\s*(.*)'
542 patternLicense = r'^License:\s*(.*)'
544 patternFiles = r'^%files\s*(.*)'
546 patternName = r'^Name:\s*(.*)'
548 patternPackage = r'^%package\s*(.*)'
549 provides_package = r'^Provides:\s*(.*)'
551 buildPkgconfig = r'pkgconfig\((.*)\).*'
553 pkgRe = r'([^ \t\n\r\f\v,]+)(?:\s+(<|>|<=|>=|=|==)\s+([^ \t\n\r\f\v,]+))?'
555 buildRequiresPackage = r'^BuildRequires:\s*(.*)'
556 requiresPackage = r'^Requires(?:\(\w+\))?:\s*(.*)'
558 paternDevel = "(.*)-devel"
560 pkgconfig_name = "/usr/lib/pkgconfig/([^*]*).pc"
562 def __init__( self ):
567 def get_macro_directory_path( current_cpu ):
569 return all the valid macro directory.
572 for macro_dir in ["lib/*",
574 "lib/platform/%s-linux/macros" % current_cpu,
579 macro_paths += os.path.join( "/usr/share/spec2yocto/macro", macro_dir ) + " "
587 msubprocess = SubprocessCrt()
588 def __init__( self, package_spec_path, package_pn = None ):
592 self.__introduction_section = "introduction_section"
593 self.__package = "%package"
594 self.__description = "%description"
595 self.__prep_flag = "%prep"
596 self.__build_flag = "%build"
597 self.__install_flag = "%install"
598 self.__clean_flag = "%clean"
599 self.__files_flag = "%files"
600 self.__check_flag = "%check"
601 #pkg_preinst, pkg_postinst, pkg_prerm, and pkg_postrm
602 self.__post_flag = "%post"
603 self.__preun_flag = "%preun"
604 self.__postun_flag = "%postun"
605 self.__pre_flag = "%pre"
607 self.__verifyscript_flag = "%verifyscript"
608 self.__changelog_flag = "%changelog"
609 self.__list_section = [self.__package,
621 self.__verifyscript_flag,
622 self.__changelog_flag]
624 self.__package_spec_path = package_spec_path
625 self.__package_pn = package_pn
627 self.__parsed_spec_file = None
628 self.__order_list = []
629 self.__spect_dico = {}
632 self.__order_raw_list = []
633 self.__raw_spect_dico = {}
635 self.__cpu = SPEC2YOCTO_CONFIG.get_target_cpu()
636 self.__cpu_native = platform.machine()
638 self.__convert_spec_file()
639 self.__parse_parsed_spec_file()
640 self.__base_name = self.get_name()
642 self.__pkg_config = []
644 def __find_patch( self ):
646 find the patchs of the spec file.
649 with open( self.__package_spec_path ) as file_d:
650 spec_file = file_d.read()
651 res_tmp = re.findall( RePattern.pattern_patch, spec_file )
652 for a_res in res_tmp:
653 self.__patchs.append( a_res.replace( "Patch", "patch" ) )
655 def __is_native_build( self ):
657 return True if the package is native.
659 res_1 = ( self.__package_pn is not None )
663 res_2 = self.__package_pn.endswith( "-native" )
667 def init_rpmspec_command( self ):
669 init rpmspec_command to parse spec file.
671 rpmspec_command = "rpmspec "
673 if self.__is_native_build():
674 current_cpu = self.__cpu_native
676 current_cpu = self.__cpu
678 rpmspec_command += " --macros=\"%s\" " % get_macro_directory_path( current_cpu )
680 rpmspec_command += " --define='buildroot ${D}' "
681 if self.__is_native_build():
682 # Not the better way to do this
683 rpmspec_command += " --define='basearch i386' "
684 # I guess other tool must be set for native build.
685 rpmspec_command += " --define='__cc gcc' "
686 # the default value of the macro is %{nil}
687 base_prefix = os.getenv( "base_prefix" )
688 if ( base_prefix != "" ) and ( base_prefix is not None ):
689 rpmspec_command += " --define='_buildPrefix %s' " % base_prefix
691 rpmspec_command += " --define='%find_lang echo no find_lang for package native'"
693 rpmspec_command += " --define='setup #setup' "
694 rpmspec_command += " --define='setup0 #setup0' "
696 package_dir = os.path.dirname( self.__package_spec_path )
698 rpmspec_command += " --define='SOURCES ${S}/packaging/' "
699 rpmspec_command += " --define='_sourcedir ${S}/packaging/' "
701 rpmspec_command += " --define='BUILD_BASENAME %{basename}' "
703 rpmspec_command += " --target='%s' " % current_cpu
705 package_name = os.path.basename( self.__package_spec_path )[:-5]
707 if package_name in SPEC2YOCTO_CONFIG.get_bb_autoreconf_blacklist() :
708 oe_runconf2 = '''oe_runconf2'''
709 rpmspec_command += " --define='%%_configure %s'" % oe_runconf2
711 return rpmspec_command
714 def __convert_spec_file( self ):
716 init convert spec to expand spec file.
718 tmp_package_spec_path = self.__package_spec_path
720 # we can't use python rpm API to parse the spec file so we need to exec rpmspec\
721 # in a subprocess and parse the result.
722 rpmspec_command = self.init_rpmspec_command()
724 # it's import to remove all "Source" url because if rpm dan't find the source,\
725 # it try to downloads the file from the url.
726 with open( tmp_package_spec_path, 'r' ) as current_spec_file:
727 current_spec_string = current_spec_file.read()
728 res_url_source_files = re.findall( RePattern.patternUrlSourceFile, current_spec_string )
730 if len( res_url_source_files ) > 0:
731 for res_url in res_url_source_files:
732 long_url = res_url[0] + res_url[1]
733 short_url = res_url[1]
734 current_spec_string = current_spec_string.replace( long_url, short_url )
736 with tempfile.NamedTemporaryFile( mode = 'w',
738 prefix = os.path.basename( tmp_package_spec_path ) + ".",
739 dir = os.path.dirname( tmp_package_spec_path ),
740 delete = False ) as tmp_spec_file:
741 tmp_spec_file.write( current_spec_string )
742 tmp_package_spec_path = tmp_spec_file.name
744 # same case as "Source"
745 with open( tmp_package_spec_path, 'r' ) as current_spec_file:
746 current_spec_string = current_spec_file.read()
747 res_url_patch_file = re.findall( RePattern.patternUrlPatchFile, current_spec_string )
749 if len( res_url_patch_file ) > 0:
750 for res_url in res_url_patch_file:
751 long_url = res_url[0] + res_url[1]
752 short_url = res_url[1]
753 current_spec_string = current_spec_string.replace( long_url, short_url )
754 if ( tmp_package_spec_path != self.__package_spec_path ) \
755 and os.path.isfile( tmp_package_spec_path ) \
757 os.remove( tmp_package_spec_path )
758 with tempfile.NamedTemporaryFile( mode = 'w',
760 prefix = os.path.basename( tmp_package_spec_path ) + ".",
761 dir = os.path.dirname( tmp_package_spec_path ),
762 delete = False ) as tmp_spec_file:
763 tmp_spec_file.write( current_spec_string )
764 tmp_package_spec_path = tmp_spec_file.name
767 for a_patch in self.__patchs:
768 if a_patch == "patch0":
769 rpmspec_command += " --define='%patch #patch' "
771 rpmspec_command += " --define='%s #%s' " % ( a_patch, a_patch )
773 rpmspec_command += " --define='debug_package %{nil}'"
775 rpmspec_command += " --parse %s " % tmp_package_spec_path
777 print "rpmspec_command :", rpmspec_command
780 self.__parsed_spec_file = SpecParser.msubprocess.exec_subprocess( rpmspec_command )
781 if ( tmp_package_spec_path != self.__package_spec_path ) \
782 and os.path.isfile( tmp_package_spec_path ) \
784 os.remove( tmp_package_spec_path )
786 if self.__parsed_spec_file == 1:
787 print >> sys.stderr, ""
788 print >> sys.stderr, "ERROR CMD: %s" % rpmspec_command
789 print >> sys.stderr, "parse error for spec file %s" % ( tmp_package_spec_path )
790 self.__parsed_spec_file = None
794 if not os.path.isdir( "/tmp/parsed_spec" ):
795 os.makedirs( "/tmp/parsed_spec" )
797 if self.__package_pn is None:
798 tmp_path = os.path.basename( self.__package_spec_path )
799 package_parsed_spec_path = os.path.join( "/tmp/parsed_spec", tmp_path )
801 tmp_path = "%s.spec" % self.__package_pn
802 package_parsed_spec_path = os.path.join( "/tmp/parsed_spec", tmp_path )
804 with open( package_parsed_spec_path, "w" ) as file_d:
805 file_d.write( self.__parsed_spec_file )
808 def __test_section( self, line ):
810 test if the line is the start of a new section.
812 for sect in self.__list_section:
813 if line.startswith( sect ):
817 def __parse_parsed_spec_file( self ):
819 parse a spec file by section after rpmspec.
821 # ordered dico is not provide yet...
822 self.__order_list = []
823 self.__spect_dico = {}
825 current_section = self.__introduction_section
826 self.__spect_dico[current_section] = []
827 self.__order_list.append( current_section )
829 if self.__parsed_spec_file is None:
832 for line in self.__parsed_spec_file.split( "\n" ):
834 if self.__test_section( line ) :
835 if line in self.__spect_dico.keys():
836 print "line %s" % line
837 print "--------------------------------------"
838 print "parsedSpecFile: %s" % self.__package_spec_path
839 print "--------------------------------------"
840 error_msg = "ERROR for the spec file \"%s\" this section \"%s\" is not unique."
841 print error_msg % ( self.__parsed_spec_file, line )
844 current_section = line
845 self.__spect_dico[current_section] = []
846 self.__order_list.append( current_section )
848 self.__spect_dico[current_section].append( line )
850 def parse_raw_spec_file( self ):
852 parse a spec file by section before rpmspec.
855 # ordered dico is not provide yet...
857 self.__order_raw_list = []
858 self.__raw_spect_dico = {}
860 current_section = self.__introduction_section
861 self.__raw_spect_dico[current_section] = []
862 self.__order_raw_list.append( current_section )
864 with open( self.__package_spec_path, "r" ) as file_d:
865 parsed_raw_spec_file = file_d.read()
867 for line in parsed_raw_spec_file.split( "\n" ):
868 if self.__test_section( line ) :
869 if line in self.__raw_spect_dico.keys():
870 print "line %s" % line
871 print "--------------------------------------"
872 print "parsedSpecFile: %s" % self.__package_spec_path
873 print "--------------------------------------"
874 error_msg = "ERROR for the spec file \"%s\" this section \"%s\" is not unique."
875 print error_msg % ( self.__parsed_spec_file, line )
878 current_section = line
879 self.__raw_spect_dico[current_section] = []
880 self.__order_raw_list.append( current_section )
882 self.__raw_spect_dico[current_section].append( line )
885 def get_prep_section( self ):
887 return the prep section of the spec file.
889 res_prep_section = "cd ${S}\n"
891 pattern_patch_dico = {}
892 pattern_source_dico = {}
894 for line in self.__spect_dico[self.__introduction_section][1:]:
895 for patch_id, files_name in re.findall( RePattern.patternPatch, line ):
898 pattern_patch_dico[patch_id] = files_name
900 for source_id, files_name in re.findall( RePattern.patternSource, line ):
903 pattern_source_dico[source_id] = files_name
905 for line in self.__spect_dico[self.__prep_flag][1:]:
906 if line.startswith( "#setup" ):
907 splited_line = line.split()
908 for i in range( len( splited_line ) ):
909 if splited_line[i].startswith( "-a" ):
910 if len( splited_line[i] ) > len( "-a" ):
911 setup_id = splited_line[i].replace( "-a", "" )
913 setup_id = splited_line[i + 1]
914 res_prep_section += "#extracte source %s \n" % setup_id
915 res_prep_section += "pushd ${S}\n"
916 source = os.path.basename( pattern_source_dico[setup_id] )
917 # not a good way to do this
918 if source.endswith( "rpmlintrc" ):
919 res_prep_section += "cp ${S}/packaging/%s .\n" % source
921 file_name = os.path.basename( pattern_source_dico[setup_id] )
922 res_prep_section += "unp ${S}/packaging/%s \n" % file_name
923 res_prep_section += "popd \n"
925 elif splited_line[i].startswith( "-b" ):
926 if len( splited_line[i] ) > len( "-b" ):
927 setup_id = splited_line[i].replace( "-b", "" )
929 setup_id = splited_line[i + 1]
931 res_prep_section += "#extracte source %s \n" % ( setup_id )
932 res_prep_section += "pushd ${S}/../\n"
933 source = os.path.basename( pattern_source_dico[setup_id] )
934 if source.endswith( "rpmlintrc" ):
935 res_prep_section += "cp ${S}/packaging/%s .\n" % source
937 res_prep_section += "unp ${S}/packaging/%s \n" % source
938 res_prep_section += "popd \n"
940 res_prep_section += "chmod -Rf a+rX,u+w,g-w,o-w ${S}\n"
943 elif line.startswith( "#patch" ):
944 res_findall = re.findall( RePattern.patternPatchCommand, line )
946 for patch_name, patch_id, EXEC_COMMAND in res_findall:
950 files_name = pattern_patch_dico[patch_id]
952 if "-p" not in EXEC_COMMAND:
953 EXEC_COMMAND += " -p0"
955 if files_name.endswith( ".bz2" ):
956 bzcat_cmd = "bzcat ${S}/packaging/%s | patch -s %s --fuzz=2\n"
957 bzcat_val = ( files_name, EXEC_COMMAND.replace( " -b", " -b --suffix" ) )
958 res_prep_section += bzcat_cmd % bzcat_val
960 cat_cmd = "cat ${S}/packaging/%s | patch -s %s --fuzz=2\n"
961 cat_val = ( files_name, EXEC_COMMAND.replace( " -b", " -b --suffix" ) )
962 res_prep_section += cat_cmd % cat_val
964 res_prep_section += line + "\n"
965 return res_prep_section
967 def get_build_section( self ):
969 return the build section of the spec file.
971 res_build_section = "cd ${S}\n"
972 if self.__build_flag not in self.__spect_dico.keys():
975 for line in self.__spect_dico[self.__build_flag][1:]:
976 res_build_section += line + "\n"
978 return res_build_section
980 def get_raw_build_section( self ):
982 return the raw build section of the spec file.
984 res_raw_build_section = ""
985 if self.__build_flag not in self.__spect_dico.keys():
987 for line in self.__raw_spect_dico[self.__build_flag][1:]:
988 res_raw_build_section += line + "\n"
989 return res_raw_build_section
991 def get_clean_raw( self ):
993 clean the raw spec file to generate spec file for yocto packaging.
996 for sect in self.__order_raw_list:
997 if sect == self.__introduction_section:
998 for line in self.__raw_spect_dico[sect]:
999 if line.startswith("Version:"):
1000 res_clean_raw += "Version: git\n"
1003 have_findall_source = len( re.findall( RePattern.patternSource , line ) ) > 0
1004 have_findall_patch = len( re.findall( RePattern.patternPatch, line ) ) > 0
1005 if not( have_findall_source or have_findall_patch ):
1006 res_clean_raw += line + "\n"
1009 elif sect == self.__prep_flag:
1010 res_clean_raw += line + "%prep\n"
1011 res_clean_raw += line + "#FAKE\n"
1012 elif sect == self.__build_flag:
1013 res_clean_raw += line + "%build\n"
1014 res_clean_raw += line + "#FAKE\n"
1015 elif sect == self.__install_flag:
1016 res_clean_raw += line + "%install\n"
1017 res_clean_raw += line + "#FAKE\n"
1018 elif sect == self.__check_flag:
1020 elif sect == self.__clean_flag:
1022 elif sect == self.__changelog_flag:
1024 elif sect.startswith( "%files" ):
1025 for line in self.__raw_spect_dico[sect]:
1026 if line.startswith( '%manifest ' ):
1027 res_clean_raw += line[len('%manifest '):] + "\n"
1028 elif line.startswith( '%doc ' ):
1030 elif line.startswith( '%ghost ' ):
1032 elif line.startswith( '%exclude ' ):
1034 elif line.startswith( '%license' ):
1038 res_clean_raw += line + "\n"
1041 for line in self.__raw_spect_dico[sect]:
1042 res_clean_raw += line + "\n"
1044 clean_raw_command = self.init_rpmspec_command()
1046 tmp_package_spec_path = self.__package_spec_path
1047 with tempfile.NamedTemporaryFile( mode = 'w',
1049 prefix = os.path.basename( tmp_package_spec_path ) + ".",
1050 dir = os.path.dirname( tmp_package_spec_path ),
1051 delete = False ) as tmp_spec_file:
1052 tmp_spec_file.write( res_clean_raw )
1053 tmp_package_spec_path = tmp_spec_file.name
1055 clean_raw_command += " --define='debug_package %{nil}'"
1056 clean_raw_command += " --define='docs_package %{nil}'"
1058 clean_raw_command += " --parse %s " % tmp_package_spec_path
1060 print "clean_raw_command :", clean_raw_command
1062 parsed_spec_file = SpecParser.msubprocess.exec_subprocess( clean_raw_command )
1064 if os.path.isfile( tmp_package_spec_path ) and not DEBUG_RUN:
1065 os.remove( tmp_package_spec_path )
1067 if parsed_spec_file == 1:
1068 print >> sys.stderr, "parse error for spec file %s" % ( tmp_package_spec_path )
1069 parsed_spec_file = None
1074 Summary: #FAKE - Debugging files
1077 %%description -n %s-dbg
1083 ''' % ( self.__base_name, self.__base_name, self.__base_name )
1084 work_dir = os.getenv( "WORKDIR" )
1086 if work_dir is None:
1087 return parsed_spec_file
1089 base_root = os.path.join( work_dir, "package" )
1090 for root, dirs, files in os.walk( base_root ):
1091 if root.endswith( ".debug" ):
1093 print "find directory %s " % dirs
1094 for a_file in files:
1095 fake_dbg += os.path.join( root, a_file ).replace( base_root, "" ) + "\n"
1096 #Test don't add dbg files
1097 #return parsed_spec_file + fake_dbg
1099 return parsed_spec_file
1101 def have_macro_configure( self ):
1103 return the number of macro %configure used inn the spec file.
1105 res_macro_configure = 0
1106 raw_build_section = self.get_raw_build_section()
1107 configure_count = raw_build_section.count( "%configure" )
1108 res_macro_configure += configure_count
1109 return res_macro_configure
1111 def have_macro_reconfigure( self ):
1113 return the number of macro %reconfigure used inn the spec file.
1115 res_have_macro_reconfigure = 0
1116 raw_build_section = self.get_raw_build_section()
1117 reconfigure_count = raw_build_section.count( "%reconfigure" )
1119 res_have_macro_reconfigure += reconfigure_count
1120 return res_have_macro_reconfigure
1122 def get_install_section( self ):
1124 return the install section.
1126 res_install_section = "cd ${S}\n"
1128 for line in self.__spect_dico[self.__install_flag][1:]:
1129 res_install_section += line + "\n"
1130 return res_install_section
1132 def get_description( self ):
1134 return the description of the spec file.
1136 for line in self.__spect_dico[self.__introduction_section] :
1137 description = re.findall( RePattern.patternDescription, line )
1138 if len( description ) > 0:
1139 return description[0]
1142 def get_homepage( self ):
1144 return the homepage of the spec file project.
1146 for line in self.__spect_dico[self.__introduction_section] :
1147 description = re.findall( RePattern.patternUrl, line )
1148 if len( description ) > 0:
1149 return description[0]
1152 def get_section( self ):
1154 return the section of the spec file project.
1156 for line in self.__spect_dico[self.__introduction_section] :
1157 description = re.findall( RePattern.patternGroup, line )
1158 if len( description ) > 0:
1159 return description[0]
1160 return "System/Base"
1162 def get_license( self ):
1164 return the licence of the package.
1166 for line in self.__spect_dico[self.__introduction_section] :
1167 description = re.findall( RePattern.patternLicense, line )
1168 if len( description ) > 0:
1169 res_license = description[0]
1170 if ";" in res_license:
1171 res_license = res_license.replace( ";", "" )
1176 def get_section_key(self, __flag):
1178 Return the list of "__flag" sections of the spec file.
1181 for section_key in self.__spect_dico.keys():
1182 if section_key.startswith(__flag):
1183 res_section.append(section_key)
1187 def get_script_section_key_pre(self):
1189 Return the list of pre script section of the spec file.
1190 get_section_key() can't be used in this case since it will also
1191 return the %preun and %prep results.
1193 res_script_section = []
1194 for section_key in self.__spect_dico.keys():
1195 if section_key.startswith("%pre") and \
1196 not section_key.startswith("%preun") and \
1197 not section_key.startswith("%prep"):
1198 res_script_section.append(section_key)
1200 return res_script_section
1202 def get_script_section_key_post(self):
1204 Return the list of post script section of the spec file.
1205 get_section_key() can't be used in this case since it will also
1206 return the %postun results.
1208 res_script_section = []
1209 for section_key in self.__spect_dico.keys():
1210 if section_key.startswith("%post") and not section_key.startswith("%postun"):
1211 res_script_section.append(section_key)
1213 return res_script_section
1215 def get_files_list_from_section( self, package_section_name ):
1217 return a list of file
1220 for line in self.__spect_dico[package_section_name][1:]:
1221 if not line.startswith( "%" ) and not line == "":
1222 line = line.replace( "//", "/" )
1223 res_list.append( line )
1224 elif line.startswith( "%attr(" ):
1225 line = line.replace( "//", "/" )
1226 pkg_f_clean=line.split(")")
1227 pkg_f=pkg_f_clean[-1].strip()
1228 res_list.append( pkg_f )
1229 elif line.startswith( "%doc " ):
1230 line = line.replace( "//", "/" )
1231 res_list.append( line.replace( "%doc ", "" ) )
1232 elif line.startswith( "%dir " ):
1233 line = line.replace( "//", "/" )
1234 res_list.append( line.replace( "%dir ", "" ) )
1235 elif line.startswith( "%config " ):
1236 line = line.replace( "//", "/" )
1237 res_list.append( line.replace( "%config ", "" ) )
1238 elif line.startswith( "%manifest " ):
1239 line = line.replace( "//", "/" )
1240 res_list.append( line.replace( "%manifest ", "" ) )
1241 elif line.startswith( "%config(noreplace) " ):
1242 line = line.replace( "//", "/" )
1243 res_list.append( line.replace( "%config(noreplace) ", "" ) )
1244 elif line.startswith( "%config(" ):
1245 line = line.replace( "//", "/" )
1246 pkg_f_clean=line.split(")")
1247 pkg_f=pkg_f_clean[-1].strip()
1248 res_list.append( pkg_f )
1254 def get_script_from_section(self, __flag):
1256 Return the pre/post script section of the spec file.
1258 res_script_section = ""
1259 if __flag in self.__spect_dico.keys():
1260 for line in self.__spect_dico[__flag][1:]:
1261 res_script_section += line + "\n"
1263 return res_script_section
1265 def get_files_packages( self ):
1267 return a dictinaire with package for key and list of files fo value.
1271 for package_section_name in self.get_section_key("%file"):
1272 tmp_package_name = package_section_name
1273 # Need to get info of the first line.
1274 if "-f " in tmp_package_name:
1275 tmp_split = tmp_package_name.split( "-f " )
1276 tmp_package_name = tmp_split[0]
1278 package = re.findall( RePattern.patternFiles, tmp_package_name )
1279 if len( package ) > 0:
1280 if "-n " in package[0]:
1281 package_name = package[0].replace( "-n ", "" )
1283 package_name = self.__base_name
1284 pkg_ext = package[0].replace( " ", "" )
1285 if len( pkg_ext ) > 0:
1286 package_name += "-" + pkg_ext
1288 package_name = self.__base_name
1290 package_name = package_name.replace( " ", "" )
1291 res_files_list = self.get_files_list_from_section( package_section_name )
1292 res_dico[ package_name ] = res_files_list
1294 #db_src=self.__base_name+"-debugsource"
1295 #if db_src not in res_dico:
1296 # res_dico[db_src] = []
1298 #dbinfo=self.__base_name+"-debug"
1299 #if dbinfo not in res_dico:
1300 # res_dico[dbinfo] = []
1304 def get_name( self ):
1306 return the name of the package
1308 for line in self.__spect_dico[self.__introduction_section]:
1309 description = re.findall( RePattern.patternName, line )
1310 if len( description ) > 0:
1311 return description[0]
1314 def get_provides( self ):
1316 return all provide service by each package of the spec file.
1319 provide_res[self.__base_name] = []
1320 provide_res[self.__base_name].append( [self.__base_name] )
1322 for k in self.__spect_dico.keys():
1323 package = re.findall( RePattern.patternPackage, k )
1324 if len( package ) > 0:
1325 package_name = self.__clean_package_name( package[0] )
1326 provide_res[ package_name ] = []
1327 provide_res[ package_name ].append( [package_name] )
1329 if len( package ) > 0 or ( k == self.__introduction_section ):
1330 for line in self.__spect_dico[k]:
1331 provides = re.findall( RePattern.provides_package, line )
1332 for provides_line in provides:
1333 for tmp_clean in self.__clean_package_line( provides_line ):
1334 if k == self.__introduction_section:
1335 provide_res[self.__base_name].append( tmp_clean )
1337 provide_res[package_name].append( tmp_clean )
1340 def __clean_package_name( self, package_name ):
1342 return the package name from spec declaration.
1344 # re should be better.
1345 if "-n " in package_name:
1346 package_name = package_name.replace( "-n ", "" ).replace( " ", "" )
1348 package_name = self.__base_name + "-" + package_name
1352 def get_rdepends( self ):
1354 return all require service by each package of the spec file.
1358 for k in self.__spect_dico.keys():
1359 package = re.findall( RePattern.patternPackage, k )
1361 if len( package ) > 0:
1362 package_name = self.__clean_package_name( package[0] )
1364 package_name = self.__base_name
1366 if len( package ) > 0 or ( k == self.__introduction_section ):
1367 requires_list = self.get_requires( self.__spect_dico[k] )
1368 rdepends_res[package_name] = requires_list
1372 def get_depends( self ):
1374 return all build require service by each package of the spec file.
1378 for k in self.__spect_dico.keys():
1379 package = re.findall( RePattern.patternPackage, k )
1380 if len( package ) > 0:
1381 package_name = self.__clean_package_name( package[0] )
1383 if len( package ) > 0 or ( k == self.__introduction_section ):
1384 build_requires_list = self.get_build_requires( self.__spect_dico[k] )
1385 if ( k == self.__introduction_section ):
1386 depends_res[self.__base_name] = build_requires_list
1388 depends_res[package_name] = build_requires_list
1393 def __clean_package_line( self, package_line ):
1395 return package list from package declaration in spec file.
1397 res_first = re.findall( RePattern.pkgRe, package_line )
1398 if len( res_first ) == 0:
1399 print "__clean_package_line faild for %s" % self.__package_spec_path
1401 # should be rewrite cleaner.
1403 for init_res in res_first:
1404 init_res = list( init_res )
1405 init_res[0] = init_res[0].replace( ",", "" )
1406 res_final.append( init_res )
1409 def get_build_requires( self, lines ):
1411 return the line of every build requires.
1413 package_replacement = SPEC2YOCTO_CONFIG.get_substitute()
1414 build_requires_res = []
1416 build_requires = re.findall( RePattern.buildRequiresPackage, line )
1417 for tmp_res in build_requires:
1418 for tmp_clean in self.__clean_package_line( tmp_res ):
1419 if len( tmp_clean ) >= 1:
1420 if tmp_clean[0] in package_replacement.keys():
1421 tmp_clean[0] = package_replacement[tmp_clean[0]]
1422 build_requires_res.append( tmp_clean )
1423 return build_requires_res
1425 def get_requires( self, lines ):
1427 return the line of every requires.
1429 package_replacement = SPEC2YOCTO_CONFIG.get_substitute()
1433 build_requires = re.findall( RePattern.requiresPackage, line )
1434 for tmp_res in build_requires:
1435 for tmp_clean in self.__clean_package_line( tmp_res ):
1436 if len( tmp_clean ) >= 1:
1437 if tmp_clean[0] in package_replacement.keys():
1438 tmp_clean[0] = package_replacement[tmp_clean[0]]
1439 requires_res.append( tmp_clean )
1444 meta spec file for generate yocto bb.
1447 mExtraRProvidesDico = {}
1449 mCrossPackageBlacklist = []
1450 mInitialPackageBlacklist = []
1451 mNativePackageBlacklist = []
1452 mOePackageBlacklist = []
1455 package_recipes_dir,
1458 package_git_srv_src,
1459 package_git_srv_path,
1462 init the MetaSpec class
1464 self.__package_recipes_dir = package_recipes_dir
1465 self.__package_name = package_name
1467 self.__package_git_srv_src = package_git_srv_src
1468 self.__package_git_srv_path = package_git_srv_path
1470 self.__package_spec_path = package_spec_path
1471 self.__git_tag = package_git_tag
1473 self.__spec_parser = SpecParser( self.__package_spec_path )
1475 self.__packages_dico = self.__spec_parser.get_files_packages()
1476 self.__provides_dico = self.__spec_parser.get_provides()
1478 self.setm_provided_dico()
1479 self.__rdepends_dico = self.__spec_parser.get_rdepends()
1481 self.__base_file = self.__package_name + ".inc"
1482 #self.__base_depends_file = self.__package_name + "-depends.inc"
1483 #self.__base_rdepends_file = self.__package_name + "-rdepends.inc"
1484 #self.__base_provides_file = self.__package_name + "-rprovides.inc"
1486 self.__extra_conf_file = self.__package_name + "-extraconf.inc"
1487 #self.__extra_native_conf_file = self.__package_name + "-native-extraconf.inc"
1488 #self.__extra_oe_conf_file = self.__package_name + "-oe-extraconf.inc"
1490 self.__git_native_file = self.__package_name + "-native_git.bb"
1491 self.__git_oe_file = self.__package_name + "_git.bb"
1493 self.__createRecipes()
1495 def setm_provided_dico( self ):
1497 add provides_list for package_name to mProvidesDico
1500 for k_provide in self.__provides_dico.keys():
1501 for p_provide in self.__provides_dico[k_provide]:
1502 provides_list.append( p_provide[0] )
1503 for p_provide in self.__packages_dico.keys():
1504 provides_list.extend( self.__packages_dico[p_provide] )
1506 for package in self.__packages_dico.keys():
1507 for pkg_file in self.__packages_dico[package]:
1508 pkgconfig_name_res = re.findall( RePattern.pkgconfig_name, pkg_file )
1509 for tmp_res in pkgconfig_name_res:
1510 provides_list.append( "pkgconfig(%s)" % tmp_res )
1512 MetaSpec.mProvidesDico[self.__package_name] = provides_list
1514 def set_mextra_provided_dico( self ):
1516 add provides_list for package_name to mExtraRProvidesDico
1519 for k_provide in self.__provides_dico.keys():
1520 for p_provide in self.__provides_dico[k_provide]:
1521 provides_list.append( p_provide[0] )
1522 for p_provide in self.__packages_dico.keys():
1523 provides_list.extend( self.__packages_dico[p_provide] )
1525 MetaSpec.mExtraRProvidesDico[self.__package_name] = provides_list
1527 def __create_base_file( self ):
1529 create the base file of the bb file.
1531 bb_path = os.path.join( self.__package_recipes_dir, self.__base_file )
1532 with open( bb_path, "w" ) as file_d:
1534 _description = self.__spec_parser.get_description()
1535 _homepage = self.__spec_parser.get_homepage()
1536 _section = self.__spec_parser.get_section()
1538 _license = self.__spec_parser.get_license()
1540 file_d.write( "DESCRIPTION = \"%s\"\n" % _description )
1541 if len( _homepage ) < 2:
1542 _homepage = "http://nohomepage.org"
1543 file_d.write( "HOMEPAGE = \"%s\"\n" % _homepage )
1544 file_d.write( "SECTION = \"%s\"\n" % _section )
1546 file_d.write( "LICENSE = \"%s\"\n" % _license )
1547 file_d.write( "\n" )
1548 file_d.write( "SRC_URI = \"\"\n" )
1549 file_d.write( "\n" )
1550 file_d.write( "S = \"${WORKDIR}/git\"\n" )
1551 file_d.write( "\n" )
1553 file_d.write( "inherit autotools-brokensep\n" )
1554 file_d.write( "\n" )
1555 file_d.write( "BBCLASSEXTEND = \"\"\n" )
1557 self.__create_provides_file( file_d)
1558 self.__create_rdepends( file_d)
1559 self.__create_depends( file_d)
1561 self.__create_patch( file_d)
1562 self.__create_configure( file_d)
1563 self. __create_compile( file_d)
1564 self.__create_install( file_d)
1566 self.__create_script_file( file_d)
1568 self.__create_files_packaging( file_d )
1570 file_d.write( "require %s\n\n" % self.__extra_conf_file )
1572 def __create_files_packaging(self,file_d):
1573 for package in self.__packages_dico.keys():
1574 pkg_yocto_name=package
1575 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1576 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1578 if pkg_yocto_name not in [self.__package_name+"-dbg",
1579 self.__package_name+"-dev",
1580 self.__package_name+"-doc",
1581 self.__package_name+"-locale",
1582 self.__package_name,
1585 file_d.write( "PACKAGES += \" %s \"\n" % pkg_yocto_name )
1587 file_d.write( "\n" )
1589 package_name = self.__spec_parser.get_name()
1590 _license = self.__spec_parser.get_license()
1592 for package in self.__packages_dico.keys():
1593 pkg_yocto_name=package
1594 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1595 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1597 file_d.write( "%s_files = \"\"\n" % pkg_yocto_name )
1599 # if "-debugsource" in package:
1600 # file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, "/usr/src/debug" ) )
1601 # elif "-debug" in package:
1602 # file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, "/usr/bin/.debug" ) )
1603 # file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, "/bin/.debug" ) )
1604 # file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, "/lib/.debug" ) )
1605 # file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, "/usr/lib/.debug" ) )
1606 # file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, "/sbin/.debug" ) )
1607 # file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, "/usr/sbin/.debug" ) )
1608 # elif "-docs" in package:
1609 # file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, "/usr/share/info" ) )
1610 # file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, "/usr/share/man" ) )
1611 # file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, "/usr/share/man/man*" ) )
1612 # file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, "/usr/share/man/*/man/*" ) )
1613 # file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, "/usr/share/gtk-doc/html/*" ) )
1614 # file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, "/usr/share/info/*\info*" ) )
1616 for pkg_f in self.__packages_dico[package]:
1618 #if pkg_f.startswith("%attr"):
1619 # pkg_f_clean=pkg_f.split(")")
1620 # pkg_f=pkg_f_clean[1].strip()
1621 # file_d.write( "#Remove rpm attribut \"%s)\"\n" % ( pkg_f_clean[0].strip()) )
1623 if pkg_f.startswith( _license ):
1626 pkg_yocto_name = package.replace("-devel","-dev")
1627 file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, pkg_f ) )
1629 file_d.write( "\n" )
1631 for package in self.__packages_dico.keys():
1632 p_parse = package.replace( package_name, "${PN}" )
1633 p_parse = p_parse.replace("-devel","-dev")
1634 pkg_yocto_name = package.replace("-devel","-dev")
1635 file_d.write( "FILES_%s = \"${%s_files}\"\n" % ( p_parse, pkg_yocto_name ) )
1636 file_d.write( "\n" )
1638 for package in self.__packages_dico.keys():
1639 pkg_yocto_name = package.replace("-devel","-dev")
1640 file_d.write( "PKG_%s= \"%s\"\n" % (pkg_yocto_name,pkg_yocto_name) )
1641 file_d.write( "\n" )
1643 def __create_patch( self ,file_d):
1644 code=self.__spec_parser.get_prep_section()
1645 code=code.replace("\n","\n ")
1646 file_d.write( "do_prep() {\n" )
1647 file_d.write( " %s\n" % code )
1648 file_d.write( "}\n" )
1649 file_d.write( "do_patch_append() {\n" )
1650 file_d.write( " bb.build.exec_func('do_prep', d)\n" )
1651 file_d.write( "}\n" )
1652 file_d.write( "\n" )
1654 def __create_configure( self ,file_d):
1655 file_d.write( "do_configure() {\n" )
1656 file_d.write( "}\n" )
1657 file_d.write( "\n" )
1659 def __create_compile( self ,file_d):
1660 code=self.__spec_parser.get_build_section()
1661 code=code.replace("\n","\n ")
1662 file_d.write( "do_compile() {\n" )
1663 file_d.write( " %s\n" % code )
1664 file_d.write( "}\n" )
1665 file_d.write( "\n" )
1667 def __create_install( self ,file_d):
1668 code=self.__spec_parser.get_install_section()
1669 code=code.replace("\n","\n ")
1670 code=code.replace("\n EOF","\nEOF")
1671 file_d.write( "do_install() {\n" )
1672 file_d.write( " echo export RPM_BUILD_ROOT=${D}\n" )
1673 file_d.write( " %s\n" % code )
1674 file_d.write( "}\n" )
1675 file_d.write( "\n" )
1677 def __create_script_file_section_code( self, spec_section):
1679 Returns the command executed in one of the %pre, %post, %preun
1680 or %postun section of a spec file.
1682 code = self.__spec_parser.get_script_from_section(spec_section)
1683 command_list = code.split("\n")
1685 for line in command_list:
1687 formated_code += " " + line + "\n"
1689 return formated_code
1691 def __create_script_file_write( self, file_d, code, recipe_section, package_name):
1693 Writes the pre/post (un)install sections of the recipe.
1695 file_d.write("%s%s() {\n" % (recipe_section, package_name))
1696 file_d.write(" #!/bin/sh -e\n\n")
1697 file_d.write("%s\n" % code)
1701 def __create_script_file_session(self, file_d, flag, script_name, script_sections):
1703 Add script for the given flag.
1705 for section in script_sections:
1707 # If %section is a one line script such as: "%post -p /sbin/ldconfig"
1708 if " -p " in section:
1709 # Remove the package name if present to only keep the command
1710 section_split = section.split(" -p ")[1].split(" -n ")
1711 code = " " + section_split[0].strip()
1713 code = self.__create_script_file_section_code(section)
1715 # Set the package name
1716 package_name = "${PN}"
1717 # If the package name is not the project name
1718 if " -n " in section:
1719 # Remove the command if any to only keep the package name
1720 section_split = section.split(" -n ")[1].split(" -p ")
1721 package_name = section_split[0].strip()
1722 self.__create_script_file_write(file_d, code, script_name, package_name)
1724 def __create_script_file(self, file_d):
1726 Add the pre/post install/uninstall sections of a spec file to
1729 script_sections = self.__spec_parser.get_script_section_key_pre()
1730 self.__create_script_file_session(file_d, "%pre", "pkg_preinst_", script_sections)
1732 script_sections = self.__spec_parser.get_script_section_key_post()
1733 self.__create_script_file_session(file_d, "%post", "pkg_postinst_", script_sections)
1735 script_sections = self.__spec_parser.get_section_key("%preun")
1736 self.__create_script_file_session(file_d, "%preun", "pkg_prerm_", script_sections)
1738 script_sections = self.__spec_parser.get_section_key("%postun")
1739 self.__create_script_file_session(file_d, "%postun", "pkg_postrm_", script_sections)
1741 def __create_provides_file( self ,file_d):
1743 generate provide file.
1745 file_d.write( "PROVIDES = \"\"\n" )
1746 file_d.write( "\n" )
1748 for k_provide in self.__provides_dico.keys():
1749 pkg_yocto_name=k_provide
1750 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1751 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1753 if len( self.__provides_dico[k_provide] ) > 0:
1754 file_d.write( "#PROVIDES by %s \n" % pkg_yocto_name )
1756 for p_provide in self.__provides_dico[k_provide]:
1759 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto ):
1760 pkg_yocto=pkg_yocto.replace("-devel","-dev")
1762 if not len( p_provide ) == 1:
1763 provide_text = "# the PROVIDES rules is ignore \"%s %s %s\"\n"
1764 file_d.write( provide_text % ( pkg_yocto, p_provide[1], p_provide[2] ) )
1766 if ( pkg == "mktemp" and self.__package_name == "tizen-coreutils" ):
1770 if pkg_yocto_name != pkg_yocto:
1771 file_d.write( "PROVIDES += \"%s\"\n" % ( pkg_yocto ) )
1772 file_d.write( "RPROVIDES_%s += \"%s\"\n" % ( pkg_yocto_name, pkg_yocto ) )
1774 #for res_pkg_devel in re.findall( RePattern.paternDevel, pkg ):
1775 # rprovide_text = "RPROVIDES_%s += \"%s\"\n"
1776 # file_d.write( rprovide_text % ( k_provide, res_pkg_devel + "-dev" ) )
1778 if len( self.__provides_dico[k_provide] ) > 0:
1779 file_d.write( "\n\n" )
1781 def __create_git_native_file( self ):
1783 create bb native file.
1785 bb_native_path = os.path.join( self.__package_recipes_dir, self.__git_native_file )
1786 with open( bb_native_path, "w" ) as file_d:
1787 file_d.write( "require %s\n" % self.__base_file )
1788 file_d.write( "\n" )
1789 file_d.write( "PRIORITY = \"9\"\n" )
1790 file_d.write( "\n" )
1791 file_d.write( "inherit native\n" )
1792 file_d.write( "\n" )
1793 file_d.write( "S = \"${WORKDIR}/git\"\n" )
1794 file_d.write( "\n" )
1796 md5_value = "801f80980d171dd6425610833a22dbe6"
1797 file_value = "${COMMON_LICENSE_DIR}/GPL-2.0"
1798 file_chksum_text = "LIC_FILES_CHKSUM ??= \"file://%s;md5=%s\"\n"
1800 file_d.write( file_chksum_text % ( file_value, md5_value ) )
1801 file_d.write( "\n" )
1802 command_source = "SRC_URI += \"%s\"\n" % GIT_COMMAND
1803 file_d.write( command_source % ( self.__package_git_srv_src ,
1804 self.__package_git_srv_path ,
1806 #file_d.write( "require %s\n" % self.__extra_native_conf_file )
1807 file_d.write( "\n" )
1809 def __create_git_oe_file( self ):
1813 bb_path = os.path.join( self.__package_recipes_dir, self.__git_oe_file )
1814 with open( bb_path, "w" ) as file_d:
1815 file_d.write( "require %s\n" % self.__base_file )
1816 file_d.write( "\n" )
1817 file_d.write( "PRIORITY = \"10\"\n" )
1818 file_d.write( "\n" )
1819 md5_value = "801f80980d171dd6425610833a22dbe6"
1820 file_value = "${COMMON_LICENSE_DIR}/GPL-2.0"
1821 file_chksum_text = "LIC_FILES_CHKSUM ??= \"file://%s;md5=%s\"\n"
1823 file_d.write( file_chksum_text % ( file_value, md5_value ) )
1824 file_d.write( "\n" )
1825 command_source = "SRC_URI += \"" + GIT_COMMAND + "\"\n"
1826 file_d.write( command_source % ( self.__package_git_srv_src ,
1827 self.__package_git_srv_path ,
1829 #file_d.write( "require %s\n" % self.__extra_oe_conf_file )
1830 file_d.write( "\n" )
1831 if self.__package_name not in MetaSpec.mNativePackageBlacklist:
1832 file_d.write( "BBCLASSEXTEND += \" native \"" )
1833 file_d.write( "\n\n" )
1835 def __createRecipes( self ):
1837 generate all bb file.
1839 if self.__package_recipes_dir is None:
1842 if not os.path.isdir( self.__package_recipes_dir ):
1843 os.makedirs( self.__package_recipes_dir )
1846 #rdepends_path = os.path.join( self.__package_recipes_dir, self.__base_rdepends_file )
1847 #open( rdepends_path, "a" ).close()
1848 #depends_path = os.path.join( self.__package_recipes_dir, self.__base_depends_file )
1849 #open( depends_path, "a" ).close()
1850 #provides_path = os.path.join( self.__package_recipes_dir, self.__base_provides_file )
1851 #open( provides_path, "a" ).close()
1853 extra_conf_file_path = os.path.join( self.__package_recipes_dir, self.__extra_conf_file )
1854 open( extra_conf_file_path, "a" ).close()
1856 #extranative_path = os.path.join( self.__package_recipes_dir, self.__extra_native_conf_file )
1857 #open( extranative_path, "a" ).close()
1858 #extra_oe_conf_path = os.path.join( self.__package_recipes_dir, self.__extra_oe_conf_file )
1859 #open( extra_oe_conf_path, "a" ).close()
1861 self.__create_base_file()
1863 if not self.__package_name not in MetaSpec.mNativePackageBlacklist:
1864 bb_native_path = os.path.join( self.__package_recipes_dir, self.__git_native_file )
1865 if os.path.isfile( bb_native_path ):
1866 os.unlink( bb_native_path )
1868 #self.__create_provides_file()
1870 if self.__package_name not in MetaSpec.mOePackageBlacklist:
1871 self.__create_git_oe_file()
1873 bb_oe_path = os.path.join( self.__package_recipes_dir, self.__git_oe_file )
1874 if os.path.isfile( bb_oe_path ):
1875 os.unlink( bb_oe_path )
1877 def __create_rdepends( self ,file_d):
1879 generate rdepends file.
1881 if self.__package_recipes_dir is None:
1884 if not os.path.isdir( self.__package_recipes_dir ):
1885 os.makedirs( self.__package_recipes_dir )
1887 #rdepends_path = os.path.join( self.__package_recipes_dir, self.__base_rdepends_file )
1889 package_replacement = SPEC2YOCTO_CONFIG.get_substitute()
1891 if file_d is not None:
1892 file_d.write( "RDEPENDS = \"\"\n" )
1894 for k_provide in self.__rdepends_dico.keys():
1895 pkg_yocto_name=k_provide
1896 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1897 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1899 res_rdepends = set()
1900 k_provide_replace = pkg_yocto_name.replace( self.__package_name, "${PN}" )
1901 if len( self.__rdepends_dico[k_provide] ) > 0:
1902 file_d.write( "#RDEPENDS of %s (%s)\n" % ( pkg_yocto_name, k_provide_replace ) )
1904 for provide in self.__rdepends_dico[k_provide]:
1905 package_provide = provide[0]
1909 for k_package_provide in MetaSpec.mExtraRProvidesDico.keys():
1911 if package_provide in MetaSpec.mExtraRProvidesDico[k_package_provide] \
1912 or package_provide == k_package_provide:
1913 res = k_package_provide
1916 res = package_provide
1918 if res in package_replacement.keys():
1919 res = package_replacement[res]
1921 res_rdepends.add( res )
1923 for pkg in res_rdepends:
1924 res_pkg_devel = re.findall( RePattern.paternDevel, pkg )
1926 if len( res_pkg_devel ) > 0:
1927 rdepends_value = "RDEPENDS_%s += \"%s\"\n"
1928 file_d.write( rdepends_value % ( k_provide_replace, res_pkg_devel[0] + "-dev" ) )
1930 if not pkg in SPEC2YOCTO_CONFIG.get_ignore_rdepend():
1931 file_d.write( "RDEPENDS_%s += \"%s\"\n" % ( k_provide_replace, pkg ) )
1933 if len( self.__rdepends_dico[k_provide] ) > 0:
1934 file_d.write( "\n" )
1936 file_d.write( "\n" )
1938 def __create_depends( self, file_d):
1940 create depends file.
1942 if self.__package_recipes_dir is None:
1945 if not os.path.isdir( self.__package_recipes_dir ):
1946 os.makedirs( self.__package_recipes_dir )
1948 depends_dico = self.__spec_parser.get_depends()
1949 #depends_path = os.path.join( self.__package_recipes_dir, self.__base_depends_file )
1951 ignore_depend_list = SPEC2YOCTO_CONFIG.get_ignore_depend()
1952 native_depend_list = SPEC2YOCTO_CONFIG.get_native_depend()
1953 cross_depend_list = SPEC2YOCTO_CONFIG.get_cross_depend()
1956 if file_d is not None:
1957 file_d.write( "DEPENDS = \"\"\n" )
1960 for k_provide in depends_dico.keys():
1961 if len( depends_dico[k_provide] ) > 0:
1962 file_d.write( "#DEPENDS of %s \n" % k_provide )
1964 for p_provide in depends_dico[k_provide]:
1965 pp_provide = p_provide[0]
1968 if pp_provide in ignore_depend_list:
1971 for k in MetaSpec.mProvidesDico.keys():
1972 if pp_provide in MetaSpec.mProvidesDico[k] or pp_provide == k:
1975 for k_package_provide in MetaSpec.mExtraRProvidesDico.keys():
1976 if pp_provide in MetaSpec.mExtraRProvidesDico[k_package_provide]:
1977 res = k_package_provide
1981 if pp_provide not in SPEC2YOCTO_CONFIG.get_inherit_gettext() and \
1982 pp_provide not in SPEC2YOCTO_CONFIG.get_inherit_python() and \
1983 pp_provide not in SPEC2YOCTO_CONFIG.get_inherit_tizen_cmake() and \
1984 pp_provide not in SPEC2YOCTO_CONFIG.get_inherit_perl() and \
1985 pp_provide not in ignore_depend_list and \
1986 pp_provide not in native_depend_list and \
1987 pp_provide not in cross_depend_list:
1989 erro_msg = "No direct provider for package DEPENDS %s : \"%s\"."
1990 print erro_msg % ( self.__package_name, pp_provide )
1992 if res != self.__package_name :
1993 res_depends.add( res )
1995 # should be from a configue file.
1996 for res in res_depends:
1998 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1999 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
2001 if pkg_yocto_name == "readline-dev":
2002 pkg_yocto_name="readline"
2004 if pkg_yocto_name in SPEC2YOCTO_CONFIG.get_inherit_gettext():
2005 file_d.write( "#Replace \"DEPENDS\" on gettext by \"inherit gettext\"\n" )
2006 file_d.write( "inherit gettext\n" )
2007 elif pkg_yocto_name in native_depend_list:
2008 file_d.write( "DEPENDS_append_class-native = \" %s-native\"\n" % pkg_yocto_name )
2009 file_d.write( "DEPENDS_append_class-target = \" %s-native\"\n" % pkg_yocto_name )
2010 elif pkg_yocto_name in cross_depend_list:
2011 file_d.write( "DEPENDS_append_class-native = \" %s\"\n" % pkg_yocto_name )
2012 file_d.write( "DEPENDS_append_class-target = \" %s-cross\"\n" % pkg_yocto_name )
2013 elif pkg_yocto_name in ignore_depend_list:
2015 elif pkg_yocto_name in SPEC2YOCTO_CONFIG.get_libtool_cross():
2016 file_d.write( "DEPENDS += \"libtool-cross\"\n" )
2017 elif pkg_yocto_name in SPEC2YOCTO_CONFIG.get_inherit_perl():
2018 file_d.write( "inherit perlnative\n" )
2019 elif pkg_yocto_name in SPEC2YOCTO_CONFIG.get_inherit_python():
2020 file_d.write( "inherit pythonnative\n" )
2022 file_d.write( "DEPENDS += \"%s\"\n" % pkg_yocto_name )
2024 file_d.write( "\n" )
2026 def parse_manifest_xml( src ):
2027 primaryFile = open( src, "r" )
2028 primaryXML = primaryFile.read()
2031 aElement = ElementTree.fromstring( primaryXML )
2034 for value in aElement:
2035 for project in value.getiterator():
2036 if project.tag == "project":
2037 name = project.attrib['name']
2038 c_name = clean_name( project.attrib['name'] )
2039 revision = clean_revision( project.attrib['revision'] )
2040 packages_dico[c_name] = [name, revision]
2041 elif project.tag == "default":
2042 remote = project.attrib['remote']
2043 elif project.tag == "remote":
2044 fetch = project.attrib['fetch']
2045 name = project.attrib['name']
2046 review = project.attrib['review']
2050 return remote, packages_dico
2052 class HTTPAccessFailure( Exception ):
2053 '''Indicate the http access failed'''
2055 def download_url( url ):
2058 raise HTTPAccessFailure()
2063 def download_manifest_url( url ):
2066 print "ERROR %s " % url
2067 raise HTTPAccessFailure()
2072 def download_build_xml( url ):
2073 return download_url( url + "/builddata/build.xml" )
2075 def get_project_id( xml ):
2076 aElement = ElementTree.fromstring( xml )
2078 for value in aElement:
2079 for project in value.getiterator():
2080 if project.tag == "id":
2083 def get_project_arch( xml ):
2084 aElement = ElementTree.fromstring( xml )
2086 for value in aElement:
2087 for project in value.getiterator():
2088 if project.tag == "archs":
2089 for arch in project.getiterator():
2090 if arch.tag == "arch":
2091 arch_list.append( arch.text )
2096 def clean_name( raw_name ):
2098 raw_name = raw_name.replace( "_", "-" )
2101 return raw_name.split( "/" )[-1]
2105 def clean_revision( raw_name ):
2107 return raw_name.split( "-" )[0]
2111 def patch_the_spec_file( package_spec_path,
2116 if not package_spec_path == dest_spec_path:
2117 shutil.copy2( package_spec_path, dest_spec_path )
2119 if dest_spec_dir.endswith( "/packaging" ):
2120 dest_spec_dir = dest_spec_dir[:-len( "/packaging" )]
2122 patch_command = "patch -s -p1 --fuzz=2 -d %s -i %s" % ( dest_spec_dir, patch_path )
2124 a_sub_command = SubprocessCrt()
2125 res = a_sub_command.exec_subprocess( patch_command )
2128 msg = "The patch \"%s\" can't be apply in directory \"%s\"."
2129 msg = msg % ( patch_path, dest_spec_dir )
2130 print >> sys.stderr, colorize( msg, "red" )
2131 print >> sys.stderr, colorize( "command: \"%s\"" % patch_command, "red" )
2134 return dest_spec_path
2137 def specfile_patcher( package_spec_path, project, package_name_list , dest_spec_path ):
2138 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( project )
2139 source_spec_patch_dir = os.path.join( working_dir, "specfile-patch" )
2141 patch_path_list = findSpecPatchFiles( source_spec_patch_dir, package_name_list )
2143 if len( patch_path_list ) > 0:
2145 dest_spec_dir = os.path.dirname( dest_spec_path )
2146 if not os.path.isdir( dest_spec_dir ):
2147 os.makedirs( dest_spec_dir )
2149 for patch_path in patch_path_list:
2150 package_spec_path = patch_the_spec_file( package_spec_path,
2155 return package_spec_path
2159 def __init__( self, project, name, path, revision, priority, git_src ):
2160 self.__project = project
2162 self.git_path = path
2163 self.git_revision = revision
2164 self.priority = priority
2165 self.git_src = git_src
2166 self.__my_meta_spec = None
2168 def printMe( self ):
2169 print "%s %s %s %s" % ( self.name , self.git_path, self.git_revision, self.git_src )
2171 def create_MetaSpec( self , package_recipes_dir, source_spec_dir ):
2172 source_path = os.path.join( source_spec_dir , self.name , "packaging" )
2173 package_spec_path = findBestSpecFile( source_path, self.name )
2175 if package_spec_path == -1:
2176 msg = "no initial spec file for package \"%s\" in directory \"%s\"."
2177 msg = msg % ( self.name, source_path )
2178 print >> sys.stderr, colorize( msg, "red" )
2181 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( self.__project )
2182 specfile_patched_dir = os.path.join( working_dir, "specfile-patched" )
2183 dest_spec_dir = os.path.join( specfile_patched_dir , self.name )
2184 dest_spec_packaging_dir = os.path.join( dest_spec_dir , "packaging" )
2185 dest_spec_path = os.path.join( dest_spec_packaging_dir ,
2186 os.path.basename( package_spec_path ) )
2189 package_spec_path = specfile_patcher( package_spec_path,
2191 [self.name, self.name + "-initial"],
2194 self.__my_meta_spec = MetaSpec( os.path.join( package_recipes_dir, self.name ),
2201 def make_alias_package( project, packages_dico ):
2203 #TO DO need to be do in conf file.
2204 alias_package["python-libxml2"] = "libxml2"
2205 alias_package["python-magic"] = "file"
2206 alias_package["cross-arm-binutils"] = "binutils"
2207 alias_package["cross-armv7hl-gcc47-icecream-backend"] = "gcc47"
2208 alias_package["libffi47"] = "gcc47"
2210 for alias in alias_package.keys():
2211 alias_to = alias_package[alias]
2212 if alias_to in packages_dico.keys() and alias not in packages_dico.keys():
2213 a_package_def = packages_dico[alias_to]
2214 packages_dico[alias] = package_def( project,
2216 a_package_def.git_path,
2217 a_package_def.git_revision,
2218 a_package_def.priority,
2219 a_package_def.git_src )
2221 return packages_dico
2223 class manifestCollection:
2225 class for all package in a distro.
2227 def __init__( self , project ):
2231 self.__my_project = project
2233 self.__recipes_list = None
2235 if not SPEC2YOCTO_CONFIG.is_valide_project( self.__my_project ):
2236 msg = "\"%s\" has no configuration in file \"%s\"."
2237 msg = msg % ( self.__my_project, CONFIGURATION_FILE_PATH )
2238 print >> sys.stderr, colorize( msg, "red" )
2241 #Just get the list of manifest uri.
2242 self.__my_manifest_meta_list = SPEC2YOCTO_CONFIG.get_manifest_meta_list( self.__my_project )
2244 self.__my_manifest_file_list = {}
2245 #Load the project manifest.
2246 self.__update_meta_manifests()
2248 self.__my_package_dico = {}
2249 self.__generate_package()
2251 self.__my_package_dico = make_alias_package( self.__my_project, self.__my_package_dico )
2253 def parse_manifest_xml( self, src ):
2254 primaryFile = open( src, "r" )
2255 primaryXML = primaryFile.read()
2258 aElement = ElementTree.fromstring( primaryXML )
2261 for value in aElement:
2262 for project in value.getiterator():
2263 if project.tag == "project":
2264 name = project.attrib['name']
2265 short_name=clean_name( name )
2266 revision = clean_revision( project.attrib['revision'] )
2267 packages_dico[short_name] = [name, revision]
2268 elif project.tag == "default":
2269 remote = project.attrib['remote']
2270 elif project.tag == "remote":
2271 fetch = project.attrib['fetch']
2272 name = project.attrib['name']
2276 return remote, packages_dico
2278 def print_list( self ):
2279 pkg_list = self.__my_package_dico.keys()
2281 for package in pkg_list:
2282 self.__my_package_dico[package].printMe()
2284 def __generate_package( self ):
2285 for meta_manifest in self.__my_manifest_file_list.keys():
2286 manifest_uri = self.__my_manifest_file_list[meta_manifest]
2287 manifest_git = SPEC2YOCTO_CONFIG.get_manifest_default_git_src( meta_manifest )
2288 manifest_priority = SPEC2YOCTO_CONFIG.get_manifest_priority( meta_manifest )
2289 remote, packages_dico = self.parse_manifest_xml( manifest_uri )
2291 if manifest_git is not None:
2292 remote = manifest_git
2294 whitelist = SPEC2YOCTO_CONFIG.get_whitelist( self.__my_project )
2295 if len( whitelist ) != 0:
2296 list_packages = set(whitelist)
2298 list_packages = set(packages_dico.keys())
2300 blacklist = set(SPEC2YOCTO_CONFIG.get_blacklist( self.__my_project ))
2302 list_packages=list_packages.difference(blacklist)
2304 for package in list_packages:
2305 if package in packages_dico.keys():
2306 [path, revision] = packages_dico[package]
2308 if package in self.__my_package_dico.keys():
2309 if manifest_priority > self.__my_package_dico[package].priority:
2310 self.__my_package_dico[package] = package_def( self.__my_project,
2316 elif manifest_priority == self.__my_package_dico[package].priority:
2317 msg = "most of one occurence of package \"%s\" ."
2318 msg = msg % ( package )
2319 print >> sys.stderr, colorize( msg, "red" )
2322 self.__my_package_dico[package] = package_def( self.__my_project,
2328 for package in whitelist:
2329 if package not in self.__my_package_dico.keys():
2330 msg = "package \"%s\" is in the white list but not in the manifest."
2331 msg = msg % ( package )
2332 print >> sys.stderr, colorize( msg, "red" )
2335 def __update_meta_manifests( self ):
2337 find/download all manifest.xml file.
2339 for meta_manifest in self.__my_manifest_meta_list:
2340 meta_manifest_uri = SPEC2YOCTO_CONFIG.get_manifest_uri( meta_manifest )
2341 if meta_manifest_uri is None:
2342 msg = "\"%s\" has no URI configuration in file \"%s\"."
2343 msg = msg % ( meta_manifest_uri, CONFIGURATION_FILE_PATH )
2344 print >> sys.stderr, colorize( msg, "red" )
2346 if meta_manifest_uri.startswith( "http" ):
2347 if meta_manifest_uri.endswith( ".xml" ):
2348 meta_manifest_url_path = meta_manifest_uri
2349 manifest_name = os.path.basename(meta_manifest_uri)
2351 xml_str = download_build_xml( meta_manifest_uri )
2352 project_id = get_project_id( xml_str )
2353 list_arch = get_project_arch( xml_str )
2355 arch = SPEC2YOCTO_CONFIG.get_project_arch( self.__my_project )
2357 if ( arch == "i586" ) and ( "ia32" in list_arch ):
2359 elif ( arch is None ) and ( len( list_arch ) > 0 ):
2361 elif ( arch not in list_arch ):
2364 manifest_name = "%s_%s.xml" % ( project_id, arch )
2365 meta_manifest_url_path = "%s/builddata/manifest/%s"
2366 meta_manifest_url_path = meta_manifest_url_path % ( meta_manifest_uri,
2369 manifest_xml = download_manifest_url( meta_manifest_url_path )
2370 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( self.__my_project )
2372 meta_manifest_dir = os.path.join( working_dir, "manifest_file" )
2373 meta_manifest_path = os.path.join( meta_manifest_dir, manifest_name )
2375 if not os.path.isdir( meta_manifest_dir ):
2376 os.makedirs( meta_manifest_dir )
2378 with open( meta_manifest_path, "w" ) as manifest_xml_file:
2379 manifest_xml_file.write( manifest_xml )
2381 if not os.path.isfile( meta_manifest_uri ):
2382 msg = "In the project \"%s\" the manifest \"%s\" is not a valid file."
2383 msg = msg % ( self.__my_project, meta_manifest_uri )
2384 print >> sys.stderr, colorize( msg, "red" )
2387 meta_manifest_path = meta_manifest_uri
2389 self.__my_manifest_file_list[ meta_manifest ] = meta_manifest_path
2391 def createRecipes( self ):
2395 self.__recipes_dir_dest = SPEC2YOCTO_CONFIG.get_recipes_sources_directory( self.__my_project )
2397 self.__clean_old_bb_files(self.__recipes_dir_dest)
2399 if self.__recipes_dir_dest is None:
2400 msg = "In the project \"%s\" recipes_dir_sources is not define."
2401 msg = msg % ( self.__my_project )
2402 print >> sys.stderr, colorize( msg, "red" )
2404 elif not os.path.isdir( self.__recipes_dir_dest ):
2405 os.makedirs( self.__recipes_dir_dest )
2407 self.__meta_spec_dico = {}
2408 self.__meta_spec_boot_strap_dico = {}
2410 self.__set_oe_package_blacklist()
2411 self.__set_native_package_blacklist()
2413 self.__init_depends()
2414 self.__init_MetaSpec()
2417 def __clean_old_bb_files( self ,path):
2418 for root, dirs, files in os.walk(path):
2419 for a_file in files:
2420 if a_file.endswith(".bb"):
2421 os.unlink( os.path.join(path, root, a_file) )
2424 def __set_oe_package_blacklist( self ):
2426 load oe_package_blacklist
2428 list_package = SPEC2YOCTO_CONFIG.get_runtime_blacklist( self.__my_project )
2429 MetaSpec.mOePackageBlacklist.extend( list_package )
2431 def __set_native_package_blacklist( self ):
2433 load oe_package_blacklist
2435 list_package = SPEC2YOCTO_CONFIG.get_native_blacklist( self.__my_project )
2436 MetaSpec.mNativePackageBlacklist.extend( list_package )
2439 def __init_MetaSpec( self ):
2440 pkg_list = self.__my_package_dico.keys()
2443 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( self.__my_project )
2444 source_spec_dir = os.path.join( working_dir, "specfile-initial" )
2446 for package in pkg_list:
2447 self.__my_package_dico[package].create_MetaSpec( self.__recipes_dir_dest,
2450 def __init_depends( self ):
2454 self.__load_package_provided_extra()
2456 pkg_list = self.__my_package_dico.keys()
2459 def __load_package_provided_extra( self ):
2461 load_package_provided_extra
2463 provided_extra_dico = SPEC2YOCTO_CONFIG.get_provided_extra( self.__my_project )
2465 for k_package in provided_extra_dico.keys():
2466 raw_list=provided_extra_dico[k_package]
2468 if k_package not in MetaSpec.mProvidesDico.keys():
2469 MetaSpec.mProvidesDico[k_package] = []
2471 MetaSpec.mProvidesDico[k_package].extend( raw_list )
2473 if k_package not in MetaSpec.mExtraRProvidesDico.keys():
2474 MetaSpec.mExtraRProvidesDico[k_package] = []
2475 MetaSpec.mExtraRProvidesDico[k_package].extend( raw_list )
2477 TERMINAL_COLORS = {"black": "\033[30;1m",
2478 "red": "\033[31;1m",
2479 "green": "\033[32;1m",
2480 "yellow": "\033[33;1m",
2481 "blue": "\033[34;1m",
2482 "magenta": "\033[35;1m",
2483 "cyan": "\033[36;1m",
2484 "white": "\033[37;1m",
2485 "default": "\033[0m"}
2487 def colorize( text, color = "green" ):
2489 Return a colorized copy of `text`.
2490 See Utils.TERMINAL_COLORS.keys() for available colors.
2492 return TERMINAL_COLORS.get( color, "" ) + text + TERMINAL_COLORS["default"]
2495 def check_group_file( project ):
2496 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( project )
2498 group_uri = SPEC2YOCTO_CONFIG.get_group_uri( project )
2500 if group_uri.startswith( "http" ):
2501 group_file_path = os.path.join( working_dir, "group/group.xml" )
2502 group_xml = download_url( group_uri )
2504 with open( group_file_path, "w" ) as group_file:
2505 group_file.write( group_xml )
2507 return group_file_path
2511 def parse_group_xml( src ):
2512 groupFile = open( src, "r" )
2513 groupXML = groupFile.read()
2516 aElement = ElementTree.fromstring( groupXML )
2519 for group in aElement:
2520 if group.tag == "group":
2523 for element in group:
2524 if element.tag == "name":
2525 group_name = element.text
2526 elif element.tag == "packagelist":
2527 for packagereq in element:
2528 list_package.append(packagereq.text)
2530 packages_dico[group_name]=list_package
2531 return packages_dico
2533 def dump_group(project,group_dico):
2535 recipes_group_directory = SPEC2YOCTO_CONFIG.get_recipes_group_directory( project )
2537 for group in group_dico.keys():
2538 group_str = group.replace( " ", "-" )
2539 path = os.path.join( recipes_group_directory, "packagegroup-tizen-%s.bb" % group_str )
2541 with open(path,"w") as group_file:
2542 group_file.write( "SUMMARY = \"%s\"\n" % group )
2543 group_file.write( "DESCRIPTION = \"%s\"\n" % group )
2544 group_file.write( "LICENSE = \"MIT\"\n" )
2545 group_file.write( "DEPENDS = \"virtual/kernel\"\n" )
2546 group_file.write( "PR = \"r1\"\n" )
2548 group_file.write( "inherit packagegroup\n" )
2549 group_file.write( "\n" )
2550 group_file.write( "PACKAGE_ARCH = \"${MACHINE_ARCH}\"\n" )
2551 group_file.write( "\n" )
2553 group_file.write( "RDEPENDS_${PN} = \"\" \n\n" )
2554 for pkg in group_dico[group]:
2555 group_file.write( "RDEPENDS_${PN} += \"%s\"\n" % pkg )
2557 def generateBuildStatus( project_path ):
2560 if not os.path.isdir( project_path ):
2561 msg = "The path \"%s\" is not a directory."
2562 msg = msg % ( project_path )
2563 print >> sys.stderr, colorize( msg, "red" )
2566 for package_path in os.listdir( project_path ):
2567 project_full_path = os.path.join( project_path, package_path )
2568 if ( package_path == "build_stats" ) and os.path.isfile( project_full_path ) :
2571 elif os.path.isdir( project_full_path ):
2572 BN, PV, PR = cleanPackageName( package_path )
2573 res_status = check_package_status( project_full_path )
2575 if BN.endswith("-native"):
2576 res_native[BN] = [PV ] + res_status
2578 res[BN] = [PV ] + res_status
2581 elif package_path in ["."]:
2585 msg = "This directory should not contain the file \"%s\"."
2586 msg = msg % ( package_path )
2587 print >> sys.stderr, colorize( msg, "red" )
2590 return res_native, res
2592 def cleanPackageName( package_path ):
2593 if package_path.count( "-" ) < 2:
2594 msg = "unknow format for package \"%s\"."
2595 msg = msg % ( package_path )
2596 print >> sys.stderr, colorize( msg, "red" )
2599 PR=package_path[package_path.rindex("-")+1:]
2600 package_path=package_path[:package_path.rindex("-")]
2601 PV=package_path[package_path.rindex("-")+1:]
2602 BN=package_path[:package_path.rindex("-")]
2607 def check_package_status( project_full_path ):
2608 tasks_order = ["do_fetch",
2615 "do_populate_sysroot",
2618 "do_package_write_rpm",
2622 for package_task in os.listdir( project_full_path ):
2623 if package_task in tasks_order:
2624 task_index = tasks_order.index( package_task )
2626 if task_index > max_index:
2627 max_index = task_index
2630 msg = "No log task in \"%s\"."
2631 msg = msg % ( project_full_path )
2632 print >> sys.stderr, colorize( msg, "red" )
2635 last_task = tasks_order[max_index][3:]
2639 with open( os.path.join( project_full_path, tasks_order[max_index] ) ) as status_file:
2640 for line in status_file:
2641 if line.startswith( "Status: " ):
2642 status = line[len( "Status: " ):].replace( "\n", "" ).replace( " ", "" )
2644 if last_task == "package_write_rpm" and status == "PASSED":
2647 return [last_task, status]
2649 def clean_Packagegroup( project,group_dico ):
2652 package_replacement = SPEC2YOCTO_CONFIG.get_substitute( project )
2654 for group in group_dico.keys():
2655 group_dico_tmp[group] = []
2656 for package in group_dico[group]:
2657 if package in package_replacement.keys():
2658 group_dico_tmp[group].append( package_replacement[package] )
2660 group_dico_tmp[group].append( package )
2662 return group_dico_tmp
2665 def check_debugmode( opts_debug ):
2667 if opts_debug == "no":
2669 elif opts_debug == "yes":
2673 class spec2yoctoCommandline( cmdln.Cmdln ):
2677 def do_manifestToList( self, subcmd, opts, project = None ):
2678 """${cmd_name}: print the list of package in projects.
2684 project = SPEC2YOCTO_CONFIG.get_current_project()
2686 pkg_co = manifestCollection( project )
2689 def do_createRecipes( self, subcmd, opts, project = None ):
2690 """${cmd_name}: create all packages recipes.
2696 project = SPEC2YOCTO_CONFIG.get_current_project()
2698 pkg_co = manifestCollection( project )
2699 pkg_co.createRecipes()
2701 @cmdln.option( "--package_pn",
2704 help = "select the package_pn." )
2705 def do_findBestSpecFile( self, subcmd, opts, package_path ):
2706 """${cmd_name}: print the speec file associate to package.
2711 res = findBestSpecFile( package_path, opts.package_pn )
2714 @cmdln.option( "--package_pn",
2717 help = "select the package_pn." )
2718 def do_findSpecPatchFiles( self, subcmd, opts, patch_dir, ):
2719 """${cmd_name}: print patch from "specfile-patch" directory associate to package.
2724 res = findSpecPatchFiles( patch_dir, opts.package_pn )
2725 print " ".join( res )
2727 @cmdln.option( "--package_pn",
2730 help = "select the package_pn." )
2731 @cmdln.option( "--project",
2734 help = "select the package_pn." )
2735 def do_specfile_patcher( self, subcmd, opts, package_spec_path ):
2736 """${cmd_name}: patch the spec file with patch from "specfile-patch" directory.
2741 if opts.project is None:
2742 project = SPEC2YOCTO_CONFIG.get_current_project()
2744 project = opts.project
2746 res = specfile_patcher( package_spec_path, project, opts.package_pn, package_spec_path )
2749 def do_createPackagegroup( self, subcmd, opts, project = None ):
2750 """${cmd_name}: print the list of package in projects.
2756 project = SPEC2YOCTO_CONFIG.get_current_project()
2759 res = SPEC2YOCTO_CONFIG.get_group( project )
2760 group_file_path = check_group_file( project )
2761 group_dico= parse_group_xml( group_file_path )
2763 group_dico = clean_Packagegroup( project, group_dico )
2765 dump_group(project,group_dico)
2767 @cmdln.option( "--debug",
2770 help = "run the in debug mode.[yes/no]" )
2771 @cmdln.option( "--project",
2774 help = "select the project." )
2775 @cmdln.option( "--package_pn",
2778 help = "select the package_pn." )
2779 def do_prep( self, subcmd, opts, spec_path ):
2780 """${cmd_name}: print the bash code of the %prep section of a spec file.
2785 check_debugmode( opts.debug )
2787 if opts.project is None:
2788 project = SPEC2YOCTO_CONFIG.get_current_project()
2790 project = opts.project
2792 res = SpecParser( spec_path, package_pn = opts.package_pn ).get_prep_section()
2796 @cmdln.option( "--debug",
2799 help = "run the in debug mode.[yes/no]" )
2800 @cmdln.option( "--project",
2803 help = "select the project." )
2804 @cmdln.option( "--package_pn",
2807 help = "select the package_pn." )
2808 def do_compile( self, subcmd, opts, spec_path ):
2809 """${cmd_name}: print the bash code of the %build section of a spec file.
2814 check_debugmode( opts.debug )
2816 if opts.project is None:
2817 project = SPEC2YOCTO_CONFIG.get_current_project()
2819 project = opts.project
2821 res = SpecParser( spec_path, package_pn = opts.package_pn ).get_build_section()
2825 @cmdln.option( "--debug",
2828 help = "run the in debug mode.[yes/no]" )
2829 @cmdln.option( "--project",
2832 help = "select the project." )
2833 @cmdln.option( "--package_pn",
2836 help = "select the package_pn." )
2837 def do_install( self, subcmd, opts, spec_path ):
2838 """${cmd_name}: print the bash code of the %install section of a spec file.
2843 check_debugmode( opts.debug )
2846 if opts.project is None:
2847 project = SPEC2YOCTO_CONFIG.get_current_project()
2849 project = opts.project
2851 res = SpecParser( spec_path, package_pn = opts.package_pn ).get_install_section()
2855 @cmdln.option( "--debug",
2858 help = "run the in debug mode.[yes/no]" )
2859 def do_generateBuildStatus( self, subcmd, opts, project_path ):
2860 """${cmd_name}: print the status and the the build state of packages,
2861 builded in a single command.
2863 build/tmp-eglibc/buildstats/core-image-minimal-qemux86/XXXX/
2867 check_debugmode( opts.debug )
2869 res_native, res = generateBuildStatus( project_path )
2871 res_native_keys = res_native.keys()
2872 res_keys = res.keys()
2874 res_native_keys.sort()
2877 for r in res_native_keys:
2878 print r + "\t" + "\t".join( res_native[r] )
2881 print r + "\t" + "\t".join( res[r] )
2884 @cmdln.option( "--debug",
2887 help = "run the in debug mode.[yes/no]" )
2888 def do_generatePseudoSpecfile( self, subcmd, opts, spec_path ):
2889 """${cmd_name}: generate a spec file use by yocto, for packaging rpm.
2894 check_debugmode( opts.debug )
2896 a_spec_parser = SpecParser( spec_path )
2897 a_spec_parser.parse_raw_spec_file()
2898 res = a_spec_parser.get_clean_raw()
2902 @cmdln.option( "--debug",
2905 help = "run the in debug mode.[yes/no]" )
2906 @cmdln.option( "--project",
2909 help = "select the project." )
2910 def do_working_dir( self, subcmd, opts ):
2911 """${cmd_name}: return the proto directory.
2916 check_debugmode( opts.debug )
2918 if opts.project is None:
2919 project = SPEC2YOCTO_CONFIG.get_current_project()
2921 project = opts.project
2923 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( project )
2924 if working_dir != 1:
2928 commandline = spec2yoctoCommandline()
2931 res = commandline.main()
2932 except ValueError as ve:
2934 print >> sys.stderr, colorize( str( ve ), "red" )
2936 except EnvironmentError as ioe:
2937 # commandline.do_help([sys.argv[0]])
2939 print >> sys.stderr, colorize( str( ioe ), "red" )
2940 if hasattr( ioe, "spec2yocto_config_error" ):
2941 msg = "See '--config' option"
2942 print >> sys.stderr, colorize( msg, "red" )
2944 # except Exception as e_all :
2946 # print >> sys.stderr, colorize( str( e_all ), "red" )
2950 if __name__ == '__main__':