Hooking VariantManager

50 views
Skip to first unread message

Zac Bowling

unread,
Sep 9, 2014, 5:26:12 PM9/9/14
to adt...@googlegroups.com
Hey guys!

I want extend the DSL for variants/flavors and add build tasks that compile for each variant to build JNI libs using our own build systems for each variant. 

The way it works inside the plugin is very hardcoded in VariantManager but I would love to get a callback myself to create my own tasks. What I would love to do is know the VariantData like it's passed around internally. 

Right now my method is super hacky. I'm running through all the tasks as they are added and parsing the task names to add dependencies. It's not optimal. 

The source provider/artifact API concept looks like it is my only hook to add different libs to each variant but it's only for adding additional folders. That works for me to set directories but doesn't help me on the task side. 

My goal is that I'm building this so you can call arbitrary build tools (like cmake or xcodebuild) with the current variant info so that custom JNI libs can be built for each flavor/architecture/configuration. 

Is there is a cute method I can use without hacking or calling private APIs?

The short term is I could fork and refactor the Android plugin but I don't want to pull what Amazon did (and hopefully work with their fork maybe) and be able to work if you apply my plugin after the Android one (sort of where the new NDK plugin seems to be going). Would you guys be open to pull requests if I refactor the base plugin to expose a few methods to get callbacks from the VariantManager when it's creating tasks?

Thanks!!! 

~
Zac Bowling
Engineering - Apportable, Inc 


Xavier Ducrohet

unread,
Sep 9, 2014, 5:51:35 PM9/9/14
to adt...@googlegroups.com
Why do you want to be notified when tasks are being created instead of doing it after? If you do:

android.applicationVariants.all { variant -> 
}

you will effectively be called as soon as each variant is created and get access to all its tasks. Is this not enough?


--
You received this message because you are subscribed to the Google Groups "adt-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adt-dev+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Xavier Ducrohet
Android SDK Tech Lead
Google Inc.
http://developer.android.com | http://tools.android.com

Please do not send me questions directly. Thanks!

Zac Bowling

unread,
Sep 9, 2014, 7:33:08 PM9/9/14
to adt...@googlegroups.com
That is really close to what I’m looking for. I need to detect if it’s a library project or application project but I can go that direction. The tasks I need to hook as dependencies on are consistently named so I can branch off that. 

I’m debating if it makes sense to actually move all the native build aspects to a new dependent project instead of trying to make it work in the same android app plugin owned project like the NDK plugin does it. I could have my native building plugin work on it’s own project and output AAR format libraries instead in it's own assemble task like the library plugin. Then get dependent compiling working instead with it instead of trying to mix into the Android plugin own project. It feels more natural doing that maybe. (Use the artifact API possibly?) The native libraries do have some JNI hooks into the main application code but really I would love separating the concerns between native building needs and Java/Android app/lib building into different projects conceptually. That way I can rebuild the native bits separately from the final app. Like Library targets but without worrying about Java or other android needs that don’t concern native (like AIDL, Renderscript, etc tasks).

It almost seems like the NDK plugin should go this same direction of moving NDK building to another plugin outside the AppPlugin/LibraryPlugin level IMHO. Maybe a NativePlugin in addition to AppPlugin and LibraryPlugin. I’m may be completely wrong but it feels more natural for the NDK integration to do that. I’m not using the NDK plugin myself (old or new) in my plugin since it’s redoing things that we have better solutions too in our build system with product for supporting multiple platforms, but the same challenges exist in the NDK builder for end users I’m sure (I’ve got 3 build systems in my head and trying to make them play together elegantly in a maintainable way and convert metaphors and concepts across each which makes this a bit more confusing so I might just be crazy). 

Thanks!

Zac

You received this message because you are subscribed to a topic in the Google Groups "adt-dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/adt-dev/dGDBoJdNLtQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to adt-dev+u...@googlegroups.com.

Xavier Ducrohet

unread,
Sep 9, 2014, 10:04:57 PM9/9/14
to adt...@googlegroups.com
We will indeed provide both native support inside "regular" android projects (apps or libs) and the ability to build pure native projects.

The trick is packaging the output of the native project in a way that's compatible with the android project that consumes it. Right now the only way to do it is to generate an aar with all supported ABIs which is not great if you're doing a build/deploy/test on a particular ABI.
The new native stuff that's coming in Gradle should allow you have the native project publish all its artifacts separately (per-ABI but also build-type debug vs release) and to have the app project consume which artifact is needed by the variant you're building. It's not there yet though.

Zac Bowling

unread,
Sep 17, 2014, 5:57:17 PM9/17/14
to adt...@googlegroups.com
Thanks! 

I'm doing something like this specifically for the XcodePlugin that I've created.

    @Override
    void apply(Project project) {
        if (project.hasProperty("android")) {
            XcodeExtension e = project.extensions.create('xcode', XcodeExtension)
            .... other magic ....
            project.afterEvaluate {
                BaseExtension android = project.getExtensions().getByName("android")
                android.applicationVariants.all { variant ->
                    //println variant.class.toString()
                    Task compileXcodeTask = project.tasks.create ("compile${variant.name.capitalize()}Xcode", XcodeBuildTask)
                    .... other magic ...
                    Task compileNdkTask = project.tasks.findByName("compile${variant.name.capitalize()}Ndk")
                    compileNdkTask.dependsOn compileXcodeTask
                }
            }
        }
    }

I don't want the new native building tools in gradle (new or old). I'm building my own that support calling 3rd party build systems for native (namely Xcode but also ninja and cmake) that we have trained to work with our middleware NDK replacement at Apportable. 

My current problem is that these build systems do not creat a root folder like ndk-build does with everything in neat CPU specific folders. They output each lib in a d ifferent folder. Our old build system supported this concept. The jniLibs/ABIFilter system is a bit aggravating taking only a root set of folders. I want to be able to specify FILES for a specific CPU arch not in a specific direction with specific subdirectories. The way the AndroidBuilder and Packager work this is all hardcoded all the way down to the core and it's frustrating because right now I'm using copy tasks to make temp folder with the layout that jniLib root and it's useless time and cycles that are not necessary. I would love if the source set for that jniLibs was changed around this to allow for specific files for specific arcs in a map instead of giving only a set of root folders.  
Reply all
Reply to author
Forward
0 new messages