Sketch using Adafruit_FT6206.h and Adafruit_ST77xx library builds with IDE fails with App_lab

On the Q forum there were issues about not being able to use the Adafruit ST7796 library, which I have a fix for and submitted a PR to Adafruit. Since my display has
a capacitive touch display I thought I would try to get it to work as well. For this latest test of this, I installed the Adafruit_FT6206 library and started off with
their CapTouch_onoffbutton example sketch and switched all of the references
from ILI9341 to ST7796S and built it using IDE 2.3.7 and also then updated the
mapping of X, Y from touchscreen to match this setup, which working.
Current code:

//This example implements a simple sliding On/Off button. The example
// demonstrates drawing and touch operations.
//
//Thanks to Adafruit forums member Asteroid for the original sketch!
//
#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_ST7796S.h>
#include <Adafruit_FT6206.h>

// The FT6206 uses hardware I2C (SCL/SDA)
Adafruit_FT6206 ts = Adafruit_FT6206();

#define TFT_DC 4
#define TFT_CS 2
#define TFT_RST 3

Adafruit_ST7796S tft(TFT_CS, TFT_DC, TFT_RST);

boolean RecordOn = false;

#define FRAME_X 210
#define FRAME_Y 180
#define FRAME_W 100
#define FRAME_H 50

#define REDBUTTON_X FRAME_X
#define REDBUTTON_Y FRAME_Y
#define REDBUTTON_W (FRAME_W/2)
#define REDBUTTON_H FRAME_H

#define GREENBUTTON_X (REDBUTTON_X + REDBUTTON_W)
#define GREENBUTTON_Y FRAME_Y
#define GREENBUTTON_W (FRAME_W/2)
#define GREENBUTTON_H FRAME_H

void drawFrame()
{
  tft.drawRect(FRAME_X, FRAME_Y, FRAME_W, FRAME_H, ST77XX_BLACK);
}

void redBtn()
{ 
  tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ST77XX_RED);
  tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, ST77XX_BLUE);
  drawFrame();
  tft.setCursor(GREENBUTTON_X + 6 , GREENBUTTON_Y + (GREENBUTTON_H/2));
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(2);
  tft.println("ON");
  RecordOn = false;
}

void greenBtn()
{
  tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, ST77XX_GREEN);
  tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ST77XX_BLUE);
  drawFrame();
  tft.setCursor(REDBUTTON_X + 6 , REDBUTTON_Y + (REDBUTTON_H/2));
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(2);
  tft.println("OFF");
  RecordOn = true;
}

void setup(void)
{
  Serial.begin(115200);
  tft.init(320, 480);
  if (!ts.begin(40)) { 
    Serial.println("Unable to start touchscreen.");
  } 
  else { 
    Serial.println("Touchscreen started."); 
  }

  tft.fillScreen(ST77XX_BLACK);
  // origin = left,top landscape (USB left upper)
  tft.setRotation(1); 
  redBtn();
}

void loop()
{
  // See if there's any  touch data for us
  if (ts.touched())
  {   
    // Retrieve a point  
    TS_Point p = ts.getPoint(); 

  uint16_t tmp = p.x;
  int x = p.y;
  int y = tft.height() - tmp;


    if (RecordOn)
    {
      if((x > REDBUTTON_X) && (x < (REDBUTTON_X + REDBUTTON_W))) {
        if ((y > REDBUTTON_Y) && (y <= (REDBUTTON_Y + REDBUTTON_H))) {
          Serial.println("Red btn hit"); 
          redBtn();
        }
      }
    }
    else //Record is off (RecordOn == false)
    {
      if((x > GREENBUTTON_X) && (x < (GREENBUTTON_X + GREENBUTTON_W))) {
        if ((y > GREENBUTTON_Y) && (y <= (GREENBUTTON_Y + GREENBUTTON_H))) {
          Serial.println("Green btn hit"); 
          greenBtn();
        }
      }
    }

    Serial.println(RecordOn);
  }  
}

