Pages: [1]   Go Down
Author Topic: Need mechanism to pass defines to library cpp files  (Read 1724 times)
0 Members and 1 Guest are viewing this topic.
Dallas, Texas
Offline Offline
God Member
*****
Karma: 31
Posts: 887
Old, decrepit curmugeon
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I am attempting to modify my Entropy library to allow the user to decide if they want to include floating point functions for the library.  I placed conditional defines around the relavent code; however, it wouldn't link.  I determined that the source level #define was not being passed to the libraries cpp compile, though it was passed to the libraries header file.

My current solution is to require the user to comment/uncomment the header file for the library, but this is cumbersome, and problematic.  It would be nice if the compilation for library code included the defines made by the Arduino sketch.
Logged

New true random number library available at: http://code.google.com/p/avr-hardware-random-number-generation/

Current version 1.0.1

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

the simplest solution I can think of is to provide two libraries but that is a burden for the developer.

Another way is to use a templates. A very short intro see
- http://www.cplusplus.com/doc/tutorial/templates/ - at the end of the page
or
- http://www.tutorialspoint.com/cplusplus/cpp_templates.htm -
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Dallas, TX USA
Online Online
Faraday Member
**
Karma: 67
Posts: 2706
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Libraries are not slaves to the user of the library.
The library code is compiled separately and the behavior you are seeing is
the expected behavior. This is how libraries work.
i.e. a library is a separate compilable module that must be capable of being compiled
separately, in advance, and without any knowledge of any code that uses the library.
In most build environments, libraries are compiled up front, saved away, and then used (linked against)
as needed. Since multiple users of the library might want to set library compile defines separately/differently
there would be no way to build the library object without seeing the user code that used it.
The Arduino build methodology is not all that smart and does not save things like the compiled libraries
for re-use across different sketches. However, in the Arduno environment, even though the libraries
are not being saved for other sketches to use, the libraries are still actual libraries and
since a library is a separate entity from the code that uses it, there is no way to do what you are wanting.


There are some ways to kind of do what you are wanting to do.

You could play some games with the pre-processor to rename the names of the
functions that the user code ends up calling.

That way you could have two sets of functions in the actual library,
one that uses floating point and the other that does not.
To select which the user simply puts a #define above the inclusion of the library header.
(The default might be floating point, then if the magic define is set it drops to integer only)

Then in the library header file, the header remaps all the function names
based on some ifdef condition

At link time the appropriate function would be pulled in and you end up with
the version of the support you want/need.

Another similar alternative would be to still have the two sets of functions
but then have an inline wrapper function that simple calls the integer or floating
point version. The inline wrapper function would be in a header file that the users
sketch code includes. That way, conditionals could change it appropriately.
The library would still have to have both sets functions but only the ones
actually referenced would be linked in.

I do some similar things in my openGLCD library to map some older functions
to the newer functions. In my case, I even manipulate the parameters being
passed to the functions.
The user sketch code doesn't change, all the magic is done by the mapping macros.

Another alternative that would work but some might call "ugly" would be to put all
the code in the header file.
The code is no longer a library at that point but you could then do whatever you
wanted and any conditionals you put in the user code prior to including the header
file would work as you are wanting.

--- bill
« Last Edit: April 16, 2014, 02:20:47 pm by bperrybap » Logged

North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 70
Posts: 2171
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Where is the source with the floating point functions in. I tried this one http://forum.arduino.cc/index.php?topic=227351.0 but  you must have a newer version.

EDIT: found the 0.72 version, no luck there either.
« Last Edit: April 16, 2014, 03:38:28 pm by pYro_65 » Logged


Dallas, Texas
Offline Offline
God Member
*****
Karma: 31
Posts: 887
Old, decrepit curmugeon
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Where is the source with the floating point functions in. I tried this one http://forum.arduino.cc/index.php?topic=227351.0 but  you must have a newer version.

EDIT: found the 0.72 version, no luck there either.

I am currently alpha testing the changes and have not published the new version yet.  If you would like to try out the alpha version send me a message and I will email you a zip file.
Logged

New true random number library available at: http://code.google.com/p/avr-hardware-random-number-generation/

Current version 1.0.1

Dallas, Texas
Offline Offline
God Member
*****
Karma: 31
Posts: 887
Old, decrepit curmugeon
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Libraries are not slaves to the user of the library.
The library code is compiled separately and the behavior you are seeing is
the expected behavior. This is how libraries work.

