0

I am writing an SQL parser. SQLSelectParser.l is the lex file which generates lex.yy.c file successfully using lex compiler. In SQLSelectParser.l file, I call external functions defined in Ast.h/c file. I #include Ast.h in %{ %} section of SQLSelectParser.l.

I compiles the src file individually without any problems.

lex SQLSelectParser.l
gcc -g -c lex.yy.c -o lex.yy.o
gcc -g -c Ast.c -o Ast.o 
gcc -g lex.yy.o Ast.o -o exe -lfl   << but get linker error.

Function ast_add_child is declared in Ast.h and defined in Ast.c. I am not able to understand why i am getting linker error. Is this common problem while linking with flex generated src file ?

/usr/bin/ld: lex.yy.o: in function `create_q_parse_columns':
/home/vm/RDBMSImplementation/Parsers/SQLSelectParser.l:405: undefined reference to `ast_add_child'
/usr/bin/ld: /home/vm/RDBMSImplementation/Parsers/SQLSelectParser.l:417: undefined reference to `ast_add_child'
collect2: error: ld returned 1 exit status

here is a link to SQLSelectParser.l file which used ast_add_child().

Ast.h is here

Ast.cpp is here

Abhishek Sagar
  • 1,189
  • 4
  • 20
  • 44
  • Note that if you provide your own `main()` function then `-lfl` does nothing useful for you. But neither is it harmful. – John Bollinger Aug 01 '23 at 21:24
  • Supposing that lex.yy.c compiled cleanly at normal or enhanced warning level, the issue is probably in your Ast.c: it does not provide an external definition of function `ast_add_child()`. Possibly it provides an internal (`static`) one instead, possibly it provides the function with a different (misspelled) name, or possibly it just doesn't provide the function at all. – John Bollinger Aug 01 '23 at 21:26
  • no, functions are public in Ast.h/.c. , not static. – Abhishek Sagar Aug 01 '23 at 22:02
  • That was only one of the possible issues I mentioned. Without a [mre] we can only suggest possibilities, but I assure you that the issue has nothing to do with `flex`. The linker error is telling you, among other things, that Ast.o is not providing `ast_add_child` as an external function. Look for the function's definition (implementation) in Ast.c. If you find it then correct the spelling of its name there, and / or make sure it's not carrying any function attributes that might be interfering, and / or ensure that it's not being excluded by conditional compilation directives. – John Bollinger Aug 01 '23 at 22:20
  • And if you have not already done so then *confirm*, too, that it is not defined with the `static` qualifier. – John Bollinger Aug 01 '23 at 22:22
  • And make sure that Ast.c `#include`s Ast.h. That will help the compiler recognize some (but not all) errors related to declarations mismatched with their definitions. And turn on at least the `-Wall` compiler option, and maybe also one or both of `-Wextra` and `-pedantic`. – John Bollinger Aug 01 '23 at 22:23
  • Added Ast.h/.cpp if you want to take a look. @john – Abhishek Sagar Aug 01 '23 at 22:42
  • since you have a .cpp file mentioned I'm curious if you are actually trying to compile a c function into a c++ application without the use of an `extern "C"` block – Scott Christensen Aug 01 '23 at 23:30
  • No, I do not want to take a look at an external resource. Everything needed to inform an answer to the question needs to be presented in the question itself. Preferably in the form of a [mre]. – John Bollinger Aug 02 '23 at 01:03
  • 2
    However, your link betrays a relevant detail that you previously disguised: you do not have an Ast.c file, but rather Ast.cpp. This would conventionally indicate a file intended for compilation as C++, and if it is indeed being compiled that way, without provision for being its functions being C-callable, then that would be another plausible explanation. – John Bollinger Aug 02 '23 at 01:11
  • Though file Ast.cpp is named with cpp extention, it contain purely C code. I was using gcc to compile. However, linking time it was throwing error as i mentioned. I renamed Ast.cpp to Ast.c and linker error immediately goes away. I thought as long as file contain pure C code, file extension dont matter to compilers. Thanks for your time and effort @JohnBollinger – Abhishek Sagar Aug 02 '23 at 03:59
  • C++ uses name mangling unless you specifically tell it not to. This is a thing you have to always be wary of when linking C and C++. https://stackoverflow.com/questions/2937273/questions-about-name-mangling-in-c – Piotr Siupa Aug 02 '23 at 07:35
  • ... and some compilers and build systems *do* pay attention to filename extension, though I'm not used to GCC doing this when run explicitly. And I have no clue why one would name a source file .cpp when one means for it to be interpreted as C code. C and C++ are distinct languages with a shared subset. If you are exceedingly careful, you can write code that is *source* compatible with both, but even then it can matter how you compile it, as you discovered. – John Bollinger Aug 02 '23 at 11:07

1 Answers1

1

gcc -g -c Ast.c -o Ast.o

Rule 1: show actual command instead of imaginary one.

You don't have Ast.c, you have Ast.cpp, so the command you've shown must not be the command you actually ran.

When you compile code with gcc -c Ast.cpp, it gets compiled as C++. If you run nm Ast.o | grep ast_add_child, you would see something like _Z13ast_add_childv.

Rule 2: learn to fish. When you get an undefined symbol error, use nm (as above) to confirm the symbol you are missing is in fact defined where you think it is.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362