# -*- coding: utf-8 -*-
#
#  This file is part of Bakefile (http://www.bakefile.org)
#
#  Copyright (C) 2005 Włodzimierz Skiba
#
#  Permission is hereby granted, free of charge, to any person obtaining a copy
#  of this software and associated documentation files (the "Software"), to
#  deal in the Software without restriction, including without limitation the
#  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
#  sell copies of the Software, and to permit persons to whom the Software is
#  furnished to do so, subject to the following conditions:
#
#  The above copyright notice and this permission notice shall be included in
#  all copies or substantial portions of the Software.
#
#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
#  IN THE SOFTWARE.
#
#  $Id: symbian.py 1157 2008-01-08 12:03:02Z vaclavslavik $
#
#  Symbian development files generator script
#

import fnmatch, re, os.path
import errno, errors, utils
from utils import *

# ------------------------------------------------------------------------
# SYMBIAN MMP FORMAT IN BAKEFILE FORMAT EXPLANATION
# ------------------------------------------------------------------------
#
# SUPPORTED #################
#
# exportunfrozen
#  SYMBIAN DOCS: create library file without requiring frozen exports
#  IN BAKEFILE added automatically for outputing dll projects
#
# library
#  SYMBIAN DOCS: import libraries
#  USE: <sys-lib>libname</sys-lib>
#
# macro
#  SYMBIAN DOCS: #defines for the preprocessing of source code
#  USE: <define>macro</define>
#
# option
#  SYMBIAN DOCS: specify additional compiler options
#  USE: <optimize>
#
# resource
#  SYMBIAN DOCS: resource file for application projects
#  USE: <symbian-res>filename.rss</symbian-res>
#
# source
#  SYMBIAN DOCS: source files
#  USE: <sources>filename.cpp</sources>
#
# sourcepath
#  SYMBIAN DOCS: location of the project and its workfiles
#  IN BAKEFILE taken from <sources> and <symbian-res> automatically
#
# target
#  SYMBIAN DOCS: file generated by the project
#  USE: <exename> for <exe>, <libname> for <lib>, <dllname> for <dll>
#
# targetpath
#  SYMBIAN DOCS: where the project should be released
#  USE: "install-to"
#
# targettype
#  SYMBIAN DOCS: kind of project
#  automatically taken form <exe>, <lib>, <dll>
#
# userinclude
#  SYMBIAN DOCS: project's header files directories
#  USE: <include>
#
# uid
#  SYMBIAN DOCS: UIDs for a project
#  USE: <uid type="symbian2">...</uid> for UID2 and "symbian3" for UID3
#
#
#
# NOT (YET?) SUPPORTED ######
#
# aif
#  SYMBIAN DOCS: application information file
#
# asspabi
#  SYMBIAN DOCS: build the project for the same ABI as the kernel for a particular ASSP
#
# assplibrary
#  SYMBIAN DOCS: a kernel library is being linked to
#
# asspexports
#  SYMBIAN DOCS: export different functions for different ASSPs
#
# baseaddress
#  SYMBIAN DOCS: address to which a DLL will be built and, if possible, loaded
#
# debuglibrary
#  SYMBIAN DOCS: libraries that are only required in debug builds
#
# deffile
#  SYMBIAN DOCS: override the default linker definition file
#
# document
#  SYMBIAN DOCS: document (non-code) files
#
# epocheapsize
#  SYMBIAN DOCS: minimum and maximum heap sizes for your executable
#
# epocprocesspriority
#  SYMBIAN DOCS: process priority for your .exe executable
#
# epocstacksize
#  SYMBIAN DOCS: stack size for your executable
#
# lang
#  SYMBIAN DOCS: languages code for the project
#
# linkas
#  SYMBIAN DOCS: give a DLL a different internal name than its filename
#
# nostrictdef
#  SYMBIAN DOCS: do not apply a u suffix to frozen .def files
#
# srcdbg
#  SYMBIAN DOCS: disables the use of optimisation in debug builds
#
# start bitmap
#  SYMBIAN DOCS: bitmaps to build into an .mbm file
#
# start...end
#  SYMBIAN DOCS: platform-specific section
#
# staticlibrary
#  SYMBIAN DOCS: static libraries
#
# strictdepend
#  SYMBIAN DOCS: project's dependencies may differ with the variant,
#
# systeminclude
#  SYMBIAN DOCS: system header files directories
#
# systemresource
#  SYMBIAN DOCS: resource file for system projects
#
# win32_library
#  SYMBIAN DOCS: Win32 system libraries to link to in a WINS/WINSCW build
#

# ------------------------------------------------------------------------
#                              Generator class
# ------------------------------------------------------------------------

