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.
20 Created on 05 fevr. 2013
22 @author: ronan@fridu.net
29 RECIPES_SOURCE_DIR = os.path.dirname( os.path.realpath( __file__ ) )
30 RECIPES_DIR_DEST = os.path.join( RECIPES_SOURCE_DIR, "../meta-tizen-ivi" )
31 GIT_COMMAND = "git://%s/%s;tag=%s;nobranch=1"
36 from urllib import urlopen
37 from xml.etree import ElementTree
42 print >> sys.stderr, 'Error spec2yocto require "python-cmdln" please install it.'
57 # Very useful to debug spec2yocto, print the subprocess EXEC_COMMAND line.
60 CONFIGURATION_FILE_PATH = os.path.expanduser( os.path.join( "~", ".spec2yoctorc" ) )
62 class Spec2yoctoConfig( object ):
64 Parse the file "spec2yocto_configure",
68 self.__config_parser = ConfigParser.ConfigParser()
69 self.__config_parser.optionxform = str
71 if not os.path.isfile( CONFIGURATION_FILE_PATH ):
72 print >> sys.stderr, "Warning CONFIGURATION_FILE_PATH \"%s\" do not exist." % (CONFIGURATION_FILE_PATH)
73 print >> sys.stderr," a sample is available in directory \"proto-meta-Tizen_generic/.spec2yoctorc\""
76 self.__config_file = open( CONFIGURATION_FILE_PATH , 'rw' )
78 self.__config_parser.readfp( self.__config_file )
80 def get_current_project( self ):
82 return the list of the manifest_meta, manifest_meta can be a file or URL.
85 return self.__get_value( "project", "current" , None )
87 def get_manifest_meta_list( self, projet ):
89 return the list of the manifest_meta, manifest_meta can be a file or URL.
91 meta_manifests_res = []
92 list_of_meta_manifest = self.__get_list( projet, "manifest", [] )
93 for meta_manifest in list_of_meta_manifest:
94 meta_manifests_res.append( meta_manifest.replace( " ", "" ) )
96 return meta_manifests_res
98 def get_manifest_uri( self, meta_manifest ):
100 return the uri of the manifest.
102 res = self.__get_value( meta_manifest, "uri" , None )
103 res = os.path.expanduser( res )
104 res = os.path.expandvars( res )
107 def get_manifest_priority( self, meta_manifest ):
109 return the priority of the manifest.
111 return self.__get_value( meta_manifest, "priority" , 0 )
113 def get_manifest_default_git_src( self, meta_manifest ):
115 return the default_git_src of the manifest.
117 return self.__get_value( meta_manifest, "default_git_src" , None )
119 def is_valide_project( self, projet ):
121 check if project is configurate in the conf file.
123 return ( projet in self.__config_parser.sections() )
125 def get_project_arch( self, projet ):
127 return the default arch of the project.
129 return self.__get_value( projet, "arch", None )
131 def get_working_dir( self, projet ):
133 return the working dir of the project.
135 res = self.__get_value( projet, "working_dir", "/tmp" )
137 res = os.path.expanduser( res )
138 res = os.path.expandvars( res )
141 def get_list(self, project, list_name):
143 Returns the corresponding list.
145 res_list = self.__get_list( project, list_name, [] )
147 for element in res_list:
148 res.extend(self.__get_list(element, "list", []))
151 def get_substitute( self , project = None ):
154 for package in self.__config_parser.options( "substitute" ):
155 package_replace = self.__get_value( "substitute", package, None )
156 if package_replace is not None:
157 res[package] = package_replace
160 def __get_list( self, section, option, default_value ):
162 generic fonction to get list value.
164 if ( section in self.__config_parser.sections() ) and \
165 ( option in self.__config_parser.options( section ) ):
166 tmp_res = str( self.__config_parser.get( section, option ) )
167 return tmp_res.replace( " ", "" ).split( "," )
171 def __get_value( self, section, option, default_value ):
173 generic fonction to get value.
175 if ( section in self.__config_parser.sections() ) and \
176 ( option in self.__config_parser.options( section ) ):
177 tmp_res = self.__config_parser.get( section, option )
182 def get_recipes_sources_directory( self, project ):
184 return a list of the recipes directory needed to build the image.
186 res = self.__get_value( project, 'recipes_dir_sources', None )
187 res = os.path.expanduser( res )
188 res = os.path.expandvars( res )
191 def get_recipes_group_directory( self, project ):
192 res = self.__get_value( project, 'recipes_dir_group', None )
193 res = os.path.expanduser( res )
194 res = os.path.expandvars( res )
198 def get_group( self , project = None ):
200 project = self.get_current_project()
201 return self.__get_list( project, 'group', [] )
204 def get_target_cpu( self , project = None ):
209 project = self.get_current_project()
210 return self.__get_value( project, 'arch' , None )
212 def get_bb_autoreconf_blacklist( self , project = None ):
214 return a list of package with no autoreconf.
217 project = self.get_current_project()
219 blacklist_list = self.__get_list( project, "blacklist_autoreconf", [] )
221 for blacklist in blacklist_list:
222 res.extend( self.__get_list( blacklist, "blacklist", [] ) )
226 def get_provided_extra( self , project = None ):
229 project = self.get_current_project()
231 provided_extra_list = self.__get_list( project, "provided-extra", [] )
232 provided_extra_dico={}
233 for provided_extra in provided_extra_list:
234 for package in self.__config_parser.options( provided_extra ):
235 provided_list = self.__get_list( provided_extra, package, [] )
236 provided_extra_dico[package] = provided_list
237 return provided_extra_dico
240 def get_ignore_depend( self ):
242 return the ignore package to ignore for depends (build require).
244 return self.__get_list( 'depends', 'ignore', [] )
246 def get_ignore_rdepend( self ):
248 return the ignore package to ignore for rdepends (require).
250 return self.__get_list( 'rdepends', 'ignore', [] )
252 def get_native_depend( self ):
254 some buildRequire mean depends on native package not runtime.
256 return self.__get_list( 'depends', 'native', [] )
258 def get_cross_depend( self ):
260 some buildRequire mean depends on native package not runtime.
262 return self.__get_list( 'depends', 'cross', [] )
264 def get_libtool_cross( self ):
266 some buildRequire mean depends on libtool-cross package not runtime.
268 return self.__get_list( 'depends', 'libtool_cross', [] )
270 def get_inherit_gettext( self ):
272 some buildRequire mean inherit_gettext package not depends runtime.
274 return self.__get_list( 'depends', 'inherit_gettext', [] )
276 def get_inherit(self, package):
278 some buildRequire mean inherit_cmake package not depends runtime.
282 def get_group_uri( self, project ):
284 return self.__get_value( project, 'group_uri', None )
287 SPEC2YOCTO_CONFIG = Spec2yoctoConfig()
289 # Implementation taken from http://hetland.org
290 def levenshtein( a, b ):
291 """Calculates the Levenshtein distance between a and b."""
292 n, m = len( a ), len( b )
294 # Make sure n <= m, to use O(min(n,m)) space
298 current = range( n + 1 )
299 for i in range( 1, m + 1 ):
300 previous, current = current, [i] + [0] * n
301 for j in range( 1, n + 1 ):
302 add, delete = previous[j] + 1, current[j - 1] + 1
303 change = previous[j - 1]
304 if a[j - 1] != b[i - 1]:
306 current[j] = min( add, delete, change )
310 def get_packaging_files( package_path ):
312 for tmp_res in os.listdir( package_path ):
313 if tmp_res.endswith( ".spec" ) and os.path.isfile( package_path + "/" + tmp_res ):
314 res.append( tmp_res )
317 def findBestSpecFile( package_path, package_name ):
319 Find the name of the spec file which matches best with `package_name`
322 package_spec_dir = package_path
323 package_spec_dir = os.path.expanduser( package_spec_dir )
324 package_spec_dir = os.path.expandvars( package_spec_dir )
326 specFileList = get_packaging_files( package_path )
329 if len( specFileList ) < 1:
330 # No spec file in list
332 elif len( specFileList ) == 1:
334 specFile = specFileList[0]
337 for spec in specFileList:
338 if str( spec[:-5] ) == str( package_name ):
339 # This spec file has the same name as the package
342 elif spec.startswith( package_name ):
343 # This spec file has a name which looks like the package
344 sameStart.append( spec )
347 if len( sameStart ) > 0:
348 # Sort the list of 'same start' by the Levenshtein distance
349 sameStart.sort( key = lambda x: levenshtein( x, package_name ) )
350 specFile = sameStart[0]
352 # No spec file starts with the name of the package,
353 # sort the whole spec file list by the Levenshtein distance
354 specFileList.sort( key = lambda x: levenshtein( x, package_name ) )
355 specFile = specFileList[0]
358 msg = "Found no spec file matching package name '%s'" % package_name
362 spec_full_path = os.path.join( package_spec_dir, specFile )
363 return spec_full_path
365 def findSpecPatchFiles( patch_dir_path, package_name_list ):
367 Find the name of the patch for the spec file which matches best with `package_name`
371 patch_dir_path = os.path.expanduser( patch_dir_path )
372 patch_dir_path = os.path.expandvars( patch_dir_path )
373 if package_name_list is not None:
374 for patch_name in set( package_name_list ):
375 for patch_extend in ["", "-yocto"]:
376 patch_file = patch_name + patch_extend + ".spec.patch"
377 patch_path = os.path.join( patch_dir_path, patch_file )
378 if os.path.isfile( patch_path ):
379 patch_list.append( patch_path )
385 class SubprocessCrt( object ):
387 usefull class to control subprocess
389 def __init__( self ):
391 Initialize subprocess.
396 def get_last_res( self ):
398 return the last subprocess output.
400 return self.output_res
402 def __read_subprocess_output( self, outputs, f_stdout, f_stderr ):
404 read the stdout, stderr of the subprocess
408 for file_d in select.select( [f_stdout, f_stderr], [], [], select_timeout )[0]:
410 output = file_d.read()
411 if f_stdout == file_d:
412 self.output_res += output
414 if DEBUG_RUN and ( len( output ) > 0 ):
415 print "ERROR ****", output, len( output )
417 for line in output.split( "\n" ):
418 if not line == b"" or not output.endswith( "\n" ):
419 outputs[file_d]["EOF"] = False
421 if line == b"" and not output.endswith( "\n" ):
422 outputs[file_d]["EOF"] = True
424 res_clean = line.decode( "utf8", "replace" ).rstrip()
429 self.__idle_time += select_timeout
435 def exec_subprocess( self, command ):
437 Execute the "command" in a sub process,
438 the "command" must be a valid bash command.
439 _args and _kwargs are for compatibility.
444 # need Python 2.7.3 to do shlex.split(command)
445 splitted_command = shlex.split( str( command ) )
446 a_process = subprocess.Popen( splitted_command,
447 stdout = subprocess.PIPE,
448 stderr = subprocess.PIPE )
449 f_stdout = a_process.stdout
450 f_stderr = a_process.stderr
452 flags = fcntl.fcntl( f_stdout, fcntl.F_GETFL )
453 if not f_stdout.closed:
454 fcntl.fcntl( f_stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK )
456 flags = fcntl.fcntl( f_stderr, fcntl.F_GETFL )
457 if not f_stderr.closed:
458 fcntl.fcntl( f_stderr, fcntl.F_SETFL, flags | os.O_NONBLOCK )
460 outputs = {f_stdout: {"EOF": False},
461 f_stderr: {"EOF": False}}
464 while ( ( not outputs[f_stdout]["EOF"] and
465 not outputs[f_stderr]["EOF"] ) or
466 ( a_process.poll() == None ) ):
468 self.__read_subprocess_output( outputs, f_stdout, f_stderr )
469 except select.error as error:
470 # see http://bugs.python.org/issue9867
471 if error.args[0] == errno.EINTR:
472 print "Got select.error: %s" % unicode( error )
477 # maybe a_process.wait() is better ?
478 poll_res = a_process.poll()
481 return self.output_res
485 def of usefull re pattern to parse spec file.
487 pattern_patch = r'([pP]atch[\d]*)[\s]*:[\s]*.*'
488 patternUrlSourceFile = r'Source[\d]*[\s]*:[\s]*([http,ftp].*/)(.*)'
489 patternUrlPatchFile = r'Patch[\d]*[\s]*:[\s]*([http,ftp].*/)(.*)'
491 patternPatch = r'[pP]atch([\d]*)[\s]*:[\s]*(.*)'
492 patternSource = r'Source([\d]*)[\s]*:[\s]*(.*)'
494 patternPatchCommand = r'#(patch)([\d]*)(.*)'
496 patternDescription = r'^Summary:\s*(.*)'
497 patternUrl = r'^Url:\s*(.*)'
498 patternGroup = r'^Group:\s*(.*)'
499 patternLicense = r'^License:\s*(.*)'
501 patternFiles = r'^%files\s*(.*)'
503 patternName = r'^Name:\s*(.*)'
505 patternPackage = r'^%package\s*(.*)'
506 provides_package = r'^Provides:\s*(.*)'
508 buildPkgconfig = r'pkgconfig\((.*)\).*'
510 pkgRe = r'([^ \t\n\r\f\v,]+)(?:\s+(<|>|<=|>=|=|==)\s+([^ \t\n\r\f\v,]+))?'
512 buildRequiresPackage = r'^BuildRequires:\s*(.*)'
513 requiresPackage = r'^Requires(?:\(\w+\))?:\s*(.*)'
515 paternDevel = "(.*)-devel"
517 pkgconfig_name = "/usr/lib/pkgconfig/([^*]*).pc"
519 def __init__( self ):
524 def get_macro_directory_path( current_cpu ):
526 return all the valid macro directory.
529 for macro_dir in ["lib/*",
531 "lib/platform/%s-linux/macros" % current_cpu,
536 macro_paths += os.path.join( "/usr/share/spec2yocto/macro", macro_dir ) + " "
544 msubprocess = SubprocessCrt()
545 def __init__( self, package_spec_path, package_pn = None ):
549 self.__introduction_section = "introduction_section"
550 self.__package = "%package"
551 self.__description = "%description"
552 self.__prep_flag = "%prep"
553 self.__build_flag = "%build"
554 self.__install_flag = "%install"
555 self.__clean_flag = "%clean"
556 self.__files_flag = "%files"
557 self.__check_flag = "%check"
558 #pkg_preinst, pkg_postinst, pkg_prerm, and pkg_postrm
559 self.__post_flag = "%post"
560 self.__preun_flag = "%preun"
561 self.__postun_flag = "%postun"
562 self.__pre_flag = "%pre"
564 self.__verifyscript_flag = "%verifyscript"
565 self.__changelog_flag = "%changelog"
566 self.__list_section = [self.__package,
578 self.__verifyscript_flag,
579 self.__changelog_flag]
581 self.__package_spec_path = package_spec_path
582 self.__package_pn = package_pn
584 self.__parsed_spec_file = None
585 self.__order_list = []
586 self.__spect_dico = {}
589 self.__order_raw_list = []
590 self.__raw_spect_dico = {}
592 self.__cpu = SPEC2YOCTO_CONFIG.get_target_cpu()
593 self.__cpu_native = platform.machine()
595 self.__convert_spec_file()
596 self.__parse_parsed_spec_file()
597 self.__base_name = self.get_name()
599 self.__pkg_config = []
601 def __find_patch( self ):
603 find the patchs of the spec file.
606 with open( self.__package_spec_path ) as file_d:
607 spec_file = file_d.read()
608 res_tmp = re.findall( RePattern.pattern_patch, spec_file )
609 for a_res in res_tmp:
610 self.__patchs.append( a_res.replace( "Patch", "patch" ) )
612 def __is_native_build( self ):
614 return True if the package is native.
616 res_1 = ( self.__package_pn is not None )
620 res_2 = self.__package_pn.endswith( "-native" )
624 def init_rpmspec_command( self ):
626 init rpmspec_command to parse spec file.
628 rpmspec_command = "rpmspec "
630 if self.__is_native_build():
631 current_cpu = self.__cpu_native
633 current_cpu = self.__cpu
635 rpmspec_command += " --macros=\"%s\" " % get_macro_directory_path( current_cpu )
637 rpmspec_command += " --define='buildroot ${D}' "
638 if self.__is_native_build():
639 # Not the better way to do this
640 rpmspec_command += " --define='basearch i386' "
641 # I guess other tool must be set for native build.
642 rpmspec_command += " --define='__cc gcc' "
643 # the default value of the macro is %{nil}
644 base_prefix = os.getenv( "base_prefix" )
645 if ( base_prefix != "" ) and ( base_prefix is not None ):
646 rpmspec_command += " --define='_buildPrefix %s' " % base_prefix
648 rpmspec_command += " --define='%find_lang echo no find_lang for package native'"
650 rpmspec_command += " --define='setup #setup' "
651 rpmspec_command += " --define='setup0 #setup0' "
653 package_dir = os.path.dirname( self.__package_spec_path )
655 rpmspec_command += " --define='SOURCES ${S}/packaging/' "
656 rpmspec_command += " --define='_sourcedir ${S}/packaging/' "
658 rpmspec_command += " --define='BUILD_BASENAME %{basename}' "
659 rpmspec_command += " --define='find_lang #find_lang' "
660 rpmspec_command += " --define='with_wayland 1' "
662 rpmspec_command += " --target='%s' " % current_cpu
664 package_name = os.path.basename( self.__package_spec_path )[:-5]
666 if package_name in SPEC2YOCTO_CONFIG.get_bb_autoreconf_blacklist() :
667 oe_runconf2 = '''oe_runconf2'''
668 rpmspec_command += " --define='%%_configure %s'" % oe_runconf2
670 return rpmspec_command
673 def __convert_spec_file( self ):
675 init convert spec to expand spec file.
677 tmp_package_spec_path = self.__package_spec_path
679 # we can't use python rpm API to parse the spec file so we need to exec rpmspec\
680 # in a subprocess and parse the result.
681 rpmspec_command = self.init_rpmspec_command()
683 # it's import to remove all "Source" url because if rpm dan't find the source,\
684 # it try to downloads the file from the url.
685 with open( tmp_package_spec_path, 'r' ) as current_spec_file:
686 current_spec_string = current_spec_file.read()
687 res_url_source_files = re.findall( RePattern.patternUrlSourceFile, current_spec_string )
689 if len( res_url_source_files ) > 0:
690 for res_url in res_url_source_files:
691 long_url = res_url[0] + res_url[1]
692 short_url = res_url[1]
693 current_spec_string = current_spec_string.replace( long_url, short_url )
695 with tempfile.NamedTemporaryFile( mode = 'w',
697 prefix = os.path.basename( tmp_package_spec_path ) + ".",
698 dir = os.path.dirname( tmp_package_spec_path ),
699 delete = False ) as tmp_spec_file:
700 tmp_spec_file.write( current_spec_string )
701 tmp_package_spec_path = tmp_spec_file.name
703 # same case as "Source"
704 with open( tmp_package_spec_path, 'r' ) as current_spec_file:
705 current_spec_string = current_spec_file.read()
706 res_url_patch_file = re.findall( RePattern.patternUrlPatchFile, current_spec_string )
708 if len( res_url_patch_file ) > 0:
709 for res_url in res_url_patch_file:
710 long_url = res_url[0] + res_url[1]
711 short_url = res_url[1]
712 current_spec_string = current_spec_string.replace( long_url, short_url )
713 if ( tmp_package_spec_path != self.__package_spec_path ) \
714 and os.path.isfile( tmp_package_spec_path ) \
716 os.remove( tmp_package_spec_path )
717 with tempfile.NamedTemporaryFile( mode = 'w',
719 prefix = os.path.basename( tmp_package_spec_path ) + ".",
720 dir = os.path.dirname( tmp_package_spec_path ),
721 delete = False ) as tmp_spec_file:
722 tmp_spec_file.write( current_spec_string )
723 tmp_package_spec_path = tmp_spec_file.name
726 for a_patch in self.__patchs:
727 if a_patch == "patch0":
728 rpmspec_command += " --define='%patch #patch' "
730 rpmspec_command += " --define='%s #%s' " % ( a_patch, a_patch )
732 rpmspec_command += " --define='debug_package %{nil}'"
734 rpmspec_command += " --parse %s " % tmp_package_spec_path
736 print "rpmspec_command :", rpmspec_command
739 self.__parsed_spec_file = SpecParser.msubprocess.exec_subprocess( rpmspec_command )
740 if ( tmp_package_spec_path != self.__package_spec_path ) \
741 and os.path.isfile( tmp_package_spec_path ) \
743 os.remove( tmp_package_spec_path )
745 if self.__parsed_spec_file == 1:
746 print >> sys.stderr, ""
747 print >> sys.stderr, "ERROR CMD: %s" % rpmspec_command
748 print >> sys.stderr, "parse error for spec file %s" % ( tmp_package_spec_path )
749 self.__parsed_spec_file = None
753 if not os.path.isdir( "/tmp/parsed_spec" ):
754 os.makedirs( "/tmp/parsed_spec" )
756 if self.__package_pn is None:
757 tmp_path = os.path.basename( self.__package_spec_path )
758 package_parsed_spec_path = os.path.join( "/tmp/parsed_spec", tmp_path )
760 tmp_path = "%s.spec" % self.__package_pn
761 package_parsed_spec_path = os.path.join( "/tmp/parsed_spec", tmp_path )
763 with open( package_parsed_spec_path, "w" ) as file_d:
764 file_d.write( self.__parsed_spec_file )
767 def __test_section( self, line ):
769 test if the line is the start of a new section.
771 for sect in self.__list_section:
772 if line.startswith( sect ):
776 def __parse_parsed_spec_file( self ):
778 parse a spec file by section after rpmspec.
780 # ordered dico is not provide yet...
781 self.__order_list = []
782 self.__spect_dico = {}
784 current_section = self.__introduction_section
785 self.__spect_dico[current_section] = []
786 self.__order_list.append( current_section )
788 if self.__parsed_spec_file is None:
791 for line in self.__parsed_spec_file.split( "\n" ):
793 if self.__test_section( line ) :
794 if line in self.__spect_dico.keys():
795 print "line %s" % line
796 print "--------------------------------------"
797 print "parsedSpecFile: %s" % self.__package_spec_path
798 print "--------------------------------------"
799 error_msg = "ERROR for the spec file \"%s\" this section \"%s\" is not unique."
800 print error_msg % ( self.__parsed_spec_file, line )
803 current_section = line
804 self.__spect_dico[current_section] = []
805 self.__order_list.append( current_section )
807 self.__spect_dico[current_section].append( line )
809 def parse_raw_spec_file( self ):
811 parse a spec file by section before rpmspec.
814 # ordered dico is not provide yet...
816 self.__order_raw_list = []
817 self.__raw_spect_dico = {}
819 current_section = self.__introduction_section
820 self.__raw_spect_dico[current_section] = []
821 self.__order_raw_list.append( current_section )
823 with open( self.__package_spec_path, "r" ) as file_d:
824 parsed_raw_spec_file = file_d.read()
826 for line in parsed_raw_spec_file.split( "\n" ):
827 if self.__test_section( line ) :
828 if line in self.__raw_spect_dico.keys():
829 print "line %s" % line
830 print "--------------------------------------"
831 print "parsedSpecFile: %s" % self.__package_spec_path
832 print "--------------------------------------"
833 error_msg = "ERROR for the spec file \"%s\" this section \"%s\" is not unique."
834 print error_msg % ( self.__parsed_spec_file, line )
837 current_section = line
838 self.__raw_spect_dico[current_section] = []
839 self.__order_raw_list.append( current_section )
841 self.__raw_spect_dico[current_section].append( line )
844 def get_prep_section( self ):
846 return the prep section of the spec file.
848 res_prep_section = "cd ${S}\n"
850 pattern_patch_dico = {}
851 pattern_source_dico = {}
853 for line in self.__spect_dico[self.__introduction_section][1:]:
854 for patch_id, files_name in re.findall( RePattern.patternPatch, line ):
857 pattern_patch_dico[patch_id] = files_name
859 for source_id, files_name in re.findall( RePattern.patternSource, line ):
862 pattern_source_dico[source_id] = files_name
864 for line in self.__spect_dico[self.__prep_flag][1:]:
865 if line.startswith( "#setup" ):
866 splited_line = line.split()
867 for i in range( len( splited_line ) ):
868 if splited_line[i].startswith( "-a" ):
869 if len( splited_line[i] ) > len( "-a" ):
870 setup_id = splited_line[i].replace( "-a", "" )
872 setup_id = splited_line[i + 1]
873 res_prep_section += "#extracte source %s \n" % setup_id
874 res_prep_section += "pushd ${S}\n"
875 source = os.path.basename( pattern_source_dico[setup_id] )
876 # not a good way to do this
877 if source.endswith( "rpmlintrc" ):
878 res_prep_section += "cp ${S}/packaging/%s .\n" % source
880 file_name = os.path.basename( pattern_source_dico[setup_id] )
881 res_prep_section += "unp ${S}/packaging/%s \n" % file_name
882 res_prep_section += "popd \n"
884 elif splited_line[i].startswith( "-b" ):
885 if len( splited_line[i] ) > len( "-b" ):
886 setup_id = splited_line[i].replace( "-b", "" )
888 setup_id = splited_line[i + 1]
890 res_prep_section += "#extracte source %s \n" % ( setup_id )
891 res_prep_section += "pushd ${S}/../\n"
892 source = os.path.basename( pattern_source_dico[setup_id] )
893 if source.endswith( "rpmlintrc" ):
894 res_prep_section += "cp ${S}/packaging/%s .\n" % source
896 res_prep_section += "unp ${S}/packaging/%s \n" % source
897 res_prep_section += "popd \n"
899 res_prep_section += "chmod -Rf a+rX,u+w,g-w,o-w ${S}\n"
902 elif line.startswith( "#patch" ):
903 res_findall = re.findall( RePattern.patternPatchCommand, line )
905 for patch_name, patch_id, EXEC_COMMAND in res_findall:
909 files_name = pattern_patch_dico[patch_id]
911 if "-p" not in EXEC_COMMAND:
912 EXEC_COMMAND += " -p0"
914 if files_name.endswith( ".bz2" ):
915 bzcat_cmd = "bzcat ${S}/packaging/%s | patch -s %s --fuzz=2\n"
916 bzcat_val = ( files_name, EXEC_COMMAND.replace( " -b", " -b --suffix" ) )
917 res_prep_section += bzcat_cmd % bzcat_val
919 cat_cmd = "cat ${S}/packaging/%s | patch -s %s --fuzz=2\n"
920 cat_val = ( files_name, EXEC_COMMAND.replace( " -b", " -b --suffix" ) )
921 res_prep_section += cat_cmd % cat_val
923 res_prep_section += line + "\n"
924 return res_prep_section
926 def get_build_section( self ):
928 return the build section of the spec file.
930 res_build_section = "cd ${S}\n"
931 if self.__build_flag not in self.__spect_dico.keys():
934 for line in self.__spect_dico[self.__build_flag][1:]:
935 res_build_section += line + "\n"
937 return res_build_section
939 def get_raw_build_section( self ):
941 return the raw build section of the spec file.
943 res_raw_build_section = ""
944 if self.__build_flag not in self.__spect_dico.keys():
946 for line in self.__raw_spect_dico[self.__build_flag][1:]:
947 res_raw_build_section += line + "\n"
948 return res_raw_build_section
950 def get_clean_raw( self ):
952 clean the raw spec file to generate spec file for yocto packaging.
955 for sect in self.__order_raw_list:
956 if sect == self.__introduction_section:
957 for line in self.__raw_spect_dico[sect]:
958 if line.startswith("Version:"):
959 res_clean_raw += "Version: git\n"
962 have_findall_source = len( re.findall( RePattern.patternSource , line ) ) > 0
963 have_findall_patch = len( re.findall( RePattern.patternPatch, line ) ) > 0
964 if not( have_findall_source or have_findall_patch ):
965 res_clean_raw += line + "\n"
968 elif sect == self.__prep_flag:
969 res_clean_raw += line + "%prep\n"
970 res_clean_raw += line + "#FAKE\n"
971 elif sect == self.__build_flag:
972 res_clean_raw += line + "%build\n"
973 res_clean_raw += line + "#FAKE\n"
974 elif sect == self.__install_flag:
975 res_clean_raw += line + "%install\n"
976 res_clean_raw += line + "#FAKE\n"
977 elif sect == self.__check_flag:
979 elif sect == self.__clean_flag:
981 elif sect == self.__changelog_flag:
983 elif sect.startswith( "%files" ):
984 for line in self.__raw_spect_dico[sect]:
985 if line.startswith( '%manifest ' ):
986 res_clean_raw += line[len('%manifest '):] + "\n"
987 elif line.startswith( '%doc ' ):
989 elif line.startswith( '%ghost ' ):
991 elif line.startswith( '%exclude ' ):
993 elif line.startswith( '%license' ):
997 res_clean_raw += line + "\n"
1000 for line in self.__raw_spect_dico[sect]:
1001 res_clean_raw += line + "\n"
1003 clean_raw_command = self.init_rpmspec_command()
1005 tmp_package_spec_path = self.__package_spec_path
1006 with tempfile.NamedTemporaryFile( mode = 'w',
1008 prefix = os.path.basename( tmp_package_spec_path ) + ".",
1009 dir = os.path.dirname( tmp_package_spec_path ),
1010 delete = False ) as tmp_spec_file:
1011 tmp_spec_file.write( res_clean_raw )
1012 tmp_package_spec_path = tmp_spec_file.name
1014 clean_raw_command += " --define='debug_package %{nil}'"
1015 clean_raw_command += " --define='docs_package %{nil}'"
1017 clean_raw_command += " --parse %s " % tmp_package_spec_path
1019 print "clean_raw_command :", clean_raw_command
1021 parsed_spec_file = SpecParser.msubprocess.exec_subprocess( clean_raw_command )
1023 if os.path.isfile( tmp_package_spec_path ) and not DEBUG_RUN:
1024 os.remove( tmp_package_spec_path )
1026 if parsed_spec_file == 1:
1027 print >> sys.stderr, "parse error for spec file %s" % ( tmp_package_spec_path )
1028 parsed_spec_file = None
1033 Summary: #FAKE - Debugging files
1036 %%description -n %s-dbg
1042 ''' % ( self.__base_name, self.__base_name, self.__base_name )
1043 work_dir = os.getenv( "WORKDIR" )
1045 if work_dir is None:
1046 return parsed_spec_file
1048 base_root = os.path.join( work_dir, "package" )
1049 for root, dirs, files in os.walk( base_root ):
1050 if root.endswith( ".debug" ):
1052 print "find directory %s " % dirs
1053 for a_file in files:
1054 fake_dbg += os.path.join( root, a_file ).replace( base_root, "" ) + "\n"
1055 #Test don't add dbg files
1056 #return parsed_spec_file + fake_dbg
1058 return parsed_spec_file
1060 def get_install_section( self ):
1062 return the install section.
1064 res_install_section = "cd ${S}\n"
1066 for line in self.__spect_dico[self.__install_flag][1:]:
1067 res_install_section += line + "\n"
1068 return res_install_section
1070 def get_description( self ):
1072 return the description of the spec file.
1074 for line in self.__spect_dico[self.__introduction_section] :
1075 description = re.findall( RePattern.patternDescription, line )
1076 if len( description ) > 0:
1077 return description[0]
1080 def get_homepage( self ):
1082 return the homepage of the spec file project.
1084 for line in self.__spect_dico[self.__introduction_section] :
1085 description = re.findall( RePattern.patternUrl, line )
1086 if len( description ) > 0:
1087 return description[0]
1090 def get_section( self ):
1092 return the section of the spec file project.
1094 for line in self.__spect_dico[self.__introduction_section] :
1095 description = re.findall( RePattern.patternGroup, line )
1096 if len( description ) > 0:
1097 return description[0]
1098 return "System/Base"
1100 def get_license( self ):
1102 return the licence of the package.
1104 for line in self.__spect_dico[self.__introduction_section] :
1105 description = re.findall( RePattern.patternLicense, line )
1106 if len( description ) > 0:
1107 res_license = description[0]
1108 if ";" in res_license:
1109 res_license = res_license.replace( ";", "" )
1114 def get_section_key(self, __flag):
1116 Return the list of "__flag" sections of the spec file.
1119 for section_key in self.__spect_dico.keys():
1120 if section_key.startswith(__flag):
1121 res_section.append(section_key)
1125 def get_script_section_key_pre(self):
1127 Return the list of pre script section of the spec file.
1128 get_section_key() can't be used in this case since it will also
1129 return the %preun and %prep results.
1131 res_script_section = []
1132 for section_key in self.__spect_dico.keys():
1133 if section_key.startswith("%pre") and \
1134 not section_key.startswith("%preun") and \
1135 not section_key.startswith("%prep"):
1136 res_script_section.append(section_key)
1138 return res_script_section
1140 def get_script_section_key_post(self):
1142 Return the list of post script section of the spec file.
1143 get_section_key() can't be used in this case since it will also
1144 return the %postun results.
1146 res_script_section = []
1147 for section_key in self.__spect_dico.keys():
1148 if section_key.startswith("%post") and not section_key.startswith("%postun"):
1149 res_script_section.append(section_key)
1151 return res_script_section
1153 def get_files_list_from_section( self, package_section_name ):
1155 return a list of file
1158 for line in self.__spect_dico[package_section_name][1:]:
1159 if not line.startswith( "%" ) and not line == "":
1160 line = line.replace( "//", "/" )
1161 res_list.append( line )
1162 elif line.startswith( "%attr(" ):
1163 line = line.replace( "//", "/" )
1164 pkg_f_clean=line.split(")")
1165 pkg_f=pkg_f_clean[-1].strip()
1166 res_list.append( pkg_f )
1167 elif line.startswith( "%doc " ):
1168 line = line.replace( "//", "/" )
1169 res_list.append( line.replace( "%doc ", "" ) )
1170 elif line.startswith( "%dir " ):
1171 line = line.replace( "//", "/" )
1172 res_list.append( line.replace( "%dir ", "" ) )
1173 elif line.startswith( "%config " ):
1174 line = line.replace( "//", "/" )
1175 res_list.append( line.replace( "%config ", "" ) )
1176 elif line.startswith( "%manifest " ):
1177 line = line.replace( "//", "/" )
1178 res_list.append( line.replace( "%manifest ", "" ) )
1179 elif line.startswith( "%config(noreplace) " ):
1180 line = line.replace( "//", "/" )
1181 res_list.append( line.replace( "%config(noreplace) ", "" ) )
1182 elif line.startswith( "%config(" ):
1183 line = line.replace( "//", "/" )
1184 pkg_f_clean=line.split(")")
1185 pkg_f=pkg_f_clean[-1].strip()
1186 res_list.append( pkg_f )
1192 def get_script_from_section(self, __flag):
1194 Return the pre/post script section of the spec file.
1196 res_script_section = ""
1197 if __flag in self.__spect_dico.keys():
1198 for line in self.__spect_dico[__flag][1:]:
1199 res_script_section += line + "\n"
1201 return res_script_section
1203 def get_files_packages( self ):
1205 return a dictinaire with package for key and list of files fo value.
1209 for package_section_name in self.get_section_key("%file"):
1210 tmp_package_name = package_section_name
1211 # Need to get info of the first line.
1212 if "-f " in tmp_package_name:
1213 tmp_split = tmp_package_name.split( "-f " )
1214 tmp_package_name = tmp_split[0]
1216 package = re.findall( RePattern.patternFiles, tmp_package_name )
1217 if len( package ) > 0:
1218 if "-n " in package[0]:
1219 package_name = package[0].replace( "-n ", "" )
1221 package_name = self.__base_name
1222 pkg_ext = package[0].replace( " ", "" )
1223 if len( pkg_ext ) > 0:
1224 package_name += "-" + pkg_ext
1226 package_name = self.__base_name
1228 package_name = package_name.replace( " ", "" )
1229 res_files_list = self.get_files_list_from_section( package_section_name )
1230 res_dico[ package_name ] = res_files_list
1232 #db_src=self.__base_name+"-debugsource"
1233 #if db_src not in res_dico:
1234 # res_dico[db_src] = []
1236 #dbinfo=self.__base_name+"-debug"
1237 #if dbinfo not in res_dico:
1238 # res_dico[dbinfo] = []
1242 def get_name( self ):
1244 return the name of the package
1246 for line in self.__spect_dico[self.__introduction_section]:
1247 description = re.findall( RePattern.patternName, line )
1248 if len( description ) > 0:
1249 return description[0]
1252 def get_provides( self ):
1254 return all provide service by each package of the spec file.
1257 provide_res[self.__base_name] = []
1258 provide_res[self.__base_name].append( [self.__base_name] )
1260 for k in self.__spect_dico.keys():
1261 package = re.findall( RePattern.patternPackage, k )
1262 if len( package ) > 0:
1263 package_name = self.__clean_package_name( package[0] )
1264 provide_res[ package_name ] = []
1265 provide_res[ package_name ].append( [package_name] )
1267 if len( package ) > 0 or ( k == self.__introduction_section ):
1268 for line in self.__spect_dico[k]:
1269 provides = re.findall( RePattern.provides_package, line )
1270 for provides_line in provides:
1271 for tmp_clean in self.__clean_package_line( provides_line ):
1272 if k == self.__introduction_section:
1273 provide_res[self.__base_name].append( tmp_clean )
1275 provide_res[package_name].append( tmp_clean )
1278 def __clean_package_name( self, package_name ):
1280 return the package name from spec declaration.
1282 # re should be better.
1283 if "-n " in package_name:
1284 package_name = package_name.replace( "-n ", "" ).replace( " ", "" )
1286 package_name = self.__base_name + "-" + package_name
1290 def get_rdepends( self ):
1292 return all require service by each package of the spec file.
1296 for k in self.__spect_dico.keys():
1297 package = re.findall( RePattern.patternPackage, k )
1299 if len( package ) > 0:
1300 package_name = self.__clean_package_name( package[0] )
1302 package_name = self.__base_name
1304 if len( package ) > 0 or ( k == self.__introduction_section ):
1305 requires_list = self.get_requires( self.__spect_dico[k] )
1306 rdepends_res[package_name] = requires_list
1310 def get_depends( self ):
1312 return all build require service by each package of the spec file.
1316 for k in self.__spect_dico.keys():
1317 package = re.findall( RePattern.patternPackage, k )
1318 if len( package ) > 0:
1319 package_name = self.__clean_package_name( package[0] )
1321 if len( package ) > 0 or ( k == self.__introduction_section ):
1322 build_requires_list = self.get_build_requires( self.__spect_dico[k] )
1323 if ( k == self.__introduction_section ):
1324 depends_res[self.__base_name] = build_requires_list
1326 depends_res[package_name] = build_requires_list
1331 def __clean_package_line( self, package_line ):
1333 return package list from package declaration in spec file.
1335 res_first = re.findall( RePattern.pkgRe, package_line )
1336 if len( res_first ) == 0:
1337 print "__clean_package_line faild for %s" % self.__package_spec_path
1339 # should be rewrite cleaner.
1341 for init_res in res_first:
1342 init_res = list( init_res )
1343 init_res[0] = init_res[0].replace( ",", "" )
1344 res_final.append( init_res )
1347 def get_build_requires( self, lines ):
1349 return the line of every build requires.
1351 package_replacement = SPEC2YOCTO_CONFIG.get_substitute()
1352 build_requires_res = []
1354 build_requires = re.findall( RePattern.buildRequiresPackage, line )
1355 for tmp_res in build_requires:
1356 for tmp_clean in self.__clean_package_line( tmp_res ):
1357 if len( tmp_clean ) >= 1:
1358 if tmp_clean[0] in package_replacement.keys():
1359 tmp_clean[0] = package_replacement[tmp_clean[0]]
1360 build_requires_res.append( tmp_clean )
1361 return build_requires_res
1363 def get_requires( self, lines ):
1365 return the line of every requires.
1367 package_replacement = SPEC2YOCTO_CONFIG.get_substitute()
1371 build_requires = re.findall( RePattern.requiresPackage, line )
1372 for tmp_res in build_requires:
1373 for tmp_clean in self.__clean_package_line( tmp_res ):
1374 if len( tmp_clean ) >= 1:
1375 if tmp_clean[0] in package_replacement.keys():
1376 tmp_clean[0] = package_replacement[tmp_clean[0]]
1377 requires_res.append( tmp_clean )
1382 meta spec file for generate yocto bb.
1385 mExtraRProvidesDico = {}
1387 mCrossPackageBlacklist = []
1388 mInitialPackageBlacklist = []
1389 mNativePackageBlacklist = []
1390 mOePackageBlacklist = []
1393 package_recipes_dir,
1396 package_git_srv_src,
1397 package_git_srv_path,
1400 init the MetaSpec class
1402 self.__package_recipes_dir = package_recipes_dir
1403 self.__package_name = package_name
1406 self.__package_git_srv_src = package_git_srv_src
1407 self.__package_git_srv_path = package_git_srv_path
1409 self.__package_spec_path = package_spec_path
1410 self.__git_tag = package_git_tag
1412 self.__spec_parser = SpecParser( self.__package_spec_path )
1413 self.__package_spec_name = self.__spec_parser.get_name()
1415 self.__packages_dico = self.__spec_parser.get_files_packages()
1416 self.__provides_dico = self.__spec_parser.get_provides()
1418 self.setm_provided_dico()
1419 self.__rdepends_dico = self.__spec_parser.get_rdepends()
1421 self.__base_file = self.__package_name + ".inc"
1422 #self.__base_depends_file = self.__package_name + "-depends.inc"
1423 #self.__base_rdepends_file = self.__package_name + "-rdepends.inc"
1424 #self.__base_provides_file = self.__package_name + "-rprovides.inc"
1426 self.__extra_conf_file = self.__package_name + "-extraconf.inc"
1427 #self.__extra_native_conf_file = self.__package_name + "-native-extraconf.inc"
1428 #self.__extra_oe_conf_file = self.__package_name + "-oe-extraconf.inc"
1430 self.__git_native_file = self.__package_name + "-native_git.bb"
1431 self.__git_oe_file = self.__package_name + "_git.bb"
1433 self.__createRecipes()
1435 def setm_provided_dico( self ):
1437 add provides_list for package_name to mProvidesDico
1440 for k_provide in self.__provides_dico.keys():
1441 for p_provide in self.__provides_dico[k_provide]:
1442 provides_list.append( p_provide[0] )
1443 for p_provide in self.__packages_dico.keys():
1444 provides_list.extend( self.__packages_dico[p_provide] )
1446 for package in self.__packages_dico.keys():
1447 for pkg_file in self.__packages_dico[package]:
1448 pkgconfig_name_res = re.findall( RePattern.pkgconfig_name, pkg_file )
1449 for tmp_res in pkgconfig_name_res:
1450 provides_list.append( "pkgconfig(%s)" % tmp_res )
1452 MetaSpec.mProvidesDico[self.__package_name] = provides_list
1454 def set_mextra_provided_dico( self ):
1456 add provides_list for package_name to mExtraRProvidesDico
1459 for k_provide in self.__provides_dico.keys():
1460 for p_provide in self.__provides_dico[k_provide]:
1461 provides_list.append( p_provide[0] )
1462 for p_provide in self.__packages_dico.keys():
1463 provides_list.extend( self.__packages_dico[p_provide] )
1465 MetaSpec.mExtraRProvidesDico[self.__package_name] = provides_list
1467 def __create_base_file( self ):
1469 create the base file of the bb file.
1471 bb_path = os.path.join( self.__package_recipes_dir, self.__base_file )
1472 with open( bb_path, "w" ) as file_d:
1474 _description = self.__spec_parser.get_description()
1475 _homepage = self.__spec_parser.get_homepage()
1476 _section = self.__spec_parser.get_section()
1478 _license = self.__spec_parser.get_license()
1480 file_d.write( "DESCRIPTION = \"%s\"\n" % _description )
1481 if len( _homepage ) < 2:
1482 _homepage = "http://nohomepage.org"
1483 file_d.write( "HOMEPAGE = \"%s\"\n" % _homepage )
1484 file_d.write( "SECTION = \"%s\"\n" % _section )
1486 file_d.write( "LICENSE = \"%s\"\n" % _license )
1487 file_d.write( "\n" )
1488 file_d.write( "SRC_URI = \"\"\n" )
1489 file_d.write( "\n" )
1490 file_d.write( "S = \"${WORKDIR}/git\"\n" )
1491 file_d.write( "\n" )
1493 file_d.write( "inherit autotools-brokensep\n" )
1494 file_d.write( "\n" )
1495 file_d.write( "BBCLASSEXTEND = \"\"\n" )
1497 self.__create_provides_file( file_d)
1498 self.__create_rdepends( file_d)
1499 self.__create_depends( file_d)
1501 self.__create_patch( file_d)
1502 self.__create_configure( file_d)
1503 self. __create_compile( file_d)
1504 self.__create_install( file_d)
1506 self.__create_script_file( file_d)
1508 self.__create_files_packaging( file_d )
1510 file_d.write( "require %s\n\n" % self.__extra_conf_file )
1512 def __create_files_packaging(self,file_d):
1513 file_d.write( "PACKAGES = \"${PN}-dbg ${PN}-doc ${PN}-locale\"\n" )
1514 for package in self.__packages_dico.keys():
1515 pkg_yocto_name=package
1516 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1517 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1519 if pkg_yocto_name not in [self.__package_name+"-dbg",
1520 self.__package_name+"-doc",
1521 self.__package_name+"-locale",
1523 file_d.write( "PACKAGES += \" %s \"\n" % pkg_yocto_name )
1525 file_d.write( "\n" )
1527 _license = self.__spec_parser.get_license()
1529 for package in self.__packages_dico.keys():
1530 pkg_yocto_name=package
1531 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1532 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1534 file_d.write( "%s_files = \"\"\n" % pkg_yocto_name )
1536 for pkg_f in self.__packages_dico[package]:
1539 if pkg_f.startswith( _license ):
1542 pkg_yocto_name = package.replace("-devel","-dev")
1543 file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, pkg_f ) )
1545 file_d.write( "\n" )
1547 for package in self.__packages_dico.keys():
1548 p_parse = package.replace( self.__package_name, "${PN}" )
1549 p_parse = p_parse.replace("-devel","-dev")
1550 pkg_yocto_name = package.replace("-devel","-dev")
1551 file_d.write( "FILES_%s = \"${%s_files}\"\n" % ( p_parse, pkg_yocto_name ) )
1552 file_d.write( "\n" )
1554 for package in self.__packages_dico.keys():
1555 pkg_yocto_name = package.replace("-devel","-dev")
1556 file_d.write( "PKG_%s= \"%s\"\n" % (pkg_yocto_name,pkg_yocto_name) )
1557 file_d.write( "\n" )
1559 def __create_patch( self ,file_d):
1560 code=self.__spec_parser.get_prep_section()
1561 code=code.replace("\n","\n ")
1562 file_d.write( "do_prep() {\n" )
1563 file_d.write( " %s\n" % code )
1564 file_d.write( "}\n" )
1565 file_d.write( "do_patch_append() {\n" )
1566 file_d.write( " bb.build.exec_func('do_prep', d)\n" )
1567 file_d.write( "}\n" )
1568 file_d.write( "\n" )
1570 def __create_configure( self ,file_d):
1571 file_d.write( "do_configure() {\n" )
1572 file_d.write( "}\n" )
1573 file_d.write( "\n" )
1575 def __create_compile( self ,file_d):
1576 code=self.__spec_parser.get_build_section()
1577 code=code.replace("\n","\n ")
1579 file_d.write( "do_compile() {\n" )
1580 file_d.write( " %s\n" % code )
1581 file_d.write( "}\n" )
1582 file_d.write( "\n" )
1584 def __create_install( self ,file_d):
1585 code=self.__spec_parser.get_install_section()
1586 code=code.replace("\n","\n ")
1587 code=code.replace("\n EOF","\nEOF")
1588 file_d.write( "do_install() {\n" )
1589 file_d.write( " echo export RPM_BUILD_ROOT=${D}\n" )
1590 file_d.write( " %s\n" % code )
1591 file_d.write( "}\n" )
1592 file_d.write( "\n" )
1594 def __create_script_file_section_code( self, spec_section):
1596 Returns the command executed in one of the %pre, %post, %preun
1597 or %postun section of a spec file.
1599 code = self.__spec_parser.get_script_from_section(spec_section)
1600 command_list = code.split("\n")
1602 for line in command_list:
1605 formated_code += " " + line + "\n"
1607 return formated_code
1609 def __create_script_file_write( self, file_d, code, recipe_section, package_name):
1611 Writes the pre/post (un)install sections of the recipe.
1613 code=code.replace("/sbin/ldconfig","[ \"x\$D\" == \"x\" ] && ldconfig")
1614 code=code.replace("${prefix}","$D${prefix}")
1617 file_d.write("%s%s() {\n" % (recipe_section, package_name))
1618 file_d.write(" #!/bin/sh -e\n\n")
1619 file_d.write("%s\n" % code)
1623 def __create_script_file_session(self, file_d, flag, script_name, script_sections):
1625 Add script for the given flag.
1627 for section in script_sections:
1629 # If %section is a one line script such as: "%post -p /sbin/ldconfig"
1630 if " -p " in section:
1631 # Remove the package name if present to only keep the command
1632 section_split = section.split(" -p ")[1].split(" -n ")
1633 code = " " + section_split[0].strip()
1635 code = self.__create_script_file_section_code(section)
1637 # Set the package name
1638 package_name = "${PN}"
1639 # If the package name is not the project name
1640 if " -n " in section:
1641 # Remove the command if any to only keep the package name
1642 section_split = section.split(" -n ")[1].split(" -p ")
1643 package_name = section_split[0].strip()
1644 self.__create_script_file_write(file_d, code, script_name, package_name)
1646 def __create_script_file(self, file_d):
1648 Add the pre/post install/uninstall sections of a spec file to
1651 script_sections = self.__spec_parser.get_script_section_key_pre()
1652 self.__create_script_file_session(file_d, "%pre", "pkg_preinst_", script_sections)
1654 script_sections = self.__spec_parser.get_script_section_key_post()
1655 self.__create_script_file_session(file_d, "%post", "pkg_postinst_", script_sections)
1657 script_sections = self.__spec_parser.get_section_key("%preun")
1658 self.__create_script_file_session(file_d, "%preun", "pkg_prerm_", script_sections)
1660 script_sections = self.__spec_parser.get_section_key("%postun")
1661 self.__create_script_file_session(file_d, "%postun", "pkg_postrm_", script_sections)
1663 def __create_provides_file( self ,file_d):
1665 generate provide file.
1667 file_d.write( "PROVIDES = \"\"\n" )
1668 file_d.write( "\n" )
1670 for k_provide in self.__provides_dico.keys():
1671 pkg_yocto_name=k_provide
1672 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1673 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1675 if len( self.__provides_dico[k_provide] ) > 0:
1676 file_d.write( "#PROVIDES by %s\n" % pkg_yocto_name.replace(" ","") )
1678 for p_provide in self.__provides_dico[k_provide]:
1681 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto ):
1682 pkg_yocto=pkg_yocto.replace("-devel","-dev")
1684 if not len( p_provide ) == 1:
1685 provide_text = "# the PROVIDES rules is ignore \"%s %s %s\"\n"
1686 file_d.write( provide_text % ( pkg_yocto, p_provide[1], p_provide[2] ) )
1688 if ( pkg == "mktemp" and self.__package_name == "tizen-coreutils" ):
1692 if pkg_yocto_name != pkg_yocto:
1693 file_d.write( "PROVIDES += \"%s\"\n" % ( pkg_yocto ) )
1694 file_d.write( "RPROVIDES_%s += \"%s\"\n" % ( pkg_yocto_name, pkg_yocto ) )
1696 #for res_pkg_devel in re.findall( RePattern.paternDevel, pkg ):
1697 # rprovide_text = "RPROVIDES_%s += \"%s\"\n"
1698 # file_d.write( rprovide_text % ( k_provide, res_pkg_devel + "-dev" ) )
1700 if len( self.__provides_dico[k_provide] ) > 0:
1701 file_d.write( "\n\n" )
1703 def __create_git_native_file( self ):
1705 create bb native file.
1707 bb_native_path = os.path.join( self.__package_recipes_dir, self.__git_native_file )
1708 with open( bb_native_path, "w" ) as file_d:
1709 file_d.write( "require %s\n" % self.__base_file )
1710 file_d.write( "\n" )
1711 file_d.write( "PRIORITY = \"9\"\n" )
1712 file_d.write( "\n" )
1713 file_d.write( "inherit native\n" )
1714 file_d.write( "\n" )
1715 file_d.write( "S = \"${WORKDIR}/git\"\n" )
1716 file_d.write( "\n" )
1718 md5_value = "801f80980d171dd6425610833a22dbe6"
1719 file_value = "${COMMON_LICENSE_DIR}/GPL-2.0"
1720 file_chksum_text = "LIC_FILES_CHKSUM ??= \"file://%s;md5=%s\"\n"
1722 file_d.write( file_chksum_text % ( file_value, md5_value ) )
1723 file_d.write( "\n" )
1724 command_source = "SRC_URI += \"%s\"\n" % GIT_COMMAND
1725 file_d.write( command_source % ( self.__package_git_srv_src ,
1726 self.__package_git_srv_path ,
1728 #file_d.write( "require %s\n" % self.__extra_native_conf_file )
1729 file_d.write( "\n" )
1731 def __create_git_oe_file( self ):
1735 bb_path = os.path.join( self.__package_recipes_dir, self.__git_oe_file )
1736 with open( bb_path, "w" ) as file_d:
1737 file_d.write( "require %s\n" % self.__base_file )
1738 file_d.write( "\n" )
1739 file_d.write( "PRIORITY = \"10\"\n" )
1740 file_d.write( "\n" )
1741 md5_value = "801f80980d171dd6425610833a22dbe6"
1742 file_value = "${COMMON_LICENSE_DIR}/GPL-2.0"
1743 file_chksum_text = "LIC_FILES_CHKSUM ??= \"file://%s;md5=%s\"\n"
1745 file_d.write( file_chksum_text % ( file_value, md5_value ) )
1746 file_d.write( "\n" )
1747 command_source = "SRC_URI += \"" + GIT_COMMAND + "\"\n"
1748 file_d.write( command_source % ( self.__package_git_srv_src ,
1749 self.__package_git_srv_path ,
1751 #file_d.write( "require %s\n" % self.__extra_oe_conf_file )
1752 file_d.write( "\n" )
1753 if self.__package_name not in MetaSpec.mNativePackageBlacklist:
1754 file_d.write( "BBCLASSEXTEND += \" native \"" )
1755 file_d.write( "\n\n" )
1757 def __createRecipes( self ):
1759 generate all bb file.
1761 if self.__package_recipes_dir is None:
1764 if not os.path.isdir( self.__package_recipes_dir ):
1765 os.makedirs( self.__package_recipes_dir )
1768 #rdepends_path = os.path.join( self.__package_recipes_dir, self.__base_rdepends_file )
1769 #open( rdepends_path, "a" ).close()
1770 #depends_path = os.path.join( self.__package_recipes_dir, self.__base_depends_file )
1771 #open( depends_path, "a" ).close()
1772 #provides_path = os.path.join( self.__package_recipes_dir, self.__base_provides_file )
1773 #open( provides_path, "a" ).close()
1775 extra_conf_file_path = os.path.join( self.__package_recipes_dir, self.__extra_conf_file )
1776 open( extra_conf_file_path, "a" ).close()
1778 #extranative_path = os.path.join( self.__package_recipes_dir, self.__extra_native_conf_file )
1779 #open( extranative_path, "a" ).close()
1780 #extra_oe_conf_path = os.path.join( self.__package_recipes_dir, self.__extra_oe_conf_file )
1781 #open( extra_oe_conf_path, "a" ).close()
1783 self.__create_base_file()
1785 if not self.__package_name not in MetaSpec.mNativePackageBlacklist:
1786 bb_native_path = os.path.join( self.__package_recipes_dir, self.__git_native_file )
1787 if os.path.isfile( bb_native_path ):
1788 os.unlink( bb_native_path )
1790 #self.__create_provides_file()
1792 if self.__package_name not in MetaSpec.mOePackageBlacklist:
1793 self.__create_git_oe_file()
1795 bb_oe_path = os.path.join( self.__package_recipes_dir, self.__git_oe_file )
1796 if os.path.isfile( bb_oe_path ):
1797 os.unlink( bb_oe_path )
1799 def __create_rdepends( self ,file_d):
1801 generate rdepends file.
1803 if self.__package_recipes_dir is None:
1806 if not os.path.isdir( self.__package_recipes_dir ):
1807 os.makedirs( self.__package_recipes_dir )
1809 #rdepends_path = os.path.join( self.__package_recipes_dir, self.__base_rdepends_file )
1811 package_replacement = SPEC2YOCTO_CONFIG.get_substitute()
1813 if file_d is not None:
1814 file_d.write( "RDEPENDS = \"\"\n" )
1816 for k_provide in self.__rdepends_dico.keys():
1817 pkg_yocto_name=k_provide
1818 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1819 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1821 res_rdepends = set()
1822 k_provide_replace = pkg_yocto_name.replace( self.__package_name, "${PN}" )
1823 if len( self.__rdepends_dico[k_provide] ) > 0:
1824 file_d.write( "#RDEPENDS of %s (%s)\n" % ( pkg_yocto_name, k_provide_replace ) )
1826 for provide in self.__rdepends_dico[k_provide]:
1827 package_provide = provide[0]
1831 for k_package_provide in MetaSpec.mExtraRProvidesDico.keys():
1833 if package_provide in MetaSpec.mExtraRProvidesDico[k_package_provide] \
1834 or package_provide == k_package_provide:
1835 res = k_package_provide
1838 res = package_provide
1840 if res in package_replacement.keys():
1841 res = package_replacement[res]
1843 res_rdepends.add( res )
1845 for pkg in res_rdepends:
1846 res_pkg_devel = re.findall( RePattern.paternDevel, pkg )
1848 if len( res_pkg_devel ) > 0:
1849 rdepends_value = "RDEPENDS_%s += \"%s\"\n"
1850 file_d.write( rdepends_value % ( k_provide_replace, res_pkg_devel[0] + "-dev" ) )
1852 if not pkg in SPEC2YOCTO_CONFIG.get_ignore_rdepend():
1853 file_d.write( "RDEPENDS_%s += \"%s\"\n" % ( k_provide_replace, pkg ) )
1855 if len( self.__rdepends_dico[k_provide] ) > 0:
1856 file_d.write( "\n" )
1858 file_d.write( "\n" )
1860 def __create_depends( self, file_d):
1862 create depends file.
1864 if self.__package_recipes_dir is None:
1867 if not os.path.isdir( self.__package_recipes_dir ):
1868 os.makedirs( self.__package_recipes_dir )
1870 depends_dico = self.__spec_parser.get_depends()
1871 #depends_path = os.path.join( self.__package_recipes_dir, self.__base_depends_file )
1873 ignore_depend_list = SPEC2YOCTO_CONFIG.get_ignore_depend()
1874 native_depend_list = SPEC2YOCTO_CONFIG.get_native_depend()
1875 cross_depend_list = SPEC2YOCTO_CONFIG.get_cross_depend()
1878 if file_d is not None:
1879 file_d.write( "DEPENDS = \"\"\n" )
1882 for k_provide in depends_dico.keys():
1883 if len( depends_dico[k_provide] ) > 0:
1884 file_d.write( "#DEPENDS of %s\n" % k_provide )
1886 for p_provide in depends_dico[k_provide]:
1887 pp_provide = p_provide[0]
1890 if pp_provide in ignore_depend_list:
1893 for k in MetaSpec.mProvidesDico.keys():
1894 if pp_provide in MetaSpec.mProvidesDico[k] or pp_provide == k:
1897 for k_package_provide in MetaSpec.mExtraRProvidesDico.keys():
1898 if pp_provide in MetaSpec.mExtraRProvidesDico[k_package_provide]:
1899 res = k_package_provide
1903 if pp_provide not in SPEC2YOCTO_CONFIG.get_inherit_gettext() and \
1904 pp_provide not in SPEC2YOCTO_CONFIG.get_inherit("python") and \
1905 pp_provide not in SPEC2YOCTO_CONFIG.get_inherit("cmake") and \
1906 pp_provide not in SPEC2YOCTO_CONFIG.get_inherit("perl") and \
1907 pp_provide not in ignore_depend_list and \
1908 pp_provide not in native_depend_list and \
1909 pp_provide not in cross_depend_list:
1911 erro_msg = "No direct provider for package DEPENDS %s : \"%s\"."
1912 print erro_msg % ( self.__package_name, pp_provide )
1914 if res != self.__package_name :
1915 res_depends.add( res )
1917 # should be from a configue file.
1918 for res in res_depends:
1920 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1921 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1923 if pkg_yocto_name == "readline-dev":
1924 pkg_yocto_name="readline"
1926 if pkg_yocto_name in SPEC2YOCTO_CONFIG.get_inherit_gettext():
1927 file_d.write( "#Replace \"DEPENDS\" on gettext by \"inherit gettext\"\n" )
1928 file_d.write( "inherit gettext\n" )
1929 elif pkg_yocto_name in native_depend_list:
1930 file_d.write( "DEPENDS_append_class-native = \" %s-native\"\n" % pkg_yocto_name )
1931 file_d.write( "DEPENDS_append_class-target = \" %s-native\"\n" % pkg_yocto_name )
1932 elif pkg_yocto_name in cross_depend_list:
1933 file_d.write( "DEPENDS_append_class-native = \" %s\"\n" % pkg_yocto_name )
1934 file_d.write( "DEPENDS_append_class-target = \" %s-cross\"\n" % pkg_yocto_name )
1935 elif pkg_yocto_name in ignore_depend_list:
1937 elif pkg_yocto_name in SPEC2YOCTO_CONFIG.get_libtool_cross():
1938 file_d.write( "DEPENDS += \"libtool-cross\"\n" )
1939 elif pkg_yocto_name in SPEC2YOCTO_CONFIG.get_inherit("perl"):
1940 file_d.write( "inherit perlnative\n" )
1941 elif pkg_yocto_name in SPEC2YOCTO_CONFIG.get_inherit("python"):
1942 file_d.write( "inherit pythonnative\n" )
1944 file_d.write( "DEPENDS += \"%s\"\n" % pkg_yocto_name )
1946 file_d.write( "\n" )
1948 def parse_manifest_xml( src ):
1949 primaryFile = open( src, "r" )
1950 primaryXML = primaryFile.read()
1953 aElement = ElementTree.fromstring( primaryXML )
1956 for value in aElement:
1957 for project in value.getiterator():
1958 if project.tag == "project":
1959 name = project.attrib['name']
1960 c_name = clean_name( project.attrib['name'] )
1961 revision = clean_revision( project.attrib['revision'] )
1962 packages_dico[c_name] = [name, revision]
1963 elif project.tag == "default":
1964 remote = project.attrib['remote']
1965 elif project.tag == "remote":
1966 fetch = project.attrib['fetch']
1967 name = project.attrib['name']
1968 review = project.attrib['review']
1972 return remote, packages_dico
1974 class HTTPAccessFailure( Exception ):
1975 '''Indicate the http access failed'''
1977 def download_url( url ):
1980 raise HTTPAccessFailure()
1985 def download_manifest_url( url ):
1988 print "ERROR %s " % url
1989 raise HTTPAccessFailure()
1994 def download_build_xml( url ):
1995 return download_url( url + "/build.xml" )
1997 def get_project_id( xml ):
1998 aElement = ElementTree.fromstring( xml )
2000 for value in aElement:
2001 for project in value.getiterator():
2002 if project.tag == "id":
2005 def get_project_arch( xml ):
2006 aElement = ElementTree.fromstring( xml )
2008 for value in aElement:
2009 for project in value.getiterator():
2010 if project.tag == "archs":
2011 for arch in project.getiterator():
2012 if arch.tag == "arch":
2013 arch_list.append( arch.text )
2018 def clean_name( raw_name ):
2020 raw_name = raw_name.replace( "_", "-" )
2023 return raw_name.split( "/" )[-1]
2027 def clean_revision( raw_name ):
2029 return raw_name.split( "-" )[0]
2033 def patch_the_spec_file( package_spec_path,
2038 if not package_spec_path == dest_spec_path:
2039 shutil.copy2( package_spec_path, dest_spec_path )
2041 if dest_spec_dir.endswith( "/packaging" ):
2042 dest_spec_dir = dest_spec_dir[:-len( "/packaging" )]
2044 patch_command = "patch -s -p1 --fuzz=2 -d %s -i %s" % ( dest_spec_dir, patch_path )
2046 a_sub_command = SubprocessCrt()
2047 res = a_sub_command.exec_subprocess( patch_command )
2050 msg = "The patch \"%s\" can't be apply in directory \"%s\"."
2051 msg = msg % ( patch_path, dest_spec_dir )
2052 print >> sys.stderr, colorize( msg, "red" )
2053 print >> sys.stderr, colorize( "command: \"%s\"" % patch_command, "red" )
2056 return dest_spec_path
2059 def specfile_patcher( package_spec_path, project, package_name_list , dest_spec_path ):
2060 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( project )
2061 source_spec_patch_dir = os.path.join( working_dir, "specfile-patch" )
2063 patch_path_list = findSpecPatchFiles( source_spec_patch_dir, package_name_list )
2065 if len( patch_path_list ) > 0:
2067 dest_spec_dir = os.path.dirname( dest_spec_path )
2068 if not os.path.isdir( dest_spec_dir ):
2069 os.makedirs( dest_spec_dir )
2071 for patch_path in patch_path_list:
2072 package_spec_path = patch_the_spec_file( package_spec_path,
2077 return package_spec_path
2081 def __init__( self, project, name, path, revision, priority, git_src ):
2082 self.__project = project
2084 self.git_path = path
2085 self.git_revision = revision
2086 self.priority = priority
2087 self.git_src = git_src
2088 self.__my_meta_spec = None
2090 def printMe( self ):
2091 print "%s %s %s %s" % ( self.name , self.git_path, self.git_revision, self.git_src )
2093 def create_MetaSpec( self , package_recipes_dir, source_spec_dir ):
2094 source_path = os.path.join( source_spec_dir , self.name , "packaging" )
2095 package_spec_path = findBestSpecFile( source_path, self.name )
2097 if package_spec_path == -1:
2098 msg = "no initial spec file for package \"%s\" in directory \"%s\"."
2099 msg = msg % ( self.name, source_path )
2100 print >> sys.stderr, colorize( msg, "red" )
2103 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( self.__project )
2104 specfile_patched_dir = os.path.join( working_dir, "specfile-patched" )
2105 dest_spec_dir = os.path.join( specfile_patched_dir , self.name )
2106 dest_spec_packaging_dir = os.path.join( dest_spec_dir , "packaging" )
2107 dest_spec_path = os.path.join( dest_spec_packaging_dir ,
2108 os.path.basename( package_spec_path ) )
2111 package_spec_path = specfile_patcher( package_spec_path,
2113 [self.name, self.name + "-initial"],
2116 self.__my_meta_spec = MetaSpec( os.path.join( package_recipes_dir, self.name ),
2123 def make_alias_package( project, packages_dico ):
2125 #TO DO need to be do in conf file.
2126 alias_package["python-libxml2"] = "libxml2"
2127 alias_package["python-magic"] = "file"
2128 alias_package["cross-arm-binutils"] = "binutils"
2129 alias_package["cross-armv7hl-gcc47-icecream-backend"] = "gcc47"
2130 alias_package["libffi47"] = "gcc47"
2132 for alias in alias_package.keys():
2133 alias_to = alias_package[alias]
2134 if alias_to in packages_dico.keys() and alias not in packages_dico.keys():
2135 a_package_def = packages_dico[alias_to]
2136 packages_dico[alias] = package_def( project,
2138 a_package_def.git_path,
2139 a_package_def.git_revision,
2140 a_package_def.priority,
2141 a_package_def.git_src )
2143 return packages_dico
2145 class manifestCollection:
2147 class for all package in a distro.
2149 def __init__( self , project ):
2153 self.__my_project = project
2155 self.__recipes_list = None
2157 if not SPEC2YOCTO_CONFIG.is_valide_project( self.__my_project ):
2158 msg = "\"%s\" has no configuration in file \"%s\"."
2159 msg = msg % ( self.__my_project, CONFIGURATION_FILE_PATH )
2160 print >> sys.stderr, colorize( msg, "red" )
2163 #Just get the list of manifest uri.
2164 self.__my_manifest_meta_list = SPEC2YOCTO_CONFIG.get_manifest_meta_list( self.__my_project )
2166 self.__my_manifest_file_list = {}
2167 #Load the project manifest.
2168 self.__update_meta_manifests()
2170 self.__my_package_dico = {}
2171 self.__generate_package()
2173 self.__my_package_dico = make_alias_package( self.__my_project, self.__my_package_dico )
2175 def parse_manifest_xml( self, src ):
2176 primaryFile = open( src, "r" )
2177 primaryXML = primaryFile.read()
2180 aElement = ElementTree.fromstring( primaryXML )
2183 for value in aElement:
2184 for project in value.getiterator():
2185 if project.tag == "project":
2186 name = project.attrib['name']
2187 short_name=clean_name( name )
2188 revision = clean_revision( project.attrib['revision'] )
2189 packages_dico[short_name] = [name, revision]
2190 elif project.tag == "default":
2191 remote = project.attrib['remote']
2192 elif project.tag == "remote":
2193 fetch = project.attrib['fetch']
2194 name = project.attrib['name']
2198 return remote, packages_dico
2200 def print_list( self ):
2201 pkg_list = self.__my_package_dico.keys()
2203 for package in pkg_list:
2204 self.__my_package_dico[package].printMe()
2206 def __generate_package( self ):
2207 for meta_manifest in self.__my_manifest_file_list.keys():
2208 manifest_uri = self.__my_manifest_file_list[meta_manifest]
2209 manifest_git = SPEC2YOCTO_CONFIG.get_manifest_default_git_src( meta_manifest )
2210 manifest_priority = SPEC2YOCTO_CONFIG.get_manifest_priority( meta_manifest )
2211 remote, packages_dico = self.parse_manifest_xml( manifest_uri )
2213 if manifest_git is not None:
2214 remote = manifest_git
2216 whitelist = SPEC2YOCTO_CONFIG.get_list(self.__my_project, "whitelist")
2217 if len( whitelist ) != 0:
2218 list_packages = set(whitelist)
2220 list_packages = set(packages_dico.keys())
2222 blacklist = set(SPEC2YOCTO_CONFIG.get_list(self.__my_project, "blacklist"))
2224 list_packages=list_packages.difference(blacklist)
2226 for package in list_packages:
2227 if package in packages_dico.keys():
2228 [path, revision] = packages_dico[package]
2230 if package in self.__my_package_dico.keys():
2231 if manifest_priority > self.__my_package_dico[package].priority:
2232 self.__my_package_dico[package] = package_def( self.__my_project,
2238 elif manifest_priority == self.__my_package_dico[package].priority:
2239 msg = "most of one occurence of package \"%s\" ."
2240 msg = msg % ( package )
2241 print >> sys.stderr, colorize( msg, "red" )
2244 self.__my_package_dico[package] = package_def( self.__my_project,
2250 for package in whitelist:
2251 if package not in self.__my_package_dico.keys():
2252 msg = "package \"%s\" is in the white list but not in the manifest."
2253 msg = msg % ( package )
2254 print >> sys.stderr, colorize( msg, "red" )
2257 def __update_meta_manifests( self ):
2259 find/download all manifest.xml file.
2261 for meta_manifest in self.__my_manifest_meta_list:
2262 meta_manifest_uri = SPEC2YOCTO_CONFIG.get_manifest_uri( meta_manifest )
2263 if meta_manifest_uri is None:
2264 msg = "\"%s\" has no URI configuration in file \"%s\"."
2265 msg = msg % ( meta_manifest_uri, CONFIGURATION_FILE_PATH )
2266 print >> sys.stderr, colorize( msg, "red" )
2268 if meta_manifest_uri.startswith( "http" ):
2269 if meta_manifest_uri.endswith( ".xml" ):
2270 meta_manifest_url_path = meta_manifest_uri
2271 manifest_name = os.path.basename(meta_manifest_uri)
2273 xml_str = download_build_xml( meta_manifest_uri )
2274 project_id = get_project_id( xml_str )
2275 list_arch = get_project_arch( xml_str )
2277 arch = SPEC2YOCTO_CONFIG.get_project_arch( self.__my_project )
2278 buildtarget = "x86_64-wayland"
2280 if ( arch == "i586" ) and ( "ia32" in list_arch ):
2282 buildtarget ="ia32-wayland"
2284 elif ( arch is None ) and ( len( list_arch ) > 0 ):
2287 elif ( arch not in list_arch ):
2290 manifest_name = "%s_%s.xml" % ( project_id, buildtarget )
2291 meta_manifest_url_path = "%s/builddata/manifest/%s"
2292 meta_manifest_url_path = meta_manifest_url_path % ( meta_manifest_uri,
2295 manifest_xml = download_manifest_url( meta_manifest_url_path )
2296 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( self.__my_project )
2298 meta_manifest_dir = os.path.join( working_dir, "manifest_file" )
2299 meta_manifest_path = os.path.join( meta_manifest_dir, manifest_name )
2301 if not os.path.isdir( meta_manifest_dir ):
2302 os.makedirs( meta_manifest_dir )
2304 with open( meta_manifest_path, "w" ) as manifest_xml_file:
2305 manifest_xml_file.write( manifest_xml )
2307 if not os.path.isfile( meta_manifest_uri ):
2308 msg = "In the project \"%s\" the manifest \"%s\" is not a valid file."
2309 msg = msg % ( self.__my_project, meta_manifest_uri )
2310 print >> sys.stderr, colorize( msg, "red" )
2313 meta_manifest_path = meta_manifest_uri
2315 self.__my_manifest_file_list[ meta_manifest ] = meta_manifest_path
2317 def createRecipes( self ):
2321 self.__recipes_dir_dest = SPEC2YOCTO_CONFIG.get_recipes_sources_directory( self.__my_project )
2323 self.__clean_old_bb_files(self.__recipes_dir_dest)
2325 if self.__recipes_dir_dest is None:
2326 msg = "In the project \"%s\" recipes_dir_sources is not define."
2327 msg = msg % ( self.__my_project )
2328 print >> sys.stderr, colorize( msg, "red" )
2330 elif not os.path.isdir( self.__recipes_dir_dest ):
2331 os.makedirs( self.__recipes_dir_dest )
2333 self.__meta_spec_dico = {}
2334 self.__meta_spec_boot_strap_dico = {}
2336 self.__set_oe_package_blacklist()
2337 self.__set_native_package_blacklist()
2339 self.__init_depends()
2340 self.__init_MetaSpec()
2343 def __clean_old_bb_files( self ,path):
2344 for root, dirs, files in os.walk(path):
2345 for a_file in files:
2346 if a_file.endswith(".bb"):
2347 os.unlink( os.path.join(path, root, a_file) )
2350 def __set_oe_package_blacklist( self ):
2352 load oe_package_blacklist
2354 list_package = SPEC2YOCTO_CONFIG.get_list(self.__my_project, "runtime_blacklist")
2355 MetaSpec.mOePackageBlacklist.extend( list_package )
2357 def __set_native_package_blacklist( self ):
2359 load oe_package_blacklist
2361 list_package = SPEC2YOCTO_CONFIG.get_list(self.__my_project, "native_blacklist")
2362 MetaSpec.mNativePackageBlacklist.extend( list_package )
2365 def __init_MetaSpec( self ):
2366 pkg_list = self.__my_package_dico.keys()
2369 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( self.__my_project )
2370 source_spec_dir = os.path.join( working_dir, "specfile-initial" )
2372 for package in pkg_list:
2373 self.__my_package_dico[package].create_MetaSpec( self.__recipes_dir_dest,
2376 def __init_depends( self ):
2380 self.__load_package_provided_extra()
2382 pkg_list = self.__my_package_dico.keys()
2385 def __load_package_provided_extra( self ):
2387 load_package_provided_extra
2389 provided_extra_dico = SPEC2YOCTO_CONFIG.get_provided_extra( self.__my_project )
2391 for k_package in provided_extra_dico.keys():
2392 raw_list=provided_extra_dico[k_package]
2394 if k_package not in MetaSpec.mProvidesDico.keys():
2395 MetaSpec.mProvidesDico[k_package] = []
2397 MetaSpec.mProvidesDico[k_package].extend( raw_list )
2399 if k_package not in MetaSpec.mExtraRProvidesDico.keys():
2400 MetaSpec.mExtraRProvidesDico[k_package] = []
2401 MetaSpec.mExtraRProvidesDico[k_package].extend( raw_list )
2403 TERMINAL_COLORS = {"black": "\033[30;1m",
2404 "red": "\033[31;1m",
2405 "green": "\033[32;1m",
2406 "yellow": "\033[33;1m",
2407 "blue": "\033[34;1m",
2408 "magenta": "\033[35;1m",
2409 "cyan": "\033[36;1m",
2410 "white": "\033[37;1m",
2411 "default": "\033[0m"}
2413 def colorize( text, color = "green" ):
2415 Return a colorized copy of `text`.
2416 See Utils.TERMINAL_COLORS.keys() for available colors.
2418 return TERMINAL_COLORS.get( color, "" ) + text + TERMINAL_COLORS["default"]
2421 def check_group_file( project ):
2422 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( project )
2424 group_uri = SPEC2YOCTO_CONFIG.get_group_uri( project )
2426 if group_uri.startswith( "http" ):
2427 group_file_path = os.path.join( working_dir, "group/group.xml" )
2428 group_xml = download_url( group_uri )
2430 with open( group_file_path, "w" ) as group_file:
2431 group_file.write( group_xml )
2433 return group_file_path
2437 def parse_group_xml( src ):
2438 groupFile = open( src, "r" )
2439 groupXML = groupFile.read()
2442 aElement = ElementTree.fromstring( groupXML )
2445 for group in aElement:
2446 if group.tag == "group":
2449 for element in group:
2450 if element.tag == "name":
2451 group_name = element.text
2452 elif element.tag == "packagelist":
2453 for packagereq in element:
2454 list_package.append(packagereq.text)
2456 packages_dico[group_name]=list_package
2457 return packages_dico
2459 def dump_group(project,group_dico):
2461 recipes_group_directory = SPEC2YOCTO_CONFIG.get_recipes_group_directory( project )
2463 for group in group_dico.keys():
2464 group_str = group.replace( " ", "-" )
2465 path = os.path.join( recipes_group_directory, "packagegroup-tizen-%s.bb" % group_str )
2467 with open(path,"w") as group_file:
2468 group_file.write( "SUMMARY = \"%s\"\n" % group )
2469 group_file.write( "DESCRIPTION = \"%s\"\n" % group )
2470 group_file.write( "LICENSE = \"MIT\"\n" )
2471 group_file.write( "DEPENDS = \"virtual/kernel\"\n" )
2472 group_file.write( "PR = \"r1\"\n" )
2474 group_file.write( "inherit packagegroup\n" )
2475 group_file.write( "\n" )
2476 group_file.write( "PACKAGE_ARCH = \"${MACHINE_ARCH}\"\n" )
2477 group_file.write( "\n" )
2479 group_file.write( "RDEPENDS_${PN} = \"\" \n\n" )
2480 for pkg in group_dico[group]:
2481 group_file.write( "RDEPENDS_${PN} += \"%s\"\n" % pkg )
2483 def generateBuildStatus( project_path ):
2486 if not os.path.isdir( project_path ):
2487 msg = "The path \"%s\" is not a directory."
2488 msg = msg % ( project_path )
2489 print >> sys.stderr, colorize( msg, "red" )
2492 for package_path in os.listdir( project_path ):
2493 project_full_path = os.path.join( project_path, package_path )
2494 if ( package_path == "build_stats" ) and os.path.isfile( project_full_path ) :
2497 elif os.path.isdir( project_full_path ):
2498 BN, PV, PR = cleanPackageName( package_path )
2499 res_status = check_package_status( project_full_path )
2501 if BN.endswith("-native"):
2502 res_native[BN] = [PV ] + res_status
2504 res[BN] = [PV ] + res_status
2507 elif package_path in ["."]:
2511 msg = "This directory should not contain the file \"%s\"."
2512 msg = msg % ( package_path )
2513 print >> sys.stderr, colorize( msg, "red" )
2516 return res_native, res
2518 def cleanPackageName( package_path ):
2519 if package_path.count( "-" ) < 2:
2520 msg = "unknow format for package \"%s\"."
2521 msg = msg % ( package_path )
2522 print >> sys.stderr, colorize( msg, "red" )
2525 PR=package_path[package_path.rindex("-")+1:]
2526 package_path=package_path[:package_path.rindex("-")]
2527 PV=package_path[package_path.rindex("-")+1:]
2528 BN=package_path[:package_path.rindex("-")]
2533 def check_package_status( project_full_path ):
2534 tasks_order = ["do_fetch",
2541 "do_populate_sysroot",
2544 "do_package_write_rpm",
2548 for package_task in os.listdir( project_full_path ):
2549 if package_task in tasks_order:
2550 task_index = tasks_order.index( package_task )
2552 if task_index > max_index:
2553 max_index = task_index
2556 msg = "No log task in \"%s\"."
2557 msg = msg % ( project_full_path )
2558 print >> sys.stderr, colorize( msg, "red" )
2561 last_task = tasks_order[max_index][3:]
2565 with open( os.path.join( project_full_path, tasks_order[max_index] ) ) as status_file:
2566 for line in status_file:
2567 if line.startswith( "Status: " ):
2568 status = line[len( "Status: " ):].replace( "\n", "" ).replace( " ", "" )
2570 if last_task == "package_write_rpm" and status == "PASSED":
2573 return [last_task, status]
2575 def clean_Packagegroup( project,group_dico ):
2578 package_replacement = SPEC2YOCTO_CONFIG.get_substitute( project )
2580 for group in group_dico.keys():
2581 group_dico_tmp[group] = []
2582 for package in group_dico[group]:
2583 if package in package_replacement.keys():
2584 group_dico_tmp[group].append( package_replacement[package] )
2586 group_dico_tmp[group].append( package )
2588 return group_dico_tmp
2591 def check_debugmode( opts_debug ):
2593 if opts_debug == "no":
2595 elif opts_debug == "yes":
2599 class spec2yoctoCommandline( cmdln.Cmdln ):
2603 def do_manifestToList( self, subcmd, opts, project = None ):
2604 """${cmd_name}: print the list of package in projects.
2610 project = SPEC2YOCTO_CONFIG.get_current_project()
2612 pkg_co = manifestCollection( project )
2615 def do_createRecipes( self, subcmd, opts, project = None ):
2616 """${cmd_name}: create all packages recipes.
2622 project = SPEC2YOCTO_CONFIG.get_current_project()
2624 pkg_co = manifestCollection( project )
2625 pkg_co.createRecipes()
2627 @cmdln.option( "--package_pn",
2630 help = "select the package_pn." )
2631 def do_findBestSpecFile( self, subcmd, opts, package_path ):
2632 """${cmd_name}: print the speec file associate to package.
2637 res = findBestSpecFile( package_path, opts.package_pn )
2640 @cmdln.option( "--package_pn",
2643 help = "select the package_pn." )
2644 def do_findSpecPatchFiles( self, subcmd, opts, patch_dir, ):
2645 """${cmd_name}: print patch from "specfile-patch" directory associate to package.
2650 res = findSpecPatchFiles( patch_dir, opts.package_pn )
2651 print " ".join( res )
2653 @cmdln.option( "--package_pn",
2656 help = "select the package_pn." )
2657 @cmdln.option( "--project",
2660 help = "select the package_pn." )
2661 def do_specfile_patcher( self, subcmd, opts, package_spec_path ):
2662 """${cmd_name}: patch the spec file with patch from "specfile-patch" directory.
2667 if opts.project is None:
2668 project = SPEC2YOCTO_CONFIG.get_current_project()
2670 project = opts.project
2672 res = specfile_patcher( package_spec_path, project, opts.package_pn, package_spec_path )
2675 def do_createPackagegroup( self, subcmd, opts, project = None ):
2676 """${cmd_name}: print the list of package in projects.
2682 project = SPEC2YOCTO_CONFIG.get_current_project()
2685 res = SPEC2YOCTO_CONFIG.get_group( project )
2686 group_file_path = check_group_file( project )
2687 group_dico= parse_group_xml( group_file_path )
2689 group_dico = clean_Packagegroup( project, group_dico )
2691 dump_group(project,group_dico)
2693 @cmdln.option( "--debug",
2696 help = "run the in debug mode.[yes/no]" )
2697 @cmdln.option( "--project",
2700 help = "select the project." )
2701 @cmdln.option( "--package_pn",
2704 help = "select the package_pn." )
2705 def do_prep( self, subcmd, opts, spec_path ):
2706 """${cmd_name}: print the bash code of the %prep section of a spec file.
2711 check_debugmode( opts.debug )
2713 if opts.project is None:
2714 project = SPEC2YOCTO_CONFIG.get_current_project()
2716 project = opts.project
2718 res = SpecParser( spec_path, package_pn = opts.package_pn ).get_prep_section()
2722 @cmdln.option( "--debug",
2725 help = "run the in debug mode.[yes/no]" )
2726 @cmdln.option( "--project",
2729 help = "select the project." )
2730 @cmdln.option( "--package_pn",
2733 help = "select the package_pn." )
2734 def do_compile( self, subcmd, opts, spec_path ):
2735 """${cmd_name}: print the bash code of the %build section of a spec file.
2740 check_debugmode( opts.debug )
2742 if opts.project is None:
2743 project = SPEC2YOCTO_CONFIG.get_current_project()
2745 project = opts.project
2747 res = SpecParser( spec_path, package_pn = opts.package_pn ).get_build_section()
2751 @cmdln.option( "--debug",
2754 help = "run the in debug mode.[yes/no]" )
2755 @cmdln.option( "--project",
2758 help = "select the project." )
2759 @cmdln.option( "--package_pn",
2762 help = "select the package_pn." )
2763 def do_install( self, subcmd, opts, spec_path ):
2764 """${cmd_name}: print the bash code of the %install section of a spec file.
2769 check_debugmode( opts.debug )
2772 if opts.project is None:
2773 project = SPEC2YOCTO_CONFIG.get_current_project()
2775 project = opts.project
2777 res = SpecParser( spec_path, package_pn = opts.package_pn ).get_install_section()
2781 @cmdln.option( "--debug",
2784 help = "run the in debug mode.[yes/no]" )
2785 def do_generateBuildStatus( self, subcmd, opts, project_path ):
2786 """${cmd_name}: print the status and the the build state of packages,
2787 builded in a single command.
2789 build/tmp-eglibc/buildstats/core-image-minimal-qemux86/XXXX/
2793 check_debugmode( opts.debug )
2795 res_native, res = generateBuildStatus( project_path )
2797 res_native_keys = res_native.keys()
2798 res_keys = res.keys()
2800 res_native_keys.sort()
2803 for r in res_native_keys:
2804 print r + "\t" + "\t".join( res_native[r] )
2807 print r + "\t" + "\t".join( res[r] )
2810 @cmdln.option( "--debug",
2813 help = "run the in debug mode.[yes/no]" )
2814 def do_generatePseudoSpecfile( self, subcmd, opts, spec_path ):
2815 """${cmd_name}: generate a spec file use by yocto, for packaging rpm.
2820 check_debugmode( opts.debug )
2822 a_spec_parser = SpecParser( spec_path )
2823 a_spec_parser.parse_raw_spec_file()
2824 res = a_spec_parser.get_clean_raw()
2828 @cmdln.option( "--debug",
2831 help = "run the in debug mode.[yes/no]" )
2832 @cmdln.option( "--project",
2835 help = "select the project." )
2836 def do_working_dir( self, subcmd, opts ):
2837 """${cmd_name}: return the proto directory.
2842 check_debugmode( opts.debug )
2844 if opts.project is None:
2845 project = SPEC2YOCTO_CONFIG.get_current_project()
2847 project = opts.project
2849 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( project )
2850 if working_dir != 1:
2854 commandline = spec2yoctoCommandline()
2857 res = commandline.main()
2858 except ValueError as ve:
2860 print >> sys.stderr, colorize( str( ve ), "red" )
2862 except EnvironmentError as ioe:
2863 # commandline.do_help([sys.argv[0]])
2865 print >> sys.stderr, colorize( str( ioe ), "red" )
2866 if hasattr( ioe, "spec2yocto_config_error" ):
2867 msg = "See '--config' option"
2868 print >> sys.stderr, colorize( msg, "red" )
2870 # except Exception as e_all :
2872 # print >> sys.stderr, colorize( str( e_all ), "red" )
2876 if __name__ == '__main__':