Merge pull request #488 from AnnaKogan8:updated-ABI-compliance-descriptor-script
This commit is contained in:
		@@ -1,130 +1,228 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from shutil import rmtree
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
ANDROID_SDK_PATH = "/opt/android-sdk-linux"
 | 
			
		||||
ANDROID_NDK_PATH = None
 | 
			
		||||
INSTALL_DIRECTORY = None
 | 
			
		||||
CLASS_PATH = None
 | 
			
		||||
TMP_HEADER_PATH="tmp_include"
 | 
			
		||||
HEADER_EXTS = set(['h', 'hpp'])
 | 
			
		||||
SYS_INCLUDES = ["platforms/android-8/arch-arm/usr/include", "sources/cxx-stl/gnu-libstdc++/include", "sources/cxx-stl/gnu-libstdc++/libs/armeabi/include"]
 | 
			
		||||
 | 
			
		||||
PROJECT_NAME = "OpenCV-branch"
 | 
			
		||||
TARGET_LIBS = ["libopencv_java.so"]
 | 
			
		||||
ARCH = "armeabi"
 | 
			
		||||
GCC_OPTIONS = "-fpermissive"
 | 
			
		||||
EXCLUDE_HEADERS = set(["hdf5.h", "eigen.hpp", "cxeigen.hpp"]);
 | 
			
		||||
architecture = 'armeabi'
 | 
			
		||||
excludedHeaders = set(['hdf5.h', 'cap_ios.h', 
 | 
			
		||||
    'eigen.hpp', 'cxeigen.hpp' #TOREMOVE
 | 
			
		||||
    ])
 | 
			
		||||
systemIncludes = ['sources/cxx-stl/gnu-libstdc++/4.6/include', \
 | 
			
		||||
    '/opt/android-ndk-r8c/platforms/android-8/arch-arm', # TODO: check if this one could be passed as command line arg
 | 
			
		||||
    'sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include']
 | 
			
		||||
targetLibs = ['libopencv_java.so']
 | 
			
		||||
preamble = ['Eigen/Core']
 | 
			
		||||
# TODO: get gcc_options automatically
 | 
			
		||||
gcc_options = ['-fexceptions', '-frtti', '-Wno-psabi', '--sysroot=/opt/android-ndk-r8c/platforms/android-8/arch-arm', '-fpic', '-D__ARM_ARCH_5__', '-D__ARM_ARCH_5T__', '-D__ARM_ARCH_5E__', '-D__ARM_ARCH_5TE__', '-fsigned-char', '-march=armv5te', '-mtune=xscale', '-msoft-float', '-fdata-sections', '-ffunction-sections', '-Wa,--noexecstack   ', '-W', '-Wall', '-Werror=return-type', '-Werror=address', '-Werror=sequence-point', '-Wformat', '-Werror=format-security', '-Wmissing-declarations', '-Wundef', '-Winit-self', '-Wpointer-arith', '-Wshadow', '-Wsign-promo', '-Wno-narrowing', '-fdiagnostics-show-option', '-fomit-frame-pointer', '-mthumb', '-fomit-frame-pointer', '-O3', '-DNDEBUG ', '-DNDEBUG']
 | 
			
		||||
excludedOptionsPrefix = '-W'
 | 
			
		||||
 | 
			
		||||
def FindClasses(root, prefix):
 | 
			
		||||
    classes = []
 | 
			
		||||
    if ("" != prefix):
 | 
			
		||||
    prefix = prefix + "."
 | 
			
		||||
    for path in os.listdir(root):
 | 
			
		||||
    currentPath = os.path.join(root, path)
 | 
			
		||||
    if (os.path.isdir(currentPath)):
 | 
			
		||||
        classes += FindClasses(currentPath, prefix + path)
 | 
			
		||||
    else:
 | 
			
		||||
        name = str.split(path, ".")[0]
 | 
			
		||||
        ext = str.split(path, ".")[1]
 | 
			
		||||
        if (ext == "class"):
 | 
			
		||||
        #print("class: %s" % (prefix + name))
 | 
			
		||||
        classes.append(prefix+name)
 | 
			
		||||
    return classes
 | 
			
		||||
 | 
			
		||||
def FindHeaders(root):
 | 
			
		||||
 | 
			
		||||
