Controlling How a Library Compiles From Within a Project

Looking for greater insight.

I have libraries that I would like to change based on the project.
For example:
I have an IR remote decoding library. It has dozens of different remotes define. In one project I may want to decode the "Sony" format, in another project I may want to decode the NEC format. Each format may have several remotes defined to it. I don't want to include every remote for every format for every project.
I would like to have a header file in the project folder where I can place configuration "#define" statements and have that header picked up with the library is compiled.

I usually put "Debug" code in my libraries. I would like to control the debug from the project I am working on. I would like to be able to turn on the debugging at the project level. It would also be nice if I could indicate where the debugging information is to go (i.e. Serial, Serial1, LCD, ...).

I know that I could put the configuration file in the library and change it there. However, if I put down one project to pickup a different project I don't want to need to go into all the libraries used and make changes.

1 Like

Source files are compilation units. It doesn't matter whether the source file is a .c file, a .cpp file, or a .ino file. Putting stuff in a header file is a good idea. The question is where to put the header file. In the library folder is one option, but not all that easy to edit, then.

Putting it in the sketch folder is another option, but then getting a library to see it is a challenge.

1 Like

theres the c pre proccessor that deals with this 100%

you will have seen

#include

but there are many other directives
#define debug // define debug

then in code
#if defined debug
... compile this code

#else

...... this code

endif

there is also
#if defined

elif defined

elif defined

#endif

look up pe processing of C on google search..

cod=e

PaulS:
Source files are compilation units. It doesn't matter whether the source file is a .c file, a .cpp file, or a .ino file.

The .ino files are a special case because of the daft way that the IDE mangles all the .ino files in the sketch into a single .cpp source file. I think it would be correct to say that the set of all .ino files in the sketch concatenated together (and with the mucking about applied) constitute a single compilation unit.

yes the ide does combine everything badly into a singlre file but preprocesser directive still work

but preprocesser directive still work

So what? The question was where to put them. You failed to address THAT.

I am seeing a lot of accurate information but not a lot of help. Let me break this down to a simple example. I will tell you what I have tried and see if anyone knows where I have missed something.

We can start with the famous library FOO. In it, we have header file FOO.h and code file FOO.cpp. Now FOO does something and can do it with either a serial or parallel interface. There is a lot of code with both methods and to save space, and for other reasons, we want to only compile the interface method we want to use.

So in a header file FOO_Options.h we have

#define USE_PARALLEL or USE_SERIAL

In FOO.h we have

#include <FOO_Options.h>

In FOO.cpp we have

#include <FOO.h>
...
#ifdef USE_PARALLEL
   ...  code to do things in Parallel
#endif
#ifdef USE_SERIAL
   ...  code to do things in serially
#endif

// scattered throughout the code there are many, many of these conditional blocks of code

Now I have tried to put the file "FOO_Options.h" in my project directory. However, the file is not found when FOO.cpp is being compiled.
The compile command lists directories to search for include file, such as:

-I/usr/share/arduino/hardware/arduino/cores/arduino

Can I get the parm like this generated for the current project directory?

-I/home/RandallR/sketchbook/Projects/MyFOOProj

It also need to be in the parameter list before the parm

-I/home/RandallR/sketchbook/libraries/FOO

I hope that this makes it clearer what I am hoping to do.

1 Like

Regarding the debugger output, I would suggest creating a little debug output framework that was configured by your sketch, so that the code generating the log messages is isolated from how the log messages get handled. There are various ways to do that depending how proficient your C++ is, but for example you could implement a logging function that presents a single common interface to all the logging implementations, and have that dispatch the log messages to whatever output mechanism your sketch has installed. Or you could define a global object that implements an output stream interface if you prefer to think in OO terms. If you implement the different logging mechanisms in separate libraries then you could keep this fairly lightweight and avoid dragging in code for logging mechanisms you aren't using. If you're used to working in the 'C'/C++ world and like the idea of having stdout, the AVR runtime library provides hooks that you can use to register your own get/put functions for the standard streams so that the sketch can simple print() to whatever output mechanism you have currently got registered. In other words, there is already one such framework - although you don't have to use that one and could easily roll your own.

I haven't seen any practical way to pass project-specific header files to a library (or pass any other compilation options in), but maybe if you considered this as a software design problem rather than a conditional compilation problem, you could find a way to implement the various behaviours without requiring conditional compilation. (Without any idea of what sort of behaviour variations you're dealing with and how that affects the code, I can't say whether that approach is going to be sensible. But in general hand-wavey terms I mean you would abstract out the concept of doing the serial-or-parallel thing in a way that could be implemented serially or parallely.)

The only way you can cause changes in your library code ( .cpp ), based on your sketch code is to make the library dependent on the sketch, what is needed is late bound references to the library, which can be achieved using templates. I have used this method to allow custom settings for many different sketches.

I'm writing an FAQ on the topic however its unfinished. I'll link to it when done.

pYro_65:
The only way you can cause changes in your library code ( .cpp ), based on your sketch code is to make the library dependent on the sketch, what is needed is late bound references to the library, which can be achieved using templates. I have used this method to allow custom settings for many different sketches.

I'm writing an FAQ on the topic however its unfinished. I'll link to it when done.

