define a var before loading a library

Hello,
I have this question. I’m trying to develop a small library that uses I2C or SPI and I’m get stuck on this following problem:
to save memory I will like to include only the I2C part or SPI functions of the library depending of what I decided to use in the sketch.

The only solution I got is create 2 different library (one I2C and one SPI) but for my pleasure to understand I will like to know if there’s a way to call just one library, define in some way a var (like loading a file or whatever) and use something like #ifdef inside the library for avoid during compiling time the parts don’t needed to save space.
Of course I can add a define inside the .h file of the library but what I really want to know if there’s a way to do this from sketch!

For example:

Sketch:

#include <SPI.h>
#include <mylib.h>
#include <mylibspiconfig.h>//set as SPI
//#include <mylibi2cconfig.h>//set as I2C


mylib test();
...

mylibspiconfig.h

#ifndef mylib_config
#define mylib_config

#include <SPI.h>

#define ___USESPIINLIB  // uses SPI

#endif

mylibi2cconfig.h

#ifndef mylib_config
#define mylib_config

#include <Wire.h>

#define ___USEI2CINLIB  // uses wire

#endif

mylib.h

#ifndef _MYLIB_H_
#define _MYLIB_H_

#include <Arduino.h>

class mylib {
public:
         mylib(void);
         void begin(void);

};
#endif

mylib.cpp

#include "Arduino.h"
#include "mylib.h"


#if defined(___USEI2CINLIB)
#include <SPI.h>
#elif defined(___USEI2CINLIB)
#include <Wire.h>
#endif


mylib::mylib(void){

};

void mylib::begin(void){
};

This not work, seems sketch load all files during compile time but unfortunatly defined var inside config file is not visible by cpp file. Any clue or solution to get the desidered result?

Something like that should work.
The preprocessor checks the code, without looking at defines a lot. I don’t understand that very well. When I write something about the preprocessor, I get corrected :stuck_out_tongue:

I would do it like this:

#define ENABLE_MYLIB_I2C
#include <mylib.h>

How much bytes does the code increase when a single class can do both with a parameter to select SPI or I2C ?
I tried using defines, changing ‘int’ to ‘byte’, and so on, only to learn that the code size sometimes increases!

Is it a problem to create two classes ?
With the creation of the class one of the two is choosen.
I think that the other one will not be created and the functions will not be in the resulting binary file.

Thanks for response but still not working. I’ve changed files so I can experiment directly.

file:aaaLib.h

#ifndef AAALIB_H
#define AAALIB_H

#include "Arduino.h"


class aaaLib
{
private:

public:
	aaaLib();
	void begin(void);


};
#endif

file:aaaLib.cpp

#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#include "aaaLib.h"


#if defined(ENABLE_AAALIB_I2C)
	#error enabled I2C
#elif defined(ENABLE_AAALIB_SPI)
	#error enabled SPI
#endif

aaaLib::aaaLib()
{

}


void aaaLib::begin(void)
{
}

file:test.ino

#include <SPI.h>
#include <Wire.h>

#define ENABLE_AAALIB_I2C

#include <aaaLib.h>

aaaLib test = aaaLib();

void setup(){
  test.begin();
}

void loop(void){
}

Running the example I should have an error (check aaaLib.cpp) but not.
I also noticed that include SPI doesn’t grow the size but Wire will add more than 1K even if not used and only in the sketch, probably because preprocessor it add it (together with twi.h) during compile time by looking sketch first. This mainly the reason I wantto understand the mechanism and a possible solution, I got a library that has kinda way to avoid this (U8glib) but it’s well over my knoledge!

Maybe define an extern var???

So the <Wire.h> does use memory, even if it is not used ?
That might have to do with the interrupt routine in twi.c. I think they are always included, and the interrupt routine uses functions and buffers, so they are also included.

I tried changing the aaaLib.h, so the Wire.h is only included when needed.

#if defined (ENABLE_AAALIB_I2C)
#include <Wire.h>
#warning enabled I2C
#elif defined (ENABLE_AAALIB_SPI)
#include <SPI.h>
#warning enabled SPI
#else
#error AAALIB not specified !
#endif

But I got lost with the includes. I could not make it work.
Like you wrote in your first post, using the #define ENABLE… in the *.h file of the library is the normal way.

According to this, it could perhaps be possible: http://embeddedcomputing.weebly.com/conditional-if-defined.html

Unfortunatly the #define method it's not praticable since the only way is put it inside the .h file and it's not elegant way to propose a library that use several different method. My vision is choose desidered method inside sketch and just in the #include and instance so all the following library commands remains the same, this allows use library in many projects without touch a line of code inside library itself.

A possible solution is use a base library and move all the methods that use different protocols or hardware driving in additional child libraries.

Example:

Main library

#ifndef AAALIB_H
#define AAALIB_H

#include "Arduino.h"

class aaaLib
{
private:
      virtual void send(byte data) = 0;
public:
    function...
    function...
};
#endif

I2C library

#ifndef AAAI2CEXT_H
#define AAAI2CEXT_H

#include "aaaLib.h"

class aaaLibI2C : public aaaLib
{
private:
          specialized hardware funcion...
          specialized hardware funcion...
public:
           virtual void send(byte data);
    ....
};
#endif

In this way the libraries are separated and on sketch I just need to instantiate aaaLibI2C (and include it, of course). On the backside I have to carefully think how to organize the libraries and will be a small nightmare the debug. This is the only possible solution I got, my knoledge of C has come from PHP so I'm not so experienced in embedded stuff but maybe anyone has a simpler solution???

The answer is to make your libraries more granular, to the object == function level:
http://www.nongnu.org/avr-libc/user-manual/library.html