Yes, and if the Arduino environment was actually using libraries I would understand that I would have to use a different method to get around the problem, for instance letting a define specify which vesion of the library to link into the code; however, as you point out below, the Arduino libaries are not really libraries, but module of code that get included in the compile process.

As such something simply like would be nice.

Code:
#define ENTROPY_FLOAT
#include <Entropy.h>


The Arduino build methodology is not all that smart and does not save things like the compiled libraries
for re-use across different sketches. However, in the Arduno environment, even though the libraries
are not being saved for other sketches to use
, the libraries are still actual libraries and
since a library is a separate entity from the code that uses it, there is no way to do what you are wanting.

--- bill
Logged

New true random number library available at: http://code.google.com/p/avr-hardware-random-number-generation/

Current version 1.0.1

Dallas, Texas
Offline Offline
God Member
*****
Karma: 31
Posts: 887
Old, decrepit curmugeon
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

the simplest solution I can think of is to provide two libraries but that is a burden for the developer.

Another way is to use a templates. A very short intro see
- http://www.cplusplus.com/doc/tutorial/templates/ - at the end of the page
or
- http://www.tutorialspoint.com/cplusplus/cpp_templates.htm -


Thanks for the references!  My c++ experience predates the inclusion of templates in the language, and I have never had a need for that feature before.  I will look at the references provided and see about incorporating that solution into the library.
Logged

New true random number library available at: http://code.google.com/p/avr-hardware-random-number-generation/

Current version 1.0.1

North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 70
Posts: 2171
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

What you want can be achieved, however is it necessary.

Do the new features add overhead even when unused?
Or will the methods have alternate functionality depending on the value of ENTROPY_FLOAT?

If you want the functions unavailable, you could simply add this to your header.
Code:
#ifndef ENTROPY_FLOAT
  #ifdef ENTROPY_FLOAT_COMPILE
#define ENTROPY_FLOAT  //Include for compilation, sketch must define to use.
  #endif
#endif

And modify the .cpp
Code:
#include <Arduino.h>
#define ENTROPY_FLOAT_COMPILE
#include <Entropy.h>

This way, the library is compiled with full functionality, and the sketch will only see the float functions if they explicity add #define ENTROPY_FLOAT. The compiler should be able to remove the unused pieces.

If you want to prevent compiling of the float features altogether, that can still be achieved.
Logged


Dallas, Texas
Offline Offline
God Member
*****
Karma: 31
Posts: 887
Old, decrepit curmugeon
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yeh, this library works even on some of the small tiny avr's (2313), but only if none of the code for floating point is included since that brings in additional 'library' code that really bulks up an application.  However, for some applications, and on the appropriate chips, floating point random numbers can be very useful, so I want to include the capability in the library, but only if the user needs it.

After reading the references on template specialization, that seems like a likely solution, though I will also try pyro_65's solution as well.  Ultimately, I want the library to be useable outside of the Arduino environment as well, since I occasionally use straight c/c++ as well.
Logged

New true random number library available at: http://code.google.com/p/avr-hardware-random-number-generation/

Current version 1.0.1

Dallas, TX USA
Online Online
Faraday Member
**
Karma: 67
Posts: 2706
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Libraries are not slaves to the user of the library.
The library code is compiled separately and the behavior you are seeing is
the expected behavior. This is how libraries work.

Yes, and if the Arduino environment was actually using libraries I would understand that I would have to use a different method to get around the problem, for instance letting a define specify which vesion of the library to link into the code; however, as you point out below, the Arduino libaries are not really libraries, but module of code that get included in the compile process.

As such something simply like would be nice.

Code:
#define ENTROPY_FLOAT
#include <Entropy.h>

All the other Arduino libraries like your Entropy library are still being treated like a library by the IDE.
The IDE doesn't create a library .a archive file for it but otherwise the library is being handled
very similar to a "normal" library.
The files in the library are each compiled separately from the users code (sketch files) and then
then the library objects are linked in with the users code.
(The library files are not included or merged into the same compilation unit as the users sketch)
The only difference between "real" libraries and what the IDE is doing
is that with the exception of the Arduino core library, the compiled objects in the other libraries
are not archived into a .a archive file before they are linked in.

--- bill
Logged

Dallas, TX USA
Online Online
Faraday Member
**
Karma: 67
Posts: 2706
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

wanderson,
In the bigger picture, without seeing your new code or understanding on how you
are changing the API,  it really isn't possible to make any
recommendations since it can depend on how you are implementing things.

