0

What is the best way to hardcode the compiler's -D flag into the source files?

I want to put the #define in one of the headers and then import bunch of stuff that should react to that define. Does it work like that? Which header should I put it? Or directly to main.c? Or to all of them?

TMI-details: The environment here is digispark hw-018 (attiny85 with built-in usb programmer) and the #define should replace -DUSE_SOFTWARE_SPI so I can use AVR-CAN library in SPI mode to read stuff from MCP2515.

EDIT: After some annoying banging head to the wall the top of main.c looks now like this and it still does not work.

#define USE_SOFTWARE_SPI 
#include "src/can.h"
#define USE_SOFTWARE_SPI 
#include <avr/io.h>
#define USE_SOFTWARE_SPI 
#include <avr/pgmspace.h>
#define USE_SOFTWARE_SPI 
#include <DigiUSB.h>

I am right in saying that there is something that overrides my define somewhere? It works if I hardcode the #define USE_SOFTWARE_SPI just before the #ifndef (or #ifdef)

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
Juha
  • 2,053
  • 23
  • 44
  • Why not put it at the very top of your `main.c` source file, with the `#include`s right after? That would make it clear to all readers what's going on. – Steve Friedl Nov 25 '20 at 16:35
  • 1
    See Steve Friedl's excellent response below (Please "upvote" and "accept" if you find it helpful) Configuring your #define at the project level (e.g. a "makefile", or a .csproj) is "ideal". A separate .h file - which #includes *ALL* of the headers that use that #define - is a reasonable alternative. Putting your #define at the top of your .c is the simplest. If this is a "one-off" project, if you have just one source file, and if it works for you - go for it :) – paulsm4 Nov 25 '20 at 17:53
  • It's no different for Arduino than for any other platform. Learn the right way and apply it. There are countless tutorials on how to do header files correctly. – TomServo Nov 26 '20 at 00:35
  • For some reason I can't get this to work... putting the define in main.c does not work. I have to put it in the same file where the #ifndef or #ifdef is... I think someone has hardcoded it somewhere deep... – Juha Dec 01 '20 at 17:41
  • Please do not edit solutions into the question. Create an answer yourself or accept one of the existin answers please. – Yunnosch Dec 07 '20 at 14:48
  • Well, the first edit is not related to the question... so it should be removed or chaged – Juha Dec 07 '20 at 14:55

1 Answers1

2

There are a couple of approaches here.

If it's just a single main.c source file, then putting this at the top of the file is fine:

// main.c
#define USE_SOFTWARE_SPI // must be first!
#include <spi_stuff.h>
...

This doesn't scale well if this needs to be in multiple source files because it's too easy to miss it in one of the several places.

I suppose that even if there are multiple source files, but only one actually references the headers files that need to be influenced, it's less risky, but this is how mistakes happen down the road.

My preference is to put this kind of thing in the project definition as a whole, either in the makefile or in whatever the IDE uses to drive the project, because that insures everybody sees it.

So, if you do have multiple source files and you can't or won't put this in the project file, then the way to handle it is with your own custom header that exists only for this purpose:

// my_spi_stuff.h
#define USE_SOFTWARE_SPI 
#include <spi_stuff.h>
... others if needed

and then include that in your .c programs. Be sure to give the file a name that strongly suggests "local adjustments" rather than something that could be confused with one provided by a library.

EDIT I just re-read that this is Arduino, and as far as I know the IDE doesn't have project-wide settings.

Steve Friedl
  • 3,929
  • 1
  • 23
  • 30
  • I had a problem with passing the #define... Did I got it correctly in the edited question? – Juha Dec 01 '20 at 17:59
  • Ok, I got now. The #define goes by 'compile unit' so if I compile a library the library header has to have the #define in addition to main.c. Normally I would put this in global CFLAGS in Makefile, now in every first header for each 'compile unit'. Could you add this note to the end. – Juha Dec 03 '20 at 10:21
  • I think I described this; any place where the library header is used, you need the `#define` before it. In some programs it could be just main.cpp, but if you use the header in some other compilation unit, you need to do the same thing there. Is that what you're saying? – Steve Friedl Dec 03 '20 at 14:49
  • yes, basically that. In a simple program top of main.c is ok, but if you compile libraries every library header needs to have it at the beginning. For casual C user (like me) this is not clear as -D in cflags in a Makefile does this automatically for all. In short: "Which header should I put it? - Every header of each compile unit." – Juha Dec 07 '20 at 14:41