Using QtCreator on host OSX to cross compile for target Android

Context

This is a log, or instructions.  Disclaimer:

  • things change, this will quickly become outdated.
  • I sometimes make mistakes
  • there may be other ways to do this

This is similar to my post about using Linux host for the same purpose.  Here, I switched to a new host: OSX.  I decided that OSX was a better host than Linux, since OSX supports more targets (OSX, iOS, and Android) whereas Linux only targets (Linux and Android.)

There are only slight differences between using host OSX and host Linux:

  • where menu items live in the QtCreator GUI.
  • how prerequisite third-party tools are packaged

My use case is also using pyqtdeploy.  So in this example, I start with a QtCreator project that pyqtdeploy created for me. You might also use these instructions for a Qt example project.

Prepare tools that QtCreator depends on

QtCreator, to build for Android, requires third-party tools.   Install:

  • Android SDK (Google)
  • Android NDK (Google)
  • Ant (Apache ) (a better ‘make’, that QtCreator uses.)
  • JDK (Oracle)

OLD: Follow widely published instructions.  But …

New: QtCreator is smart enough to help you download these things: choose the download icons (a green arrow pointing down into a tray) in QtCreator>Preferences>Android.

Expect:

  • a directory e.g. $HOME/android-sdk-macosx
  • a directory e.g. $HOME/android-ndk-r10d
  • a directory e.g. $HOME/apache-ant-1.9.4
  • a scattered installation of the JDK (it comes as an OSX .dmg, or self-installer)

You should not expect any executables to be installed in your PATH, i.e. ‘which ant’ returns nothing.  Or at least you will not be invoking any executables: instead you will configure QtCreator to know where the executables live.

Open a project and configure it with a kit

Here I double-clicked on the .pro file that pyqtdeploy created.  Expect QtCreator to start and show you a dialog asking you to choose a kit.

In my case (probably because of futzing I had done earlier) there were multiple Android kits, including one that apparently I had created earlier.  I chose ‘Android for armeabi-v7a (GCC 4.0, Qt 5.4.0)’, which I think is one that is distributed (not the one I had created earlier.)

I also changed the ‘build directory’ to the one that was specialized with ‘android’ e.g. /Users/bootch/pensoolpyqtdeploy/build-Pensool-Android_for_armeabi_v7a_GCC_4_9_Qt_5_4_0-Debug  (not $HOME/pyqtdeploy/build which is the directory that pyqtdeploy created.)

Choose the ‘OK’ button.  Expect the usual Qt screen showing your open project.

Configure QtCreator Android Tools

Choose QtCreator>Preferences.  Expect a ‘Preferences’ dialog to open.

Select the ‘Android’ item in the left panel.  Expect the right panel to display ‘Android Configurations.’

If you haven’t installed the third-party prerequisites already, you can use the download icons in the right panel.  QtCreator is also smart enough to find some of these prerequisites (the JDK).

In the right panel, click on the ‘Choose’ button beside ‘Android SDK location’.  Expect a file browser to appear.  Navigate to the directory where you installed the Android SDK and choose the OK button.

Repeat for Android NDK and Ant executable (which is in apache-ant-1.9.4/bin/ant).

Running your app

Choose the ‘Run’ icon.  Expect a dialog titled ‘Select Android Device’.

Plug in your Android device to a USB port and power up the device.  Wait for it to boot.  Choose the ‘Refresh Device List’ button.  Expect your device to appear in the list.

Select your device and choose the ‘OK’ button.  Expect Qt progress bar to show ‘Build’.

Expect link errors (at least in my case using pyqtdeploy, I had not properly compiled a static Python?)  Or, if it deploys, expect a mysterious crash (better to use target iOS from this host, since it gives much better crash reports.)

 

 

The rest of this is cruft.  If you choose the kit distributed with QtCreator, you won’t need this.  If you choose a kit that you created.

Configure the build settings for a custom kit

At least for me, I needed to configure:

  • the build directory
  • the compiler

Choose the ‘Projects’ icon in the left panel.  Expect it to show a tabbed panel, initially on the ‘Build&Run’ tab.

