2014-12-19 11:41:53 +00:00
# Recipe creation tool - create command plugin
#
2016-03-09 04:48:49 +00:00
# Copyright (C) 2014-2016 Intel Corporation
2014-12-19 11:41:53 +00:00
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import sys
import os
import argparse
import glob
import fnmatch
import re
2016-01-18 11:18:31 +00:00
import json
2014-12-19 11:41:53 +00:00
import logging
2015-04-28 11:25:30 +00:00
import scriptutils
2015-09-22 16:21:29 +00:00
import urlparse
2016-03-09 04:48:51 +00:00
import hashlib
2014-12-19 11:41:53 +00:00
logger = logging . getLogger ( ' recipetool ' )
tinfoil = None
plugins = None
def plugin_init ( pluginlist ) :
# Take a reference to the list so we can use it later
global plugins
plugins = pluginlist
def tinfoil_init ( instance ) :
global tinfoil
tinfoil = instance
2016-01-18 11:18:31 +00:00
class RecipeHandler ( object ) :
recipelibmap = { }
recipeheadermap = { }
2016-02-19 09:39:02 +00:00
recipecmakefilemap = { }
2016-03-09 04:48:49 +00:00
recipebinmap = { }
2016-01-18 11:18:31 +00:00
@staticmethod
def load_libmap ( d ) :
''' Load library->recipe mapping '''
import oe . package
if RecipeHandler . recipelibmap :
return
# First build up library->package mapping
shlib_providers = oe . package . read_shlib_providers ( d )
libdir = d . getVar ( ' libdir ' , True )
base_libdir = d . getVar ( ' base_libdir ' , True )
libpaths = list ( set ( [ base_libdir , libdir ] ) )
libname_re = re . compile ( ' ^lib(.+) \ .so.*$ ' )
pkglibmap = { }
2016-05-18 18:39:44 +00:00
for lib , item in shlib_providers . items ( ) :
for path , pkg in item . items ( ) :
2016-01-18 11:18:31 +00:00
if path in libpaths :
res = libname_re . match ( lib )
if res :
libname = res . group ( 1 )
if not libname in pkglibmap :
pkglibmap [ libname ] = pkg [ 0 ]
else :
logger . debug ( ' unable to extract library name from %s ' % lib )
# Now turn it into a library->recipe mapping
pkgdata_dir = d . getVar ( ' PKGDATA_DIR ' , True )
2016-05-18 18:39:44 +00:00
for libname , pkg in pkglibmap . items ( ) :
2016-01-18 11:18:31 +00:00
try :
with open ( os . path . join ( pkgdata_dir , ' runtime ' , pkg ) ) as f :
for line in f :
if line . startswith ( ' PN: ' ) :
RecipeHandler . recipelibmap [ libname ] = line . split ( ' : ' , 1 ) [ - 1 ] . strip ( )
break
except IOError as ioe :
if ioe . errno == 2 :
logger . warn ( ' unable to find a pkgdata file for package %s ' % pkg )
else :
raise
2016-01-18 11:18:32 +00:00
# Some overrides - these should be mapped to the virtual
RecipeHandler . recipelibmap [ ' GL ' ] = ' virtual/libgl '
RecipeHandler . recipelibmap [ ' EGL ' ] = ' virtual/egl '
RecipeHandler . recipelibmap [ ' GLESv2 ' ] = ' virtual/libgles2 '
2016-01-18 11:18:31 +00:00
@staticmethod
2016-02-19 09:39:02 +00:00
def load_devel_filemap ( d ) :
''' Build up development file->recipe mapping '''
2016-01-18 11:18:31 +00:00
if RecipeHandler . recipeheadermap :
return
2016-02-19 09:39:02 +00:00
pkgdata_dir = d . getVar ( ' PKGDATA_DIR ' , True )
2016-01-18 11:18:31 +00:00
includedir = d . getVar ( ' includedir ' , True )
2016-02-19 09:39:02 +00:00
cmakedir = os . path . join ( d . getVar ( ' libdir ' , True ) , ' cmake ' )
2016-01-18 11:18:31 +00:00
for pkg in glob . glob ( os . path . join ( pkgdata_dir , ' runtime ' , ' *-dev ' ) ) :
with open ( os . path . join ( pkgdata_dir , ' runtime ' , pkg ) ) as f :
pn = None
headers = [ ]
2016-02-19 09:39:02 +00:00
cmakefiles = [ ]
2016-01-18 11:18:31 +00:00
for line in f :
if line . startswith ( ' PN: ' ) :
pn = line . split ( ' : ' , 1 ) [ - 1 ] . strip ( )
elif line . startswith ( ' FILES_INFO: ' ) :
val = line . split ( ' : ' , 1 ) [ 1 ] . strip ( )
dictval = json . loads ( val )
for fullpth in sorted ( dictval ) :
if fullpth . startswith ( includedir ) and fullpth . endswith ( ' .h ' ) :
headers . append ( os . path . relpath ( fullpth , includedir ) )
2016-02-19 09:39:02 +00:00
elif fullpth . startswith ( cmakedir ) and fullpth . endswith ( ' .cmake ' ) :
cmakefiles . append ( os . path . relpath ( fullpth , cmakedir ) )
2016-01-18 11:18:31 +00:00
if pn and headers :
for header in headers :
RecipeHandler . recipeheadermap [ header ] = pn
2016-02-19 09:39:02 +00:00
if pn and cmakefiles :
for fn in cmakefiles :
RecipeHandler . recipecmakefilemap [ fn ] = pn
2016-01-18 11:18:31 +00:00
2016-03-09 04:48:49 +00:00
@staticmethod
def load_binmap ( d ) :
''' Build up native binary->recipe mapping '''
if RecipeHandler . recipebinmap :
return
sstate_manifests = d . getVar ( ' SSTATE_MANIFESTS ' , True )
staging_bindir_native = d . getVar ( ' STAGING_BINDIR_NATIVE ' , True )
build_arch = d . getVar ( ' BUILD_ARCH ' , True )
fileprefix = ' manifest- %s - ' % build_arch
for fn in glob . glob ( os . path . join ( sstate_manifests , ' %s *-native.populate_sysroot ' % fileprefix ) ) :
with open ( fn , ' r ' ) as f :
pn = os . path . basename ( fn ) . rsplit ( ' . ' , 1 ) [ 0 ] [ len ( fileprefix ) : ]
for line in f :
if line . startswith ( staging_bindir_native ) :
prog = os . path . basename ( line . rstrip ( ) )
RecipeHandler . recipebinmap [ prog ] = pn
2014-12-19 11:41:53 +00:00
@staticmethod
2015-12-22 04:03:02 +00:00
def checkfiles ( path , speclist , recursive = False ) :
2014-12-19 11:41:53 +00:00
results = [ ]
2015-12-22 04:03:02 +00:00
if recursive :
for root , _ , files in os . walk ( path ) :
for fn in files :
for spec in speclist :
if fnmatch . fnmatch ( fn , spec ) :
results . append ( os . path . join ( root , fn ) )
else :
for spec in speclist :
results . extend ( glob . glob ( os . path . join ( path , spec ) ) )
2014-12-19 11:41:53 +00:00
return results
2016-01-18 11:18:31 +00:00
@staticmethod
def handle_depends ( libdeps , pcdeps , deps , outlines , values , d ) :
if pcdeps :
recipemap = read_pkgconfig_provides ( d )
if libdeps :
RecipeHandler . load_libmap ( d )
ignorelibs = [ ' socket ' ]
2016-03-09 04:48:49 +00:00
ignoredeps = [ ' gcc-runtime ' , ' glibc ' , ' uclibc ' , ' musl ' , ' tar-native ' , ' binutils-native ' , ' coreutils-native ' ]
2016-01-18 11:18:31 +00:00
unmappedpc = [ ]
pcdeps = list ( set ( pcdeps ) )
for pcdep in pcdeps :
2016-05-18 18:52:33 +00:00
if isinstance ( pcdep , str ) :
2016-01-18 11:18:31 +00:00
recipe = recipemap . get ( pcdep , None )
if recipe :
deps . append ( recipe )
else :
if not pcdep . startswith ( ' $ ' ) :
unmappedpc . append ( pcdep )
else :
for item in pcdep :
recipe = recipemap . get ( pcdep , None )
if recipe :
deps . append ( recipe )
break
else :
unmappedpc . append ( ' ( %s ) ' % ' or ' . join ( pcdep ) )
unmappedlibs = [ ]
for libdep in libdeps :
if isinstance ( libdep , tuple ) :
lib , header = libdep
else :
lib = libdep
header = None
if lib in ignorelibs :
logger . debug ( ' Ignoring library dependency %s ' % lib )
continue
recipe = RecipeHandler . recipelibmap . get ( lib , None )
if recipe :
deps . append ( recipe )
elif recipe is None :
if header :
2016-02-19 09:39:02 +00:00
RecipeHandler . load_devel_filemap ( d )
2016-01-18 11:18:31 +00:00
recipe = RecipeHandler . recipeheadermap . get ( header , None )
if recipe :
deps . append ( recipe )
elif recipe is None :
unmappedlibs . append ( lib )
else :
unmappedlibs . append ( lib )
deps = set ( deps ) . difference ( set ( ignoredeps ) )
if unmappedpc :
outlines . append ( ' # NOTE: unable to map the following pkg-config dependencies: %s ' % ' ' . join ( unmappedpc ) )
outlines . append ( ' # (this is based on recipes that have previously been built and packaged) ' )
if unmappedlibs :
outlines . append ( ' # NOTE: the following library dependencies are unknown, ignoring: %s ' % ' ' . join ( list ( set ( unmappedlibs ) ) ) )
outlines . append ( ' # (this is based on recipes that have previously been built and packaged) ' )
if deps :
values [ ' DEPENDS ' ] = ' ' . join ( deps )
2015-09-22 16:21:28 +00:00
def genfunction ( self , outlines , funcname , content , python = False , forcespace = False ) :
if python :
prefix = ' python '
else :
prefix = ' '
outlines . append ( ' %s %s () { ' % ( prefix , funcname ) )
if python or forcespace :
indent = ' '
else :
indent = ' \t '
addnoop = not python
2014-12-19 11:41:53 +00:00
for line in content :
2015-09-22 16:21:28 +00:00
outlines . append ( ' %s %s ' % ( indent , line ) )
if addnoop :
strippedline = line . lstrip ( )
if strippedline and not strippedline . startswith ( ' # ' ) :
addnoop = False
if addnoop :
# Without this there'll be a syntax error
outlines . append ( ' %s : ' % indent )
2014-12-19 11:41:53 +00:00
outlines . append ( ' } ' )
outlines . append ( ' ' )
2015-12-22 04:03:02 +00:00
def process ( self , srctree , classes , lines_before , lines_after , handled , extravalues ) :
2014-12-19 11:41:53 +00:00
return False
2015-12-22 04:03:02 +00:00
def validate_pv ( pv ) :
if not pv or ' _version ' in pv . lower ( ) or pv [ 0 ] not in ' 0123456789 ' :
return False
return True
2014-12-19 11:41:53 +00:00
2015-12-22 04:03:03 +00:00
def determine_from_filename ( srcfile ) :
""" Determine name and version from a filename """
part = ' '
if ' .tar. ' in srcfile :
2016-01-06 11:15:49 +00:00
namepart = srcfile . split ( ' .tar. ' ) [ 0 ] . lower ( )
2015-12-22 04:03:03 +00:00
else :
2016-01-06 11:15:49 +00:00
namepart = os . path . splitext ( srcfile ) [ 0 ] . lower ( )
2016-05-29 22:21:00 +00:00
if is_package ( srcfile ) :
# Force getting the value from the package metadata
return None , None
else :
splitval = namepart . rsplit ( ' _ ' , 1 )
2015-12-22 04:03:03 +00:00
if len ( splitval ) == 1 :
splitval = namepart . rsplit ( ' - ' , 1 )
pn = splitval [ 0 ] . replace ( ' _ ' , ' - ' )
if len ( splitval ) > 1 :
if splitval [ 1 ] [ 0 ] in ' 0123456789 ' :
pv = splitval [ 1 ]
else :
pn = ' - ' . join ( splitval ) . replace ( ' _ ' , ' - ' )
pv = None
else :
pv = None
return ( pn , pv )
2016-02-11 01:13:30 +00:00
def determine_from_url ( srcuri ) :
""" Determine name and version from a URL """
pn = None
pv = None
2016-02-11 01:13:33 +00:00
parseres = urlparse . urlparse ( srcuri . lower ( ) . split ( ' ; ' , 1 ) [ 0 ] )
2016-02-11 01:13:30 +00:00
if parseres . path :
if ' github.com ' in parseres . netloc :
res = re . search ( r ' .*/(.*?)/archive/(.*)-final \ .(tar|zip) ' , parseres . path )
if res :
pn = res . group ( 1 ) . strip ( ) . replace ( ' _ ' , ' - ' )
pv = res . group ( 2 ) . strip ( ) . replace ( ' _ ' , ' . ' )
else :
res = re . search ( r ' .*/(.*?)/archive/v?(.*) \ .(tar|zip) ' , parseres . path )
if res :
pn = res . group ( 1 ) . strip ( ) . replace ( ' _ ' , ' - ' )
pv = res . group ( 2 ) . strip ( ) . replace ( ' _ ' , ' . ' )
elif ' bitbucket.org ' in parseres . netloc :
res = re . search ( r ' .*/(.*?)/get/[a-zA-Z_-]*([0-9][0-9a-zA-Z_.]*) \ .(tar|zip) ' , parseres . path )
if res :
pn = res . group ( 1 ) . strip ( ) . replace ( ' _ ' , ' - ' )
pv = res . group ( 2 ) . strip ( ) . replace ( ' _ ' , ' . ' )
if not pn and not pv :
srcfile = os . path . basename ( parseres . path . rstrip ( ' / ' ) )
pn , pv = determine_from_filename ( srcfile )
logger . debug ( ' Determined from source URL: name = " %s " , version = " %s " ' % ( pn , pv ) )
return ( pn , pv )
2014-12-19 11:41:53 +00:00
def supports_srcrev ( uri ) :
localdata = bb . data . createCopy ( tinfoil . config_data )
2015-04-28 16:10:11 +00:00
# This is a bit sad, but if you don't have this set there can be some
# odd interactions with the urldata cache which lead to errors
localdata . setVar ( ' SRCREV ' , ' $ {AUTOREV} ' )
2014-12-19 11:41:53 +00:00
bb . data . update_data ( localdata )
fetcher = bb . fetch2 . Fetch ( [ uri ] , localdata )
urldata = fetcher . ud
for u in urldata :
if urldata [ u ] . method . supports_srcrev ( ) :
return True
return False
2016-01-22 11:59:59 +00:00
def reformat_git_uri ( uri ) :
''' Convert any http[s]://....git URI into git://...;protocol=http[s] '''
2016-02-11 01:13:34 +00:00
checkuri = uri . split ( ' ; ' , 1 ) [ 0 ]
if checkuri . endswith ( ' .git ' ) or ' /git/ ' in checkuri :
res = re . match ( ' (https?)://([^;]+( \ .git)?)(;.*)?$ ' , uri )
if res :
# Need to switch the URI around so that the git fetcher is used
return ' git:// %s ;protocol= %s %s ' % ( res . group ( 2 ) , res . group ( 1 ) , res . group ( 4 ) or ' ' )
2016-01-22 11:59:59 +00:00
return uri
2016-05-29 22:21:00 +00:00
def is_package ( url ) :
''' Check if a URL points to a package '''
checkurl = url . split ( ' ; ' , 1 ) [ 0 ]
if checkurl . endswith ( ( ' .deb ' , ' .ipk ' , ' .rpm ' , ' .srpm ' ) ) :
return True
return False
2014-12-19 11:41:53 +00:00
def create_recipe ( args ) :
import bb . process
import tempfile
import shutil
2016-05-29 22:20:59 +00:00
import oe . recipeutils
2014-12-19 11:41:53 +00:00
pkgarch = " "
if args . machine :
pkgarch = " $ {MACHINE_ARCH} "
2016-05-29 22:21:00 +00:00
extravalues = { }
2014-12-19 11:41:53 +00:00
checksums = ( None , None )
tempsrc = ' '
srcsubdir = ' '
2015-04-28 16:10:11 +00:00
srcrev = ' $ {AUTOREV} '
2014-12-19 11:41:53 +00:00
if ' :// ' in args . source :
# Fetch a URL
2016-01-22 11:59:59 +00:00
fetchuri = reformat_git_uri ( urlparse . urldefrag ( args . source ) [ 0 ] )
2015-09-22 16:21:39 +00:00
if args . binary :
# Assume the archive contains the directory structure verbatim
# so we need to extract to a subdirectory
2016-05-29 22:21:01 +00:00
fetchuri + = ' ;subdir=$ {BP} '
2015-09-22 16:21:29 +00:00
srcuri = fetchuri
2015-04-28 16:10:11 +00:00
rev_re = re . compile ( ' ;rev=([^;]+) ' )
res = rev_re . search ( srcuri )
if res :
srcrev = res . group ( 1 )
srcuri = rev_re . sub ( ' ' , srcuri )
2015-04-28 11:22:36 +00:00
tempsrc = tempfile . mkdtemp ( prefix = ' recipetool- ' )
srctree = tempsrc
2016-03-09 04:48:53 +00:00
if fetchuri . startswith ( ' npm:// ' ) :
# Check if npm is available
npm = bb . utils . which ( tinfoil . config_data . getVar ( ' PATH ' , True ) , ' npm ' )
if not npm :
logger . error ( ' npm:// URL requested but npm is not available - you need to either build nodejs-native or install npm using your package manager ' )
sys . exit ( 1 )
2014-12-19 11:41:53 +00:00
logger . info ( ' Fetching %s ... ' % srcuri )
2015-12-22 04:02:56 +00:00
try :
checksums = scriptutils . fetch_uri ( tinfoil . config_data , fetchuri , srctree , srcrev )
2016-01-22 12:00:01 +00:00
except bb . fetch2 . BBFetchException as e :
logger . error ( str ( e ) . rstrip ( ) )
2015-12-22 04:02:56 +00:00
sys . exit ( 1 )
2014-12-19 11:41:53 +00:00
dirlist = os . listdir ( srctree )
if ' git.indirectionsymlink ' in dirlist :
dirlist . remove ( ' git.indirectionsymlink ' )
2015-12-22 04:03:00 +00:00
if len ( dirlist ) == 1 :
singleitem = os . path . join ( srctree , dirlist [ 0 ] )
if os . path . isdir ( singleitem ) :
# We unpacked a single directory, so we should use that
srcsubdir = dirlist [ 0 ]
srctree = os . path . join ( srctree , srcsubdir )
else :
with open ( singleitem , ' r ' ) as f :
if ' <html ' in f . read ( 100 ) . lower ( ) :
logger . error ( ' Fetching " %s " returned a single HTML page - check the URL is correct and functional ' % fetchuri )
sys . exit ( 1 )
2016-05-29 22:21:00 +00:00
if is_package ( fetchuri ) :
tmpfdir = tempfile . mkdtemp ( prefix = ' recipetool- ' )
try :
pkgfile = None
try :
fileuri = fetchuri + ' ;unpack=0 '
scriptutils . fetch_uri ( tinfoil . config_data , fileuri , tmpfdir , srcrev )
for root , _ , files in os . walk ( tmpfdir ) :
for f in files :
pkgfile = os . path . join ( root , f )
break
except bb . fetch2 . BBFetchException as e :
logger . warn ( ' Second fetch to get metadata failed: %s ' % str ( e ) . rstrip ( ) )
if pkgfile :
if pkgfile . endswith ( ( ' .deb ' , ' .ipk ' ) ) :
stdout , _ = bb . process . run ( ' ar x %s control.tar.gz ' % pkgfile , cwd = tmpfdir )
stdout , _ = bb . process . run ( ' tar xf control.tar.gz ./control ' , cwd = tmpfdir )
values = convert_debian ( tmpfdir )
extravalues . update ( values )
elif pkgfile . endswith ( ( ' .rpm ' , ' .srpm ' ) ) :
stdout , _ = bb . process . run ( ' rpm -qp --xml %s > pkginfo.xml ' % pkgfile , cwd = tmpfdir )
values = convert_rpm_xml ( os . path . join ( tmpfdir , ' pkginfo.xml ' ) )
extravalues . update ( values )
finally :
shutil . rmtree ( tmpfdir )
2014-12-19 11:41:53 +00:00
else :
# Assume we're pointing to an existing source tree
2015-02-19 16:39:50 +00:00
if args . extract_to :
logger . error ( ' --extract-to cannot be specified if source is a directory ' )
2014-12-19 11:41:53 +00:00
sys . exit ( 1 )
if not os . path . isdir ( args . source ) :
logger . error ( ' Invalid source directory %s ' % args . source )
sys . exit ( 1 )
srctree = args . source
2016-01-22 11:59:59 +00:00
srcuri = ' '
if os . path . exists ( os . path . join ( srctree , ' .git ' ) ) :
# Try to get upstream repo location from origin remote
try :
stdout , _ = bb . process . run ( ' git remote -v ' , cwd = srctree , shell = True )
except bb . process . ExecutionError as e :
stdout = None
if stdout :
for line in stdout . splitlines ( ) :
splitline = line . split ( )
if len ( splitline ) > 1 :
if splitline [ 0 ] == ' origin ' and ' :// ' in splitline [ 1 ] :
srcuri = reformat_git_uri ( splitline [ 1 ] )
2016-02-11 01:13:35 +00:00
srcsubdir = ' git '
2016-01-22 11:59:59 +00:00
break
2014-12-19 11:41:53 +00:00
2016-01-22 11:59:58 +00:00
if args . src_subdir :
srcsubdir = os . path . join ( srcsubdir , args . src_subdir )
srctree_use = os . path . join ( srctree , args . src_subdir )
else :
srctree_use = srctree
2015-12-22 04:03:02 +00:00
if args . outfile and os . path . isdir ( args . outfile ) :
outfile = None
outdir = args . outfile
else :
outfile = args . outfile
outdir = None
2014-12-19 11:41:53 +00:00
if outfile and outfile != ' - ' :
if os . path . exists ( outfile ) :
logger . error ( ' Output file %s already exists ' % outfile )
sys . exit ( 1 )
lines_before = [ ]
lines_after = [ ]
lines_before . append ( ' # Recipe created by %s ' % os . path . basename ( sys . argv [ 0 ] ) )
lines_before . append ( ' # This is the basis of a recipe and may need further editing in order to be fully functional. ' )
lines_before . append ( ' # (Feel free to remove these comments when editing.) ' )
2016-05-29 22:20:59 +00:00
# We need a blank line here so that patch_recipe_lines can rewind before the LICENSE comments
lines_before . append ( ' ' )
2014-12-19 11:41:53 +00:00
2016-01-22 11:59:58 +00:00
licvalues = guess_license ( srctree_use )
2014-12-19 11:41:53 +00:00
lic_files_chksum = [ ]
if licvalues :
licenses = [ ]
for licvalue in licvalues :
if not licvalue [ 0 ] in licenses :
licenses . append ( licvalue [ 0 ] )
lic_files_chksum . append ( ' file:// %s ;md5= %s ' % ( licvalue [ 1 ] , licvalue [ 2 ] ) )
lines_before . append ( ' # WARNING: the following LICENSE and LIC_FILES_CHKSUM values are best guesses - it is ' )
lines_before . append ( ' # your responsibility to verify that the values are complete and correct. ' )
if len ( licvalues ) > 1 :
lines_before . append ( ' # ' )
lines_before . append ( ' # NOTE: multiple licenses have been detected; if that is correct you should separate ' )
lines_before . append ( ' # these in the LICENSE value using & if the multiple licenses all apply, or | if there ' )
lines_before . append ( ' # is a choice between the multiple licenses. If in doubt, check the accompanying ' )
lines_before . append ( ' # documentation to determine which situation is applicable. ' )
else :
lines_before . append ( ' # Unable to find any files that looked like license statements. Check the accompanying ' )
lines_before . append ( ' # documentation and source headers and set LICENSE and LIC_FILES_CHKSUM accordingly. ' )
lines_before . append ( ' # ' )
lines_before . append ( ' # NOTE: LICENSE is being set to " CLOSED " to allow you to at least start building - if ' )
lines_before . append ( ' # this is not accurate with respect to the licensing of the software being built (it ' )
lines_before . append ( ' # will not be in most cases) you must specify the correct value before using this ' )
lines_before . append ( ' # recipe for anything other than initial testing/development! ' )
licenses = [ ' CLOSED ' ]
2016-05-29 22:21:00 +00:00
pkg_license = extravalues . pop ( ' LICENSE ' , None )
if pkg_license :
if licenses == [ ' Unknown ' ] :
lines_before . append ( ' # NOTE: The following LICENSE value was determined from the original package metadata ' )
licenses = [ pkg_license ]
else :
lines_before . append ( ' # NOTE: Original package metadata indicates license is: %s ' % pkg_license )
2014-12-19 11:41:53 +00:00
lines_before . append ( ' LICENSE = " %s " ' % ' ' . join ( licenses ) )
lines_before . append ( ' LIC_FILES_CHKSUM = " %s " ' % ' \\ \n ' . join ( lic_files_chksum ) )
lines_before . append ( ' ' )
2016-01-06 11:15:50 +00:00
classes = [ ]
2014-12-19 11:41:53 +00:00
# FIXME This is kind of a hack, we probably ought to be using bitbake to do this
2015-12-22 04:03:02 +00:00
pn = None
pv = None
if outfile :
recipefn = os . path . splitext ( os . path . basename ( outfile ) ) [ 0 ]
fnsplit = recipefn . split ( ' _ ' )
if len ( fnsplit ) > 1 :
pn = fnsplit [ 0 ]
pv = fnsplit [ 1 ]
else :
pn = recipefn
2014-12-19 11:41:53 +00:00
2015-04-28 16:07:31 +00:00
if args . version :
pv = args . version
2015-12-22 04:03:02 +00:00
if args . name :
pn = args . name
2016-01-06 11:15:50 +00:00
if args . name . endswith ( ' -native ' ) :
2016-01-06 11:15:52 +00:00
if args . also_native :
logger . error ( ' --also-native cannot be specified for a recipe named *-native (*-native denotes a recipe that is already only for native) - either remove the -native suffix from the name or drop --also-native ' )
sys . exit ( 1 )
2016-01-06 11:15:50 +00:00
classes . append ( ' native ' )
elif args . name . startswith ( ' nativesdk- ' ) :
2016-01-06 11:15:52 +00:00
if args . also_native :
logger . error ( ' --also-native cannot be specified for a recipe named nativesdk-* (nativesdk-* denotes a recipe that is already only for nativesdk) ' )
sys . exit ( 1 )
2016-01-06 11:15:50 +00:00
classes . append ( ' nativesdk ' )
2015-12-22 04:03:02 +00:00
2015-04-28 16:07:31 +00:00
if pv and pv not in ' git svn hg ' . split ( ) :
realpv = pv
else :
realpv = None
2015-12-22 04:03:03 +00:00
if srcuri and not realpv or not pn :
2016-02-11 01:13:30 +00:00
name_pn , name_pv = determine_from_url ( srcuri )
if name_pn and not pn :
pn = name_pn
if name_pv and not realpv :
realpv = name_pv
2015-12-22 04:03:03 +00:00
2015-12-22 04:03:02 +00:00
if not srcuri :
2014-12-19 11:41:53 +00:00
lines_before . append ( ' # No information for SRC_URI yet (only an external source tree was specified) ' )
lines_before . append ( ' SRC_URI = " %s " ' % srcuri )
( md5value , sha256value ) = checksums
if md5value :
lines_before . append ( ' SRC_URI[md5sum] = " %s " ' % md5value )
if sha256value :
lines_before . append ( ' SRC_URI[sha256sum] = " %s " ' % sha256value )
if srcuri and supports_srcrev ( srcuri ) :
lines_before . append ( ' ' )
lines_before . append ( ' # Modify these as desired ' )
2015-04-28 16:07:31 +00:00
lines_before . append ( ' PV = " %s +git$ {SRCPV} " ' % ( realpv or ' 1.0 ' ) )
2016-05-29 22:21:02 +00:00
if not args . autorev and srcrev == ' $ {AUTOREV} ' :
if os . path . exists ( os . path . join ( srctree , ' .git ' ) ) :
( stdout , _ ) = bb . process . run ( ' git rev-parse HEAD ' , cwd = srctree )
srcrev = stdout . rstrip ( )
2015-04-28 16:10:11 +00:00
lines_before . append ( ' SRCREV = " %s " ' % srcrev )
2014-12-19 11:41:53 +00:00
lines_before . append ( ' ' )
2016-05-29 22:21:01 +00:00
if srcsubdir and not args . binary :
# (for binary packages we explicitly specify subdir= when fetching to
# match the default value of S, so we don't need to set it in that case)
2014-12-19 11:41:53 +00:00
lines_before . append ( ' S = " $ {WORKDIR} / %s " ' % srcsubdir )
lines_before . append ( ' ' )
if pkgarch :
lines_after . append ( ' PACKAGE_ARCH = " %s " ' % pkgarch )
lines_after . append ( ' ' )
2015-09-22 16:21:39 +00:00
if args . binary :
lines_after . append ( ' INSANE_SKIP_$ {PN} += " already-stripped " ' )
lines_after . append ( ' ' )
2014-12-19 11:41:53 +00:00
# Find all plugins that want to register handlers
2015-12-22 04:03:01 +00:00
logger . debug ( ' Loading recipe handlers ' )
raw_handlers = [ ]
2014-12-19 11:41:53 +00:00
for plugin in plugins :
if hasattr ( plugin , ' register_recipe_handlers ' ) :
2015-12-22 04:03:01 +00:00
plugin . register_recipe_handlers ( raw_handlers )
# Sort handlers by priority
handlers = [ ]
for i , handler in enumerate ( raw_handlers ) :
if isinstance ( handler , tuple ) :
handlers . append ( ( handler [ 0 ] , handler [ 1 ] , i ) )
else :
handlers . append ( ( handler , 0 , i ) )
handlers . sort ( key = lambda item : ( item [ 1 ] , - item [ 2 ] ) , reverse = True )
for handler , priority , _ in handlers :
logger . debug ( ' Handler: %s (priority %d ) ' % ( handler . __class__ . __name__ , priority ) )
handlers = [ item [ 0 ] for item in handlers ]
2014-12-19 11:41:53 +00:00
# Apply the handlers
handled = [ ]
2016-03-09 04:48:52 +00:00
handled . append ( ( ' license ' , licvalues ) )
2015-09-22 16:21:39 +00:00
if args . binary :
classes . append ( ' bin_package ' )
handled . append ( ' buildsystem ' )
2014-12-19 11:41:53 +00:00
for handler in handlers :
2016-01-22 11:59:58 +00:00
handler . process ( srctree_use , classes , lines_before , lines_after , handled , extravalues )
2015-12-22 04:03:02 +00:00
2016-03-09 04:48:54 +00:00
extrafiles = extravalues . pop ( ' extrafiles ' , { } )
2016-05-29 22:20:59 +00:00
extra_pn = extravalues . pop ( ' PN ' , None )
extra_pv = extravalues . pop ( ' PV ' , None )
2016-03-09 04:48:54 +00:00
2016-05-29 22:20:59 +00:00
if extra_pv and not realpv :
realpv = extra_pv
if not validate_pv ( realpv ) :
realpv = None
else :
realpv = realpv . lower ( ) . split ( ) [ 0 ]
if ' _ ' in realpv :
realpv = realpv . replace ( ' _ ' , ' - ' )
if extra_pn and not pn :
pn = extra_pn
if pn . startswith ( ' GNU ' ) :
pn = pn [ 4 : ]
if ' ' in pn :
# Probably a descriptive identifier rather than a proper name
pn = None
else :
pn = pn . lower ( )
if ' _ ' in pn :
pn = pn . replace ( ' _ ' , ' - ' )
2015-12-22 04:03:02 +00:00
if not outfile :
if not pn :
logger . error ( ' Unable to determine short program name from source tree - please specify name with -N/--name or output file name with -o/--outfile ' )
# devtool looks for this specific exit code, so don't change it
sys . exit ( 15 )
else :
if srcuri and srcuri . startswith ( ( ' git:// ' , ' hg:// ' , ' svn:// ' ) ) :
outfile = ' %s _ %s .bb ' % ( pn , srcuri . split ( ' : ' , 1 ) [ 0 ] )
elif realpv :
outfile = ' %s _ %s .bb ' % ( pn , realpv )
else :
outfile = ' %s .bb ' % pn
if outdir :
outfile = os . path . join ( outdir , outfile )
# We need to check this again
if os . path . exists ( outfile ) :
logger . error ( ' Output file %s already exists ' % outfile )
sys . exit ( 1 )
2016-03-09 04:48:54 +00:00
# Move any extra files the plugins created to a directory next to the recipe
2016-03-13 19:59:03 +00:00
if extrafiles :
if outfile == ' - ' :
extraoutdir = pn
else :
extraoutdir = os . path . join ( os . path . dirname ( outfile ) , pn )
bb . utils . mkdirhier ( extraoutdir )
2016-05-18 18:39:44 +00:00
for destfn , extrafile in extrafiles . items ( ) :
2016-03-13 19:59:03 +00:00
shutil . move ( extrafile , os . path . join ( extraoutdir , destfn ) )
2016-03-09 04:48:54 +00:00
2015-12-22 04:03:02 +00:00
lines = lines_before
lines_before = [ ]
skipblank = True
for line in lines :
if skipblank :
skipblank = False
if not line :
continue
if line . startswith ( ' S = ' ) :
if realpv and pv not in ' git svn hg ' . split ( ) :
line = line . replace ( realpv , ' $ {PV} ' )
if pn :
line = line . replace ( pn , ' $ {BPN} ' )
if line == ' S = " $ {WORKDIR} /$ {BPN} -$ {PV} " ' :
skipblank = True
continue
elif line . startswith ( ' SRC_URI = ' ) :
if realpv :
line = line . replace ( realpv , ' $ {PV} ' )
elif line . startswith ( ' PV = ' ) :
if realpv :
line = re . sub ( ' " [^+]* \ + ' , ' " %s + ' % realpv , line )
lines_before . append ( line )
2014-12-19 11:41:53 +00:00
2016-01-06 11:15:52 +00:00
if args . also_native :
lines = lines_after
lines_after = [ ]
bbclassextend = None
for line in lines :
if line . startswith ( ' BBCLASSEXTEND = ' ) :
splitval = line . split ( ' " ' )
if len ( splitval ) > 1 :
bbclassextend = splitval [ 1 ] . split ( )
if not ' native ' in bbclassextend :
bbclassextend . insert ( 0 , ' native ' )
line = ' BBCLASSEXTEND = " %s " ' % ' ' . join ( bbclassextend )
lines_after . append ( line )
if not bbclassextend :
lines_after . append ( ' BBCLASSEXTEND = " native " ' )
2014-12-19 11:41:53 +00:00
outlines = [ ]
outlines . extend ( lines_before )
if classes :
2016-01-18 11:18:33 +00:00
if outlines [ - 1 ] and not outlines [ - 1 ] . startswith ( ' # ' ) :
outlines . append ( ' ' )
2014-12-19 11:41:53 +00:00
outlines . append ( ' inherit %s ' % ' ' . join ( classes ) )
outlines . append ( ' ' )
outlines . extend ( lines_after )
2016-05-29 22:20:59 +00:00
if extravalues :
2016-05-29 22:21:00 +00:00
if ' LICENSE ' in extravalues and not licvalues :
# Don't blow away 'CLOSED' value that comments say we set
del extravalues [ ' LICENSE ' ]
2016-05-29 22:20:59 +00:00
_ , outlines = oe . recipeutils . patch_recipe_lines ( outlines , extravalues , trailing_newline = False )
2015-04-28 11:22:36 +00:00
if args . extract_to :
2015-04-28 11:25:30 +00:00
scriptutils . git_convert_standalone_clone ( srctree )
2015-10-02 13:05:08 +00:00
if os . path . isdir ( args . extract_to ) :
# If the directory exists we'll move the temp dir into it instead of
# its contents - of course, we could try to always move its contents
# but that is a pain if there are symlinks; the simplest solution is
# to just remove it first
os . rmdir ( args . extract_to )
2015-04-28 11:22:36 +00:00
shutil . move ( srctree , args . extract_to )
2015-12-22 04:03:17 +00:00
if tempsrc == srctree :
tempsrc = None
2015-04-28 11:22:36 +00:00
logger . info ( ' Source extracted to %s ' % args . extract_to )
2014-12-19 11:41:53 +00:00
if outfile == ' - ' :
sys . stdout . write ( ' \n ' . join ( outlines ) + ' \n ' )
else :
with open ( outfile , ' w ' ) as f :
f . write ( ' \n ' . join ( outlines ) + ' \n ' )
logger . info ( ' Recipe %s has been created; further editing may be required to make it fully functional ' % outfile )
if tempsrc :
shutil . rmtree ( tempsrc )
return 0
def get_license_md5sums ( d , static_only = False ) :
import bb . utils
md5sums = { }
if not static_only :
# Gather md5sums of license files in common license dir
commonlicdir = d . getVar ( ' COMMON_LICENSE_DIR ' , True )
for fn in os . listdir ( commonlicdir ) :
md5value = bb . utils . md5_file ( os . path . join ( commonlicdir , fn ) )
md5sums [ md5value ] = fn
# The following were extracted from common values in various recipes
# (double checking the license against the license file itself, not just
# the LICENSE value in the recipe)
md5sums [ ' 94d55d512a9ba36caa9b7df079bae19f ' ] = ' GPLv2 '
md5sums [ ' b234ee4d69f5fce4486a80fdaf4a4263 ' ] = ' GPLv2 '
md5sums [ ' 59530bdf33659b29e73d4adb9f9f6552 ' ] = ' GPLv2 '
md5sums [ ' 0636e73ff0215e8d672dc4c32c317bb3 ' ] = ' GPLv2 '
md5sums [ ' eb723b61539feef013de476e68b5c50a ' ] = ' GPLv2 '
md5sums [ ' 751419260aa954499f7abaabaa882bbe ' ] = ' GPLv2 '
md5sums [ ' 393a5ca445f6965873eca0259a17f833 ' ] = ' GPLv2 '
md5sums [ ' 12f884d2ae1ff87c09e5b7ccc2c4ca7e ' ] = ' GPLv2 '
md5sums [ ' 8ca43cbc842c2336e835926c2166c28b ' ] = ' GPLv2 '
md5sums [ ' ebb5c50ab7cab4baeffba14977030c07 ' ] = ' GPLv2 '
md5sums [ ' c93c0550bd3173f4504b2cbd8991e50b ' ] = ' GPLv2 '
md5sums [ ' 9ac2e7cff1ddaf48b6eab6028f23ef88 ' ] = ' GPLv2 '
md5sums [ ' 4325afd396febcb659c36b49533135d4 ' ] = ' GPLv2 '
md5sums [ ' 18810669f13b87348459e611d31ab760 ' ] = ' GPLv2 '
md5sums [ ' d7810fab7487fb0aad327b76f1be7cd7 ' ] = ' GPLv2 ' # the Linux kernel's COPYING file
md5sums [ ' bbb461211a33b134d42ed5ee802b37ff ' ] = ' LGPLv2.1 '
md5sums [ ' 7fbc338309ac38fefcd64b04bb903e34 ' ] = ' LGPLv2.1 '
md5sums [ ' 4fbd65380cdd255951079008b364516c ' ] = ' LGPLv2.1 '
md5sums [ ' 2d5025d4aa3495befef8f17206a5b0a1 ' ] = ' LGPLv2.1 '
md5sums [ ' fbc093901857fcd118f065f900982c24 ' ] = ' LGPLv2.1 '
md5sums [ ' a6f89e2100d9b6cdffcea4f398e37343 ' ] = ' LGPLv2.1 '
md5sums [ ' d8045f3b8f929c1cb29a1e3fd737b499 ' ] = ' LGPLv2.1 '
md5sums [ ' fad9b3332be894bab9bc501572864b29 ' ] = ' LGPLv2.1 '
md5sums [ ' 3bf50002aefd002f49e7bb854063f7e7 ' ] = ' LGPLv2 '
md5sums [ ' 9f604d8a4f8e74f4f5140845a21b6674 ' ] = ' LGPLv2 '
md5sums [ ' 5f30f0716dfdd0d91eb439ebec522ec2 ' ] = ' LGPLv2 '
md5sums [ ' 55ca817ccb7d5b5b66355690e9abc605 ' ] = ' LGPLv2 '
md5sums [ ' 252890d9eee26aab7b432e8b8a616475 ' ] = ' LGPLv2 '
2016-01-18 11:18:33 +00:00
md5sums [ ' 3214f080875748938ba060314b4f727d ' ] = ' LGPLv2 '
2016-01-18 11:18:34 +00:00
md5sums [ ' db979804f025cf55aabec7129cb671ed ' ] = ' LGPLv2 '
2014-12-19 11:41:53 +00:00
md5sums [ ' d32239bcb673463ab874e80d47fae504 ' ] = ' GPLv3 '
md5sums [ ' f27defe1e96c2e1ecd4e0c9be8967949 ' ] = ' GPLv3 '
md5sums [ ' 6a6a8e020838b23406c81b19c1d46df6 ' ] = ' LGPLv3 '
md5sums [ ' 3b83ef96387f14655fc854ddc3c6bd57 ' ] = ' Apache-2.0 '
md5sums [ ' 385c55653886acac3821999a3ccd17b3 ' ] = ' Artistic-1.0 | GPL-2.0 ' # some perl modules
2016-01-18 11:18:34 +00:00
md5sums [ ' 54c7042be62e169199200bc6477f04d1 ' ] = ' BSD-3-Clause '
2014-12-19 11:41:53 +00:00
return md5sums
2016-03-09 04:48:51 +00:00
def crunch_license ( licfile ) :
'''
Remove non - material text from a license file and then check
its md5sum against a known list . This works well for licenses
which contain a copyright statement , but is also a useful way
to handle people ' s insistence upon reformatting the license text
slightly ( with no material difference to the text of the
license ) .
'''
import oe . utils
# Note: these are carefully constructed!
license_title_re = re . compile ( ' ^ \ (?(#+ *)?(The )?. { 1,10} [Ll]icen[sc]e( \ (. { 1,10} \ ))? \ )?:?$ ' )
license_statement_re = re . compile ( ' ^This (project|software) is( free software)? released under the . { 1,10} [Ll]icen[sc]e:?$ ' )
copyright_re = re . compile ( ' ^(#+)? *Copyright .*$ ' )
crunched_md5sums = { }
# The following two were gleaned from the "forever" npm package
crunched_md5sums [ ' 0a97f8e4cbaf889d6fa51f84b89a79f6 ' ] = ' ISC '
crunched_md5sums [ ' eecf6429523cbc9693547cf2db790b5c ' ] = ' MIT '
# https://github.com/vasi/pixz/blob/master/LICENSE
crunched_md5sums [ ' 2f03392b40bbe663597b5bd3cc5ebdb9 ' ] = ' BSD-2-Clause '
# https://github.com/waffle-gl/waffle/blob/master/LICENSE.txt
crunched_md5sums [ ' e72e5dfef0b1a4ca8a3d26a60587db66 ' ] = ' BSD-2-Clause '
# https://github.com/spigwitmer/fakeds1963s/blob/master/LICENSE
crunched_md5sums [ ' 8be76ac6d191671f347ee4916baa637e ' ] = ' GPLv2 '
# https://github.com/datto/dattobd/blob/master/COPYING
# http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/GPLv2.TXT
crunched_md5sums [ ' 1d65c5ad4bf6489f85f4812bf08ae73d ' ] = ' GPLv2 '
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
# http://git.neil.brown.name/?p=mdadm.git;a=blob;f=COPYING;h=d159169d1050894d3ea3b98e1c965c4058208fe1;hb=HEAD
crunched_md5sums [ ' fb530f66a7a89ce920f0e912b5b66d4b ' ] = ' GPLv2 '
# https://github.com/gkos/nrf24/blob/master/COPYING
crunched_md5sums [ ' 7b6aaa4daeafdfa6ed5443fd2684581b ' ] = ' GPLv2 '
# https://github.com/josch09/resetusb/blob/master/COPYING
crunched_md5sums [ ' 8b8ac1d631a4d220342e83bcf1a1fbc3 ' ] = ' GPLv3 '
# https://github.com/FFmpeg/FFmpeg/blob/master/COPYING.LGPLv2.1
crunched_md5sums [ ' 2ea316ed973ae176e502e2297b574bb3 ' ] = ' LGPLv2.1 '
# unixODBC-2.3.4 COPYING
crunched_md5sums [ ' 1daebd9491d1e8426900b4fa5a422814 ' ] = ' LGPLv2.1 '
# https://github.com/FFmpeg/FFmpeg/blob/master/COPYING.LGPLv3
crunched_md5sums [ ' 2ebfb3bb49b9a48a075cc1425e7f4129 ' ] = ' LGPLv3 '
lictext = [ ]
with open ( licfile , ' r ' ) as f :
for line in f :
# Drop opening statements
if copyright_re . match ( line ) :
continue
elif license_title_re . match ( line ) :
continue
elif license_statement_re . match ( line ) :
continue
# Squash spaces, and replace smart quotes, double quotes
# and backticks with single quotes
2016-05-18 18:57:23 +00:00
line = oe . utils . squashspaces ( line . strip ( ) )
2016-03-09 04:48:51 +00:00
line = line . replace ( u " \u2018 " , " ' " ) . replace ( u " \u2019 " , " ' " ) . replace ( u " \u201c " , " ' " ) . replace ( u " \u201d " , " ' " ) . replace ( ' " ' , ' \' ' ) . replace ( ' ` ' , ' \' ' )
if line :
lictext . append ( line )
m = hashlib . md5 ( )
try :
2016-05-18 18:57:23 +00:00
m . update ( ' ' . join ( lictext ) . encode ( ' utf-8 ' ) )
2016-03-09 04:48:51 +00:00
md5val = m . hexdigest ( )
except UnicodeEncodeError :
md5val = None
lictext = ' '
license = crunched_md5sums . get ( md5val , None )
return license , md5val , lictext
2014-12-19 11:41:53 +00:00
def guess_license ( srctree ) :
import bb
md5sums = get_license_md5sums ( tinfoil . config_data )
licenses = [ ]
2016-03-09 04:48:50 +00:00
licspecs = [ ' *LICEN[CS]E* ' , ' COPYING* ' , ' *[Ll]icense* ' , ' LEGAL* ' , ' [Ll]egal* ' , ' *GPL* ' , ' README.lic* ' , ' COPYRIGHT* ' , ' [Cc]opyright* ' ]
2014-12-19 11:41:53 +00:00
licfiles = [ ]
for root , dirs , files in os . walk ( srctree ) :
for fn in files :
for spec in licspecs :
if fnmatch . fnmatch ( fn , spec ) :
2015-03-08 21:41:18 +00:00
fullpath = os . path . join ( root , fn )
if not fullpath in licfiles :
licfiles . append ( fullpath )
2014-12-19 11:41:53 +00:00
for licfile in licfiles :
md5value = bb . utils . md5_file ( licfile )
2016-03-09 04:48:51 +00:00
license = md5sums . get ( md5value , None )
if not license :
license , crunched_md5 , lictext = crunch_license ( licfile )
if not license :
license = ' Unknown '
2014-12-19 11:41:53 +00:00
licenses . append ( ( license , os . path . relpath ( licfile , srctree ) , md5value ) )
# FIXME should we grab at least one source file with a license header and add that too?
return licenses
2016-03-09 04:48:52 +00:00
def split_pkg_licenses ( licvalues , packages , outlines , fallback_licenses = None , pn = ' $ {PN} ' ) :
"""
Given a list of ( license , path , md5sum ) as returned by guess_license ( ) ,
a dict of package name to path mappings , write out a set of
package - specific LICENSE values .
"""
pkglicenses = { pn : [ ] }
for license , licpath , _ in licvalues :
2016-05-18 18:39:44 +00:00
for pkgname , pkgpath in packages . items ( ) :
2016-03-09 04:48:52 +00:00
if licpath . startswith ( pkgpath + ' / ' ) :
if pkgname in pkglicenses :
pkglicenses [ pkgname ] . append ( license )
else :
pkglicenses [ pkgname ] = [ license ]
break
else :
# Accumulate on the main package
pkglicenses [ pn ] . append ( license )
outlicenses = { }
for pkgname in packages :
2016-04-27 13:06:19 +00:00
license = ' ' . join ( list ( set ( pkglicenses . get ( pkgname , [ ' Unknown ' ] ) ) ) ) or ' Unknown '
2016-03-09 04:48:52 +00:00
if license == ' Unknown ' and pkgname in fallback_licenses :
license = fallback_licenses [ pkgname ]
outlines . append ( ' LICENSE_ %s = " %s " ' % ( pkgname , license ) )
outlicenses [ pkgname ] = license . split ( )
return outlicenses
2014-12-19 11:41:53 +00:00
def read_pkgconfig_provides ( d ) :
pkgdatadir = d . getVar ( ' PKGDATA_DIR ' , True )
pkgmap = { }
for fn in glob . glob ( os . path . join ( pkgdatadir , ' shlibs2 ' , ' *.pclist ' ) ) :
with open ( fn , ' r ' ) as f :
for line in f :
pkgmap [ os . path . basename ( line . rstrip ( ) ) ] = os . path . splitext ( os . path . basename ( fn ) ) [ 0 ]
recipemap = { }
2016-05-18 18:39:44 +00:00
for pc , pkg in pkgmap . items ( ) :
2014-12-19 11:41:53 +00:00
pkgdatafile = os . path . join ( pkgdatadir , ' runtime ' , pkg )
if os . path . exists ( pkgdatafile ) :
with open ( pkgdatafile , ' r ' ) as f :
for line in f :
if line . startswith ( ' PN: ' ) :
recipemap [ pc ] = line . split ( ' : ' , 1 ) [ 1 ] . strip ( )
return recipemap
def convert_pkginfo ( pkginfofile ) :
values = { }
with open ( pkginfofile , ' r ' ) as f :
indesc = False
for line in f :
if indesc :
if line . strip ( ) :
values [ ' DESCRIPTION ' ] + = ' ' + line . strip ( )
else :
indesc = False
else :
splitline = line . split ( ' : ' , 1 )
key = line [ 0 ]
value = line [ 1 ]
if key == ' LICENSE ' :
for dep in value . split ( ' , ' ) :
dep = dep . split ( ) [ 0 ]
mapped = depmap . get ( dep , ' ' )
if mapped :
depends . append ( mapped )
elif key == ' License ' :
values [ ' LICENSE ' ] = value
elif key == ' Summary ' :
values [ ' SUMMARY ' ] = value
elif key == ' Description ' :
values [ ' DESCRIPTION ' ] = value
indesc = True
return values
def convert_debian ( debpath ) :
2016-05-29 22:21:00 +00:00
value_map = { ' Package ' : ' PN ' ,
' Version ' : ' PV ' ,
' Section ' : ' SECTION ' ,
' License ' : ' LICENSE ' ,
' Homepage ' : ' HOMEPAGE ' }
2014-12-19 11:41:53 +00:00
# FIXME extend this mapping - perhaps use distro_alias.inc?
depmap = { ' libz-dev ' : ' zlib ' }
values = { }
depends = [ ]
with open ( os . path . join ( debpath , ' control ' ) ) as f :
indesc = False
for line in f :
if indesc :
2016-05-29 22:21:00 +00:00
if line . startswith ( ' ' ) :
2014-12-19 11:41:53 +00:00
if line . startswith ( ' This package contains ' ) :
indesc = False
else :
2016-05-29 22:21:00 +00:00
if ' DESCRIPTION ' in values :
values [ ' DESCRIPTION ' ] + = ' ' + line . strip ( )
else :
values [ ' DESCRIPTION ' ] = line . strip ( )
2014-12-19 11:41:53 +00:00
else :
indesc = False
2016-05-29 22:21:00 +00:00
if not indesc :
2014-12-19 11:41:53 +00:00
splitline = line . split ( ' : ' , 1 )
2016-05-29 22:21:00 +00:00
if len ( splitline ) < 2 :
continue
key = splitline [ 0 ]
value = splitline [ 1 ] . strip ( )
2014-12-19 11:41:53 +00:00
if key == ' Build-Depends ' :
for dep in value . split ( ' , ' ) :
dep = dep . split ( ) [ 0 ]
mapped = depmap . get ( dep , ' ' )
if mapped :
depends . append ( mapped )
elif key == ' Description ' :
values [ ' SUMMARY ' ] = value
indesc = True
2016-05-29 22:21:00 +00:00
else :
varname = value_map . get ( key , None )
if varname :
values [ varname ] = value
2014-12-19 11:41:53 +00:00
2016-05-29 22:21:00 +00:00
#if depends:
# values['DEPENDS'] = ' '.join(depends)
2014-12-19 11:41:53 +00:00
return values
2016-05-29 22:21:00 +00:00
def convert_rpm_xml ( xmlfile ) :
''' Converts the output from rpm -qp --xml to a set of variable values '''
import xml . etree . ElementTree as ElementTree
rpmtag_map = { ' Name ' : ' PN ' ,
' Version ' : ' PV ' ,
' Summary ' : ' SUMMARY ' ,
' Description ' : ' DESCRIPTION ' ,
' License ' : ' LICENSE ' ,
' Url ' : ' HOMEPAGE ' }
values = { }
tree = ElementTree . parse ( xmlfile )
root = tree . getroot ( )
for child in root :
if child . tag == ' rpmTag ' :
name = child . attrib . get ( ' name ' , None )
if name :
varname = rpmtag_map . get ( name , None )
if varname :
values [ varname ] = child [ 0 ] . text
return values
2014-12-19 11:41:53 +00:00
2015-11-22 19:55:45 +00:00
def register_commands ( subparsers ) :
2015-02-05 14:04:00 +00:00
parser_create = subparsers . add_parser ( ' create ' ,
help = ' Create a new recipe ' ,
description = ' Creates a new recipe from a source tree ' )
2014-12-19 11:41:53 +00:00
parser_create . add_argument ( ' source ' , help = ' Path or URL to source ' )
2015-12-22 04:03:02 +00:00
parser_create . add_argument ( ' -o ' , ' --outfile ' , help = ' Specify filename for recipe to create ' )
2014-12-19 11:41:53 +00:00
parser_create . add_argument ( ' -m ' , ' --machine ' , help = ' Make recipe machine-specific as opposed to architecture-specific ' , action = ' store_true ' )
2015-02-05 14:04:00 +00:00
parser_create . add_argument ( ' -x ' , ' --extract-to ' , metavar = ' EXTRACTPATH ' , help = ' Assuming source is a URL, fetch it and extract it to the directory specified as %(metavar)s ' )
2015-12-22 04:03:02 +00:00
parser_create . add_argument ( ' -N ' , ' --name ' , help = ' Name to use within recipe (PN) ' )
2015-04-28 16:07:31 +00:00
parser_create . add_argument ( ' -V ' , ' --version ' , help = ' Version to use within recipe (PV) ' )
2015-09-22 16:21:39 +00:00
parser_create . add_argument ( ' -b ' , ' --binary ' , help = ' Treat the source tree as something that should be installed verbatim (no compilation, same directory structure) ' , action = ' store_true ' )
2016-01-06 11:15:52 +00:00
parser_create . add_argument ( ' --also-native ' , help = ' Also add native variant (i.e. support building recipe for the build host as well as the target machine) ' , action = ' store_true ' )
2016-01-22 11:59:58 +00:00
parser_create . add_argument ( ' --src-subdir ' , help = ' Specify subdirectory within source tree to use ' , metavar = ' SUBDIR ' )
2016-05-29 22:21:02 +00:00
parser_create . add_argument ( ' -a ' , ' --autorev ' , help = ' When fetching from a git repository, set SRCREV in the recipe to a floating revision instead of fixed ' , action = " store_true " )
2014-12-19 11:41:53 +00:00
parser_create . set_defaults ( func = create_recipe )