Using APPLIBS with local toolchain

I’m trying to use the APPLIBS option with the local toolchain.

Here is my basic structure:

src/
  - main.cpp
inc/
 - neopixel/
   - neopixel.h       # These are
   - neopixel.cpp     # symlinks

In main.cpp I am using #include "neopixel/neopixel.h" and here is the make command I am using:

make all -s -C "$FIRMWARE_PARTICLE/firmware/main" APPDIR="src" APPLIBS="inc" TARGET_DIR="bin" PLATFORM="photon"

When I try to build I get an error like:

src/main.cpp:2:31: fatal error: neopixel/neopixel.h: No such file or directory
compilation terminated.
../build/module.mk:267: recipe for target '../build/target/user/platform-6-m/src/main.o' failed
make[2]: *** [../build/target/user/platform-6-m/src/main.o] Error 1
../../../build/recurse.mk:11: recipe for target 'user' failed
make[1]: *** [user] Error 2
../build/recurse.mk:11: recipe for target 'modules/photon/user-part' failed
make: *** [modules/photon/user-part] Error 2

Why is this happening? Is it because the files are symlinks? EDIT: I just checked by copying the files instead of making symlinks and it still happens.

I also get this error when trying to add TARGET_NAME="helloworld":

make[1]: *** No rule to make target '../../../build/target/user/platform-6-m/src/libuser.a', needed by 'bin/helloworld.elf'.  Stop.
../build/recurse.mk:11: recipe for target 'modules/photon/user-part' failed
make: *** [modules/photon/user-part] Error 2

Creating src/build.mk with the following and not using APPLIBS allows neopixel/neopixel.h to be included:

# Standard behavior must be included here
INCLUDE_DIRS += $(SOURCE_PATH)/$(USRSRC)  # add user sources to include path
CPPSRC += $(call target_files,$(USRSRC_SLASH),*.cpp)
CSRC += $(call target_files,$(USRSRC_SLASH),*.c)

APPSOURCES=$(call target_files,$(USRSRC_SLASH),*.cpp)
APPSOURCES+=$(call target_files,$(USRSRC_SLASH),*.c)

# Custom stuff can be added here
INCLUDE_DIRS += $(SOURCE_PATH)/../inc

Still getting the TARGET_NAME error. I’ll just have the .bin renamed.

I’m having the same trouble. Trying to work out a way around it. I’ll try you suggestion on the custom make script

And yes that works perfectly. When I grep -R for APPLIBS nothing is detected. I’m new to makefile but I’d assume the variable would need to be used somewhere.

There was however a APPLIBSV1 and V2. See here, https://github.com/spark/firmware/pull/1009.

I’m using the develop branch so maybe APPLIBS applies the the release branch.

2 Likes

This seems to no longer work. I’m getting an error like:

../../../build/target/user/platform-6-m/src//libuser.a(main.o): In function `setup':
/home/nrobinson/temp/derp/src/main.cpp:26: undefined reference to `Adafruit_NeoPixel::begin()'
/home/nrobinson/temp/derp/src/main.cpp:27: undefined reference to `Adafruit_NeoPixel::show()'
../../../build/target/user/platform-6-m/src//libuser.a(main.o): In function `Wheel(unsigned char)':
/home/nrobinson/temp/derp/src/main.cpp:51: undefined reference to `Adafruit_NeoPixel::Color(unsigned char, unsigned char, unsigned char)'
/home/nrobinson/temp/derp/src/main.cpp:54: undefined reference to `Adafruit_NeoPixel::Color(unsigned char, unsigned char, unsigned char)'
/home/nrobinson/temp/derp/src/main.cpp:57: undefined reference to `Adafruit_NeoPixel::Color(unsigned char, unsigned char, unsigned char)'
../../../build/target/user/platform-6-m/src//libuser.a(main.o): In function `rainbow(unsigned char)':
/home/nrobinson/temp/derp/src/main.cpp:39: undefined reference to `Adafruit_NeoPixel::numPixels() const'
/home/nrobinson/temp/derp/src/main.cpp:40: undefined reference to `Adafruit_NeoPixel::setPixelColor(unsigned short, unsigned long)'
/home/nrobinson/temp/derp/src/main.cpp:42: undefined reference to `Adafruit_NeoPixel::show()'
../../../build/target/user/platform-6-m/src//libuser.a(main.o): In function `__static_initialization_and_destruction_0':
/home/nrobinson/temp/derp/src/main.cpp:18: undefined reference to `Adafruit_NeoPixel::Adafruit_NeoPixel(unsigned short, unsigned char, unsigned char)'
/home/nrobinson/temp/derp/src/main.cpp:18: undefined reference to `Adafruit_NeoPixel::~Adafruit_NeoPixel()'
collect2: error: ld returned 1 exit status
../../../build/module.mk:222: recipe for target '/home/nrobinson/temp/derp/bin/src.elf' failed
make[1]: *** [/home/nrobinson/temp/derp/bin/src.elf] Error 1
../build/recurse.mk:11: recipe for target 'modules/photon/user-part' failed
make: *** [modules/photon/user-part] Error 2

Yes I got that too when I had a header that required implementation from an object. The script dosent create the external object file. I’m not good enough with make yet to know how to tell it to build the external library so i put my call in the include file where everything was compliled and linked.

1 Like

Just adding some things I’ve found :slight_smile:

Note that this uses APPLIBSV1 not APPLIBS

I have this layout:

firmware/user/applications/
 - myapp/
   - app.c
   - app.h

and elsewhere

- /path/libs/
  - somelib/src/
    - libname/
     - lib.c
     - lib.h
  - anotherlib/firmware/
     - lib2.c
     - lib2.h

The following command works nicely - no need for any makefiles

make PLATFORM=photon all APP=myapp APPLIBSV1="/path/libs/somelib/src /path/libs/anotherlib/firmware"

in my code I have:

#include libname/lib.h
#include lib2.h

both lib.c and lib2.c are built into libuser.a for that specific app

Note:
I know the docs say APPLIBS - but if you grep the entire codebase it’s not actually used anywhere in the makefiles :confused:
Instead the build tests use both APPLIBSV1 and APPLIBSV2
The difference seems to be that the V2 variant appends src/ to the elements in your path to adhere to the library packaging guidelines.

terse/gory details of MODULE_LIBS in the makefiles for some 'aha!'
core-firmware$ grep -r MODULE_LIBS *
build/module.mk:LIBCPPSRC += $(call target_files_dirs,$(MODULE_LIBSV1),,*.cpp)
build/module.mk:LIBCSRC += $(call target_files_dirs,$(MODULE_LIBSV1),,*.c)
build/module.mk:LIBCPPSRC += $(call target_files_dirs,$(MODULE_LIBSV2)/,src/,*.cpp)
build/module.mk:LIBCSRC += $(call target_files_dirs,$(MODULE_LIBSV2)/,src/,*.c)
build/module.mk:INCLUDE_DIRS += $(MODULE_LIBSV1)
build/module.mk:INCLUDE_DIRS += $(addsuffix /src,$(MODULE_LIBSV2))
build/module.mk:$(foreach lib,$(MODULE_LIBSV1) $(MODULE_LIBSV2),$(eval $(call build_LIB_files,$(lib))))
user/build.mk:MODULE_LIBSV1+=$(call remove_slash,$(APPLIBSV1))
user/build.mk:MODULE_LIBSV2+=$(call remove_slash,$(APPLIBSV2))
user/build.mk:MODULE_LIBSV2 += $(wildcard $(APPROOT)/lib/*)

Hope this helps local builders :smile:

(Documentation pull request)