I then created a new App (Foo) in Applab and copied these sources into
sketch.ino. Note I edited the sketch.yaml as well to point to my modified
version of the ST77 library: like:

profiles:
  default:
    fqbn: arduino:zephyr:unoq
    platforms:
      - platform: arduino:zephyr
    libraries:
      - MsgPack (0.4.2)
      - DebugLog (0.8.4)
      - ArxContainer (0.7.0)
      - ArxTypeTraits (0.3.1)
      - dir: /home/arduino/libraries/Adafruit-ST7735-Library
      - dir: /home/arduino/libraries/BitBang_I2C
      - dependency: Adafruit BusIO (1.17.4)
      - Adafruit GFX Library (1.12.4)
      - FT6236G (1.0.0)

default_profile: default

It failed to build as I had not yet added the Adafruit_FT6206 library to the project.
Which I then did and then tried to run it again and it brought a lot of other libraries
and failed to build:

tarting app "foo"
Sketch profile configured: Name="default", Port=""
The library Adafruit BusIO has been automatically added from sketch project.
The library Adafruit FT6206 Library has been automatically added from sketch project.
The library Adafruit GFX Library has been automatically added from sketch project.
The library Adafruit ILI9341 has been automatically added from sketch project.
The library Adafruit SH110X has been automatically added from sketch project.
The library Adafruit ST7735 and ST7789 Library has been automatically added from sketch project.
The library Adafruit STMPE610 has been automatically added from sketch project.
The library Adafruit TSC2007 has been automatically added from sketch project.
The library Adafruit TouchScreen has been automatically added from sketch project.
The library ArxContainer has been automatically added from sketch project.
The library ArxTypeTraits has been automatically added from sketch project.
The library DebugLog has been automatically added from sketch project.
The library MsgPack has been automatically added from sketch project.
/home/arduino/.arduino15/internal/Adafruit_ILI9341_1.6.2_7e00cb0d7f19934d/Adafruit ILI9341/Adafruit_ILI9341.cpp:51:10: fatal error: pins_arduino.h: No such file or directory
51 | #include "pins_arduino.h"
|          ^~~~~~~~~~~~~~~~
compilation terminated.
exit status 1

In particular the Adafruit_ILI9341 library was installed, and has not yet been
modified to work with Zephyr.

Why did it do this? Because the Adafruit FT6206 Library says it depends on GFX and ILI9341 libraries. Note: their source files have no dependency on these, however their examples do. And the Adafruit_ILI9341 library says it depends on
STMPE610...

The issue is caused by how Applab is doing the library dependency processing.
It went ahead and tried to build the source files for ILI9341, yet nothing in our
simple project depends on it.

Note: So on other sketch I went to using the FT6236G library by Bitbank2, which
I needed to update a supporting library BitBang_I2C to run on Q (zephyr boards)
PR issued.

Not sure what to do here for the Adafruit library

Hi @KurtE.

This is the cause:

libraries specified on profiles are always imported and compiled, even if not referenced directly or indirectly by the sketch.
This reduces the number of "library discovery" passes and slightly improves compilation times.

[...]

Does this PR introduce a breaking change, and is titled accordingly?

It might introduce a breaking change. For example, if a library is listed in a sketch profile but not used in the sketch, after this update, the library will still be compiled, leading to a compilation failure.

Similar problem building a sketch for the Adafruit Quad Rotary Encoder board. The library name is "Adafruit seesaw Library". Some examples use Adafruit GFX and drivers but my short test program does not. arduino-cli compiles all libraries which results in "no pins_arduino.h" failure.

I deleted the three dependency lines for GFX, drivers, and SD which allows the sketch to compile. This also correctly describes what the simple sketch depends on.

profiles:
  default:
    fqbn: arduino:zephyr:unoq
    platforms:
      - platform: arduino:zephyr
    libraries:
      - dependency: Adafruit BusIO (1.17.4)
      - Adafruit seesaw Library (1.7.9)
      - dependency: Adafruit GFX Library (1.12.4)
      - dependency: Adafruit ST7735 and ST7789 Library (1.11.0)
      - dependency: SD (1.3.0)

