sudar / Arduino-Makefile

Makefile for Arduino sketches. It defines the workflows for compiling code, flashing it to Arduino and even communicating through Serial.
http://hardwarefun.com/tutorials/compiling-arduino-sketches-using-makefile
GNU Lesser General Public License v2.1
2.02k stars 449 forks source link

Make fails if loop() and setup() #370

Open J-Dunn opened 9 years ago

J-Dunn commented 9 years ago

I have just installed Arduino-Makefile from github zip and made a Makefile for grbl-sketch.ino , which is provided as the sketch to build GRBL. It mostly seems to work but then fails with the following:

The code does build and run from the Arduino non-IDE.

mkdir -p build-uno
//bin/avr-gcc -mmcu=atmega328p -Wl,--gc-sections -Os -o build-uno/grbl_sketch.elf build-uno/grbl_sketch.ino.o build-uno/libcore.a  -lc -lm 
build-uno/libcore.a(main.cpp.o): In function `main':
main.cpp:(.text.startup.main+0x4): undefined reference to `setup'
main.cpp:(.text.startup.main+0xc): undefined reference to `loop'
collect2: error: ld returned 1 exit status
make: *** [build-uno/grbl_sketch.elf] Error 1

There is no loop() or setup() in GRBL, what has it dug up?

The GRBL ino file is just a list of includes , all the actual code is elsewhere, including it's own main.c that does not have loop() or setup().

It seems that is it digging main.cpp out of the arduino libraries somehow , which probably also means that it is not using main.c in the "grbl" library specified in the Makefile.

ARDUINO_LIBS=grbl grbl_L6474
 ARDUINO_PORT=/dev/ttyACM0
 BOARD_TAG =uno
 MONITOR_BAUDRATE=115200

 include  ~/avr/wkg/Arduino-Makefile/Arduino.mk
J-Dunn commented 9 years ago

OK, I've renamed it to avoid it getting picked up by the make rules:

mv /usr/share/arduino/hardware/arduino/cores/arduino/main.cpp main.cpp.not 

I don't know whether this could be handled more cleanly. Presumably it will now fail on any other sketches which would classically depend up main.cpp being there.

It now builds an object file 8328 bytes (25.4% Full) compared to 8,322 bytes produced with the (non) IDE.

I have not looked into the where that difference comes from. Having done a reportedly successful make upload, the program seems to work as before.

Man, am I glad to be free of that damned pseudo-IDE. Big thanks to all those who have made and maintained this project.

sej7278 commented 9 years ago

can't really tell without seeing all the sketch, but renaming /usr/share/arduino/hardware/arduino/cores/arduino/main.cpp doesn't seem like the way to go, when i've used cpp instead of ino i tend to replace setup() with main() and a loop method:

void loop()
{
}

int main(void)
{
    // arduino startup
    init();

    // arduino loop
    for (;;) {
        loop();
    }

    // return true
    return 0;
}    

its much nicer being able to just type "make" than that awful ide isn't it?

with the recent commit from a day or two ago, we should be able to handle multiple files with the same name though.

J-Dunn commented 9 years ago

Thanks, GRBL is here on github if you want to take a look at an example.

I'm wondering how the IDE avoids errors from main.cpp when main is provided in the library directory files.

Putting nothing but #include in the .ino seems to be one way to work around some of the mess the IDE can make, so it probably would be good to have a better solution than my quick hack to get this to build. It is not a one-off case.

http://www.gammon.com.au/forum/?id=12625

sej7278 commented 9 years ago

no idea, it must be the munging the ide does, as the compilation commands seem the same.

the grbl library does seem to reuse a lot of filenames/function names from the arduino core which doesn't help.

i got a bit further by adding this to grbl/main.c and renaming the main() function to grbl_main(), but then it started rewriting wiring.c functions too! its hardly a sketch made for the arduino it seems.


int setup(void) {return 0;}
int loop(void) {return 0;}
J-Dunn commented 9 years ago

GRBL is very much made for arduino and is used in thousands of installations typically CNC or 3D printers. It compiles and runs from IDE. Initial testing shows make; make upload; make monitor also work on this project, once main.cpp is hidden.

There are a couple of macros and other #defines that are over written but I'm not convinced from compiler output that the GRBL ones are always getting used.

One example is defining true as 0x01 rather than 0UL. This presumably intended to be shorter and do faster comparisons.

GRBL is claimed to work three stepper axes at up to 30kHz which is pretty impressive for an Arduino Uno. This means a lot of attention has been given to byte level efficiency and size optimization.

I'm not sure what you mean by rewriting Wiring.c , it generally avoids the grossly inefficient and repetitive crap in the Arduino libs like WriteDigital() . Toggling an output takes a few clock cycles, not a few microseconds !

The main point here is that if it compiles in IDE with main.cpp in place it probably should compile using the Makefile.

I don't see why it is necessary to explicitly compile everything in the ardino dir even if it is not linked. I would have thought that correctly constructed make rules would pull in only anything which is referenced by #include.

GRBL makes no reference to main.cpp and it seems to point to a structural defect in the Makefile if it is compiling it.

sej7278 commented 9 years ago

the IDE compiles everything - all the libs and cores even if they're not used, that's how it does its preprocessing - see issue #29

the only real difference is the Makefile doesn't do that preprocessing of the sketch - so you have to declare your methods before calling them from setup/loop, like proper C++

if the GRBL guys can figure out how to make it build, we welcome PR's.

J-Dunn commented 9 years ago

Thanks, I'd already seen #29

The preprocessing step is irrelevant in GRBL since it only has #includes in the sketch file, so even IDE has nothing to do there. However the IDE does not barf with the lack of setup() and loop().

Removing everything but #include from the sketch is one strategy to avoiding some of the brokenness of the IDE. Maybe this reflects more obscure, inconsistent behaviour of the IDE, I have not check whether this is the case.

It seems that in this respect the Makefile is trying to reproduce what IDE does ( ie mindlessly compiling "everything" ) but does not quite have the same definition of "everything" .

One thing I notice in /usr/share/arduino/hardware/arduino/cores/arduino is that there is no main.h yet there are .h files for all the stuff , like IPaddress, that the IDE does compile, even when not needed.

Neither do I think that the IDE builds everything for Leonardo when compiling for Uno. Maybe the Makefile is assuming that IDE is dumber than it really is.

It seems that building make.cpp is merely one symptom of a larger problem.

If the aim is to rebuild the same things as the IDE does, it seems some refining needs to be done. If we don't care how dumb the IDE is, the solution would be to have a classic set of make rules which build what is actually needed. That would be preferable IMHO.

I had assumes ( apparently wrongly ) that was what this Makefile was about.

sej7278 commented 9 years ago

neither the IDE nor the Makefile build cores for boards not specified

J-Dunn commented 9 years ago

That seems to contradict what several people were saying on #29 but I have not checked myself.

Do you have any understanding of why Makefile is building main.cpp and IDE does not ?

sej7278 commented 9 years ago

no, there's the odd library (SPI.h?) that the IDE builds for both platforms, but generally only the libraries not cores get built.

i've no idea why main.cpp is being built I'm afraid, it seems to be looking for setup() and loop(), so must be due to the lack of pre-processing that the IDE does.