How do I link Intel MKL and libdl with gold linker? - c

I'm having a problem linking Intel MKL and libdl using the gold linker on CentOS:
When I run this script:
#!/bin/bash
MKL_INC=$MKL_INSTALL_DIR/include
MKL_LIB=$MKL_INSTALL_DIR/lib
. /opt/rh/devtoolset-6/enable
cat > t.c << end_mkltest
#include <dlfcn.h>
#include "mkl_service.h"
int main() {
dlerror(); /* use libdl */
mkl_set_num_threads(1); /* use mkl */
}
end_mkltest
gcc -I$MKL_INC -c t.c -o t.o
gcc -L$MKL_LIB -fuse-ld=gold t.o -lmkl_rt -ldl
I get:
libmkl_rt.so: error: undefined reference to 'calloc'
libmkl_rt.so: error: undefined reference to 'realloc'
libmkl_rt.so: error: undefined reference to 'malloc'
libmkl_rt.so: error: undefined reference to 'free'
We're using:
CentOS 7.3
devtoolset-6
mkl-2017.2.174.tar.bz2
Any ideas?

This should work. Can you post the linker command shown by this command?
gcc -v -L$MKL_LIB -fuse-ld=gold t.o -lmkl_rt -ldl
(Sorry, can't post this as a comment due to lack of reputation.)

Related

why asan linker flag is needed

Could someone help me understand, why after generating the object file with using ASan flag (compiler flag), when linking the object file still needs the same flag? (linker flag)
For example
clang -fsanitize=address -c test.c
clang -fsanitize=address test.o -o test.exe
When you compile your program with Address Sanitizer, it instruments every memory access and prefixes it with a check and includes the function calls to report memory access errors.
For e.g.
Sample program which leaks memory and try to access array beyond its size:
#include <stdio.h>
#include <stdlib.h>
void fun (void) {
void *p = malloc(1);
char a[] = "abc";
printf ("%c\n", a[4]);
}
int main (void) {
fun();
return 0;
}
Compiling:
# gcc -fsanitize=address -g -c test.c
# ls
test.c test.o
Linking without -fsanitize=address:
# gcc -g test.o -o test.exe
test.o: In function `fun':
/root/mywork/asan/sample7/test.c:4: undefined reference to `__asan_option_detect_stack_use_after_return'
/root/mywork/asan/sample7/test.c:4: undefined reference to `__asan_stack_malloc_1'
/root/mywork/asan/sample7/test.c:6: undefined reference to `__asan_report_store4'
/root/mywork/asan/sample7/test.c:8: undefined reference to `__asan_report_load1'
test.o: In function `_GLOBAL__sub_D_00099_0_fun':
/root/mywork/asan/sample7/test.c:14: undefined reference to `__asan_unregister_globals'
test.o: In function `_GLOBAL__sub_I_00099_1_fun':
/root/mywork/asan/sample7/test.c:14: undefined reference to `__asan_init'
/root/mywork/asan/sample7/test.c:14: undefined reference to `__asan_version_mismatch_check_v8'
/root/mywork/asan/sample7/test.c:14: undefined reference to `__asan_register_globals'
collect2: error: ld returned 1 exit status
The code of test.o is instrumented by Address Sanitizer. The Address Sanitizer runtime library replaces malloc() call with its own malloc() function call (which allocate requested amount of memory with redzone around it) and provides error reporting function like __asan_report_load1(), __asan_report_store4() etc. In order to resolve these functions, the -fsanitize=address flag is required at the time of linking to tell linker to check the ASan runtime library to resolve the references.
Linking with -fsanitize=address:
# gcc -fsanitize=address -g test.o -o test.exe
# ls
test.c test.exe test.o
If you don't want to use -fsanitize=address flag with linker, you can provide the Address Sanitizer library to the linker which it can use to resolve the references:
# ls
test.c test.o
# gcc -lasan -g test.o -o test.exe
# ls
test.c test.exe test.o

undefined main during linking but defined during full compilitaion process

I am novice in C programming. So I learned different process of compilation(preproccessing, compiling, linking). My program is
#include <stdio.h>
#define testDefinition(x) printf(#x " is equal to %lf\n",x)
int main(void)
{
testDefinition(3.15);
return 0;
}
It is simple program which doesn't have any sense,but problem is when I use gcc -o test test.c it works fine, but when I do that
gcc -E test.c -o test.i
gcc -C test.i -o test.o
gcc test.o -o test
I get error
usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
I am using Ubuntu 20.04 and GCC compiler.
test.o is already the executable, you did not pass -c.
$ gcc -E test.c -o test.i
$ gcc -C test.i -o test.o
$ ./test.o
3.15 is equal ....
Because of it, test.o is an ELF file and gcc treats it as shared library (I think). Because there are no source files passed in gcc test.o -o test there is no main, so it's undefined.
I guess, you wanted to do gcc -C -c test.i -o test.o to create an object file.

Can't link custom shared library with gcc

I'm trying to write my own shared library to link to an executable, but can't get the .so to link.
I'm using a very basic example to try and get it working. The shared library (test_lib.c):
#include "test_lib.h" //stdlib includes and function prototype
char *hello(void) {
char *c = malloc(100);
memcpy(c, "hello\n", 7);
return c;
}
The executable (test.c):
#include "test_lib.h"
int main() {
printf("%s", hello());
return 0;
}
Following all the guides I can find, I compile the .so with gcc -I . -fPIC -shared -o test_lib.so test_lib.c, and then the executable (in the same directory) with gcc -I . -L . test.c -ltest_lib
This gives the error:
/usr/bin/ld: cannot find -ltest_lib
collect2: error: ld returned 1 exit status
As I understand including the path through the -L flag should tell gcc where to find the .so, but this isn't working. What am I missing here?
When linking a library, the library usually has to be named libxxx.a|so for the linker to find it.
Compiling the library:
gcc -I . -fPIC -shared -o libtest.so test_lib.c
Then you can link with:
gcc -I . -L . test.c -ltest

libcheck test fails to link

I'm trying to build a simple example using libcheck but it fails to build while using the flags reported by pkg-config.
My file: tests/test.c
#include <stdlib.h>
#include <check.h>
START_TEST(zero)
{
int z = 0;
ck_assert_int_eq(0, z);
}
END_TEST
Suite* suite_zero(void)
{
Suite* s;
TCase* tc;
s = suite_create("suite_zero");
tc = tcase_create("zero");
tcase_add_test(tc, zero);
suite_add_tcase(s, tc);
return s;
}
int main(void)
{
int number_failed;
SRunner* sr;
Suite* s_zero = suite_zero();
sr = srunner_create(s_zero);
srunner_run_all(sr, CK_NORMAL);
number_failed = srunner_ntests_failed(sr);
srunner_free(sr);
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
My system:
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04 LTS"
$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609
$ pkg-config --version
0.29.1
When I try to build my test using the flags and libs reported by pkg-config:
$ pkg-config --cflags --libs check
-pthread -lcheck_pic -pthread -lrt -lm -lsubunit
$ gcc -pthread -lcheck_pic -pthread -lrt -lm -lsubunit -g tests/test.c -o tests/zero
/tmp/ccRV2kLw.o: In function `zero':
Code/tests/test.c:4: undefined reference to `tcase_fn_start'
/Code/tests/test.c:7: undefined reference to `_mark_point'
/Code/tests/test.c:7: undefined reference to `_ck_assert_failed'
/tmp/ccRV2kLw.o: In function `suite_zero':
/Code/tests/test.c:15: undefined reference to `suite_create'
/Code/tests/test.c:16: undefined reference to `tcase_create'
/Code/tests/test.c:17: undefined reference to `_tcase_add_test'
/Code/tests/test.c:19: undefined reference to `suite_add_tcase'
/tmp/ccRV2kLw.o: In function `main':
/Code/tests/test.c:30: undefined reference to `srunner_create'
/Code/tests/test.c:32: undefined reference to `srunner_run_all'
/Code/tests/test.c:33: undefined reference to `srunner_ntests_failed'
/Code/tests/test.c:34: undefined reference to `srunner_free'
collect2: error: ld returned 1 exit status
Libcheck was installed by apt and the library and headers are in the typical locations, /usr/lib and /usr/include respectively. Yet it appears it can't be found. I'm a bit stumped as why. Any ideas?
Thanks.
Try adding the flags reported by pkg-config after the compilation command as this answer and the documentation for pkg-config suggests. The compiler needs to know what file it's trying to link the library to beforehand so that the flags can be applied appropriately.
gcc -g test.c -o test -pthread -lcheck_pic -pthread -lrt -lm -lsubunit
or more succinctly
gcc -g test.c -o test `pkg-config --cflags --libs check`

cannot compile mongo-c-driver example

I try to write simple mongo c client. Source file (a.c):
#include <stdio.h>
#define MONGO_HAVE_STDINT
#include <mongo.h>
void mongo_init_c(mongo *con)
{
mongo_init(con);
}
int main() {
return 0;
}
And i try to compile it with:
gcc -I/usr/local/include -L/usr/local/lib -lmongoc a.c
But get an error:
a.c:(.text+0xd): undefined reference to `mongo_init'
Files /usr/local/include/mongo.h and /usr/local/lib/libmongoc.so exists
How can I correctly compile a.c?
p.s. mongo-2.0.4, gcc-4.6, mongo-c-driver - pulled from github
update
$ nm /usr/local/lib/libmongoc.so | grep init
000034e0 T _init
0000dd10 T bson_init
0000c740 T bson_init_data
0000c7b0 T bson_init_finished_data
0000dc10 T bson_init_size
0000d060 T bson_iterator_init
0000a5e0 T gridfile_init
00009af0 T gridfile_writer_init
000095e0 T gridfs_init
00010a18 R initialBufferSize
00005f40 T mongo_cursor_init
00008da0 T mongo_env_sock_init
00005d90 T mongo_init
000057b0 T mongo_init_sockets
00004800 T mongo_md5_init
00005e40 T mongo_replica_set_init
00005f00 T mongo_replset_init
00005b80 T mongo_write_concern_init
$ gcc -I/usr/local/include -L/usr/local/lib -Wall -Werror -lmongoc a.c
/tmp/cccuNEp1.o: In function `mongo_init_c':
a.c:(.text+0xd): undefined reference to `mongo_init'
Try linking the library after the source file, like gcc a.c -lmongoc. This is because you're using a traditional single-pass linker, which expects to satisfy dependencies with subsequent, not previous, objects specified on the command line.

Resources