default_profile: default
default_port: /dev/ttyHS1
default_port_config:
  baudrate: 115200

Side note today I submitted a PR on the issue for Adafruit_ili9341 library, which I verified on zephyr based Portenta h7

Maybe blacklist some libraries?

@ptillisch I can probably try to deduce it, but can a sketch know if it is being
compiled in Arduino IDE 2 versus App Lab? That is with this maybe the code
would do things conditionally...

There is no intentional mechanism that would allow this. I did some looking for an unintentional mechanism, but didn't find anything.

The significant difference between the two is that Arduino App Lab uploads the sketch with the "Flash mode" board option set to "RAM" (FQBN arduino:zephyr:unoq:flash_mode=ram):

Conversely, it is most likely that any Arduino IDE user will leave it at the default "Flash" setting.

However, this only affects the OpenOCD configuration used when uploading the compiled sketch binary. Furthermore, Arduino App Lab compiles the sketch in a separate operation, with FQBN set to the default arduino:zephyr:unoq, so there is no hope that this difference will have an effect at compile time (even if you modified the platform).

This approach breaks things multiple ways!

First off the messages I started off with. I submitted a PR to change
Adafruit_ILI9341library to not load that file if using zephyr so the build got
farther

It then had similar compile errors in the TouchScreen library. I locally edited
this file to also not include That file.

Now we get to link phase it errors out, with duplicate symbols and like:

