Arduino-Makefile
Arduino-Makefile copied to clipboard
Local libraries in sketch directory
Hi guys!
I've made some test. It seems that if I put my .h
and .cpp
files in my sketch folder, it compiles, but if I put them inside a lib
directory inside the sketch folder, it does not work...
So this works:
.
├── Blink.ino
├── Makefile
├── MyFirstLib.cpp
└── MyFirstLib.h
But this does not:
.
├── Blink.ino
├── Makefile
└── lib
├── MyFirstLib.cpp
└── MyFirstLib.h
It this normal? :)
yes that's normal and seems to be fixed by my PR #245 which you said you'd test :-)
I tried with your PR and I get the following error in the second example I described:
undefined reference to `MyFirstClass::MyFirstClass()'
actually my USER_LIB_PATH
is defined to something else.
the fact that it's not working doesn't surprise me. But I'm wondering if it could be useful to automatically look for libs inside the sketch directory. I often find myself putting code inside another lib
directory inside my sketch directories for local code.
But maybe it's juste me and in this case it is not useful :)
well USER_LIB_PATH should not be defined as one thing and your libraries stored elsewhere really.
could you maybe confirm it works if your libs are in your USER_LIB_PATH, then we could probably merge #245 and keep this open as a feature request, although your last comment seems to contradict your first one! ;-)
I confirm that it works when my libs are in my USER_LIB_PATH :)
and we can keep this as a feature request.
in your first comment you say that if you put the library files in the same directory (1) as your sketch it works, but if you put them in a subdirectory (2) that's different to
$(USER_LIB_PATH)
it doesn't?
Exactly. I've tested (1) and (2) with the Blink
example in the vanilla Arduino-Makefile. I've written a little lib to test this, you can find it here.
Case (1)
In case (1), I have the following:
tree
structure
.
├── Blink.ino
├── Makefile
├── MyFirstLib.cpp
└── MyFirstLib.h
Blink.ino
#include "MyFirstLib.h"
MyFirstClass object;
void setup() {
pinMode(13, OUTPUT);
Serial.begin(115200);
}
void loop() {
digitalWrite(13, HIGH);
object.methodNumberOne();
delay(1000);
digitalWrite(13, LOW);
object.methodNumberTwo();
delay(1000);
}
Makefile
BOARD_TAG = uno
ARDUINO_LIBS =
include ../../Arduino.mk
Conclusion
This compiles and works on an Arduino Uno
Case (2)
In case (2), I have the following:
tree
structure
.
├── Blink.ino
├── Makefile
└── lib
├── MyFirstLib.cpp
└── MyFirstLib.h
Blink.ino
#include "lib/MyFirstLib.h"
MyFirstClass object;
void setup() {
pinMode(13, OUTPUT);
Serial.begin(115200);
}
void loop() {
digitalWrite(13, HIGH);
object.methodNumberOne();
delay(1000);
digitalWrite(13, LOW);
object.methodNumberTwo();
delay(1000);
}
Makefile
BOARD_TAG = uno
ARDUINO_LIBS =
include ../../Arduino.mk
Conclusion
This does not compile, I get the following error:
/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/avr-gcc -mmcu=atmega328p -Wl,--gc-sections -Os -o build-uno/Blink.elf build-uno/Blink.o build-uno/libcore.a -lc -lm
build-uno/Blink.o: In function `global constructors keyed to object':
Blink.ino:(.text._GLOBAL__I_object+0x4): undefined reference to `MyFirstClass::MyFirstClass()'
build-uno/Blink.o: In function `loop':
Blink.ino:(.text.loop+0x12): undefined reference to `MyFirstClass::methodNumberOne() const'
Blink.ino:(.text.loop+0x2c): undefined reference to `MyFirstClass::methodNumberTwo() const'
make: *** [build-uno/Blink.elf] Error 1
Other cases based on case (2)
If I set USER_LIB_PATH = $(realpath ./lib)
and #include "lib/MyFirstLib.h"
, it does not work and I get the same error.
If I set USER_LIB_PATH = $(realpath ./lib)
and #include "MyFirstLib.h"
as I would normally do, it does not work and I get the same error.
But if I set USER_LIB_PATH = $(realpath ./lib)
and I move the library's .h
and .cpp
inside a folder of the same name, i.e. ./lib/MyFirstLib
, it does work:
.
├── Blink.ino
├── Makefile
└── lib
└── MyFirstLib
├── MyFirstLib.cpp
└── MyFirstLib.h
Conclusion
What do you think of that? Was I clear? :) I can make more tests if you want.
@sej7278 no I haven't tried setting ARDUINO_LIBS
but I'd like to do it without that as in a real project I may have a lot of different libs.
As for relative vs absolute path, i don't want my devs to change every include to make it work on their machine. It would be easier for everyone to just clone my computer and use the same username :) (kidding)
it's not urgent, take your time. and may be the Makefile is just not intended to be used this way.
I will try it then :)
ahhhhh! i've got it now. you're saying you want to put library headers/source inside the lib/ directory instead of lib/MyFirstLib/
i don't think that's even good c/c++ is it - what if two libraries have headers with the same name? certainly wouldn't be supported by the ide which moans if your sketch filename doesn't match the directory name.
yep that's the idea.
I have my main libraries such as Motors, Leds, Sensors, and stuff inside USER_LIB_PATH
. Then, on a per sketch basis, I like to write Behaviors (a .h
and a .cpp
) that I'd like to put inside a folder inside my sketch folder.
You might be right, putting everything into a single folder might not be a good idea, so I'm willing to have something like lib/MyFirstLib
:)
So the feature request would be to automatically look for files to include inside the sketch directory. But if it's too complex, I'll do otherwise.
I agree with you, but it seems to work. have you tried it yourself?
it seems only pde/ino files are checked for only a single file, cpp files are missed out of the checks from around line 709-744
could you try with this simple patch. it seems to work for a very basic test case of including a header file and reading a constant from it (not sure how to make a test case with a .cpp file that isn't a library, that's just weird c++):
Blink.ino:
#include "includes/myheader.h"
Directory structure:
Blink.ino
Makefile
includes/
myheader.h
Patch:
diff --git a/Arduino.mk b/Arduino.mk
index c1981d0..85b5a8d 100644
--- a/Arduino.mk
+++ b/Arduino.mk
@@ -774,6 +774,8 @@ ifndef ARDUINO_LIBS
$(shell sed -ne "s/^ *\# *include *[<\"]\(.*\)\.h[>\"]/\1/p" $(LOCAL_SRCS)))
ARDUINO_LIBS += $(filter $(notdir $(wildcard $(USER_LIB_PATH)/*)), \
$(shell sed -ne "s/^ *\# *include *[<\"]\(.*\)\.h[>\"]/\1/p" $(LOCAL_SRCS)))
+ ARDUINO_LIBS += $(filter $(notdir $(wildcard includes/*)), \
+ $(shell sed -ne "s/^ *\# *include *[<\"]\(.*\)\.h[>\"]/\1/p" $(LOCAL_SRCS)))
endif
########################################################################
it works with the header but not with the MyFirstLib.