예제 #1
0
bool HIDDEN FindModuleByAddress(size_t addr, Module *module)
{
	if (!module)
		return false;

	Section *section = GetSectionByAddress(addr);
	if (section == NULL)
		return false;

	if (section->filename[0] != '/')	// should point to a real file
		return false;

	// Start over with the name to find module start
	return FindModuleByName(section->filename + 1, module);
}
HRESULT CThingTreeCtrl::HandleOnModuleChanged(BSTR bstrName, long lHint, VARIANT varHintData)
{
	TV_INSERTSTRUCT tvInsert;
	TV_ITEM			tvItem;
	CString			strModuleName;
	HTREEITEM		hItem;

	strModuleName = bstrName;

	// the module has changed, find out which one
	if (lHint == moCreate)
	{
		// create a new module
		tvItem.mask = TVIF_PARAM | TVIF_TEXT;
		tvItem.pszText = LPTSTR(LPCTSTR(strModuleName));
		tvItem.lParam = -2;

		tvInsert.hParent = m_hModules;
		tvInsert.hInsertAfter = TVI_LAST;
		tvInsert.item = tvItem;

		hItem = m_treeCtrl.InsertItem(&tvInsert);

		// check to see if the module node is expanded
		// if not, expand it
		m_treeCtrl.Expand(m_hModules, TVE_EXPAND);
		m_treeCtrl.SortChildren(m_hModules);

		// select the module (as per bug #5044)
		m_treeCtrl.SelectItem(hItem);
	}
	if (lHint == moRemove)
	{
		// remove an existing module
		// find the module in the tree
		hItem = FindModuleByName(strModuleName);
		if (hItem)
			m_treeCtrl.DeleteItem(hItem);
	}
	
	return S_OK;
}
CORE::CString
GenerateContentForAndroidMakefile( const TModuleInfoEntryPairVector& mergeLinks ,
                                   const TModuleInfo& moduleInfo                ,
                                   const CORE::CString& moduleRoot              ,
                                   bool addGeneratorCompileTimeToOutput         ,
                                   TStringSet& ndkModulesUsed                   )
{GUCEF_TRACE;

    CORE::CString contentPrefix = makefileHeader;

    if ( addGeneratorCompileTimeToOutput )
    {
        contentPrefix +=
          "#"
          "# The project generator version used was compiled on " __TIME__ __DATE__ "\n"
          "#\n\n";
    }

    contentPrefix +=
      "ifndef MY_MODULE_PATH\n"
      "  MY_MODULE_PATH := $(call my-dir)\n"
      "endif\n"
      "LOCAL_PATH := $(MY_MODULE_PATH)\n\n"
      "include $(CLEAR_VARS)\n\n"
      "@echo Module path: $(MY_MODULE_PATH)\n"
      "LOCAL_MODULE := " + moduleInfo.name + "\n";

    if ( ( MODULETYPE_SHARED_LIBRARY == moduleInfo.moduleType ) ||
         ( MODULETYPE_STATIC_LIBRARY == moduleInfo.moduleType )  )
    {
        contentPrefix += "LOCAL_MODULE_FILENAME := lib" + moduleInfo.name + "\n";
    }
    contentPrefix += "@echo Module name: $(LOCAL_MODULE)\n\n";

    // Generate the source files section
    CORE::CString srcFilesSection = "LOCAL_SRC_FILES := \\\n";
    bool firstLoop = true;
    TStringVectorMap::const_iterator i = moduleInfo.sourceDirs.begin();
    while ( i != moduleInfo.sourceDirs.end() )
    {
        const CORE::CString& srcDir = (*i).first;
        const TStringVector& srcFiles = (*i).second;

        TStringVector::const_iterator n = srcFiles.begin();
        while ( n != srcFiles.end() )
        {
            if ( !firstLoop )
            {
                srcFilesSection += " \\\n";
            }
            firstLoop = false;

            CORE::CString relFilePath = srcDir;
            CORE::AppendToPath( relFilePath, (*n) );

            srcFilesSection += "  " + relFilePath.ReplaceChar( '\\', '/' );

            ++n;
        }
        ++i;
    }

    // Add some spacing for readability
    srcFilesSection += "\n\n";

    // Generate the included files section
    // for android make files we only need the path
    // it will locate the header file on its own
    CORE::CString includeFilesSection = "LOCAL_C_INCLUDES := \\\n";
    i = moduleInfo.includeDirs.begin();
    firstLoop = true;
    while ( i != moduleInfo.includeDirs.end() )
    {
        if ( !firstLoop )
        {
            includeFilesSection += " \\\n";
        }
        firstLoop = false;

        const CORE::CString& dir = (*i).first;
        if ( !dir.IsNULLOrEmpty() )
        {
            includeFilesSection += "  $(MY_MODULE_PATH)/" + dir.ReplaceChar( '\\', '/' );
        }
        else
        {
            // Support the use-case where the include dir is empty because the moduleinfo dir == include dir
            includeFilesSection += "  $(MY_MODULE_PATH)";
        }

        ++i;
    }

    // We also need to add the include paths required to find headers
    // refered to because of dependencies
    TStringSet::const_iterator n = moduleInfo.dependencyIncludeDirs.begin();
    while ( n != moduleInfo.dependencyIncludeDirs.end() )
    {
        if ( !firstLoop )
        {
            includeFilesSection += " \\\n";
        }
        firstLoop = false;

        includeFilesSection += "  $(MY_MODULE_PATH)/" + (*n).ReplaceChar( '\\', '/' );

        ++n;
    }

    // Add some spacing for readability
    includeFilesSection += "\n\n";

    // Now we add the preprocessor definitions
    CORE::CString preprocessorSection;
    if ( !moduleInfo.preprocessorSettings.defines.empty() )
    {
        preprocessorSection = "LOCAL_CFLAGS :=";

        TStringSet::const_iterator m = moduleInfo.preprocessorSettings.defines.begin();
        while ( m != moduleInfo.preprocessorSettings.defines.end() )
        {
            preprocessorSection += " -D" + (*m);
            ++m;
        }

        // Add some spacing for readability
        preprocessorSection += "\n\n";
    }

    // Now we add the compiler flags, if any
    // For Android we only support the GCC compilers
    CORE::CString compilerSection;
    TStringMap::const_iterator p = moduleInfo.compilerSettings.compilerFlags.find( "GCC" );
    if ( p != moduleInfo.compilerSettings.compilerFlags.end() )
    {
        compilerSection = "LOCAL_CFLAGS +=" + (*p).second + "\n\n";
    }
    p = moduleInfo.compilerSettings.compilerFlags.find( "G++" );
    if ( p != moduleInfo.compilerSettings.compilerFlags.end() )
    {
        compilerSection = "LOCAL_CPPFLAGS +=" + (*p).second + "\n\n";
    }

    // Now we will add all the dependency linking instructions.
    // For some reason it matters, at specification time, to Android's build
    // system whether the module you are linking to is a dynamically linked module
    // or a statically linked module. As such we have to figure out which is which.
    //
    // We make an alphabetical list instead of creating the section right away because
    // we dont want the order to vary in the makefile because such changes cause the NDK
    // to build the code again for no reason.
    CORE::CString linkingErrorSection;
    TStringSet linkedSharedLibraries;
    TStringSet linkedStaticLibraries;
    TStringSet linkedRuntimeLibraries;
    TModuleTypeMap::const_iterator m = moduleInfo.linkerSettings.linkedLibraries.begin();
    while ( m != moduleInfo.linkerSettings.linkedLibraries.end() )
    {
        const CORE::CString& linkedLibName = (*m).first;
        TModuleType linkedLibType = (*m).second;
        switch ( linkedLibType )
        {
            case MODULETYPE_EXECUTABLE:
            {
                // This is really nasty but the best option for now...
                // It is possible to link to exported symbols from an executable
                // under linux and as such we will leverage this here
                linkedSharedLibraries.insert( linkedLibName );
                break;
            }
            case MODULETYPE_SHARED_LIBRARY:
            {
                linkedSharedLibraries.insert( linkedLibName );
                break;
            }
            case MODULETYPE_STATIC_LIBRARY:
            {
                linkedStaticLibraries.insert( linkedLibName );
                break;
            }
            case MODULETYPE_CODE_INTEGRATE_LOCATION:
            case MODULETYPE_HEADER_INTEGRATE_LOCATION:
            case MODULETYPE_HEADER_INCLUDE_LOCATION:
            {
                // Skip this, no linking required
                break;
            }
            default:
            {
                // Since the depedendency module type was not predefined we will investigate among
                // the other modules to try to determine the nature of the linked module
                const TModuleInfo* linkedDependency = FindModuleByName( mergeLinks, linkedLibName );
                if ( NULL != linkedDependency )
                {
                    // The module we are linking too is part of this project.
                    // As such we can simply check the other module's info
                    // to find out wheter its a dynamically linked module or not
                    // which in turn tells us how to instruct the Android build system
                    // to link.
                    switch( linkedDependency->moduleType )
                    {
                        case MODULETYPE_SHARED_LIBRARY:
                        {
                            linkedSharedLibraries.insert( linkedLibName );
                            break;
                        }
                        case MODULETYPE_STATIC_LIBRARY:
                        {
                            linkedStaticLibraries.insert( linkedLibName );
                            break;
                        }
                        case MODULETYPE_EXECUTABLE:
                        {
                            // This is really nasty but the best option for now...
                            // It is possible to link to exported symbols from an executable
                            // under linux and as such we will leverage this here
                            linkedSharedLibraries.insert( linkedLibName );
                            break;
                        }
                        case MODULETYPE_HEADER_INTEGRATE_LOCATION:
                        case MODULETYPE_CODE_INTEGRATE_LOCATION:
                        {
                            // Dont do anything.
                            // The files for this 'module' have already been merged into the dependent module
                            break;
                        }
                        case MODULETYPE_HEADER_INCLUDE_LOCATION:
                        {
                            // Don't have to do anything.
                            // Due to the auto-dependency tracking of include paths the header paths will have been added to
                            // whatever module depends on this 'module'
                            break;
                        }
                        default:
                        {
                            linkingErrorSection +=
                              "# *** ERROR *** Finish me\n"
                              "# Unable to determing module type from the source information\n"
                              "# Please edit the line below to manually set the correct linking method for this dependency\n";
                            linkingErrorSection += "#LOCAL_<(LDLIBS???)> += " + moduleInfo.name + "\n\n";

                            GUCEF_ERROR_LOG( CORE::LOGLEVEL_NORMAL, "Error: the module " + moduleInfo.name + " does not have a useable module type set, you will have to manually edit the file to correct the error" );
                            break;
                        }
                    }
                }
                else
                {
                    // If we get here then this dependency is not on a module which is part of the project
                    // As such we cannot build this module thus the only approriote linking method would seem
                    // to be the one where we simply instruct the linker to load this dependency at runtime.
                    // This will typically be the case for any Android NDK modules we have to link to.
                    linkedRuntimeLibraries.insert( linkedLibName );
                }
            }
        }
        ++m;
    }

    CORE::CString linkingSection;
    CORE::CString linkedSharedLibrariesSection = "\nLOCAL_SHARED_LIBRARIES := \\\n";
    CORE::CString linkedStaticLibrariesSection = "\nLOCAL_STATIC_LIBRARIES := \\\n";
    CORE::CString linkedRuntimeLibrariesSection = "\nLOCAL_LDLIBS := \\\n";

    // Based on what was found we will construct the linking section
    bool first = true;
    n = linkedSharedLibraries.begin();
    while ( n != linkedSharedLibraries.end() )
    {
        if ( !first )
        {
             linkedSharedLibrariesSection += " \\\n";
        }
        linkedSharedLibrariesSection += "  " + (*n);
        first = false;
        ++n;
    }
    first = true;
    n = linkedStaticLibraries.begin();
    while ( n != linkedStaticLibraries.end() )
    {
        if ( !first )
        {
             linkedStaticLibrariesSection += " \\\n";
        }
        linkedStaticLibrariesSection += "  " + (*n);
        first = false;
        ++n;
    }
    first = true;
    n = linkedRuntimeLibraries.begin();
    while ( n != linkedRuntimeLibraries.end() )
    {
        if ( !first )
        {
             linkedRuntimeLibrariesSection += " \\\n";
        }
        linkedRuntimeLibrariesSection += "  -l" + (*n);
        first = false;
        ++n;
    }

    if ( !linkedSharedLibraries.empty() )
    {
        linkingSection += linkedSharedLibrariesSection + "\n\n";
    }
    if ( !linkedStaticLibraries.empty() )
    {
        linkingSection += linkedStaticLibrariesSection + "\n\n";
    }
    if ( !linkedRuntimeLibraries.empty() )
    {
        linkingSection += linkedRuntimeLibrariesSection + "\n\n";
    }
    linkingSection += linkingErrorSection;

    // Check if we have a file on disk of information which is to be inserted into
    // our automatically generated make file
    CORE::CString manualContent;
    CORE::CString manualContentFilePath = moduleRoot;
    CORE::AppendToPath( manualContentFilePath, "AndroidAddition.mk" );
    if ( CORE::FileExists( manualContentFilePath ) )
    {
        if ( CORE::LoadTextFileAsString( manualContentFilePath ,
                                         manualContent         ) )
        {
            GUCEF_LOG( CORE::LOGLEVEL_NORMAL, "Successfully loaded manually defined content for module " + moduleInfo.name + " from addition file " + manualContentFilePath );
        }
        else
        {
            manualContent =
              "# *** ERROR *** Finish me\n"
              "# Unable to load manually defined content from detected AndroidAddition.mk file\n"
              "# Please manually insert its contents here\n\n";
            GUCEF_ERROR_LOG( CORE::LOGLEVEL_NORMAL, "Error: the module " + moduleInfo.name + " has manually defined content in a AndroidAddition.mk file but it could not be loaded, you will have to manually edit the file to correct the error" );
        }
    }

    // Now generate the latter part of the file which contains more meta data about the module
    CORE::CString contentSuffix;
    switch ( moduleInfo.moduleType )
    {
        case MODULETYPE_SHARED_LIBRARY:
        {
            contentSuffix += "include $(BUILD_SHARED_LIBRARY)\n\n";
            break;
        }
        case MODULETYPE_STATIC_LIBRARY:
        {
            contentSuffix += "include $(BUILD_STATIC_LIBRARY)\n\n";
            break;
        }
        case MODULETYPE_EXECUTABLE:
        {
            contentSuffix += "include $(BUILD_EXECUTABLE)\n\n";
            break;
        }
        default:
        {
            contentSuffix +=
              "# *** ERROR *** Finish me\n"
              "# Unable to determine module type from the source information\n"
              "# Please edit the line below to manually set the correct module type to build\n"
              "#include $(BUILD_???)\n\n";

            GUCEF_ERROR_LOG( CORE::LOGLEVEL_NORMAL, "Error: the module " + moduleInfo.name + " does not have a useable module type set, you will have to manually edit the file to correct the error" );
            break;
        }
    }

    // Check for NDK static libraries to import
    if ( !linkedStaticLibraries.empty() )
    {
        TStringSet::iterator a = linkedStaticLibraries.find( "android_native_app_glue" );
        if ( a != linkedStaticLibraries.end() )
        {
            ndkModulesUsed.insert( "android_native_app_glue" );
            contentSuffix += "$(call import-module,android/native_app_glue)\n";
        }
        a = linkedStaticLibraries.find( "cpufeatures" );
        if ( a != linkedStaticLibraries.end() )
        {
            ndkModulesUsed.insert( "cpufeatures" );
            contentSuffix += "$(call import-module,android/cpufeatures)\n";
        }
    }

    return contentPrefix + srcFilesSection + includeFilesSection + preprocessorSection + compilerSection + linkingSection + manualContent + contentSuffix;
}