/home/arduino/.arduino15/packages/zephyr/tools/arm-zephyr-eabi/0.16.8/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit STMPE610/Adafruit_STMPE610.cpp.o: in function `TS_Point::TS_Point()':
/home/arduino/.arduino15/internal/Adafruit_STMPE610_1.1.6_0f64aaf329b7d2b8/Adafruit STMPE610/Adafruit_STMPE610.cpp:357: multiple definition of `TS_Point::TS_Point()'; /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit FT6206 Library/Adafruit_FT6206.cpp.o:/home/arduino/.arduino15/internal/Adafruit_FT6206_Library_1.1.0_bc69d5fa46520035/Adafruit FT6206 Library/Adafruit_FT6206.cpp:238: first defined here
/home/arduino/.arduino15/packages/zephyr/tools/arm-zephyr-eabi/0.16.8/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit STMPE610/Adafruit_STMPE610.cpp.o: in function `TS_Point::TS_Point()':
/home/arduino/.arduino15/internal/Adafruit_STMPE610_1.1.6_0f64aaf329b7d2b8/Adafruit STMPE610/Adafruit_STMPE610.cpp:357: multiple definition of `TS_Point::TS_Point()'; /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit FT6206 Library/Adafruit_FT6206.cpp.o:/home/arduino/.arduino15/internal/Adafruit_FT6206_Library_1.1.0_bc69d5fa46520035/Adafruit FT6206 Library/Adafruit_FT6206.cpp:238: first defined here
/home/arduino/.arduino15/packages/zephyr/tools/arm-zephyr-eabi/0.16.8/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit STMPE610/Adafruit_STMPE610.cpp.o: in function `TS_Point::TS_Point(short, short, short)':
/home/arduino/.arduino15/internal/Adafruit_STMPE610_1.1.6_0f64aaf329b7d2b8/Adafruit STMPE610/Adafruit_STMPE610.cpp:368: multiple definition of `TS_Point::TS_Point(short, short, short)'; /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit FT6206 Library/Adafruit_FT6206.cpp.o:/home/arduino/.arduino15/internal/Adafruit_FT6206_Library_1.1.0_bc69d5fa46520035/Adafruit FT6206 Library/Adafruit_FT6206.cpp:249: first defined here
/home/arduino/.arduino15/packages/zephyr/tools/arm-zephyr-eabi/0.16.8/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit STMPE610/Adafruit_STMPE610.cpp.o: in function `TS_Point::TS_Point(short, short, short)':
/home/arduino/.arduino15/internal/Adafruit_STMPE610_1.1.6_0f64aaf329b7d2b8/Adafruit STMPE610/Adafruit_STMPE610.cpp:368: multiple definition of `TS_Point::TS_Point(short, short, short)'; /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit FT6206 Library/Adafruit_FT6206.cpp.o:/home/arduino/.arduino15/internal/Adafruit_FT6206_Library_1.1.0_bc69d5fa46520035/Adafruit FT6206 Library/Adafruit_FT6206.cpp:249: first defined here
/home/arduino/.arduino15/packages/zephyr/tools/arm-zephyr-eabi/0.16.8/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit STMPE610/Adafruit_STMPE610.cpp.o: in function `TS_Point::operator==(TS_Point)':
/home/arduino/.arduino15/internal/Adafruit_STMPE610_1.1.6_0f64aaf329b7d2b8/Adafruit STMPE610/Adafruit_STMPE610.cpp:378: multiple definition of `TS_Point::operator==(TS_Point)'; /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit FT6206 Library/Adafruit_FT6206.cpp.o:/home/arduino/.arduino15/internal/Adafruit_FT6206_Library_1.1.0_bc69d5fa46520035/Adafruit FT6206 Library/Adafruit_FT6206.cpp:261: first defined here
/home/arduino/.arduino15/packages/zephyr/tools/arm-zephyr-eabi/0.16.8/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit STMPE610/Adafruit_STMPE610.cpp.o: in function `TS_Point::operator!=(TS_Point)':
/home/arduino/.arduino15/internal/Adafruit_STMPE610_1.1.6_0f64aaf329b7d2b8/Adafruit STMPE610/Adafruit_STMPE610.cpp:386: multiple definition of `TS_Point::operator!=(TS_Point)'; /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit FT6206 Library/Adafruit_FT6206.cpp.o:/home/arduino/.arduino15/internal/Adafruit_FT6206_Library_1.1.0_bc69d5fa46520035/Adafruit FT6206 Library/Adafruit_FT6206.cpp:271: first defined here
/home/arduino/.arduino15/packages/zephyr/tools/arm-zephyr-eabi/0.16.8/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit TSC2007/Adafruit_TSC2007.cpp.o: in function `TS_Point::TS_Point()':
/home/arduino/.arduino15/internal/Adafruit_TSC2007_1.1.2_14d720b8bc33c43d/Adafruit TSC2007/Adafruit_TSC2007.cpp:156: multiple definition of `TS_Point::TS_Point()'; /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit FT6206 Library/Adafruit_FT6206.cpp.o:/home/arduino/.arduino15/internal/Adafruit_FT6206_Library_1.1.0_bc69d5fa46520035/Adafruit FT6206 Library/Adafruit_FT6206.cpp:238: first defined here
/home/arduino/.arduino15/packages/zephyr/tools/arm-zephyr-eabi/0.16.8/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit TSC2007/Adafruit_TSC2007.cpp.o: in function `TS_Point::TS_Point()':
/home/arduino/.arduino15/internal/Adafruit_TSC2007_1.1.2_14d720b8bc33c43d/Adafruit TSC2007/Adafruit_TSC2007.cpp:156: multiple definition of `TS_Point::TS_Point()'; /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit FT6206 Library/Adafruit_FT6206.cpp.o:/home/arduino/.arduino15/internal/Adafruit_FT6206_Library_1.1.0_bc69d5fa46520035/Adafruit FT6206 Library/Adafruit_FT6206.cpp:238: first defined here
/home/arduino/.arduino15/packages/zephyr/tools/arm-zephyr-eabi/0.16.8/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit TSC2007/Adafruit_TSC2007.cpp.o: in function `TS_Point::TS_Point(short, short, short)':
/home/arduino/.arduino15/internal/Adafruit_TSC2007_1.1.2_14d720b8bc33c43d/Adafruit TSC2007/Adafruit_TSC2007.cpp:167: multiple definition of `TS_Point::TS_Point(short, short, short)'; /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit FT6206 Library/Adafruit_FT6206.cpp.o:/home/arduino/.arduino15/internal/Adafruit_FT6206_Library_1.1.0_bc69d5fa46520035/Adafruit FT6206 Library/Adafruit_FT6206.cpp:249: first defined here
/home/arduino/.arduino15/packages/zephyr/tools/arm-zephyr-eabi/0.16.8/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit TSC2007/Adafruit_TSC2007.cpp.o: in function `TS_Point::TS_Point(short, short, short)':
/home/arduino/.arduino15/internal/Adafruit_TSC2007_1.1.2_14d720b8bc33c43d/Adafruit TSC2007/Adafruit_TSC2007.cpp:167: multiple definition of `TS_Point::TS_Point(short, short, short)'; /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit FT6206 Library/Adafruit_FT6206.cpp.o:/home/arduino/.arduino15/internal/Adafruit_FT6206_Library_1.1.0_bc69d5fa46520035/Adafruit FT6206 Library/Adafruit_FT6206.cpp:249: first defined here
/home/arduino/.arduino15/packages/zephyr/tools/arm-zephyr-eabi/0.16.8/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit TSC2007/Adafruit_TSC2007.cpp.o: in function `TS_Point::operator==(TS_Point)':
/home/arduino/.arduino15/internal/Adafruit_TSC2007_1.1.2_14d720b8bc33c43d/Adafruit TSC2007/Adafruit_TSC2007.cpp:177: multiple definition of `TS_Point::operator==(TS_Point)'; /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit FT6206 Library/Adafruit_FT6206.cpp.o:/home/arduino/.arduino15/internal/Adafruit_FT6206_Library_1.1.0_bc69d5fa46520035/Adafruit FT6206 Library/Adafruit_FT6206.cpp:261: first defined here
/home/arduino/.arduino15/packages/zephyr/tools/arm-zephyr-eabi/0.16.8/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit TSC2007/Adafruit_TSC2007.cpp.o: in function `TS_Point::operator!=(TS_Point)':
/home/arduino/.arduino15/internal/Adafruit_TSC2007_1.1.2_14d720b8bc33c43d/Adafruit TSC2007/Adafruit_TSC2007.cpp:185: multiple definition of `TS_Point::operator!=(TS_Point)'; /home/arduino/ArduinoApps/st7796-adafruit-cap-touch-paint/.cache/sketch/libraries/Adafruit FT6206 Library/Adafruit_FT6206.cpp.o:/home/arduino/.arduino15/internal/Adafruit_FT6206_Library_1.1.0_bc69d5fa46520035/Adafruit FT6206 Library/Adafruit_FT6206.cpp:271: first defined here
collect2: error: ld returned 1 exit status
exit status 1

My guess even if I had not run into this, it would have bloated the size of the binary, both with code and data.

It seems like it would have been better to limit the system only to the libraries explicitly listed in the build profile. It is a safe assumption that all those libraries are dependencies of the sketch.

There is no such guarantee that the same is true for the list of dependencies specified by each of those libraries (and the dependencies specified by those, and so on...) though. As you noted, it is common practice for library maintainers to specify as dependencies all libraries that are a dependency of the library's example sketches, even when the library's codebase has a dependency on it. Additionally, a dependency may be specified that is only included conditionally by the library (e.g., when compiling for specific boards, or when the library user utilizes application-specific header files of the library) it is needed for one specific use case of the library (e.g., compiling for certain boards). Doing either of these things is completely reasonable in the context of the only impact of the additional dependency being a few extra seconds of installation time, an occasional update from Library Manager, and some KB of hard drive space.

In order to make relevant information available to any who are interested in this subject, I'll share a link to the formal report @KurtE submitted to the Arduino CLI developers: