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_manifest_buildtarget(self, meta_manifest):
133 return the default buildtarget of the project.
135 return self.__get_value( meta_manifest, "buildtarget", None )
137 def get_working_dir( self, projet ):
139 return the working dir of the project.
141 res = self.__get_value( projet, "working_dir", "/tmp" )
143 res = os.path.expanduser( res )
144 res = os.path.expandvars( res )
147 def get_list(self, project, list_name):
149 Returns the corresponding list.
151 res_list = self.__get_list( project, list_name, [] )
153 for element in res_list:
154 res.extend(self.__get_list(element, "list", []))
157 def get_substitute( self , project = None ):
160 for package in self.__config_parser.options( "substitute" ):
161 package_replace = self.__get_value( "substitute", package, None )
162 if package_replace is not None:
163 res[package] = package_replace
166 def __get_list( self, section, option, default_value ):
168 generic fonction to get list value.
170 if ( section in self.__config_parser.sections() ) and \
171 ( option in self.__config_parser.options( section ) ):
172 tmp_res = str( self.__config_parser.get( section, option ) )
173 return tmp_res.replace( " ", "" ).split( "," )
177 def get_whitelist( self , project ):
182 whitelist_list=self.__get_list(project,"whitelist", None)
183 for whitelist_v in whitelist_list:
184 whitelist_uri = os.path.expanduser(os.path.expandvars(self.__get_value(whitelist_v,"uri", None )))
186 if whitelist_uri.startswith( "http" ):
187 whitelist_file=download_url( whitelist_uri )
189 f=open(whitelist_uri,'r')
190 whitelist_file=f.read()
193 for w_pkg in whitelist_file.split("\n"):
195 pkg,path=w_pkg.split("\t")
197 packages_dico[pkg]=path
203 def __get_value( self, section, option, default_value ):
205 generic fonction to get value.
207 if ( section in self.__config_parser.sections() ) and \
208 ( option in self.__config_parser.options( section ) ):
209 tmp_res = self.__config_parser.get( section, option )
214 def get_recipes_sources_directory( self, project ):
216 return a list of the recipes directory needed to build the image.
218 res = self.__get_value( project, 'recipes_dir_sources', None )
219 res = os.path.expanduser( res )
220 res = os.path.expandvars( res )
223 def get_recipes_group_directory( self, project ):
224 res = self.__get_value( project, 'recipes_dir_group', None )
225 res = os.path.expanduser( res )
226 res = os.path.expandvars( res )
230 def get_group( self , project = None ):
232 project = self.get_current_project()
233 return self.__get_list( project, 'group', [] )
236 def get_target_cpu( self , project = None ):
241 project = self.get_current_project()
242 return self.__get_value( project, 'arch' , None )
244 def get_bb_autoreconf_blacklist( self , project = None ):
246 return a list of package with no autoreconf.
249 project = self.get_current_project()
251 blacklist_list = self.__get_list( project, "blacklist_autoreconf", [] )
253 for blacklist in blacklist_list:
254 res.extend( self.__get_list( blacklist, "blacklist", [] ) )
258 def get_provided_extra( self , project = None ):
261 project = self.get_current_project()
263 provided_extra_list = self.__get_list( project, "provided-extra", [] )
264 provided_extra_dico={}
265 for provided_extra in provided_extra_list:
266 for package in self.__config_parser.options( provided_extra ):
267 provided_list = self.__get_list( provided_extra, package, [] )
268 provided_extra_dico[package] = provided_list
269 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(self, package):
309 some buildRequire mean inherit_cmake package not depends runtime.
313 def get_group_uri( self, project ):
315 return self.__get_value( project, 'group_uri', None )
318 SPEC2YOCTO_CONFIG = Spec2yoctoConfig()
320 # Implementation taken from http://hetland.org
321 def levenshtein( a, b ):
322 """Calculates the Levenshtein distance between a and b."""
323 n, m = len( a ), len( b )
325 # Make sure n <= m, to use O(min(n,m)) space
329 current = range( n + 1 )
330 for i in range( 1, m + 1 ):
331 previous, current = current, [i] + [0] * n
332 for j in range( 1, n + 1 ):
333 add, delete = previous[j] + 1, current[j - 1] + 1
334 change = previous[j - 1]
335 if a[j - 1] != b[i - 1]:
337 current[j] = min( add, delete, change )
341 def get_packaging_files( package_path ):
343 for tmp_res in os.listdir( package_path ):
344 if tmp_res.endswith( ".spec" ) and os.path.isfile( package_path + "/" + tmp_res ):
345 res.append( tmp_res )
348 def findBestSpecFile( package_path, package_name ):
350 Find the name of the spec file which matches best with `package_name`
353 package_spec_dir = package_path
354 package_spec_dir = os.path.expanduser( package_spec_dir )
355 package_spec_dir = os.path.expandvars( package_spec_dir )
357 specFileList = get_packaging_files( package_path )
360 if len( specFileList ) < 1:
361 # No spec file in list
363 elif len( specFileList ) == 1:
365 specFile = specFileList[0]
368 for spec in specFileList:
369 if str( spec[:-5] ) == str( package_name ):
370 # This spec file has the same name as the package
373 elif spec.startswith( package_name ):
374 # This spec file has a name which looks like the package
375 sameStart.append( spec )
378 if len( sameStart ) > 0:
379 # Sort the list of 'same start' by the Levenshtein distance
380 sameStart.sort( key = lambda x: levenshtein( x, package_name ) )
381 specFile = sameStart[0]
383 # No spec file starts with the name of the package,
384 # sort the whole spec file list by the Levenshtein distance
385 specFileList.sort( key = lambda x: levenshtein( x, package_name ) )
386 specFile = specFileList[0]
389 msg = "Found no spec file matching package name '%s'" % package_name
393 spec_full_path = os.path.join( package_spec_dir, specFile )
394 return spec_full_path
396 def findSpecPatchFiles( patch_dir_path, package_name_list ):
398 Find the name of the patch for the spec file which matches best with `package_name`
402 patch_dir_path = os.path.expanduser( patch_dir_path )
403 patch_dir_path = os.path.expandvars( patch_dir_path )
404 if package_name_list is not None:
405 for patch_name in set( package_name_list ):
406 for patch_extend in ["", "-yocto"]:
407 patch_file = patch_name + patch_extend + ".spec.patch"
408 patch_path = os.path.join( patch_dir_path, patch_file )
409 if os.path.isfile( patch_path ):
410 patch_list.append( patch_path )
416 class SubprocessCrt( object ):
418 usefull class to control subprocess
420 def __init__( self ):
422 Initialize subprocess.
427 def get_last_res( self ):
429 return the last subprocess output.
431 return self.output_res
433 def __read_subprocess_output( self, outputs, f_stdout, f_stderr ):
435 read the stdout, stderr of the subprocess
439 for file_d in select.select( [f_stdout, f_stderr], [], [], select_timeout )[0]:
441 output = file_d.read()
442 if f_stdout == file_d:
443 self.output_res += output
445 if DEBUG_RUN and ( len( output ) > 0 ):
446 print "ERROR ****", output, len( output )
448 for line in output.split( "\n" ):
449 if not line == b"" or not output.endswith( "\n" ):
450 outputs[file_d]["EOF"] = False
452 if line == b"" and not output.endswith( "\n" ):
453 outputs[file_d]["EOF"] = True
455 res_clean = line.decode( "utf8", "replace" ).rstrip()
460 self.__idle_time += select_timeout
466 def exec_subprocess( self, command ):
468 Execute the "command" in a sub process,
469 the "command" must be a valid bash command.
470 _args and _kwargs are for compatibility.
475 # need Python 2.7.3 to do shlex.split(command)
476 splitted_command = shlex.split( str( command ) )
477 a_process = subprocess.Popen( splitted_command,
478 stdout = subprocess.PIPE,
479 stderr = subprocess.PIPE )
480 f_stdout = a_process.stdout
481 f_stderr = a_process.stderr
483 flags = fcntl.fcntl( f_stdout, fcntl.F_GETFL )
484 if not f_stdout.closed:
485 fcntl.fcntl( f_stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK )
487 flags = fcntl.fcntl( f_stderr, fcntl.F_GETFL )
488 if not f_stderr.closed:
489 fcntl.fcntl( f_stderr, fcntl.F_SETFL, flags | os.O_NONBLOCK )
491 outputs = {f_stdout: {"EOF": False},
492 f_stderr: {"EOF": False}}
495 while ( ( not outputs[f_stdout]["EOF"] and
496 not outputs[f_stderr]["EOF"] ) or
497 ( a_process.poll() == None ) ):
499 self.__read_subprocess_output( outputs, f_stdout, f_stderr )
500 except select.error as error:
501 # see http://bugs.python.org/issue9867
502 if error.args[0] == errno.EINTR:
503 print "Got select.error: %s" % unicode( error )
508 # maybe a_process.wait() is better ?
509 poll_res = a_process.poll()
512 return self.output_res
516 def of usefull re pattern to parse spec file.
518 pattern_patch = r'([pP]atch[\d]*)[\s]*:[\s]*.*'
519 patternUrlSourceFile = r'Source[\d]*[\s]*:[\s]*([http,ftp].*/)(.*)'
520 patternUrlPatchFile = r'Patch[\d]*[\s]*:[\s]*([http,ftp].*/)(.*)'
522 patternPatch = r'[pP]atch([\d]*)[\s]*:[\s]*(.*)'
523 patternSource = r'Source([\d]*)[\s]*:[\s]*(.*)'
525 patternPatchCommand = r'#(patch)([\d]*)(.*)'
527 patternDescription = r'^Summary:\s*(.*)'
528 patternUrl = r'^Url:\s*(.*)'
529 patternGroup = r'^Group:\s*(.*)'
530 patternLicense = r'^License:\s*(.*)'
531 patternVersion = r'^Version:\s*(.*)'
533 patternFiles = r'^%files\s*(.*)'
535 patternName = r'^Name:\s*(.*)'
537 patternPackage = r'^%package\s*(.*)'
538 provides_package = r'^Provides:\s*(.*)'
540 buildPkgconfig = r'pkgconfig\((.*)\).*'
542 pkgRe = r'([^ \t\n\r\f\v,]+)(?:\s+(<|>|<=|>=|=|==)\s+([^ \t\n\r\f\v,]+))?'
544 buildRequiresPackage = r'^BuildRequires:\s*(.*)'
545 requiresPackage = r'^Requires(?:\(\w+\))?:\s*(.*)'
547 paternDevel = "(.*)-devel"
549 pkgconfig_name = "/usr/lib/pkgconfig/([^*]*).pc"
551 def __init__( self ):
556 def get_macro_directory_path( current_cpu ):
558 return all the valid macro directory.
561 for macro_dir in ["lib/*",
563 "lib/platform/%s-linux/macros" % current_cpu,
568 macro_paths += os.path.join( "/usr/share/spec2yocto/macro", macro_dir ) + " "
576 msubprocess = SubprocessCrt()
577 def __init__( self, package_spec_path, package_pn = None ):
581 self.__introduction_section = "introduction_section"
582 self.__package = "%package"
583 self.__description = "%description"
584 self.__prep_flag = "%prep"
585 self.__build_flag = "%build"
586 self.__install_flag = "%install"
587 self.__clean_flag = "%clean"
588 self.__files_flag = "%files"
589 self.__check_flag = "%check"
590 #pkg_preinst, pkg_postinst, pkg_prerm, and pkg_postrm
591 self.__post_flag = "%post"
592 self.__preun_flag = "%preun"
593 self.__postun_flag = "%postun"
594 self.__pre_flag = "%pre"
596 self.__verifyscript_flag = "%verifyscript"
597 self.__changelog_flag = "%changelog"
598 self.__list_section = [self.__package,
610 self.__verifyscript_flag,
611 self.__changelog_flag]
613 self.__package_spec_path = package_spec_path
614 self.__package_pn = package_pn
616 self.__parsed_spec_file = None
617 self.__order_list = []
618 self.__spect_dico = {}
621 self.__order_raw_list = []
622 self.__raw_spect_dico = {}
624 self.__cpu = SPEC2YOCTO_CONFIG.get_target_cpu()
625 self.__cpu_native = platform.machine()
627 self.__convert_spec_file()
628 self.__parse_parsed_spec_file()
629 self.__base_name = self.get_name()
631 self.__pkg_config = []
633 def __find_patch( self ):
635 find the patchs of the spec file.
638 with open( self.__package_spec_path ) as file_d:
639 spec_file = file_d.read()
640 res_tmp = re.findall( RePattern.pattern_patch, spec_file )
641 for a_res in res_tmp:
642 self.__patchs.append( a_res.replace( "Patch", "patch" ) )
644 def __is_native_build( self ):
646 return True if the package is native.
648 res_1 = ( self.__package_pn is not None )
652 res_2 = self.__package_pn.endswith( "-native" )
656 def init_rpmspec_command( self ):
658 init rpmspec_command to parse spec file.
660 rpmspec_command = "rpmspec "
662 if self.__is_native_build():
663 current_cpu = self.__cpu_native
665 current_cpu = self.__cpu
667 rpmspec_command += " --macros=\"%s\" " % get_macro_directory_path( current_cpu )
669 rpmspec_command += " --define='buildroot ${D}' "
670 rpmspec_command += " --define='optflags \\$CFLAGS' "
671 if self.__is_native_build():
672 # Not the better way to do this
673 rpmspec_command += " --define='basearch i386' "
674 # I guess other tool must be set for native build.
675 rpmspec_command += " --define='__cc gcc' "
676 # the default value of the macro is %{nil}
677 base_prefix = os.getenv( "base_prefix" )
678 if ( base_prefix != "" ) and ( base_prefix is not None ):
679 rpmspec_command += " --define='_buildPrefix %s' " % base_prefix
681 rpmspec_command += " --define='%find_lang echo no find_lang for package native'"
683 rpmspec_command += " --define='setup #setup' "
684 rpmspec_command += " --define='setup0 #setup0' "
686 package_dir = os.path.dirname( self.__package_spec_path )
688 rpmspec_command += " --define='SOURCES ${S}/packaging/' "
689 rpmspec_command += " --define='_sourcedir ${S}/packaging/' "
691 rpmspec_command += " --define='BUILD_BASENAME %{basename}' "
692 rpmspec_command += " --define='find_lang #find_lang' "
693 rpmspec_command += " --define='fdupes #fdupes' "
694 rpmspec_command += " --define='lang_package #lang_package' "
695 rpmspec_command += " --define='with_wayland 1' "
698 package_name = os.path.basename( self.__package_spec_path )[:-5]
700 if package_name in SPEC2YOCTO_CONFIG.get_bb_autoreconf_blacklist() :
701 oe_runconf2 = '''oe_runconf2'''
702 rpmspec_command += " --define='%%_configure %s'" % oe_runconf2
704 return rpmspec_command
707 def __convert_spec_file( self ):
709 init convert spec to expand spec file.
711 tmp_package_spec_path = self.__package_spec_path
713 # we can't use python rpm API to parse the spec file so we need to exec rpmspec\
714 # in a subprocess and parse the result.
715 rpmspec_command = self.init_rpmspec_command()
717 # it's import to remove all "Source" url because if rpm dan't find the source,\
718 # it try to downloads the file from the url.
719 with open( tmp_package_spec_path, 'r' ) as current_spec_file:
720 current_spec_string = current_spec_file.read()
721 res_url_source_files = re.findall( RePattern.patternUrlSourceFile, current_spec_string )
723 if len( res_url_source_files ) > 0:
724 for res_url in res_url_source_files:
725 long_url = res_url[0] + res_url[1]
726 short_url = res_url[1]
727 current_spec_string = current_spec_string.replace( long_url, short_url )
729 with tempfile.NamedTemporaryFile( mode = 'w',
731 prefix = os.path.basename( tmp_package_spec_path ) + ".",
732 dir = os.path.dirname( tmp_package_spec_path ),
733 delete = False ) as tmp_spec_file:
734 tmp_spec_file.write( current_spec_string )
735 tmp_package_spec_path = tmp_spec_file.name
737 # same case as "Source"
738 with open( tmp_package_spec_path, 'r' ) as current_spec_file:
739 current_spec_string = current_spec_file.read()
740 res_url_patch_file = re.findall( RePattern.patternUrlPatchFile, current_spec_string )
742 if len( res_url_patch_file ) > 0:
743 for res_url in res_url_patch_file:
744 long_url = res_url[0] + res_url[1]
745 short_url = res_url[1]
746 current_spec_string = current_spec_string.replace( long_url, short_url )
747 if ( tmp_package_spec_path != self.__package_spec_path ) \
748 and os.path.isfile( tmp_package_spec_path ) \
750 os.remove( tmp_package_spec_path )
751 with tempfile.NamedTemporaryFile( mode = 'w',
753 prefix = os.path.basename( tmp_package_spec_path ) + ".",
754 dir = os.path.dirname( tmp_package_spec_path ),
755 delete = False ) as tmp_spec_file:
756 tmp_spec_file.write( current_spec_string )
757 tmp_package_spec_path = tmp_spec_file.name
760 for a_patch in self.__patchs:
761 if a_patch == "patch0":
762 rpmspec_command += " --define='%patch #patch' "
764 rpmspec_command += " --define='%s #%s' " % ( a_patch, a_patch )
766 rpmspec_command += " --define='debug_package %{nil}'"
768 rpmspec_command += " --parse %s " % tmp_package_spec_path
770 print "rpmspec_command :", rpmspec_command
773 self.__parsed_spec_file = SpecParser.msubprocess.exec_subprocess( rpmspec_command )
774 if ( tmp_package_spec_path != self.__package_spec_path ) \
775 and os.path.isfile( tmp_package_spec_path ) \
777 os.remove( tmp_package_spec_path )
779 if self.__parsed_spec_file == 1:
780 print >> sys.stderr, ""
781 print >> sys.stderr, "ERROR CMD: %s" % rpmspec_command
782 print >> sys.stderr, "parse error for spec file %s" % ( tmp_package_spec_path )
783 self.__parsed_spec_file = None
787 if not os.path.isdir( "/tmp/parsed_spec" ):
788 os.makedirs( "/tmp/parsed_spec" )
790 if self.__package_pn is None:
791 tmp_path = os.path.basename( self.__package_spec_path )
792 package_parsed_spec_path = os.path.join( "/tmp/parsed_spec", tmp_path )
794 tmp_path = "%s.spec" % self.__package_pn
795 package_parsed_spec_path = os.path.join( "/tmp/parsed_spec", tmp_path )
797 with open( package_parsed_spec_path, "w" ) as file_d:
798 file_d.write( self.__parsed_spec_file )
801 def __test_section( self, line ):
803 test if the line is the start of a new section.
805 for sect in self.__list_section:
806 if line.startswith( sect ):
810 def __parse_parsed_spec_file( self ):
812 parse a spec file by section after rpmspec.
814 # ordered dico is not provide yet...
815 self.__order_list = []
816 self.__spect_dico = {}
818 current_section = self.__introduction_section
819 self.__spect_dico[current_section] = []
820 self.__order_list.append( current_section )
822 if self.__parsed_spec_file is None:
825 for line in self.__parsed_spec_file.split( "\n" ):
827 if self.__test_section( line ) :
828 if line in self.__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.__spect_dico[current_section] = []
839 self.__order_list.append( current_section )
841 self.__spect_dico[current_section].append( line )
843 def parse_raw_spec_file( self ):
845 parse a spec file by section before rpmspec.
848 # ordered dico is not provide yet...
850 self.__order_raw_list = []
851 self.__raw_spect_dico = {}
853 current_section = self.__introduction_section
854 self.__raw_spect_dico[current_section] = []
855 self.__order_raw_list.append( current_section )
857 with open( self.__package_spec_path, "r" ) as file_d:
858 parsed_raw_spec_file = file_d.read()
860 for line in parsed_raw_spec_file.split( "\n" ):
861 if self.__test_section( line ) :
862 if line in self.__raw_spect_dico.keys():
863 print "line %s" % line
864 print "--------------------------------------"
865 print "parsedSpecFile: %s" % self.__package_spec_path
866 print "--------------------------------------"
867 error_msg = "ERROR for the spec file \"%s\" this section \"%s\" is not unique."
868 print error_msg % ( self.__parsed_spec_file, line )
871 current_section = line
872 self.__raw_spect_dico[current_section] = []
873 self.__order_raw_list.append( current_section )
875 self.__raw_spect_dico[current_section].append( line )
878 def get_prep_section( self ):
880 return the prep section of the spec file.
882 res_prep_section = "cd ${S}\n"
884 pattern_patch_dico = {}
885 pattern_source_dico = {}
887 for line in self.__spect_dico[self.__introduction_section][1:]:
888 for patch_id, files_name in re.findall( RePattern.patternPatch, line ):
891 pattern_patch_dico[patch_id] = files_name
893 for source_id, files_name in re.findall( RePattern.patternSource, line ):
896 pattern_source_dico[source_id] = files_name
898 for line in self.__spect_dico[self.__prep_flag][1:]:
899 if line.startswith( "#setup" ):
900 splited_line = line.split()
901 for i in range( len( splited_line ) ):
902 if splited_line[i].startswith( "-a" ):
903 if len( splited_line[i] ) > len( "-a" ):
904 setup_id = splited_line[i].replace( "-a", "" )
906 setup_id = splited_line[i + 1]
907 res_prep_section += "#extracte source %s\n" % setup_id
908 res_prep_section += "CURDIR=$(pwd)\n"
909 res_prep_section += "cd ${S}\n"
910 source = os.path.basename( pattern_source_dico[setup_id] )
911 # not a good way to do this
912 if source.endswith( "rpmlintrc" ):
913 res_prep_section += "cp ${S}/packaging/%s .\n" % source
915 file_name = os.path.basename( pattern_source_dico[setup_id] )
916 res_prep_section += "tar -zxf ${S}/packaging/%s\n" % file_name
917 res_prep_section += "cd ${CURDIR}\n"
919 elif splited_line[i].startswith( "-b" ):
920 if len( splited_line[i] ) > len( "-b" ):
921 setup_id = splited_line[i].replace( "-b", "" )
923 setup_id = splited_line[i + 1]
925 res_prep_section += "#extracte source %s\n" % ( setup_id )
926 res_prep_section += "CURDIR=$(pwd)\n"
927 res_prep_section += "cd ${S}/../\n"
928 source = os.path.basename( pattern_source_dico[setup_id] )
929 if source.endswith( "rpmlintrc" ):
930 res_prep_section += "cp ${S}/packaging/%s .\n" % source
932 res_prep_section += "tar -zxf ${S}/packaging/%s\n" % source
933 res_prep_section += "cd ${CURDIR}\n"
935 res_prep_section += "chmod -Rf a+rX,u+w,g-w,o-w ${S}\n"
938 elif line.startswith( "#patch" ):
939 res_findall = re.findall( RePattern.patternPatchCommand, line )
941 for patch_name, patch_id, EXEC_COMMAND in res_findall:
945 files_name = pattern_patch_dico[patch_id]
947 if "-p" not in EXEC_COMMAND:
948 EXEC_COMMAND += " -p0"
950 if files_name.endswith( ".bz2" ):
951 bzcat_cmd = "bzcat ${S}/packaging/%s | patch -s %s --fuzz=2\n"
952 bzcat_val = ( files_name, EXEC_COMMAND.replace( " -b", " -b --suffix" ) )
953 res_prep_section += bzcat_cmd % bzcat_val
955 cat_cmd = "cat ${S}/packaging/%s | patch -s %s --fuzz=2\n"
956 cat_val = ( files_name, EXEC_COMMAND.replace( " -b", " -b --suffix" ) )
957 res_prep_section += cat_cmd % cat_val
959 res_prep_section += line + "\n"
960 return res_prep_section
962 def get_build_section( self ):
964 return the build section of the spec file.
966 res_build_section = "cd ${S}\n"
967 if self.__build_flag not in self.__spect_dico.keys():
970 for line in self.__spect_dico[self.__build_flag][1:]:
971 res_build_section += line + "\n"
973 return res_build_section
975 def get_raw_build_section( self ):
977 return the raw build section of the spec file.
979 res_raw_build_section = ""
980 if self.__build_flag not in self.__spect_dico.keys():
982 for line in self.__raw_spect_dico[self.__build_flag][1:]:
983 res_raw_build_section += line + "\n"
984 return res_raw_build_section
986 def get_clean_raw( self ):
988 clean the raw spec file to generate spec file for yocto packaging.
991 for sect in self.__order_raw_list:
992 if sect == self.__introduction_section:
993 for line in self.__raw_spect_dico[sect]:
994 if line.startswith("Version:"):
995 res_clean_raw += "Version: git\n"
998 have_findall_source = len( re.findall( RePattern.patternSource , line ) ) > 0
999 have_findall_patch = len( re.findall( RePattern.patternPatch, line ) ) > 0
1000 if not( have_findall_source or have_findall_patch ):
1001 res_clean_raw += line + "\n"
1004 elif sect == self.__prep_flag:
1005 res_clean_raw += line + "%prep\n"
1006 res_clean_raw += line + "#FAKE\n"
1007 elif sect == self.__build_flag:
1008 res_clean_raw += line + "%build\n"
1009 res_clean_raw += line + "#FAKE\n"
1010 elif sect == self.__install_flag:
1011 res_clean_raw += line + "%install\n"
1012 res_clean_raw += line + "#FAKE\n"
1013 elif sect == self.__check_flag:
1015 elif sect == self.__clean_flag:
1017 elif sect == self.__changelog_flag:
1019 elif sect.startswith( "%files" ):
1020 for line in self.__raw_spect_dico[sect]:
1021 if line.startswith( '%manifest ' ):
1022 res_clean_raw += line[len('%manifest '):] + "\n"
1023 elif line.startswith( '%doc ' ):
1025 elif line.startswith( '%ghost ' ):
1027 elif line.startswith( '%exclude ' ):
1029 elif line.startswith( '%license' ):
1033 res_clean_raw += line + "\n"
1036 for line in self.__raw_spect_dico[sect]:
1037 res_clean_raw += line + "\n"
1039 clean_raw_command = self.init_rpmspec_command()
1041 tmp_package_spec_path = self.__package_spec_path
1042 with tempfile.NamedTemporaryFile( mode = 'w',
1044 prefix = os.path.basename( tmp_package_spec_path ) + ".",
1045 dir = os.path.dirname( tmp_package_spec_path ),
1046 delete = False ) as tmp_spec_file:
1047 tmp_spec_file.write( res_clean_raw )
1048 tmp_package_spec_path = tmp_spec_file.name
1050 clean_raw_command += " --define='debug_package %{nil}'"
1051 clean_raw_command += " --define='docs_package %{nil}'"
1053 clean_raw_command += " --parse %s " % tmp_package_spec_path
1055 print "clean_raw_command :", clean_raw_command
1057 parsed_spec_file = SpecParser.msubprocess.exec_subprocess( clean_raw_command )
1059 if os.path.isfile( tmp_package_spec_path ) and not DEBUG_RUN:
1060 os.remove( tmp_package_spec_path )
1062 if parsed_spec_file == 1:
1063 print >> sys.stderr, "parse error for spec file %s" % ( tmp_package_spec_path )
1064 parsed_spec_file = None
1069 Summary: #FAKE - Debugging files
1072 %%description -n %s-dbg
1078 ''' % ( self.__base_name, self.__base_name, self.__base_name )
1079 work_dir = os.getenv( "WORKDIR" )
1081 if work_dir is None:
1082 return parsed_spec_file
1084 base_root = os.path.join( work_dir, "package" )
1085 for root, dirs, files in os.walk( base_root ):
1086 if root.endswith( ".debug" ):
1088 print "find directory %s " % dirs
1089 for a_file in files:
1090 fake_dbg += os.path.join( root, a_file ).replace( base_root, "" ) + "\n"
1091 #Test don't add dbg files
1092 #return parsed_spec_file + fake_dbg
1094 return parsed_spec_file
1096 def get_install_section( self ):
1098 return the install section.
1100 res_install_section = "cd ${S}\n"
1102 for line in self.__spect_dico[self.__install_flag][1:]:
1103 res_install_section += line + "\n"
1104 return res_install_section
1106 def get_description( self ):
1108 return the description of the spec file.
1110 for line in self.__spect_dico[self.__introduction_section] :
1111 description = re.findall( RePattern.patternDescription, line )
1112 if len( description ) > 0:
1113 return description[0]
1116 def get_homepage( self ):
1118 return the homepage of the spec file project.
1120 for line in self.__spect_dico[self.__introduction_section] :
1121 description = re.findall( RePattern.patternUrl, line )
1122 if len( description ) > 0:
1123 return description[0]
1126 def get_section( self ):
1128 return the section of the spec file project.
1130 for line in self.__spect_dico[self.__introduction_section] :
1131 description = re.findall( RePattern.patternGroup, line )
1132 if len( description ) > 0:
1133 return description[0]
1134 return "System/Base"
1136 def get_license( self ):
1138 return the licence of the package.
1140 for line in self.__spect_dico[self.__introduction_section] :
1141 description = re.findall( RePattern.patternLicense, line )
1142 if len( description ) > 0:
1143 res_license = description[0]
1144 if ";" in res_license:
1145 res_license = res_license.replace( ";", "" )
1151 def get_version(self):
1153 Return the version of the package.
1155 for line in self.__spect_dico[self.__introduction_section] :
1156 description = re.findall(RePattern.patternVersion, line)
1157 if len( description ) > 0:
1158 return description[0]
1161 def get_section_key(self, __flag):
1163 Return the list of "__flag" sections of the spec file.
1166 for section_key in self.__spect_dico.keys():
1167 if section_key.startswith(__flag):
1168 res_section.append(section_key)
1172 def get_script_section_key_pre(self):
1174 Return the list of pre script section of the spec file.
1175 get_section_key() can't be used in this case since it will also
1176 return the %preun and %prep results.
1178 res_script_section = []
1179 for section_key in self.__spect_dico.keys():
1180 if section_key.startswith("%pre") and \
1181 not section_key.startswith("%preun") and \
1182 not section_key.startswith("%prep"):
1183 res_script_section.append(section_key)
1185 return res_script_section
1187 def get_script_section_key_post(self):
1189 Return the list of post script section of the spec file.
1190 get_section_key() can't be used in this case since it will also
1191 return the %postun results.
1193 res_script_section = []
1194 for section_key in self.__spect_dico.keys():
1195 if section_key.startswith("%post") and not section_key.startswith("%postun"):
1196 res_script_section.append(section_key)
1198 return res_script_section
1200 def get_files_list_from_section( self, package_section_name ):
1202 return a list of file
1209 for line in self.__spect_dico[package_section_name][1:]:
1210 if not line.startswith( "%" ) and not line == "":
1211 line = line.replace( "//", "/" )
1212 res_list.append( line )
1213 elif line.startswith( "%attr(" ):
1214 line = line.replace( "//", "/" )
1215 pkg_f_clean=line.split(")")
1216 pkg_f=pkg_f_clean[-1].strip()
1217 res_list.append( pkg_f )
1218 elif line.startswith( "%doc " ):
1219 line = line.replace( "//", "/" )
1220 res_list.append( line.replace( "%doc ", "" ) )
1221 elif line.startswith( "%dir " ):
1222 line = line.replace( "//", "/" )
1224 file_name = line.replace( "%dir ", "" )
1225 dir_list.append( file_name )
1227 res_list.append( file_name )
1228 elif line.startswith( "%config " ):
1229 line = line.replace( "//", "/" )
1231 file_name = line.replace( "%config ", "" )
1232 config_list.append( file_name )
1234 res_list.append( file_name )
1235 elif line.startswith( "%manifest " ):
1236 line = line.replace( "//", "/" )
1238 file_name = line.replace( "%manifest ", "" )
1239 manifest_list.append( file_name )
1241 #res_list.append( file_name )
1243 elif line.startswith( "%config(noreplace) " ):
1244 line = line.replace( "//", "/" )
1245 res_list.append( line.replace( "%config(noreplace) ", "" ) )
1246 elif line.startswith( "%config(" ):
1247 line = line.replace( "//", "/" )
1248 pkg_f_clean=line.split(")")
1249 pkg_f=pkg_f_clean[-1].strip()
1250 res_list.append( pkg_f )
1254 #return res_list,config_list
1255 return res_list,config_list, manifest_list, dir_list
1257 def get_script_from_section(self, __flag):
1259 Return the pre/post script section of the spec file.
1261 res_script_section = ""
1262 if __flag in self.__spect_dico.keys():
1263 for line in self.__spect_dico[__flag][1:]:
1264 res_script_section += line + "\n"
1266 return res_script_section
1268 def get_files_packages( self ):
1270 return a dictinaire with package for key and list of files fo value.
1274 for package_section_name in self.get_section_key("%file"):
1275 tmp_package_name = package_section_name
1276 # Need to get info of the first line.
1277 if "-f " in tmp_package_name:
1278 tmp_split = tmp_package_name.split( "-f " )
1279 tmp_package_name = tmp_split[0]
1281 package = re.findall( RePattern.patternFiles, tmp_package_name )
1282 if len( package ) > 0:
1283 if "-n " in package[0]:
1284 package_name = package[0].replace( "-n ", "" )
1286 package_name = self.__base_name
1287 pkg_ext = package[0].replace( " ", "" )
1288 if len( pkg_ext ) > 0:
1289 package_name += "-" + pkg_ext
1291 package_name = self.__base_name
1293 package_name = package_name.replace( " ", "" )
1294 res_list,config_list, manifest_list, dir_list = self.get_files_list_from_section( package_section_name )
1295 res_dico[ package_name ] = res_list,config_list, manifest_list, dir_list
1297 #db_src=self.__base_name+"-debugsource"
1298 #if db_src not in res_dico:
1299 # res_dico[db_src] = []
1301 #dbinfo=self.__base_name+"-debug"
1302 #if dbinfo not in res_dico:
1303 # res_dico[dbinfo] = []
1307 def get_name( self ):
1309 return the name of the package
1311 for line in self.__spect_dico[self.__introduction_section]:
1312 description = re.findall( RePattern.patternName, line )
1313 if len( description ) > 0:
1314 return description[0]
1317 def get_provides( self ):
1319 return all provide service by each package of the spec file.
1322 provide_res[self.__base_name] = []
1323 provide_res[self.__base_name].append( [self.__base_name] )
1325 for k in self.__spect_dico.keys():
1326 package = re.findall( RePattern.patternPackage, k )
1327 if len( package ) > 0:
1328 package_name = self.__clean_package_name( package[0] )
1329 provide_res[ package_name ] = []
1330 provide_res[ package_name ].append( [package_name] )
1332 if len( package ) > 0 or ( k == self.__introduction_section ):
1333 for line in self.__spect_dico[k]:
1334 provides = re.findall( RePattern.provides_package, line )
1335 for provides_line in provides:
1336 for tmp_clean in self.__clean_package_line( provides_line ):
1337 if k == self.__introduction_section:
1338 provide_res[self.__base_name].append( tmp_clean )
1340 provide_res[package_name].append( tmp_clean )
1343 def __clean_package_name( self, package_name ):
1345 return the package name from spec declaration.
1347 # re should be better.
1348 if "-n " in package_name:
1349 package_name = package_name.replace( "-n ", "" ).replace( " ", "" )
1351 package_name = self.__base_name + "-" + package_name
1355 def get_rdepends( self ):
1357 return all require service by each package of the spec file.
1361 for k in self.__spect_dico.keys():
1362 package = re.findall( RePattern.patternPackage, k )
1364 if len( package ) > 0:
1365 package_name = self.__clean_package_name( package[0] )
1367 package_name = self.__base_name
1369 if len( package ) > 0 or ( k == self.__introduction_section ):
1370 requires_list = self.get_requires( self.__spect_dico[k] )
1371 rdepends_res[package_name] = requires_list
1375 def get_depends( self ):
1377 return all build require service by each package of the spec file.
1381 for k in self.__spect_dico.keys():
1382 package = re.findall( RePattern.patternPackage, k )
1383 if len( package ) > 0:
1384 package_name = self.__clean_package_name( package[0] )
1386 if len( package ) > 0 or ( k == self.__introduction_section ):
1387 build_requires_list = self.get_build_requires( self.__spect_dico[k] )
1388 if ( k == self.__introduction_section ):
1389 depends_res[self.__base_name] = build_requires_list
1391 depends_res[package_name] = build_requires_list
1396 def __clean_package_line( self, package_line ):
1398 return package list from package declaration in spec file.
1400 res_first = re.findall( RePattern.pkgRe, package_line )
1401 if len( res_first ) == 0:
1402 print "__clean_package_line faild for %s" % self.__package_spec_path
1404 # should be rewrite cleaner.
1406 for init_res in res_first:
1407 init_res = list( init_res )
1408 init_res[0] = init_res[0].replace( ",", "" )
1409 res_final.append( init_res )
1412 def get_build_requires( self, lines ):
1414 return the line of every build requires.
1416 package_replacement = SPEC2YOCTO_CONFIG.get_substitute()
1417 build_requires_res = []
1420 build_requires = re.findall( RePattern.buildRequiresPackage, line )
1421 for tmp_res in build_requires:
1422 # If a dependency uses pkgconfig, explicitely add pkgconfig as a dependency.
1423 if pkgconfig == 0 and 'pkgconfig' in tmp_res:
1424 build_requires_res.append(['pkgconfig', '', ''])
1426 for tmp_clean in self.__clean_package_line( tmp_res ):
1427 if len( tmp_clean ) >= 1:
1428 if tmp_clean[0] in package_replacement.keys():
1429 tmp_clean[0] = package_replacement[tmp_clean[0]]
1430 build_requires_res.append( tmp_clean )
1431 return build_requires_res
1433 def get_requires( self, lines ):
1435 return the line of every requires.
1437 package_replacement = SPEC2YOCTO_CONFIG.get_substitute()
1441 build_requires = re.findall( RePattern.requiresPackage, line )
1442 for tmp_res in build_requires:
1443 for tmp_clean in self.__clean_package_line( tmp_res ):
1444 if len( tmp_clean ) >= 1:
1445 if tmp_clean[0] in package_replacement.keys():
1446 tmp_clean[0] = package_replacement[tmp_clean[0]]
1447 requires_res.append( tmp_clean )
1452 meta spec file for generate yocto bb.
1455 mExtraRProvidesDico = {}
1457 mCrossPackageBlacklist = []
1458 mInitialPackageBlacklist = []
1459 mNativePackageBlacklist = []
1460 mOePackageBlacklist = []
1463 package_recipes_dir,
1467 package_git_srv_src,
1468 package_git_srv_path,
1471 init the MetaSpec class
1474 self.__package_name = package_name.replace( "_", "-" )
1475 self.__package_meta_path=package_meta_path
1477 self.__package_git_srv_src = package_git_srv_src
1478 self.__package_git_srv_path = package_git_srv_path
1480 self.__package_spec_path = package_spec_path
1481 self.__git_tag = package_git_tag
1483 self.__spec_parser = SpecParser( self.__package_spec_path )
1484 self.__package_spec_name = self.__spec_parser.get_name()
1486 self.__packages_dico = self.__spec_parser.get_files_packages()
1487 self.__provides_dico = self.__spec_parser.get_provides()
1489 self.setm_provided_dico()
1490 self.__rdepends_dico = self.__spec_parser.get_rdepends()
1492 self.__package_name = self.__spec_parser.get_name().replace( "_", "-" )
1493 self.__package_recipes_dir = os.path.join(package_recipes_dir,self.__package_meta_path)
1494 self.__base_file = self.__package_name + ".inc"
1495 #self.__base_depends_file = self.__package_name + "-depends.inc"
1496 #self.__base_rdepends_file = self.__package_name + "-rdepends.inc"
1497 #self.__base_provides_file = self.__package_name + "-rprovides.inc"
1499 self.__extra_conf_file = self.__package_name + "-extraconf.inc"
1500 #self.__extra_native_conf_file = self.__package_name + "-native-extraconf.inc"
1501 #self.__extra_oe_conf_file = self.__package_name + "-oe-extraconf.inc"
1503 self.__git_native_file = self.__package_name + "-native_git.bb"
1504 self.__git_oe_file = self.__package_name + "_git.bb"
1506 self.__createRecipes()
1508 def setm_provided_dico( self ):
1510 add provides_list for package_name to mProvidesDico
1513 for k_provide in self.__provides_dico.keys():
1514 for p_provide in self.__provides_dico[k_provide]:
1515 provides_list.append( p_provide[0] )
1516 for p_provide in self.__packages_dico.keys():
1517 provides_list.extend( self.__packages_dico[p_provide][0] )
1519 for package in self.__packages_dico.keys():
1520 for pkg_file in self.__packages_dico[package][0]:
1521 pkgconfig_name_res = re.findall( RePattern.pkgconfig_name, pkg_file )
1522 for tmp_res in pkgconfig_name_res:
1523 provides_list.append( "pkgconfig(%s)" % tmp_res )
1525 if self.__package_name not in MetaSpec.mProvidesDico.keys():
1526 MetaSpec.mProvidesDico[self.__package_name] = []
1528 MetaSpec.mProvidesDico[self.__package_name].extend( provides_list )
1530 def set_mextra_provided_dico( self ):
1532 add provides_list for package_name to mExtraRProvidesDico
1535 for k_provide in self.__provides_dico.keys():
1536 for p_provide in self.__provides_dico[k_provide]:
1537 provides_list.append( p_provide[0] )
1538 for p_provide in self.__packages_dico.keys():
1539 provides_list.extend( self.__packages_dico[p_provide][0] )
1541 MetaSpec.mExtraRProvidesDico[self.__package_name] = provides_list
1543 def __create_base_file( self ):
1545 create the base file of the bb file.
1547 bb_path = os.path.join( self.__package_recipes_dir, self.__base_file )
1548 with open( bb_path, "w" ) as file_d:
1550 _description = self.__spec_parser.get_description()
1551 _homepage = self.__spec_parser.get_homepage()
1552 _section = self.__spec_parser.get_section()
1554 _license = self.__spec_parser.get_license()
1555 _version = self.__spec_parser.get_version()
1557 file_d.write( "DESCRIPTION = \"%s\"\n" % _description )
1558 if len( _homepage ) < 2:
1559 _homepage = "http://nohomepage.org"
1560 file_d.write( "HOMEPAGE = \"%s\"\n" % _homepage )
1561 file_d.write( "SECTION = \"%s\"\n" % _section )
1563 file_d.write( "LICENSE = \"%s\"\n" % _license )
1564 file_d.write( "PV = \"%s\"\n" % _version )
1565 file_d.write( "\n" )
1566 file_d.write( "SRC_URI = \"\"\n" )
1567 file_d.write( "\n" )
1568 file_d.write( "S = \"${WORKDIR}/git\"\n" )
1569 file_d.write( "\n" )
1571 file_d.write( "inherit manifest autotools-brokensep\n" )
1572 file_d.write( "\n" )
1573 file_d.write( "BBCLASSEXTEND = \"\"\n" )
1575 self.__create_provides_file( file_d)
1576 self.__create_rdepends( file_d)
1577 self.__create_depends( file_d)
1579 self.__create_patch( file_d)
1580 self.__create_configure( file_d)
1581 self. __create_compile( file_d)
1582 self.__create_install( file_d)
1584 self.__create_script_file( file_d)
1586 self.__create_files_packaging( file_d )
1588 file_d.write( "require %s\n\n" % self.__extra_conf_file )
1590 def __create_files_packaging(self,file_d):
1591 file_d.write( "PACKAGES = \"${PN}-dbg ${PN}-doc ${PN}-locale\"\n" )
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 if pkg_yocto_name not in [self.__package_name+"-dbg",
1598 self.__package_name+"-doc",
1599 self.__package_name+"-locale",
1601 file_d.write( "PACKAGES += \" %s \"\n" % pkg_yocto_name )
1603 file_d.write( "\n" )
1605 _license = self.__spec_parser.get_license()
1607 for package in self.__packages_dico.keys():
1608 pkg_yocto_name=package
1609 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1610 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1612 file_d.write( "%s_files = \"\"\n" % pkg_yocto_name )
1613 pkg_list, config_list, manifest_list, dir_list = self.__packages_dico[package]
1614 for pkg_f in pkg_list:
1617 if pkg_f.startswith( _license ):
1620 pkg_yocto_name = package.replace("-devel","-dev")
1621 file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, pkg_f ) )
1623 pkg_yocto_name_short = pkg_yocto_name.replace( self.__package_name, "${PN}" )
1625 if len(config_list)>0:
1626 file_d.write( "CONFFILES_%s = \"\"\n" % ( pkg_yocto_name_short ) )
1627 for pkg_f in config_list:
1628 file_d.write( "CONFFILES_%s += \"%s\"\n" % ( pkg_yocto_name_short, pkg_f ) )
1630 if (len(manifest_list) == 1) :
1631 file_d.write( "MANIFESTFILES_%s = \"%s\"\n" % ( pkg_yocto_name_short, manifest_list[0] ) )
1632 elif (len(manifest_list) > 1) :
1633 msg="ERROR Too many manifest for \"%s\" " % self.__package_name
1634 print >> sys.stderr, colorize( msg, "red" )
1637 file_d.write( "DIRFILES_%s = \"\"\n" % ( pkg_yocto_name_short ) )
1638 for pkg_f in dir_list:
1639 file_d.write( "DIRFILES_%s += \"%s\"\n" % ( pkg_yocto_name_short, pkg_f ) )
1641 file_d.write( "\n" )
1643 for package in self.__packages_dico.keys():
1644 p_parse = package.replace( self.__package_name, "${PN}" )
1645 p_parse = p_parse.replace("-devel","-dev")
1646 pkg_yocto_name = package.replace("-devel","-dev")
1647 file_d.write( "FILES_%s = \"${%s_files}\"\n" % ( p_parse, pkg_yocto_name ) )
1648 file_d.write( "\n" )
1650 for package in self.__packages_dico.keys():
1651 pkg_yocto_name = package.replace("-devel","-dev")
1652 file_d.write( "PKG_%s= \"%s\"\n" % (pkg_yocto_name,pkg_yocto_name) )
1653 file_d.write( "\n" )
1655 def __cleanCode( self ,code):
1656 code=code.replace("\n","\n ")
1657 code=code.replace("\n EOF","\nEOF")
1658 code=code.replace("///lib","/lib")
1659 code=code.replace("//lib","/lib")
1660 code=code.replace("//usr","/usr")
1662 code=code.replace("${D}/${prefix}","${D}${prefix}")
1665 def __create_patch( self ,file_d):
1666 code=self.__spec_parser.get_prep_section()
1667 code=self.__cleanCode(code)
1668 file_d.write( "do_prep() {\n" )
1669 file_d.write( " %s\n" % code )
1670 file_d.write( "}\n" )
1671 file_d.write( "do_patch_append() {\n" )
1672 file_d.write( " bb.build.exec_func('do_prep', d)\n" )
1673 file_d.write( "}\n" )
1674 file_d.write( "\n" )
1676 def __create_configure( self ,file_d):
1677 file_d.write( "do_configure() {\n" )
1678 file_d.write( "}\n" )
1679 file_d.write( "\n" )
1681 def __create_compile( self ,file_d):
1683 code=self.__spec_parser.get_build_section()
1684 code=self.__cleanCode(code)
1686 file_d.write( "do_compile() {\n" )
1687 if code.count("autotools_do_configure") == 1 :
1688 code_line=code.replace("\\\n"," ").split("\n")
1689 for line in code_line:
1690 if "autotools_do_configure" in line:
1691 post= line.split("autotools_do_configure")[0]
1692 EXTRA_OECONF = line.split("autotools_do_configure")[1]
1693 file_d.write( "%sautotools_do_configure\n" % post)
1695 file_d.write( " %s\n" % line )
1698 elif code.count("autotools_do_configure") > 1 :
1699 msg="ERROR more than 1 autotools_do_configure for \"%s\"" % self.__package_name
1700 print >> sys.stderr, colorize( msg, "red" )
1703 file_d.write( " %s\n" % code )
1705 file_d.write( "}\n" )
1706 if EXTRA_OECONF is not None:
1707 while EXTRA_OECONF.count(" "):
1708 EXTRA_OECONF=EXTRA_OECONF.replace(" "," ")
1709 file_d.write( "EXTRA_OECONF += \"%s\"\n" % EXTRA_OECONF )
1711 file_d.write( "\n" )
1713 def __create_install( self ,file_d):
1714 code=self.__spec_parser.get_install_section()
1715 code=self.__cleanCode(code)
1719 file_d.write( "do_install() {\n" )
1720 file_d.write( " export RPM_BUILD_ROOT=${D}\n" )
1721 file_d.write( " %s\n" % code )
1722 file_d.write( "}\n" )
1723 file_d.write( "\n" )
1725 def __create_script_file_section_code( self, spec_section):
1727 Returns the command executed in one of the %pre, %post, %preun
1728 or %postun section of a spec file.
1730 code = self.__spec_parser.get_script_from_section(spec_section)
1731 command_list = code.split("\n")
1733 for line in command_list:
1736 formated_code += " " + line + "\n"
1738 return formated_code
1740 def __create_script_file_write( self, file_d, code, recipe_section, package_name):
1742 Writes the pre/post (un)install sections of the recipe.
1744 code=code.replace("/sbin/ldconfig","[ \"x$D\" == \"x\" ] && ldconfig")
1745 code=code.replace("${prefix}","$D${prefix}")
1746 code=code.replace("${systemd_unitdir}","$D${systemd_unitdir}")
1747 code=code.replace("${sysconfdir}","$D${sysconfdir}")
1749 file_d.write("%s%s() {\n" % (recipe_section, package_name))
1750 file_d.write(" #!/bin/sh -e\n\n")
1751 file_d.write("%s\n" % code)
1755 def __create_script_file_session(self, file_d, flag, script_name, script_sections):
1757 Add script for the given flag.
1759 for section in script_sections:
1761 # If %section is a one line script such as: "%post -p /sbin/ldconfig"
1762 if " -p " in section:
1763 # Remove the package name if present to only keep the command
1764 section_split = section.split(" -p ")[1].split(" -n ")
1765 code = " " + section_split[0].strip()
1767 code = self.__create_script_file_section_code(section)
1769 # Set the package name
1770 package_name = "${PN}"
1771 # If the package name is not the project name
1772 if " -n " in section:
1773 # Remove the command if any to only keep the package name
1774 section_split = section.split(" -n ")[1].split(" -p ")
1775 package_name = section_split[0].strip()
1776 self.__create_script_file_write(file_d, code, script_name, package_name)
1778 def __create_script_file(self, file_d):
1780 Add the pre/post install/uninstall sections of a spec file to
1783 script_sections = self.__spec_parser.get_script_section_key_pre()
1784 self.__create_script_file_session(file_d, "%pre", "pkg_preinst_", script_sections)
1786 script_sections = self.__spec_parser.get_script_section_key_post()
1787 self.__create_script_file_session(file_d, "%post", "pkg_postinst_", script_sections)
1789 script_sections = self.__spec_parser.get_section_key("%preun")
1790 self.__create_script_file_session(file_d, "%preun", "pkg_prerm_", script_sections)
1792 script_sections = self.__spec_parser.get_section_key("%postun")
1793 self.__create_script_file_session(file_d, "%postun", "pkg_postrm_", script_sections)
1795 def __create_provides_file( self ,file_d):
1797 generate provide file.
1799 file_d.write( "PROVIDES = \"\"\n" )
1800 file_d.write( "\n" )
1802 for k_provide in self.__provides_dico.keys():
1803 pkg_yocto_name=k_provide
1804 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1805 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1807 if len( self.__provides_dico[k_provide] ) > 0:
1808 file_d.write( "#PROVIDES by %s\n" % pkg_yocto_name.replace(" ","") )
1809 if pkg_yocto_name != self.__package_name:
1810 file_d.write( "PROVIDES += \"%s\"\n" % ( pkg_yocto_name ) )
1814 for p_provide in self.__provides_dico[k_provide]:
1817 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto ):
1818 pkg_yocto=pkg_yocto.replace("-devel","-dev")
1820 if not len( p_provide ) == 1:
1821 provide_text = "# the PROVIDES rules is ignore \"%s %s %s\"\n"
1822 file_d.write( provide_text % ( pkg_yocto, p_provide[1], p_provide[2] ) )
1824 if ( pkg == "mktemp" and self.__package_name == "tizen-coreutils" ):
1828 if pkg_yocto_name != pkg_yocto:
1829 file_d.write( "PROVIDES += \"%s\"\n" % ( pkg_yocto ) )
1830 file_d.write( "RPROVIDES_%s += \"%s\"\n" % ( pkg_yocto_name, pkg_yocto ) )
1832 #for res_pkg_devel in re.findall( RePattern.paternDevel, pkg ):
1833 # rprovide_text = "RPROVIDES_%s += \"%s\"\n"
1834 # file_d.write( rprovide_text % ( k_provide, res_pkg_devel + "-dev" ) )
1836 if len( self.__provides_dico[k_provide] ) > 0:
1837 file_d.write( "\n\n" )
1839 def __create_git_native_file( self ):
1841 create bb native file.
1843 bb_native_path = os.path.join( self.__package_recipes_dir, self.__git_native_file )
1844 with open( bb_native_path, "w" ) as file_d:
1845 file_d.write( "require %s\n" % self.__base_file )
1846 file_d.write( "\n" )
1847 file_d.write( "PRIORITY = \"9\"\n" )
1848 file_d.write( "\n" )
1849 file_d.write( "inherit native\n" )
1850 file_d.write( "\n" )
1851 file_d.write( "S = \"${WORKDIR}/git\"\n" )
1852 file_d.write( "\n" )
1854 md5_value = "801f80980d171dd6425610833a22dbe6"
1855 file_value = "${COMMON_LICENSE_DIR}/GPL-2.0"
1856 file_chksum_text = "LIC_FILES_CHKSUM ??= \"file://%s;md5=%s\"\n"
1858 file_d.write( file_chksum_text % ( file_value, md5_value ) )
1859 file_d.write( "\n" )
1860 command_source = "SRC_URI += \"%s\"\n" % GIT_COMMAND
1861 file_d.write( command_source % ( self.__package_git_srv_src ,
1862 self.__package_git_srv_path ,
1864 #file_d.write( "require %s\n" % self.__extra_native_conf_file )
1865 file_d.write( "\n" )
1867 def __create_git_oe_file( self ):
1871 bb_path = os.path.join( self.__package_recipes_dir, self.__git_oe_file )
1872 with open( bb_path, "w" ) as file_d:
1873 file_d.write( "require %s\n" % self.__base_file )
1874 file_d.write( "\n" )
1875 file_d.write( "PRIORITY = \"10\"\n" )
1876 file_d.write( "\n" )
1877 md5_value = "801f80980d171dd6425610833a22dbe6"
1878 file_value = "${COMMON_LICENSE_DIR}/GPL-2.0"
1879 file_chksum_text = "LIC_FILES_CHKSUM ??= \"file://%s;md5=%s\"\n"
1881 file_d.write( file_chksum_text % ( file_value, md5_value ) )
1882 file_d.write( "\n" )
1883 command_source = "SRC_URI += \"" + GIT_COMMAND + "\"\n"
1884 file_d.write( command_source % ( self.__package_git_srv_src ,
1885 self.__package_git_srv_path ,
1887 #file_d.write( "require %s\n" % self.__extra_oe_conf_file )
1888 file_d.write( "\n" )
1889 if self.__package_name not in MetaSpec.mNativePackageBlacklist:
1890 file_d.write( "BBCLASSEXTEND += \" native \"" )
1891 file_d.write( "\n\n" )
1893 def __createRecipes( self ):
1895 generate all bb file.
1897 if self.__package_recipes_dir is None:
1900 if not os.path.isdir( self.__package_recipes_dir ):
1901 os.makedirs( self.__package_recipes_dir )
1904 #rdepends_path = os.path.join( self.__package_recipes_dir, self.__base_rdepends_file )
1905 #open( rdepends_path, "a" ).close()
1906 #depends_path = os.path.join( self.__package_recipes_dir, self.__base_depends_file )
1907 #open( depends_path, "a" ).close()
1908 #provides_path = os.path.join( self.__package_recipes_dir, self.__base_provides_file )
1909 #open( provides_path, "a" ).close()
1911 extra_conf_file_path = os.path.join( self.__package_recipes_dir, self.__extra_conf_file )
1912 open( extra_conf_file_path, "a" ).close()
1914 #extranative_path = os.path.join( self.__package_recipes_dir, self.__extra_native_conf_file )
1915 #open( extranative_path, "a" ).close()
1916 #extra_oe_conf_path = os.path.join( self.__package_recipes_dir, self.__extra_oe_conf_file )
1917 #open( extra_oe_conf_path, "a" ).close()
1919 self.__create_base_file()
1921 if not self.__package_name not in MetaSpec.mNativePackageBlacklist:
1922 bb_native_path = os.path.join( self.__package_recipes_dir, self.__git_native_file )
1923 if os.path.isfile( bb_native_path ):
1924 os.unlink( bb_native_path )
1926 #self.__create_provides_file()
1928 if self.__package_name not in MetaSpec.mOePackageBlacklist:
1929 self.__create_git_oe_file()
1931 bb_oe_path = os.path.join( self.__package_recipes_dir, self.__git_oe_file )
1932 if os.path.isfile( bb_oe_path ):
1933 os.unlink( bb_oe_path )
1935 def __create_rdepends( self ,file_d):
1937 generate rdepends file.
1939 if self.__package_recipes_dir is None:
1942 if not os.path.isdir( self.__package_recipes_dir ):
1943 os.makedirs( self.__package_recipes_dir )
1945 #rdepends_path = os.path.join( self.__package_recipes_dir, self.__base_rdepends_file )
1947 package_replacement = SPEC2YOCTO_CONFIG.get_substitute()
1949 if file_d is not None:
1950 file_d.write( "RDEPENDS = \"\"\n" )
1952 for k_provide in self.__rdepends_dico.keys():
1953 pkg_yocto_name=k_provide
1954 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1955 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1957 res_rdepends = set()
1958 k_provide_replace = pkg_yocto_name.replace( self.__package_name, "${PN}" )
1959 if len( self.__rdepends_dico[k_provide] ) > 0:
1960 file_d.write( "#RDEPENDS of %s (%s)\n" % ( pkg_yocto_name, k_provide_replace ) )
1962 for provide in self.__rdepends_dico[k_provide]:
1963 package_provide = provide[0]
1967 for k_package_provide in MetaSpec.mExtraRProvidesDico.keys():
1969 if package_provide in MetaSpec.mExtraRProvidesDico[k_package_provide] \
1970 or package_provide == k_package_provide:
1971 res = k_package_provide
1974 res = package_provide
1976 if res in package_replacement.keys():
1977 res = package_replacement[res]
1979 res_rdepends.add( res )
1981 for pkg in res_rdepends:
1982 res_pkg_devel = re.findall( RePattern.paternDevel, pkg )
1984 if len( res_pkg_devel ) > 0:
1985 rdepends_value = "RDEPENDS_%s += \"%s\"\n"
1986 file_d.write( rdepends_value % ( k_provide_replace, res_pkg_devel[0] + "-dev" ) )
1988 if not pkg in SPEC2YOCTO_CONFIG.get_ignore_rdepend():
1989 file_d.write( "RDEPENDS_%s += \"%s\"\n" % ( k_provide_replace, pkg ) )
1991 if len( self.__rdepends_dico[k_provide] ) > 0:
1992 file_d.write( "\n" )
1994 file_d.write( "\n" )
1996 def __create_depends( self, file_d):
1998 create depends file.
2000 if self.__package_recipes_dir is None:
2003 if not os.path.isdir( self.__package_recipes_dir ):
2004 os.makedirs( self.__package_recipes_dir )
2006 depends_dico = self.__spec_parser.get_depends()
2007 #depends_path = os.path.join( self.__package_recipes_dir, self.__base_depends_file )
2009 ignore_depend_list = SPEC2YOCTO_CONFIG.get_ignore_depend()
2010 native_depend_list = SPEC2YOCTO_CONFIG.get_native_depend()
2011 cross_depend_list = SPEC2YOCTO_CONFIG.get_cross_depend()
2014 if file_d is not None:
2015 file_d.write( "DEPENDS = \"\"\n" )
2018 for k_provide in depends_dico.keys():
2019 if len( depends_dico[k_provide] ) > 0:
2020 file_d.write( "#DEPENDS of %s\n" % k_provide )
2022 for p_provide in depends_dico[k_provide]:
2023 pp_provide = p_provide[0]
2026 if pp_provide in ignore_depend_list:
2029 for k in MetaSpec.mProvidesDico.keys():
2030 if pp_provide in MetaSpec.mProvidesDico[k] or pp_provide == k:
2033 for k_package_provide in MetaSpec.mExtraRProvidesDico.keys():
2034 if pp_provide in MetaSpec.mExtraRProvidesDico[k_package_provide]:
2035 res = k_package_provide
2039 if pp_provide not in SPEC2YOCTO_CONFIG.get_inherit_gettext() and \
2040 pp_provide not in SPEC2YOCTO_CONFIG.get_inherit("python") and \
2041 pp_provide not in SPEC2YOCTO_CONFIG.get_inherit("cmake") and \
2042 pp_provide not in SPEC2YOCTO_CONFIG.get_inherit("perl") and \
2043 pp_provide not in ignore_depend_list and \
2044 pp_provide not in native_depend_list and \
2045 pp_provide not in cross_depend_list:
2047 erro_msg = "No direct provider for package DEPENDS %s : \"%s\"."
2048 print erro_msg % ( self.__package_name, pp_provide )
2050 if res != self.__package_name :
2051 res_depends.add( res )
2053 # should be from a configue file.
2054 for res in res_depends:
2056 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
2057 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
2059 if pkg_yocto_name == "readline-dev":
2060 pkg_yocto_name="readline"
2062 if pkg_yocto_name in SPEC2YOCTO_CONFIG.get_inherit_gettext():
2063 file_d.write( "#Replace \"DEPENDS\" on gettext by \"inherit gettext\"\n" )
2064 file_d.write( "inherit gettext\n" )
2065 elif pkg_yocto_name in ['cmake']:
2066 file_d.write( "inherit tizen_cmake\n" )
2067 elif pkg_yocto_name in ['pkgconfig']:
2068 file_d.write( "inherit pkgconfig\n" )
2069 elif pkg_yocto_name in native_depend_list:
2070 file_d.write( "DEPENDS_append_class-native = \" %s-native\"\n" % pkg_yocto_name )
2071 file_d.write( "DEPENDS_append_class-target = \" %s-native\"\n" % pkg_yocto_name )
2072 elif pkg_yocto_name in cross_depend_list:
2073 file_d.write( "DEPENDS_append_class-native = \" %s\"\n" % pkg_yocto_name )
2074 file_d.write( "DEPENDS_append_class-target = \" %s-cross\"\n" % pkg_yocto_name )
2075 elif pkg_yocto_name in ignore_depend_list:
2077 elif pkg_yocto_name in SPEC2YOCTO_CONFIG.get_libtool_cross():
2078 file_d.write( "DEPENDS += \"libtool-cross\"\n" )
2079 elif pkg_yocto_name in SPEC2YOCTO_CONFIG.get_inherit("perl"):
2080 file_d.write( "inherit perlnative\n" )
2081 elif pkg_yocto_name in SPEC2YOCTO_CONFIG.get_inherit("python"):
2082 file_d.write( "inherit pythonnative\n" )
2084 file_d.write( "DEPENDS += \"%s\"\n" % pkg_yocto_name )
2086 file_d.write( "\n" )
2088 class HTTPAccessFailure( Exception ):
2089 '''Indicate the http access failed'''
2091 def download_url( url ):
2094 raise HTTPAccessFailure()
2099 def download_manifest_url( url ):
2102 print "ERROR %s " % url
2103 raise HTTPAccessFailure()
2108 def download_build_xml( url ):
2109 return download_url( url + "/build.xml" )
2111 def get_project_id( xml ):
2112 aElement = ElementTree.fromstring( xml )
2114 for value in aElement:
2115 for project in value.getiterator():
2116 if project.tag == "id":
2119 def get_project_arch( xml ):
2120 aElement = ElementTree.fromstring( xml )
2122 for value in aElement:
2123 for project in value.getiterator():
2124 if project.tag == "archs":
2125 for arch in project.getiterator():
2126 if arch.tag == "arch":
2127 arch_list.append( arch.text )
2131 def get_project_buildtarget(xml):
2132 aElement = ElementTree.fromstring(xml)
2133 buildtarget_list = []
2134 for value in aElement:
2135 for project in value.getiterator():
2136 if project.tag == "buildtargets":
2137 for buildtarget in project.getiterator():
2138 if buildtarget.tag == "buildtarget":
2139 buildtarget_list.append(buildtarget.text)
2141 return buildtarget_list
2143 def clean_name( raw_name ):
2144 #if "_" in raw_name:
2145 # raw_name = raw_name.replace( "_", "-" )
2148 return raw_name.split( "/" )[-1]
2152 def clean_revision( raw_name ):
2154 return raw_name.split( "-" )[0]
2158 def patch_the_spec_file( package_spec_path,
2163 if not package_spec_path == dest_spec_path:
2164 shutil.copy2( package_spec_path, dest_spec_path )
2166 if dest_spec_dir.endswith( "/packaging" ):
2167 dest_spec_dir = dest_spec_dir[:-len( "/packaging" )]
2169 patch_command = "patch -s -p1 --fuzz=2 -d %s -i %s" % ( dest_spec_dir, patch_path )
2171 a_sub_command = SubprocessCrt()
2172 res = a_sub_command.exec_subprocess( patch_command )
2175 msg = "The patch \"%s\" can't be apply in directory \"%s\"."
2176 msg = msg % ( patch_path, dest_spec_dir )
2177 print >> sys.stderr, colorize( msg, "red" )
2178 print >> sys.stderr, colorize( "command: \"%s\"" % patch_command, "red" )
2181 return dest_spec_path
2184 def specfile_patcher( package_spec_path, project, package_name_list , dest_spec_path ):
2185 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( project )
2186 source_spec_patch_dir = os.path.join( working_dir, "specfile-patch" )
2188 patch_path_list = findSpecPatchFiles( source_spec_patch_dir, package_name_list )
2190 if len( patch_path_list ) > 0:
2192 dest_spec_dir = os.path.dirname( dest_spec_path )
2193 if not os.path.isdir( dest_spec_dir ):
2194 os.makedirs( dest_spec_dir )
2196 for patch_path in patch_path_list:
2197 package_spec_path = patch_the_spec_file( package_spec_path,
2202 return package_spec_path
2206 def __init__( self, project, name, git_path, meta_path, revision, priority, git_src ):
2207 self.__project = project
2209 self.git_path = git_path
2210 self.meta_path = meta_path
2211 self.git_revision = revision
2212 self.priority = priority
2213 self.git_src = git_src
2214 self.__my_meta_spec = None
2216 def printMe( self ):
2217 print "%s %s %s %s" % ( self.name , self.git_path, self.git_revision, self.git_src )
2219 def create_MetaSpec( self , package_recipes_dir, source_spec_dir ):
2220 source_path = os.path.join( source_spec_dir , self.name , "packaging" )
2221 package_spec_path = findBestSpecFile( source_path, self.name )
2223 if package_spec_path == -1:
2224 msg = "no initial spec file for package \"%s\" in directory \"%s\"."
2225 msg = msg % ( self.name, source_path )
2226 print >> sys.stderr, colorize( msg, "red" )
2229 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( self.__project )
2230 specfile_patched_dir = os.path.join( working_dir, "specfile-patched" )
2231 dest_spec_dir = os.path.join( specfile_patched_dir , self.name )
2232 dest_spec_packaging_dir = os.path.join( dest_spec_dir , "packaging" )
2233 dest_spec_path = os.path.join( dest_spec_packaging_dir ,
2234 os.path.basename( package_spec_path ) )
2237 package_spec_path = specfile_patcher( package_spec_path,
2239 [self.name, self.name + "-initial"],
2242 self.__my_meta_spec = MetaSpec( package_recipes_dir,
2250 def make_alias_package( project, packages_dico ):
2252 #TO DO need to be do in conf file.
2253 alias_package["python-libxml2"] = "libxml2"
2254 alias_package["python-magic"] = "file"
2255 alias_package["cross-arm-binutils"] = "binutils"
2256 alias_package["cross-armv7hl-gcc47-icecream-backend"] = "gcc47"
2257 alias_package["libffi47"] = "gcc47"
2258 alias_package["crosswalk-bin"] = "crosswalk"
2260 for alias in alias_package.keys():
2261 alias_to = alias_package[alias]
2262 if alias_to in packages_dico.keys() and alias not in packages_dico.keys():
2263 a_package_def = packages_dico[alias_to]
2264 packages_dico[alias] = package_def( project,
2266 a_package_def.git_path,
2267 a_package_def.meta_path,
2268 a_package_def.git_revision,
2269 a_package_def.priority,
2270 a_package_def.git_src )
2272 return packages_dico
2274 class manifestCollection:
2276 class for all package in a distro.
2278 def __init__( self , project ):
2282 self.__my_project = project
2284 self.__recipes_list = None
2286 if not SPEC2YOCTO_CONFIG.is_valide_project( self.__my_project ):
2287 msg = "\"%s\" has no configuration in file \"%s\"."
2288 msg = msg % ( self.__my_project, CONFIGURATION_FILE_PATH )
2289 print >> sys.stderr, colorize( msg, "red" )
2292 #Just get the list of manifest uri.
2293 self.__my_manifest_meta_list = SPEC2YOCTO_CONFIG.get_manifest_meta_list( self.__my_project )
2295 self.__my_manifest_file_list = {}
2296 #Load the project manifest.
2297 self.__update_meta_manifests()
2299 self.__my_package_dico = {}
2300 self.__generate_package()
2302 self.__my_package_dico = make_alias_package( self.__my_project, self.__my_package_dico )
2304 def parse_manifest_xml( self, src ):
2305 primaryFile = open( src, "r" )
2306 primaryXML = primaryFile.read()
2309 aElement = ElementTree.fromstring( primaryXML )
2312 for value in aElement:
2313 for project in value.getiterator():
2314 if project.tag == "project":
2315 name = project.attrib['name']
2316 short_name=clean_name( name )
2317 revision = clean_revision( project.attrib['revision'] )
2318 packages_dico[short_name] = [name, revision]
2319 elif project.tag == "default":
2320 remote = project.attrib['remote']
2321 elif project.tag == "remote":
2322 fetch = project.attrib['fetch']
2323 name = project.attrib['name']
2327 return remote, packages_dico
2329 def print_list( self ):
2330 pkg_list = self.__my_package_dico.keys()
2332 for package in pkg_list:
2333 self.__my_package_dico[package].printMe()
2335 def __generate_package( self ):
2336 for meta_manifest in self.__my_manifest_file_list.keys():
2337 manifest_uri = self.__my_manifest_file_list[meta_manifest]
2339 manifest_git = SPEC2YOCTO_CONFIG.get_manifest_default_git_src( meta_manifest )
2340 manifest_priority = SPEC2YOCTO_CONFIG.get_manifest_priority( meta_manifest )
2341 remote, packages_dico = self.parse_manifest_xml( manifest_uri )
2343 if manifest_git is not None:
2344 remote = manifest_git
2346 whitelist_dico = SPEC2YOCTO_CONFIG.get_whitelist(self.__my_project)
2348 if len( whitelist_dico.keys() ) != 0:
2349 list_packages = set(whitelist_dico.keys())
2351 list_packages = set(packages_dico.keys())
2353 blacklist = set(SPEC2YOCTO_CONFIG.get_list(self.__my_project, "blacklist"))
2354 list_packages=list_packages.difference(blacklist)
2355 for package in list_packages:
2356 meta_path=whitelist_dico[package]
2357 if package in packages_dico.keys():
2358 [git_path, revision] = packages_dico[package]
2360 if package in self.__my_package_dico.keys():
2361 if manifest_priority > self.__my_package_dico[package].priority:
2362 self.__my_package_dico[package] = package_def( self.__my_project,
2369 elif manifest_priority == self.__my_package_dico[package].priority:
2370 msg = "most of one occurence of package \"%s\" ."
2371 msg = msg % ( package )
2372 print >> sys.stderr, colorize( msg, "red" )
2375 self.__my_package_dico[package] = package_def( self.__my_project,
2382 for package in whitelist_dico.keys():
2383 if package not in self.__my_package_dico.keys():
2384 msg = "package \"%s\" is in the white list but not in the manifest."
2385 msg = msg % ( package )
2386 print >> sys.stderr, colorize( msg, "red" )
2389 def __update_meta_manifests( self ):
2391 find/download all manifest.xml file.
2393 for meta_manifest in self.__my_manifest_meta_list:
2394 meta_manifest_uri = SPEC2YOCTO_CONFIG.get_manifest_uri( meta_manifest )
2395 if meta_manifest_uri is None:
2396 msg = "\"%s\" has no URI configuration in file \"%s\"."
2397 msg = msg % ( meta_manifest_uri, CONFIGURATION_FILE_PATH )
2398 print >> sys.stderr, colorize( msg, "red" )
2400 if meta_manifest_uri.startswith( "http" ):
2401 if meta_manifest_uri.endswith( ".xml" ):
2402 meta_manifest_url_path = meta_manifest_uri
2403 manifest_name = os.path.basename(meta_manifest_uri)
2405 xml_str = download_build_xml( meta_manifest_uri )
2406 project_id = get_project_id( xml_str )
2407 list_arch = get_project_arch( xml_str )
2408 list_buildtarget = get_project_buildtarget(xml_str)
2410 arch = SPEC2YOCTO_CONFIG.get_project_arch( self.__my_project )
2411 buildtarget = SPEC2YOCTO_CONFIG.get_manifest_buildtarget(meta_manifest)
2413 if ( arch == "i586" ) and ( "ia32" in list_arch ):
2415 buildtarget ="ia32-wayland"
2417 elif ( arch is None ) and ( len( list_arch ) > 0 ):
2420 elif ( arch not in list_arch ):
2423 manifest_name = "%s_%s.xml" % ( project_id, buildtarget )
2424 meta_manifest_url_path = "%s/builddata/manifest/%s"
2425 meta_manifest_url_path = meta_manifest_url_path % ( meta_manifest_uri,
2428 manifest_xml = download_manifest_url( meta_manifest_url_path )
2429 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( self.__my_project )
2431 meta_manifest_dir = os.path.join( working_dir, "manifest_file" )
2432 meta_manifest_path = os.path.join( meta_manifest_dir, manifest_name )
2434 if not os.path.isdir( meta_manifest_dir ):
2435 os.makedirs( meta_manifest_dir )
2437 with open( meta_manifest_path, "w" ) as manifest_xml_file:
2438 manifest_xml_file.write( manifest_xml )
2440 filename = os.path.expanduser(os.path.expandvars(meta_manifest_uri))
2442 if not os.path.isfile( filename ):
2443 msg = "In the project \"%s\" the manifest \"%s\" is not a valid file."
2444 msg = msg % ( self.__my_project, meta_manifest_uri )
2445 print >> sys.stderr, colorize( msg, "red" )
2448 meta_manifest_path = filename
2450 self.__my_manifest_file_list[ meta_manifest ] = meta_manifest_path
2452 def createRecipes( self ):
2456 self.__recipes_dir_dest = SPEC2YOCTO_CONFIG.get_recipes_sources_directory( self.__my_project )
2458 #self.__clean_old_bb_files(self.__recipes_dir_dest)
2460 if self.__recipes_dir_dest is None:
2461 msg = "In the project \"%s\" recipes_dir_sources is not define."
2462 msg = msg % ( self.__my_project )
2463 print >> sys.stderr, colorize( msg, "red" )
2465 elif not os.path.isdir( self.__recipes_dir_dest ):
2466 os.makedirs( self.__recipes_dir_dest )
2468 self.__meta_spec_dico = {}
2469 self.__meta_spec_boot_strap_dico = {}
2471 self.__set_oe_package_blacklist()
2472 self.__set_native_package_blacklist()
2474 self.__init_depends()
2475 self.__init_MetaSpec()
2478 def __clean_old_bb_files( self ,path):
2479 for root, dirs, files in os.walk(path):
2480 for a_file in files:
2481 if a_file.endswith(".bb"):
2482 os.unlink( os.path.join(path, root, a_file) )
2485 def __set_oe_package_blacklist( self ):
2487 load oe_package_blacklist
2489 list_package = SPEC2YOCTO_CONFIG.get_list(self.__my_project, "runtime_blacklist")
2490 MetaSpec.mOePackageBlacklist.extend( list_package )
2492 def __set_native_package_blacklist( self ):
2494 load oe_package_blacklist
2496 list_package = SPEC2YOCTO_CONFIG.get_list(self.__my_project, "native_blacklist")
2497 MetaSpec.mNativePackageBlacklist.extend( list_package )
2500 def __init_MetaSpec( self ):
2501 pkg_list = self.__my_package_dico.keys()
2504 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( self.__my_project )
2505 source_spec_dir = os.path.join( working_dir, "specfile-initial" )
2507 for package in pkg_list:
2508 self.__my_package_dico[package].create_MetaSpec( self.__recipes_dir_dest,
2511 def __init_depends( self ):
2515 self.__load_package_provided_extra()
2517 pkg_list = self.__my_package_dico.keys()
2520 def __load_package_provided_extra( self ):
2522 load_package_provided_extra
2524 provided_extra_dico = SPEC2YOCTO_CONFIG.get_provided_extra( self.__my_project )
2526 for k_package in provided_extra_dico.keys():
2527 raw_list=provided_extra_dico[k_package]
2529 if k_package not in MetaSpec.mProvidesDico.keys():
2530 MetaSpec.mProvidesDico[k_package] = []
2532 MetaSpec.mProvidesDico[k_package].extend( raw_list )
2534 if k_package not in MetaSpec.mExtraRProvidesDico.keys():
2535 MetaSpec.mExtraRProvidesDico[k_package] = []
2536 MetaSpec.mExtraRProvidesDico[k_package].extend( raw_list )
2538 TERMINAL_COLORS = {"black": "\033[30;1m",
2539 "red": "\033[31;1m",
2540 "green": "\033[32;1m",
2541 "yellow": "\033[33;1m",
2542 "blue": "\033[34;1m",
2543 "magenta": "\033[35;1m",
2544 "cyan": "\033[36;1m",
2545 "white": "\033[37;1m",
2546 "default": "\033[0m"}
2548 def colorize( text, color = "green" ):
2550 Return a colorized copy of `text`.
2551 See Utils.TERMINAL_COLORS.keys() for available colors.
2553 return TERMINAL_COLORS.get( color, "" ) + text + TERMINAL_COLORS["default"]
2556 def check_group_file( project ):
2557 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( project )
2559 group_uri = SPEC2YOCTO_CONFIG.get_group_uri( project )
2561 if group_uri.startswith( "http" ):
2562 group_file_path = os.path.join( working_dir, "group/group.xml" )
2563 group_xml = download_url( group_uri )
2565 with open( group_file_path, "w" ) as group_file:
2566 group_file.write( group_xml )
2568 return group_file_path
2572 def parse_group_xml( src ):
2573 groupFile = open( src, "r" )
2574 groupXML = groupFile.read()
2577 aElement = ElementTree.fromstring( groupXML )
2580 for group in aElement:
2581 if group.tag == "group":
2584 for element in group:
2585 if element.tag == "name":
2586 group_name = element.text
2587 elif element.tag == "packagelist":
2588 for packagereq in element:
2589 list_package.append(packagereq.text)
2591 packages_dico[group_name]=list_package
2592 return packages_dico
2594 def dump_group(project,group_dico):
2596 recipes_group_directory = SPEC2YOCTO_CONFIG.get_recipes_group_directory( project )
2598 for group in group_dico.keys():
2599 group_str = group.replace( " ", "-" )
2600 path = os.path.join( recipes_group_directory, "packagegroup-tizen-%s.bb" % group_str )
2602 with open(path,"w") as group_file:
2603 group_file.write( "SUMMARY = \"%s\"\n" % group )
2604 group_file.write( "DESCRIPTION = \"%s\"\n" % group )
2605 group_file.write( "LICENSE = \"MIT\"\n" )
2606 group_file.write( "DEPENDS = \"virtual/kernel\"\n" )
2607 group_file.write( "PR = \"r1\"\n" )
2609 group_file.write( "inherit packagegroup\n" )
2610 group_file.write( "\n" )
2611 group_file.write( "PACKAGE_ARCH = \"${MACHINE_ARCH}\"\n" )
2612 group_file.write( "\n" )
2614 group_file.write( "RDEPENDS_${PN} = \"\" \n\n" )
2615 for pkg in group_dico[group]:
2616 group_file.write( "RDEPENDS_${PN} += \"%s\"\n" % pkg )
2618 def generateBuildStatus( project_path ):
2621 if not os.path.isdir( project_path ):
2622 msg = "The path \"%s\" is not a directory."
2623 msg = msg % ( project_path )
2624 print >> sys.stderr, colorize( msg, "red" )
2627 for package_path in os.listdir( project_path ):
2628 project_full_path = os.path.join( project_path, package_path )
2629 if ( package_path == "build_stats" ) and os.path.isfile( project_full_path ) :
2632 elif os.path.isdir( project_full_path ):
2633 BN, PV, PR = cleanPackageName( package_path )
2634 res_status = check_package_status( project_full_path )
2636 if BN.endswith("-native"):
2637 res_native[BN] = [PV ] + res_status
2639 res[BN] = [PV ] + res_status
2642 elif package_path in ["."]:
2646 msg = "This directory should not contain the file \"%s\"."
2647 msg = msg % ( package_path )
2648 print >> sys.stderr, colorize( msg, "red" )
2651 return res_native, res
2653 def cleanPackageName( package_path ):
2654 if package_path.count( "-" ) < 2:
2655 msg = "unknow format for package \"%s\"."
2656 msg = msg % ( package_path )
2657 print >> sys.stderr, colorize( msg, "red" )
2660 PR=package_path[package_path.rindex("-")+1:]
2661 package_path=package_path[:package_path.rindex("-")]
2662 PV=package_path[package_path.rindex("-")+1:]
2663 BN=package_path[:package_path.rindex("-")]
2668 def check_package_status( project_full_path ):
2669 tasks_order = ["do_fetch",
2676 "do_populate_sysroot",
2679 "do_package_write_rpm",
2683 for package_task in os.listdir( project_full_path ):
2684 if package_task in tasks_order:
2685 task_index = tasks_order.index( package_task )
2687 if task_index > max_index:
2688 max_index = task_index
2691 msg = "No log task in \"%s\"."
2692 msg = msg % ( project_full_path )
2693 print >> sys.stderr, colorize( msg, "red" )
2696 last_task = tasks_order[max_index][3:]
2700 with open( os.path.join( project_full_path, tasks_order[max_index] ) ) as status_file:
2701 for line in status_file:
2702 if line.startswith( "Status: " ):
2703 status = line[len( "Status: " ):].replace( "\n", "" ).replace( " ", "" )
2705 if last_task == "package_write_rpm" and status == "PASSED":
2708 return [last_task, status]
2710 def clean_Packagegroup( project,group_dico ):
2713 package_replacement = SPEC2YOCTO_CONFIG.get_substitute( project )
2715 for group in group_dico.keys():
2716 group_dico_tmp[group] = []
2717 for package in group_dico[group]:
2718 if package in package_replacement.keys():
2719 group_dico_tmp[group].append( package_replacement[package] )
2721 group_dico_tmp[group].append( package )
2723 return group_dico_tmp
2726 def check_debugmode( opts_debug ):
2728 if opts_debug == "no":
2730 elif opts_debug == "yes":
2734 class spec2yoctoCommandline( cmdln.Cmdln ):
2738 def do_manifestToList( self, subcmd, opts, project = None ):
2739 """${cmd_name}: print the list of package in projects.
2745 project = SPEC2YOCTO_CONFIG.get_current_project()
2747 pkg_co = manifestCollection( project )
2750 def do_createRecipes( self, subcmd, opts, project = None ):
2751 """${cmd_name}: create all packages recipes.
2757 project = SPEC2YOCTO_CONFIG.get_current_project()
2759 pkg_co = manifestCollection( project )
2760 pkg_co.createRecipes()
2762 @cmdln.option( "--package_pn",
2765 help = "select the package_pn." )
2766 def do_findBestSpecFile( self, subcmd, opts, package_path ):
2767 """${cmd_name}: print the speec file associate to package.
2772 res = findBestSpecFile( package_path, opts.package_pn )
2775 @cmdln.option( "--package_pn",
2778 help = "select the package_pn." )
2779 def do_findSpecPatchFiles( self, subcmd, opts, patch_dir, ):
2780 """${cmd_name}: print patch from "specfile-patch" directory associate to package.
2785 res = findSpecPatchFiles( patch_dir, opts.package_pn )
2786 print " ".join( res )
2788 @cmdln.option( "--package_pn",
2791 help = "select the package_pn." )
2792 @cmdln.option( "--project",
2795 help = "select the package_pn." )
2796 def do_specfile_patcher( self, subcmd, opts, package_spec_path ):
2797 """${cmd_name}: patch the spec file with patch from "specfile-patch" directory.
2802 if opts.project is None:
2803 project = SPEC2YOCTO_CONFIG.get_current_project()
2805 project = opts.project
2807 res = specfile_patcher( package_spec_path, project, opts.package_pn, package_spec_path )
2810 def do_createPackagegroup( self, subcmd, opts, project = None ):
2811 """${cmd_name}: print the list of package in projects.
2817 project = SPEC2YOCTO_CONFIG.get_current_project()
2820 res = SPEC2YOCTO_CONFIG.get_group( project )
2821 group_file_path = check_group_file( project )
2822 group_dico= parse_group_xml( group_file_path )
2824 group_dico = clean_Packagegroup( project, group_dico )
2826 dump_group(project,group_dico)
2828 @cmdln.option( "--debug",
2831 help = "run the in debug mode.[yes/no]" )
2832 @cmdln.option( "--project",
2835 help = "select the project." )
2836 @cmdln.option( "--package_pn",
2839 help = "select the package_pn." )
2840 def do_prep( self, subcmd, opts, spec_path ):
2841 """${cmd_name}: print the bash code of the %prep section of a spec file.
2846 check_debugmode( opts.debug )
2848 if opts.project is None:
2849 project = SPEC2YOCTO_CONFIG.get_current_project()
2851 project = opts.project
2853 res = SpecParser( spec_path, package_pn = opts.package_pn ).get_prep_section()
2857 @cmdln.option( "--debug",
2860 help = "run the in debug mode.[yes/no]" )
2861 @cmdln.option( "--project",
2864 help = "select the project." )
2865 @cmdln.option( "--package_pn",
2868 help = "select the package_pn." )
2869 def do_compile( self, subcmd, opts, spec_path ):
2870 """${cmd_name}: print the bash code of the %build section of a spec file.
2875 check_debugmode( opts.debug )
2877 if opts.project is None:
2878 project = SPEC2YOCTO_CONFIG.get_current_project()
2880 project = opts.project
2882 res = SpecParser( spec_path, package_pn = opts.package_pn ).get_build_section()
2886 @cmdln.option( "--debug",
2889 help = "run the in debug mode.[yes/no]" )
2890 @cmdln.option( "--project",
2893 help = "select the project." )
2894 @cmdln.option( "--package_pn",
2897 help = "select the package_pn." )
2898 def do_install( self, subcmd, opts, spec_path ):
2899 """${cmd_name}: print the bash code of the %install section of a spec file.
2904 check_debugmode( opts.debug )
2907 if opts.project is None:
2908 project = SPEC2YOCTO_CONFIG.get_current_project()
2910 project = opts.project
2912 res = SpecParser( spec_path, package_pn = opts.package_pn ).get_install_section()
2916 @cmdln.option( "--debug",
2919 help = "run the in debug mode.[yes/no]" )
2920 def do_generateBuildStatus( self, subcmd, opts, project_path ):
2921 """${cmd_name}: print the status and the the build state of packages,
2922 builded in a single command.
2924 build/tmp-eglibc/buildstats/core-image-minimal-qemux86/XXXX/
2928 check_debugmode( opts.debug )
2930 res_native, res = generateBuildStatus( project_path )
2932 res_native_keys = res_native.keys()
2933 res_keys = res.keys()
2935 res_native_keys.sort()
2938 for r in res_native_keys:
2939 print r + "\t" + "\t".join( res_native[r] )
2942 print r + "\t" + "\t".join( res[r] )
2945 @cmdln.option( "--debug",
2948 help = "run the in debug mode.[yes/no]" )
2949 def do_generatePseudoSpecfile( self, subcmd, opts, spec_path ):
2950 """${cmd_name}: generate a spec file use by yocto, for packaging rpm.
2955 check_debugmode( opts.debug )
2957 a_spec_parser = SpecParser( spec_path )
2958 a_spec_parser.parse_raw_spec_file()
2959 res = a_spec_parser.get_clean_raw()
2963 @cmdln.option( "--debug",
2966 help = "run the in debug mode.[yes/no]" )
2967 @cmdln.option( "--project",
2970 help = "select the project." )
2971 def do_working_dir( self, subcmd, opts ):
2972 """${cmd_name}: return the proto directory.
2977 check_debugmode( opts.debug )
2979 if opts.project is None:
2980 project = SPEC2YOCTO_CONFIG.get_current_project()
2982 project = opts.project
2984 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( project )
2985 if working_dir != 1:
2989 commandline = spec2yoctoCommandline()
2992 res = commandline.main()
2993 except ValueError as ve:
2995 print >> sys.stderr, colorize( str( ve ), "red" )
2997 except EnvironmentError as ioe:
2998 # commandline.do_help([sys.argv[0]])
3000 print >> sys.stderr, colorize( str( ioe ), "red" )
3001 if hasattr( ioe, "spec2yocto_config_error" ):
3002 msg = "See '--config' option"
3003 print >> sys.stderr, colorize( msg, "red" )
3005 # except Exception as e_all :
3007 # print >> sys.stderr, colorize( str( e_all ), "red" )
3011 if __name__ == '__main__':