Extension Template Repository

Hi all,

I have been experimenting on a new system for building extensions. This version no longer requires checking out the whole source tree of App Inventor to build an extension, which means that you can manage extensions in different repositories without a lot of overhead. The template repository is available on GitHub. I would appreciate feedback on this approach and how it is or isn’t working.

Regards,
Evan W. Patton, Ph.D.
Lead Software Engineer, MIT App Inventor

23 Likes

Just tested out this new system and its working perfectly. It takes significantly less time to build the extensions.
BTW, do I need to make any changes in case I want to use any external dependencies in addition to adding them to the lib/deps folder?

PS: I found a bug. When I try to rebuild the extension again after successfully building it, the build fails. (Although, it builds successfully if I perform ant clean.) Here is the error log:
I’ve replaced BUILD F@ILED to BUILD UNSUCCESSFUL as Discource was not allowing me add word “F@ILED” to my post. :man_shrugging:

$ ant extensions
Buildfile: e:\Shreyash\AI2-Extensions\build.xml

javac:
    [javac] Compiling 3 source files to e:\Shreyash\GitHub\AI2-Extensions\build\classes
    [javac] warning: [options] bootstrap class path not set in conjunction with -source 7
    [javac] warning: [options] source value 7 is obsolete and will be removed in a future release
    [javac] warning: [options] target value 7 is obsolete and will be removed in a future release
    [javac] warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
    [javac] 4 warnings

process:
     [java]
     [java] Extensions : Generating extensions
     [java]
     [java] Extensions : Generating files [io.shreyash.snacky]

BUILD UNSUCCESSFUL
e:\Shreyash\GitHub\AI2-Extensions\build.xml:45: java.io.IOException: Unable to create temporary path for extension build
        at com.google.appinventor.components.scripts.ExternalComponentGenerator.copyRelatedExternalClasses(ExternalComponentGenerator.java:357)
        at com.google.appinventor.components.scripts.ExternalComponentGenerator.generateExternalComponentBuildFiles(ExternalComponentGenerator.java:163)
        at com.google.appinventor.components.scripts.ExternalComponentGenerator.generateAllExtensions(ExternalComponentGenerator.java:113)
        at com.google.appinventor.components.scripts.ExternalComponentGenerator.main(ExternalComponentGenerator.java:71)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:567)
        at org.apache.tools.ant.taskdefs.ExecuteJava.run(ExecuteJava.java:218)
        at org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:155)
        at org.apache.tools.ant.taskdefs.Java.run(Java.java:861)
        at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:231)
        at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:135)
        at org.apache.tools.ant.taskdefs.Java.execute(Java.java:108)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:567)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:99)
        at org.apache.tools.ant.Task.perform(Task.java:350)
        at org.apache.tools.ant.Target.execute(Target.java:449)
        at org.apache.tools.ant.Target.performTasks(Target.java:470)
        at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1391)
        at org.apache.tools.ant.Project.executeTarget(Project.java:1364)
        at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1254)
        at org.apache.tools.ant.Main.runBuild(Main.java:830)
        at org.apache.tools.ant.Main.startAnt(Main.java:223)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:284)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:101)

Total time: 3 seconds
2 Likes

Thanks for the bug report. I've identified the issue and have a fix:

I too created a PR doing necessary changes that solved the issue on my machine a few minutes ago. :point_down:

Yes, your approach is line with what happens when you run ant extensions in the main repo. I’d like to get to the point where we don’t have to clean before every build though.

1 Like

Can you please shed some light on this?

The build.xml file enumerates all of the JAR files in this directory, so as long as you just drop them in there it should be fine. You shouldn't need to do anything special to the build.xml file like you do in appinventor-sources.

Of course, this is still a beta feature so that may be subject to change as we continue to build it out.

1 Like

It seems not to be working. I'm getting package XYZ does not exist error.

That’s my fault as I included the deps in the extension steps but not in the javac step. I pushed a patch that should fix it.

1 Like

Hi @ewpatton,
This commit still doesn’t solve the issue. The libs aren’t getting added to the AndroidRuntime.jar file. I’m not sure but, maybe this is caused due to the build system treating the external libs as core-libs (like android.jar, etc.) and hence, not including them in AndroidRuntime.jar.

I've pushed another commit that should fix this. You will still need to include the lib in @UsesLibraries.

1 Like

Is there any news about this?

1 Like

Will this project continue at some point?

@Anke I’ve updated the repo to fix the bug in question. As we make further changes to the extension system I’m willing to update it. I think the only thing outstanding at this point is porting the Proguard functionality that @Diego implemented in the main repo. Is there something in particular missing that you need?

3 Likes

Thanks, I didn’t notice that change / last fix.

I tried to follow a suggestion from @vishwas to simplify my first extension My first extension - quadratic equation

this way:

public YailList Calc(float a, float b, float c) {
  float x1 = /*YOUR CODE TO FIND THE FIRST SOLUTION*/;
  float x2 = /*YOUR CODE TO FIND THE SECOND SOLUTION*/;
  return YailList.makeList(new Object[] {x1, x2});
}

but unfortunately that fails:

I got this PM from @vishwas
It looks like you cannot use the gnu.lists.Pair module in the template repository. The YailList module uses Pair to make the list, hence the build failed when you added the list to your code. Evan might have a better idea as to why this is happening as he’s the author of the template repository.

(I just tried making the extension using the full AI sources, and it works​:thinking:)

Is there any solution for that?

I added kawa-1.10.jar, which contains gnu-lists.Pair from the App Inventor sources to the libraries and in the build.xml to solve that issue

2 Likes

But where exactly does that (kawa-1.11-modified.jar ?) have to be placed?

grafik

and here:

@Anke place in

lib/deps/kawa-1.11-modified.jar

and dont forget import and add anotation library..

import com.google.appinventor.components.annotations.UsesLibraries;
and
@UsesLibraries(libraries = "kawa-1.11-modified.jar")

1 Like

This is not necessary for me. See modifications in

import com.google.appinventor.components.runtime.util.YailList should do it

2 Likes