Arduino IDE v.s. make utility?

Status
Not open for further replies.

wolfv

Well-known member
What are the advantages and disadvantages of using the Arduino IDE or make utility for compiling source code?

I have been using Vim and Arduino IDE. Now I am looking into using the make utility.
I will be including two libraries in this project
Code:
#include <Keyboard.h>
#include "Wire.h"
I am using Teesny 2.0 and Windows 7.

Thank you.
 
Last edited:
Make

+ You can use any code editor that you like, from simple like notepad to classicals as Emacs or hevyweight stuff like Eclipse
+ The error reporting and possibility to find the exact line where errors happens is better.
+ You can run other compilers/toolchains than the one included in Arduino/Teensyduino IDE
- Getting the make setup running is more work, but once it works it can be as simple as clicking a menu button saying [Flash]
- Using other versions of the gcc toolchains can break things
- Including Arduino libraries need some tinkering with the Makefile

Arduino IDE

+ (Mostly) Works with no extra setup
+ You dont need to hunt for the location of source and header files
- The Arduino build process seems to break some standard preprocessing things like #ifdef
- The errorreporting is a shadow of the raw error output, so some complexties are hidden from the user,
making things easy when they work and harder when theres problems.

This is my purely personal take, and I do use both.

/Magnus
 
Make

- Including Arduino libraries need some tinkering with the Makefile

/Magnus

Thank you Magnus for the make/Arduino IDE comparisons. I am afraid including Arduino libraries with make could be a time sink, Keyboard.h in particular.
Code:
#include <Keyboard.h>
Although Arduino IDE compiles with the #include <Keyboard.h>, there is no Keyboard.h on my system.
Keyboard class is defined in arduino-1.0.5\hardware\teensy\cores\usb_hid\usb_api.cpp
Do you know off hand how to make with the #include <Keyboard.h> or usb_api.h?
 
usb_api.h is in arduino-1.0.5\hardware\teensy\cores\usb_hid\

So you need to set an includepath to arduino-1.0.5\hardware\teensy\cores\usb_hid\ using the -I option in your makefile.
 
You can turn on full build information and error reporting in the Arduino IDE. They're off by default. Look in Preferences for these options.
 
usb_api.h is in arduino-1.0.5\hardware\teensy\cores\usb_hid\

So you need to set an includepath to arduino-1.0.5\hardware\teensy\cores\usb_hid\ using the -I option in your makefile.

Thanks mlu. I got the Wire.h included with the -I option and ran make. Got this compile error
Code:
D:/wolf/Documents/teensy/arduino-1.0.5/libraries/Wire/Wire.h:30: error: expected
 identifier or '(' before string constant
And here is line 30 of Wire.h
Code:
extern "C" void i2c0_isr(void);
Arduino IDE had no problem here, but make broke it. What is the "C" for?

Here is the full make output
Code:
D:\wolf\Documents\teensy\demo_c\MCP23018_2>make

-------- begin --------
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Compiling C: MCP23018_2.c
avr-gcc -c -mmcu=atmega32u4         -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsig
ned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -W
all -Wstrict-prototypes -Wa,-adhlns=./MCP23018_2.lst -ID:/wolf/Documents/teensy/
arduino-1.0.5/libraries/Wire -ID:/wolf/Documents/teensy/arduino-1.0.5/hardware/t
eensy/cores/teensy -std=gnu99 -MMD -MP -MF .dep/MCP23018_2.o.d MCP23018_2.c -o M
CP23018_2.o
In file included from MCP23018_2.c:18:
D:/wolf/Documents/teensy/arduino-1.0.5/libraries/Wire/Wire.h:30: error: expected
 identifier or '(' before string constant
D:/wolf/Documents/teensy/arduino-1.0.5/libraries/Wire/Wire.h:32: error: expected
 '=', ',', ';', 'asm' or '__attribute__' before 'TwoWire'
D:/wolf/Documents/teensy/arduino-1.0.5/libraries/Wire/Wire.h:93: error: expected
 '=', ',', ';', 'asm' or '__attribute__' before 'Wire'
MCP23018_2.c: In function 'main':
MCP23018_2.c:26: error: 'Wire' undeclared (first use in this function)
MCP23018_2.c:26: error: (Each undeclared identifier is reported only once
MCP23018_2.c:26: error: for each function it appears in.)
make: *** [MCP23018_2.o] Error 1
 
Thanks mlu. I got the Wire.h included with the -I option and ran make. Got this compile error
Code:
D:/wolf/Documents/teensy/arduino-1.0.5/libraries/Wire/Wire.h:30: error: expected
 identifier or '(' before string constant
And here is line 30 of Wire.h
Code:
extern "C" void i2c0_isr(void);
Arduino IDE had no problem here, but make broke it. What is the "C" for?

There are two langauges, C, and C++. C is the original language, and C++ is mostly an upwards compatible superset. One of the features of C++ is the ability to have multiple functions based on the number and type of the arguments. In doing so, the C++ compiler changes the name used in the actual object file to include the base and all of the types. In C, you do not have the ability to have different functions with the same name with different number of arguments or types of the arguments, so the name is not modified. The extern "C" says that the following definition uses the C naming style or not mangling the name.

What you did was call your function with a '.c' suffix, and the compiler assumed it was straight C. However, it included files that were for C++, and it got a syntax error, because C does not support the "C" in extern declarations.

The simplest solution is to rename your file to have a '.cc' or '.cpp' suffix, and then the compiler will compile it as a C++ object. Or you can use the '-x c++' option to tell the compiler to ignore the suffix and always treat the file as C++. If if you really want a challenge, change all of the header files so that they can be used with either C or C++, and then get the library authors, and IDE packagers like Paul/Arduino to adapt these changes. The first is the simplest approach.

I miss the nerd smiley that other forums have. :cool:
 
'extern "C"' instructs the C++ compiler to use C linkage/name mangling for the function.

You are trying to compile C++ code with the C compiler; 'gcc' is the C compiler, 'g++' the C++ one. 'extern "C"' is not valid C code. You should name your C++ file '.cpp', not '.c'.
 
The simplest solution is to rename your file to have a '.cc' or '.cpp' suffix,

Thanks Michael and tni. Changing my file suffix from MCP23018_2.c to MCP23018_2.cpp fixed it:) And I learned something!


But I got another compile error that makes no sense to me:
Code:
                 from MCP23018_2.cpp:18:
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:112:
38: error: macro "print" passed 2 arguments, but takes just 1
Why does the error message say "macro"? I don't see a macro on line 38.
Why does the compiler say print takes just 1 argument? The Print declaration shows 2 parameters.

MCP23018_2.cpp, line 18 is an include
Code:
#include "Wire.h"

line 112 of Print.h is inside the class Print declaration.
Code:
	void print(unsigned char n, int base)		{ printNumber(n, base, 0); }