How the linker behaves is very important in designing a library. Ideally, you want to design a library where only the functions that are called are the only functions to be linked into the final application. This helps keep the code size to a minimum. In order to do this, with the way the linker works, is to only write one function per code module. This will compile to one function per object module.

Ray

Probably this solution will result a more compact code but really don't know how to start with it. Did you know any library that uses this method?

Edit: object == function level, I'm not sure can be an easy solution since I'm just try to separate wire methods from SPI and so on, did this method result in many files?

I do not recommend this and it is extra work, but I have been known to bring a library into my sketch directory (.h & .CPP & .s) and reference the .h in a tab, and change the #include line to indicate a local library. Once that compiles, I gut out what is not required.

This defeats general library use, makes a one-off product, makes it impossible to ask for forum help because everyone will scream @you.... But, it will create smaller code.

Just do not tell anyone I mentioned it :fearful:

Ray

Thanks for suggestion! I solved by using parent-child method, if carefully designed it saves a lot of headaches and maintain library well compact,small and easy to debug.

Show us !

It's reply #4! it works and it's a standard C++ method. It fit almost perfectly in libraries that can use different protocols or hardware methods since share same functions by changing only include and instance, the only problem it's design the parent library to have all commands and basic vars (those need to be protected) and split all different hardware methods in child libraries, I just made some fast experiments and seems work well but need more experiment time to check how much good is it. I just start to understand that sometime what seems a clever solution can be not as good when compiled (es. multiple copies in memory for example or switch/case that uses more memory than standard if/then) so I normally create tiny test useless libraries for study purposes. I got 2 C++ books and was not full clear the use of virtual, protected and how impact the compiler. For example, I was thing that const xxx var should be declared also static when just one copy in memory is needed but I made some experiments and had no change in memory and size, so I think that compilers are more clever to optimize now...

Thank you.

A "const int x = 3;" will not be assigned to a memory location, but the '3' will be used directly in the code. There are so many compiler options and tricks. The Arduino IDE uses only moderate optimizations.

There is for example an option that the compiler will store the variables in registers if possible, and do that optimization for the complete code as a whole. That could bypass function calling and change memory usage a lot.

Just an update on child class method, it works if no external library (wire, etc.) are needed but if one of the child class (or virtual) need to use one of those libraries I'm back again at the same problem... The sketch ask for all external libraries used in childs! Compiler, preprocessor or linker kick my ass again since it make a list of everithing to include before look what it was used in code?!? whatever. I find a way that seems to work, I create separate additional libraries that contain methods that need those external libraries (for example wire need to be included in the additional library that have to include all methods that needs wire directly) and included in child libraries, compiling sketch now will not ask for external libs again so now every virtual lib has it's own methods and includes without interfere with the others but are all methods of one library and stays in a single folder, clean and ordered as I was looking for! This can save some headache if someone want try but beware that code polverization it's nasty to debug so I raccomend small steps, unfortunatly a good C++ book doesn't help so much here since microcontrollers compiler have they own world and I still not find a good book to understand what's going on

The sketch ask for all external libraries used in childs!

That's by design. If you don't like it, don't use the IDE.

If I'm right I managed the way to cheat the ide 'design'.

one more question related… is there any difference in using #include <…/Wire/Wire.h> instead of #include <Wire.h> in a lib?
I ask because if I using canonical #include <Wire.h> the sketch try always include it (even if the virtual library I’m actually use don’t need it), switch to #include <…/Wire/Wire.h> solve the problem.

aleandrogreete:
I ask because if I using canonical #include <Wire.h> the sketch try always include it

I don’t understand why you would #include a file that you did not need, or #include the header for a library if you did not require the library.

It’s a series of child libraries (…class aaaLibI2C : public aaaLib, class aaaLibSPI : public aaaLib, and so on, read earlier this post) so every child have their necessary includes obviously.
In this case I’m using Wire and SPI as example but when try to instantiate in a sketch one of the child lib, for example aaaLibSPI, I got an error because have to include the libs used in other childs that are not used in the sketch. PaulS says that’s IDE designed to operate like this but it’s true only if in the childs library I using #include <Wire.h> (or #include <SPI.h>), if I use #include <…/Wire/Wire.h> (or #include <…/SPI/SPI.h>) the sketch works fine, no error and sketch don’t borrow me to include unused libraries that belongs to unused child library (someone call virtual lib, whatever).
It’s working, but I will like to know why

It’s working, but I will like to know why

I’d think that that was obvious. <Wire.h> tells the compiler to go look for Wire.h in the usual places. <…/Wire/Wire.h> tells the compiler to look for Wire.h in a specific place (relative to where the source file lives). Since Wire.h is at that location, but is not in any of the usual places, unless Wire.h is included in the sketch, one method (not a good practice) allows it to be found, while the other (the preferred practice) does not.

Why is the preferred practice not the one that finds the header file? Pretty simple, really. The preferred method allows the header file to be moved. The other method does not.

The Arduino team could decide that libraries should be in a different place with respect to the Arduino executable. Then, your sketch that doesn’t include Wire.h but that includes your library would no longer compile. The sketch that includes Wire.h and your library would continue to compile.

Thanks Paul, that’s help me to understand the file location issue.
But I’m still figure out why compiler try to include ‘always’ <Wire.h> present in an unused method of a virtual library (and kick an error that force me to include in the sketch) and <…/Wire/Wire.h> not (as it should be, since it’s rely to unused method).
I dunno how IDE decide to preprocess the code but suppose that it try to get a list of every external library used in the library and sketch even if are apart of methods not used by sketch and force to include. Include in a virtual method of the library <…/Wire/Wire.h> will break this but even put on verbose I still cannot see any error and everithing works as expected and no extra useless code will be included.

…one method (not a good practice) allows it to be found, while the other (the preferred practice) does not.

Is this should trigger an error during compiling?