Expect that tab to have a nested tabbed panel initially displaying one kit ‘Qt5.4.0 for Android armv7’.

Expect that kit to have a toggle button ‘Build/Run’.  Ensure it is toggled to ‘Build’.

Configuring the compiler for the kit

Choose the ‘Manage Kits…’ button to the left of the ‘Qt5.4.0 for Android armv7’ tab.  Expect a ‘Preferences’ dialog to open.

Ensure that ‘Build&Run’ is selected in the left panel.  Expect the right panel to be titled ‘Build&Run’ and to have tabs such as ‘General’, ‘Kits’, etc.

Choose the ‘Compilers’ tab.  Expect the tabbed panel to display a list of  compilers under the heading ‘Auto-detected.’

Select ‘Android GCC(arm-4.9)’ and choose the OK button.

 

 

 

 

Cutting Powerfilm thin-film solar cells

Experimental result: you can cut Powerfilm thin-film solar cells.  I wrote this blog because whenever I search for that topic, the usual results are obscure references to “follow the instructions” and the manufacturer’s website doesn’t seem to discuss it.   Maybe this is not an important use case.  But I wanted a solar cell (a panel really) smaller than the smallest one made by Powerfilm (model SP3-37, which is about 4×6 cm.

Cutting down a thin-film solar cell

Simply take a sharp scissors and cut in on a line along the direction of the fingers (the T-shapes that seem to gather charge from the top of one row of cells and carry it in series to the bottom of the next row of cells.)  In other words, each piece retains a portion of the silvery contact bars at opposite sides of the panel.

I was able to cut on SP3-37 into thirds very nicely (each piece about 1.2 cm by 6 cm.)  For some reason, there is a slight voltage drop on the pieces.  Under a certain light condition, the whole panel generated 3V open circuit, a two-thirds piece generated about 2.8V and a one-third piece generated about 2.6V.

Cutting in in thirds avoids cutting into the fingers, and gives three pieces that look about the same (with the finger down the middle.)  I don’t see why you couldn’t cut along the fingers and get six pieces.  I would guess that if you cut so that some piece has no fingers, that piece would have much reduced function.  But I haven’t tried it.

Cutting in this way leaves the pieces with edges that are not sealed by the outer covering plastic laminate of the entire panel.  I can’t say what the effect is on the lifetime, or warranty.

When I first contemplated cutting a thin-film solar cell, I worried that the shearing action would somehow short the layers of the solar cells.  Evidently not, at least in the short term.

Trimming the silvery contact bars

In my opinion, the silvery contact bars are much larger than they need to be.  Probably the manufacturer contemplates they need to be that large for ease and reliability of soldering to them, and that they will always be hidden by a bezel of the enclosing product.

Some applications, such as in RC planes, for which the manufacturer makes a lightweight model, you would also want to trim off excess silvery contact bars.

I haven’t yet tried to trim the silvery contact bars.

Simple trimming of excess

On the stock part, you can see where the outer plastic laminate seals the edges, away from any functional layers.  In other words, you can see the channels where the manufacturer has cut a strip of the parts into parts.  The stock part seems to have some excess, especially along the edge having a silvery contact bar.  Even if I don’t want a smaller panel, I usually trim this excess away just for neatness and to save weight.

Cutting non-rectangular shapes

Suppose you wanted to cut a thin-film solar panel into a decorative shape.  I suppose you could do that as long as you retained a portion of each silvery contact bar.

Cutting down the number of cells in series

I don’t think you can do that.  You are stuck with the lowest voltage panel that the manufacturer makes (3V: 5 cells of 0.6V each, in series.)  In my opinion, there will be demand for 1.5V panels.  Many electronics nowdays work at only 1.5V.

But it might be possible to cut the thin-film solar cell orthogonally to the fingers, and fabricate a new silvery contact bar to replace the one you cut away.

Understanding QML, prototypal inheritance, and generalization/specialization

This discusses QML in object oriented terms, for someone who is familiar with classes and unfamiliar with declarative programming and prototypal inheritance.

This was quickly written, and could be wrong.

Thinking of QML Components as classes

QML has no classes (which are first-class objects).  However, you can loosely think of component files as class definitions.

For example you have a directory:

foo
  Foo.qml

which defines a component.  (In QML, every .qml file must have only one root item, the component that is being defined.)  You can think of this as class “Foo”.  Note that this enforces the common programming practice ‘one class per file’ and it eliminates the tedium of naming a class AND the file that contains the class definition:  the filename IS the class name.

Like a class, you can instantiate it many times:

import "foo" as MyFoo

Item {
 id: item1
 MyFoo.Foo{}
 MyFoo.Foo{}
}

(Glossing over the details of how you might identify and reference the two separate instances.)  The two instances are of the same type (they have the same properties.)  The instance “item1” has a new type, an unnamed type.  (Making this code a named component (loosely speaking, class) only requires that you put it in a file whose name starts with a capital letter.)  You can say the two instances have the class Foo, but the class Foo is not a first-class object: you can’t pass it around, except as the string name of the file that defines it.

Likewise, you can think of the directory “foo” as a module, and the directory name and the module name are one-and-the-same.

Specializing generalizations in QML

Suppose you want Foo to be a generalization, and to specialize instances of it.

Note that specializing instances creates new types (derived types but not subtypes?).  It is NOT like creating subclasses?  (I should refresh my reading of Bertrand Meyer’s discussions of the orthogonality of generalization and inheritance.)

QML has two “kinds” of properties:

  • non-visual, sometimes called ‘resources’
  • visual, often items in the list value of a property named ‘children’ (which QML magically hides using default property, all of which is a digression which I won’t discuss in detail.)

Specializing non-visual properties of generalizations in QML

It is often relatively easy to specialize an instance’s non-visual properties.  First define a generalized component (class?):

//File: Foo.qml
Item {
  property var specializableProperty
}

Then create a specialized instance:

//File: Bar.qml
import "foo" as MyFoo

MyFoo.Foo { specializableProperty: "specialValue" }

This creates an instance of Foo whose specializableProperty is bound to string “specialValue.”  You might think of this a procedural parameter passing.  Except that QML is mostly declarative (except for Javascript functions.)  If “specialValue” was not a string literal, it would seem less like parameter passing.

A more illustrative example (and a common use case) would be if the name of the property were ‘model’  and you bound it to a more elaborate object (say of class Model or the QML predefined type: ListModel) than a simple string.  Then you are creating instances of Foo, specialized by having different models.  (Where the use case is: using the model-view-controller paradigm.)

Specializing visual properties of generalizations in QML

Summary: use a QML Loader.

Specializing with visual components is complicated by the fact that visual components are frequently trying to bind their properties to properties of their parent.  In other words, the object you are specializing with must be instantiated later, when the specialized component is instantiated, not at the time you are ‘passing’ the specializing component.  First create a component whose contents are loaded from a url at instantiation time:

//File: Foo.qml
// to be specialized
Item {
  property var specializedVisualPropertySourceURL
  Loader {
    id: specializedVisualProperty
    source: specializedVisualPropertySourceURL
  } 
}

Then create a specialized instance:

//File: Bar.qml
import "foo" as MyFoo
MyFoo.Foo {specializedVisualPropertySourceURL: "../baz/Baz.qml" }

where Baz.qml defines some visual component.  Here you are passing the name of the file that defines the specializing part (you are passing a class as a factory.)  You are passing it into the specialized component, to its Loader.  The Loader instantiates the specializing part in the context of the specialized component (said context having many properties such as ‘anchor’ that are needed by the specializing visual component part.)

If you try to use the same technique as for non-visual specialization, you might get errors such as “anchor not defined”.  These errors come when you are instantiating the specializing stuff so that you can pass it: at that time, the context may not be a visual component having the needed properties such as anchor.

(Here I should have example wrong code.)

Note there are many ways to skin a cat.  I think you could also use property aliases in the above code, for example to expose Loader.source directly to the specializing component.