How can I avoid the arduino ide 'Magic'?

Hi there!

I'm a new Arduino user, and I'm finding it very neat.

However, I must say that my first question after using the IDE for 10 minutes was, "How do I never have to use this IDE ever again?"

Thankfully there is the wonderful 'user external editor' option that lets you use a real editor and still use the nice arduino IDE upload / select serial device / select device / serial monitor.

However, I'm starting to get a little frustrated, and I'd like some guidance.

I have carefully read the arduino 'build rules', found here: http://www.arduino.cc/en/Hacking/BuildProcess

This process could be thoughtfully summarised as, "the IDE takes your sketch directory, looks for .h, .c, .pde and .cpp files and applies some arbitrary poorly defined and largely undocumented rules on those files to generate some .cpp files, which, if you're very lucky and only have code in your .pde file, may compile."

I mean, what it is supposed to do is concatenate all of your files into one big file, search of functions, generate prototypes and then run it. That's what it says happens.

...but, that doesn't seem to happen. Eg. add func.c, add a function in it, try calling it from setup --> fail:

test.cpp: In function 'void setup()': test.pde:-1: error: 'mySetup' was not declared in this scope

How about using a #include statement?

No, no, some more vague and poorly explained rules seem to be applied to includes.

In fact, the only way to get external files working correctly I've found is to this this bizaar hack:

test.pde:

#include "source.h"

void setup() {
  mySetup(); 
} 

void loop() {
}

#include "source.h"

source.h:

#ifndef __SOURCE_H
#define __SOURCE_H
void mySetup();

#else
char x;
void mySetup() {
 x = 0;
}
#endif

This is just nonsense.

Clearly I'm doing something wrong, but I don't know what it is.

So, rather than just having a moan, I wonder if anyone here could help me by:

1) Telling how I can see the post-IDE .cpp files which are being generated. I'm using a Mac and I can't seem to find them anywhere.

2) Tell me what the 'best practice' for multiple file sketches is?

3) Tell me exactly what rules are applied to what types of files, and, if possible, if there is a way to disable these rules, so my code, as written, is compiled by the IDE (eg. a sketch something like:

void setup() {                
  mySetup(); // external file un-modified function.
}

void loop() {
  myLoop(); // external file un-modified function.
}

Help much appreciated!

Cheers, Doug.

1) Telling how I can see the post-IDE .cpp files which are being generated. I'm using a Mac and I can't seem to find them anywhere.

Enable 'Show verbose output' in the preferences dialog.

In fact, the only way to get external files working correctly I've found is to this this bizaar hack

That is bizarre, and not necessary. Other people do not have to do that.

...but, that doesn't seem to happen. Eg. add func.c, add a function in it, try calling it from setup --> fail:

A specific example of you doing this, along with the specific error messages would really be needed in order to help you understand why it didn't work.

In general, though, it is much easier to put stuff in .cpp files than in .c file. I don't know whether that is relevant for you, or not.

2) Tell me what the 'best practice' for multiple file sketches is?

If you want to create a class, it gets defined in a .h file, and implemented in a .cpp file. If you just want to create a bunch of functions, they can go in either a .cpp file, a .c file, or a .pde file. Which extension to use is really up to you.

Keep in mind that the .c compiler will be invoked for .c files, and that does stuff differently than the .cpp compiler, and the differences cause the linker problems, unless you use extern "C" guards in the .h file.

