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")
# 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
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):
if self.types.has_key(name):
FFIConstants.notify.warning('Redefining type named: ' + name)
FFIConstants.notify.info('Redefining type named: ' + name)
self.types[name] = typeDescriptor
def getTypeNamed(self, name):

View File

@ -5,7 +5,7 @@
import string
import os
import compileall
import glob
import FFIEnvironment
import FFITypes
@ -15,8 +15,8 @@ import FFIConstants
import FFIOverload
from direct.showbase.PythonUtil import *
# FFIConstants.notify.setDebug(1)
FFIConstants.notify.info('Importing interrogate library: ' + FFIConstants.InterrogateModuleName)
# 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
exec('from ' + FFIConstants.InterrogateModuleName + ' import *')
@ -220,7 +220,14 @@ def getTypeName(typeIndex, scoped=0):
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.environment = FFIEnvironment.FFIEnvironment()
@ -230,7 +237,7 @@ class FFIInterrogateDatabase:
def constructDescriptor(self, typeIndex):
if interrogate_type_is_atomic(typeIndex):
return self.constructPrimitiveTypeDescriptor(typeIndex)
elif interrogate_type_is_enum(typeIndex):
return self.constructEnumTypeDescriptor(typeIndex)
@ -377,7 +384,6 @@ class FFIInterrogateDatabase:
descriptor.foreignTypeName = typeName
if (typeName == "TypedObject"):
print "Found typed object descriptor"
FFITypes.TypedObjectDescriptor = descriptor
descriptor.isNested = interrogate_type_is_nested(typeIndex)
@ -586,9 +592,11 @@ class FFIInterrogateDatabase:
funcSpec.index = funcIndex
return funcSpec
def addTypes(self):
def addTypes(self, CModuleName):
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):
for descriptor in self.typeIndexMap.values():
@ -599,6 +607,11 @@ class FFIInterrogateDatabase:
moduleName = 'lib' + interrogate_function_module_name(funcIndex)
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):
# We really do not need the descriptor for the value, just
@ -724,18 +737,57 @@ class FFIInterrogateDatabase:
file = open(init, 'w')
file.close()
# Commented out based upon assumption that squeeze will do the compile
#FFIConstants.notify.info( 'Compiling code...')
#compileall.compile_dir(codeDir)
def squeezeGeneratedCode(self, outputDir):
# 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):
# Reset the environment so we are clean from any old modules
self.environment.reset()
FFIConstants.notify.info('='*50)
FFIConstants.notify.info('Importing code library: ' + CModuleName)
FFIConstants.notify.warning('Importing code library: ' + 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)
FFIConstants.notify.info( 'Generating type code...')
@ -803,7 +855,7 @@ class FFIInterrogateDatabase:
def updateBindings(self, CModuleName):
FFIConstants.notify.info( 'Updating Bindings')
FFIConstants.notify.info( 'Adding Types...')
self.addTypes()
self.addTypes(CModuleName)
FFIConstants.notify.info( 'Adding global values...')
self.addGlobalValues(CModuleName)
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'))