def GetHeaderFiles(root):
 | 
			
		||||
    headers = []
 | 
			
		||||
    for path in os.listdir(root):
 | 
			
		||||
    currentPath = os.path.join(root, path)
 | 
			
		||||
    if (os.path.isdir(currentPath)):
 | 
			
		||||
        headers += FindHeaders(currentPath)
 | 
			
		||||
    else:
 | 
			
		||||
        ext = str.split(path, ".")[-1]
 | 
			
		||||
        #print("%s: \"%s\"" % (currentPath, ext))
 | 
			
		||||
        if (ext in HEADER_EXTS):
 | 
			
		||||
        #print("Added as header file")
 | 
			
		||||
        if (path not in EXCLUDE_HEADERS):
 | 
			
		||||
            headers.append(currentPath)
 | 
			
		||||
        if not os.path.isdir(os.path.join(root, path)) \
 | 
			
		||||
            and os.path.splitext(path)[1] in ['.h', '.hpp'] \
 | 
			
		||||
            and not path in excludedHeaders:
 | 
			
		||||
            headers.append(os.path.join(root, path))
 | 
			
		||||
    return sorted(headers)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def GetClasses(root, prefix):
 | 
			
		||||
    classes = []
 | 
			
		||||
    if ('' != prefix):
 | 
			
		||||
        prefix = prefix + '.'
 | 
			
		||||
    for path in os.listdir(root):
 | 
			
		||||
        currentPath = os.path.join(root, path)
 | 
			
		||||
        if (os.path.isdir(currentPath)):
 | 
			
		||||
            classes += GetClasses(currentPath, prefix + path)
 | 
			
		||||
        else:
 | 
			
		||||
            name = str.split(path, '.')[0]
 | 
			
		||||
            ext = str.split(path, '.')[1]
 | 
			
		||||
            if (ext == 'class'):
 | 
			
		||||
                classes.append(prefix + name)
 | 
			
		||||
    return classes
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def GetJavaHHeaders():
 | 
			
		||||
    print('\nGenerating JNI headers for Java API ...')
 | 
			
		||||
 | 
			
		||||
    javahHeaders = os.path.join(managerDir, 'javah_generated_headers')
 | 
			
		||||
    if os.path.exists(javahHeaders):
 | 
			
		||||
        rmtree(javahHeaders)
 | 
			
		||||
    os.makedirs(os.path.join(os.getcwd(), javahHeaders))
 | 
			
		||||
 | 
			
		||||
    AndroidJavaDeps = os.path.join(SDK_path, 'platforms/android-11/android.jar')
 | 
			
		||||
 | 
			
		||||
    classPath = os.path.join(managerDir, 'sdk/java/bin/classes')
 | 
			
		||||
    if not os.path.exists(classPath):
 | 
			
		||||
        print('Error: no Java classes found in \'%s\'' % classPath)
 | 
			
		||||
        quit()
 | 
			
		||||
 | 
			
		||||
    allJavaClasses = GetClasses(classPath, '')
 | 
			
		||||
    if not allJavaClasses:
 | 
			
		||||
        print('Error: no Java classes found')
 | 
			
		||||
        quit()
 | 
			
		||||
 | 
			
		||||
    for currentClass in allJavaClasses:
 | 
			
		||||
        os.system('javah -d %s -classpath %s:%s %s' % (javahHeaders, classPath, \
 | 
			
		||||
            AndroidJavaDeps, currentClass))
 | 
			
		||||
 | 
			
		||||
    print('\nBuilding JNI headers list ...')
 | 
			
		||||
    jniHeaders = GetHeaderFiles(javahHeaders)
 | 
			
		||||
 | 
			
		||||
    return jniHeaders
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def GetImmediateSubdirs(dir):
 | 
			
		||||
    return [name for name in os.listdir(dir)
 | 
			
		||||
            if os.path.isdir(os.path.join(dir, name))]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def GetOpenCVModules():
 | 
			
		||||
    makefile = open(os.path.join(managerDir, 'sdk/native/jni/OpenCV.mk'), 'r')
 | 
			
		||||
    makefileStr = makefile.read()
 | 
			
		||||
    left = makefileStr.find('OPENCV_MODULES:=') + len('OPENCV_MODULES:=')
 | 
			
		||||
    right = makefileStr[left:].find('\n')
 | 
			
		||||
    modules = makefileStr[left:left+right].split()
 | 
			
		||||
    modules = filter(lambda x: x != 'ts' and x != 'androidcamera', modules)
 | 
			
		||||
    return modules
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def FindHeaders():
 | 
			
		||||
    headers = []
 | 
			
		||||
 | 
			
		||||
    print('\nBuilding Native OpenCV header list ...')
 | 
			
		||||
 | 
			
		||||
    cppHeadersFolder = os.path.join(managerDir, 'sdk/native/jni/include/opencv2')
 | 
			
		||||
 | 
			
		||||
    modulesFolders = GetImmediateSubdirs(cppHeadersFolder)
 | 
			
		||||
    modules = GetOpenCVModules()
 | 
			
		||||
 | 
			
		||||
    cppHeaders = []
 | 
			
		||||
    for m in modules:
 | 
			
		||||
        for f in modulesFolders:
 | 
			
		||||
            moduleHeaders = []
 | 
			
		||||
            if f == m:
 | 
			
		||||
                moduleHeaders += GetHeaderFiles(os.path.join(cppHeadersFolder, f))
 | 
			
		||||
                if m == 'flann':
 | 
			
		||||
                    flann = os.path.join(cppHeadersFolder, f, 'flann.hpp') 
 | 
			
		||||
                    moduleHeaders.remove(flann)
 | 
			
		||||
                    moduleHeaders.insert(0, flann)
 | 
			
		||||
                cppHeaders += moduleHeaders
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    cppHeaders += GetHeaderFiles(cppHeadersFolder)
 | 
			
		||||
    headers += cppHeaders
 | 
			
		||||
 | 
			
		||||
    cHeaders = GetHeaderFiles(os.path.join(managerDir, \
 | 
			
		||||
        'sdk/native/jni/include/opencv'))
 | 
			
		||||
    headers += cHeaders
 | 
			
		||||
 | 
			
		||||
    headers += GetJavaHHeaders()
 | 
			
		||||
 | 
			
		||||
    return headers
 | 
			
		||||
 | 
			
		||||
