generating so files for ICU on AIX 7.1 - c++

I am trying to compile ICU 49.1.2 on AIX 7.1 with vaC++ 11.1.
By default ICU make files are configured to generate .a files instead of .so files.
There is an option to change the type of shared library extension inside /source/config/mh-aix-va file.
SO = a -> this can be changed to so to generate so files.
But when I change it to so, I get error as below. Any idea what else has to be done to generate .so files?
gmake[1]: Leaving directory `/export/home/cmbabu/xml/icu/source/common'
gmake[1]: Entering directory `/export/home/cmbabu/xml/icu/source/common'
gmake[1]: * No rule to make target `../lib/libicuuc.so', needed by `all-local'. Stop.
gmake[1]: Leaving directory `/export/home/cmbabu/xml/icu/source/common'
gmake: *** [all-recursive] Error 2
Thanks in advance.

To get rid of the error and successfully generate so files, I did lot of trial and errors and finally came up with a solution to as described below.
I had to modify few existing rules and add few more rules in config/mh-aix-va file.
Changes are...
line# 17 and 18: uncomment line #18
# If you readd this line, you must change the SO value
LDFLAGS += -brtl
line # 80 and 81: change the line # 81
# without the -brtl option, the library names use .a. AIX is funny that way.
SO= so
line # 92 to 99:
comment all these lines
#%.a : %.so
# ln -f $< $(SHARED_OBJECT_NO_VERSION)
# $(AIX_PREDELETE) $(AR) $(ARFLAGS) $# $(SHARED_OBJECT_NO_VERSION)
# rm -f $(SHARED_OBJECT_NO_VERSION)
#$(LIBDIR)/%.a : %.so
# ln -f $< $(SHARED_OBJECT_NO_VERSION)
# $(AIX_PREDELETE) $(AR) $(ARFLAGS) $# $(SHARED_OBJECT_NO_VERSION)
# rm -f $(SHARED_OBJECT_NO_VERSION)
Add below lines at line # 100:
$(LIBDIR)/%.so : %.so
ln -f $< $#
$(LIBDIR)/%$(SO_TARGET_VERSION).so : %.so
ln -s $< $#
$(LIBDIR)/%$(SO_TARGET_VERSION_MAJOR).so : %.so
ln -s $< $#

AIX by default (unless you link with -brtl) expects shared libraries to have the suffix .a. So you should not be changing SO=a to SO=so unless you also uncomment the -brtl flag in the makefile.
This is alluded to by the comment in the makefile:
without the -brtl option, the library names use .a. AIX is funny that way.

Related

Build error: make: Nothing to be done for 'compile'

I need to add my own package to the openwrt image. On the wiki of the project I found this article.
I tried to follow the instructions for it, but in the end I did not manage to add my own package to the source code tree (the build ignored its presence).
Because of this, I tried to find some other way. And it turned out to be a this instruction. I followed the directions from there and compiled my own package.
But as you can see, the source code of that package does not depend on others and does not require any other build header files. Also, his Makefile completely includes instructions for compiling.
define Build/Compile
$(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/helloworld.o -c $(PKG_BUILD_DIR)/helloworld.c
$(TARGET_CC) $(TARGET_LDFLAGS) -o $(PKG_BUILD_DIR)/$1 $(PKG_BUILD_DIR)/helloworld.o
endef
But now this does not suit me, since another package that I want to add already has such dependencies.
I tried to bypass them like this (copy the source code to the build folder and call the makefile located there) but nothing came of it:
define Build/Prepare
echo $PKG_NAME
mkdir -p $(PKG_BUILD_DIR)
cp $(SOURCE_DIR)/* $(PKG_BUILD_DIR)
$(Build/Patch)
endef
define Build/Compile
$(PKG_BUILD_DIR) $(MAKE)
endef
I am getting next output:
$ make -C package/feeds/mypackages/helloworld compile TOPDIR=$PWD
make: Entering directory '/home/username/mypackages/examples/helloworld'
bash: mkhash: command not found
bash: mkhash: command not found
bash: mkhash: command not found
bash: mkhash: command not found
bash: mkhash: command not found
bash: mkhash: command not found
bash: mkhash: command not found
bash: mkhash: command not found
make: Nothing to be done for 'compile'.
make: Leaving directory '/home/username/mypackages/examples/helloworld'
My full Makefile for both package and binary:
include $(TOPDIR)/rules.mk
PKG_NAME:=helloworld
PKG_VERSION:=1.0
PKG_RELEASE:=1
SOURCE_DIR:=/home/username/helloworld
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)
SECTION:=utils
DEPENDS:= +libstdcpp
TITLE:=helloworld
endef
define Package/helloworld/description
A simple "Hello, world!" -application.
endef
define Build/Prepare
echo $PKG_NAME
mkdir -p $(PKG_BUILD_DIR)
cp $(SOURCE_DIR)/* $(PKG_BUILD_DIR)
$(Build/Patch)
endef
define Build/Compile
$(PKG_BUILD_DIR) $(MAKE)
endef
define Package/helloworld/install
# Install binary
#$(INSTALL_DIR) $(1)/usr/bin
#$(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/usr/bin/
endef
$(eval $(call BuildPackage,$(PKG_NAME)))
,
TARGET = heloworld
OBJS = heloworld.o
CFLAGS += -Wall -Wextra
LDFLAGS += -lxsacpp -lxsac -lubus -lubox
CXXFLAGS += $(CFLAGS) -std=c++14
%.o : %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $#
all: $(TARGET)
$(TARGET): $(OBJS)
$(CXX) $(LDFLAGS) -o $# $^
clean:
rm *.o $(TARGET)
And actually my question is, what needs to be set in the Makefile to copy files correctly and call the local Makefile for package binary?
In order to copy files and directories you can use below step:
# copy all files and directories using **cp -r -f **
define Build/Prepare
echo $PKG_NAME
mkdir -p $(PKG_BUILD_DIR)
cp -r -f $(SOURCE_DIR)/* $(PKG_BUILD_DIR)
$(Build/Patch)
endef
In order to execute the local makefile use below step:
# Execute local makefile by giving path using '-C' option
define Build/Compile
`$(MAKE) -C $(PKG_BUILD_DIR)`
endef

Error loading shared libraries: cannot open shared object file :: on external hardware

I'm currently developing a C++ application which will reference multiple *.so libraries, each containing code for different machines - written in C.
I also have one shared object containing code from a custom namespace Utilities, which (as the name implies) contains basic utilities useful for the application (written in C++, like the rest of the application).
Currently, utilities.so is the only (custom) library referenced by the application.
The application compiles and links just fine, however executing it on the target hardware display the following error: bin/updater_v4test: error while loading shared libraries: ../../../bin/device_modules/utilities.so.1.0.0: cannot open shared object file: No such file or directory
When calling LDD on said application, the following output is shown: ../../../bin/device_modules/utilities.so.1.0.0 => not found
I've written a script which (upon make exiting without errors) collects all SOs and pushes them in to the /lib/ directory on the target hardware; meaning that upon each successful build of the application (whether in part or entirely), the updated files are pushed to the correct directory on the target hardware.
In an attempt to mimic other libraries I've used (e.g. zlib), I've attempted to create a symlink to the library file, with no luck (utilities.so.1.0.0 is the symlink, utilities.so is the actual SO).
utilities.so.1.0.0 --> utilities.so
At the moment I'm at a loss, and I can't waste much more time in trying to figure this out myself.
Below is an excerpt from the utilities Makefile:
include ../../common/user.mk
LIB_DIR=../../../libs/lib/powerpc-linux-gnu
CFLAGS=-Wall -ggdb -I../../libs/include -I../../common -lpthread -lddc -std=c++0x -I../../libs/include/zlib
LDFLAGS=../../libs/lib/powerpc-linux-gnu/libcurl.so.4 ../../libs/include/minizip/.libs/libminizip.so.1.0.0 \
-L ../../libs/lib \
-L ../../libs/lib/powerpc-linux-gnu \
-Wl,-rpath-link,../../libs/lib/powerpc-linux-gnu \
-lrt -lddc -lpthread -shared
BIN_DIR=../bin
CANONICAL_BIN_DIR := $(shell readlink -f $(BIN_DIR))
CANONICAL_CUR_DIR := $(shell readlink -f "./")
COMP_OBJECTS := $(wildcard *.cpp)
OBJECTS := $(patsubst %.cpp,%.o,$(wildcard *.cpp))
all: objects utilities.so
-cp --parents utilities.so $(GLOBAL_BIN_LIB)
-ln -s utilities.so utilities.so.1.0.0
-mv utilities.so.1.0.0 $(GLOBAL_BIN_LIB)
# -cp --parents *.h $(GLOBAL_HEADER_DIR)
-rm -f utilities.so
-rm -f *.o
for header in $(wildcard *.h); do \
echo $$header; \
ln -s $(CANONICAL_CUR_DIR)/$$header $(GLOBAL_HEADER_DIR)/$$header; \
done;
#printf "########## BUILT $^ ##########\n\n"
utilities.so: $(OBJECTS)
${CXX} $^ -o $# ${LDFLAGS}
objects: $(COMP_OBJECTS)
${CXX} -c $^ ${CFLAGS}
And now an excerpt from the application Makefile.
Here I've added a reference to the library in the linker flags, the header files are all included in from one directory.
include ../../../common/user.mk
LIB_DIR=../../../libs/lib/powerpc-linux-gnu
CFLAGS=-Wall -ggdb -I../../../libs/include -I${COMMON_DIR} -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I${HEADER_DIR}
LDFLAGS=../../../libs/lib/powerpc-linux-gnu/libcurl.so.4 ../../../libs/include/minizip/.libs/libminizip.so.1.0.0 ../../../bin/device_modules/utilities.so.1.0.0 \
-L ../../../libs/lib \
-L ../../../libs/lib/powerpc-linux-gnu \
-Wl,-rpath-link,../../../libs/lib/powerpc-linux-gnu \
-lrt -lddc -lpthread -L ${SO_DIR}
BIN_DIR=../bin
CANONICAL_BIN_DIR := $(shell readlink -f $(BIN_DIR))
CANONICAL_CUR_DIR := $(shell readlink -f "./")
all: test_update.bin
-cp --parents test_update.bin $(BIN_DIR)
-ln -s $(CANONICAL_BIN_DIR)/test_update.bin $(GLOBAL_BIN_APP)/test_update.bin
-rm -f *.bin
#printf "########## BUILT $^ ##########\n\n"
test_update.bin: main.o updaterdelegate.o commonfunctions.o tinyxml.o
${CXX} $^ -o $# ${LDFLAGS}
####################
# Required Files #
####################
main.o: Main.cpp
${CXX} -c $^ -o $# ${CFLAGS}
updaterdelegate.o: UpdaterDelegate.cpp
${CXX} -c $^ -o $# ${CFLAGS}
commonfunctions.o: $(shell python -c "import os.path; print os.path.relpath('${IMPL_CMN_FUNC}'.replace('\"', ''), '${CANONICAL_CUR_DIR}'.replace('\"', ''))")
${CXX} -c $^ -o $# ${CFLAGS}
tinyxml.o: $(shell python -c "import os.path; print os.path.relpath('${IMPL_TXML}'.replace('\"', ''), '${CANONICAL_CUR_DIR}'.replace('\"', ''))")
${CXX} -c $^ -o $# ${CFLAGS}
####################
# /Required Files #
####################
Just for gits and shiggles, I'll add the build output of the utilities.so and application.
utilities.so:
(Clean ommitted)
=============== CLEAN COMPLETE... BUILDING... ===============
make: Entering directory `~/_workspace/upv4/common/utils'
powerpc-linux-gnu-g++ -c ArgumentHandling.cpp Extensions.cpp Logging.cpp -Wall -ggdb -I../../libs/include -I../../common -lpthread -lddc -std=c++0x -I../../libs/include/zlib
ArgumentHandling.cpp: In member function ‘void Utilities::ArgumentHandler::freeMemory()’:
ArgumentHandling.cpp:136: warning: deleting ‘void*’ is undefined
powerpc-linux-gnu-g++ ArgumentHandling.o Extensions.o Logging.o -o utilities.so ../../libs/lib/powerpc-linux-gnu/libcurl.so.4 ../../libs/include/minizip/.libs/libminizip.so.1.0.0 -L ../../libs/lib -L ../../libs/lib/powerpc-linux-gnu -Wl,-rpath-link,../../libs/lib/powerpc-linux-gnu -lrt -lddc -lpthread -shared
cp --parents utilities.so """~/_workspace/upv4""/bin/device_modules"
ln -s utilities.so utilities.so.1.0.0
mv utilities.so.1.0.0 """~/_workspace/upv4""/bin/device_modules"
rm -f utilities.so
rm -f *.o
for header in ArgumentHandling.h Enumerations.h Extensions.h Logging.h; do \
echo $header; \
ln -s ~/_workspace/upv4/common/utils/$header """"~/_workspace/upv4""/bin/device_modules"/headers"/$header; \
done;
ArgumentHandling.h
Enumerations.h
Extensions.h
Logging.h
########## BUILT objects utilities.so ##########
make: Leaving directory `~/_workspace/upv4/common/utils'
=============== BUILD COMPLETE... PARSING... ===============
========== Warnings ==========
Total: 1
ArgumentHandling.cpp:136: warning: deleting ‘void*’ is undefined
========== Errors ==========
Total: 0
test_update.bin:
(Clean ommitted)
=============== CLEAN COMPLETE... BUILDING... ===============
make: Entering directory `~/_workspace/_workspace/upv4/test/app/src'
powerpc-linux-gnu-g++ -c Main.cpp -o main.o -Wall -ggdb -I../../../libs/include -I"""~/_workspace/_workspace/upv4""/common" -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I"""""~/_workspace/_workspace/upv4""/bin/device_modules"/headers""
powerpc-linux-gnu-g++ -c UpdaterDelegate.cpp -o updaterdelegate.o -Wall -ggdb -I../../../libs/include -I"""~/_workspace/_workspace/upv4""/common" -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I"""""~/_workspace/_workspace/upv4""/bin/device_modules"/headers""
powerpc-linux-gnu-g++ -c ../../../common/commonFunctions.cpp -o commonfunctions.o -Wall -ggdb -I../../../libs/include -I"""~/_workspace/_workspace/upv4""/common" -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I"""""~/_workspace/_workspace/upv4""/bin/device_modules"/headers""
powerpc-linux-gnu-g++ -c ../../../common/xmlreader/tinyxml2.cpp -o tinyxml.o -Wall -ggdb -I../../../libs/include -I"""~/_workspace/_workspace/upv4""/common" -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I"""""~/_workspace/_workspace/upv4""/bin/device_modules"/headers""
powerpc-linux-gnu-g++ main.o updaterdelegate.o commonfunctions.o tinyxml.o -o test_update.bin ../../../libs/lib/powerpc-linux-gnu/libcurl.so.4 ../../../libs/include/minizip/.libs/libminizip.so.1.0.0 ../../../bin/device_modules/utilities.so.1.0.0 -L ../../../libs/lib -L ../../../libs/lib/powerpc-linux-gnu -Wl,-rpath-link,../../../libs/lib/powerpc-linux-gnu -lrt -lddc -lpthread -L """"~/_workspace/_workspace/upv4""/bin/device_modules""
cp --parents test_update.bin ../bin
ln -s ~/_workspace/_workspace/upv4/test/app/bin/test_update.bin """~/_workspace/_workspace/upv4""/bin"/test_update.bin
ln: failed to create symbolic link `~/_workspace/_workspace/upv4/bin/test_update.bin': File exists
make: [all] Error 1 (ignored)
rm -f *.bin
########## BUILT test_update.bin ##########
make: Leaving directory `~/_workspace/_workspace/upv4/test/app/src'
=============== BUILD COMPLETE... PARSING... ===============
========== Warnings ==========
Total: 0
========== Errors ==========
Total: 0
The build script is custom, I built it myself to rid myself of the entire make output when I don't need it, and it parses out all the errors and warnings.
Due to the issue, I have turned make output back on.
Did I miss something during compilation/linking of the library, or is something going wrong during the linking of the application?
I'm inclined to say it's during compilation/linking of the library - although I don't know what exactly is going wrong, as everything is compiling and linking just fine.
Why is the application looking for the .so file in a path it can't possibly have?
I also made sure that the .so files are found with the $PATH variable, so the application should be able to find them.
The system normally searches for shared objects in a fixed set of directories. You can handle around this by defining the environment variable LD_LIBRARY_PATH and adding the directory where you install the shared libraries into.
Or you can add those libraries to some of the standard libraries directories and execute ldconfig -a to update the cache of shared libraries.
See ldconfig(8), for more info.
edit
There are two mechanisms to load a shared object.
The first is the normal library loading mechanism, that specifies what has to be loaded at start executable time, and implies linking your executable with the shared objects. This is what you do in your Makefile. You specify the shared executables, and the ld.so.xxx shared object (which is linked to your application when you are dynamically linking it) loads and follows all the unresolved identifiers to find a place for them in the virtual address space. The ld.so.xxx object uses the /etc/ld.so.cache file, that is just a hash table with the directories and shared executables available to be loaded this way. That file is indexed by what is called the soname (which is something useful to allow different versions of the same library to coexist in the same system) and normally maps to the last versioned shared found in the list of directories listed in the file /etc/ld.so.conf (this is static information to accelerate the process of loading libraries and is generated at each boot of the system). If the shared was found at link time (this mechanism is not used by ld, but only to load the libraries at program start time) to have a soname, then that soname is searched in the /etc/ld.so.cache to find the final file that has to be loaded. This cache is built on each boot of the system, so you don't have to cope with that, but only if you don't want to reboot and you install a new library for system use. It is important to note that shared objects must be given sonames for this to work, and that the list of directories in the file /etc/ld.so.conf are the only directories used to search for files. This means that for a standard library to be usable, you need to put it in one of this directories (or add the directory to the list in /etc/ld.so.conf) and then execute ldconfig -a to rebuild the cache and let it include a reference for the file under that soname.
The other way it to add to the list of search places a list in the form of a PATH variable. The variable is LD_LIBRARY_PATH so, in case you have your shared objects in ${HOME}/libs, you can add this line to your .profile:
export LD_LIBRARY_PATH=${HOME}/libs
or
setenv LD_LIBRARY_PATH ${HOME}/libs
this allows your library to live outside of the standard directories, but think twice, as this is a far less efficient way to load a file (as it involves processing a list of directories to look for the final shared objects, while the previous approach is direct, you ask for the file matching the soname that ld.so.xxx asks for, only one search, only one step)
The second is to use a library function dlopen(3) that allow you to load a shared object and do some housekeeping before calling anything inside. The dl library allows you to search for a symbol in the shared executable and then decide if you interpret it as data or a jump target. dlopen() just opens and loads into the virtual address space a shared object. It resolves the dependencies (if requested to) and is the more flexible way (but it is also nontransparent) to load unknown code for execution. This is the way plugins normally work. You decide in a config file, or dynamically what to load, and then you load it. The program doesn't have to know previously the symbol table of what you are dealing with and you are free to implement whatever you want in the module you are loading.
All of these methods work with ELF binaries, so you have a lot of freedom, but also a lot of complexity on it.
more...
As i've seen from your compilation:
you are including -l in the compile only commands, the libraries are only needed if you are linking an executable, don't put libraries in the compile phase.
for a library to be searched and selected by the linker, it has to be named as lib<name>.so (without the version info at the end) so this means that you normally find three names for a standard library (let me use the math library -lm as an example):
/usr/lib/libm.so.3.2.8 # this is the ELF file with the library contents.
/usr/lib/libm.so.3 -> libm.so.3.2.8 # this is the soname used to create the library.
/usr/lib/libm.so -> libm.so.3 # this is the actual file the ld(1) program searches for when using -lm.
those links have to be created, as the system normally doesn't. This is part of the installation procedure for a shared library. The soname link allows you to have different versions of a library and detect which one of them will be used at runtime (all must be compatible so you can interchange, when you make an incompatible modification, then you have to change the soname, so the system doesn't get confused on loading)
It is very important to know that the ld(1) program only selects a library if it is called lib<name>.so, with no version info. Indeed, the compiler first searchs for lib<name>.so, then for lib<name>.a, then it complains.
It is very important to put -L places to search for libraries before any -l option that will use those directories in the linking parameters.
You only need to run ldconfig -a and install the library in a system directory if you are not going to use the LD_LIBRARY_PATH mechanism. (this mechanism doesn't work for root account, for obvious reasons :))
Expecting this added comments give some light to the process.

Fortran compile error: makefile recipe for target '../lib/libSPheno.a(Mathematics.o)' failed

I am using a package and modified a SPheno4.F90 file in src folder. When I tried compile using make in src,
make: Warning: Archive '../lib/libSPheno.a' seems to have been
created in deterministic mode. 'Control.o' will always be updated.
Please consider passing the U flag to ar to avoid the problem.
Control.F90
make: Control.F90: Command not found
Makefile:86: recipe for target '../lib/libSPheno.a(Control.o)' failed
make: *** [../lib/libSPheno.a(Control.o)] Error 127
where in the makefile,
InDir = ../include
Mdir = ${InDir}
name = ../lib/libSPheno.a
ifeq (${F90},gfortran)
comp = -c -O -J${Mdir} -I${InDir}
LFlagsB = -O
endif
.SUFFIXES : .o .ps .f90 .F90 .a
bin/SPheno: ${name} SPheno4.o
${F90} -o SPheno ${LFlagsB} SPheno4.o ../lib/${name}
mv SPheno ../bin
${name}: ${name}(Control.o) ${name}(Mathematics.o) ${name}(RGEs.o)\
...
.f90.a:
${F90} ${comp} $<
ar -ruc $# $*.o
rm -f $*.o
...
while in ../lib folder, there is only a single file, libSPheno.a.
I totally have no idea about this error.
In fact, I don't understand each line in this makefile hence any advice for this kind of debugging is also welcome.

makefile: how to perform “ranlib” operation correctly

I downloaded a third party lib( Library link) which installs and compiles properly. It creates multiple object file (*.o), rather than creating executable, it's using gnu libtool to do some scripting. I plan to make some changes in some function; however, given I am new to linux, I thought to avoid libtool and just create executable.
I wrote a small makefile to link multiple object files and libraries and create an executable. All object files already exists. One library is as archive file (libtaucs.a). Based on online resouce, I came to know that I have to perform "ranlib" utlity as suggested here link. However, I get the following error:
$ make
make: *** No rule to make target `ranlib', needed by `test_me_DKU'. Stop.
Here is my makefile which I am using to link already existing object file (disclaimer: I barely understand makefile;so, you may find lots of error)
# Here is a simple Make Macro.
LINK_TARGET = test_me_DKU
# Here is a Make Macro that uses the backslash to extend to multiple lines.
##OBJS = tsnnls_test.o
OBJS = libtsnnls_la-taucs_malloc.o libtsnnls_la-taucs_ccs_order.o \
libtsnnls_la-taucs_ccs_ops.o libtsnnls_la-taucs_vec_base.o \
libtsnnls_la-taucs_complex.o libtsnnls_la-colamd.o \
libtsnnls_la-amdbar.o libtsnnls_la-amdexa.o \
libtsnnls_la-amdtru.o libtsnnls_la-genmmd.o \
libtsnnls_la-taucs_timer.o libtsnnls_la-taucs_sn_llt.o \
libtsnnls_la-taucs_ccs_base.o libtsnnls_la-tlsqr.o \
libtsnnls_la-tsnnls.o libtsnnls_la-lsqr.o \
tsnnls_test.o
# Here is a Make Macro defined by two Macro Expansions.
# A Macro Expansion may be treated as a textual replacement of the Make Macro.
# Macro Expansions are introduced with $ and enclosed in (parentheses).
REBUILDABLES = $(OBJS) $(LINK_TARGET)
clean :
rm -f $(REBUILDABLES)
echo Clean done
all : $(LINK_TARGET)
echo All done
RANLIB = ranlib
LIBTARGET= /usr/local/lib/taucs_full/lib/linux/libtaucs.a
tsnnls_test_LDADD = $(LDADD)
LIBS = -largtable2 -llapack -lblas -lquadmath $? $(RANLIB) $(LIBTARGET) -lm
# Here is a Rule that uses some built-in Make Macros in its command:
# $# expands to the rule's target, in this case "test_me.exe".
# $^ expands to the rule's dependencies, in this case the multiple files
# defined in OBJS (*.o)
$(LINK_TARGET) : $(OBJS) $(tsnnls_test_LDADD) $(LIBS)
g++ -g -o $# $^
Also, can someone please also explain this command ?
g++ -g -o $# $^
Your error is that you put $(tsnnls_test_LDADD) and $(LIBS) in the prerequisites line. That isn't correct. You want those on the linking line. They are flags to the linker.
You also don't want ranlib in LIBS because it is a command that needs to be run and not a flag to the linker.
That all being said you don't appear to be creating a static library (.a file) so you shouldn't need ranlib at all. Alternatively, since you probably do want to be making a library and not an executable (binary). You need to run ranlib on the .a file as indicated in the question/answer you linked.

Implicit Build Rules: GNU Make Multiple Makefiles Multiple Directories

I have the following directory structure:
.
..
./Graphic/
./Graphic/SymbolXLib
There are several other directories in this project but I won't list them for simplicities sake.I want a main makefile that drives the build of other Makefiles stored in their own directories. There are several project comming together, so I can't just move source around.
The main makefile is defined as:
[mehoggan#hogganz400 Core]$ cat ./Makefile
CORE_LIBS_DIR = libs
OBJS_DIR = obj/symb_obj
include ./Graphic/SymbolXLib/Makefile
The Graphic makefile is defined as:
#
# make BUILD_MODE={release|debug} OS_ARCH={32|64}
#
# default is 32-bit release build
#
BUILD_MODE = release
OS_ARCH = 64
OBJS_DIR = $(BUILD_MODE)$(OS_ARCH)
SRC = \
./Graphic/SymbolXLib/CartoCursor.cpp \
...
./Graphic/SymbolXLib/TextureConversion.cpp \
$(NULL)
CC = gcc -fPIC
OBJS = $(SRC:%.cpp=$(OBJS_DIR)/%.o)
COPTS = -m$(OS_ARCH) -O2
CDEFS = -DLINUXx86 \
-I../../../SharedArcGIS/Include/GraphicsPipeline/Display/SymbolX/SymbolXLib \
-I../../../SharedArcGIS/Include/System/Geometry/GeometryXLib \
-I../../../ArcSDE/pe/include \
-I../../../ArcSDE/shape/include
CFLAGS = $(COPTS) $(CDEFS) $(CINCS)
TARGET = libSymbolXLib.a
all : $(OBJS_DIR) $(OBJS_DIR)/$(TARGET)
$(OBJS_DIR) :
mkdir -p $(OBJS_DIR)
$(OBJS_DIR)/$(TARGET) : $(OBJS)
ar qc $# $^
$(OBJS_DIR)/%.o : %.cpp
$(CC) -c $(CFLAGS) -o $# $<
The response at the previous post (Previous Post) helped only if I moved alot of things around. I can't do this. So the question still remains, how do I get make to recognize the implicit build in a subdirectory from the main Makefile?
The error I am getting is
make: *** No rule to make target `release64/./Graphic/SymbolXLib/CartoCursor.o', needed by `release64/libSymbolXLib.a'. Stop.
I have to think you'd have far better success if you avoided include and instead use recursive make. In the top-level Makefile, something like:
graphic:
$(MAKE) -C Graphic
And the Makefile in Graphic/Makefile can have its sub-projects:
symbolxlib:
$(MAKE) -C SymbolXLib
and so on. You might need to add each of the targets to a default target or something similar to hang them all together on a single execution. You could give each of these targets an actual dependency (they should be .PHONY: if they don't have a dependency...) to rebuild them only when necessary or when commanded to by an upper-level target that touch(1)es "command files".
Alternatively, this paper recommends a different approach to avoid recursive make, but I've not yet read it -- and have found recursive make works well enough in projects I've been a part of that I don't mind recommending it.
Does this gnumake documentation help you?