avenue33 and Jan Bayens, maintainers of embedXcode and Arduino Eclipse plugin, expressed some concerns about the "arch" folder in the 1.5 library layout Just to be clear, we are talking about libraries created and contributed by users the ones that we put under SKETCHBOOK/libraries
Now, unless I made some errors on the recap, I want to hear the opinion of the others member of the list too:
- is the "arch" folder an "overengineering"?
- it may be useful, or is something that nobody is going to use?
Follows a recap of what the arch folder is, the PRO and the CONS already expressed. (warning: very long email)
The reasons behind the "arch" folder:
it was conceived to store architecture specific code ONLY, instead of writing a singe huge file where code is selected through #ifdefs.
For example, an hypothethical "probe" library written without the arch folder may looks like this:
Probe/src/probe.c
int probe() {
#ifdef ARDUINO_ARCH_AVR
return PORTA & 0x01; // AVR Only
#elif ARDUINO_ARCH_SAM
return REG_PORTA_DR & 0x01; // SAM Only
#else
#error The hardware is not supported
#endif
}
Instead using the arch folder the library author provides one file per architecture:
Probe/arch/avr/probe.c:
int probe() {
return PORTA & 0x01; // AVR Only
}
Probe/arch/sam/probe.c
int probe() {
return REG_PORTA_DR & 0x01; // SAM Only
}
IMHO the PRO of this approach are:
- Much more clear structure of the code
- Adding another platform is much easier (just add the arch/xxxx/probe.c file)
- Code that is not platform specific is common for every architecture can be placed in Probe/src, it may be updated and all architectures will benefit from the update
- The same structure is used by many real world projects:
https://github.com/mirrors/linux/tree/master (notice the arch folder)
http://stackoverflow.com/a/3627208/1655275
http://stackoverflow.com/a/14592359/1655275
- The linux kernel uses the same structure and it actually use make and the gnu-gcc toolchains and its still not clear to me why changing the Makefiles accordingly is so hard, but I understand that this may be my limit.
The CONS expressed by janjte are:
1) There are plenty of non architectural dependent libraries who do not
need to cope with the complexity multiple architectures bring.
2) The "average starting Arduino library builder" will get scared when
he sees an overly complex folder/file structure which will damage the
"Arduino simple and easy advantage".
3) I expect that most ide's won't have lots of trouble to implement it.
4) And 3 has to be implemented anyway during transition.
The CONS expressed by avenue33 are:
Last remark: the inner structure of the libraries should be friendly with standard C++. This implies understanding that Arduino is two things: an IDE and a framework.
The Arduino IDE performs many hidden jobs for compilation. It provides basic features and there are many other more powerful IDEs.
The Arduino framework should be compatible with the C++ tools —make— that can't provide the fine granularity of the hidden work performed by the Arduino IDE.
C
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.
Paul, you're right that backwards compatibility is important, but so is the future. If we never change anything, it's hard to make progress.
Now, again, you might not have thought the change from WProgram.h to Arduino.h was worth it -- but I think it shows that its possible to make a transition.
Guys, the point is not to argue about the past, but to figure out the future. Any comments on the actual suggestion in my message?
My suggestion is to modify the 1.5.x library format to be compatible with 1.0.x, but keep the addition of the arch/ folders, a sub-folder of which is automatically included in the compilation process by the IDE. That is, you could take an existing 1.0.x library and it would work as-is on 1.5.x (as long its architecture-independent or you're using an AVR board). If you want to modify the library to support multiple architectures, you could add bunch of #ifdefs (which I think will be very messy in the long-run) or you could use the arch/ folder. This latter option requires a transitional hack to allow the library to continue to work on Arduino 1.0.x: i.e. you'd need to use an #ifdef to selectively #include the AVR-specific files (in arch/avr) for ARDUINO < 150 (from within a file in the library's root folder). This is a hack, yes, but it would (I believe) allow someone to transition to the new, cleaner multiple-architecture support (w/ the arch/ folder) while still providing a single download for use on 1.0.x and 1.5.x. I think this is cleaner than requiring an #ifdef for every single supported architecture -- and, furthermore, it's only necessary for the transition from 1.0.x to 1.5.x, which, while it will probably be long, will not be infinite.
Any comments on the actual suggestion in my message?
My suggestion is to modify the 1.5.x library format to be compatible with 1.0.x, but keep the addition of the arch/ folders, a sub-folder of which is automatically included in the compilation process by the IDE. That is, you could take an existing 1.0.x library and it would work as-is on 1.5.x (as long its architecture-independent or you're using an AVR board). If you want to modify the library to support multiple architectures, you could add bunch of #ifdefs (which I think will be very messy in the long-run) or you could use the arch/ folder.
This latter option requires a transitional hack to allow the library to continue to work on Arduino 1.0.x: i.e. you'd need to use an #ifdef to selectively #include the AVR-specific files (in arch/avr) for ARDUINO < 150 (from within a file in the library's root folder). This is a hack, yes, but it would (I believe) allow someone to transition to the new, cleaner multiple-architecture support (w/ the arch/ folder) while still providing a single download for use on 1.0.x and 1.5.x.
Guys, the point is not to argue about the past, but to figure out the future. Any comments on the actual suggestion in my message?
In data giovedì 31 ottobre 2013 01:56:53, Paul Stoffregen ha scritto:
> Please allow me to provide an example. VirtualWire is a 3rd party
These are a great test bench to check how good or bad the library specification works. Have you some other real world examples of multi-architecture libraries?
> My point is this seemingly clean and beautiful scheme with plaform
> indepent source and arch specific folders doesn't necesarily match up
> nicely to the reality of actual libraries.
Ok let's go and try it: I converted the library to the current 1.5 specification, here the process I followed:
1) first commit of the original library:
https://github.com/cmaglie/VirtualWire/tree/bc92ed3645dee3dca2b70eff9621138a87adbab6
2) I moved source files to follow 1.5 layout, in particular I moved the sources into the "src" folder and drop a properties files. (I know that probably we are going to remove the src folder to ensure forward compatibility with 1.0, but this is another topic ok? I'm just trying it :-))
Inside the library.properties I asserted that the library works with the architectures: "avr", "kinetis", "msp" and "stm32"
changeset:
https://github.com/cmaglie/VirtualWire/commit/459141f589dbe171bbb9da4da67bbdcc3c036397
code:
https://github.com/cmaglie/VirtualWire/tree/459141f589dbe171bbb9da4da67bbdcc3c036397
3) this is the most interesting part:
once everything is in place I moved all the arch dependent pieces into their respective arch folder.
If you notice every architecture is rounded by #ifdefs, something like:
#if defined(ARCHITECTURE_XXX_GUARD)
do stuff with XXX Architecture
#elif defined(ARCHITECTURE_YYY_GUARD)
do stuff with YYY Architecture
#else
....
basically I mentally followed what the C++ preprocessor would do and COPIED the corresponding piece of code through the various arch/xxx folders.
This allows me to remove all the architecture dependent code from src/.
Interesting also the Teensy case: it seems that Teensy use some #defines machinery to make the same ISR used by AVR to work without modifications. This lead to some partial code replication in the arch/kinetis folder that was not present in the original library.
changeset:
https://github.com/cmaglie/VirtualWire/commit/0b2e2c9c8c81dbd67b98a8cdf947e38b7e61afb8
code:
https://github.com/cmaglie/VirtualWire/tree/0b2e2c9c8c81dbd67b98a8cdf947e38b7e61afb8
4) Once that the various arch/xxx were in place I noticed that they share the same interrupt service routine. So the most reasonable thing to do is to refactor the subroutine: remove it from all architectures, put a single copy of it into the main src/ folder, and call it from the interrupt handler.
Someone may argue that this lead to inefficiency, but the compiler seems to be able to inline the call, at least on the AVR I see no code increase after the refactoring.
changeset:
https://github.com/cmaglie/VirtualWire/commit/ed144a173197a10f3d9536d6948df9c2315eb30b
code:
https://github.com/cmaglie/VirtualWire/tree/ed144a173197a10f3d9536d6948df9c2315eb30b
It doesn't took more than an hour, and here the final result:
https://github.com/cmaglie/VirtualWire
I tried to compile it on avr and it works. I haven't tried with other plaftforms since no one has yet their core ported to the 1.5 format (or I'm wrong?).
Now some observations:
- IMHO the library had an enormous benefit from this refactoring. Now its crystal clear (at least to me) how the architecture-specific stuff interact with the vanilla-core of the library. Its clear also that the only hardware specific part is the Timer setup and the ISR, while before it was absolutely not clear, and Paul had to explain in detail some of the library internals sometimes pointing directly to the code with line numbers.
- If I want to add support for another platform, say, sam or pic32, what should do I do? With the original library I should read through the code, understand where to hook, add my patch by adding whole new sections of #ifdefs, and submit the patch to the upstream authors. This is feasible yes, but simply dropping a file in arch/sam or arch/pic32 seems much more feasible to me, and requires basically no effort from the upstream author to accept the patch, because it doesn't interfere in any way with the other platforms.
- The original library has the interrupt handler replicated 3 times inside the big .cpp file. This means that every change to ISR should be propagated to *all* the 3 copies. The upstream authors failed to notice that the ISR can be declared as a vanilla function to be inlined inside the real ISR. This refactoring was pretty obvious to me during the step 4) of my porting because I wasn't distracted by all the #ifdefs crap. I want to recall the observation made by Matthijs Kooijman, that is very sensible here:
>libraries that only support a single architecture, could also leave out
>the arch/ subdirectory and just put the arch-specific code inside src/.
>The library.properties should of course note that only a single
>architecture is supported in this case.
>The downside of this approach is that it's harder to add support for a
>second architecture, but in practice it's not always easy to predict
>what code should go into arch/ when you still only support a single
>architecture (especially for novice programmers), so postponing this
>separation until a second architecture is supported probaly makes sense.
- Paul, I see that you setup the AVR-ISR-emulation to avoid the code duplication above but, if my refactoring is applied to the original library (even if it keep the 1.0 format), then you can optimize the Teensy version by removing the ugly AVR emulation and declare the interrupt handler directly.
- Another pro is that if I'm an expert of an architecture, I can safely ignore all the others. They are out of the way when I look at the core of the library, and doesn't distract me from my goal. I have no idea how the Energia or STM32 code works and it's nice to be able to ignore it.
- Let's look at the STM32 arch file (the Teensy one still uses some hardware dependent parts):
https://github.com/cmaglie/VirtualWire/blob/master/arch/stm32/VirtualWireInterrupts.h
we can see that by providing an HardwareTimer class we can further abstract the library and remove the architecture dependent parts at all, transforming the library into a "vanilla" library. This make me think that Paul statement about improving and extending the current low level APIs / Variants support is even more true (but we already know that, right? :)). I see also that all the complexity of the multi architecture timers will be transferred from the VirtualWrite library to the hypotetical HardwareTimer library, where the arch/ folder may still have sense.
C
Previously, a distinction between "users" (who write sketches) and
"library authors" (who write libraries) has been made. Is this the same
distinction you are making, or is yours subtly different?
> Instead of focusing on where files are, and the relative merits of
> those changes, is it instead valuable to incrementally move towards a
> cleaner, more easily supported structure?
different problems and might both have merits. I certainly agree that
improving APIs is a good idea!
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.
These are a great test bench to check how good or bad the library specification works. Have you some other real world examples of multi-architecture libraries?
-
I guess from my perspective of how it affects my openGLCD project,
--
You received this message because you are subscribed to a topic in the Google Groups "Developers" group.
To unsubscribe from this topic, visit https://groups.google.com/a/arduino.cc/d/topic/developers/4Jk4P0rsWPc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to developers+...@arduino.cc.
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.
Bill
I not fully understanding what you are saying here.
You do look like a library builder to me. And so does Paul.
Both you and Paul have uttered concerns with the new library structure.
I can't recall 1 single library builder who has spoken in favor of this spec.
As this is supposed to make the life of library creators easier http://forum.arduino.cc//index.php?topic=165827.msg1429696#msg1429696
Can the library creators who think this is a good specification please stand up?
his experience should not be ignored and should
be a big driver in defining the requirements for any new library format/specification.