new genPyCode

This commit is contained in:
David Rose 2004-06-03 17:43:44 +00:00
parent 94ac41108d
commit f144196ffe
7 changed files with 218 additions and 296 deletions

View File

@ -4,7 +4,7 @@ from direct.directnotify.DirectNotifyGlobal import *
notify = directNotify.newCategory("FFI") notify = directNotify.newCategory("FFI")
# This is the name of the file that the importing code will be stored # This is the name of the file that the importing code will be stored
importModuleName = 'PandaModulesUnsqueezed' importModuleName = 'PandaModules'
# A header for all the generated files # A header for all the generated files
generatedHeader = '# This file is automatically generated. It would be unwise to edit.\n\n' generatedHeader = '# This file is automatically generated. It would be unwise to edit.\n\n'

View File

@ -13,7 +13,7 @@ class FFIEnvironment:
def addType(self, typeDescriptor, name): def addType(self, typeDescriptor, name):
if self.types.has_key(name): if self.types.has_key(name):
FFIConstants.notify.warning('Redefining type named: ' + name) FFIConstants.notify.info('Redefining type named: ' + name)
self.types[name] = typeDescriptor self.types[name] = typeDescriptor
def getTypeNamed(self, name): def getTypeNamed(self, name):

View File

@ -5,7 +5,7 @@
import string import string
import os import os
import compileall import glob
import FFIEnvironment import FFIEnvironment
import FFITypes import FFITypes
@ -15,8 +15,8 @@ import FFIConstants
import FFIOverload import FFIOverload
from direct.showbase.PythonUtil import * from direct.showbase.PythonUtil import *
# FFIConstants.notify.setDebug(1)
FFIConstants.notify.info('Importing interrogate library: ' + FFIConstants.InterrogateModuleName) FFIConstants.notify.info('Importing interrogate library: ' + FFIConstants.InterrogateModuleName)
# Note: we do a from lib import * here because we do not want # Note: we do a from lib import * here because we do not want
# to be dependent on the name of the interrogate library in this code # to be dependent on the name of the interrogate library in this code
exec('from ' + FFIConstants.InterrogateModuleName + ' import *') exec('from ' + FFIConstants.InterrogateModuleName + ' import *')
@ -220,7 +220,14 @@ def getTypeName(typeIndex, scoped=0):
class FFIInterrogateDatabase: class FFIInterrogateDatabase:
def __init__(self): def __init__(self, etcPath = []):
# Temporary try..except for old Panda.
try:
for dir in etcPath:
interrogate_add_search_directory(dir)
except:
pass
self.typeIndexMap = {} self.typeIndexMap = {}
self.environment = FFIEnvironment.FFIEnvironment() self.environment = FFIEnvironment.FFIEnvironment()
@ -377,7 +384,6 @@ class FFIInterrogateDatabase:
descriptor.foreignTypeName = typeName descriptor.foreignTypeName = typeName
if (typeName == "TypedObject"): if (typeName == "TypedObject"):
print "Found typed object descriptor"
FFITypes.TypedObjectDescriptor = descriptor FFITypes.TypedObjectDescriptor = descriptor
descriptor.isNested = interrogate_type_is_nested(typeIndex) descriptor.isNested = interrogate_type_is_nested(typeIndex)
@ -586,9 +592,11 @@ class FFIInterrogateDatabase:
funcSpec.index = funcIndex funcSpec.index = funcIndex
return funcSpec return funcSpec
def addTypes(self): def addTypes(self, CModuleName):
for i in range(interrogate_number_of_global_types()): for i in range(interrogate_number_of_global_types()):
self.constructDescriptor(interrogate_get_global_type(i)) typeIndex = interrogate_get_global_type(i)
if self.typeInCModule(typeIndex, CModuleName):
self.constructDescriptor(typeIndex)
def addEnvironmentTypes(self): def addEnvironmentTypes(self):
for descriptor in self.typeIndexMap.values(): for descriptor in self.typeIndexMap.values():
@ -599,6 +607,11 @@ class FFIInterrogateDatabase:
moduleName = 'lib' + interrogate_function_module_name(funcIndex) moduleName = 'lib' + interrogate_function_module_name(funcIndex)
return (moduleName == CModuleName) return (moduleName == CModuleName)
def typeInCModule(self, typeIndex, CModuleName):
if interrogate_type_has_module_name(typeIndex):
moduleName = 'lib' + interrogate_type_module_name(typeIndex)
return (moduleName == CModuleName)
def constructGlobal(self, globalIndex, CModuleName): def constructGlobal(self, globalIndex, CModuleName):
# We really do not need the descriptor for the value, just # We really do not need the descriptor for the value, just
@ -724,18 +737,57 @@ class FFIInterrogateDatabase:
file = open(init, 'w') file = open(init, 'w')
file.close() file.close()
# Commented out based upon assumption that squeeze will do the compile def squeezeGeneratedCode(self, outputDir):
#FFIConstants.notify.info( 'Compiling code...')
#compileall.compile_dir(codeDir) # Since we will be squeezing the importModuleName file, rename
# the original to something we can import from within the
# squeezed version.
squeezedName = FFIConstants.importModuleName
unsqueezedName = FFIConstants.importModuleName + 'Unsqueezed'
os.rename(os.path.join(outputDir, squeezedName + '.py'),
os.path.join(outputDir, unsqueezedName + '.py'))
# Get the list of files to squeeze. This is all of the .py
# files in the output directory except for the __init__.py
# file.
files = glob.glob(os.path.join(outputDir, '*.py'))
init = os.path.join(outputDir, '__init__.py')
try:
files.remove(init)
except:
pass
print "Squeezing %s files." % (len(files))
from direct.showbase import pandaSqueezeTool
pandaSqueezeTool.squeeze(squeezedName, unsqueezedName,
files, outputDir)
# Remove the now-squeezed source files.
for file in files:
os.remove(file)
def generateCodeLib(self, codeDir, extensionsDir, CModuleName): def generateCodeLib(self, codeDir, extensionsDir, CModuleName):
# Reset the environment so we are clean from any old modules # Reset the environment so we are clean from any old modules
self.environment.reset() self.environment.reset()
FFIConstants.notify.info('='*50) FFIConstants.notify.info('='*50)
FFIConstants.notify.info('Importing code library: ' + CModuleName) FFIConstants.notify.warning('Importing code library: ' + CModuleName)
exec('import ' + CModuleName) exec('import ' + CModuleName)
# Temporary try..except for old Panda.
try:
errorFlag = interrogate_error_flag()
except:
errorFlag = False
if errorFlag:
FFIConstants.notify.error("Error reading interrogate database; can't continue.")
self.updateBindings(CModuleName) self.updateBindings(CModuleName)
FFIConstants.notify.info( 'Generating type code...') FFIConstants.notify.info( 'Generating type code...')
@ -803,7 +855,7 @@ class FFIInterrogateDatabase:
def updateBindings(self, CModuleName): def updateBindings(self, CModuleName):
FFIConstants.notify.info( 'Updating Bindings') FFIConstants.notify.info( 'Updating Bindings')
FFIConstants.notify.info( 'Adding Types...') FFIConstants.notify.info( 'Adding Types...')
self.addTypes() self.addTypes(CModuleName)
FFIConstants.notify.info( 'Adding global values...') FFIConstants.notify.info( 'Adding global values...')
self.addGlobalValues(CModuleName) self.addGlobalValues(CModuleName)
FFIConstants.notify.info( 'Adding global functions...') FFIConstants.notify.info( 'Adding global functions...')

