undefined main during linking but defined during full compilitaion process - c

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.

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

Compile minimal test shared library using clang

I am trying to compile a minimal test shared library in FreeBSD using:
FreeBSD clang version 6.0.1 (tags/RELEASE_601/final 335540) (based on LLVM 6.0.1)
Target: x86_64-unknown-freebsd12.0
Thread model: posix
InstalledDir: /usr/bin
test.c
#include "test.h"
int SampleFunction(int a, int b)
{
return a * b;
}
test.h
#ifndef TESTLIB_H
#define TESTLIB_H
extern int SampleFunction(int a, int b);
#endif
Makefile
# Makefile TESTLIB
TEST_OBJS = test.o
TEST_HEADERS = test.h
TEST_LIB = test.so
CC = cc
testlib: $(TEST_OBJS)
$(CC) -fpic -o $(TEST_LIB) $(TEST_OBJS)
# Rebuilt if this Makefile or header changes
$(TEST_OBJS): Makefile $(TEST_HEADERS)
Output:
$ make testlib
cc -O2 -pipe -c test.c -o test.o
cc -fpic -o test.so test.o
/usr/bin/ld: error: undefined symbol: main
>>> referenced by crt1.c:76 (/usr/src/lib/csu/amd64/crt1.c:76)
>>> /usr/lib/crt1.o:(_start)
cc: error: linker command failed with exit code 1 (use -v to see invocation)
*** Error code 1
Stop.
make: stopped in /usr/home/user/testlib
As well as adding -shared to the linker stage (as mentioned by Oo.oO), you probably also want to compile with the -fPIC flag as well. So if you are using the makefile implicit rules for the compiling (looks like you are) then you will probably want to add that flag to CFLAGS. I don't think you need it for the linking stage:
# Makefile TESTLIB
TEST_OBJS = test.o
TEST_HEADERS = test.h
TEST_LIB = test.so
CFLAGS += -fPIC
CC = cc
testlib: $(TEST_OBJS)
$(CC) -shared -o $(TEST_LIB) $(TEST_OBJS)
# Rebuilt if this Makefile or header changes
$(TEST_OBJS): Makefile $(TEST_HEADERS)
I prefer using the OS-provided bsd.lib.mk for such building libraries. The following should do the right thing -- whatever it may be:
SHLIB_NAME= testlib
SRCS= test.c
.include <bsd.lib.mk>
(For building executables there is bsd.prog.mk, BTW.)

Unable to compile and link main.c to another source file using gcc

I am trying to compile the following source file using gcc -g -Wall -Wextra -pedantic -std=c99 -o main -lm.
source.h
void simple_sum(void)
source.c
#include "source.h"
#include <stdio.h>
void simple_sum(void)
{
int a, b;
scanf("%d %d", &a, &b);
printf("%d + %d = %d\n",a, b, a + b);
}
main.c
#include "source.h"
#include <stdio.h>
int main(void)
{
printf("\n");
simple_sum();
return 0;
}
I get following error:
gcc -g -Wall -Wextra -pedantic -std=c99 -o main -lm
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In function _start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
Makefile:6: recipe for target 'main' failed
make: *** [main] Error 1
Could someone please suggest how to fix this?
Edit
I get the following error when I run using gcc -g -Wall main.c -o main
/tmp/ccEAL4iG.o: In functionmain':
/home/a/aalto_university/functions/calculation/main.c:7: undefined reference to simple_sum'
collect2: error: ld returned 1 exit status
Compile with
gcc -g -Wall -Wextra -pedantic -std=c99 source.c main.c -o myprog -lm
(actually, -lm is not needed, you don't use <math.h> functions; but keeping -lm should not harm)
Later, learn to write your Makefile to do these things in several steps:
First, get the source.o object file with
gcc -g -Wall -Wextra -pedantic -std=c99 -c source.c
then get the main.o object file with
gcc -g -Wall -Wextra -pedantic -std=c99 -c main.c
At last, link both of them
gcc -g source.o main.o -lm -o myprog
Here
gcc -g -Wall -Wextra -pedantic -std=c99 -o main -lm
you are not providing source file name to linker, hence it throw error like
undefined reference to `main'
While compiling provide source file main.c and source.c. For e.g first run this
gcc -g -Wall -Wextra -pedantic -std=c99 -c main.c source.c -lm
to create the object.o files & then create the executable by running
gcc source.o main.o -o my_exe
And finally run the executable. Also declaration of simple_sum() missing ; it should be
void simple_sum(void); /* you miss ;*/
Also learn how to use Makefile for compilation as #Basile pointed, there you don't have to create .o file manually, your Makefile will create .o file & compile if it's written correctly.

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`

Undefined reference resulting from g++ linking

I am new to g++ and Makefile. I am trying to link this BeBOP SMC library, which is in my lib directory. Under the lib directory are bebop_util and sparse_matrix_converter, both of which have already been built without errors. I see libbebop_util.a, libbebop_util.so under bebop_util and libsparse_matrix_converter.a, libsparse_matrix_converter.so under sparse_matrix_converter. Below is the source:
Makefile
CC=g++
CFLAGS=-c -Wall
test.out: test.o
$(CC) -o test.out -Ilib/sparse_matrix_converter/include -Llib/bebop_util \
-Llib/sparse_matrix_converter -lbebop_util -lsparse_matrix_converter test.o
test.o: test.cpp
$(CC) $(CFLAGS) -Ilib/sparse_matrix_converter/include test.cpp
clean:
rm -f test.o test.out
test.cpp
#include <bebop/smc/sparse_matrix.h>
#include <bebop/smc/sparse_matrix_ops.h>
int main(int argc, const char* argv[])
{
struct sparse_matrix_t* A = load_sparse_matrix (MATRIX_MARKET, "sample_input");
destroy_sparse_matrix(A);
return 0;
}
Output:
login3% make
g++ -c -Wall -Ilib/sparse_matrix_converter/include test.cpp
g++ -o test.out -Ilib/sparse_matrix_converter/include -Llib/bebop_util -Llib/sparse_matrix_converter -lbebop_util -lsparse_matrix_converter test.o
test.o: In function `main':
test.cpp:(.text+0x1a): undefined reference to `load_sparse_matrix(sparse_matrix_file_format_t, char const*)'
test.cpp:(.text+0x27): undefined reference to `destroy_sparse_matrix(sparse_matrix_t*)'
collect2: ld returned 1 exit status
make: *** [test.out] Error 1
Please note that test.cpp depends on sparse_matrix_converter, which depends on bebop_util. Would you please let me know what mistakes I may have made? Thanks.
Tom
The BeBOP code looks to be C code but hasn't add the correct C++ guards. Surround your includes with extern "C" to fix that:
extern "C" {
#include <bebop/smc/sparse_matrix.h>
#include <bebop/smc/sparse_matrix_ops.h>
}

Resources