Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 16 of 16

Thread: __has_include(<SD.h>) how is it supposed to work?

  1. #1
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,565

    __has_include(<SD.h>) how is it supposed to work?

    I am playing around with some MTP stuff and trying to detect if the Sketch is using SD library or not... So __has_include...

    But I am getting strange results.... Or at least the feel strange to me... Short version.

    Suppose: For lack of anything I have a header file "XYZ.h"
    That just has:
    Code:
    #ifndef _XYZ_H_
    #define MTP_Storage_H
    #if defined(__has_include) && __has_include(<SD.h>)
    #pragma message " __has_include(<SD.h>"
    #include <SD.h>
    #endif
    #else
    #pragma message " NOT __has_include(<SD.h>"
    #endif
    Now suppose I have sketch (or library)... That has like:
    Code:
    #include "XYZ.h"
    
    void setup() {
      // put your setup code here, to run once:
      while(!Serial) ;
      Serial.begin(115200);
      delay(500);
      Serial.println("Test for include file");
      #ifdef BUILTIN_SDCARD
      Serial.printf("BUILTIN_SDCARD defined %u\n", BUILTIN_SDCARD);
      #else
      Serial.println("BUILTIN_SDCARD NOT defined");
      #endif
    
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    }
    As expected on the T4.1, it
    Prints out that is not defined...

    However if you instead do:
    Code:
    #include "XYZ.h"
    #include <SD.h>
    
    void setup() {
      // put your setup code here, to run once:
      while(!Serial) ;
      Serial.begin(115200);
      delay(500);
      Serial.println("Test for include file");
      #ifdef BUILTIN_SDCARD
      Serial.printf("BUILTIN_SDCARD defined %u\n", BUILTIN_SDCARD);
      #else
      Serial.println("BUILTIN_SDCARD NOT defined");
      #endif
    
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    }
    It still prints "BUILTIN_SDCARD NOT defined"
    I am confused.

    However if instead you do:
    Code:
    #include <SD.h>
    #include "XYZ.h"
    
    void setup() {
      // put your setup code here, to run once:
      while(!Serial) ;
      Serial.begin(115200);
      delay(500);
      Serial.println("Test for include file");
      #ifdef BUILTIN_SDCARD
      Serial.printf("BUILTIN_SDCARD defined %u\n", BUILTIN_SDCARD);
      #else
      Serial.println("BUILTIN_SDCARD NOT defined");
      #endif
    
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    }
    It works as expected

    So what is going on in the second case?

  2. #2
    Senior Member
    Join Date
    Jul 2014
    Posts
    3,451
    is the "__has_include("file.h") not testing if "file.h" CAN be included and not if it is included by the sketch?

    gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html :
    "The special operator __has_include (operand) may be used in ‘#if’ and ‘#elif’ expressions to test whether the header referenced by its operand can be included using the ‘#include’ directive. "

  3. #3
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,028
    That is a good ref @WMXZ : gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html#g_t_005f_005fhas_00 5finclude

    @Kurt - hopefully this link goes there as used that is not portable when has_include isn't supported

    Also it seems to work indicated and not as desired in that test?

  4. #4
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    Your xyz.h looks broken.
    Code:
    #ifndef _XYZ_H_
    #    define MTP_Storage_H
    #    if defined(__has_include) && __has_include(<SD.h>)
    #        pragma message " __has_include(<SD.h>"
    #        include <SD.h>
    #    endif
    #else
    #    pragma message " NOT __has_include(<SD.h>"
    #endif
    Maybe you meant something like
    Code:
    #ifndef _XYZ_H_
    #    define MTP_Storage_H
    #    if defined(__has_include) && __has_include(<SD.h>)
    #        pragma message " __has_include(<SD.h>"
    #    else
    #        pragma message " NOT __has_include(<SD.h>"
    #        include <SD.h>
    #    endif
    #endif
    Anyway, this does not fix your issue.

    To me it looks like the Arduino "library finder" (don't know the official name for the thing) only identifies <sd.h> as a library when #include <sd.h> appears before any other use of <sd.h>. Otherwise it interprets sd.h as just another header to include. This code shows the effect more directly:
    Code:
    #if defined(__has_include) && __has_include(<SD.h>)
    #endif
    
    #include <SD.h>
    
    void setup() {
      // put your setup code here, to run once:
      while(!Serial) ;
      Serial.begin(115200);
      delay(500);
      Serial.println("Test for include file");
      #ifdef BUILTIN_SDCARD
      Serial.printf("BUILTIN_SDCARD defined %u\n", BUILTIN_SDCARD);
      #else
      Serial.println("BUILTIN_SDCARD NOT defined");
      #endif
    
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    }
    If you comment/uncomment the first two lines and look at the compile output you see that it identifies/not identifies SD.h as library. It looks like in the second case it even ignores the #include <SD.h> completely. Because, without setting up the library paths, the compiler shouldn't even find sd.h? I suspect that this is a bug in the library detection/ preparsing stuff of the IDE.

    Edit: I tried this now with VisualTeensy which does not do any automatic library detection. Looks the has_include(<SD.h>) makes the compiler ignore the next #include of the same header completely.

    This compiles (but doesn't include SD.h)
    Code:
    #if defined __has_include
    #    if __has_include(<SD.h>)
    #        include <SD.h>
    #    endif
    #endif
    
    #include <SD.h>
    ....
    This generates a "sd.h not found" compiler error as expected (note the changed capitalization of sd.h (Windows files are not case sensitive))
    Code:
    #if defined __has_include
    #    if __has_include(<SD.h>)
    #        include <SD.h>
    #    endif
    #endif
    
    #include <sd.h>
    ....
    Maybe that's a feature? If one checked for the existence of sd.h and if it doesn't exist the compiler ignores trying to #include the same file? Weird indeed ...
    This also explains why the Arduino IDE doesn't interpret SD.h as library of course...
    Last edited by luni; 06-23-2022 at 05:57 AM.

  5. #5
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,028
    @luni I started a reply like yours ... if not there then #else bring it in, but did a refresh and saw the @WMXZ note that the has_include doesn't seem to perform the desired test?

  6. #6
    Senior Member
    Join Date
    Jul 2014
    Posts
    3,451
    my reply was triggered by
    trying to detect if the Sketch is using SD library or not... So __has_include...
    (emphasis my me)
    but may KurtE was intending something different

  7. #7
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,028
    Quote Originally Posted by WMXZ View Post
    my reply was triggered by
    (emphasis my me)
    but may KurtE was intending something different
    That's how I read it as AFAIK it would make sense in context to help with sorting FS coding issues.

  8. #8
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    Question is what does "is using SD library" actually mean? IMHO, the only thing you can detect with __has_include is, if the build sytem added the corresponding -Ipath/to/the/lib directives to the compiler call? Maybe Kurt can expand on the actual use case?

  9. #9
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,565
    Sorry, I think my example may be too convoluted. let me get to the real one.

    I am trying to make MTP_Teensy, automatically add support to detect if an SD card was inserted or removed from the slot...
    So Suppose, in MTP_Storage.h I add:
    Code:
    #if defined(__has_include) && __has_include(<SD.h>)
    #include <SD.h>
    #endif
    Which is included by MTP_Teensy.h

    Now suppose in MTP_Teensy.h I have:
    Code:
    #if defined(__SD_H__)
      uint32_t addFilesystem(SDClass &disk, const char *diskname);
      #endif
      uint32_t addFilesystem(FS &disk, const char *diskname);
    Now suppose I had a really simple SD example for MTP... I removed stuff from the current simple example 3 down to basics:
    Code:
    #include <SD.h>
    #include <MTP_Teensy.h>
    
    #define CS_SD BUILTIN_SDCARD  // Works on T_3.6 and T_4.1
    //#define CS_SD 10  // Works on SPI with this CS pin
    void setup()
    {
      // mandatory to begin the MTP session.
      MTP.begin();
    
      // Add SD Card
      SD.begin(CS_SD);
      MTP.addFilesystem(SD, "SD Card");
    }
    
    void loop() {
      MTP.loop();  //This is mandatory to be placed in the loop code.
    }
    This builds and runs.
    However this one fails to build:
    Code:
    #include <MTP_Teensy.h>
    #include <SD.h>
    
    #define CS_SD BUILTIN_SDCARD  // Works on T_3.6 and T_4.1
    //#define CS_SD 10  // Works on SPI with this CS pin
    void setup()
    {
      // mandatory to begin the MTP session.
      MTP.begin();
    
      // Add SD Card
      SD.begin(CS_SD);
      MTP.addFilesystem(SD, "SD Card");
    }
    
    void loop() {
      MTP.loop();  //This is mandatory to be placed in the loop code.
    }
    Code:
    C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy\examples\Simplified Examples\Example_3_simple_SD\Example_3_simple_SD.ino: In function 'void setup()':
    C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy\examples\Simplified Examples\Example_3_simple_SD\Example_3_simple_SD.ino:12:3: error: 'SD' was not declared in this scope
       SD.begin(CS_SD);
       ^
    C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy\examples\Simplified Examples\Example_3_simple_SD\Example_3_simple_SD.ino:4:15: error: 'BUILTIN_SDCARD' was not declared in this scope
     #define CS_SD BUILTIN_SDCARD  // Works on T_3.6 and T_4.1
                   ^
    C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy\examples\Simplified Examples\Example_3_simple_SD\Example_3_simple_SD.ino:12:12: note: in expansion of macro 'CS_SD'
       SD.begin(CS_SD);
                ^
    Using library MTP_Teensy at version 1.0.0 in folder: C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy 
    exit status 1

  10. #10
    Senior Member
    Join Date
    Jul 2014
    Posts
    3,451
    Kurt,
    Do I understand it correctly, you wanted to detect at compile time if the user inserts/removes a uSD card?
    I am trying to make MTP_Teensy, automatically add support to detect if an SD card was inserted or removed from the slot...

  11. #11
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,565
    OK, I think I know what is going on...

    It is Arduino's fault! (I think)

    A few hints on it, with the build that works, the build output looks like:
    Code:
    "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-tools\\1.56.53/precompile_helper" "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53/cores/teensy4" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino" "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-compile\\1.56.1/arm/bin/arm-none-eabi-g++" -x c++-header -O2 -g -Wall -ffunction-sections -fdata-sections -nostdlib -MMD -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10600 -DARDUINO_TEENSY41 -DF_CPU=600000000 -DUSB_MTPDISK -DLAYOUT_US_ENGLISH "-IC:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53/cores/teensy4" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino/pch/Arduino.h" -o "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino/pch/Arduino.h.gch"
    Using previously compiled file: C:\Users\kurte\AppData\Local\Temp\arduino_build_Example_3_simple_SD.ino\pch\Arduino.h.gch
    "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-compile\\1.56.1/arm/bin/arm-none-eabi-g++" -c -O2 -g -Wall -ffunction-sections -fdata-sections -nostdlib -MMD -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10600 -DARDUINO_TEENSY41 -DF_CPU=600000000 -DUSB_MTPDISK -DLAYOUT_US_ENGLISH "-IC:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino/pch" "-IC:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53\\cores\\teensy4" "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\SD\\src" "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\SdFat\\src" "-IC:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53\\libraries\\SPI" "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\MTP_Teensy\\src" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino\\sketch\\Example_3_simple_SD.ino.cpp" -o "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino\\sketch\\Example_3_simple_SD.ino.cpp.o"
    
    ...
    teensy_size: Memory Usage on Teensy 4.1:
    teensy_size:   FLASH: code:84868, data:11252, headers:8324   free for files:8022020
    teensy_size:    RAM1: variables:13760, code:82184, padding:16120   free for local variables:412224
    teensy_size:    RAM2: variables:17504  free for malloc/new:506784
    Multiple libraries were found for "SdFat.h"
     Used: C:\Users\kurte\Documents\Arduino\libraries\SdFat
     Not used: C:\Users\kurte\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.56.53\libraries\SdFat
    Multiple libraries were found for "SD.h"
     Used: C:\Users\kurte\Documents\Arduino\libraries\SD
     Not used: C:\arduino-1.8.19\libraries\SD
     Not used: C:\Users\kurte\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.56.53\libraries\SD
    Using library SD at version 2.0.0 in folder: C:\Users\kurte\Documents\Arduino\libraries\SD 
    Using library SdFat at version 2.1.2 in folder: C:\Users\kurte\Documents\Arduino\libraries\SdFat 
    Using library SPI at version 1.0 in folder: C:\Users\kurte\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.56.53\libraries\SPI 
    Using library MTP_Teensy at version 1.0.0 in folder: C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy 
           upload@7819620-Teensy  Uploading to board '7819620-Teensy' (Teensy 4.1)
           upload@7819620-Teensy  Triggering board reboot
           upload@7819620-Teensy  Waiting for Teensy Loader
    [Finished in 24.0s]
    A couple of interesting points:
    1) The Using library... code says:
    Code:
    Using library SD at version 2.0.0 in folder: C:\Users\kurte\Documents\Arduino\libraries\SD 
    Using library SdFat at version 2.1.2 in folder: C:\Users\kurte\Documents\Arduino\libraries\SdFat 
    Using library SPI at version 1.0 in folder: C:\Users\kurte\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.56.53\libraries\SPI 
    Using library MTP_Teensy at version 1.0.0 in folder: C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy
    2) Look at the -I in the build.
    Code:
    "-IC:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino/pch"
    "-IC:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53\\cores\\teensy4"
    "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\SD\\src" 
    "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\SdFat\\src" 
    "-IC:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53\\libraries\\SPI"
    "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\MTP_Teensy\\src"
    Now look at the build that failed:
    Code:
    Building Sketch: ".\Example_3_simple_SD.ino"
    Using board 'teensy41' from platform in folder: C:\Users\kurte\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.56.53
    Using core 'teensy4' from platform in folder: C:\Users\kurte\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.56.53
    Detecting libraries used...
    "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-compile\\1.56.1/arm/bin/arm-none-eabi-g++" -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10600 -DARDUINO_TEENSY41 -DF_CPU=600000000 -DUSB_MTPDISK -DLAYOUT_US_ENGLISH "-IC:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53\\cores\\teensy4" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino\\sketch\\Example_3_simple_SD.ino.cpp" -o nul
    Alternatives for MTP_Teensy.h: [MTP_Teensy@1.0.0]
    ResolveLibrary(MTP_Teensy.h)
      -> candidates: [MTP_Teensy@1.0.0]
    "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-compile\\1.56.1/arm/bin/arm-none-eabi-g++" -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10600 -DARDUINO_TEENSY41 -DF_CPU=600000000 -DUSB_MTPDISK -DLAYOUT_US_ENGLISH "-IC:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53\\cores\\teensy4" "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\MTP_Teensy\\src" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino\\sketch\\Example_3_simple_SD.ino.cpp" -o nul
    "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-compile\\1.56.1/arm/bin/arm-none-eabi-g++" -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10600 -DARDUINO_TEENSY41 -DF_CPU=600000000 -DUSB_MTPDISK -DLAYOUT_US_ENGLISH "-IC:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53\\cores\\teensy4" "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\MTP_Teensy\\src" "C:\\Users\\kurte\\Documents\\Arduino\\libraries\\MTP_Teensy\\src\\MTP_SD_Callbacks.cpp" -o nul
    "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-compile\\1.56.1/arm/bin/arm-none-eabi-g++" -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10600 -DARDUINO_TEENSY41 -DF_CPU=600000000 -DUSB_MTPDISK -DLAYOUT_US_ENGLISH "-IC:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53\\cores\\teensy4" "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\MTP_Teensy\\src" "C:\\Users\\kurte\\Documents\\Arduino\\libraries\\MTP_Teensy\\src\\MTP_Storage.cpp" -o nul
    "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-compile\\1.56.1/arm/bin/arm-none-eabi-g++" -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10600 -DARDUINO_TEENSY41 -DF_CPU=600000000 -DUSB_MTPDISK -DLAYOUT_US_ENGLISH "-IC:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53\\cores\\teensy4" "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\MTP_Teensy\\src" "C:\\Users\\kurte\\Documents\\Arduino\\libraries\\MTP_Teensy\\src\\MTP_Teensy.cpp" -o nul
    Generating function prototypes...
    "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-compile\\1.56.1/arm/bin/arm-none-eabi-g++" -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10600 -DARDUINO_TEENSY41 -DF_CPU=600000000 -DUSB_MTPDISK -DLAYOUT_US_ENGLISH "-IC:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53\\cores\\teensy4" "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\MTP_Teensy\\src" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino\\sketch\\Example_3_simple_SD.ino.cpp" -o "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino\\preproc\\ctags_target_for_gcc_minus_e.cpp"
    "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\builtin\\tools\\ctags\\5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino\\preproc\\ctags_target_for_gcc_minus_e.cpp"
    Compiling sketch...
    "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-tools\\1.56.53/precompile_helper" "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53/cores/teensy4" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino" "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-compile\\1.56.1/arm/bin/arm-none-eabi-g++" -x c++-header -O2 -g -Wall -ffunction-sections -fdata-sections -nostdlib -MMD -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10600 -DARDUINO_TEENSY41 -DF_CPU=600000000 -DUSB_MTPDISK -DLAYOUT_US_ENGLISH "-IC:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53/cores/teensy4" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino/pch/Arduino.h" -o "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino/pch/Arduino.h.gch"
    Using previously compiled file: C:\Users\kurte\AppData\Local\Temp\arduino_build_Example_3_simple_SD.ino\pch\Arduino.h.gch
    "C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-compile\\1.56.1/arm/bin/arm-none-eabi-g++" -c -O2 -g -Wall -ffunction-sections -fdata-sections -nostdlib -MMD -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=157 -DARDUINO=10600 -DARDUINO_TEENSY41 -DF_CPU=600000000 -DUSB_MTPDISK -DLAYOUT_US_ENGLISH "-IC:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino/pch" "-IC:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53\\cores\\teensy4" "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\MTP_Teensy\\src" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino\\sketch\\Example_3_simple_SD.ino.cpp" -o "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_Example_3_simple_SD.ino\\sketch\\Example_3_simple_SD.ino.cpp.o"
    C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy\examples\Simplified Examples\Example_3_simple_SD\Example_3_simple_SD.ino: In function 'void setup()':
    C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy\examples\Simplified Examples\Example_3_simple_SD\Example_3_simple_SD.ino:12:3: error: 'SD' was not declared in this scope
       SD.begin(CS_SD);
       ^
    C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy\examples\Simplified Examples\Example_3_simple_SD\Example_3_simple_SD.ino:4:15: error: 'BUILTIN_SDCARD' was not declared in this scope
     #define CS_SD BUILTIN_SDCARD  // Works on T_3.6 and T_4.1
                   ^
    C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy\examples\Simplified Examples\Example_3_simple_SD\Example_3_simple_SD.ino:12:12: note: in expansion of macro 'CS_SD'
       SD.begin(CS_SD);
                ^
    Using library MTP_Teensy at version 1.0.0 in folder: C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy 
    exit status 1
    [Finished in 11.5s]
    Again hints:
    1) Notice it only mentions MTP at end, it does not mention SD or SDFat
    Code:
       SD.begin(CS_SD);
       ^
    C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy\examples\Simplified Examples\Example_3_simple_SD\Example_3_simple_SD.ino:4:15: error: 'BUILTIN_SDCARD' was not declared in this scope
     #define CS_SD BUILTIN_SDCARD  // Works on T_3.6 and T_4.1
                   ^
    C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy\examples\Simplified Examples\Example_3_simple_SD\Example_3_simple_SD.ino:12:12: note: in expansion of macro 'CS_SD'
       SD.begin(CS_SD);
                ^
    Using library MTP_Teensy at version 1.0.0 in folder: C:\Users\kurte\Documents\Arduino\libraries\MTP_Teensy 
    exit status 1
    [Finished in 11.5s]
    2) command lines -Is
    Code:
    "-IC:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.56.53\\cores\\teensy4" 
    "-IC:\\Users\\kurte\\Documents\\Arduino\\libraries\\MTP_Teensy\\src"
    So sure enough it does not find SD.h

  12. #12
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    8,240
    Been experimenting after and during Kurt's post. The issue is definitely in MTP_Storage.h and use of the has_include. For instance (after some trial and error) I just did this:
    Code:
    //#if defined(__has_include) && !(__has_include(<SD.h>)
    #include <SD.h>
    //#endif
    It compiles and runs as it should and identifies when the cards are removed.

    Test 2. If I remove the specifying to use SD.h and wrap the appropriate functions in
    Code:
    #if defined(__SD_H__)
    It compiles and runs but those functions are not visible.

    Wondering to self is since MTP_Storage is (pardon my terminology here) third level its not seeing whats in the sketch only MTP_Teensy is, my thought:
    Sketch ->MTP_Teensy -> MTP_Storage

    Dont know - does this make sense?

  13. #13
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,565
    It might work... as long as the implementation for it is within the .h file... Although maybe would still work
    if the __has_include_ is not in the .h file but in the couple of .cpp files that rely on it.

    Might try that.
    In the mean time, I thought I would mention it to Arduino, so:
    https://github.com/arduino/arduino-cli/issues/1782

    Edit: I think it would build... But it would not get the functionality... I could be wrong:
    That is if MTP.h was included first, then the #if defined(__SD_H__)
    will be false, so then it will simply fall through and use the generic FS* version
    (I think)

  14. #14
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    @Kurt, I don't know if you read #4.
    I also thought that this is an Arduino issue first, but it turned out (see Edit in #4) that GCC is simply ignoring the #include after the __has_include. Thus Arduino never sees the #include <sd.h> which leads to not detecting the lib. At least this is how I interpreted the weird results
    Last edited by luni; 06-23-2022 at 04:05 PM.

  15. #15
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,565
    Quote Originally Posted by luni View Post
    @Kurt, I don't know if you read #4.
    I also thought that this is an Arduino issue first, but it turned out (see Edit in #4) that GCC is simply ignoring the #include after the __has_include. Thus Arduino never sees the #include <sd.h> which leads to detect the lib. At least this is how I interpreted the weird results
    I read it... But it did not fully register...

    On the Issue, I created on CLI... matthijskooijman commented 24 minutes ago
    This is unfortunately a gcc bug, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80753

    The Arduino build relies on error messages for missing includes to autodetect the libraries that are used. However, the gcc bug means that if you use _has_include() on a header that is not available (like SD.h in your breaking example), then gcc will not emit an error message when the file is later included unconditionally, so arduino-cli never finds out that SD.h is needed.

    The only workaround I know about is what you already showed: Make sure SD.h is included before the _has_include(). A proper fix must be done in gcc, but there's no real movement there, unfortunately.
    So I don't think this approach will work as transparent as I was hoping for.

  16. #16
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    Yes, __has_include works nicely for the standard use case (I'm using it for the TeensyTimerTool)

    Code:
    #if defined __has_include
    #    if __has_include("optional.h")
    #        include "optional.h"
    #    else
    #        include "default.h"
    #endif
    but not for more exotic uses

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •