Should some of our system libraries generate archive files (.a)?

KurtE

Senior Member+
While trying to figure out how to resolve anther issue. In particular how to handle the same font defined in a display library as might be contained in a fonts library and not end up with a bunch of multiple defined errors,

I started playing around some with some of the newer library format stuff and was wondering if we should apply it to some of our other system libraries.

To do this, requires us to use the newer library directory structure. In particular move the header files and source files into a sub directory: src

And create a library.properties file.

In the library.properties file you can then have a line: dot_a_linkage=true
More details in the documentation: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification

But what this will do, is to compile everything in the directory and then like the core, will create an archive file, which is then included in the link.

Where I think this might be interesting is with things like the wire library which may create objects and buffers for all possible objects on the device, which then is loaded into your sketch. Whereas if each of these objects are created in their own .c/.cpp file than it may be possible that they will only consume resources in those sketches who actually use those objects.

Does this make sense?

Kurt
 
...
Where I think this might be interesting is with things like the wire library which may create objects and buffers for all possible objects on the device, which then is loaded into your sketch. Whereas if each of these objects are created in their own .c/.cpp file than it may be possible that they will only consume resources in those sketches who actually use those objects.
...

Sounds nice and makes sense if it speeds re-compile time. Though something seems worse in handling between IDE 1.8.9 and 1.8.10 where it seems some things get rebuilt more often - but that hasn't been side by side tested to document.

Is that where the LTO option comes in to prune out unused objects?

Wondering if the next IDE iteration was it 1.9.x with parallel building and then the addition of PRO will do this better or differently?
 
For what it is worth, I did a quick hack of Wire library. Where I moved source files to SRC directory, updated library properties.

Then for T4, I created a seperate source file for the three Wire objects and then built the wire scanner...

No difference in code size, but reduced RAM usage from 18432 to 18288 which is not a whole lot, but... Would probably be nicer on things like T-LC

WIP up at: https://github.com/KurtE/Wire/tree/Make-archive-objects-own-file
 
Sounds nice and makes sense if it speeds re-compile time. Though something seems worse in handling between IDE 1.8.9 and 1.8.10 where it seems some things get rebuilt more often - but that hasn't been side by side tested to document.

Is that where the LTO option comes in to prune out unused objects?

Wondering if the next IDE iteration was it 1.9.x with parallel building and then the addition of PRO will do this better or differently?
Actually I don't know if in general it will speed up or slow down builds... That is I don't know if the system will be smart enough to know nothing changed in sources so don't recompile... And it adds in the steps to archive each file, like it does for cores.

I was/am going to experiment with doing the same to WireKinetis.cpp, but I am trying to figure out that there are some places in the code that look for Wire1.

In particular the ISR code does:
Code:
		// Continue Slave Receive
		irqcount = 0;
		#ifdef WIRE_HAS_STOP_INTERRUPT
		port().FLT |= I2C_FLT_STOPIE;
		#else
		#if defined(WIRE_IMPLEMENT_WIRE) && !defined(WIRE_IMPLEMENT_WIRE1)
		attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr0, RISING);
		#elif !defined(WIRE_IMPLEMENT_WIRE) && defined(WIRE_IMPLEMENT_WIRE1)
		attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr1, RISING);
		#elif defined(WIRE_IMPLEMENT_WIRE) && defined(WIRE_IMPLEMENT_WIRE1)
		if (this == &Wire) {
			attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr0, RISING);
		} else if (this == &Wire1) {
			attachInterrupt(hardware.sda_pin[sda_pin_index], sda_rising_isr1, RISING);
		}
And then the function: sda_rising_isr1 also refers to Wire1 object...

But no where refers to Wire2 and Wire3 objects. So those could easily be moved into files. Does that imply that we have not implemented slave receive on Wire2 and WIre3 for T3.5/6?

Again fix would not be hard here. add pointers to sda_rising_isr0 into either hardware structure or constructor and save away in object and then we simply use that pointer. And move those functions into the individual Wire files for each object.

But again wondering if this is something that is desired. The plus is, we can be default define Wire1 for T-LC and the like and only if someone uses it will it take up the real memory.
 
The plus is, we can be default define Wire1 for T-LC and the like and only if someone uses it will it take up the real memory.

That's pretty compelling.

One minor issue, discussed just yesterday, is the installer doesn't know how to delete the old files if they're present from a prior install. I believe Arduino is supposed to ignore them if we have a src folder. I also recall some versions of Arduino had bugs where that wasn't done properly. Today we only support back to Arduino 1.8.5, so maybe that's not an issue? But of course to proper thing to do would be for me to make the installer aware of how to clean up the old version's files.
 
Yes there is the issue, of those files still existing. I have not played with that yet to see what they do. Could put blank files there if we need to. Yes would be nice if installer could remove them.

Quick update. I made the edits for T-LC/3.x... And pushed the changes up to the branch: https://github.com/KurtE/Wire/tree/Make-archive-objects-own-file

I have not run them on the different boards yet, but did compile them using the scanner sketch
T-LC - No change in size BUT I also enable Wire1
3.2 - 5224 -> 5112
3.6 - 5280 -> 5064 I also enabled Wire3
 
Quick update: Ran into issue with Wire library with Adafruit_SSD1306, when I switched the constructor in the example to use Wire1 instead of Wire. The program would not link as it was missing the Wire object.

The SSD1306 library had reference to Wire object within one of it's constructors that I was not using...

So in my unreleased/version of Wire library I moved the Wire object back into the main files (wirekenitis.cpp wireIMXRT.cpp)...
 
FrankB started a library and adding this from above to "library.properties": dot_a_linkage=true

Results in this - still shows checks of the *.o files - then shows using the '.a' file to build.
Code:
Compiling library "spiffs"
Using previously compiled file: T:\TEMP\arduino_build_spiffstest_internal_flash.ino\libraries\spiffs\spiffs_gc.c.o
Using previously compiled file: T:\TEMP\arduino_build_spiffstest_internal_flash.ino\libraries\spiffs\spiffs_hydrogen.c.o
Using previously compiled file: T:\TEMP\arduino_build_spiffstest_internal_flash.ino\libraries\spiffs\spiffs_check.c.o
Using previously compiled file: T:\TEMP\arduino_build_spiffstest_internal_flash.ino\libraries\spiffs\spiffs_nucleus.c.o
Using previously compiled file: T:\TEMP\arduino_build_spiffstest_internal_flash.ino\libraries\spiffs\spiffs_cache.c.o
Using previously compiled file: T:\TEMP\arduino_build_spiffstest_internal_flash.ino\libraries\spiffs\spiffs.a
Compiling core...
[B]Using precompiled core: T:\TEMP\arduino_cache_spiffstest_internal_flash.ino\core\core_c4001b4cf26344258c8c5e3af8f414dd.a[/B]
 
What I think I was running into is I believe with the linkers, that the order of the includes in the command line is important. And I ran into an issue where:
you have something like: <some files>, Wire.a, adafruit_ssd1306.cpp, ... core.a...

The problem and benefit of using .a files is that only those objects that fulfill some currently outstanding external reference will be pulled in.... So in my case the sketch brought in the Wire1 object as it was the only one that had any external dependencies, and then the Adafrut_ssd1306 driver referenced the Wire object, and since the .a file was already processed the Wire object was not loaded into the binary...
 
Back
Top