#!/usr/bin/env python
# coding=utf-8
#
# android-gcc 1.6.0
# http://www.flowdas.com/blog/android-gcc
# Copyright (c) 2009, 오 동권(Dong-gweon Oh) bookman@flowdas.com
#
import sys, os

def cache(fn):
    def cached_fn():
        if not hasattr(fn, 'cache'):
            fn.cache = fn()
        return fn.cache
    return cached_fn

def substitute(command):
    return os.popen(command).read().strip()

@cache
def TARGET_PLATFORM():
    return os.environ.get('TARGET_PLATFORM', 'android-3')

@cache
def SYSROOT():
    for dir in os.environ.get('PATH', '').split(os.pathsep):
        if not dir: continue
        if os.path.exists(os.path.join(dir, target_compiler())):
            toolroot = os.path.abspath(os.path.join(dir, '..'))
            return os.path.abspath(os.path.join(toolroot, '../../../platforms/%s/arch-arm' % TARGET_PLATFORM()))
    sys.exit('Cannot determine SYSROOT')

@cache
def target_libgcc():
    return substitute('arm-eabi-gcc -mthumb-interwork -print-libgcc-file-name')

@cache
def CPPFLAGS():
    return [
        '-I%s/usr/include' % SYSROOT(),
        '-D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID',
        ]

@cache
def CFLAGS_options():
    flags = []
    APP_OPTIM = os.environ.get('APP_OPTIM')
    if APP_OPTIM is None:
        if '-DNDEBUG' in sys.argv[1:]:
            release = True
        else:
            release = False
    elif APP_OPTIM == 'release':
        release = True

    elif APP_OPTIM == 'debug':
        release = False
    else:
        sys.exit('Unknown APP_OPTIM')
    LOCAL_ARM_MODE = os.environ.get('LOCAL_ARM_MODE')
    if LOCAL_ARM_MODE is None:
        thumb = release
    elif LOCAL_ARM_MODE == 'thumb':
        thumb = True
    elif LOCAL_ARM_MODE == 'arm':
        thumb = False
    else:
        sys.exit('Unknown LOCAL_ARM_MODE')
    if release:
        if '-DNDEBUG' not in sys.argv[1:]:
            flags.append('-DNDEBUG')
        flags.append('-fomit-frame-pointer')
        if thumb:
            flags.append('-Os')
        else:
            flags.append('-O2')
    else:
        flags.append('-O0 -fno-omit-frame-pointer')
    if thumb:
        flags.append('-mthumb -fno-strict-aliasing -finline-limit=64')
    else:
        flags.append('-marm -fstrict-aliasing -funswitch-loops -finline-limit=300')
    return flags

@cache
def CFLAGS():
    cflags = [
        CPPFLAGS(),
        '-march=armv5te -mtune=xscale -msoft-float -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -g',
        CFLAGS_options(),
        CXXFLAGS(),
        ]
    return cflags

@cache
def CXXFLAGS():
    if target_compiler() == 'arm-eabi-g++':
        return  '-fno-exceptions -fno-rtti'
    else:
        return []

@cache
def no_undefined():
    if os.environ.get('ALLOW_UNDEFINED') == 'yes':
        return ''
    else:
        return '-Wl,--no-undefined'

@cache
def LDFLAGS():
    return '-nostdlib -Bdynamic -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc  %(SYSROOT)s/usr/lib/libc.so %(SYSROOT)s/usr/lib/libstdc++.so %(SYSROOT)s/usr/lib/libm.so %(SYSROOT)s/usr/lib/crtbegin_dynamic.o -L%(SYSROOT)s/usr/lib' % {'SYSROOT' : SYSROOT()}

@cache
def target_libgcc():
    return substitute('arm-eabi-gcc -mthumb-interwork -print-libgcc-file-name')

@cache
def LDFLAGS_epilog():
    return [
        no_undefined(),
        '-Wl,-rpath-link=%(SYSROOT)s/usr/lib %(libgcc)s %(SYSROOT)s/usr/lib/crtend_android.o' % {'SYSROOT':SYSROOT(), 'libgcc':target_libgcc()},
        ]

@cache
def LDSHFLAGS():
    return '-nostdlib -Wl,-shared,-Bsymbolic -L%(SYSROOT)s/usr/lib' % {'SYSROOT':SYSROOT()}

@cache
def LDSHFLAGS_epilog():
    return [
        '-Wl,--whole-archive -Wl,--no-whole-archive %(SYSROOT)s/usr/lib/libc.so %(SYSROOT)s/usr/lib/libstdc++.so %(SYSROOT)s/usr/lib/libm.so' % {'SYSROOT':SYSROOT()},
        no_undefined(),
        '-Wl,-rpath-link=%(SYSROOT)s/usr/lib %(libgcc)s' % {'SYSROOT':SYSROOT(), 'libgcc':target_libgcc()},
        ]

@cache
def target_compiler():
    return os.path.basename(sys.argv[0]).replace('android-', 'arm-eabi-')

def cmd_build_empty():
    return [
        target_compiler(),
        sys.argv[1:],
        ]

def cmd_build_executable():
    return [
        target_compiler(),
        CFLAGS(),
        LDFLAGS(),
        sys.argv[1:],
        LDFLAGS_epilog(),
        ]

def cmd_build_c():
    return [
        target_compiler(),
        CFLAGS(),
        sys.argv[1:],
        ]

def cmd_build_E():
    return [
        target_compiler(),
        CPPFLAGS(),
        sys.argv[1:],
        ]

def cmd_build_S():
    return cmd_build_c()

def cmd_build_shared():
    argv = sys.argv[1:]
    argv.remove('-shared')
    return [
        target_compiler(),
        CFLAGS(),
        LDSHFLAGS(),
        argv,
        LDSHFLAGS_epilog(),
        ]

def cmd_build():
    mode = None
    for opt in ('-c', '-E', '-S', '-shared'):
        if opt in sys.argv[1:]:
            mode = opt
            break
    if mode is None:
        mode = '-empty'
        skip = False
        for arg in sys.argv[1:]:
            if arg.startswith('-'):
                if arg in ('-o', '-x'):
                    skip = True
            elif skip:
                skip = False
            else:
                mode = '-executable'
                break
    return eval('cmd_build_%s()' % mode[1:]),

def deepjoin(obj):
    if type(obj) == type(''): return obj
    return ' '.join(map(deepjoin, obj))

cmd = deepjoin(cmd_build())
cmd = cmd.replace('"', '"\\"')
os.system(cmd)

