Merry Christmas, Happy Festivus, and a joyous end to the fourth fiscal quarter (as my buddy would say).
Since Monkey C is rather space-inefficient, in many situations it is advantageous to implement code paths that are specific to a given device, and/or define device-specific layout constants or other tweaks. It seems that runtime exclusions have been discussed quite a bit, but these only allow excluding a function, and often require a corresponding "negated" exclusion to pull in an alternate implementation on all devices to which the exclusion needs to not apply. Exclusions "work" but incur the space penalty associated with adding a new function. I realize also that 'has' can be used to detect an exclusion (rather than having to define an alternate implementation) but this too has a cost.
As for per-device constants, it seems we can define them using device properties, but these "constants" aren't known at compile time, and are thus unavailable to the optimizer. The overhead for querying them is nontrivial, as well.
So, I've been thinking..... is it possible to solve some of these problems using per-device const definitions?
Hear me out.
The .jungle file already allows us to specify multiple source paths. What if we put our "main" .mc file in sources/, then create a pile of device-specific .mc files in constants/devicename/constants.mc, fill these with const WHATEVER=foo;, then reference these constants from the main implementation?
Furthermore, if we define const DEVICE_NEEDS_FEATURE_X = false in a device-specific constants file, our shared implementation file can then do this:
if (DEVICE_NEEDS_FEATURE_X) {
do some stuff
}
and since DEVICE_NEEDS_FEATURE_X is known at compile time, the compiler is smart enough to exclude the body of the 'if' if the feature X is set to false.
The device-specific constant files could even be auto-generated, without have to involve (gaslight-prone) codegen junk in our main implementation.
Would something like this work, or have I been getting even less sleep than usual?
Something along the line of:
Jungle:
fenix5xplus.sourcePath = $(sources-common);constants/fenix5xplus fenix6pro.sourcePath = $(sources-common);constants/fenix6pro fenix6spro.sourcePath = $(sources-common);constants/fenix6spro fenix6xpro.sourcePath = $(sources-common);constants/fenix6xpro fenix843mm.sourcePath = $(sources-common);constants/fenix843mm fenix847mm.sourcePath = $(sources-common);constants/fenix847mm
constants/fenix5xplus/constants.mc
const ARC_DIVISION_WIDTH = 3; const HAVE_ELEVATION_UNITS = true;
sources-common/datafield.mc:
if (HAVE_ELEVATION_UNITS) { // Known at build-time; one half gets optimized out elev_units = System.getDeviceSettings().elevationUnits; } else { elev_units = System.getDeviceSettings().distanceUnits; } dc.drawArc(foo, bar, start, start + ARC_DIVIDION_WIDTH); etc
Would something like this work, or is there a better way, that doesn't use more memory? Thanks!