How to conditional compile main() in C? - c

I'm working on a small open source project in C where I'm trying to use a test framework with C (the framework is min_unit).
I have a foo.h file with prototypes, and foo.c, with the implementation.
In my test file, tests.c, I have
#include "../test_framework/min_unit.h"
#include "foo.c"
... test cases ...
the problem is, because I have a main() function in foo.c (which I need to compile it), I can't compile tests.c because I get an error that states
note: previous definition of ‘main’ was here
int main() {
My question is, is there a way to make it so that the main() function in foo.c is conditional, so that it does not compile when I'm running tests.c? It's just annoying to have to remove and add main over and over.

The easiest way to use conditional compilation is to use #ifdef statements. E.g., in foo.c you have:
#ifdef NOT_TESTING //if a macro NOT_TESTING was defined
int main() {
//main function here
}
#endif
While in test.c, you put:
#ifndef NOT_TESTING //if NOT_TESTING was NOT defined
int main() {
//main function here
}
#endif
When you want to compile the main function in foo.c, you simply add the option -DNOT_TESTING to your compile command. If you want to compile the main function in test.c, don't add that option.

Haven't you try the use of pre-processor compiler conditions? May be you've tried but it doesn't work, hum?
Anyway, you probably should:
1- Define a token at top of "tests.c" class file like:
#defined foo_MIN_UNIT_TEST
2- Surround your "main() { ... } " method in "foo.c" class file with #ifndef / #endif like:
#ifndef foo_MIN_UNIT_TEST //consider using #ifndef not #ifdef!!!
int main()
{ ... }
#endif
3- This way, when you compile your unit test files, the main() method of foo.c will not be included in compile time and the only main() method of tests will be available to compiler.
For further reading: http://www.cprogramming.com/
Regards.

Related

Toggling assert testing

I have two source files: one I want to test via asserts, the second containing the asserts.
My problem is that I do not want the testing to be run each time the program itself is run, so is there a way to toggle assert testing on or off depending on a makefile argument?
Or will I have to create another source file, containing both the code I want to test and the assert testing itself?
man 3 assert says
If the macro NDEBUG is defined at the moment <assert.h> was last
included, the macro assert() generates no code, and hence does
nothing at all.
gcc ... -DNDEBUG is intended for a release build, and will not do anything in assert().
My problem is that I do not want the testing to be run each time the
program itself is run
If only the second file you mention contains the assert statements, why would the test code be run when you run the program?
Here is a typical way to divide the code for a module Foo containing a function Bar and its unit test:
Foo.h
#ifndef FOO_H
#define FOO_H
int Foo_Bar(int i);
#endif
Foo.c
#include "Foo.h"
int Foo_Bar(int i)
{
/*to be implemented*/
return -1;
}
FooTest.c
#include "Foo.h"
#include <assert.h>
int main(void)
{
assert(Foo_Bar(0) == 0);
return 0;
}
myprog.c
#include "Foo.h"
int main(void)
{
int bar = Foo_Bar(0);
/*...*/
return 0;
}

multiple definitions of main --> how to add only some functions from another header?

In C I get the linker error multiple definition of `main'. Yes, that is true but:
Why does the linker try to include the second (ext.c) main function although I have just included the header ext.h? I'd expect, the linker only links the functions whose prototypes have been found or which are needed by the initial main?
How can I solve this that
a) test compiles and gets linked without issues (just use the func() from ext.c) and
b) also ext.c can be compiled and linked as separate application?
The (example) code:
//file: test.c
#include "/home/stefanm/test/test.h"
void main (int argc, char * argv[])
{
uint8_t var = 123;
printf ("main(): var= %i\n", var);
func (var);
}
//file: test.h
#ifndef TEST_H
#define TEST_H
#include <the rest>
#include "/home/stefanm/test/ext.h"
#endif
...and the external module:
//file: ext.c
#include "/home/stefanm/test/ext.h"
uint8_t func (uint8_t i){
printf ("func(): Variable i is %i", i);
return 0;
}
void main () {
printf ("ext main func");
}
//file: ext.h
#ifndef EXT_H
#define EXT_H
#include "all needed headers"
uint8_t func (uint8_t);
#endif
I call the compiler with gcc test.c ext.c -o test
Your external module should not have main() because it's a module and not an application. You should just move main() from your module to a separate file:
//file: app.c
#include "/home/stefanm/test/ext.h" // <-- BTW, using absolute paths is not a good idea
void main () {
//use function from ext here
printf ("app main func");
}
And then compile your application like this:
gcc app.c ext.c
and your test like this:
gcc test.c ext.c
In C, you can only have one definition of a function in all of the files you link into your executable. There's no good way to tell the compiler "I want to use this main() and not all the others". (There's a bad way, using macros, but it would be messy).
If you want to use a function with two different main() functions, put it in a separate file.
I suppose your compile/link call goes like
gcc test.c ext.c
In this case, test.c and ext.c (resp., to be exact, the .o files created out of them) are peers, i. e. on the same level. How should the linker know which version of the symbol main to take and which to discard? The linker doesn't know about the include files used.
In the case of a main function, the correct way to go is to have exactly one of them in your project.
For any other function where you have this requirement, there are several ways to go:
Either, you could declare one of them as "weak". It will be discarded when there is a "strong one".
Or you put your function into a library, e. g. libext.a. If you link that with -ext, only the object files which define symbols which are undeined are taken out of it. But then again, name clashes can occur if another name defined by that object file is defined already. So it is the best to only define as few symbols per object file as possible.

Default function implementation for linking

I have a family of executables pieced together from a set of .o files. There's some reusable ones, and then usually a couple of executable specific modules. One of the reusable pieces wants to provide a sort of "application hook". But many of the executables just do a standard no-op thing. While a couple of others actually want to define interesting behavior for said hook.
What would be ideal, is if there was a way to provide a standard default version of the function, which the linker would use if none of the other .o files defined said function, but if they did, use the others.
Is there any way/technique to approximate this sort of thing with just straight C?
If you're using GCC as your compiler, then you can declare the replaceable functions like this:
void foo() __attribute__ ((weak));
Here's an example on how this works. In your main.c file:
#include <stdio.h>
void foo()__attribute__ ((weak))
{
printf("%s", "Hidden foo\n");
}
int main()
{
foo();
return 0;
}
In another file, foo.c:
#include <stdio.h>
void foo()
{
printf("%s", "foo\n");
}
Now when you only compile, link and run main.c, you'll get:
gcc main.c -o main
./main
Hidden foo
If you instead also compile foo.c, you'll get:
gcc main.c foo.c -o main
./main
foo
The weak version of foo() was replaced.
On a real setup, you would probably use a header file to provide the function prototypes:
void foo();
and then implement the weak version of those functions like this:
__attribute__ ((weak)) void foo()
{
// ...
}
You could also use a macro to make this a bit more readable:
#define WEAK_SYMBOL __attribute__ ((weak))
So that you'll get:
WEAK_SYMBOL void foo() { /* ... */ }

#include other C programs

I need to include file_1.c into main.c. In file_1.c, I currently have multiple functions. If I want to call these functions in main.c, what do I need to do? I have #include"file_1.c" in my main program.
Use standard approach by making header file
#include"file_1.h"
you will have to compile this "file_1.c" together with main.c and make one executable
because function calls are need in run time.
Try this :
create a header file file_1.h
#ifndef _FILE_H
#define _FILE_H
void foo(int );
#endif
give all the declaraion of function and struct definitions (if any) or any global variables
then in file_1.c will contain actual defintion of function
//file_1.c
#include "file_1.h"
#include <stdio.h>
void foo(int x)
{
printf("%d\t",x);
}
//main.c
#include "file_1.h"
int main()
{
int x=10;
foo(x);
return 0;
}
include header file file_1.h in both (main.c and file_1.c) the c files
In gcc
gcc -Wall main.c file_1.c -o myexe.out
Why do you think you need to do this?
Normally you would add the declaration of functions in file_1.c into file_1.h and include that in main.c.
When you link the program, you just need to include both main.c and file_1.c (which then includes the definitions of the functions) on the command line.

Experimenting with global variables and functions in C

I'm trying to understand how global variables and functions work in C. My program compiles and works fine with gcc, but does not compile with g++. I have the following files:
globals.h:
int i;
void fun();
globals.c:
#include "stdlib.h"
#include "stdio.h"
void fun()
{
printf("global function\n");
}
main.c:
#include "stdlib.h"
#include "stdio.h"
#include "globals.h"
void myfun();
int main()
{
i=1;
myfun();
return 0;
}
And finally, myfun.c:
#include "stdlib.h"
#include "stdio.h"
#include "globals.h"
void myfun()
{
fun();
}
I get the following error when compiling with g++:
/tmp/ccoZxBg9.o:(.bss+0x0): multiple definition of `i'
/tmp/ccz8cPTA.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status
Any ideas why? I would prefer to compile with g++.
Every file you include globals.h from will define "int i".
Instead, put "extern int i;" into the header file and then put the actual definition of "int i = 1;" in globals.c.
Putting header guards around globals.h would be sensible too.
Edit: In answer to your question its because a #include works kind of like a cut and paste. It pastes the contents of the included file into the c file that you are calling include from. As you include "globals.h" from main.c and myfun.c you define int i = 1 in both files. This value, being global, gets put into the table of linkable values. If you have the same variable name twice then the linker won't be able to tell which one it needs and you get the error you are seeing. Instead by adding extern on the front in the header file you are telling each file that "int i" is defined somewhere else. Obviously, you need to define it somewhere else (and ONLY in one place) so defining it in globals.c makes perfect sense.
Hope that helps :)
I would add an include guard in your globals file
#ifndef GLOBALS_H
#define GLOBALS_H
int i;
void fun();
#endif
Edit: Change your globals to be like this (using extern as the other answer describes)
globals.h
extern int i;
extern void fun();
globals.c
#include "stdlib.h"
#include "stdio.h"
int i;
void fun()
{
printf("global function\n");
}
I compiled it with
g++ globals.c main.c myfun.c
and it ran ok
Several things wrong here; several other things highly recommended:
globals.h:
#ifndef GLOBALS_H
#define GLOBALS_H
extern int my_global;
#ifdef __cplusplus
extern "C" {
#endif
void fun();
#ifdef __cplusplus
}
#endif
#endif
/* GLOBALS_H */
globals.c:
#include <stdlib.h>
#include <stdio.h>
#include "globals.h"
int my_global;
void fun()
{
printf("global function: %d\n", my_global);
}
main.c:
#include <stdlib.h>
#include <stdio.h>
#include "globals.h"
void myfun();
int main()
{
my_global=1;
myfun();
return 0;
}
void myfun()
{
fun();
}
You should declare "extern int myvar" in your header, and actually allocate "int myvar" in one and only one .c file.
You should include "globals.h" in every file that uses "myvar" - including the file where it's allocated.
Especially if you're planning on mixing C and C++ modules, you should use 'extern "C"' to distinguish non-C++ functions.
System headers should be "#include <some_header.h>"; your own headers should use quotes (#include "myheader.h") instead.
Short variable names like "i" might be OK for a strictly local variable (like a loop index), but you should always use longer, descriptive names whenever you can't avoid using a global variable.
I added a "printf" for my_global.
'Hope that helps!
I had this problem when porting some old C code to C++. The problem was it was a project that was connected to a database, and i wanted to port the database to c++ but not the rest. The database pulled in some C dependencies that couldn't be ported, so i needed the C code that overlapped both the database and the other project to compile in g++ as well as gcc...
The solution to this problem is to define all variables as extern in the .h file. then when you compile in either gcc or g++ it will report symbols missing in the .c files. So edit the .c files in the error messages and insert the declaration into all the .c files that need the variables. Note: you may have to declare it in multiple .c files, which is what threw me and why I was stuck on this problem for ages.
Anyway this solved my problem and the code compiles cleanly under both gcc and g++ now.

Resources