protobuf and pkg-Config missing libdir and includedirs - c++

I was trying to build a binary for the protocol buffers C++ AddressBook tutorial. I compiled the protocol buffers successfully, but when I was building the binary with g++, I used pkg-config to get cflags and libs, and it failed to locate the necessary headers. I manually passed all the necessary flags, include directories, library directories, etc. to g++ and it worked.
pkg-config --cflags protobuf returns "-pthread"
pkg-config --libs protobuf returns "-lprotobuf -pthread -lpthread"
Meanwhile, protobuf.pc lists:
Cflags: -I${includedir} -pthread
Libs: -L${libdir} -lprotobuf -pthread -lpthread
I confirmed that the variables are set correctly with --variable=(include/libdir), and when using the --debug option, it confirms variables are set. However, it also shows that the -I and -L options are removed. The following is truncated debug output.
...Pasing pacage file protobuf.pc...
...Variable declarations...
Unknown keyword 'Libs.private' in protobuf.pc
...More variable declarations...
Adding 'protobuf' to list of known packages
Package protobuf has -I/usr/include in Cflags
Removing -I/usr/include from cflags for protobuf
Package protobuf has -L /usr/lib/x86_64-linux-gnu in Libs
Removing -L /usr/libx86-64-linux-gnu from libs for protobuf

Related

MSYS2 and libcurl, which libs to link?

I am having some big headaches linking statically libcurl in MSYS2 mingw.
I installed libcurl and all the listed dependencies from here
https://packages.msys2.org/package/mingw-w64-x86_64-curl
Since I am using CodeBlocks as IDE I need to supply a whole list of libs in form of lib#?.a, please keep in mind that I know nothing of Linux world and gcc tools and command line, otherwise I wouldn't be using an IDE!
Also I am not skilled enough to compile lib packages. I just need to write some portable code to do a https post request in cpp, so I need libcurl.
Can you tell me a complete list of all the needed libs to link against ? I tried all my best but I keep getting an infinity of unresolved symbols
UPDATE
After having checked what the package config for libcurl says, I have installed all the missing libs and used the following command line:
g++.exe -o MyProg.exe obj\Release\main.o -static-libstdc++ -static-libgcc -static -m64 -lcurl -lnghttp2 -lidn2 -lssh2 -lpsl -ladvapi32 -lcrypt32 -lssl -lcrypto -lssl -lcrypto -lgdi32 -lwldap32 -lzstd -lbrotlidec -lz -lws2_32 -s
Despite that I am still getting tons of undefined references:
d:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: d:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/lib/../lib\libcurl.a(gsasl.o):(.text+0x14): undefined reference to `gsasl_init'
[plus many other 'gsasl...' referrences]
d:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: d:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../lib\libbrotlidec.a(decode.c.o):(.text+0x2d28): undefined reference to `BrotliTransformDictionaryWord'
[plus many other 'brotli...' references]
pkg-config will tell you the necessary flags. Install it from the package mingw-w64-x86_64-pkg-config.
Run it as pkg-config --libs --static libcurl.
Copy the output into "linker flags -> other". For me the output is -L/mingw64/lib -lcurl -lnghttp2 -lidn2 -lssh2 -lpsl -ladvapi32 -lcrypt32 -lssl -lcrypto -lssl -lcrypto -lgdi32 -lwldap32 -lzstd -lbrotlidec -lz -lws2_32. Don't forget to add the --static flag, if you're not already doing so.

Understanding LD under MSYS2

