Why linking .cc file works in make file but linking .c file doesn't? - c

I'm working on a quite large Makefile from the tensorflow repo and I need to add a file link.
After quite some debugging of a link error, I found out that if my file ends with .cc, then the link error disappears, whereas when linking a .c file, the error appears (file content remains the same).
I am linking the file in a Makefile.inc file:
.
.
.
FL_SRCS := \
tensorflow/lite/vis_mi/main.cc \
myFunctions.c \ -->>>>IF I CHANGE THE FILENAME TO myFunctions.cc and link to this .cc file here, it works!!
.
.
.
# Builds a standalone binary.
$(eval $(call vis_test,vis_mi,\
$(FL_SRCS),$(FL_HDRS)))
The link error when using the .c ending ends with:
tensorflow/lite/vis_mi/main.o: In function `main':
tensorflow/lite/vis_mi/main.cc:183: undefined reference to `printMsg()'
../downloads/gcc_embedded/bin/../lib/gcc/arm-none-eabi/7.3.1/../../../../arm-none-eabi/bin/ld: link errors found, deleting executable `tensorflow/lite/vis_mi'
collect2: error: ld returned 1 exit status
gmake: *** [tensorflow/lite/vis_mi/Makefile.inc:578: tensorflow/lite/vis_mi/bin/micro_speech] Error 1
The .c file code:
#include <stdio.h>
#include "myFunctions.h"
void printMsg(){
//do something here
}
And the header file:
#ifndef MYFUNCTIONS_H
#define MYFUNCTIONS_H
void printMsg();
#endif /* MYFUNCTIONS_H */
How can I include a file ending with .c? Makefiles are fairly new to me, and didn't want to include all the details, and if you need any further details from the Makefile to answer this question I'm happy to edit my post.

The name resolution for C and C++ functions is different. This is sometimes causing problem to "C" code that is also valid "C++". For example:
int foo(int x) { return x+1 } ;
The code Will create a function called 'foo' when compiled as "C", and will create a function called '_Z3fooi' when compiled as C++. Decoding the C++ name will (using c++filt) will show foo(int). The reason for the difference is that C++ support polymorphic functions (and methods), so that function names also identify the type of their parameters.
The proper solution is to decide on the language of the code. C++ and C are different language, and while it's possible to write code that will be valid for both, it will limit the ability to leverage each function abilities.
Important constraint: If a project contain both C and C++ code, it is important to remember that only functions that follow the "C" conventions can be called between the languages. This is usually implemented with extern "C" directive, and with #ifdef __cplusplus:
See more: https://www.thegeekstuff.com/2013/01/mix-c-and-cpp/ How to call C++ function from C? Call a C function from C++ code

Related

how I call a function in my source file including only header file in c?

I would like to know , if I have source file like this
#include <stdio.h>
int main()
{
printf("Hello world");
}
as I know header files contains only prototypes of functions. If it so how can my source file get the function printf ? If I don't include the source file where it has been declared?
thank you
The question is not clear, but there are 2 things which happen before a program gets created,
Compiling (requires prototypes / declarations)
Linking (requires definitions).
Header information is needed for knowing prototypes. Even this would compile fine:
int printf ( const char * format, ... );
int main()
{
printf("Hello world");
}
On linking there will be no issues because the printf function is found in the C standard library, so on linking it will look into the standard directories (of the compiler where the library is kept - bin/lib folder) and link the function.
The source only needs to know the prototype. The problem a programmer will have in this case:
int my_printf ( const char * format, ... );
int main()
{
my_printf("Hello world");
}
The above will compile, but when linking my_printf your code will not have a definition so it will give an error on linking.
Header file has the definitions declarations of the functions ( stdio.h has definition declaration for printf ). The actual function exists in the libraries and gets linked when you compile the code.
When it comes to using libraries, you include the header of the library in your code and you instruct the linker to link using the code files of that library(usually object files). For the standard libraries, the IDE usually instructs the linker to link to them by default.
Assuming you're using gcc as a compiler the standard libraries are linked by default and that is where the function definitions lie. If you'd like to see exactly which libraries are being linked you can pass gcc the -v option which will cause it to dump information about the default options it will use including the library paths and default libraries and object files that will be linked in.
If you give the -Wl,--verbose option, gcc will pass the --verbose to the linker which will dump exactly where it's looking for libraries, including both failed and successful searches
gcc -v foo.c -Wl,--verbose
The header file stdio.h would declare printf as an extern function, i.e., it is defined elsewhere. The compiler is happy as long as functions you use have a declaration. The linker is the one that resolves these dependencies.
A very useful thing to do when you start asking good questions like this is to play with some linker commands.
Assuming you're on *nix, once you have your executable file (lets call it foo), do:
ldd foo
You should see a list of libraries that were linked with while creating foo.
libc.so should be one among those. It contains the definition for printf among other things!
You can refer to this link to learn more

Including source files in C files

I am very new to C, so I apologize for this newby question.
I would like to use this source code in my project: http://base64.sourceforge.net/b64.c.
So, I include it in my test file:
#include <stdio.h>
#include "b64.c"
int main()
{
return 0;
}
However, main() is defined in b64.c as well, so upon compiling, I get:
test.c:4:5: error: redefinition of ‘main’
b64.c:495:5: note: previous definition of ‘main’ was here
test.c: In function ‘main’:
test.c:5:1: error: number of arguments doesn’t match prototype
b64.c:495:5: error: prototype declaration
What is the correct usage of this source file, or any? How do we correctly use it, or use functions defined in that file?
Edit: I understand that the problem is due to the duplicate definitions of main. I know there can only be one. My question is rather, won't every meaningful project need it's main method? Then why is there a main method defined in b64.c? Are we just supposed to delete this method from the source code? It seems odd that the source code doesn't just come ready to be included and used.
It is never a good idea to #include a C source file into your code. You can either copy the code from the other C source file into your code, or include the needed prototypes in your code and make a call to the functions, linking those after compiling them separately.
you should use one of the two main functions.
If you want a new main, write your main method in your file and remove it from the 'b64.c' file, if you want to use it from the 'b64.c' file remove your (empty) main.
If main is defined in b64.c either you cannot simply redefine it in your main source file.
What do you want is to use several functions from b64.c in your program. Delete the main function from it and create a header file where you protoype all of the functions in b64.c. After that, include this header file in your main program. Have a look at this short Wikipedia entry. It should give you an overview of the topic.
Besides this: It seems that you aren't very familar with C. Try out some tutorials and go on reading about C.
First of all, you must redeclare the .c file as a .h, and then you have to go through the source code and rename any duplicate methods or global variable names. The main method is the starting point of a program so there can only be one.
(Usualy you dont include .c files, only .h)
if you want the functions inside the "b64.c" you should delete the main function from "b54.c"!
A C application needs one main() function. Your file b64.c looks like a self-sufficient C program so you don't need your test.c. Just compile and run b64.c.
When you are including that source file you are getting 2 main() declaration which is incorrect. So you have redefined "main" in this case.
Including .c into another .c file doesn't make sense. C files compile to .obj files, which are linked by the linker into the executable code , so there is no need to include one .C file into another. Instead, you can make a .h file that lists the functions and include that .h file

Calling methods from multiple C files without custom header files, Makefile Linking

This has gotten a bit lost in translation so I am going to be more precise:
we have classes recursion.c, fib.c, and countUp.c. from recursion.c we have to recursively call fib.c or countUp.c, decided by the input argument. I can't use header files and am only given that I must place prototypes:
int fib(int n);
and
void countUp(int n);
My Makefile
TAR = tar
COMPILER_FLAGS = -g -Wall -std=c99 -c
LINKER_FLAGS = -g -o
OBJS = recurse.o
C_FILES = recurse.c fib.c countUp.c
ASM_FILES = recurse.asm
TARGET_FILE = recurse
TARGET_TAR = PA5.tar
$(TARGET_TAR): $(TARGET_FILE)
$(TAR) -cvf $(TARGET_TAR) $(C_FILES) $(ASM_FILES) $(TARGET_FILE) Makefi$
recurse.o: recurse.c
$(C_COMPILER) $(COMPILER_FLAGS) $(C_FILES)
$(TARGET_FILE): $(OBJS)
$(LD_LINKER) $(LINKER_FLAGS) $(TARGET_FILE) $(OBJS)
where fib and countUp class methods must be called recursively. The recursive.c file is considered our c driver. Do not create or implement any header files OTHER than those that are standard c headers (stdio.h, string.h, etc.). When I try to run this I get:
make
gcc -g -o recurse recurse.o
recurse.o: In function `main':
(file root location)/recurse.c:43: undefined reference to `fib'
(file root location)/recurse.c:46: undefined reference to `countUp'
collect2: ld returned 1 exit status
make: *** [recurse] Error 1
Any clue what is going on.
Original Question:
I have multiple C files that I am combining into an executable. For example say I have math.c, the arguments are passed into it, and then if the input argument calls add it performs functions from add.c, if the argument calls subtract it will call functions from subtract.c, etc. The files are then compiled into a .o file, and then an executable is created. The issue I have is not being able to utilize header (.h) files. Is there any way to break into the separate classes or am I missing something? I really don't know exactly how to ask the question, jargon is pretty bad as far as C goes, sorry :(
I don't really get the idea of a driver I guess. (Not a device driver, she keeps telling us this is a c executable driver).
If I understood correctly, what I think you need to do is add the following prototypes above any of the functions you define in recursion.c. The prototypes will allow you to call these functions from within any function inside recursion.c (In fact, including a header file is akin to copy-pasting all of the prototypes defined in the file, as #Justin and #EdS already pointed out)
int fib(int n);
void countUp(int n);
int main() {
...
}
Then you need to make sure that your project file includes the files recursion.c, fib.c, and countUp.c - When you build your project, the linker will do its job and lookup the entry points in your compiled object files, and will proceed to assemble a single executable file.
What compiler are you using?
Including a header file is just a preprocessor directive to include the contents of that file at the location of the include. To achieve the same thing without a header file just copy and paste the code that you would have put in the header file into the top of each c file.
Of course this isn't very maintainable as if you want to change that contents you need to change it in many files, hence why header files exist in the first place.
Since this is homework and considering the fact that you have told us that A) You have no header files to use, and B) you have not been instructed to utilize the extern keyword, it seems to me that your only choice is to include the .c files themselves:
#include "add.c"
#include "subtract.c"
/* etc... */
int main()
{
// use functions defined in "add.c", "subtract.c", etc.
}
Note that this is bad form as you are including the implementation instead of the interface and likely pulling in a bunch of stuff you don't want or need. If that doesn't answer your question then there is something, some instruction from your teacher, missing in the question.

Include c file in another

I want to include a .c file in another. Is it possible right? It works well if I include a header file in a .c file, but doesn't work as well if I include a .c file in another .c file.
I am using Visual Studio and I get the following error:
main.obj : error LNK2005: _sayHello already defined in sayHello.obj
/* main.c */
#include "sayHello.c"
int main()
{
return 0;
}
/* sayHello.c */
#include <stdio.h>
void sayHello()
{
printf("Hello World");
}
I don't know what this error could mean. Time to ask more advanced C coders. :)
I want to include a .c file in another.
No you don't. You really, really don't. Don't take any steps down this path; it only ends in pain and misery. This is bad practice even for trivial programs such as your example, much less for programs of any real complexity. A trivial, one-line change in one file will require you to rebuild both that file and anything that includes it, which is a waste of time. You lose the ability to control access to data and functions; everything in the included .c file is visible to the including file, even functions and file scope variables declared static. If you wind up including a .c file that includes another .c file that includes another .c file und so weiter, you could possibly wind up with a translation unit too large for the compiler to handle.
Separate compilation and linking is an unequivocal Good Thing. The only files you should include in your .c files are header files that describe an interface (type definitions, function prototype declarations, macro defintions, external declarations), not an implementation.
It works, but you need to be careful with how you build the program. Also, as folks have pointed out in comments, it's generally considered a bad idea. It's unexpected, and it creates problems like these. There are few benetfits, especially for what seems like a trivial program. You should probably re-think this approach, altogether.
After doing something like this, you should only compile main.c, and not attempt to link it with the result of compiling sayHello.c, which you seem to be doing.
You might need to tell Visual Studio to exclude the latter file from the build.
Yes, any '.c' file can be included into another program.
As one include '.h' file like 'stdio.h' in the program.
After that we can call those function written into this external file.
test.c::
#include<stdio.h>
#include<conio.h>
void xprint()
{
printf("Hello World!");
}
main.c::
#include "test.c"
void main()
{
xprint();
getch();
}
Output:: Hello World!
This is a linker error. After compiling all your .c files to .obj files (done by the compiler) the linker "merges" them together to make your dll/exe. The linker has found that two objects declare the same function (which is obviously not allowed). In this case you would want the linker to only process main.obj and not sayhello.obj as well (as its code is already included in main.obj).
This is because in main.obj you will ALSO have the sayHello() function due to the include!
sayHello.h
#include <stdio.h>
void sayHello(void);
main.c
#include "sayHello.h"
int main()
{
sayHello();
return 0;
}
You probably defined two times this function
void sayHello()
{
printf("Hello World");
}
one in your current file and one in sayhello.c
You must remove one definition.
The problem seems to be that sayHello.c got compiled into an object file called sayHello.obj, and main.c (also including all the source text from sayHello.c), got compiled into main.obj, and so both .obj files got a copy of all the external symbols (like non-static function definitions) from sayHello.c.
Then all the object files were supposed to get "linked" together to produce the final executable program file, but the linking breaks when any external symbols appear more than once.
If you find yourself in this situation, you need to stop linking sayHello.obj to main.obj (and then you might not want to compile sayHello.c by itself into its own object file at all).
If you manually control every step of the build (like you might when using the CLI of your compiler), this is often just a matter of excluding that object file from the invocation of the linker or compiler.
Since you are using Visual Studio, it's probably making a bunch of assumptions for you, like "every .c file should be compiled into its own object file, and all those object files should be linked together", and you have to find a way to circumvent or disable this assumption for sayHello.c.
One easy and somewhat idiomatic solution might be to rename sayHello.c into sayHello.c.inc.
//THIS IS THE MAIN FILE//
#include "test.c"
int main()
{
multi(10);
}
//THIS IS THE TEST FILE//
#include<stdio.h>
void multi(int a)
{
printf("%d",a*2);
}
POINTS TO BE NOTED:
Here you need to run the program which contains "main()" function.
You can avoid the "stdio.h" header file in main function. Because, you are including the file which already contains the "stdio.h" header file.
You have to call the function from the "main" file.
The including file should be "file_name.c" not "file_name.h". Because usually we use .h extension for the header file. Since we are including another program file and not the header file, we have to use .c. Otherwise it will give you Fatal Error and the Compilation gets terminated.

