How to select a specific version of a library

When I get something like this, how do I tell the compiler which version of the library to use?
(Not sure whether this is a programming or IDE question...)

/tmp/cctS178T.s: Assembler messages:
/tmp/cctS178T.s:37: Error: bad instruction `jmp 0'
/tmp/cctS178T.s:3780: Error: bad instruction `jmp 0'
/tmp/cctS178T.s:4818: Error: bad instruction `jmp 0'
Multiple libraries were found for "SdFat.h"
  Used: /mnt/ntfs/Data/Data/Programming/Arduino/libraries/SdFat
  Not used: /home/johnc/.arduino15/packages/teensy/hardware/avr/1.59.0/libraries/SdFat
exit status 1

Compilation error: exit status 1

Also, are the assembler messages related, or some other problem?
The board selected is Teensy 4.1.

You can only have one version of a library installed at any one time. So go to the library manager in the IDE and search for the library you want. When you find it then there is an option to change the version you want to use.

The assembler error messages are for the code in the .s file, and have nothing to do with the SdFat library.

Those two SdFat libraries are probably the same, so you could delete one of them.

Always post the complete code that demonstrates the problem, using code tags.

There is only one version of the library that has actually been installed and I am aware that I can choose (e.g. revert to a previous) the version. However, I think the problem here is that the Teensy board package has installed its own version.

I cannot remove the generic library installed in ./Arduino/libraries/SdFat because it is needed to compile for other Arduino AVR boards such as the Mega2560 or MightyCore 1284.

On the other hand, this library does not work for the Teensy 4/4.1. Possibly the version supplied with the Teensy package (which is slightly older) has been modified to work with Teensy. I need to test this and I guess deleting (or at least temporarily moving) the generic library would prove this one way or the other, but its definitely not a desirable solution.

The ide should be choosing the version of the library in the board package. Something might be corrupted, and reloading the Teensyduino package for the Teensy 4/4.1 might help.

Well, moving the generic/independent version of the library does result in the message about the duplicate library no longer appearing, but the assembler error is still present. It obviously doesn't matter which version of the SdFat library is used.

Turns out that the assembler error is related to my use of typedef FsFile File. Out of interest, what is a .s file?

The problem does seem to be related to the Teensy board package and maybe compatibility with the SdFat library. The sketch compiles without error or warning for the Mega2560 and MightyCore 1284. I did find this which might explain some things:

There is some mention of name clashes with the term 'File' so I created my own typedef FsFile MyFile to use instead of File. Again, this works for the Mega2560 and MightyCore 1284, but I still get the same assembler error when I switch to the Teensy.

Since the original library works for the Mega and MightyCore boards, this must be OK. I therefore removed and re-loaded the Teensy board package as per the suggestion from cattledog, but no change.

One of the posts in the above link mentions an SdFat wrapper for the Teensy. I am just in the process off reading the remainder of the discussion. Just for reference, the current version of the Teensy package is 1.59.0.

Hi @BitSeeker.

It looks like you have determined that this may not actually be needed in this case, but I think it is a generally interesting question, so I'll go ahead and answer anyway.

Background

Arduino IDE has a "library discovery" system. For each #include directive in the program being compiled, the IDE first checks to see if the file is present in the the compiler's "search path". If not, it then searches through the root source folder of each of the installed libraries to look for a file of that name.

Sometimes multiple libraries contain a file matching the #include directive. In this case, Arduino IDE must decide which of the libraries to use. It has a sophisticated algorithm for picking the best library so it usually makes the right decision, but not always.

In this case, Arduino IDE is discovering the library for the sketch's #include <BLEDevice.h> directive and found that two libraries contain a header file matching the name specified by the directive. The algorithm caused it to chose the library that is installed in your sketchbook folder, at this path:

/mnt/ntfs/Data/Data/Programming/Arduino/libraries/SdFat

over the alternative that is bundled with the "Teensy" boards platform, at this path:

/home/johnc/.arduino15/packages/teensy/hardware/avr/1.59.0/libraries/SdFat

Solution

As was already mentioned, the most simple solution would be to uninstall the "SdFat" library installation from the sketchbook folder. However, since you need that installation for other projects that is not an acceptable solution.

In this case the solution will be to influence the library discovery system to chose the library bundled with the "Teensy" platform over the one in the sketchbook folder.

As I mentioned before, files from the include search path are always given priority by the library discovery system. Once a library is "discovered", its path is added to the include search path. So if we can cause the platform bundled library to be discovered before Arduino IDE does discovery for the ambiguous SdFat.h file, then it will not discover the library in the sketchbook folder. This is accomplished by placing an #include directive for a file unique to the "Teensy" platform's bundled library above the ambiguous #include directive.

In some cases we are fortunate enough to find that the target library already contains a uniquely named header file suitable for this usage. Unfortunately there is no such file in the platform bundled library. So in this case it will be necessary for you to add such a file to the library. You might name it something like Teensy_SdFat.h

It would be sufficient to simply add an empty file to the library. However, it will be a good idea to add a comment to the file to help you to understand its obscure purpose in case you chance to be looking at some point point in the future when you no longer recall the exact reason for adding it. Something like this:

/*
  This file allows the library to be given priority over the globally installed "SdFat" library by the Arduino library
  discovery system:
  https://forum.arduino.cc/t/how-to-select-a-specific-version-of-a-library/1383714

  This file is intentionally left empty.
*/

For further convenience, you can add an #include directive to the new file for the library's header file so that this file can be used as a substitute for the primary header filename in the #include directive instead of only a supplement:

/*
  This file allows the library to be given priority over the globally installed "SdFat" library by the Arduino library
  discovery system:
  https://forum.arduino.cc/t/how-to-select-a-specific-version-of-a-library/1383714

  This file is intentionally left empty.
*/

#include "SdFat.h"

Place the file in the folder at this path on your hard drive:

/home/johnc/.arduino15/packages/teensy/hardware/avr/1.59.0/libraries/SdFat

Now in your code that depends on the "Teensy" platform's bundled "SdFat" library, add this #include directive:

#include <Teensy_SdFat.h>

(adjust the directive if you chose a different name for the file you added)

If you added an #include "SdFat.h" directive to the Teensy_SdFat.h file as I described above, you can replace the #include directive for SdFat.h with the one for Teensy_SdFat.h. If you did not add an #include directive to Teensy_SdFat.h, then you must place it on a line at some point before the #include directive for SdFat.h in your code.

Now when you compile the sketch you should see from the compilation output that the platform bundled library was used.

When all other factors are equal, the library discovery system is designed to give higher priority to the libraries that are installed in the sketchbook folder:

https://arduino.github.io/arduino-cli/latest/sketch-build-process/#location-priority

The reason for this is to allow the user to use modified versions of the platform bundled libraries.

The .s file extension (or more canonically .S) is used for files that contain code written in assembly language.

Thank you for the detailed explanation. Just to prove the point made by cattledog, I commented out the storage related bits of the code and am still getting the assembler error, so that error is not related to the SdFat library but something else. Need to figure out what.....

Then ask them on the Teensy Forum:-

Teensy Forum

That's a fair point and I didn't realise there was a Teensy forum yet, but I may just do that. I sat up until 3.00am last night trying to figure out the assembly file error - trying commenting stuff out and various other things - and got nowhere. I also tried compiling another working project - this one does not use the SD library - but ran into similar problems. Again, the project compiles fine for other boards.

The example projects seem to compile fine though, so it must be something else I am doing in my two projects that has some kind of compatibility issue with the Teensy.

I might have go at compiling for Teensy in the PlatformIO environment on Vscode to see whether I get the same problem and if I do whether it gives me more detail. The next step after that will probably need to be to reach out on the Teensy forum as suggested.

What would help is if you can post cade which is a minimal example and produces the error message. This simplified example code which fails to compile would also help if you post on the Teensy forum.

I understand the request, but since I don't have any idea what might be causing the problem, I don't know what would need to be included in the smaller sketch in order to replicate the problem. The Teensy examples provided in the IDE and basic sketches like blink seem to compile just fine.

I tried compiling in Vscode/sPlatformIO but it tells me that the Arduino framework is not supported on this board. Yet, we have a board package and example sketches in the Arduino IDE ???

I would be happy to oblige with an example sketch if I could figure one out that replicates the problem! All I can say for now is: I am working on it!

If you are serious about reliable storage of data on SD cards, SdFat is not the way to go.

I gave up on SdFat years ago, as it is orders of magnitude less reliable than the extremely well debugged file handling system built into tiny linux systems, like the Pi Zero W and other variants.

At the half the price of the Teensy 4.1, you get a mature compiler/debugger/file system, along with other standard linux utilities, and a vast array of open source code for advanced applications.

I found it! :alien_monster::alien_monster::alien_monster:

It was a matter of cutting out one logical function at a time from the code until I hit a point where the project finally compiled successfully. It took a bit of time, but eventually I did arrive at the function that was causing the problem. In my sketch (both of the ones I tested actually) I have a function that resets the MCU. Different MCUs require different reset code so there is an #if defined .. #elif defined() ...#endif clause that selects the correct option for a number of boards including, AVR, ESP and RP2040. I needed to add an #if defined() section to select the appropriate reset code for the Teensy platform. In the event, the code was just dropping through to the default AVR code which includes a jmp(0) instruction.

Once identified, I added a fix on both sketches and test compiled them. They now compile successfully. I still need to test on an actual board though.

I also still have the SdFat library selection problem, so next I am going to have a look at the solution proposed by ptillisch.

I did encounter some reliability problems with an early version of the SdFat library, but for most part, later versions seem to work fine. Working with it was something of an imposed choice though. Its a project that I have been collaborating with someone else on. I did suggest a Pico actually, which is also much cheaper and also has plenty of pins and I do have a working example of the project code using it. However, like the Zero W, there is the problem of interfacing a 3.3V chip with a 5V legacy environment. I have actually had the Pico connected to a 5V bus for test purposes, which is how I was able to continue development of a working example and fortunately it is still working, so they do appear to be reasonably robust, but ideally there does need to be some form of protection/buffering in-between.

The Teensy is also 3.3V board, but unlike the RP2040 and RP2350, the datasheet does indicate that it is 5V tolerant. The downside, as you point out, is the cost. I am actually a bit hesitant to buy the board for that reason so I can imagine others thinking the same. Besides, for that price, I would be rather more upset if it got toasted!

I might consider developing a MicroPython version, but would need to solve the 3.3V to 5V conversion dilema. I have tried a couple of level shifter chips without much success so far.

What problem is this? All Arduino chips capable of running Micro python are 3V3 in the first place.

True, but for this particular application, the GPIO pins would need to interface with a legacy bus that runs at 5V.

I tried this and it worked as described. Thank you.

You are welcome. I'm glad if I was able to be of assistance.

Regards, Per