I'm trying to compile the simavr project from https://github.com/buserror/simavr on Windows 10 using MSYS2 and mingw-w64.
After editing the makefiles to enable the MSYS clauses (Which are commented out by default), and changing the order of 2 include files, I can get the project to compile. I do however encounter an error in the linking step.
The output is
C:/Programs/msys64/mingw32/bin/../lib/gcc/i686-w64-mingw32/5.3.0/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lsimavr
Editing the makefile to print the ${LDFLAGS}, yield the following.
-L/lib -L/local/lib -L/c/Users/University/GitHub/simavr/simavr/../simavr/obj-i686-w64-mingw32 -lsimavr -lelf -lws2_32
Looking in the folder "obj-i686-w64-mingw32" mentioned in the build script, the file "libsimavr.a" is present. If I copy the file to the msys lib folder the linking step works fine.
The folder structure of the project is as follows:
simavr root (Where i run the makefile from, located in /c/Users/University/GitHub)
simavr
obj-i686-w64-mingw32
As far as I can tell, LD should be able to link properly without me copying the file manually. What am I missing here?
Edit:
The final command before the linker error.
cc -MMD -Werror -O2 -Wall -g -I/usr/local/include -DNO_COLOR -o obj-i686-w64-mingw32/run_avr.elf obj-i686-w64-mingw32/run_avr.o -L/lib -L/local/lib -L/c/Users/University/GitHub/simavr/simavr/../simavr/obj-i686-w64-mingw32 -lsimavr -lelf -lws2_32
Edit 2:
Cleaning the include paths of MSYS folders:
cc -MMD -Werror -O2 -Wall -g -DNO_COLOR -o obj-i686-w64-mingw32/run_avr.elf obj-i686-w64-mingw32/run_avr.o -L/c/Users/University/GitHub/simavr/simavr/../simavr/obj-i686-w64-mingw32 -lsimavr -lelf -lws2_32
C:/Programs/msys64/mingw32/bin/../lib/gcc/i686-w64-mingw32/5.3.0/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lsimavr
Passing CC=gcc to make:
gcc -MMD -Werror -O2 -Wall -g -DNO_COLOR -o obj-i686-w64-mingw32/run_avr.elf obj-i686-w64-mingw32/run_avr.o -L/c/Users/University/GitHub/simavr/simavr/../simavr/obj-i686-w64-mingw32 -lsimavr -lelf -lws2_32
C:/Programs/msys64/mingw32/bin/../lib/gcc/i686-w64-mingw32/5.3.0/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lsimavr
Edit 3:
Output of the find command:
$ find /c/Users/University/GitHub/simavr -name 'libsimavr.a'
/c/Users/University/GitHub/simavr/simavr/obj-i686-w64-mingw32/libsimavr.a
Note that previous entries have been made using the git bash prompt, not the one from msys2. However, running the same commands in the msys2 prompt or the mingw prompt from msys2 yields the same results.
Using mingw-w64 toolchain to build project you MUST remove from CFLAGS/CXXFLAGS/CPPFLAGS all paths with /usr, /local, /lib, /include as this paths can contain headers and libs from MSYS2 itself. Second, try pass "CC=gcc" to makefile.

Create shared .so library that has all it's dependencies statically linked

I am trying to build my .so library with all dependencies (mostly boost) statically linked. Currently, I can build statically linked static library and dynamically linked shared library:
I would like to add other dependencies to .so library so that it has 20MB and does not require user to install anything. Note that this is just a temporary solution before we upgrade to new Boost 1.55 on production servers.
I define libraries like this in Makefile ($ARCH can be either 32 or 64):
## Multi-arch library locations
LIB32=/usr/lib/i386-linux-gnu/
LIB64=/usr/lib/x86_64-linux-gnu/
LIBDIR:=$(LIB$(ARCH))
##Library directory
LIB=-L $(LIBDIR)
## DYNAMIC
LIBS=-lboost_serialization -lboost_thread -lboost_date_time -lboost_signals -lboost_iostreams -lboost_system -llog4cplus -lcrypto -lssl -lm
## STATIC
SLIBS=$(LIBDIR)libboost_serialization.a $(LIBDIR)libboost_thread.a $(LIBDIR)libboost_date_time.a $(LIBDIR)libboost_signals.a $(LIBDIR)libboost_iostreams.a $(LIBDIR)libboost_system.a $(LIBDIR)liblog4cplus.a
Shared lib with dynamic linking:
This is my shared lib GCC command:
Makefile:
$(CXX) $(CFLAGS) $(INCLUDE) $(LIB) $(LIBS) -shared -Wl,-soname,$(SHARED_LIB_VERSION) -o $(NEW_LIB_DIR)${SHARED_LIB_VERSION} $(OBJ_CPP_DYN) $(OBJ_C_DYN)
Changes into:
g++ -m64 -Wl,--trace -D NDEBUG -I /usr/include/ -I /usr/local/include -L /usr/lib/x86_64-linux-gnu/ -shared -lboost_serialization -lboost_thread -lboost_date_time -lboost_signals -lboost_iostreams -lboost_system -llog4cplus -lcrypto -lssl -lm -Wl,-soname,libLIBNAMEx64.so -o ../Release/libLIBNAMELIBNAMEx64.so ... and much more .o files ...
Linker says:
-lboost_serialization (/usr/lib/x86_64-linux-gnu//libboost_serialization.so)
-lboost_thread (/usr/lib/x86_64-linux-gnu//libboost_thread.so)
-lboost_date_time (/usr/lib/x86_64-linux-gnu//libboost_date_time.so)
-lboost_signals (/usr/lib/x86_64-linux-gnu//libboost_signals.so)
-lboost_iostreams (/usr/lib/x86_64-linux-gnu//libboost_iostreams.so)
-lboost_system (/usr/lib/x86_64-linux-gnu//libboost_system.so)
-llog4cplus (/usr/lib/x86_64-linux-gnu//liblog4cplus.so)
-lcrypto (/usr/lib/x86_64-linux-gnu//libcrypto.so)
-lssl (/usr/lib/x86_64-linux-gnu//libssl.so)
And it works.
Shared lib with static linking:
I thought I can just replace -shared with -static:
g++ -m64 -Wl,--trace -D NDEBUG -I /usr/include/ -I /usr/local/include -L /usr/lib/x86_64-linux-gnu/ -static -lboost_serialization -lboost_thread -lboost_date_time -lboost_signals -lboost_iostreams -lboost_system -llog4cplus -lcrypto -lssl -lm -Wl,-soname,libLIBNAMEx64_static_link.so -o ../Release/libLIBNAMEx64_static_link.so ... and much more .o files ...
But I get undefined reference errors everywhere.
So where do I configure how are dependencies linked with my binary? How can I achieve my goal?
More things I tried (edit)
-Wl,--library:
I also tried passing libraries directly to linker in a very assertive manner:
-Wl,--library=:/usr/lib/x86_64-linux-gnu/libboost_serialization.a
And without : (which prevents searching for .a):
-Wl,--library=/usr/lib/x86_64-linux-gnu/libboost_serialization.a
But I get the error:
/usr/bin/ld: cannot find -l/usr/lib/x86_64-linux-gnu/libboost_serialization.a
Of course, the file exists at that path.
Pass just library names:
Of course, here it's not even interpreted as linking command:
g++: error: libboost_serialization.a: No such file or directory
Interesting is that if I pass full path instead (/usr/lib/x86_64-linux-gnu/libboost_iostreams.a), GCC doubles it:
g++: error: /usr/lib/x86_64-linux-gnu//usr/lib/x86_64-linux-gnu/libboost_signals.a: No such file or directory
Use command man ld, I got this information:
-static
Do not link against shared libraries. It affects library searching for -l options which follow it. This option also implies --unresolved-symbols=report-all. This option can be used with -shared. Doing so means that a shared library is being created but that all of the library's external references must be resolved by pulling in entries from static libraries.
This option is exactly what you want: create a shared library with all dependencies (mostly boost) statically linked.
-l parameter is used to specify the library name, so you should use boost_serialization instead of /path/libboost_serialization.a:
-larchive
If you specify -lcommon, then ld will search its path-list for occurrences of "libcommon.a" for every common specified.
You can use -L parameter many times to specify the library paths when ld try to search static libraries:
-Lsearchdir
For example:
-L/usr/lib/x86_64-linux-gnu/
You could try -Wl,--whole-archive ${your library} -Wl,--no-whole-archive.

mingw g++ is unable to link with libraries

I'm trying to use X86_64-w64-mingw32-g++ (packaged in Archlinux's MingW package) to cross compile some C++ code into an Windows executable, however I'm having trouble getting past some issues.
I'm calling
x86_64-w64-mingw32-g++ -o build_win/asm build_win/asm.o build_win/asm_lib.o build_win/socket_boost.o -I../extra/etc -fopenmp -lrt -std=c++11 -g -lboost_system -lboost_serialization
from a makefile, but I get thrown the errors:
/usr/lib/gcc/x86_64-w64-mingw32/5.1.0/../../../../x86_64-w64-mingw32/bin/ld: cannot find -lrt
/usr/lib/gcc/x86_64-w64-mingw32/5.1.0/../../../../x86_64-w64-mingw32/bin/ld: cannot find -lboost_system
/usr/lib/gcc/x86_64-w64-mingw32/5.1.0/../../../../x86_64-w64-mingw32/bin/ld: cannot find -lboost_serialization
This works fine with native g++, so exactly do I have to change for mingw to compile?
EDIT: I have mingw-w64-boost package installed, which includes boost libraries pre-compiled and ready to be linked. However, it seems the naming convention is a bit different, and -lboost_system for example becomes -llibboost_system-mt (not exactly sure what the -mt suffix entails).
Problem is I can't find the mingw counterpart for -lrt. I've tried with both -lrtm and -lrtutils but in both cases I get:
[...]
undefined reference to `__imp_getsockopt'
Are you sure that -lboost_system and other libraries are present in the same directory as makefile ?
If not then please include -L flag which indicates the location of your library.
For example:
-L /path_openmp -fopenmp -L /path_boost_system/ -lboost_system -L /path_serialization -lboost_serialization
Moreover, you need not include -I and -g flag when creating an executable from .o files. These are needed when you create .o from .cpp files.
There is no rt library on Windows.
You are missing -lws2_32.
$ x86_64-w64-mingw32-nm -A /usr/x86_64-w64-mingw32/lib/*.a 2>/dev/null | grep getsockopt | grep " T "

Go + Swig building with external lib

I'm trying to build a cpp file with opencv functions.
Go 1.3 states that swig building is now bundled in go build tool but I didn't find a way to tell that build tool to add include dirs and libs args with pkg-config.
go test -x cv_test.go
cd /Users/pierre/Projects/go-swig
clang++ -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fno-common -g -O2 -o $WORK/_/Users/pierre/Projects/go-swig/_obj/binding.cpp.o -c ./binding.cpp
# _/Users/pierre/Projects/go-swig
In file included from ./binding.cpp:1:
./binding.h:5:10: fatal error: 'cv.h' file not found
$WORK/command-line-arguments/_test/tiler.test
FAIL command-line-arguments [build failed]
Has anyone did it successfully ?
As of right now, Go doesn't correctly pass include paths to swig if you use pkg-config, I submitted a patch but it most likely won't be included until 1.4 is out.
So you either build Go with the patch or manually specify the paths with #cgo CXXFLAGS / #cgo LDFLAGS like #JamesHenstridge suggested.
You can tell CGo to use the include and link flags for a particular pkg-config library using the following syntax in one of your Go source files:
// #cgo pkg-config: some-package
import "C"
That is, include it along with any other declarations in the comment block processed by cgo. It is only necessary to include this in one of the .go files in the package. You can also specify additional compile and link flags:
// #cgo CXXFLAGS: -std=c++11
// #cgo LDFLAGS: -L/some/library/dir -lfoo
Full details can be found in the cgo documentation