2016-01-26 02:53:53 +00:00
# Development tool - utility commands plugin
#
# Copyright (C) 2015-2016 Intel Corporation
#
# 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.
""" Devtool utility plugins """
import os
import sys
import shutil
import tempfile
import logging
import argparse
import subprocess
from devtool import exec_build_env_command , setup_tinfoil , check_workspace_recipe , DevtoolError
from devtool import parse_recipe
logger = logging . getLogger ( ' devtool ' )
def edit_recipe ( args , config , basepath , workspace ) :
""" Entry point for the devtool ' edit-recipe ' subcommand """
if args . any_recipe :
tinfoil = setup_tinfoil ( config_only = False , basepath = basepath )
try :
rd = parse_recipe ( config , tinfoil , args . recipename , True )
if not rd :
return 1
recipefile = rd . getVar ( ' FILE ' , True )
finally :
tinfoil . shutdown ( )
else :
check_workspace_recipe ( workspace , args . recipename )
recipefile = workspace [ args . recipename ] [ ' recipefile ' ]
if not recipefile :
raise DevtoolError ( " Recipe file for %s is not under the workspace " %
args . recipename )
editor = os . environ . get ( ' EDITOR ' , None )
if not editor :
raise DevtoolError ( " EDITOR environment variable not set " )
import subprocess
try :
subprocess . check_call ( ' %s " %s " ' % ( editor , recipefile ) , shell = True )
except subprocess . CalledProcessError as e :
return e . returncode
return 0
2016-01-26 02:53:54 +00:00
def configure_help ( args , config , basepath , workspace ) :
""" Entry point for the devtool ' configure-help ' subcommand """
import oe . utils
check_workspace_recipe ( workspace , args . recipename )
tinfoil = setup_tinfoil ( config_only = False , basepath = basepath )
try :
rd = parse_recipe ( config , tinfoil , args . recipename , appends = True , filter_workspace = False )
if not rd :
return 1
b = rd . getVar ( ' B ' , True )
s = rd . getVar ( ' S ' , True )
configurescript = os . path . join ( s , ' configure ' )
confdisabled = ' noexec ' in rd . getVarFlags ( ' do_configure ' ) or ' do_configure ' not in ( rd . getVar ( ' __BBTASKS ' , False ) or [ ] )
configureopts = oe . utils . squashspaces ( rd . getVar ( ' CONFIGUREOPTS ' , True ) or ' ' )
extra_oeconf = oe . utils . squashspaces ( rd . getVar ( ' EXTRA_OECONF ' , True ) or ' ' )
extra_oecmake = oe . utils . squashspaces ( rd . getVar ( ' EXTRA_OECMAKE ' , True ) or ' ' )
do_configure = rd . getVar ( ' do_configure ' , True ) or ' '
do_configure_noexpand = rd . getVar ( ' do_configure ' , False ) or ' '
packageconfig = rd . getVarFlags ( ' PACKAGECONFIG ' ) or [ ]
autotools = bb . data . inherits_class ( ' autotools ' , rd ) and ( ' oe_runconf ' in do_configure or ' autotools_do_configure ' in do_configure )
cmake = bb . data . inherits_class ( ' cmake ' , rd ) and ( ' cmake_do_configure ' in do_configure )
cmake_do_configure = rd . getVar ( ' cmake_do_configure ' , True )
pn = rd . getVar ( ' PN ' , True )
finally :
tinfoil . shutdown ( )
if ' doc ' in packageconfig :
del packageconfig [ ' doc ' ]
if autotools and not os . path . exists ( configurescript ) :
logger . info ( ' Running do_configure to generate configure script ' )
try :
stdout , _ = exec_build_env_command ( config . init_path , basepath ,
' bitbake -c configure %s ' % msg , args . recipename ,
stderr = subprocess . STDOUT )
except bb . process . ExecutionError :
pass
if confdisabled or do_configure . strip ( ) in ( ' ' , ' : ' ) :
raise DevtoolError ( " do_configure task has been disabled for this recipe " )
elif args . no_pager and not os . path . exists ( configurescript ) :
raise DevtoolError ( " No configure script found and no other information to display " )
else :
configopttext = ' '
if autotools and configureopts :
configopttext = '''
Arguments currently passed to the configure script :
% s
Some of those are fixed . ''' % (configureopts + ' ' + extra_oeconf)
if extra_oeconf :
configopttext + = ''' The ones that are specified through EXTRA_OECONF (which you can change or add to easily):
% s ''' % e xtra_oeconf
elif cmake :
in_cmake = False
cmake_cmd = ' '
for line in cmake_do_configure . splitlines ( ) :
if in_cmake :
cmake_cmd = cmake_cmd + ' ' + line . strip ( ) . rstrip ( ' \\ ' )
if not line . endswith ( ' \\ ' ) :
break
if line . lstrip ( ) . startswith ( ' cmake ' ) :
cmake_cmd = line . strip ( ) . rstrip ( ' \\ ' )
if line . endswith ( ' \\ ' ) :
in_cmake = True
else :
break
if cmake_cmd :
configopttext = '''
The current cmake command line :
% s
Arguments specified through EXTRA_OECMAKE ( which you can change or add to easily )
% s ''' % (oe.utils.squashspaces(cmake_cmd), extra_oecmake)
else :
configopttext = '''
The current implementation of cmake_do_configure :
cmake_do_configure ( ) {
% s
}
Arguments specified through EXTRA_OECMAKE ( which you can change or add to easily )
% s ''' % (cmake_do_configure.rstrip(), extra_oecmake)
elif do_configure :
configopttext = '''
The current implementation of do_configure :
do_configure ( ) {
% s
} ''' % d o_configure.rstrip()
if ' $ {EXTRA_OECONF} ' in do_configure_noexpand :
configopttext + = '''
Arguments specified through EXTRA_OECONF ( which you can change or add to easily ) :
% s ''' % e xtra_oeconf
if packageconfig :
configopttext + = '''
Some of these options may be controlled through PACKAGECONFIG ; for more details please see the recipe . '''
if args . arg :
helpargs = ' ' . join ( args . arg )
elif cmake :
helpargs = ' -LH '
else :
helpargs = ' --help '
msg = ''' configure information for %s
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
% s ''' % (pn, configopttext)
if cmake :
msg + = '''
The cmake % s output for % s follows . After " -- Cache values " you should see a list of variables you can add to EXTRA_OECMAKE ( prefixed with - D and suffixed with = followed by the desired value , without any spaces ) .
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ''' % (helpargs, pn)
elif os . path . exists ( configurescript ) :
msg + = '''
The . / configure % s output for % s follows .
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ''' % (helpargs, pn)
olddir = os . getcwd ( )
tmppath = tempfile . mkdtemp ( )
with tempfile . NamedTemporaryFile ( ' w ' , delete = False ) as tf :
if not args . no_header :
tf . write ( msg + ' \n ' )
tf . close ( )
try :
try :
cmd = ' cat %s ' % tf . name
if cmake :
cmd + = ' ; cmake %s %s 2>&1 ' % ( helpargs , s )
os . chdir ( b )
elif os . path . exists ( configurescript ) :
cmd + = ' ; %s %s ' % ( configurescript , helpargs )
if sys . stdout . isatty ( ) and not args . no_pager :
pager = os . environ . get ( ' PAGER ' , ' less ' )
cmd = ' ( %s ) | %s ' % ( cmd , pager )
subprocess . check_call ( cmd , shell = True )
except subprocess . CalledProcessError as e :
return e . returncode
finally :
os . chdir ( olddir )
shutil . rmtree ( tmppath )
os . remove ( tf . name )
2016-01-26 02:53:53 +00:00
def register_commands ( subparsers , context ) :
""" Register devtool subcommands from this plugin """
parser_edit_recipe = subparsers . add_parser ( ' edit-recipe ' , help = ' Edit a recipe file in your workspace ' ,
description = ' Runs the default editor (as specified by the EDITOR variable) on the specified recipe. Note that the recipe file itself must be in the workspace (i.e. as a result of " devtool add " or " devtool upgrade " ); you can override this with the -a/--any-recipe option. ' )
parser_edit_recipe . add_argument ( ' recipename ' , help = ' Recipe to edit ' )
parser_edit_recipe . add_argument ( ' --any-recipe ' , ' -a ' , action = " store_true " , help = ' Edit any recipe, not just where the recipe file itself is in the workspace ' )
parser_edit_recipe . set_defaults ( func = edit_recipe )
2016-01-26 02:53:54 +00:00
# NOTE: Needed to override the usage string here since the default
# gets the order wrong - recipename must come before --arg
parser_configure_help = subparsers . add_parser ( ' configure-help ' , help = ' Get help on configure script options ' ,
usage = ' devtool configure-help [options] recipename [--arg ...] ' ,
description = ' Displays the help for the configure script for the specified recipe (i.e. runs ./configure --help) prefaced by a header describing the current options being specified. Output is piped through less (or whatever PAGER is set to, if set) for easy browsing. ' )
parser_configure_help . add_argument ( ' recipename ' , help = ' Recipe to show configure help for ' )
parser_configure_help . add_argument ( ' -p ' , ' --no-pager ' , help = ' Disable paged output ' , action = " store_true " )
parser_configure_help . add_argument ( ' -n ' , ' --no-header ' , help = ' Disable explanatory header text ' , action = " store_true " )
parser_configure_help . add_argument ( ' --arg ' , help = ' Pass remaining arguments to the configure script instead of --help (useful if the script has additional help options) ' , nargs = argparse . REMAINDER )
parser_configure_help . set_defaults ( func = configure_help )