Can't link against libsqlite3.a to create my own static library - sqlite

I'm creating a static library that contains some objects including one that depends on sqlite3. This is my make file; it basically compiled the 3 cpp files into objects, put them into a .a lib and then use this library to get my main binary
CPPSRCS := \
$(LIBDIR)/database/active_database.$(SRCEXT) \
$(LIBDIR)/sd_card/sd_card.$(SRCEXT) \
$(LIBDIR)/led/led.$(SRCEXT)
OBJS := $(CPPSRCS:.cpp=.o)
lib/%.o: %.$(SRCEXT)
$(CXX) $(CXXFLAGS) -c $^ -o $# -lsqlite3
lib_$(APP).a: $(OBJS)
$(AR) rcs lib_$(APP).a $(OBJS)
$(APP): lib_$(APP).a
$(CXX) $(CXXFLAGS) $(SRCDIR)/$#.$(SRCEXT) -o $(DESTDIR)/$# lib_$(APP).a
My static library is built but when trying to get my binary against it I get undefined reference:
lib_XX.a(active_database.o): In function `database::ActiveDatabase::sqlite_exec_wrapper(std::string, int (*)(void*, int, char**, char**), void*)':
database/active_database.cpp:174: undefined reference to `sqlite3_exec'
database/active_database.cpp:178: undefined reference to `sqlite3_free'
lib_XX.a(active_database.o): In function `database::ActiveDatabase::init_db()':
I can see that -lsqlite3 (in /usr/lib) is not included in the compilation but I can't seem to force it to be included when I build my static library.

-lsqlite3 is ignored when compiling into object files because no linking happens.
You have three options.
You can add the SQLite object files to your static library lib_XX.a.
You can perform a relocatable link and produce a single .o file which contains the entire static library and SQLite, using ld -r.
Or consumers of your library need to link to your library and SQLite, using -l_XX -lsqlite3.
The last option is the most common approach and can be automated somewhat with tools like pkg-config.

Related

gcc Compling and linking object file and source file at the same time

In a nutshell , the issue is I have some object file (say a.o , b.o ) and some source file (f.c and g.c)
I have to compile and link in a single step.
This is what I am doing but I don't think this is the write way atleast I should give something like -l or -L for linking
gcc -Wall -O0 -ggdb -fPIC a.o b.o f.c g.c -o executable
This is the correct way, -l is used to link to a library (for example, the ptheads library needs -lpthread) and -L is used to add directories to the directories in which the linker looks for library files.
There is nothing wrong with compiling the software this way.
Most build systems build files one at a time in order to avoid having to rebuild the object file in case the source file was not modified and the object file still exists. If you are fine with rebuilding code, then your approach is perfectly valid.

How to specify Libs variable of pkgconfig during its generation by qmake?

I want to set Libs: line via qmake .pro file and I try doing it like this:
LIBS += -ldl
to make my target executable be also linked with dl library because my library I am trying to link it with uses dl inside. However, this does not work, and qmake puts this string into Libs.private section instead which is not passed to gcc command line during compilation and so I am unable to produce an executable:
Libs.private: -ldl
while I want it to be in Libs: line like that:
Libs: -lmylibrary -ldl
I also can't find any references to QMAKE_PKGCONFIG_* variables anywhere in the web, is there any?
Is used for generating .pc files:
CONFIG += create_pc create_prl no_install_prl
By greping for QMAKE_PKGCONFIG_ I found the following in ~/5.12.0/clang_64/mkspecs/features/qt_module.prf
QMAKE_PKGCONFIG_DESTDIR
QMAKE_PKGCONFIG_LIBDIR
QMAKE_PKGCONFIG_INCDIR
QMAKE_PKGCONFIG_CFLAGS
QMAKE_PKGCONFIG_NAME
QMAKE_PKGCONFIG_FILE
QMAKE_PKGCONFIG_REQUIRES
QMAKE_PKGCONFIG_DESCRIPTION
QMAKE_PKGCONFIG_INSTALL_REPLACE
From the man page for pkg-config:
Libs.private:
This line should list any private libraries in use.
Private libraries are libraries which are not exposed through your library,
but are needed in the case of static linking.
This differs from Requires.private in that it references
libraries that do not have package files installed.
So i guess as long as you don't export them through your lib they will end up in Libs.private.

How to solve undefined reference errors when linking log4cxx in qmake project

