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
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.
$ 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
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.
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.
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.
@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?
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});
}
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:)