For example, if the function names for obtaining floating point random numbers
vs integer random numbers is different or are overloaded functions, then there is nothing that you will need to do.
The IDE sets the gcc compiler and linker options to remove functions that are not called.
So while the Entropy library object will have the compiled code for the functions for both integer
and floating point functions as well as all the s/w floating point routines in it,
only the functions used will actually be linked in.
i.e. if you don't call the floating point functions, they will not be linked in
and all the floating point s/w support will also be yanked out.


git has great support for branches. Perhaps you could push your latest updates
into a branch so we could take a look at it?

--- bill
« Last Edit: April 16, 2014, 08:06:05 pm by bperrybap » Logged

Dallas, Texas
Offline Offline
God Member
*****
Karma: 31
Posts: 887
Old, decrepit curmugeon
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

All the other Arduino libraries like your Entropy library are still being treated like a library by the IDE.
The IDE doesn't create a library .a archive file for it but otherwise the library is being handled
very similar to a "normal" library.
The files in the library are each compiled separately from the users code (sketch files) and then
then the library objects are linked in with the users code.
(The library files are not included or merged into the same compilation unit as the users sketch)
The only difference between "real" libraries and what the IDE is doing
is that with the exception of the Arduino core library, the compiled objects in the other libraries
are not archived into a .a archive file before they are linked in.

--- bill

It doesn't appear to me that the Arduino IDE is treating them as libraries, but rather as additional source files included in a make like environment.  In that environment I would feed defines to my make file to control the compilation of the executable.  That is what I am looking for here; however, I think the template specialization may make a cleaner solution, or perhaps I can simply rely on the linker to not include any methods which aren't used as you described above; however, that behavior wasn't what I thought occurred.  I thought if you used some of a classes code, then all of it were included.
Logged

New true random number library available at: http://code.google.com/p/avr-hardware-random-number-generation/

Current version 1.0.1

North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 70
Posts: 2171
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Yeh, this library works even on some of the small tiny avr's (2313), but only if none of the code for floating point is included since that brings in additional 'library' code that really bulks up an application.  However, for some applications, and on the appropriate chips, floating point random numbers can be very useful, so I want to include the capability in the library, but only if the user needs it...

I thought if you used some of a classes code, then all of it were included.
No overhead for unused data. To achieve what you want, no mods are needed.

The defines I provided hide them from the user. I use templates frequently, however they are overkill for this. The floating point data is compiled, but not linked in unless you use it. Which means there is no additional code impact if the user decides not to use it.

Also they work if the user wants, just like you wanted.
« Last Edit: April 16, 2014, 08:34:49 pm by pYro_65 » Logged


Dallas, TX USA
Online Online
Faraday Member
**
Karma: 67
Posts: 2706
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No overhead for unused data. To achieve what you want, no mods are needed.
Same is true for code.

The gcc tools have gotten a lot more sophisticated/smarter in the past few years.
There are new options that put every single function and data element into its own section
and if there is no referenced to that section, the linker tosses it out.
It requires cooperation between the compiler and linker but the IDE turns on the
options to enable it.

make can do anything, since it just a dependency rule based system to run commands.
Most of the makefiles that I create for doing builds/compiles
use real libraries and create archive files and even peek into the archive files for dependencies.
I only wish the IDE was using meak underneath the covers vs trying to create their own set
of rules.
Much of the Arduino build nonsense that the IDE is doing and has been doing over the years would have been avoided.

As far as the libraries being real "libaries". The IDE is treating them similar to real libraries.
The distinction being that they are compiled separately vs being combined with users source when compiled.
The only thing not being done by the IDE is to combine the library objects into .a archive file.
The IDE does create a library archive file by combining all the core objects into a .a archive,
so for sure the Arduino core library is a true archive library.

In the early days, the IDE was combining everything into one mega gigantic file and then compiling it.
For many unsophisticated users, that probably would work better and even allow certain kinds
of optimizations that cannot be done when things are separate modules and compiled separately.

Maybe what was throwing me is this:
Quote
the Arduino libaries are not really libraries, but module of code that get included in the compile process.
as it was ambiguous to me.
I had assumed that you meant that the library source was getting included in the users sketch code
as part of the compile process where both were compiled together.
While that used to happen long ago, the current IDE process treats the libraries as libraries and compiles
the library modules separately. The only thing the IDE doesn't do right now is build a library archive .a file
for the libraries. (well it does for the core library).

--- bill

Logged

Pages: [1]   Go Up
Jump to: