Library project issues

Follow up to: https://forum.sierrawireless.com/t/link-error-undefined-reference-to/5819/1

I created a new test workspace and created:

  1. main application project
  2. library project #1
  3. library project #2

Dependency is:

  1. depends on 2)

  2. depends on 3)

  3. calls library function from 2)

  4. calls library function from 3)

When building the libraries I get no warnings
If I then build 1) I get:

C:\TESTLIB\libmain\[Target]_ARM_EABI_GCC_Debug/..\src/mylib.c:42: undefined reference to `MyLibInterface2'

Does the library linker not link in stuff from other libraries or what’s going on?

The project I discovered this with is rather large and worked without problems in the old (probably ancient by now) build environment where I could use ARM ADS compiler.

How are you managing dependencies between your projects?
Can you provide the linker command line?
GCC linker is sensible to the libraries order provided on the command line, unless is they are surrounded with -( and -) options. These options are handled by DS, if you use the integrated references system (app project should reference lib project simply by handling references in Project Properties > References page)

In “Properties for libmain” (my library project #1) -> Project References I have checked libsec (my library project #2).

In the source file for libmain I have an include for the libsec interface file.

Looking closer at the output when building libmain:

..\src\mylib.c:42: warning: implicit declaration of function 'MyLibInterface2'

buildlog for libsec:

10:17:12 **** Rebuild of configuration [Target]_ARM_EABI_GCC_Debug for project libsec ****
Info: Internal Builder is used for build
"C:\\Program Files (x86)\\Sierra Wireless\\Developer Studio\\tools\\armeabigcc\\4.4.1\\bin\\arm-none-eabi-gcc.exe" -D__DEBUG_APP__ -D__OAT_API_VERSION__=650 -DDS_DEBUG -D__arm -D__GNU_GCC__ "-IC:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.os.model.6.50.0.A1.201302051441_6.50.0.A1_201302051441\\resources/ADL/itf" "-IC:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.os.model.6.50.0.A1.201302051441_6.50.0.A1_201302051441\\resources/ADL/basic" "-IC:\\TESTLIB\\libsec\\inc" "-IC:\\TESTLIB\\libsec\\itf" -O0 -Os -ggdb3 -Wall -c -fshort-enums -fdollars-in-identifiers -nostartfiles -fno-strict-aliasing -fno-common -fomit-frame-pointer -mthumb-interwork -mthumb -msoft-float -mapcs -mno-apcs-stack-check -o "src\\mylib2.o" "..\\src\\mylib2.c" 
"C:\\Program Files (x86)\\Sierra Wireless\\Developer Studio\\tools\\armeabigcc\\4.4.1\\arm-none-eabi\\bin\\ar.exe" crs libsec.lib "src\\mylib2.o" 

10:17:12 Build Finished (took 469ms)

buildlog for libmain:

10:17:13 **** Rebuild of configuration [Target]_ARM_EABI_GCC_Debug for project libmain ****
Info: Internal Builder is used for build
"C:\\Program Files (x86)\\Sierra Wireless\\Developer Studio\\tools\\armeabigcc\\4.4.1\\bin\\arm-none-eabi-gcc.exe" -D__DEBUG_APP__ -D__OAT_API_VERSION__=650 -DDS_DEBUG -D__arm -D__GNU_GCC__ "-IC:\\TESTLIB\\libsec\\itf" "-IC:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.os.model.6.50.0.A1.201302051441_6.50.0.A1_201302051441\\resources/ADL/itf" "-IC:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.os.model.6.50.0.A1.201302051441_6.50.0.A1_201302051441\\resources/ADL/basic" "-IC:\\TESTLIB\\libmain\\inc" "-IC:\\TESTLIB\\libmain\\itf" -O0 -Os -ggdb3 -Wall -c -fshort-enums -fdollars-in-identifiers -nostartfiles -fno-strict-aliasing -fno-common -fomit-frame-pointer -mthumb-interwork -mthumb -msoft-float -mapcs -mno-apcs-stack-check -o "src\\mylib.o" "..\\src\\mylib.c" 
..\src\mylib.c: In function 'MyLibInterface':
..\src\mylib.c:42: warning: implicit declaration of function 'MyLibInterface2'
"C:\\Program Files (x86)\\Sierra Wireless\\Developer Studio\\tools\\armeabigcc\\4.4.1\\arm-none-eabi\\bin\\ar.exe" crs libmain.lib "src\\mylib.o" 

10:17:13 Build Finished (took 473ms)

Where can the linker command line be found? I looked in the project but couldn’t find it there…

In the libmain source file:

#include "mylib.h"
#include "mylib2.h"

If I instead do:

#include "mylib2.h"
#include "mylib.h"

The “Implicit declaration of function”… warning disappears… but still get the original error “undefined reference to…” when I try to build the main application…

Info: Internal Builder is used for build
"C:\\Program Files (x86)\\Sierra Wireless\\Developer Studio\\tools\\armeabigcc\\4.4.1\\bin\\arm-none-eabi-g++.exe" -Wl,--script,gcc.lkopt "src\\main.o" "src\\generated.o" -llibsec -llibmain -Wl,-( -nostartfiles "-LC:\\TESTLIB\\libsec\\[Target]_ARM_EABI_GCC_Debug" "-LC:\\TESTLIB\\libmain\\[Target]_ARM_EABI_GCC_Debug" -Os -O2 -fshort-enums -fdollars-in-identifiers -ggdb3 -u _siwiStubsImplementation -fomit-frame-pointer -mthumb-interwork -mthumb -mcpu=arm926ej-s -march=armv5te -msoft-float -mfpu=fpa -mapcs -mno-apcs-stack-check -Wl,-nmagic -Wl,-Map,app.map "C:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.os.model.6.50.0.A1.201302051441_6.50.0.A1_201302051441\\resources\\ADL\\RVDS_ADL.lib" -Wl,-) -oapp.axf 
C:\TESTLIB\libmain\[Target]_ARM_EABI_GCC_Debug\liblibmain.a(mylib.o): In function `MyLibInterface':
C:\TESTLIB\libmain\[Target]_ARM_EABI_GCC_Debug/..\src/mylib.c:43: undefined reference to `MyLibInterface2'
collect2: ld returned 1 exit status

After testing around I find the following…

If I only have a project reference from main application to libmain, then I get the error…
If I have a project reference from main application to both libmain and libsec, I get the error if the order of the libs in Paths and Symbols -> Libraries is “incorrect” but not when I manually switch the order…

Question 1: Why does the main application have to reference both library projects when the main application only directly uses stuff from libmain?
Question 2: Why is the order of the libraries not inferred automatically?
Question 3: Why does libmain not link in the necessary parts from libsec?

Even if your final app doesn’t directly use the functions implemented in a lib, it will need to embed that lib in the final link, and it’s true that this link is not automagically propagated from the requiring lib dependency.
Anyway, you’re doing the things right.
We’ve seen in the linker command line that the automated Inputs management of the linker ($(INPUTS) variable, which represents the list of the app objects + the -l options for the libraries) is provided out of the -Wl,-( & -Wl,-) containing options.
As a workaround, you can give a try to modify the linker command line:

  • Go to Project Properties > C/C++ Build > Settings > C/C++ linker
  • Give a look to the command line: it should looks like:
${COMMAND} ... ${INPUTS} "-Wl,-(" ${FLAGS} ${WmOatIdeLibraryFiles} "-Wl,-)" ...
  • Try to move the $(INPUTS) variable inside the -Wl,-( & -Wl,-) containing options:
${COMMAND} ... "-Wl,-(" ${INPUTS} ${FLAGS} ${WmOatIdeLibraryFiles} "-Wl,-)" ...
  • Rerun the build: it should now be successful, whatever is the Libraries order
    Please let us know if the workaround is correct.

Changing from:

${COMMAND} -Wl,--script,${WmOatIdeGccScript} ${INPUTS} "-Wl,-(" ${FLAGS} ${WmOatIdeLibraryFiles} "-Wl,-)" ${OUTPUT_FLAG}${OUTPUT_PREFIX}${OUTPUT}

to:

${COMMAND} -Wl,--script,${WmOatIdeGccScript} "-Wl,-(" ${INPUTS} ${FLAGS} ${WmOatIdeLibraryFiles} "-Wl,-)" ${OUTPUT_FLAG}${OUTPUT_PREFIX}${OUTPUT}

seems to have worked.

At least I no longer get any errors :smiley:

Thanks for the feedback.
We’ll push the tests a little bit further to make sure there are no hidden impacts, before integrating this as the default command line in next DS release.