7

I have multiple C and H files

In main.c I defined a macro, and in ws_driver.c I want to use it.

ws_driver.h is included in main.c.

main.c

#define WS_PORT PORT_D8
#define WS_BIT D8
#define WS_DDR DDR_D8

#include "ws_driver.h"

In ws_dirver.c I have two checks:

ws_driver.c

#include "ws_driver.h"

#ifndef WS_PORT
# error "WS_PORT not defined!"
#endif

#ifndef WS_BIT
# error "WS_BIT not defined!"
#endif

Both are failing.

$ avr-gcc -std=gnu99 -mmcu=atmega328p -DF_CPU=16000000UL -Os -I. -I -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wno-main -Wno-strict-prototypes -Wno-comment -g2 -ggdb -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax -std=gnu99 main.c  ws_driver.c --output main.elf
ws_driver.c:10:3: error: #error "WS_PORT not defined!"
 # error "WS_PORT not defined!"
   ^
ws_driver.c:14:3: error: #error "WS_BIT not defined!"
 # error "WS_BIT not defined!"
   ^
ws_driver.c: In function 'ws_show':
ws_driver.c:23:20: error: 'WS_PORT' undeclared (first use in this function)
 #define bus_low() (WS_PORT) &= ~(1 << WS_BIT)
                    ^
ws_driver.c:37:2: note: in expansion of macro 'bus_low'
  bus_low();
  ^
ws_driver.c:23:20: note: each undeclared identifier is reported only once for each function it appears in
 #define b......

What am I doing wrong? Please ask if you want to see some other part of the code.

MightyPork
  • 18,270
  • 10
  • 79
  • 133
  • Maybe remove the spaces before error: `# error` – Rizier123 Dec 13 '14 at 23:10
  • You should not include source files. Your `main.c` isn't included. You included the `.h` file from your `main.c`, not the other way around. – bzeaman Dec 13 '14 at 23:11
  • @BennoZeeman I don't include any `c` file anywhere, what do you mean? – MightyPork Dec 13 '14 at 23:12
  • Your post does not seem very clear to me. It looks like you're defining your constants in `main.c` and not in `ws_driver.h`, which would explain why `ws_driver.c` does not see them. – kuroi neko Dec 13 '14 at 23:12
  • The point is that ws_driver.c (and h) are meant to work as a library. Those macros are configuration for them. How else should I pass it? – MightyPork Dec 13 '14 at 23:13
  • define a `config.h` that sets the values of your configurable ports and includes `ws_driver.h`, then include it in both your `.c`files? – kuroi neko Dec 13 '14 at 23:15
  • Yeah that might work, but is that the proper way of doing it? If I want to distribute `ws_driver` as a library, everyone would have to make their own `config.h`? (Or maybe I'm not getting something.. dunno. Perhaps put everything that is now in `ws_driver.c` into `ws_driver.h` file? That's not good tho, I guess) – MightyPork Dec 13 '14 at 23:16
  • There is something seriously wrong with your structure when you're defining `define`s in your `main.c` and using them in your library files. – bzeaman Dec 13 '14 at 23:17
  • Yeah, I figured that much from your comments. Say, usually, if there's a library with configuration like this - where do you define it then? In the makefile as -Dsomething? – MightyPork Dec 13 '14 at 23:18
  • You can define them in your `ws_driver.h`, or make a separate `config.h` for all your `define`s. I think that's the most conventional and convenient way to do it. – bzeaman Dec 13 '14 at 23:19
  • ok, it's clearer now. thanks – MightyPork Dec 13 '14 at 23:25

1 Answers1

12

You have to define the macros in a header file, not in the .c file if you want to use them in multiple places.

When the compiler compiles ws_driver.c it only includes ws_driver.h and the macro is not there. It does not include main.c. Each .c file is compiled separately.

Move the macro definitions in say config.h and include it everywhere you need it.

You can also use the compiler's define -DWS_BIT=123 -DOTHER=SMTH. The value you pass will be in the generated object file and can not be changed without recompiling.

If you want to compile only once, then pass these as parameters or create a configure_my_library() function...

Doncho Gunchev
  • 2,159
  • 15
  • 21