Open MrPointer opened 5 years ago
Since a sketch may include many headers, it's not possible to simply generate prototypes for every function defined in the sketch/source file as some of them might already be declared in one of those headers. To cope with that, all headers need to be parsed, extracting all function declarations inside them. Then, each function definition in the sketch file can be compared against the list of all function declarations.
Function declarations don't have to name their arguments, thus a function foo
declared like this:
void foo (int bar1, short bar2);
is the same as this:
void foo(int, short);
That complicates things as comparing string isn't enough to determine whether a defined function is already declared, and a smarter approach is required. Searching merely for a function name also doesn't suffice as functions might be overloaded (Arduino is C++ after all)
To deal with the problems described above, a map-like data structure can be used: The key will be a function's name, and the value a list of matching overloads. The overloads themselves might be in the form of a list of argument types, as it's enough to differentiate one function declaration from another.
Then, each function defined in the sketch file will be converted to a similar form, and its name will be searched in the map as a key - If it exists, the argument list will be compared. Based on that, a decision on whether to generate a prototype/signature/declaration will be taken.
CMake doesn't quite allow constructing any data structs pragmatically, mainly because of its variable scope limitations (It's extremely difficult to propagate a variable declared inside a function 2 or more levels up the call stack).
Because of that, pre-mapping all functions declarations is not a feasible solution.
Custom data structs could be constructed in CMake only by using properties (namely global ones), as it's the only way to handle variable scoping in pragmatically.
However, for now - The lookup process should be performed for each function definition met inside a sketch file, since it wouldn't actually require to build a map struct.
Later on it could be optimized to use a map to pre-map the functions.
After a long period developing this feature, It seems that CMake just isn't the right tool for this job, and there are tools better suited for this, like python. While the general algorithm isn't hard to grasp, it's painfully difficult to implement in pure CMake. Besides, the task of sketch-to-source conversion happens only once - The 1st time a sketch is added to a project. What it means is that it doesn't really matter if the conversion would be done using the framework itself, or an external tool better suited for this. After all, the framework only supports standard C/C++ source files, so the process of converting a sketch to a source is merely a utility.
Developing an external tool, desirably in Python (As it would be cross-platform without the burden of compiling it for each architecture), should be the ultimate way to implement this feature. It would allow all kinds of optimizations, as well as perfect function argument matching, which has been the main concern in the pure CMake implementation.
The Arduino Build-Process Specification specifies:
In their terminology, prototypes are simply function declarations, or signatures. For example, given the following sketch file:
The following prototype/declaration will be generated above the
setup
function in the converted source:This is necessary for a source file to be valid and compile as required - Otherwise the compiler will complain it can't find declarations for the function symbol (
foo
in our example).