Can a sketch modify a #defined symbol in a library?

I want to #define a symbol in a library, but this is a default value and a sketch may want to alter it. Is this possible? I've tried a couple things to no avail. For instance, in the library I've tried

#ifndef foo
#define foo 42
#endif

But I can't seem to override that value with another #define in the sketch.

In a word, no.

The library will have its own compilation units (.cpp files) that are compiled independently of your sketch. They might be linked together, but defines in your sketch won't affect them.

What Nick said - with one addition: You can use an #undef directive in your file so that you can re-use the #define directive to set a new value within your containing source file.

If C programming is analogous to tightrope-walking without a safety net, doing something like this is more like tightrope-walking without a safety net blindfolded.

I suggest you not do it. :grin:

Is it your library (or one you are willing to modify)?

Are you using Arduino 1.0?

Thanks for the replies, guys.

@Nick, I was coming to that conclusion.

@Morris, the idea is to have the library support related devices, only one of which will be used by a given sketch. Part of the library code works verbatim for all devices, part has differences depending on the particular device. It seemed reasonable to have the main sketch indicate the device, so the library code can be conditionally compiled to minimize size. Maybe there is a better/safer approach? BTW your analogy made me :slight_smile:

@Coding, yes, it's kind of a conglomeration from a couple sources, am willing to modify. Using Arduino 1.0 only sometimes, mostly not currently, but would still be interested in any applicable technique.

My understanding is that the gnu linker is pretty good at sorting out module dependencies and not including dead code. If it can't find a dependency chain from the user's code to an external module or variable, the external item isn't linked in. I'd suggest doing a bit of experimentation to see how true that might be for the Arduino implementation and then structuring your library to take advantage of that. Some things can be handled dynamically without much contortion, but others (like changing the sizes of multiple members of a structure) can become pretty messy...

Giving users the ability to modify the library with #defines can bring major headaches: Their #define directives would almost certainly need to preceed the #include directives for your stuff and if the user didn't screw that up, it's entirely possible that the IDE might - at which point you'll have a PO'd user angry with you for distributing a "buggy" library. Problems are always the library author's fault, even when they aren't. :frowning:

There was a robust conversation on the developers list about this... http://arduino.cc/pipermail/developers_arduino.cc/2012-January/006168.html

The first (low) potential solution is to set the CPATH environment variable to the sketch directory...

SET CPATH=C:\Projects\Arduino\Sketch\Forum_92382

You can then have an options header file stored in the sketch directory and included by the library. The draw-back to this solution is that the CPATH environment variable has to point to the sketch directory before starting the Arduino IDE.

How many #define sets do you expect? In other words, do you expect to have settings for each sketch or will several sketches have identical settings?

Less than a handful, and just two for now, just initial testing.

@maniacbug, thanks for the link, glad to know I'm not alone. I keep getting this feeling that I should explore getting out of the Arduino IDE some more. Have done some little work with WinAVR, but need to get smarter on makefiles.

@morris, indeed it is good at not linking in unused modules or functions. My approach was within several functions though, replacing lines of code here and there as needed. But certainly there are different methods, so maybe time to rethink the approach here. What I thought would be the path of least resistance turned out otherwise.

"Variants" may help. Try this...

• Close the Arduino IDE
• Using Explorer, navigate to the variants directory...
{ArduinoRoot}\hardware\arduino\variants
• Create a new directory (e.g. bigserial). This new directory is where you will place configuration header files for your libraries.
• Assuming you are using an Uno, copy pins_arduino.h from the standard directory to the directory you just created
• Open the boards.txt file in the Arduino directory...
{ArduinoRoot}\hardware\arduino
• Copy-and-paste the Arduino Uno section
• Rename the section ("uno." to "unobs.")
• Change the name ("Arduino Uno" to "Arduino Uno (Big Serial)")
• Change the build.variant entry to reference the directory you just created
• Save and close boards.txt
• Modify the libraries to include a header file you have placed in the variants directory
• Repeat the process for other configurations

Example boards.txt entry...

##############################################################

unobs.name=Arduino Uno (Big Serial)
unobs.upload.protocol=arduino
unobs.upload.maximum_size=32256
unobs.upload.speed=115200
unobs.bootloader.low_fuses=0xff
unobs.bootloader.high_fuses=0xde
unobs.bootloader.extended_fuses=0x05
unobs.bootloader.path=optiboot
unobs.bootloader.file=optiboot_atmega328.hex
unobs.bootloader.unlock_bits=0x3F
unobs.bootloader.lock_bits=0x0F
unobs.build.mcu=atmega328p
unobs.build.f_cpu=16000000L
unobs.build.core=arduino
unobs.build.variant=bigserial

##############################################################

Ah! Thanks for that! Hadn't poked around in 1.0 enough yet to have noticed that. Also have been reading the make manual. Interesting. I see that some folks have cooked up various makefiles. Also have an example or two off the forum here so I may also bark up that tree a bit.