View File

@ -1 +1,11 @@
#define INSTALL_SCRIPTS generatePythonCode genPyCode #define INSTALL_SCRIPTS genPyCode.py
// If we're on Win32 without Cygwin, install the genPyCode.bat file;
// for all other platforms, install the genPyCode sh script.
#if $[eq $[PLATFORM],Win32]
#define INSTALL_SCRIPTS $[INSTALL_SCRIPTS] genPyCode.bat
#else
#define INSTALL_SCRIPTS $[INSTALL_SCRIPTS] genPyCode
#endif
#include $[THISDIRPREFIX]genPyCode.pp

View File

@ -1,124 +0,0 @@
#! /bin/bash
# This is just a helper script to generatePythonCode to cover
# the three or four cases we use all the time
# usage: genPyCode [opts] [linux|win-debug|win-release|win-publish|install|release] [other libs]
# -g adds libgateway
# -t adds libtoontown
# -p adds libpirates
# -v adds libvrpn
# -e adds libpandaegg
# -n doesn't perform a squeeze
base_dir=$(pwd)
extra_genPyCode_libs=""
squeezeFlag=""
optimizeFlag=""
ppython=ppython
ppythonOptimizeFlag=""
while getopts ogtpven flag; do
case $flag in
o) extra_genPyCode_libs="$extra_genPyCode_libs libotp" ;;
g) extra_genPyCode_libs="$extra_genPyCode_libs libgateway" ;;
t) extra_genPyCode_libs="$extra_genPyCode_libs libtoontown" ;;
p) extra_genPyCode_libs="$extra_genPyCode_libs libpirates" ;;
v) extra_genPyCode_libs="$extra_genPyCode_libs libvrpn" ;;
e) extra_genPyCode_libs="$extra_genPyCode_libs libpandaegg" ;;
n) doSqueeze="-n" ;;
esac
done
shift `expr $OPTIND - 1`
buildType="$1"
shift
extra_genPyCode_libs="$extra_genPyCode_libs $*"
if [ "$INSTALL_DIR" != "" ]; then
install_dir="$INSTALL_DIR"
elif [ "$PANDA_INSTALL" != "" ]; then
install_dir="$PANDA_INSTALL"
elif [ "$DIRECT" != "" ]; then
install_dir="$DIRECT"
else
install_dir=./install
fi
if [ "$DIRECT" == "" ]; then
if [ "$PLAYER" != "" -a -d "$PLAYER/direct" ]; then
DIRECT="$PLAYER/direct"
elif [ -d direct ]; then
DIRECT=direct
else
echo "Define PLAYER to point to the panda & direct source root."
exit 1
fi
fi
pyDir=$DIRECT/lib/pandac
extDir=$DIRECT/src/extensions
pSqueezer=$DIRECT/src/showbase/pandaSqueezer.py
if [ "$buildType" = "linux" ]; then
cd $DIRECT/bin
ppython -d generatePythonCode -v -d $pyDir $doSqueeze -e $extDir -i libdtoolconfig libpandaexpress libpanda libpandaphysics libdirect $extra_genPyCode_libs || exit
pSqueezer=$DIRECT/src/showbase/pandaSqueezer.py
elif [ "$buildType" = "win-debug" ]; then
cd $DIRECT/bin
pyDir="$(cygpath -w $pyDir)"
extDir="$(cygpath -w $extDir)"
pSqueezer="$(cygpath -w $pSqueezer)"
ppython -d generatePythonCode -v -d $pyDir $doSqueeze -e $extDir -i libdtoolconfig libpandaexpress libpanda libpandaphysics libdirect $extra_genPyCode_libs || exit
elif [ "$buildType" = "win-release" ]; then
cd $DIRECT/bin
pyDir="$(cygpath -w $pyDir)"
extDir="$(cygpath -w $extDir)"
pSqueezer="$(cygpath -w $pSqueezer)"
ppython generatePythonCode -v -d $pyDir $doSqueeze -e $extDir -i libdtoolconfig libpandaexpress libpanda libpandaphysics libdirect $extra_genPyCode_libs || exit
elif [ "$buildType" = "win-publish" ]; then
# no assertions, no comments, no docstrings
cd $DIRECT/bin
pyDir="$(cygpath -w $pyDir)"
extDir="$(cygpath -w $extDir)"
pSqueezer="$(cygpath -w $pSqueezer)"
ppython -OO generatePythonCode -O -v -d $pyDir $doSqueeze -e $extDir -i libdtoolconfig libpandaexpress libpanda libpandaphysics libdirect $extra_genPyCode_libs || exit
optimizeFlag="-O"
ppythonOptimizeFlag="-OO"
elif [ "$buildType" = "install" ]; then
# Use relative paths; as installed on a machine without ctattach etc.
pyDir=$install_dir/lib/pandac
ppython=$install_dir/bin/ppython
pSqueezer=$DIRECT/src/showbase/pandaSqueezer.py
$ppython -d $install_dir/bin/generatePythonCode -O -v -d $pyDir $doSqueeze -e $DIRECT/src/extensions -i libdtoolconfig libpandaexpress libpanda libpandaphysics libdirect $extra_genPyCode_libs || exit
elif [ "$buildType" = "release" ]; then
# Use relative paths; as installed on a machine without ctattach etc.
pyDir=$install_dir/lib/pandac
ppython=$install_dir/bin/ppython
pSqueezer=$DIRECT/src/showbase/pandaSqueezer.py
$ppython $install_dir/bin/generatePythonCode -v -d $pyDir $doSqueeze -e $DIRECT/src/extensions -i libdtoolconfig libpandaexpress libpanda libpandaphysics libdirect $extra_genPyCode_libs || exit
else
echo "Invalid parameter: $buildType"
exit 1
fi
# The squeeze step is now performed as part of generatePythonCode.
#if [ "$fSqueeze" = "squeezeMe" ]; then
# echo SQUEEZING PandaModules
# rm -f $pyDir/PandaModules.py* $pyDir/__init__.py || exit
# $ppython $ppythonOptimizeFlag $pSqueezer $optimizeFlag -d $pyDir || exit
# touch $pyDir/__init__.py || exit
#else
# # renaming PandaModulesUnsqueezed.py to PandaModules.py
# cd $pyDir || exit
# rm -f PandaModules.py* || exit
# echo # junk line needed to keep mv from failing
# mv PandaModulesUnsqueezed.py PandaModules.py || exit
#fi
echo DONE