How to prevent multiple definitions in C?

I'm a C newbie and I was just trying to write a console application with Code::Blocks. Here's the (simplified) code:
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "test.c" // include not necessary for error in Code::Blocks
int main()
{
//t = test(); // calling of method also not necessary
return 0;
}
test.c:
void test() {}
When I try to build this program, it gives the following errors:
*path*\test.c|1|multiple definition of `_ test'|
obj\Debug\main.o:*path*\test.c|1|first defined here|
There is no way that I'm multiply defining test (although I don't know where the underscore is coming from) and it seems highly unlikely that the definition is somehow included twice. This is all the code there is.
I've ruled out that this error is due to some naming conflict with other functions or files being called test or test.c. Note that the multiple and the first definition are on the same line in the same file.
Does anyone know what is causing this and what I can do about it? Thanks!
You actually compile the source code of test.c twice:
The first time when compiling test.c itself,
The second time when compiling main.c which includes all the test.c source.
What you need in your main.c in order to use the test() function is a simple declaration, not its definition. This is achieved by including a test.h header file which contains something like:
void test(void);
This informs the compiler that such a function with input parameters and return type exists. What this function does ( everything inside { and } ) is left in your test.c file.
In main.c, replace #include "test.c" by #include "test.h".
A last point: with your programs being more complex, you will be faced to situations when header files may be included several times. To prevent this, header sources are sometimes enclosed by specific macro definitions, like:
#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED
void test(void);
#endif
The underscore is put there by the compiler and used by the linker. The basic path is:
main.c
test.h ---> [compiler] ---> main.o --+
|
test.c ---> [compiler] ---> test.o --+--> [linker] ---> main.exe
So, your main program should include the header file for the test module which should consist only of declarations, such as the function prototype:
void test(void);
This lets the compiler know that it exists when main.c is being compiled but the actual code is in test.c, then test.o.
It's the linking phase that joins together the two modules.
By including test.c into main.c, you're defining the test() function in main.o. Presumably, you're then linking main.o and test.o, both of which contain the function test().
You shouldn't include other source files (*.c) in .c files. I think you want to have a header (.h) file with the DECLARATION of test function, and have it's DEFINITION in a separate .c file.
The error is caused by multiple definitions of the test function (one in test.c and other in main.c)
I had similar problem and i solved it following way.
Solve as follows:
Function prototype declarations and global variable should be in test.h file and you can not initialize global variable in header file.
Function definition and use of global variable in test.c file
if you initialize global variables in header it will have following error
multiple definition of `_ test'|
obj\Debug\main.o:path\test.c|1|first defined here|
Just declarations of global variables in Header file no initialization should work.
Hope it helps
Cheers
Including the implementation file (test.c) causes it to be prepended to your main.c and complied there and then again separately. So, the function test has two definitions -- one in the object code of main.c and once in that of test.c, which gives you a ODR violation. You need to create a header file containing the declaration of test and include it in main.c:
/* test.h */
#ifndef TEST_H
#define TEST_H
void test(); /* declaration */
#endif /* TEST_H */
If you have added test.c to your Code::Blocks project, the definition will be seen twice - once via the #include and once by the linker. You need to:
remove the #include "test.c"
create a file test.h which contains the declaration:
void test();
include the file test.h in main.c
If you're using Visual Studio you could also do "#pragma once" at the top of the headerfile to achieve the same thing as the "#ifndef ..."-wrapping. Some other compilers probably support it as well ..
.. However, don't do this :D Stick with the #ifndef-wrapping to achieve cross-compiler compatibility. I just wanted to let you know that you could also do #pragma once, since you'll probably meet this statement quite a bit when reading other peoples code.
Good luck with it
Ages after this I found another problem that causes the same error and did not find the answer anywhere. I thought to put it here for reference to other people experiencing the same problem.
I defined a function in a header file and it kept throwing this error. (I know it is not the right way, but I thought I would quickly test it that way.)
The solution was to ONLY put a declaration in the header file and the definition in the cpp file.
The reason is that header files are not compiled, they only provide definitions.

Resources