if (len(sys.argv) < 3):
 | 
			
		||||
    print("Error: Invalid command line arguments")
 | 
			
		||||
    exit(-1)
 | 
			
		||||
 | 
			
		||||
INSTALL_DIRECTORY = sys.argv[1]
 | 
			
		||||
PROJECT_NAME = sys.argv[2]
 | 
			
		||||
 | 
			
		||||
CLASS_PATH = os.path.join(INSTALL_DIRECTORY, "sdk/java/bin/classes")
 | 
			
		||||
if (not os.path.exists(CLASS_PATH)):
 | 
			
		||||
    print("Error: no java classes found in \"%s\"" % CLASS_PATH)
 | 
			
		||||
    exit(-2)
 | 
			
		||||
def FindLibraries():
 | 
			
		||||
    libraries = []
 | 
			
		||||
    for lib in targetLibs:
 | 
			
		||||
        libraries.append(os.path.join(managerDir, 'sdk/native/libs', architecture, lib))
 | 
			
		||||
    return libraries
 | 
			
		||||
 | 
			
		||||
if (os.environ.has_key("NDK_ROOT")):
 | 
			
		||||
    ANDROID_NDK_PATH = os.environ["NDK_ROOT"];
 | 
			
		||||
    print("Using Android NDK from NDK_ROOT (\"%s\")" % ANDROID_NDK_PATH)
 | 
			
		||||
 | 
			
		||||
if (not ANDROID_NDK_PATH):
 | 
			
		||||
    pipe = os.popen("which ndk-build")
 | 
			
		||||
    tmp = str.strip(pipe.readline(), "\n")
 | 
			
		||||
    while(not tmp):
 | 
			
		||||
    tmp = str.strip(pipe.readline(), "\n")
 | 
			
		||||
    pipe.close()
 | 
			
		||||
    ANDROID_NDK_PATH = os.path.split(tmp)[0]
 | 
			
		||||
    print("Using Android NDK from PATH (\"%s\")" % ANDROID_NDK_PATH)
 | 
			
		||||
 | 
			
		||||
print("Using Android SDK from \"%s\"" % ANDROID_SDK_PATH)
 | 
			
		||||
def FindIncludes():
 | 
			
		||||
    includes = [os.path.join(managerDir, 'sdk', 'native', 'jni', 'include'),
 | 
			
		||||
        os.path.join(managerDir, 'sdk', 'native', 'jni', 'include', 'opencv'),
 | 
			
		||||
        os.path.join(managerDir, 'sdk', 'native', 'jni', 'include', 'opencv2')]
 | 
			
		||||
 | 
			
		||||
outputFileName = PROJECT_NAME + ".xml"
 | 
			
		||||
try:
 | 
			
		||||
    outputFile = open(outputFileName, "w")
 | 
			
		||||
except:
 | 
			
		||||
    print("Error: Cannot open output file \"%s\" for writing" % outputFileName)
 | 
			
		||||
    for inc in systemIncludes:
 | 
			
		||||
        includes.append(os.path.join(NDK_path, inc))
 | 
			
		||||
 | 
			
		||||
allJavaClasses = FindClasses(CLASS_PATH, "")
 | 
			
		||||
if (not allJavaClasses):
 | 
			
		||||
    print("Error: No Java classes found :(")
 | 
			
		||||
    exit(-1)
 | 
			
		||||
    return includes
 | 
			
		||||
 | 
			
		||||
if (not os.path.exists(TMP_HEADER_PATH)):
 | 
			
		||||
    os.makedirs(os.path.join(os.getcwd(), TMP_HEADER_PATH))
 | 
			
		||||
 | 
			
		||||
print("Generating JNI headers for Java API ...")
 | 
			
		||||
AndroidJavaDeps = os.path.join(ANDROID_SDK_PATH, "platforms/android-11/android.jar")
 | 
			
		||||
for currentClass in allJavaClasses:
 | 
			
		||||
    os.system("javah -d %s -classpath %s:%s %s" % (TMP_HEADER_PATH, CLASS_PATH, AndroidJavaDeps, currentClass))
 | 
			
		||||
 | 
			
		||||
print("Building JNI headers list ...")
 | 
			
		||||
jniHeaders = FindHeaders(TMP_HEADER_PATH)
 | 
			
		||||
#print(jniHeaders)
 | 
			
		||||
def FilterGCCOptions():
 | 
			
		||||
    gcc = filter(lambda x: not x.startswith(excludedOptionsPrefix), gcc_options)
 | 
			
		||||
    return sorted(gcc)
 | 
			
		||||
 | 
			
		||||
print("Building Native OpenCV header list ...")
 | 
			
		||||
cHeaders = FindHeaders(os.path.join(INSTALL_DIRECTORY, "sdk/native/jni/include/opencv"))
 | 
			
		||||
cppHeaders = FindHeaders(os.path.join(INSTALL_DIRECTORY, "sdk/native/jni/include/opencv2"))
 | 
			
		||||
#print(cHeaders)
 | 
			
		||||
#print(cppHeaders)
 | 
			
		||||
 | 
			
		||||
print("Writing config file ...")
 | 
			
		||||
outputFile.write("<descriptor>\n\n<version>\n\t%s\n</version>\n\n<headers>\n" % PROJECT_NAME)
 | 
			
		||||
outputFile.write("\t"   + "\n\t".join(cHeaders))
 | 
			
		||||
outputFile.write("\n\t" + "\n\t".join(cppHeaders))
 | 
			
		||||
outputFile.write("\n\t" + "\n\t".join(jniHeaders))
 | 
			
		||||
outputFile.write("\n</headers>\n\n")
 | 
			
		||||
 | 
			
		||||
includes = [os.path.join(INSTALL_DIRECTORY, "sdk", "native", "jni", "include"),
 | 
			
		||||
    os.path.join(INSTALL_DIRECTORY, "sdk", "native", "jni", "include", "opencv"),
 | 
			
		||||
    os.path.join(INSTALL_DIRECTORY, "sdk", "native", "jni", "include", "opencv2")]
 | 
			
		||||
def WriteXml(version, headers, includes, libraries):
 | 
			
		||||
    xmlName = version + '.xml'
 | 
			
		||||
 | 
			
		||||