141
direct/src/ffi/genPyCode.pp Normal file
View File

@ -0,0 +1,141 @@
//
// genPyCode.pp
//
// This file defines the script to auto-generate a sensible genPyCode
// for the user based on the Config.pp variables in effect at the time
// ppremake is run. The generated script will know which directories
// to generate its output to, as well as which source files to read
// for the input.
//
#define hash #
#define install_dir $[$[upcase $[PACKAGE]]_INSTALL]
#define install_lib_dir $[or $[INSTALL_LIB_DIR],$[install_dir]/lib]
#define install_bin_dir $[or $[INSTALL_BIN_DIR],$[install_dir]/bin]
#define install_igatedb_dir $[or $[INSTALL_IGATEDB_DIR],$[install_dir]/etc]
// If we're on Win32 without Cygwin, generate a genPyCode.bat file;
// for all other platforms, generate a genPyCode sh script. Although
// it's true that on non-Win32 platforms we don't need the script
// (since the python file itself could be made directly executable),
// we generate the script anyway to be consistent with Win32, which
// does require it.
#if $[eq $[PLATFORM],Win32]
#output genPyCode.bat
@echo off
python $[osfilename $[install_bin_dir]/genPyCode.py]
#end genPyCode.bat
#else // Win32
#output genPyCode
$[hash]! /bin/sh
python $[install_bin_dir]/genPyCode.py
#end genPyCode
#endif // Win32
#output genPyCode.py
$[hash]! /usr/bin/env python
import os
import sys
import glob
#if $[CTPROJS]
# This script was generated while the user was using the ctattach
# tools. That had better still be the case.
ctprojs = os.getenv('CTPROJS')
if not ctprojs:
print "You are no longer attached to any trees!"
sys.exit(1)
directDir = os.getenv('DIRECT')
if not directDir:
print "You are not attached to DIRECT!"
sys.exit(1)
# Make sure that direct/src/showbase/sitecustomize.py gets loaded.
parent, base = os.path.split(directDir)
if parent not in sys.path:
sys.path.append(parent)
import direct.showbase.sitecustomize
#endif
from direct.ffi import DoGenPyCode
from direct.ffi import FFIConstants
# The following parameters were baked in to this script at the time
# ppremake was run in Direct.
DoGenPyCode.outputDir = '$[osfilename $[install_lib_dir]/pandac]'
DoGenPyCode.extensionsDir = '$[osfilename $[TOPDIR]/src/extensions]'
DoGenPyCode.interrogateLib = 'libdtoolconfig'
DoGenPyCode.codeLibs = '$[GENPYCODE_LIBS]'.split()
DoGenPyCode.etcPath = ['$[osfilename $[install_igatedb_dir]]']
#if $[>= $[OPTIMIZE], 4]
FFIConstants.wantComments = 0
FFIConstants.wantTypeChecking = 0
#endif
#if $[CTPROJS]
# Actually, the user is expected to be using ctattach, so never mind
# on the baked-in stuff--replace it with the dynamic settings from
# ctattach.
DoGenPyCode.outputDir = os.path.join(directDir, 'lib', 'pandac')
DoGenPyCode.extensionsDir = os.path.join(directDir, 'src', 'extensions')
DoGenPyCode.etcPath = []
# Look for additional packages (other than the basic three)
# that the user might be dynamically attached to.
packages = []
for proj in ctprojs.split():
projName = proj.split(':')[0]
packages.append(projName)
packages.reverse()
for package in packages:
packageDir = os.getenv(package)
if packageDir:
etcDir = os.path.join(packageDir, 'etc')
try:
inFiles = glob.glob(os.path.join(etcDir, '*.in'))
except:
inFiles = []
if inFiles:
DoGenPyCode.etcPath.append(etcDir)
if package not in ['DTOOL', 'DIRECT', 'PANDA']:
libDir = os.path.join(packageDir, 'lib')
try:
files = os.listdir(libDir)
except:
files = []
for file in files:
if os.path.isfile(os.path.join(libDir, file)):
basename, ext = os.path.splitext(file)
# Try to import the library. If we can import it,
# instrument it.
try:
__import__(basename, globals(), locals())
isModule = True
except:
isModule = False
if isModule:
if basename not in DoGenPyCode.codeLibs:
DoGenPyCode.codeLibs.append(basename)
#endif
DoGenPyCode.run()
#end genPyCode.py