If you are talking about using true late binding techniques with virtual calls etc., then the IDE is rubbish at resolving these properly since the IDE does all the mangling without the need for h files and creates one big cpp its no wonder virtual call tables give it a head ache. anyone who is not a seasons C++ programer needs to avoid the ideas behind Late binding stick with standard linkage.

My reply regarding Pre-Processor directives would solve the described requirement, yes the library itself would still be fully compiled, but the sketch app would only link to the aspects of library selected by the pre-porocessor directives. given the responces
to mine and other replies, this person is a newbie without a great deaL of experience in C so possibly reading a true book On C / C++ and programming in objects ... rather than internet code snippets might prove useful.

tgsuperspec:

pYro_65:
The only way you can cause changes in your library code ( .cpp ), based on your sketch code is to make the library dependent on the sketch, what is needed is late bound references to the library, which can be achieved using templates. I have used this method to allow custom settings for many different sketches.

I'm writing an FAQ on the topic however its unfinished. I'll link to it when done.

If you are talking about using true late binding techniques with virtual calls etc., then the IDE is rubbish at resolving these properly since the IDE does all the mangling without the need for h files and creates one big cpp its no wonder virtual call tables give it a head ache. anyone who is not a seasons C++ programer needs to avoid the ideas behind Late binding stick with standard linkage.

My reply regarding Pre-Processor directives would solve the described requirement, yes the library itself would still be fully compiled, but the sketch app would only link to the aspects of library selected by the pre-porocessor directives. given the responces
to mine and other replies, this person is a newbie without a great deaL of experience in C so possibly reading a true book On C / C++ and programming in objects ... rather than internet code snippets might prove useful.

Nope, I made no mention of virtual calls, I said templates. Virtual calls still require the whole implementation.

And no, pre-processor arguments do not work for selective compiling, have you tested it? The library .cpp files are compiled before your sketch is even able to provide its pre-processing. The directives will only affect the header file your sketch uses to compile, not the actual library.

Sorry if you thought I was getting picky but Templates do not constitute true late binding, late binding realistically can only be truely implemented by virtual call tables as per ISO standards, the IDE will support virtual to some degree had it working, but now use Embedded X code far more satisfactory answer for larger complexprojects.

Also I did not say that pre processor would make library compilable differently, I said based on description of the problem he wanted to solve perhaps the whole library won't matter and he can use pre processor diective to compile specific aspects of his sketch only..

tgsuperspec:
Sorry if you thought I was getting picky but Templates do not constitute true late binding, late binding realistically can only be truely implemented by virtual call tables as per ISO standards, the IDE will support virtual to some degree had it working, but now use Embedded X code far more satisfactory answer for larger complexprojects.

Also I did not say that pre processor would make library compilable differently, I said based on description of the problem he wanted to solve perhaps the whole library won't matter and he can use pre processor diective to compile specific aspects of his sketch only.

Well , in a run-time environment, yes, virtual calls are a form late binding, however so is using a non-virtual, non-member function pointer.
As for templates, they are only templates during compilation. Which also has late and early binding, which is a result of dependent & non-dependent types. The compiler is a Turing complete system which templates can exploit, and delaying the instantiation of an object is sometime necessary.

None of this is addressing the OP's basic issue.

I agree with him, I have had the same issues. Unfortunately, I think this is an inherent weakness of the Arduino IDE scheme. perhaps a necessary and reasonable one in the interests of perceived "simplicity" and the inherent project scale limitations of microcontrollers.

1 Like

michinyon:
None of this is addressing the OP's basic issue.

I agree with him, I have had the same issues. Unfortunately, I think this is an inherent weakness of the Arduino IDE scheme. perhaps a necessary and reasonable one in the interests of perceived "simplicity" and the inherent project scale limitations of microcontrollers.

Well actually as I pointed out, using a template design would allow selective compiling of components or debugging. And tgsuperspec pointed out how defines could select what to use in the header file. Wandered a bit off topic, however there are solutions to investigate. And neither are out of reach using the IDE.

pYro_65:
Well actually as I pointed out, using a template design would allow selective compiling of components or debugging. And tgsuperspec pointed out how defines could select what to use in the header file. Wandered a bit off topic, however there are solutions to investigate. And neither are out of reach using the IDE.

You correctly pointed out that the use of templates allows selective compiling of the project where it is being used. I think that templates are not that well understood and are probably underutilized. I must confess that I never use templates.

With that said, it does not solve the problem. The template (or #ifdef) only effect the current source file.

Let's look at the problem from a different angle. The core library contains conditional compiled code based on hardware differences. This makes since. There is no effort to use templates to address this. So now let's look at third party library. The library to interface to Hitachi HD44780 is LiquidCrystal. The library uses a parallel interface. Now someone comes along and makes a board that talks I2C. One option is to create another library, LiquidCrystal_I2C, that inherits from LiquidCrystal. Now you have two libraries to manage. I will grant you that when using LiquidCrystal_I2C you still need all the code for LiquidCrystal since it will still need to talk parallel to the HD44780. So now in your project you must include the headers from both LiquidCrystal and LiquidCrystal_I2C.

This is not a perfect example, but I hope the intent is clear.

1 Like