class SymbianGenerator:

    def __init__(self):
        self.basename = os.path.splitext(os.path.basename(FILE))[0]
        self.dirname = os.path.dirname(FILE)

    def MMP_NAME(self, project):
        project_name = project._targetname
        if project._debug_or_release != 'default':
            project_name = project._debug_or_release + '_' + project_name
        return '%s' % (project_name)

    def getPath(self, src):
        source_path = os.path.dirname( src )
        if source_path == '':
            source_path = '.'
        if os.path.isabs( source_path ) != True:
            source_path = '..\\' + source_path
        return '%s' % (source_path)

    def genMMP(self, project, name):
        project_name = os.path.join(self.dirname, name)
        project_name = os.path.join(project_name, name + '.mmp' )
        content = ''
        #################################
        # TARGET settings
        #################################
        content += 'TARGET        %s.%s\n' % (project._targetname,project._targetextension)
        content += 'TARGETTYPE    %s\n'     % project._targettype
        if project._installto != '':
            content += 'TARGETPATH    %s\n' % nativePaths(project._installto)
        if project._uid2 != '':
            content += 'UID           %s' % project._uid2
            if project._uid3 != '':
                content += ' %s' % project._uid3
            content += '\n'
        else:
            if project._targettype == 'exe':
                content += 'UID           0\n'
        #################################
        # BUILD settings
        #################################
        if project._CW_options != '':
            content += 'OPTIONS       CW %s\n' % project._CW_options
        if project._GCC_options != '':
            content += 'OPTIONS       GCC %s\n' % project._GCC_options
        if project._MSVC_options != '':
            content += 'OPTIONS       MSVC %s\n' % project._MSVC_options
        for m in project._defines.split():
            content += 'MACRO         '
            if m.find('=') == -1:
                content += '%s' % m
            else:
                import config
                if not config.quiet:
                    sys.stderr.write("Warning: MACRO definitions in symbian format are always = 1 (%s).\n" % m)
                content += '%s' % m.split("=")[0]
            content += '\n'
        for i in project._include_paths.split():
            include_path = i
            if os.path.isabs( include_path ) != True:
                include_path = '..\\' + include_path
            content += 'USERINCLUDE   %s\n' % nativePaths(include_path)
        last_path = ''
        first_path = True
        for s in project._sources.split():
            source_path = self.getPath( s )
            if first_path == True or last_path != source_path:
                first_path = False
                last_path = source_path
                content += 'SOURCEPATH    %s\n' % nativePaths(last_path)
            if os.path.splitext( s )[1] == ".rss":
                content += 'RESOURCE      '
            else:
                content += 'SOURCE        '
            content += '%s\n' % os.path.basename( s )
        for l in project._libraries.split():
            content += 'LIBRARY       %s\n' % l
        if project._targettype == 'dll':
            content += 'EXPORTUNFROZEN\n'

        #################################
        # LINK settings
        #################################
        writer.writeFile(project_name, content )

    def genSingleExtension(self,
                           dir_name,
                           extension_filename,
                           if_keyword,
                           else_keyword,
                           endif_keyword,
                           condition,
                           command_if,
                           command_else):
        makefile_content = ''
        if condition != '':
            makefile_content += if_keyword + ' ' + condition + '\n'
        makefile_content += command_if + '\n\n'
        if condition != '':
            makefile_content += else_keyword + '\n'
            makefile_content += command_else + '\n\n'
            makefile_content += endif_keyword + '\n'
        writer.writeFile('%s' % (
        os.path.join(dir_name, extension_filename)
        ), makefile_content)
        return extension_filename

    def genExtension(self,
                     dir_name,
                     extension_name,
                     what_compare,
                     expected_value,
                     command_if,
                     command_else):
        mmp_addition = ''
        with_condition = False
        if what_compare != '' or expected_value != '' or command_else != '':
            with_condition = True

        # GNUMAKE - use this variant because GNU make is at least in symbian own bin path
        mmp_addition += self.genSingleExtension(
                                dir_name,
                                extension_name + '.gnumake',
                                'ifeq',
                                'else',
                                'endif',
                                '(' + what_compare + ',' + expected_value + ')',
                                command_if,
                                command_else) + '\n'

        # MAKE - replace GNUMAKE if required
        # mmp_addition += self.genSingleExtension(
        #                         dir_name,
        #                         extension_name + '.make',
        #                         '!IF',
        #                         '!ELSE',
        #                         '!ENDIF',
        #                         '"' + what_compare + '" == "' + expected_value + '"',
        #                         command_if,
        #                         command_else) + '\n'
        #
        # NMAKE - replace GNUMAKE if required
        # mmp_addition += self.genSingleExtension(
        #                         dir_name,
        #                         extension_name + '.nmake',
        #                         '!IF',
        #                         '!ELSE',
        #                         '!ENDIF',
        #                         '"' + what_compare + '" == "' + expected_value + '"',
        #                         command_if,
        #                         command_else) + '\n'

        return mmp_addition

    def genINF(self, projects, build):
        selected_projects = [p for p in projects if p._debug_or_release == build]
        # generate bld.inf files
        all_projects = ''
        all_extensions_targets = 'MAKMAKE FINAL FREEZE LIB CLEANLIB RESOURCE RELEASABLES CLEAN BLD SAVESPACE :\n\t'
        for s in selected_projects:
            project_name = s._targetname
            dir_name = os.path.join(self.dirname, project_name)
            writer.Mkdir(dir_name)
            self.genMMP(s, project_name )
            project = 'PRJ_MMPFILES\n'
            if build != "default":
                project += self.genExtension(dir_name,
                                             "build_check",
                                             "$(CFG)",build,
                                             all_extensions_targets + "REM do nothing - correct build",
                                             "all :\n\tWrong UDEB/UREL switch")
            project += project_name + '.mmp\n'
            writer.writeFile('%s.inf' % (
            os.path.join(dir_name, self.basename)
            ), project)

    def genSymbianFiles(self):
        # do different targets in different subdirectories
        projects = [t for t in targets if t._kind == 'project']
        self.genINF(projects,"default")
        self.genINF(projects,"UDEB")
        self.genINF(projects,"UREL")


def run():
    generator = SymbianGenerator()
    generator.genSymbianFiles()