View File

@ -1,157 +0,0 @@
#!/usr/local/bin/python
import getopt
import sys
import os
import glob
from direct.ffi import FFIConstants
# Define a help string for the user
helpString ="""
generatePythonCode [opts] -i libtool libcode1 libcode2 ...
Generates Python code for the C++ libraries listed.
Example:
Linux:
ppython -d generatePythonCode -v -d $DIRECT/lib/py -e $DIRECT/src/extensions -i libdtoolconfig libpandaexpress libpanda libpandaphysics libdirect libtoontown
Windows debug:
ppython -d generatePythonCode -v -d `cygpath -w $DIRECT/lib/py` -e `cygpath -w $DIRECT/src/extensions` -i libdtoolconfig libpandaexpress libpanda libpandaphysics libdirect libtoontown
Windows release:
ppython generatePythonCode -v -d `cygpath -w $DIRECT/lib/py` -e `cygpath -w $DIRECT/src/extensions` -i libdtoolconfig libpandaexpress libpanda libpandaphysics libdirect libtoontown
Windows publish (no assertions, no comments, no docstrings):
ppython -OO generatePythonCode -O -v -d `cygpath -w $DIRECT/lib/py` -e `cygpath -w $DIRECT/src/extensions` -i libdtoolconfig libpandaexpress libpanda libpandaphysics libdirect libtoontown
Options:
-h print this message
-v verbose
-d dir directory to write output code
-e dir directory to pull extension code from
-i lib interrogate library
-O no C++ comments or assertion statements
-n Don't use squeezeTool to squeeze the result into one .pyz file
"""
# Initialize variables
outputDir = ''
extensionsDir = ''
interrogateLib = ''
codeLibs = []
doSqueeze = True
# Extract the args the user passed in
try:
opts, pargs = getopt.getopt(sys.argv[1:], 'hvOd:e:i:n')
except Exception, e:
# User passed in a bad option, print the error and the help, then exit
print e
print helpString
sys.exit()
if len(opts)==0:
print helpString
sys.exit()
# Store the option values into our variables
for opt in opts:
flag, value = opt
if (flag == '-h'):
print helpString
sys.exit()
elif (flag == '-v'):
FFIConstants.notify.setInfo(1)
elif (flag == '-d'):
outputDir = value
elif (flag == '-e'):
extensionsDir = value
elif (flag == '-i'):
interrogateLib = value
elif (flag == '-O'):
FFIConstants.wantComments = 0
FFIConstants.wantTypeChecking = 0
elif (flag == '-n'):
doSqueeze = False
else:
FFIConstants.notify.error('illegal option: ' + flag)
# Store the program arguments into the codeLibs
codeLibs = pargs
# Now do some error checking and verbose output
if (not interrogateLib):
FFIConstants.notify.error('You must specify an interrogate library (-i lib)')
else:
FFIConstants.notify.info('Setting interrogate library to: ' + interrogateLib)
FFIConstants.InterrogateModuleName = interrogateLib
if (not outputDir):
FFIConstants.notify.info('Setting output directory to current directory')
outputDir = '.'
elif (not os.path.exists(outputDir)):
FFIConstants.notify.info('Directory does not exist, creating: ' + outputDir)
os.mkdir(outputDir)
FFIConstants.notify.info('Setting output directory to: ' + outputDir)
else:
FFIConstants.notify.info('Setting output directory to: ' + outputDir)
if (not extensionsDir):
FFIConstants.notify.info('Setting extensions directory to current directory')
extensionsDir = '.'
elif (not os.path.exists(extensionsDir)):
FFIConstants.notify.error('Directory does not exists: ' + extensionsDir)
else:
FFIConstants.notify.info('Setting extensions directory to: ' + extensionsDir)
if (not codeLibs):
FFIConstants.notify.error('You must specify one or more libraries to generate code from')
else:
FFIConstants.notify.info('Generating code for: ' + `codeLibs`)
FFIConstants.CodeModuleNameList = codeLibs
# Ok, now we can start generating code
from direct.ffi import FFIInterrogateDatabase
db = FFIInterrogateDatabase.FFIInterrogateDatabase()
db.generateCode(outputDir, extensionsDir)
# Remove any leftover junk files in outputDir from a previous run.
print "outputDir = %s, doSqueeze = %s" % (outputDir, doSqueeze)
for file in glob.glob(os.path.join(outputDir, 'PandaModules.py*')):
print "removing junk %s" % (file)
os.remove(file)
if doSqueeze:
# Invoke the squeezer.
files = glob.glob(os.path.join(outputDir, '*.py'))
init = os.path.join(outputDir, '__init__.py')
try:
files.remove(init)
except:
pass
print "Squeezing %s files." % (len(files))
from direct.showbase import pandaSqueezeTool
pandaSqueezeTool.squeeze("PandaModules", "PandaModulesUnsqueezed",
files, outputDir)
# Remove the squeezed source files.
for file in files:
os.remove(file)
else:
print "Not squeezing."
os.rename(os.path.join(outputDir, 'PandaModulesUnsqueezed.py'),
os.path.join(outputDir, 'PandaModules.py'))