I have an autotools project that compiles just fine on the Mac, but under Linux (Ubuntu 12.04.1 LTS) the command lines passed to gcc have the libraries out of order relative to the object files. For example, autotools generates the following command to compile my code, a single file named test.c into a binary named test:
gcc -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -g -O2 -lglib-2.0 -o test test-test.o
This command line fails with:
/home/user/glib-test/test.c:4: undefined reference to `g_malloc`
/home/user/glib-test/test.c:5: undefined reference to `g_free`
However, if I compile from the command line and switch it up so the library reference is after the object files it works just fine:
gcc -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -g -O2 -o test test-test.o -lglib-2.0
The challenge is that I can't figure out how to force Autotools to generate the command line in the right order. For the sake of clarity, I've reproduced the simple test case here. First up is configure.ac:
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(glib-test, 1.0)
AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE()
AC_PROG_CC
AM_PROG_CC_C_O
PKG_CHECK_MODULES(GLIB, glib-2.0 > 2.0)
AC_CONFIG_FILES(Makefile)
AC_OUTPUT
Next is the simple Makefile.am:
CFLAGS=-Wall
bin_PROGRAMS=test
test_CFLAGS=$(GLIB_CFLAGS)
test_LDFLAGS=$(GLIB_LIBS)
test_SOURCES=test.c
Finally, the source code to this minimal test case, test.c:
#include <glib.h>
int main(int argc, char **argv) {
gchar *foo = g_malloc(100);
g_free(foo);
return 0;
}
Compilation is then achieved using the following series of commands:
touch NEWS README AUTHORS ChangeLog
aclocal
autoconf
automake --add-missing
./configure
make
I should be clear, I understand why my code won't compile, I'm just wondering how to get automake to put the libraries at the end of the command line so gcc will execute and link properly. It should be noted that gcc on Mac OS X Lion doesn't seem to have this problem.
The solution turned out to be the difference between LDFLAGS and LDADD. In short LDFLAGS is added before the object files on the command line and LDADD is added afterwards. Thus, changing Makefile.am to the following solved the problem:
CFLAGS=-Wall
bin_PROGRAMS=test
test_CFLAGS=$(GLIB_CFLAGS)
test_LDADD=$(GLIB_LIBS)
test_SOURCES=test.c
It only took tracking down a GCC developer at work to solve. Also, this example I provided is rather poor because test has a defined meaning in some contexts of autotools.
I solved a similar problem. The ./configure script in question was unable to complete a check for presence of a function due to a missing symbol. If I added the correct library to $LDFLAGS or such like, it was added before the .c file and the library was ignored.
The names of functions to check are first added to ac_func_list and then there is a loop in the body of the ./configure that for each of them calls ac_fn_c_check_func () and that in turns calls ac_fn_c_try_link ()
the checking function ac_fn_c_try_link () uses a command of this pattern:
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS \
$LDFLAGS conftest.$ac_ext $LIBS >&5'
$LDADD is completely ignored here. Therefore the only solution here is to add the -l flags to variable $LIBS.
Related
I have 3 classes - I denote those by firstClass,secondClass,thirdClass.
My headers - firstClass.h, secondClass.h, thirdClass.h and sources firstClass.cpp, secondClass.cpp, thirdClass.cpp.
In class thirdClass I create instance of firstClass and two instance of secondClass.
In main.cpp I deamonize and create instance thirdClass.
I want to create static library of thirdclass and linking to main.cpp.
firstClass and thirdClass used the same library libm.a
I created library step by step as following:
g++ -c -I-/usr/include/ -I-/usr/lib/ -I-/home/projects/Learninig firstClass.cpp -lstdc++ -lm-o WsChannel.o -w -m32
g++ -c -I-/usr/include/ -I-/usr/lib/ --I-/home/projects/Learninig secondClass -lstdc++ -o secondClass.o -w -m32
g++ -c -I-/usr/include/ -I-/usr/lib/ --I-/home/projects/Learninig thirdClass.cpp -lstdc++ -lm -o thirdClass.o -w -m32
ar rcs libLearning.a firstClass.o secondClass.o thirdClass.o
g++ main.cpp -L. -lLearning -lm -o MnLearning.o -m32
Compiling was maked correctly without any errors, but when I execute program I have same error. I spent some hours on checking code, but I don't find bugs. So then maybe compiling was incorrect. I did this using some tutorial in web.
If whatever was unclearly I am ready to more explain my question.
Edit: My error:
segfault at 557400000045 ip 00005574bd509dcd sp 00007ffd9e887900 error 4 in MnLearning[5574bd4f2000+26000]
The error is surely inside your own source code. Avoid undefined behavior in it, and be scared of UB.
Your use of -I- is strange, and probably wrong. I recommend removing it (and also, at first, remove the -m32 flag if your computer and distribution is 64 bits; work first to have your program run correctly on your laptop, then port it later to 32 bits Linux by adding the -m32 flag). You might use preprocessor options like -H to be shown what files are included.
I recommend building your library and your program with some build automation tool, such as GNU make or ninja.
Configure your build to compile with all warnings and debug info, i.e. using g++ -Wall -Wextra -g with GCC. Improve your source code to get no warnings. Then use the gdb debugger to understand the behavior of your program (and library).
So then maybe compiling was incorrect.
No, the compiler is probably good, and you should trust it.
The bug is very likely to be in your own code.
My error: segfault at 557400000045 ip 00005574bd509dcd sp 00007ffd9e887900 error 4 in MnLearning[5574bd4f2000+26000]
Segmentation fault is a symptom of some error in your own code (e.g. some buffer overflow, some bad pointer dereference, etc; or other kind of UB).
You might also use valgrind.
I spent some hours on checking code, but I don't find bugs.
You did not spend enough time (some bugs may take you weeks of work to be found), and you forgot to use the debugger, a very handy tool to help you understand the behavior of your program and find bugs in it. Be aware that programming is difficult, and don't be discouraged.
When compiling my C++ project that includes uuid.h I get the compile error:
fatal error: uuid.h: No such file or directory
I'm not sure whats going wrong. It could be my compiler instructions are wrong or that I indeed dont have that file installed (but I don't think thats the problem).
sudo apt-get install uuid-dev
The above command outputs: uuid-dev is already the newest version
My makefile is simply this:
all:
g++ -o bin/myapplication src/main.cpp -std=c++11
Edit:
In .h file:
#include <uuid.h>
Any ideas what the issue could be?
The package's file list shows that it contains /usr/include/uuid/uuid.h. Since your default include path looks for files relative to /usr/include, you'd need to either write <uuid/uuid.h>, or add -I/usr/include/uuid to your compile options.
However, the package also provides a .pc file for use with pkg-config, which is meant to abstract the details of which compiler options you need to build a program against a library. If you run pkg-config --cflags uuid you get get the output -I/usr/include/uuid, and if you run pkg-config --libs uuid, you get the output -luuid. These are meant to be incorporated into your program's build.
Since it looks like you're using Make, you should add these lines to your Makefile:
CFLAGS += `pkg-config --cflags uuid`
LDFLAGS += `pkg-config --libs uuid`
That'll incoroporate the necessary -I and -l options into your compile commands automatically — and it'll also work on other systems where the UUID library might be installed in a different location.
I bielive in newer version of the uuid the header is <uuid/uuid.h>
I have some trouble with crosscompiling C++ program which takes advantage of openMP library. I am using Linux Ubuntu 12.04 LTS. I want to obtain executable file runnable on Windows.
I have no problem with compiling my program with OMP with regular g++ command:
g++ a.cpp b.cpp -o OMPres -pg -O3 -I./CBLAS/include -L./ -lcblas
Also when I try crosscompilation without OMP, everything runs perfectly fine:
x86_64-w64-mingw32-g++ a.cpp b.cpp -O3 -I./CBLAS/include ./CBLAS/cblas_WIN64.a ./BLAS/blas_WIN64.a -o res.exe -l gfortran -static
But when I try to crosscompile it with OMP using following command:
x86_64-w64-mingw32-g++ a.cpp b.cpp -O3 -I./CBLAS/include ./CBLAS/cblas_WIN64.a ./BLAS/blas_WIN64.a -o OMPres.exe -l gfortran -static -fopenmp
I get this error:
a.cpp:41:17: fatal error: omp.h: No such file or directory
compilation terminated.
I found where omp.h file is located on my disk, and added the path to the command. After executing it:
x86_64-w64-mingw32-g++ a.cpp b.cpp -O3 -I./CBLAS/include -I/usr/lib/gcc/x86_64-linux-gnu/4.6/include ./CBLAS/cblas_WIN64.a ./BLAS/blas_WIN64.a -o OMPres.exe -l gfortran -static -fopenmp
I got another error: x86_64-w64-mingw32-g++: error: libgomp.spec: No such file or directory
As I also have this file on the disk I tried to copy it in various places and finaly it worked when I copied it directly into the directory where compilation takes place. Then it produced another error:
/usr/bin/x86_64-w64-mingw32-ld: cannot find -lgomp
/usr/bin/x86_64-w64-mingw32-ld: cannot find -lrt
collect2: ld returned 1 exit status
I don't have a good understanding of how compilers exactly work. I tried to update all mingw-w64 compilers that I could find with apt-cache search but nothing helped. I have no idea what more I can do :(.
First, #nmaier is completely correct in that the Ubuntu x86_64-w64-mingw32 toolchain is crippled, and that you can rebuild the toolchain yourself.
I, however, suggest that you use MXE, which saves you the time of manually compiling gcc and every dependency of it. The steps below should be enough for your purpose:
# Get MXE
git clone https://github.com/mxe/mxe.git && cd mxe
# Settings
cat <<EOF > settings.mk
MXE_TARGETS := x86_64-w64-mingw32.static
JOBS := 4
EOF
# Build gcc, libgomp, blas, and cblas. It will take a while
make -j2 libgomp cblas
# Add toolchain to PATH
# See http://htmlpreview.github.io/?https://github.com/mxe/mxe/blob/master/index.html#tutorial step 4
export PATH=`pwd`/usr/bin:$PATH
# You don't need -I./CBLAS/include ./CBLAS/cblas_WIN64.a ./BLAS/blas_WIN64.a
# because headers and libraries are installed to standard location and
# I already used `-lcblas -lblas`.
x86_64-w64-mingw32-g++ a.cpp b.cpp -fopenmp -O3 -o res.exe -lcblas -lblas -lgfortran -lquadmath
Your x86_64-w64-mingw32 toolchain appears to have been build without libgomp.
You could check your supplier/distribution if it there additional or variant packages that have libgomp.
Or switch to a different supplier/distribution.
Or you could rebuild (or build in the first place) a cross gcc with --enable-libgomp. This is kinda the hard way.
PS:
Adding paths that do not correspond with your platform, like -I/usr/lib/gcc/x86_64-linux-gnu/4.6/include, is a bad idea in general, and will most certainly fail... This kinda creates a Franken-compiler.
Building and installing OpenSSL 1.0.0.e worked without problems, all I had to do was to setup the correct compiler in the Makefile.
Compiling libCURL without OpenSSL works fine but when compiling with OpenSSL using
./configure --host=mipsel-angstrom-linux PCRECONFIG=/usr/local/crosstoolchain/usr/local/bin/pcre-config --with-openssl
I get the following error message:
ld: libssl.a(s2_clnt.o): relocation R_MIPS_HI16 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
libssl.a: could not read symbols: Bad value
I tried to compile OpenSSL with -fPIC and also tried to use -fPIC for libCURL to no avail. How can I fix this problem?
I think this works best, since it doesn't involve hacking files.
./Configure linux-x86_64 -fPIC
I found this by running
./config -h
and making a few guesses. I confirmed it works by using
grep PIC Makefile
Open the OpenSSL file called Configure in the root of the tarball. Move down to around line 610 and you will see the following for MIPS (find a better match if this is poor):
"vxworks-mips","ccmips:-mrtp -mips2 -O -G 0 -B\$(WIND_BASE)/host/\$(WIND_HOST_TYPE)/lib/gcc-lib/ -D_VSB_CONFIG_FILE=\"\$(WIND_BASE)/target/lib/h/config/vsbConfig.h\" -DCPU=MIPS32 -msoft-float -mno-branch-likely -DTOOL_FAMILY=gnu -DTOOL=gnu -fno-builtin -fno-defer-pop -DNO_STRINGS_H -I\$(WIND_BASE)/target/usr/h -I\$(WIND_BASE)/target/h/wrn/coreip::-D_REENTRANT:VXWORKS:-Wl,--defsym,__wrs_rtp_base=0xe0000000 -L \$(WIND_BASE)/target/usr/lib/mips/MIPSI32/sfcommon::${mips32_asm}:o32::::::ranlibmips:",
Add -fPIC to the options used.
Alternately, open the OpenSSL file called Makefile.org in the root of the tarball. Move down to around line 60 and you will see the following:
CC= gcc
Add the following as CC:
CC= gcc -fPIC
Its kind of a hack because you want to do that for CFLAGS, but the Makefile does not intake the macro.
Or, you can wait until OpenSSL's configure is complete (i.e., after running ./config), and then open all the makefiles and add it to the CFLAGS created from the Makefile.org template. Be sure to visit makefiles in subdirectories like crypto and engines.
The final solution for OpenSSL is to add a custom line to config and Configure. Ben Laurie and other do it when they perform custom builds. Search config and Configure for "debug-ben" or "ben-debug" or similar.
For libcurl, I believe that's an automake project. Simply perform the following:
$ export CFLAGS="-fPIC"
$ ./config
I'm trying to get a "Hello World" application compiled for an ARM target. I'm cross compiling using gcc on Ubuntu/VMWare. If I compile for the host machine, it works fine. When I compile for the target, I get this error:
/root/picokernel/toolchain/arm-eabi/lib/libcs3hosted.a(hosted-sbrk.o): In function `_sbrk':
sbrk.c:(.text+0x74): undefined reference to `__cs3_heap_limit'
/root/picokernel/toolchain/arm-eabi/lib/libcs3hosted.a(hosted-sbrk.o):(.data+0x0): undefined reference to `__cs3_heap_start'
make: *** [HelloWorld] Error 1
So I think I need to link something in - perhaps my toolchain does not have the right libs? I was able to build the kernel, so I thought it was complete. Thanks! This is the target board. - runs Angstrom or Android.
makefile:
CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)ld
CROSS_LIB1=/root/picokernel/toolchain/arm-eabi/lib
CROSS_LIB2=/root/picokernel/toolchain/lib/gcc/arm-eabi/4.2.1
CFLAGS=-Wall
LDFLAGS= -L$(CROSS_LIB1) -L$(CROSS_LIB2) -lc -lcs3hosted -lg -lgcc --entry main
HelloWorld: HelloWorld.o
$(LD) HelloWorld.o $(LDFLAGS)
clean:
rm -f HelloWorld HelloWorld.o
program:
#include <stdio.h>
int main(int argc, char **argv)
{
printf("Hello World\n");
return 0;
}
I gotta say, this is suspicious: -nostdlib
How about not using this flag?
The kernel does not use the C runtime library since the library does many—if not most—things not permitted by kernel code like file i/o and allocating memory.
Normally, you don't have to specify a library at all. gcc assumes the right thing. Try removing setting LDFLAGS altogether: I bet it works better.
Ok - finally worked this out, picked up a toolchain from the source here:
http://www.codesourcery.com/sgpp/lite/arm/portal/release1803
Hello World works great! Thanks for the suggestions
Does the toolchain you are using have a library called "lcs3arm" ? If so, try adding that to the list. You can also try "-lcs3" itself
Out of interest, which version of GCC are you using here? (i.e. which CodeSourcery release)