SdFat icon indicating copy to clipboard operation
SdFat copied to clipboard

"one declaration" rule broken with USE_DEDICATED_SPI=0

Open samy opened this issue 4 years ago • 4 comments

Hi In my project I tried to use the USE_DEDICATED_SPI=0 setting to reduce memory usage (and I have other SPI devices in the project) But each time I compile I have errors about C++ "One Declaration" rule broken (about SdSpiCard class) Do you have any idea ?

I can post the full project source code if needed

Thanks

samy avatar Oct 18 '21 07:10 samy

I can' do anything without the code. Also I need a description of your hardware.

Try running this program. It compiles and runs on my hardware. Be sure to edit SdfatConfig.h and set ENABLE_DEDICATED_SPI zero like this.

#ifndef ENABLE_DEDICATED_SPI
#if defined(__AVR__) && FLASHEND < 0X8000
// 32K AVR boards.
#define ENABLE_DEDICATED_SPI 0  // <------- Edit Here
#else  // defined(__AVR__) && FLASHEND < 0X8000
// All other boards.
#define ENABLE_DEDICATED_SPI 0  //<--------- Edit Here
#endif  // defined(__AVR__) && FLASHEND < 0X8000
#endif  // ENABLE_DEDICATED_SPI

Edit SD_CS_PIN for your hardware.

#include "SdFat.h"

#if ENABLE_DEDICATED_SPI
#error "Edit SdFatConfig.h and set ENABLE_DEDICATED_SPI zero"
#endif

SdFat sd;
#define SD_CS_PIN 10  // use your Chip Select pin
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(8))

void setup() {
  Serial.begin(9600);
  while(!Serial) {}
  Serial.println("Type any character to begin");
  while (!Serial.available()) {}
  if (!sd.begin(SD_CONFIG)) {
    sd.initErrorHalt(&Serial);
  }
  Serial.println("Success");
}

void loop() {}

greiman avatar Oct 18 '21 11:10 greiman

Rather than editing SdFatConfig.h , would it not work correctly to define ENABLE_DEDICATED_SPI? In other words:

#define ENABLE_DEDICATED_SPI 0  // <-- this line
#include "SdFat.h"

#if ENABLE_DEDICATED_SPI
#error "Edit SdFatConfig.h and set ENABLE_DEDICATED_SPI zero"
#endif

SdFat sd;
#define SD_CS_PIN 10  // use your Chip Select pin
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(8))

void setup() {
  Serial.begin(9600);
  while(!Serial) {}
  Serial.println("Type any character to begin");
  while (!Serial.available()) {}
  if (!sd.begin(SD_CONFIG)) {
    sd.initErrorHalt(&Serial);
  }
  Serial.println("Success");
}

void loop() {}

Assuming this is a valid way to evaluate the ENABLE_DEDICATED_SPI flag, I can confirm I have the same problem as the original post:

c:\users\slowd\documents\arduino\libraries\sdfat\src\common\fscache.h:37:7: warning: type 'struct FsCache' violates the C++ One Definition Rule [-Wodr]
 class FsCache {
       ^
c:\users\slowd\documents\arduino\libraries\sdfat\src\common\fscache.h:37:7: note: a different type is defined in another translation unit
 class FsCache {
       ^
c:\users\slowd\documents\arduino\libraries\sdfat\src\common\fscache.h:179:18: note: the first difference of corresponding definitions is field 'm_blockDev'
   FsBlockDevice* m_blockDev;
                  ^
c:\users\slowd\documents\arduino\libraries\sdfat\src\common\fscache.h:179:18: note: a field of same name but different type is defined in another translation unit
   FsBlockDevice* m_blockDev;
                  ^
c:\users\slowd\documents\arduino\libraries\sdfat\src\common\fsblockdevice.h:31:16: note: type 'struct FsBlockDevice' should match type 'struct FsBlockDevice'
 typedef SdCard FsBlockDevice;
                ^
C:\Users\slowd\Documents\Arduino\libraries\SdFat\src/FatLib/FatPartition.h:51:7: warning: type 'struct FatPartition' violates the C++ One Definition Rule [-Wodr]
 class FatPartition {
       ^
C:\Users\slowd\Documents\Arduino\libraries\SdFat\src\FatLib\FatPartition.h:51:7: note: a different type is defined in another translation unit
 class FatPartition {
       ^

However, I can confirm, that setting ENABLE_DEDICATED_SPI via editing the SdFatConfig.h , does work correctly . This doesn't explain to me why this should work. Isn't the purpose of the #ifndef logic in SdFatConfig.h supposed to let us define a value for ENABLE_DEDICATED_SPI before #including sdfat.h ? If so, why doesn't that work here?

#ifndef ENABLE_DEDICATED_SPI
#if defined(__AVR__) && FLASHEND < 0X8000
// 32K AVR boards.
.....

stripwax avatar Jun 09 '22 23:06 stripwax

(update - apologies, I now understand the cause of what I described, which is coming from the limitation/misunderstanding of the Arduino IDE compilation process, rather than a problem in this library)

stripwax avatar Jun 10 '22 11:06 stripwax

Yes, Adruino has way too many limitation. You can define symbols in other IDEs like PlatformIO. The #ifndef sections in SdFatConfig.h then work and you don't need to edit the file.

Community use of PlatformIO is free.

The PlatformIO for Arduino is here.

greiman avatar Jun 10 '22 12:06 greiman