Fix games crash because of some extensions not included in the generated games

Revert "Fix missing export files by including the free functions of every extension that is actually used (#4672)" (#4746) (commit 93121d1a1c)
This commit is contained in:
Florian Rival
2022-12-26 12:36:39 +01:00
committed by GitHub
parent 2005f9c37b
commit abd417c494
4 changed files with 112 additions and 45 deletions

View File

@@ -54,8 +54,8 @@ bool Exporter::ExportWholePixiProject(
auto usedExtensions = gd::UsedExtensionsFinder::ScanProject(project);
auto exportProject = [this, &exportedProject, &exportOptions, &helper,
&usedExtensions](gd::String exportDir) {
auto exportProject = [this, &exportedProject, &exportOptions, &helper](
gd::String exportDir) {
bool exportForCordova = exportOptions["exportForCordova"];
bool exportForFacebookInstantGames =
exportOptions["exportForFacebookInstantGames"];
@@ -88,8 +88,7 @@ bool Exporter::ExportWholePixiProject(
exportedProject.GetLoadingScreen().GetGDevelopLogoStyle(),
includesFiles);
// Export files for free function, object and behaviors
helper.ExportFreeFunctionIncludes(exportedProject, includesFiles, usedExtensions);
// Export files for object and behaviors
helper.ExportObjectAndBehaviorsIncludes(exportedProject, includesFiles);
helper.ExportObjectAndBehaviorsRequiredFiles(exportedProject, resourcesFiles);

View File

@@ -41,7 +41,6 @@
#include "GDCore/Tools/Log.h"
#include "GDJS/Events/CodeGeneration/LayoutCodeGenerator.h"
#include "GDJS/Extensions/JsPlatform.h"
#include "GDCore/IDE/Events/UsedExtensionsFinder.h"
#undef CopyFile // Disable an annoying macro
namespace {
@@ -116,9 +115,7 @@ bool ExporterHelper::ExportProjectForPixiPreview(
immutableProject.GetLoadingScreen().GetGDevelopLogoStyle(),
includesFiles);
// Export files for free function, object and behaviors
auto usedExtensions = gd::UsedExtensionsFinder::ScanProject(exportedProject);
ExportFreeFunctionIncludes(exportedProject, includesFiles, usedExtensions);
// Export files for object and behaviors
ExportObjectAndBehaviorsIncludes(immutableProject, includesFiles);
ExportObjectAndBehaviorsRequiredFiles(immutableProject, resourcesFiles);
@@ -800,37 +797,6 @@ bool ExporterHelper::ExportIncludesAndLibs(
return true;
}
void ExporterHelper::ExportFreeFunctionIncludes(
gd::Project &project, std::vector<gd::String> &includesFiles,
std::set<gd::String> &usedExtensions) {
auto addIncludeFiles = [&](const std::vector<gd::String> &newIncludeFiles) {
for (const auto &includeFile : newIncludeFiles) {
InsertUnique(includesFiles, includeFile);
}
};
for (auto &&usedExtension : usedExtensions) {
if (project.HasEventsFunctionsExtensionNamed(usedExtension)) {
auto &extension = project.GetEventsFunctionsExtension(usedExtension);
for (size_t functionIndex = 0;
functionIndex < extension.GetEventsFunctionsCount(); functionIndex++) {
auto &function = extension.GetEventsFunction(functionIndex);
gd::String fullType = gd::PlatformExtension::GetEventsFunctionFullType(
usedExtension, function.GetName());
auto metadata = function.IsCondition()
? gd::MetadataProvider::GetConditionMetadata(
project.GetCurrentPlatform(), fullType)
: gd::MetadataProvider::GetActionMetadata(
project.GetCurrentPlatform(), fullType);
addIncludeFiles(metadata.GetIncludeFiles());
}
}
}
}
void ExporterHelper::ExportObjectAndBehaviorsIncludes(
const gd::Project &project, std::vector<gd::String> &includesFiles) {
auto addIncludeFiles = [&](const std::vector<gd::String> &newIncludeFiles) {

View File

@@ -247,12 +247,6 @@ class ExporterHelper {
bool ExportEffectIncludes(const gd::Project &project,
std::vector<gd::String> &includesFiles);
/**
* \brief Add the include files for all free functions from used extensions.
*/
void ExportFreeFunctionIncludes(gd::Project &project,
std::vector<gd::String> &includesFiles,
std::set<gd::String> &usedExtensions);
/**
* \brief Add the include files for all the objects of the project
* and their behaviors.

View File

@@ -43,6 +43,7 @@ type Options = {|
type CodeGenerationContext = {|
codeNamespacePrefix: string,
extensionIncludeFiles: Array<string>,
|};
const mangleName = (name: string) => {
@@ -144,6 +145,29 @@ const loadProjectEventsFunctionsExtension = (
});
};
/**
* Get the list of mandatory include files when using the
* extension.
*/
const getExtensionIncludeFiles = (
project: gdProject,
eventsFunctionsExtension: gdEventsFunctionsExtension,
options: Options,
codeNamespacePrefix: string
): Array<string> => {
return mapFor(0, eventsFunctionsExtension.getEventsFunctionsCount(), i => {
const eventsFunction = eventsFunctionsExtension.getEventsFunctionAt(i);
const codeNamespace = getFreeFunctionCodeNamespace(
eventsFunction,
codeNamespacePrefix
);
const functionName = codeNamespace + '.func'; // TODO
return options.eventsFunctionCodeWriter.getIncludeFileFor(functionName);
}).filter(Boolean);
};
/**
* Generate the code for the events based extension
*/
@@ -158,8 +182,15 @@ const generateEventsFunctionExtension = (
const codeNamespacePrefix =
'gdjs.evtsExt__' + mangleName(eventsFunctionsExtension.getName());
const extensionIncludeFiles = getExtensionIncludeFiles(
project,
eventsFunctionsExtension,
options,
codeNamespacePrefix
);
const codeGenerationContext = {
codeNamespacePrefix,
extensionIncludeFiles,
};
return Promise.all(
@@ -215,6 +246,9 @@ const generateEventsFunctionExtension = (
)
)
.then(functionInfos => {
if (!options.skipCodeGeneration) {
applyFunctionIncludeFilesDependencyTransitivity(functionInfos);
}
return extension;
});
};
@@ -267,6 +301,11 @@ const generateFreeFunction = (
.setIncludeFile(functionFile)
.setFunctionName(functionName);
// Always include the extension include files when using a free function.
codeGenerationContext.extensionIncludeFiles.forEach(includeFile => {
instructionOrExpression.addIncludeFile(includeFile);
});
if (!options.skipCodeGeneration) {
const includeFiles = new gd.SetString();
const eventsFunctionsExtensionCodeGenerator = new gd.EventsFunctionsExtensionCodeGenerator(
@@ -314,6 +353,65 @@ const generateFreeFunction = (
}
};
/**
* Add dependencies between functions according to transitivity.
* @param functionInfos free function metadatas
*/
const applyFunctionIncludeFilesDependencyTransitivity = (
functionInfos: Array<{
functionFile: string,
functionMetadata:
| gdInstructionMetadata
| gdExpressionMetadata
| gdMultipleInstructionMetadata,
}>
): void => {
// Note that the iteration order doesn't matter, for instance for:
// a -> b
// b -> c
// c -> d
//
// going from a to c:
// a -> (b -> c)
// b -> c
// c -> d
//
// or from c to a:
// a -> b
// b -> (c -> d)
// c -> d
//
// give the same result:
// a -> (b -> (c -> d))
// b -> (c -> d)
// c -> d
const includeFileSets = functionInfos.map(
functionInfo =>
new Set(functionInfo.functionMetadata.getIncludeFiles().toJSArray())
);
// For any function A of the extension...
for (let index = 0; index < functionInfos.length; index++) {
const includeFiles = includeFileSets[index];
const functionIncludeFile = functionInfos[index].functionFile;
// ...and any function B of the extension...
for (let otherIndex = 0; otherIndex < functionInfos.length; otherIndex++) {
const otherFunctionMetadata = functionInfos[otherIndex].functionMetadata;
const otherIncludeFileSet = includeFileSets[otherIndex];
// ...where function B depends on function A...
if (otherIncludeFileSet.has(functionIncludeFile)) {
// ...add function A dependencies to the function B ones.
includeFiles.forEach(includeFile => {
if (!otherIncludeFileSet.has(includeFile)) {
otherIncludeFileSet.add(includeFile);
otherFunctionMetadata.addIncludeFile(includeFile);
}
});
}
}
}
};
function generateBehavior(
project: gdProject,
extension: gdPlatformExtension,
@@ -338,6 +436,11 @@ function generateBehavior(
behaviorMetadata.setIncludeFile(includeFile);
// Always include the extension include files when using a behavior.
codeGenerationContext.extensionIncludeFiles.forEach(includeFile => {
behaviorMetadata.addIncludeFile(includeFile);
});
return Promise.resolve().then(() => {
const behaviorMethodMangledNames = new gd.MapStringString();
@@ -454,6 +557,11 @@ function generateObject(
objectMetadata.setIncludeFile(includeFile);
// Always include the extension include files when using an object.
codeGenerationContext.extensionIncludeFiles.forEach(includeFile => {
objectMetadata.addIncludeFile(includeFile);
});
return Promise.resolve().then(() => {
const objectMethodMangledNames = new gd.MapStringString();