inside the class Print definition in Print.ccp
Code:
#if ARDUINO >= 100
size_t Print::printNumber(unsigned long n, uint8_t base, uint8_t sign)
#else
void Print::printNumber(unsigned long n, uint8_t base, uint8_t sign)
#endif
{
 ...
Do you see the source of the compile error?
 
Some include file is defining print as a macro, and you need to track down where it is. Look for something that does '#define print(' (there might be any number of spaces or tabs between the '#' and 'define' and 'define' and 'print', but there won't be a space between 'print' and '('.

Because macros are textual, you should be careful when you use them (use inline functions where you can). A lot of people tend to use upper case in macros, so that it is less likely to use the macro for an ordinary identifier.

If you use -save-temps and -dD, you will see all of the macro definitions used in the .ii file (which is the logical output of the preprocessor before the compiler itself).
 
Thank you again Michael. As last time, you correctly called the compile error without even seeing the code. I am impressed.

I found the print macro on line 9 of the the print.h file (whereas the compile error is from Print.h).
Here is the print.h file in it's entirety
Code:
#ifndef print_h__
#define print_h__

#include <avr/pgmspace.h>
#include "usb_debug_only.h"

// this macro allows you to write print("some text") and
// the string is automatically placed into flash memory :)
#define print(s) print_P(PSTR(s))
#define pchar(c) usb_debug_putchar(c)

void print_P(const char *s);
void phex(unsigned char c);
void phex16(unsigned int i);

#endif
here is the Print class definition from Print.h, notice all the overloaded print() and println() methods.
Code:
class Print
{
  public:
	virtual void write(uint8_t);
	virtual void write(const char *str);
	virtual void write(const uint8_t *buffer, size_t size);
	void print(const String &s);
	void print(char c)				{ write((uint8_t)c); }
	void print(const char s[])			{ write(s); }
	void print(const __FlashStringHelper *f);

	void print(uint8_t b)				{ write(b); }
	void print(int n)				{ print((long)n); }
	void print(unsigned int n)			{ printNumber(n, 10, 0); }
	void print(long n);
	void print(unsigned long n)			{ printNumber(n, 10, 0); }

	void print(unsigned char n, int base)		{ printNumber(n, base, 0); }
	void print(int n, int base)			{ (base == 10) ? print(n) : printNumber(n, base, 0); }
	void print(unsigned int n, int base)		{ printNumber(n, base, 0); }
	void print(long n, int base)			{ (base == 10) ? print(n) : printNumber(n, base, 0); }
	void print(unsigned long n, int base)		{ printNumber(n, base, 0); }

	void print(double n, int digits = 2)		{ printFloat(n, digits); }
	void println(void);
	void println(const String &s)			{ print(s); println(); }
	void println(char c)				{ print(c); println(); }
	void println(const char s[])			{ print(s); println(); }
	void println(const __FlashStringHelper *f)	{ print(f); println(); }
	void println(uint8_t b)				{ print(b); println(); }
	void println(int n)				{ print(n); println(); }
	void println(unsigned int n)			{ print(n); println(); }
	void println(long n)				{ print(n); println(); }
	void println(unsigned long n)			{ print(n); println(); }

	void println(unsigned char n, int base)		{ print(n, base); println(); }
	void println(int n, int base)			{ print(n, base); println(); }
	void println(unsigned int n, int base)		{ print(n, base); println(); }
	void println(long n, int base)			{ print(n, base); println(); }
	void println(unsigned long n, int base)		{ print(n, base); println(); }

	void println(double n, int digits = 2)		{ print(n, digits); println(); }
  private:
	void printNumber(unsigned long n, uint8_t base, uint8_t sign);
	void printFloat(double n, uint8_t digits);
};
Below is the compiler output in it's entirety. There is one error for each overloaded print() and println() method not containing exactly one parameter, plus some warnings.
At this point I am considering going back to the Arduino IDE. What would you do?
Code:
D:\wolf\Documents\teensy\demo_c\MCP23018_2>make

-------- begin --------
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Compiling C: usb_debug_only.c
avr-gcc -c -mmcu=atmega32u4         -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsig
ned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -W
all -Wstrict-prototypes -Wa,-adhlns=./usb_debug_only.lst -ID:/wolf/Documents/tee
nsy/arduino-1.0.5/libraries/Wire -ID:/wolf/Documents/teensy/arduino-1.0.5/hardwa
re/teensy/cores/teensy -std=gnu99 -MMD -MP -MF .dep/usb_debug_only.o.d usb_debug
_only.c -o usb_debug_only.o

Compiling C: print.c
avr-gcc -c -mmcu=atmega32u4         -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsig
ned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -W
all -Wstrict-prototypes -Wa,-adhlns=./print.lst -ID:/wolf/Documents/teensy/ardui
no-1.0.5/libraries/Wire -ID:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy
/cores/teensy -std=gnu99 -MMD -MP -MF .dep/print.o.d print.c -o print.o

Linking: MCP23018_2.elf
avr-gcc -mmcu=atmega32u4         -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned
-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -Wall
 -Wstrict-prototypes -Wa,-adhlns=MCP23018_2.cpp -ID:/wolf/Documents/teensy/ardui
no-1.0.5/libraries/Wire -ID:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy
/cores/teensy -std=gnu99 -MMD -MP -MF .dep/MCP23018_2.elf.d MCP23018_2.cpp usb_d
ebug_only.o print.o --output MCP23018_2.elf -Wl,-Map=MCP23018_2.map,--cref -Wl,-
-relax -Wl,--gc-sections     -lm
cc1plus.exe: warning: command line option "-Wstrict-prototypes" is valid for Ada
/C/ObjC but not for C++
cc1plus.exe: warning: command line option "-std=gnu99" is valid for C/ObjC but n
ot for C++
In file included from D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cor
es/teensy/Stream.h:24,
                 from D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cor
es/teensy/HardwareSerial.h:5,
                 from D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cor
es/teensy/WProgram.h:25,
                 from D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cor
es/teensy/Arduino.h:1,
                 from D:/wolf/Documents/teensy/arduino-1.0.5/libraries/Wire/Wire
.h:26,
                 from MCP23018_2.cpp:18:
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:112:
38: error: macro "print" passed 2 arguments, but takes just 1
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:113:
28: error: macro "print" passed 2 arguments, but takes just 1
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:114:
37: error: macro "print" passed 2 arguments, but takes just 1
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:115:
29: error: macro "print" passed 2 arguments, but takes just 1
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:116:
38: error: macro "print" passed 2 arguments, but takes just 1
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:118:
37: error: macro "print" passed 2 arguments, but takes just 1
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:130:
58: error: macro "print" passed 2 arguments, but takes just 1
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:131:
49: error: macro "print" passed 2 arguments, but takes just 1
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:132:
57: error: macro "print" passed 2 arguments, but takes just 1
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:133:
50: error: macro "print" passed 2 arguments, but takes just 1
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:134:
58: error: macro "print" passed 2 arguments, but takes just 1
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:136:
59: error: macro "print" passed 2 arguments, but takes just 1
In file included from D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cor
es/teensy/Stream.h:24,
                 from D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cor
es/teensy/HardwareSerial.h:5,
                 from D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cor
es/teensy/WProgram.h:25,
                 from D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cor
es/teensy/Arduino.h:1,
                 from D:/wolf/Documents/teensy/arduino-1.0.5/libraries/Wire/Wire
.h:26,
                 from MCP23018_2.cpp:18:
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:101:
 error: expected identifier before '(' token
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:101:
 error: expected `)' before '__extension__'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:101:
 error: expected ',' or '...' before '__extension__'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:101:
 error: expected ';' before ')' token
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:102:
 error: expected identifier before '(' token
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:102:
 error: expected `)' before '__extension__'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:102:
 error: expected ',' or '...' before '__extension__'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:102:
 error: expected ';' before ')' token
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:103:
 error: expected `;' before 'void'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:103:
 error: expected identifier before '(' token
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:103:
 error: expected `)' before '__extension__'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:103:
 error: expected ',' or '...' before '__extension__'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:103:
 error: expected ';' before ')' token
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:104:
 error: expected `;' before 'void'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:104:
 error: expected identifier before '(' token
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:104:
 error: expected `)' before '__extension__'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:104:
 error: expected ',' or '...' before '__extension__'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:104:
 error: expected ';' before ')' token
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:106:
 error: expected identifier before '(' token
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:106:
 error: expected `)' before '__extension__'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:106:
 error: expected ',' or '...' before '__extension__'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:106:
 error: expected ';' before ')' token
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:107:
 error: expected `;' before 'void'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:107:
 error: expected identifier before '(' token
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:107:
 error: expected `)' before '__extension__'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:107:
 error: expected ',' or '...' before '__extension__'
D:/wolf/Documents/teensy/arduino-1.0.5/hardware/teensy/cores/teensy/Print.h:107:
 error: expected ';' before ')' token
MCP23018_2.cpp:50: error: expected `;' at end of input
MCP23018_2.cpp:50: error: expected `}' at end of input
MCP23018_2.cpp:50: error: expected unqualified-id at end of input
make: *** [MCP23018_2.elf] Error 1
 
Status
Not open for further replies.
Back
Top