Acknowledged
over 1 year ago

excludeAnnotations stopped working as documented in new SDKs

An excludeAnnotations clause started to return errors for the pattern in the official doc that used to work for years. 

function setLayoutVars(){
	if(dataLoading){
		scheduleDataLoading(activity);
		...
	}
	...
}

(:data)
function scheduleDataLoading(activity){	
	...
}

monkey.jungle excludes that function for some devices:

fenix3.excludeAnnotations = data

Those devices never call that function thanks to the dataLoading var.

It worked perfectly for years.

Yet with the latest SDK version (I skipped multiple versions), the raises an error:

> monkeyc -r -o late.prg -y [path2devkey] -f ../monkey.jungle -d fenix3 --typecheck 0

ERROR: fenix3: ./source/lateView.mlc:x,y: Undefined symbol ':scheduleDataLoading' detected

The documentation guides to such usage with conditinal launching excluded symbols even in an example of the excludeAnnotations with conditional launching of (:newer)newHotnessAlgorithm(){} vs. (:older)oldAndBustedAlgorithm(){} annotations

https://developer.garmin.com/connect-iq/reference-guides/jungle-reference/


What's the problem?

Is there any new compiler setting for that? 

  • --Eno-invalid-symbol looks as an acceptable workaround.

    It would be better if this was a standard behavior like before. It does not make sense to create empty functions just because of the compiler. It adds unnecessary complexity and increases memory usage of the weakest devices. That counts for gracefully degrading functions for weaker devices either without data, barometer or OLED. 

    The initial solution was better. 

  • I was talking with the engineering team about this, and we plan to update the documentation to avoid confusion about this, but one suggestion came up: you should be able to use the --Eno-invalid-symbol compiler option to turn that error into a warning without using the solution provided by FlowState.

  • Thanks. I finally did exactly that solution and it works. 

    Then Garmin guys should update the doc where the example suggests something that the compiler does not allow now.

    Or better they should fix this half-baked change, so devs need not todo such unnecessary workarounds with an impact to the memory footprint, that is already quite tight. 

    Thank you took a time to suggest the solution. 

  • It's not that excludeAnnotations per se stopped working, it's that:

    1) The compiler tries to determine whether your app calls an undefined symbol at compile-time now, rather than allowing that kind of situation to cause a crash at run-time

    2) In your case, even if dataLoading is always false for the devices which exclude data (which means they'd never actually call scheduleDataLoading), the compiler isn't smart enough to know or care.

    The simplest solution would be to provide a version of scheduleDataLoading() with an empty body for devices which exclude data. This may waste a few bytes, but who knows, maybe the optimizer will optimize out the call and the function itself when appropriate, which means no bytes would be wasted.

    e.g.

    monkey.jungle:

    base.excludeAnnotations = non_data
    fr245m.excludeAnnotations = data

    .mc file:
    (:data) var dataLoading = true;
    (:non_data) const dataLoading = false;

    (:data)
    function scheduleDataLoading() {
    System.println("scheduleDataLoading");
    }

    (:non_data)
    function scheduleDataLoading() { }

    function testExcludes() {
    System.println("testExcludes");
    if (dataLoading) {
    scheduleDataLoading();
    }
    }