GCC builtin functions - 2003 vs 2019 behaviour - gcc

At page 14 of the book "Introduction to GCC" by Brian Gough, the author wants to show a linker error due to not supplying gcc with the libm library, where the code for the function sqrt resides:
$ gcc -Wall calc.c -o calc
/tmp/ccbR6Ojm.o: In function ‘main’:
/tmp/ccbR6Ojm.o(.text+0x19): undefined reference to ‘sqrt’
The file calc.c (where the functionsqrt is invoked) is this:
#include <math.h>
#include <stdio.h>
int main (void)
{
double x = sqrt (2.0);
printf ("The square root of 2.0 is %f\n", x);
return 0;
}
This book is from 2003.
On my current Ubuntu Linux 18, I can't reproduce the link error: it links and works, printing the correct result:
$ ./calc
1.414214
I found with ldd calc that the libm.so shared library is not invoked at runtime. Nor of course is the static library libm.a involved here.
So how does gcc deal with the function sqrt? I found that in this case it uses the sqrt GCC built-in function.
Its code gets inserted in the calc.o object file at compile time. So no "undefined reference" error.
First question: this the whole story or am I missing something?
Second question: why did this behavior regarding the built-in functions of GCC change so much between 2003 (when the book was written) and now? (Practically invalidating the whole example, it seems to me)
Third question: why does the author make his examples (e.g.$ gcc -Wall calc.c -lm -o cal) implying that the static library libc.a will be used, when in reality in Linux that syntax invokes the dynamic library libm.so? Is this specific to Linux and not to GNU GCC? What am I mising?

I think this is due to optimization of a constant value. Modern GCC can compute exact value of sqrt (2.0). If you force it not to use the built-ins with -fno-builtin, it will still fail to link. Also, if you change the code a little bit so that the argument to sqrt() is not literal, it will fail to link:
#include <math.h>
#include <stdio.h>
double t = 2.0;
int main (void)
{
double x = sqrt (t);
printf ("The square root of 2.0 is %f\n", x);
return 0;
}
This produces link error:
> gcc -o test test.c
/usr/bin/ld: /tmp/ccLjHnQx.o: in function `main':
test.c:(.text+0x11): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
Regarding your 3rd question, -lm does not imply static library, AFAIK.

Related

threading program runs with g++ but not with gcc

I have compiled a c++ code using g++ -std=c++11 -o main main.cpp -pthread and it compiled fine however if I compile the same code using gcc -std=c++11 -o main main.cpp -pthread it does not compile and throws error. The program uses threading which properly taken care of using -pthread option while compiling. For the reference I am attaching the code below. Any help is highly appreciated.
#include <iostream>
#include <thread>
class foo
{
public:
void bar(int loop_num)
{
for (int i = 0; i < loop_num; ++i) {
std::cout << "Thread executing\n";
++n;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
int n = 0;
};
int main()
{
int n = 0;
foo f;
std::thread t1(&foo::bar, &f, 5);
t1.join();
}
If you’ve written C++ code with GCC, you’ll know that you need to use the program g++, both for compilation and linking. For multi-module programs, this means every .cpp file gets compiled with g++, and then the entire program must be linked separately using g++. If you try to link the program using gcc, it will almost work, but you’ll get a lot of “undefined reference” errors, like this:
test.cpp:(.text+0x11): undefined reference to `std::cout'
The need to use g++ to link the entire program causes trouble when you have a very complicated build process you don’t have full control of. For instance, I’m trying to link C++ code with Mercury, and I have to use the Mercury linker, which in turn calls gcc.
So just a quick tip: If you are forced to use gcc to link the program, just add the library “stdc++”, as you would any other library, and it will work. That is, add the option “-lstdc++” to your GCC linker command line. For example:
g++ -c hello.cpp
gcc -lstdc++ -o hello hello.o
I assume the error you get looks something like this:
/tmp/ccUKAq0K.o: In function `main':
main.cpp:(.text+0x59): undefined reference to `std::thread::join()'
/tmp/ccUKAq0K.o: In function `__static_initialization_and_destruction_0(int, int)':
main.cpp:(.text+0xb6): undefined reference to `std::ios_base::Init::Init()'
main.cpp:(.text+0xcb): undefined reference to `std::ios_base::Init::~Init()'
/tmp/ccUKAq0K.o: In function `std::thread::~thread()':
main.cpp:(.text._ZNSt6threadD2Ev[_ZNSt6threadD5Ev]+0x1d): undefined reference to `std::terminate()'
(And so on.)
C++ programs which use the standard library (so most of them) need to be linked using g++, not gcc. Only the g++ compiler driver links in most of the standard library. The gcc compiler driver compiles C++ programs, just like g++, but when the linker is invoked, the program is treated as a C program, which usually leads to linker errors.
Try adding the -lrt flag after the pthread one.

C and the <complex.h> file

My simple program compTest.c
#include<stdio.h>
#include<complex.h>
int main(void)
{
double complex z = 1.0 + 1.0 * I;
printf("|z| = %.4f\n", cabs(z));
return 0;
}
When using the standard library and compiling with gcc on a Linux system do I need to include the -lm flag for it to work?
Example:
gcc -o executableName fileName.c -lm
When I don't I get the following:
/tmp/cc1o7rtt.o: In function `main':
comTest.c:(.text+0x35): undefined reference to `cabs'
collect2: error: ld returned 1 exit status
It seems that you've already discovered that the answer is yes.
The -lm flag tells the linker to link the math library, which contains, among other things, the code for the cabs function. (This is a gcc/Linux issue, not a C language issue.)
The Linux man page for cabs specifically says Link with -lm.
(In general, if you want to call any library function and you're not 100% certain how to use it, read the man page.)

gcc undefined reference to header function

I know there have been a lot of such topics, but I didn't found the answer, really. There's nothing that isn't working.
I am compiling file
gcc -std=c99 -Lmem xx.c
in the file there is
#include "include/memory.h"
#include <stdlib.h>
void main(){
meminit(100);
}
and in memory.h
#include "private.h"
#pragma once
MEMI * memdiag();
void meminit(int block_number);
void * memalloc(int desired_size);
void memfree(void * ptr);
the folder contains libmem.a, and headers, yet I'm getting error
/tmp/ccSJ4trm.o: In function `main':
xx.c:(.text+0xa): undefined reference to `meminit'
collect2: error: ld returned 1 exit status
I would be very grateful if You helped me, tomorrow I have to hand in the project.
You need to read some tutorials about using GCC.
You might want to try to compile and link with with
gcc -std=c99 -Wall -g xx.c -L. -lmem
(assuming your current directory [not folder] i.e. the . in -L. contains a libmem.a or libmem.so* library)
BTW, order of program arguments to gcc matters a big lot!

Link to cutil in GPU Computing SDK

I've been trying to link to the functions in the cutil.h ofthe GPU Computing SDK released by NVIDIA.
At the moment, I am simply trying to compile this simple piece of code:
#include <iostream>
#include <cuda.h>
#include <cutil.h>
using namespace std;
int main(){
unsigned int time_total;
cutCreateTimer(&time_total);
return 0;
}
using the following command:
nvcc -I/home/sj755/NVIDIA_GPU_Computing_SDK/C/common/inc/ -L/home/sj755/NVIDIA_GPU_Computing_SDK/C/lib/libcutil_x86_64.a cutiltest.cu
Only to get the following error:
/tmp/tmpxft_000077cc_00000000-13_cutiltest.o: In function `main':
tmpxft_000077cc_00000000-1_cutiltest.cudafe1.cpp:(.text+0x10): undefined reference to
`cutCreateTimer'
collect2: ld returned 1 exit status
ld also can't find -lcutil if I were to add the flag.
There is a static library that I'm supposed to link to, but for some reason this never works out. Here's what I tried:
I've changed my .bashrc file so that LD_LIBRARY_PATH includes the path to the static library
##########< CULA >
export CULA_ROOT=/usr/local/cula
export CULA_INC_PATH=$CULA_ROOT/include
export CULA_BIN_PATH_32=$CULA_ROOT/bin
export CULA_BIN_PATH_64=$CULA_ROOT/bin64
export CULA_LIB_PATH_32=$CULA_ROOT/lib
export CULA_LIB_PATH_64=$CULA_ROOT/lib64
##########< CUDA >
export PATH=$PATH:/usr/local/cuda/bin
export LD_LIBRARY_PATH=:/usr/local/cuda/lib64
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CULA_LIB_PATH_64
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/libnvvp/
export CUDA_SDK_ROOT_DIR=/home/sj755/NVIDIA_GPU_Computing_SDK/C
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CUDA_SDK_ROOT_DIR/lib
I've also tried renaming libcutil_x86_64.a to libcutil.a, still nothing.
Tried extracting the archive, creating a shared object file, and linking to it:
ar -x libcutil_x86_64.a
gcc -I /usr/include/GL/ -L /usr/include/GL/ -lglut -lGL -lGLU -lX11 -lXmu -lXi -lm -lpthread -shared *.cpp.o -o libcutil.so
nvcc -lcutil -I /home/sj755/NVIDIA_GPU_Computing_SDK/C/common/inc/ -L /home/sj755/NVIDIA_GPU_Computing_SDK/C/lib/libcutil.so cutiltest.cu
Only to get the following /usr/bin/ld: cannot find -lcutil
What step am I forgetting here?
Your compilation statement is incorrect. It should look something like this:
nvcc -I$SDKROOT/C/common/inc -L$SDKROOT/C/lib cutiltest.cc -lcutil_x86_64
where SDKROOT holds the root path to the SDK, which looks to be
/home/sj755/NVIDIA_GPU_Computing_SDK
in your case. The key things to note here are that the library must be passed by name as a -l option after the code and objects that require it. A concrete example on OS X using your code snippet:
$ cat cutiltest.cc
#include <iostream>
#include <cuda.h>
#include <cutil.h>
using namespace std;
int main(){
unsigned int time_total;
cutCreateTimer(&time_total);
return 0;
}
$ nvcc -I/Developer/GPU\ Computing/C/common/inc -L /Developer/GPU\ Computing/C/lib -o cutiltest cutiltest.cc -lcutil_i386
$ ls -l cutiltest
-rwxr-xr-x 1 talonmies talonmies 117548 May 25 07:57 cutiltest
But as a last remark, you really should rethink your choice of using the SDK cutils library at all. It is only intended for use with the SDK examples. It isn't part of CUDA, it has no documentation, it isn't guaranteed to work or not contain bugs, and isn't guaranteed to be consistent (or even present) from one SDK release to another.
This is not only your problem. Are you tried to link with cutil as with shared library? This solution was posted on NVIDIA dev. zone forum

A linking error related to 'gcc' and '-lm'

Well, I think my problem is a little bit interesting and I want to understand what's happening on my Ubuntu box.
I compiled and linked the following useless piece of code with gcc -lm -o useless useless.c:
/* File useless.c */
#include <stdio.h>
#include <math.h>
int main()
{
int sample = (int)(0.75 * 32768.0 * sin(2 * 3.14 * 440 * ((float) 1/44100)));
return(0);
}
So far so good. But when I change to this:
/* File useless.c */
#include <stdio.h>
#include <math.h>
int main()
{
int freq = 440;
int sample = (int)(0.75 * 32768.0 * sin(2 * 3.14 * freq * ((float) 1/44100)));
return(0);
}
And I try to compile using the same command line, and gcc responds:
/tmp/cctM0k56.o: In function `main':
ao_example3.c:(.text+0x29): undefined reference to `sin'
collect2: ld returned 1 exit status
And it stops. What is happening? Why can't I compile that way?
I also tried a sudo ldconfig -v without success.
There are two different things going on here.
For the first example, the compiler doesn't generate a call to sin. It sees that the argument is a constant expression, so it replaces the sin(...) call with the result of the expression, and the math library isn't needed. It will work just as well without the -lm. (But you shouldn't count on that; it's not always obvious when the compiler will perform this kind of optimization and when it won't.)
(If you compile with
gcc -S useless.c
and take a look at useless.s, the generated assembly language listing, you can see that there's no call to sin.)
For the second example, you do need the -lm option -- but it needs to be at the end of the command line, or at least after the file (useless.c) that needs it:
gcc -o useless useless.c -lm
or
gcc useless.c -lm -o useless
The linker processes files in order, keeping track of unresolved symbols for each one (sin, referred to by useless.o), and then resolving them as it sees their definitions. If you put the -lm first, there are no unresolved symbols when it processes the math library; by the time it sees the call to sin in useless.o, it's too late.

Resources