# \#ifndef Definition Specification

**URL:** <https://forum.arduino.cc/t/ifndef-definition-specification/1336813>\
**Category:** Programming\
**Created:** [December 29, 2024, 9:09am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813 "2024-12-29T09:09:10Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![UniquePete](https://avatars.discourse-cdn.com/v4/letter/u/d6d6ee/32.png) [@UniquePete](https://forum.arduino.cc/u/UniquePete)\
**Post date:** [December 29, 2024, 9:09am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/1 "2024-12-29T09:09:10Z")

</div>

In the `Sd2Card.cpp` file, used within the SD library, there is a `#ifndef` macro:

```arduino
  #ifndef SDCARD_SPI
    #define SDCARD_SPI SPI
  #endif

```

that sets the SPI bus to be used. In my case, I would like to use the second SPI bus, SPI1, but I cannot work out how to define the entity `SDCARD_SPI` in my sketch in a way that is recognised by this macro. I can change the definition in `Sd2Card.cpp` to

```arduino
    #define SDCARD_SPI SPI1

```

and everything works as I would like, but how do I include a definition somewhere else so that the macro behaves as intended, assigns the value SPI, by default—when there is no existing definition of `SDCARD_SPI`—but picks up my desired definition, SPI1, when I want to use the SPI1 bus?

I have tried the obvious option of simply including the above definition in my sketch, but it does not appear to be recognised within `Sd2Card.cpp`, and I don't have a good enough understanding of the use of `extern` or any other construct that might be used to achieve the desired outcome.

---

<div class="post-metadata">

**Author:** ![horace](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/horace/32/1014299_2.png) [@horace](https://forum.arduino.cc/u/horace)\
**Post date:** [December 29, 2024, 9:32am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/2 "2024-12-29T09:32:43Z")

</div>

what microcontroller are you using?  
with the ESP32 I use the alternate HSPI interface so

```arduino
 #define HSPI_MISO 16//12
  #define HSPI_MOSI 17//13
  #define HSPI_SCLK 4// 14
  #define HSPI_SS 15

#include "FS.h"
#include "SD.h"
#include "SPI.h"

SPIClass *hspi = NULL; // SPI object

void setup() {
  Serial.begin(115200);
  hspi = new SPIClass(HSPI); // create SPI class
  hspi->begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI, HSPI_SS); //SCLK, MISO, MOSI, SS
  if (!SD.begin(HSPI_SS, *hspi)) { // mount card
    Serial.println("Card Mount Failed");
    return;
  }

```

---

<div class="post-metadata">

**Author:** ![bojan\_jurca](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/bojan_jurca/32/1199504_2.png) [@bojan\_jurca](https://forum.arduino.cc/u/bojan_jurca)\
**Post date:** [December 29, 2024, 10:57am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/3 "2024-12-29T10:57:25Z")

</div>

#define SDCARD\_SPI SPI1 actually defines how the library is going to be compiled. You can not have it compiled twice in the same sketch with different #definition. So, if you #define SDCARD\_SPI prior to #including the library this is how the library is going to be compiled in your sketch.  
If you need two different values for SDCARD\_SPI in the same sketch you should reprogram the whole library so that SDCARD\_SPI would be a parameter rather than compile-time directive.

---

<div class="post-metadata">

**Author:** ![gcjr](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gcjr/32/314015_2.png) [@gcjr](https://forum.arduino.cc/u/gcjr)\
**Post date:** [December 29, 2024, 11:10am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/4 "2024-12-29T11:10:01Z")

</div>

> [@UniquePete](#):
>
> ```arduino
> #ifndef SDCARD_SPI
> #define SDCARD_SPI SPI
> #endif
> 
> ```
> 
> that sets the SPI bus to be used.

looks like it defines `SDCARD_SPI` to `SPI` if it hasn't be defined (i.e. `ifndef`)

have you tried defining `SDCARD_SPI` before including the library

```arduino
#define SDCARD_SPI SPI1

```

---

<div class="post-metadata">

**Author:** ![UniquePete](https://avatars.discourse-cdn.com/v4/letter/u/d6d6ee/32.png) [@UniquePete](https://forum.arduino.cc/u/UniquePete)\
**Post date:** [December 29, 2024, 12:22pm UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/5 "2024-12-29T12:22:19Z")

</div>

Thanks guys.

> [@horace](#):
>
> what microcontroller are you using?

I'm using a Heltec CubeCell Plus Dev-Board, but the question was really meant more generally: if there's a [`#ifndef`] macro checking whether or not something has been defined before a library file is 'processed', how do I get that entity defined in such a way that the linker/loader or whatever knows that it has indeed been defined?

> [@bojan\_jurca](#):
>
> If you need two different values for SDCARD\_SPI in the same sketch

No, I only need it defined once, I just need to know how to define it in such a way that the [`#ifndef`] macro in the library knows that it has already been defined [elsewhere].

> [@gcjr](#):
>
> have you tried defining `SDCARD_SPI` before including the library

That suggestion was sounding promising but alas, no, that didn't seem to make any difference. My local definition is recognised within my sketch, but not, it would seem, by the library when it is loaded.

If it helps, the following is the code, including the recommendation of @gcjr, to the point of 'failure':

```arduino
#define SDCARD_SPI SPI1

#include <SPI.h>
#include <SD.h>

#define CS1 GPIO4

File myFile;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  delay(1000);
  
  SPI1.begin(SCK1,MISO1,MOSI1,CS1);// sck, miso, mosi, nss

  #ifndef SDCARD_SPI
    Serial.println("[setup] No definition...");
  #else
    Serial.println("[setup] Definition recognised...");
  #endif

  Serial.print("Initializing SD card...");

  if (!SD.begin(CS1)) {
    Serial.println("failed!");
    while (1);
  }
  Serial.println("done");

```

As it stands, my definition is recognised locally, but I never get past the `SD.begin(CS1)` check, unless I go in and modify the library to assign SPI1 as described in my original post.

---

<div class="post-metadata">

**Author:** ![gcjr](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gcjr/32/314015_2.png) [@gcjr](https://forum.arduino.cc/u/gcjr)\
**Post date:** [December 29, 2024, 12:27pm UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/6 "2024-12-29T12:27:29Z")

</div>

> [@UniquePete](#):
>
> My local definition is recognised within my sketch, but not, it would seem, by the library when it is loaded.

guessing your output was `[setup] Definition recognised...`. which would also be the output without your local definition because `SDCARD_SPI` will be defined in the library

can you print the values of `SPI`, `SPI1` and `SDCARD_SPI` instead?

---

<div class="post-metadata">

**Author:** ![gfvalvo](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gfvalvo/32/1013044_2.png) [@gfvalvo](https://forum.arduino.cc/u/gfvalvo)\
**Post date:** [December 29, 2024, 12:56pm UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/7 "2024-12-29T12:56:20Z")

</div>

> [@UniquePete](#):
>
> if there's a [`#ifndef`] macro checking whether or not something has been defined before a library file is 'processed', how do I get that entity defined in such a way that the linker/loader or whatever knows that it has indeed been defined?

That depend on how the library is structured. In some cases you can't, you must change the definition in the library's source files themselves. In other cases you can put the `#define` statement before the `#include` statement for the library's .h file. The FastLED library, for example, has several optional features that are implemented this way.

---

<div class="post-metadata">

**Author:** ![UniquePete](https://avatars.discourse-cdn.com/v4/letter/u/d6d6ee/32.png) [@UniquePete](https://forum.arduino.cc/u/UniquePete)\
**Post date:** [December 29, 2024, 10:20pm UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/8 "2024-12-29T22:20:12Z")

</div>

Thanks again for persisting with this.

> [@gcjr](#):
>
> guessing your output was `[setup] Definition recognised...`.

That's correct, but without my local definition I get

```arduino
08:30:40.302 -> [setup] No definition...
08:30:40.302 -> Initializing SD card...failed!

```

So there's no 'link' between my local definition and that used in the SD library. The fact that the `#ifndef` macro is present in the `Sd2Card.cpp` file suggests that the author believes that the relevant definitions could have been made elsewhere. I think what I am trying to work out how this would be possible—how would a situation arise where that `#ifndef` macro would not assign a value to `SDCARD_SPI`.

> [@gfvalvo](#):
>
> In other cases you can put the `#define` statement before the `#include` statement for the library's .h file.

I tried just putting the `#define` before the `#include` statement in the `SD.h` file and that didn't work either. Not surprisingly, if I put the `#define` in the `Sd2Card.h` file, before the `#ifndef` macro, or in either of the `.h` files that are `#include`d therein, it is recognised but, in a practical sense, that's not really any different to changing the definition in the `Sd2Card.cpp` file—it would apply every time the definition was used, and the `#ifndef` macro would then appear to be superfluous (_i.e._ if it can only ever give one result, why would it be there in the first place?)

I'd like to specify the option of using the SPI1 bus—signalling to the `#ifndef` macro that it should not include the definition that specifies the SPI[0] bus—in some file that a user would normally be responsible for preparing, ideally the 'parent' sketch itself, and not to have to modify any of the library files, which the average user would not be expected to be doing.

> [@gfvalvo](#):
>
> The FastLED library, for example, has several optional features that are implemented this way.

So how is this done? Does the user set the optional features by declaring or defining something in their sketch or a 'local' `.h` file?

---

<div class="post-metadata">

**Author:** ![UniquePete](https://avatars.discourse-cdn.com/v4/letter/u/d6d6ee/32.png) [@UniquePete](https://forum.arduino.cc/u/UniquePete)\
**Post date:** [December 29, 2024, 11:00pm UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/9 "2024-12-29T23:00:20Z")

</div>

OK, maybe this thread

> [@Preprocessor problem](https://forum.arduino.cc/t/preprocessor-problem/696970):
>
> Hi! I'm facing a strange problem... On my main ino file, on first line, i have a definition: #define MYDEF #include "Ethernet.h" Then i include the ethernet library, modified in this way: #ifndef W5100\_H\_INCLUDED #define W5100\_H\_INCLUDED #define SPI\_ETHERNET\_SETTINGS SPISettings(14000000, MSBFIRST, SPI\_MODE0) #pragma message "14" ... #if defined(MYDEF) #pragma message "4" #undef SPI\_ETHERNET\_SETTINGS #define SPI\_ETHERNET\_SETTINGS SPISettings(4000000, MSBFIRST, SPI\_MODE0) #endif ... #en…

explains the situation... What I want can't be done through the IDE, maybe unless I'm willing to get under the covers and use the CLI, which I didn't even know existed.

If I've misinterpreted the essence of the explanations provided in this thread, I'd still love to hear how I can solve my particular problem, or if @pert is out there and can confirm my [unwelcome] suspicion, I'd be [not so] happy to have my conclusion confirmed.

---

<div class="post-metadata">

**Author:** ![van\_der\_decken](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/van_der_decken/32/1006976_2.png) [@van\_der\_decken](https://forum.arduino.cc/u/van_der_decken)\
**Post date:** [December 29, 2024, 11:17pm UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/10 "2024-12-29T23:17:56Z")

</div>

It all comes down to the library's .cpp files being compiled separately from your .ino file. So any #define's you make in the .ino file have no effect on the library's .cpp files.

Some light reading:

> <https://stackoverflow.com/questions/14418936/overriding-define-in-libraries>

> [@Additional compiler options](https://forum.arduino.cc/t/additional-compiler-options/631297):
>
> Hello, is there a way, by way of the Arduino IDE (1.8.10), to add additional options to the compiler for the .cpp file ? In particular I want to add the "-S" option to the compiler invocation line to get the assembler code for my sketch. I tried adding "-S" to the 'compiler.cpp.extra\_flags=' in the 'C:\Program Files (x86)\Arduino\hardware\arduino\avr\platform.txt' file, but to no avail. Would be great if someone could push me in the right direction. Thanks.

> [@How to add compile options to Arduino IDE 1.8.13](https://forum.arduino.cc/t/how-to-add-compile-options-to-arduino-ide-1-8-13/692640):
>
> I have found a lot telling me to add the options to global.txt platform.txt, platform.local.txt and so on. I want to add an option that will be added to the compile options for all boards. Here is the Arduino CLI command: arduino-cli compile --fqbn arduino:avr:mega --build-property build.extra\_flags=-DOSH\_NOXMLNS Unified\_Sensor\_ArduinoMEGA\_ATWINC1500B\_Test29.ino If you notice in the line, the option I want to add to all my boards is "--build-property build.extra\_flags=-DOSH\_NOXMLNS" It is u…

I've added extra choices to existing options with the techniques outlined above. It's quite likely that you could add an extra option to give you a choice of the default SPI bus in the same manner. It would be a bit of a learning experience though.

---

<div class="post-metadata">

**Author:** ![UniquePete](https://avatars.discourse-cdn.com/v4/letter/u/d6d6ee/32.png) [@UniquePete](https://forum.arduino.cc/u/UniquePete)\
**Post date:** [December 30, 2024, 12:05am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/11 "2024-12-30T00:05:43Z")

</div>

@horace, I just realised a detail in what you were suggesting there:

> [@horace](#):
>
> ```arduino
> if (!SD.begin(HSPI_SS, *hspi)) { // mount card
> Serial.println("Card Mount Failed");
> return;
> }
> 
> ```

The SD library for the ESP32 provides a form of the `begin` method that includes the specification of the SPI bus to use. There is no such form of the `begin` method in the 'standard' version of the library.

The fact probably is that the Heltec CubeCell support software also needs to include a version of the SD library that includes this functionality, particularly given that in this case there is an expectation that the second SPI bus, SPI1, will generally be used to support external SPI connectivity.

---

<div class="post-metadata">

**Author:** ![gfvalvo](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gfvalvo/32/1013044_2.png) [@gfvalvo](https://forum.arduino.cc/u/gfvalvo)\
**Post date:** [December 30, 2024, 12:58am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/12 "2024-12-30T00:58:21Z")

</div>

> [@UniquePete](#):
>
> I tried just putting the `#define` before the `#include` statement in the `SD.h` file and that didn't work either.

As I said:

> [@gfvalvo](#):
>
> That depend on how the library is structured.

> [@UniquePete](#):
>
> > [@gfvalvo](#):
> >
> > The FastLED library, for example, has several optional features that are implemented this way.
> 
> So how is this done? Does the user set the optional features by declaring or defining something in their sketch or a 'local' `.h` file?

By putting the macro's `#define` in the user code before the `#include` for the library. It works because that library is structured to support that method.

---

<div class="post-metadata">

**Author:** ![gfvalvo](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gfvalvo/32/1013044_2.png) [@gfvalvo](https://forum.arduino.cc/u/gfvalvo)\
**Post date:** [December 30, 2024, 1:00am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/13 "2024-12-30T01:00:29Z")

</div>

> [@UniquePete](#):
>
> The fact probably is that the Heltec CubeCell support software also needs to include a version of the SD library that includes this functionality, particularly given that in this case there is an expectation that the second SPI bus, SPI1, will generally be used to support external SPI connectivity.

That's the beauty of the Open Source paradigm. The source code is available and on your computer. Look at the SPI library code for this board and see.

---

<div class="post-metadata">

**Author:** ![UniquePete](https://avatars.discourse-cdn.com/v4/letter/u/d6d6ee/32.png) [@UniquePete](https://forum.arduino.cc/u/UniquePete)\
**Post date:** [December 30, 2024, 1:14am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/14 "2024-12-30T01:14:21Z")

</div>

> [@gfvalvo](#):
>
> Look at the SPI library code for this board and see.

Yes, no problem there. I've worked through that code. The real issue is getting the SD library methods to use what's available there.

---

<div class="post-metadata">

**Author:** ![UniquePete](https://avatars.discourse-cdn.com/v4/letter/u/d6d6ee/32.png) [@UniquePete](https://forum.arduino.cc/u/UniquePete)\
**Post date:** [December 30, 2024, 1:19am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/15 "2024-12-30T01:19:25Z")

</div>

> [@gfvalvo](#):
>
> It works because that library is structured to support that method.

I've just had a quick look at that library, but there's a lot of stuff in there. Is there any particular area there you could point me to that illustrates the required structure?

---

<div class="post-metadata">

**Author:** ![gfvalvo](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gfvalvo/32/1013044_2.png) [@gfvalvo](https://forum.arduino.cc/u/gfvalvo)\
**Post date:** [December 30, 2024, 1:20am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/16 "2024-12-30T01:20:21Z")

</div>

> [@UniquePete](#):
>
> The real issue is getting the SD library methods to use what's available there.

Right. I'll have a look when I have time. How did you install the Heltec Arduino board support package? What URL did you add to "Preferences"?

---

<div class="post-metadata">

**Author:** ![gcjr](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gcjr/32/314015_2.png) [@gcjr](https://forum.arduino.cc/u/gcjr)\
**Post date:** [December 30, 2024, 1:25am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/17 "2024-12-30T01:25:27Z")

</div>

it looks like this is more complicated. Don't understand why the code was written this way or how these defines are intended to be used

if you look inside [Sd2Card.cpp](https://github.com/arduino-libraries/SD/blob/master/src/utility/Sd2Card.cpp), the bodies of functions often contain code defined within an `#ifndef USE_SPI_LIB` and an alternative that uses `SDCARD_SPI` as a prefix for methods, e.g. `SDCARD_SPI.transfer()`. There is also `SOFTWARE_SPI`

`USE_SPI_LIB` is defined within both Sd2Card.h and Sd2Card.cpp. `SOFTWARE_SPI` and `SDCARD_SPI` are undefined.

i don't see any point in defining `SDCARD_SPI` with providing the associated methods.

---

<div class="post-metadata">

**Author:** ![ptillisch](https://avatars.discourse-cdn.com/v4/letter/p/ad7895/32.png) [@ptillisch](https://forum.arduino.cc/u/ptillisch)\
**Post date:** [December 30, 2024, 1:30am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/18 "2024-12-30T01:30:59Z")

</div>

Hi @UniquePete.

> [@UniquePete](#):
>
> Is there any particular area there you could point me to that illustrates the required structure?

Another example of such a structure was mentioned in the forum topic you linked in one of your previous replies:

> [@Preprocessor problem](https://forum.arduino.cc/t/preprocessor-problem/696970/5):
>
> you might be interested in the approach used in the Encoder library:
> 
> [Encoder/examples/NoInterrupts/NoInterrupts.ino at 1.4.4 · PaulStoffregen/Encoder · GitHub](https://github.com/PaulStoffregen/Encoder/blob/1.4.4/examples/NoInterrupts/NoInterrupts.ino#L7-L14)
> 
> This might seem odd at first, since you just discovered that attempting to control conditional compilation of libraries via `#define` directives in the sketch doesn't work so well.
> 
> The reason it's possible with the Encoder library is because the author put all the relevant source code in `Encoder.h`:
> 
> [Encoder/Encoder.h at 1.4.4 · PaulStoffregen/Encoder · GitHub](https://github.com/PaulStoffregen/Encoder/blob/1.4.4/Encoder.h)
> 
> So the sketch's translation unit contains the library source code that is being controlled by the macro defined in the sketch.

The "Encoder" library is much more simple than the FastLED library, so I think this will serve as a more friendly reference.

> [@gcjr](#):
>
> Don't understand why the code was written this way or how these defines are intended to be used

The macro is defined in the core variant of boards that have a built-in SD card holder. For example, the [**MKR Zero**](https://docs.arduino.cc/hardware/mkr-zero):

> <https://github.com/arduino/ArduinoCore-samd/blob/1.8.14/variants/mkrzero/variant.h#L123-L124>

The macro is available to the library's translation units via the `#include` directive for `Arduino.h`:

> <https://github.com/arduino-libraries/SD/blob/1.3.0/src/utility/Sd2Card.cpp#L21-L21>

> <https://github.com/arduino/ArduinoCore-samd/blob/1.8.14/cores/arduino/Arduino.h#L51-L51>

---

<div class="post-metadata">

**Author:** ![UniquePete](https://avatars.discourse-cdn.com/v4/letter/u/d6d6ee/32.png) [@UniquePete](https://forum.arduino.cc/u/UniquePete)\
**Post date:** [December 30, 2024, 1:37am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/19 "2024-12-30T01:37:34Z")

</div>

> [@gfvalvo](#):
>
> How did you install the Heltec Arduino board support package?

I just downloaded it directly from the GitHub repository.

---

<div class="post-metadata">

**Author:** ![UniquePete](https://avatars.discourse-cdn.com/v4/letter/u/d6d6ee/32.png) [@UniquePete](https://forum.arduino.cc/u/UniquePete)\
**Post date:** [December 30, 2024, 1:47am UTC](https://forum.arduino.cc/t/ifndef-definition-specification/1336813/20 "2024-12-30T01:47:38Z")

</div>

> [@ptillisch](#):
>
> The macro is defined in the core variant of boards that have a built-in SD card holder.

So am I understanding correctly if I read this to mean that the definition is not really intended to be user-controlled as such, but rather controlled universally for a particular board definition—_i.e._ the intention [of the macro] is not for a user to be able to specify which SPI bus to use but rather for a particular SPI bus to be identified for use with a specific board?

[Next page](https://forum.arduino.cc/t/ifndef-definition-specification/1336813.md?page=2)