It's the second day I'm trying to marry Qt5, MinGW and log4cxx.
Even after I've compiled everything successfully, linked apr, apr-util and log4cxx libraries, ld gives me a bunch of "undefined reference" problems.
It looks like different settings were specified during log4cxx compilation (I'm using ant).
Was anyone able to successfully compile and use log4cxx with MinGW?
Environment:
log4cxx trunk
apr 1.4.6
apr-util 1.5.2
latest MinGW
I'm using Qt 5 with latest MinGW as a compiler
What I've done:
compiled log4cxx using ant with the following command: "ant
-Dcompiler=gcc -Dfind=false -DLOG4CXX_STATIC=1 -Dlib.type=static"
added result libraries to my project in pro file: "LIBS +=
-L../log4cxx/lib LIBS += -llibapr-1 -llibaprutil-1 -lliblog4cxx"
And now, as I try to link my project, I'm getting the next:
*C:/mingw/bin/mingw32-make -f Makefile.Debug
mingw32-make[1]: Entering directory 'C:/Work/SPP_Development/AutoHaul/Sub-systems/TCS/Source/build-SimulatorEngine-Standalone_MinGW-Debug'
g++ -Wl,-subsystem,windows -mthreads -o debug\SimulatorEngine.exe object_script.SimulatorEngine.Debug -lmingw32 -lqtmaind -L../log4cxx/lib -llibapr-1 -llibaprutil-1 -lliblog4cxx -LC:\Qt\Qt5.0.1\5.0.1\mingw47_32\lib -lQt5XmlPatternsd -lQt5Widgetsd -lQt5Networkd -lQt5Xmld -lQt5Guid -lQt5Cored -llibEGLd -llibGLESv2d -lgdi32 -luser32
Makefile.Debug:200: recipe for target 'debug\SimulatorEngine.exe' failed
mingw32-make[1]: Leaving directory 'C:/Work/SPP_Development/AutoHaul/Sub-systems/TCS/Source/build-SimulatorEngine-Standalone_MinGW-Debug'
Makefile:34: recipe for target 'debug' failed
../log4cxx/lib/liblog4cxx.lib(mutex.o): In function `ZN7log4cxx7helpers5MutexC2ERNS0_4PoolE':
c:/Work/log4cxx/apache-log4cxx-trunc/src/main/cpp/mutex.cpp:35: undefined reference to `apr_thread_mutex_create#12'
../log4cxx/lib/liblog4cxx.lib(mutex.o): In function `ZN7log4cxx7helpers5MutexC2EP10apr_pool_t':
c:/Work/log4cxx/apache-log4cxx-trunc/src/main/cpp/mutex.cpp:45: undefined reference to `apr_thread_mutex_create#12'
../log4cxx/lib/liblog4cxx.lib(mutex.o): In function `ZN7log4cxx7helpers5MutexD2Ev':
c:/Work/log4cxx/apache-log4cxx-trunc/src/main/cpp/mutex.cpp:55: undefined reference to `apr_thread_mutex_destroy#4'*
It looks like log4cxx library cannot findfunctions declared and defined in the apr library by whatever reason.
Is there any way to analyze the problem further to see why is this happening?
I will describe the 1st problem you have and give the solution for it. If it does not solve your problem, do not revert back because that would be just the 1st step of fixing process, and I will gradually expand the answer to solve more incoming issues as long as you provide relevant feedback on each fix until we finally nail it down. So, lets begin.
First of all, you add libraries into LIBS variable in a wrong way. You have 2 options to do it right:
#1
LIBS += $${PWD}/../log4cxx/lib/libapr-1.a
LIBS += $${PWD}/../log4cxx/lib/libaprutil-1.a
LIBS += $${PWD}/../log4cxx/lib/liblog4cxx-1.a
#2
LIBS += -L$${PWD}/../log4cxx/lib
LIBS += -lapr-1
LIBS += -laprutil-1
LIBS += -llog4cxx-1
NOTE: Of course one liner is possible too:
LIBS += -L$${PWD}/../log4cxx/lib -lapr-1 -laprutil-1 -llog4cxx-1
NOTE: Using line continuation (\) for readability is possible too:
LIBS += -L$${PWD}/../log4cxx/lib \
-lapr-1 \
-laprutil-1 \
-llog4cxx-1
You need to take care of the proper link order: liblog4cxx depends on libapr*, so the libapr entries need to come after liblog4cxx:
LIBS += -L../log4cxx/lib \
-llog4cxx-1 \
-lapr-1 \
-laprutil-1
The reason is that dependencies are resolved left to right, so that in your case the apr libraries have been read, and forgotten, when log4cxx comes along that has some external symbols that need resolving. ld won't read the apr libraries again (has to do with cyclic dependency issues, and historical reasons).
To test if this works, you can try running the command
g++ -Wl,-subsystem,windows -mthreads -o debug\SimulatorEngine.exe object_script.SimulatorEngine.Debug -lmingw32 -lqtmaind -L../log4cxx/lib -lliblog4cxx -llibapr-1 -llibaprutil-1 -LC:\Qt\Qt5.0.1\5.0.1\mingw47_32\lib -lQt5XmlPatternsd -lQt5Widgetsd -lQt5Networkd -lQt5Xmld -lQt5Guid -lQt5Cored -llibEGLd -llibGLESv2d -lgdi32 -luser32
from the directory
C:/Work/SPP_Development/AutoHaul/Sub-systems/TCS/Source/build-SimulatorEngine-Standalone_MinGW-Debug
yourself first. But perhaps just modifying the .pro file is simplest.

Out of tree builds with makefiles and static pattern rules

I'm working on some bare-metal embedded code that runs on ARM, and thus has to deal with the whole ARM vs. THUMB mode distinction. The current build system uses static pattern rules to determine whether to compile files in ARM or THUMB mode.
$(ACOBJS) : %.o : %.c
#echo
$(CC) -c $(CFLAGS) $(AOPT) -I . $(IINCDIR) $< -o $#
$(TCOBJS) : %.o : %.c
#echo
$(CC) -c $(CFLAGS) $(TOPT) -I . $(IINCDIR) $< -o $#
Where ACOBJS is a list of output objects that should be in ARM mode and the same for TCOBJS and Thumb mode. These lists are created from the list of sources in the usual manner of
ACOBJS = $(ACSRC:.c=.o)
TCOBJS = $(TCSRC:.c=.o)
Currently this results in the object files from the build being strewn about the source tree, which I don't particularly desire. I've been trying to set this up for out of tree builds but haven't been able to get this to work. I don't necessarily need to get full out of tree builds working, but I would like to at least be able to use an output directory under which all the intermediate files end up going. What is the best strategy to achieve this under these constraints?
One option I'm considering is using either automake or the whole autotools toolchain to build a makefile. This would seem to support creating the type of makefile I want, but seems like overkill. It also seems like there would be an inherent impedance mismatch between autotools, which is designed for portable builds, and bare-metal embedded systems, where things like host tuple are dictated by the target micro.
This is a bit old but I was just trying to do the same thing this was the first google hit. I thought it was worth sharing another approach since neither answer is convenient if you're not using autotools and want to be able to build in any directory with a single command and later just blow away that directory.
Here's an example of a Makefile that refers to files relative to the directory containing the Makefile.
MAKEFILE_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
MFD := $(MAKEFILE_DIR)
CXX=g++
CXXFLAGS=-std=c++14 -Wall -Wextra -pedantic -c
test: test.o adjacency_pointers_graph.o
$(CXX) $^ -o $#
%.o: $(MFD)/%.cpp $(MFD)/adjacency_pointers_graph.h
$(CXX) $(CXXFLAGS) $< -o $#
Then to do an sort of source build:
mkdir build
cd build
make -f ../Makefile
Considering/assuming you don't care about portability and are using GNU make, you can use the VPATH feature:
Create the directory where you want to do your build.
Create a 'Makefile' in that directory with (approximately) the following contents:
path_to_source = ..
VPATH = $(path_to_source)
include $(path_to_source)/Makefile
Change the path_to_source variable to point to the root of your source tree.
Additionally you probably need to tweak your original Makefile to make sure that it supports the out of source build. For example, you can't reference to prerequisites from your build rules and instead must use $^ and $<. (See GNU make - Writing Recipes with Directory Search) You might also need to modify the vpath-makefile. For example: adding CFLAGS+=-I$(path_to_source) might be useful.
Also note that if a file is in both your source and build directory, make will use the file in your build directory.
On automake
If you use automake, you're pretty much using the entire autotools. automake cannot work without autoconf.
The Makefiles generated by automake support out-of-source builds and cross-compilation, so you should be able to create subdirectories arm/ and thumb/ and run ../configure --host=arm-host-prefix in arm/ and run ../configure --host=thumb-host-prefix in thumb/. (I don't know the actual host tuples that you'd use for each compiler.)
Using GNU make
Since you're using GNUMake, you could do something like this:
ACOBJS := $(addprefix arm/,$(ACSRC:.c=.o))
TCOBJS := $(addprefix thumb/,$(TCSRC:.c=.o))
Use something like this answer to ensure that the arm/ and thumb/ directories (and any subdirectories) exist.

cannot get makefile to work with Qt library

I have 3 files in my program: App_interface.h, App_interface.cpp, main.cpp. Im trying to compile my program which requires the Qt library. I just installed the Qt library in the default location. This is my makefile:
if your wondering why i don't use moc in this makefile is because 1) i dont know how to do that. 2) i just want to stop getting the compiler error "cannot find ... file".
thanks
# Project: App_interface
# 10-19-09
#
# general variables
CPP := g++
OBJS := main.o App_interface.o
# Qt directorys
QTLIB := /usr/local/Trolltech/Qt-4.5.3/lib
QTINC := /usr/local/Trolltech/Qt-4.5.3/include
QTMOC := /usr/local/Trolltech/Qt-4.5.3/bin
App_interfaceV1: $(OBJS)
$(CPP) $(OBJS) -o App_interfaceV1 $(QTLIB)
main.o: main.cpp App_interface.h
$(CPP) -B $(QTINC) -c main.cpp -o main.o
App_interface.o: App_interface.h
$(CPP) -B $(QTINC) -c App_interface.cpp -o App_interface.o
There are several problems: You should use -I $(QTINC) to compile files, -L $(QTLIB) and at least -lQtCore -lQtGui to link the application. To get more help you should provide exact error messages.
Sorry to be blunt, but if you don't know how to write Makefiles, I'd suggest to use qmake.

Resources