3) Tell me exactly what rules are applied to what types of files, and, if possible, if there is a way to disable these rules, so my code, as written, is compiled by the IDE (eg. a sketch something like:

No, can't tell you. It's a company secret. And, no, you can't disable the rules.

Seriously, what "rules" are you thinking about? The only "rules" that the IDE imposes are based on the file extension, invoking the correct compiler, and performing some sleight of hand in .pde files, to do all the stuff you didn't do, like creating function prototypes before the functions.

The IDE also determines what files to copy to the temporary folder based on what is included in the .pde file(s).

If you provide some [u]specific[/u] examples of how the "rules" are negatively impacting you, we can help you learn to live with them.

The behaviour of the IDE seems pretty bizarre to me, too. I still haven't figured out a good way to deal with projects that are implemented in multiple files, some of which depend on each other, some of which are common to multiple sketches. At the moment I simply push anything common out to a 'library' and tell the IDE to import it into my sketch. Which is a fiddle. I'd find it much easier if the rules for including header and code files into a sketch were clearly described somewhere. It seems to me that chucking that pde stuff in the bin and just programming it in straight forward 'C' and/or C++ would make it a whole lot simpler to use.

It seems to me that chucking that pde stuff in the bin and just programming it in straight forward 'C' and/or C++ would make it a whole lot simpler to use.

Isn't that what AVRStudio is for?

dxw00d: Isn't that what AVRStudio is for?

I don't know, is it? I haven't tried using it yet, but perhaps I should give it a go.

I haven't used it. I've only just started with the arduino, so I haven't hit any limitations with the IDE yet.

If you still interested... This seems to be all about "C linkage" in avr-gcc to use pure-c sources in your scetch you need to specify "extern "C"" for your pure-c includes. like this, for example: sketch.ino:

extern "C" 
{
#include "purec.h"
}
void setup()
{
   foo();
   foo();
   foo();
}
void loop(){}

purec.h:

#ifndef PUREC_H
#define PUREC_H
void foo();
#endif

purec.c:

#include "purec.h"
void foo()
{
   int a=1,b=2;
   int c=a+b;
   ...
   ...
}

I got the same issue when tried to use generated c-code for protobuf This explained solution I fond there http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=76358&start=0.

Hi Doug,

I’m a fairly new user as well and through trial, error and Google, these answers are what works for me…

shadowmint:
I mean, what it is supposed to do is concatenate all of your files into one big file, search of functions, generate prototypes and then run it. That’s what it says happens.

I believe it works like that if you put all your code in “.PDE” files - It does not do prototype
generation for other files and linking rules are different as well.

shadowmint:

  1. Telling how I can see the post-IDE .cpp files which are being generated. I’m using a Mac and I can’t seem to find them anywhere.

I’m not on a Mac, but holding the shift key while it builds keeps the interim files and shows verbose logging messages - I expect you’d even see the path to the files you want to examine.

shadowmint:
2) Tell me what the ‘best practice’ for multiple file sketches is?

Not sure about “best practice”, but my project has 1 PDE file, and lots of .CPP & .H pairs (code & prototypes) plus some extra .H files for value definitions.

shadowmint:
3) Tell me exactly what rules are applied to what types of files, and, if possible, if there is a way to disable these rules, so my code, as written, is compiled by the IDE

Also not sure about a “list of all the rules”, but here are some that I understand…

  1. Automatic prototype generation only occurs for .pde files

  2. In your .pde, #include the “XXX.h” file that has the prototypes for the functions you use - the “XXX.cpp” or “XXX.c” will then be be compiled and linked automatically. The same applies for .cpp (and probably .c) as well, so you can chain (eg: .pde includes “XXX.h”, “XXX.cpp” includes “YYY.h”, etc)

  3. The .h file is slightly different for .c and .cpp - simply changing the extension on the file means you need to change the .h file to suit [which makes it pretty obvious why I just use .cpp files]

.h for .c

#ifndef	MY_LIB_H
  #define MY_LIB_H

  #ifdef __cplusplus
    extern "C" {
  #endif

  char* MyFunc(unsigned char cX);

  #ifdef  __cplusplus
    }
  #endif
#endif

.h for .cpp

#ifndef	MY_LIB_H
  #define MY_LIB_H

  char* MyFunc(unsigned char cX);

#endif
  1. Including libraries [eg: “#include <EEPROM.h>”] from a “.cpp” file needs you to also include the library in the .pde - something to do with the linker only finding the “” from a .pde file.

There you go - that’s what works for me, as opposed to what is right or wrong :wink: I hope it helps!

AVR Libc docs --- the IDE uses AVR Libc.

You can also use AVR-GCC with a makefile and AVRdude to upload. Then you have full control of everything. :)

bubulindo...

Many, many thanks! I just downloaded the avr-gcc toolchain from

http://www.ladyada.net/learn/avr/setup-mac.html

and it's up and running (I'm looking at an assembler output listing in another window and smiling as I type.)

yea I got sick of it a year ago, everything I do now is in debian linux which just happens to have a nice little "apt-get arduino-core" which reduces your makefile down to a few lines of basic crap (mcu, programmer, speed, and what big file you need to use for everything else like core files and whatnot) then its just a matter of "make TARGET=file upload" and bob's your uncle