"precompiled headers" problem - how to force recompilation?

I have a library file (pinChange.h) that contains:

#if !defined NUM_PCINTS
	#define NUM_PCINTS 20
#endif

and I include it thus:

#define NUM_PCINTS 3
#include <pinChange.h>

as I'm trying to override the value of NUM_PCINTS (to reduce the size of an array - int x[NUM_PCINTS] for efficiency)

when I use Serial.print(NUM_PCINTS) I get two different values: 3 if I print it from the calling sketch and 20 if I call it from the library....looks like I'm getting a "cached" version of the library linked in. If I modify the library, to set NUM_PCINTS to - say - 15 then I get the new value 15 shown from the library call, but still 3 from the call in the sketch

What I DONT want to do is have something like:

pinChange pcInstance(NUM_PCINTS);

or

pcInstance.begin(NUM_PCINTS);

and dynamically allocate the array in the library at runtime, as the extra code required will doubtless outweigh the savings I make! (and of course dynamic allocation=danger of dangling pointers, fragmented heaps, random bugs balh blah blah)

I just want the library user to be able to (easily) override the value used by the library...this method obviously doesn't work - is there a way that will? How do I force the library to recompile , or always prefer the previously #defined value?

Hmmm - just did some resaecrh in other (more general forums) I can see a) that there isnt a "clean" way to do this - I have seen one suggestion about putting ALL the code in the .h (ie not having a .cpp file and b) that it could start a "holy war" re "code purity" "library independence" "interface contracts" and other such beard-stroking topics...I will try the "dirty" suggestion.

I like to keep my code as clean and rule-bound as the next fellow....to a point. That point does not extend to bowing to academic theory when there is a rule-breaking/dirty solution that is a) simple b) obvious c) foolproof d) bug-free. If it satisfies those four points I don't care HOW dirty it is. IMHO while "clean" and "easy to maintain" are worthy goals that we should always strive to achieve, "Working" is more important than "pretty".

Hence consider this parked / solved / no longer a question

Close ALL copies of the IDE then reoprn one the libs are then rebuilt.

Mark

You're right that there is no "clean" way of directly achieving what you want, but there are ways.

The problem here is that the library is compiled separately to the sketch, and the sketch is the only place where the #define appears. It is not seen by the library when it compiles.

So how do you do it...?

There's a number of methods, some of which you have already identified:

1. Put all your code in the header
Just... no. Yes, it may seem like a good idea, and yes it may work for you in your situation, but it's really not a good idea. If you're thinking of distributing your code to others you need it to work in other situations than the one you are using it in. Code in headers is all very well if you only have one file that it is ever included in, but as soon as you include it in two files you start running into problems - your code gets included twice, which throws up multiple-definition errors. Nasty.

2. Have a configuration header file that you can tweak
It's not really any different to modifying the existing header file each time - though a little more obvious how to do it (config.h as opposed to pinChange.h). Not ideal.

3. Do dynamic allocation
Normally we don't like dynamically allocated memory, but in situations like this it is perfectly fine. You allocate the memory once at startup and never free it, so there is no problems of memory fragmentation, etc. Pass the number of pins (or whatever) to the constructor and that uses malloc() to allocate all the arrays and things that are needed. Slightly more complex, but this is probably the "best" option.

4. Use a different IDE that allows you to define things properly.
UECIDE allows you to use something like:

#pragma parameter extra.flags=-DNUM_PINS=3

and that would be added to the compilation flags of every compilation unit, so could be used to define whatever you want (be sure to purge the cache folder each time you change it). Of course, it's not then portable to other IDEs...

So if it works for you, use whatever method feels right. However, if you're thinking of distributing code, you really must use the option that a) is most compatible with as many scenarios as possible, and b) isn't going to get you laughed at :wink:

Thanks for the suggestions. I dont care about being laughed at if my code works and is portable. If the end product is useful to other folk, AND it makes them laugh, its win-win. I have seen the all-code-in-header technique in another pin change interrupt library. I didnt laugh, because it worked. I now know why he did what he did. Even without this tweak im trying to fix, my code is smaller faster, works on all pins AND when finished will run on tiny25/45/85 tiny24/44/84 uno, mega 2313 4313 etc. I havent seen any other do that yet. We'll see who laughs once its finished... :slight_smile:

You can force libraries to recompile by changing the board type, "verify"ing, and then changing the board type back again.

But that won't solve your actual problem, which is that the library is not going to pay attention to any #define NUM_PCINTS 3 that occurs in your main sketch.

In a traditional programming environment, you would put the #define for such parameters in a "config.h", and dependency calculations would recompile the "library" source (not to be confused with the more common binary pre-compiled libraries) as needed. But the arduino environment doesn't provide for such capabilities....

Presumably you could modify the library code so that you could supply the number (of pins?) as a parameter when the class is initialized?

...R

Robin2:
Presumably you could modify the library code so that you could supply the number (of pins?) as a parameter when the class is initialized?

...R

From my opening post:

What I DONT want to do is have something like:

Code:

pinChange pcInstance(NUM_PCINTS);

or
Code:

pcInstance.begin(NUM_PCINTS);

About the only thing I can think of is to play some games with where the data is declared/allocated.
For example, if NUM_PCINTS is not defined, the data gets allocated in the library code
as it is now.
If NUM_PCINTS is defined, prior to including the header,
the data is declared/allocated in the header which will be allcoated in
the user sketch.

The trick then becomes turning off the allocation in the library code.
That can be handled with an additional conditional define or the declaration/allocation
in the code could use the "weak" attribute which would allow the declaration/allocation in
the header to override it.

Because the user sketch is the only entity that will ever define NUM_PCINTS
before including the header file, there is no danger of duplicate declarations.

--- bill

There is no need for run time control over a compile time constant. Using templates you can achieve what you want. Depending on how the library is structured, it may be very simple.

What is the library you are using. Searching finds pinChangeInt.h not pinChange.h. I'll give an example if I can find it.

As it stands, the libraries are compiled first which is why only the header can see the change you made to the define ( your sketch is not used to compile cpp library files ). Using templates makes the library dependent on your code.

many thanks. the library in question is one im writing myself, so I have the chance to try some of these ideas any way I choose. you guys have given me lots to experiment with.