for inc in SYS_INCLUDES:
 | 
			
		||||
    includes.append(os.path.join(ANDROID_NDK_PATH, inc))
 | 
			
		||||
    print '\noutput file: ' + xmlName
 | 
			
		||||
    try:
 | 
			
		||||
        xml = open(xmlName, 'w')
 | 
			
		||||
    except:
 | 
			
		||||
        print 'Error: Cannot open output file "%s" for writing' % xmlName
 | 
			
		||||
        quit()
 | 
			
		||||
 | 
			
		||||
outputFile.write("<include_paths>\n\t%s\n</include_paths>\n\n" % "\n\t".join(includes))
 | 
			
		||||
    xml.write('<descriptor>')
 | 
			
		||||
 | 
			
		||||
libraries = []
 | 
			
		||||
for lib in TARGET_LIBS:
 | 
			
		||||
    libraries.append(os.path.join(INSTALL_DIRECTORY, "sdk/native/libs", ARCH, lib))
 | 
			
		||||
    xml.write('\n\n<version>')
 | 
			
		||||
    xml.write('\n\t%s' % version)
 | 
			
		||||
    xml.write('\n</version>')
 | 
			
		||||
 | 
			
		||||
outputFile.write("<libs>\n\t%s\n</libs>\n\n" % "\n\t".join(libraries))
 | 
			
		||||
outputFile.write("<gcc_options>\n\t%s\n</gcc_options>\n\n</descriptor>" % GCC_OPTIONS)
 | 
			
		||||
    xml.write('\n\n<headers>')
 | 
			
		||||
    xml.write('\n\t%s' % '\n\t'.join(headers))
 | 
			
		||||
    xml.write('\n</headers>')
 | 
			
		||||
 | 
			
		||||
print("done!")
 | 
			
		||||
    xml.write('\n\n<include_paths>')
 | 
			
		||||
    xml.write('\n\t%s' % '\n\t'.join(includes))
 | 
			
		||||
    xml.write('\n</include_paths>')
 | 
			
		||||
 | 
			
		||||
    # TODO: uncomment when Eigen problem is solved
 | 
			
		||||
    # xml.write('\n\n<include_preamble>')
 | 
			
		||||
    # xml.write('\n\t%s' % '\n\t'.join(preamble))
 | 
			
		||||
    # xml.write('\n</include_preamble>')
 | 
			
		||||
 | 
			
		||||
    xml.write('\n\n<libs>')
 | 
			
		||||
    xml.write('\n\t%s' % '\n\t'.join(libraries))
 | 
			
		||||
    xml.write('\n</libs>')
 | 
			
		||||
 | 
			
		||||
    xml.write('\n\n<gcc_options>')
 | 
			
		||||
    xml.write('\n\t%s' % '\n\t'.join(gcc_options))
 | 
			
		||||
    xml.write('\n</gcc_options>')
 | 
			
		||||
 | 
			
		||||
    xml.write('\n\n</descriptor>')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    usage = '%prog <OpenCV_Manager install directory> <OpenCV_Manager version>'
 | 
			
		||||
    parser = OptionParser(usage = usage)
 | 
			
		||||
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
    if 2 != len(args):
 | 
			
		||||
        parser.print_help()
 | 
			
		||||
        quit()
 | 
			
		||||
 | 
			
		||||
    managerDir = args[1][0]
 | 
			
		||||
    version = args[1][1]
 | 
			
		||||
 | 
			
		||||
    NDK_path = '/opt/android-ndk-r8c'
 | 
			
		||||
    print '\nUsing Android NDK from "%s"' % NDK_path
 | 
			
		||||
 | 
			
		||||
    SDK_path = '~/NVPACK/android-sdk-linux'
 | 
			
		||||
    print '\nUsing Android SDK from "%s"' % SDK_path
 | 
			
		||||
 | 
			
		||||
    headers = FindHeaders()
 | 
			
		||||
 | 
			
		||||
    includes = FindIncludes()
 | 
			
		||||
 | 
			
		||||
    libraries = FindLibraries()
 | 
			
		||||
 | 
			
		||||
    gcc_options = FilterGCCOptions()
 | 
			
		||||
 | 
			
		||||
    WriteXml(version, headers, includes, libraries)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user