Linking files having multiple main function in c - c

Is it possible to link two C files using makefile which calls each other function but both have a main function of their own.
e.g:
C1.c uses function f() from C2.c.but both have main function and I want the main in C1.c to be considered as main only.
FILES.o=set.o hash.o printnfa.o input.o nfa.o dfa.o terp.o minimize.o defnext.o print_ar.o pairs.o squash.o signon.o print.o lex.o assort.o prnt.o printv.o bintoasc.o ferr.o onferr.o fputstr.o pchar.o driver.o searchenv.o hashadd.o esc.o
PROGRAM= Lexer
INC := -I./debug.h -I./global.h -I./stack.h -I./set.h -I./hash.h
CFLAGS=-DMAIN
all: ${PROGRAM}
${PROGRAM}: ${FILES.o}
${CC} -o $# ${CFLAGS} $(INC) $^ ${LDFLAGS} ${LDLIBS}
Now terp.c has a main and lex.c also has a main. I want only the main for lex.c to be considered.

This will be specific for the linker you use. On Linux you can pass the --allow-multiple-definition flag to the linker in order to use only the first symbol in case of multiple definitions:
${PROGRAM}: ${FILES.o}
${CC} -Xlinker --allow-multiple-definition -o $# ${CFLAGS} $(INC) $^ ${LDFLAGS} ${LDLIBS}
This will omit all errors about duplicate symbols and cause the linker to ignore any redefinitions. Make sure that the object file containing the symbol you wish to use comes before any redefinitions in the list.

The short answer... NO ... it is NOT possible

First of all I would recommend that you refactor the code so that you don't have functions that will be used by many programs in the same file as a main function.
Any way, here is an example on how to use the pre-processor to include only one of the main functions.
We have two source code files both with a main function plus one other function, foo() in file1.c and bar() in file2.c. foo() and baa() are called from both of the main functions.
By changing the MAIN_ALT value in the Makefile we can switch between the main functions:
Use the main function in file1.c:
DEFINES += -DMAIN_ALT=1
Use the main function in file2.c:
DEFINES += -DMAIN_ALT=2
Makefile:
OBJS = file1.o file2.o
DEFINES += -DMAIN_ALT=1
CFLAGS += -Wall $(DEFINES)
prog:$(OBJS)
$(CC) $(CFLAGS) -o $# $^
file1.c:
#include "stdio.h"
#include "def.h"
void foo(){
printf("From foo\n");
}
#if MAIN_ALT == 1
int main(){
printf("Main in file1.c\n");
bar();
foo();
return 0;
}
#endif
file2.c:
#include "stdio.h"
#include "def.h"
void bar(){
printf("From bar\n");
}
#if MAIN_ALT == 2
int main(){
printf("Main in file2.c\n");
bar();
foo();
return 0;
}
#endif
def.h:
#ifndef __DEF_H__
#define __DEF_H__
void foo();
void bar();
#endif

Related

Why i must to include my own lib archive when i´m compiling

I have a problem including my own library.
I have created some functions in a few archives .c,
after that i have created the header file .h,
but when i try to compile a main.c that call a function that was in my own lib
i must to type gcc ownlib.a main.c -o prog.out and include the lib ownlib.a archive
as a parameter of gcc.
In this case i was trying to call my own strlen() called ft_strlen() function that is in my own lib.
I know when i compile any program using a function that is in a compiler library i only must
include the header in the code for example: #include <string.h>,
but when i call my own function i add #include "ownlib.h".
If i compile the main.c calling system function strlen() i have to compile only the main.c
archive and it works.
When i create a lib with my own ft_strlen() and in the main.c i include my own lib
#include "ownlib.h" it doesn´t work if i do this gcc main.c -o program.out
but it works if i add my lib archive like this gcc main.c ownlib.a -o program.out
I want to know why when i use a system library function i don´t need to compile with the library archive,
for example gcc main.c string.c -o program.out,
only whith the #include <string.h> it works,
and why i must to include my ownlib.a in the compiation gcc libft.a main.c -o program.out.
I don't know if I explained myself well
LIBNAME = ownlib.a
HEADERNAME = ownlib.h
SRCS = ft_strlen.c
OBJS = $(SRCS:.c=.o)
CC = gcc
CFLAGS = -Wall -Wextra -Werror
AR = ar
ARFLAGS = -rcs
$(LIBNAME): $(OBJS) $(HEADERNAME)
#$(AR) $(ARFLAGS) $(LIBNAME) $(OBJS)
all: $(LIBNAME)
clean:
$(RM) $(OBJS)
fclean: clean
$(RM) $(LIBNAME)
re: fclean all
%.o: %.c $(HEADERNAME)
#${CC} ${CFLAGS} -c $< -o ${<:.c=.o}
.PHONY: all clean fclean re
one of the functions is like this:
#include "ownlib.h"
size_t ft_strlen(const char *str)
{
int i;
i = 0;
while (str[i] != '\0')
i++;
return (i);
}
Th main function is:
#include <stdio.h>
#include "ownlib.h"
int main(void)
{
char *str;
str = "How many characters";
printf("%i", ft_strlen(str);
return (0);
}
If i compile gcc main.c -o program.out don´t know what is ft_strlen()
Thanks so much

linking with wrap directive for unit testing can be used to redefine a subroutine?

I'm using Cmocka to write a unit testing suite for a shared object written in C, but I'm having some issue. Since I cannot share the source code, I have written a minimum "not-working" example to show what is the issue:
my program is composed 5 files: foo.c, foo.h bar.c bar.h main.c.
bar.* files define a bar() function, which simply returns the argument multiplied by 2
foo.* files declare a foo() function that uses the bar() function defined by bar.h
main.c contains a simple cmocka test and a __wrap_bar()
function, returning the argument multiplied by 3.
I compile the program by producing a libfootest.so object (foo+bar) and then I link this object with main.o passing the -Wl,--wrap=bar flag to the compiler. In this configuration libfootest is the module under test and main is the tester program. I expect the __wrap__bar to be called (failing the test), but the standard bar() is called(test is passed). How can I solve this problem? Below you find all the code I'm using.
bar.c:
#include "bar.h"
int bar(int val) {
return val*2;
}
bar.h:
int bar(int val);
foo.h:
#include <stdio.h>
int foo(int val);
foo.c:
#include "foo.h"
#include "bar.h"
int foo(int val) {
int ret;
ret = bar(val);
printf("RET: %d", ret);
return ret;
}
main.c:
#include <stdio.h>
//required include for CMOCKA
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <setjmp.h>
#include <cmocka.h>
//library under test
#include "foo.h"
int __wrap_bar(int val) {
return 3*val;
}
static void test_foo(void **state) {
int ret = foo(5);
assert_int_equal(ret, 10);
}
int main (int argc, char** argv) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_foo),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}
Makefile:
CMOCKA_LIB_DIR=../../cmocka-1.1.5/build/src
CXXFLAGS+=-g -Og -fPIC
CFLAGS+=-g -Og -std=c99 -fPIC
CC=gcc
CXX=g++
all: main.o ./libfootest.so
gcc -o linux-test -g -L. -L$(CMOCKA_LIB_DIR) $(filter %.o, $^) -lcmocka -lfootest -Wl,-rpath=. -Wall -Wl,--wrap=bar -Wl,-rpath=$(CMOCKA_LIB_DIR)
./libfootest.so: foo.o bar.o
$(CC) -shared -o $# -g $^ -pedantic -Wall
clean:
rm -f *.o
rm -f *.so
The problem is your build of the library. You don't create a link library as commonly done, with separated modules. Instead you link all given modules and place the resulting single module in the target library.
That's why the linker resolved the call to bar() already, and it is no longer unresolved when linking the test program.
The option --wrap works only for unresolved references between modules.
The solution is to build the library from separated modules. Use the tool ar for this:
ar r libfootest.a foo.o bar.o

Compile time error while running multiple c files

#Edited
I am tested on simple two files now that are add.h and add.c.
I made a Makefile in order to compile my program. Here is my makefile.
# Make file for running the project
CC=gcc
CFLAGS= -Wall -g
LDFLAGS = -include
OBJFILES = add.o
LIB = add.h
TARGET = add
all: ${TARGET}
%.o: %.c
${CC} ${CFLAGS} -c -o $# $<
${TARGET}: ${OBJFILES}
${CC} ${CFLAGS} -o ${TARGET} ${OBJFILES}
clean:
rm -f $(OBJFILES) $(TARGET) *~
when I run
make add
I get the following error:
gcc -Wall -g -c -o add.o add.c
gcc -Wall -g -o add add.o
Undefined symbols for architecture x86_64:
"_b", referenced from:
_main in add.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [add] Error 1
here are snippets of my code
add.c
#include <stdio.h>
#include <stdlib.h>
#include "add.h"
int main(void) {
int a = 10, b=20;
add(a, b);
return 0;
}
add.h
#ifndef __ADD_H_
#define __ADD_H_
extern int a,b;
int add(a,b)
{
return a+b;
}
#endif // __ADD_H_
You are lacking a rule to actually build your object files. Right now you only have one to link them all together once they already exist. Try adding:
%.o: %.c
${CC} ${CFLAGS} -c -o $# $<
This tells make how to build object files out of source files.
You are misusing the extern keyword, losing track of your variables and making your code too complicated.
Let's try something very simple:
int main(void) {
int a = 10; b=20;
return 0;
}
This fails. The compiler complains about the statement b=20;, since it has never heard of this b. The semicolon that made this a separate statement was either a typo or a conceptual error caused by declaring extern int b elsewhere. There is no need for extern here, at least not yet.
This:
int main(void) {
int a=10, b=20;
return 0;
}
works.
Now for an add function.
int add(int a, int b)
{
return a+b;
}
int main(void) {
int a = 10, b=20;
add(a,b);
return 0;
}
Note that the a and b in add are not the same variables as the a and b in main. This is crucial; do not proceed until you understand it.
Now add a declaration of the add function:
int add(int a, int b); // <- declaration
int add(int a, int b) // <- definition
{
return a+b;
}
The declaration can be moved into a header file (add.h); the definition belongs in a source file (add.c).
Finally, I would advise you to add a line to the makefile:
add.o: add.h
Aren't you missing an #endif at the end of the last header file queue.h ?
This can be for sure an issue when compiling. Moreover, aren't you missing the main_application.h header file you are then including within the stack.h one for example?
Have a look at this: https://medium.com/#m.muizzsuddin_25037/error-ld-symbol-not-found-for-architecture-x86-64-a5e5b648ffc seems helpful here and point our attention to the header files again!..

call c function from a .c file with a main function

I have two .c files that both have mains. One of the files has a function that I would like to use in the other main. Is it possible to reference this other function without copying and pasting it into the other .c file?
No you don't need to copy and paste, suppose you have this
program-one.c
First program.
#include "common.h" /* This should be implemented */
int main(void)
{
do_program_one_stuff();
common_function();
return 0;
}
program-two.c
Second program.
#include "common.h" /* This should be implemented */
int main(void)
{
do_program_two_stuff();
common_function();
return 0;
}
You need a third .c file and a .h file, like this
common.c
Common Functions Implementation.
void common_function()
{
/* Do it here */
}
common.h
Common Functions Header.
void common_function();
You now can compile a single binary for each program consisting of two files, the program specific .c file and common.c.
The right way to do it is to have a Makefile and generate object code first, and then link the object files togeather, thus compiling each file only once.
Makefile
This is a GNU make Makefile using gcc as the compiler.
CC = gcc
CFLAGS = -Wall -Wextra -Werror -g3 -O0 # enable debug symbols and warnings
LDFLAGS = # linker flags here ...
OBJ = common.o program-one.o program-two.o
all:
$(CC) $(LDFLAGS) common.o program-one.o -o program-one
$(CC) $(LDFLAGS) common.o program-two.o -o program-two
%.o: %.c
$(CC) $(CFLAGS) -c $<
clean:
#rm -fv *.o program-one program-two
EDIT: in response to your comment I would suggest the following
#define main ignore /* Or whatever name you want */
#include "the-student-implementation.c"
#undef main
int main(void)
{
/* This would be your `main()' */
return 0;
}
The best solution is what iharob suggested, but if for some reason that isn't possible, you could surround the main() in the file containing the common function with #ifdef USE_MAIN, then only define the USE_MAIN identifier in the command to build that project. When you build the other project that doesn't have USE_MAIN defined, the preprocessor will cause the second main() to be skipped, so the compiler won't be confused.
But unless this is really needed, I highly recommend splitting this into three files: main1.c, main2.c, and common.c/common.h

multiple definition in g++?

The code is as follows:
global.h
#ifndef GLOBAL_H
#define GLOBAL_H
#include <stdio.h>
int test;
void test_fun(void);
#endif
global.c
#include "global.h"
void test_fun()
{
printf("%d\n", test);
}
main.c
#include "global.h"
int main(void)
{
test_fun();
test = 1;
printf("%d\n", test);
}
Makefile using gcc compiler
main: main.o global.o
gcc -o main main.o global.o
main.o: main.c global.h
gcc -c main.c
global.o: global.c global.h
gcc -c global.c
clean:
rm -f global.o main.o main
This works well.
However, when I change my code to C++, as follows:
global.h
#ifndef GLOBAL_H
#define GLOBAL_H
#include <iostream>
int test;
void test_fun(void);
#endif
global.cpp
#include "global.h"
void test_fun()
{
cout << test
}
main.cpp
#include "global.h"
int main(void)
{
test_fun();
test = 1;
std::cout << test;
}
Makefile using g++ compiler
main: main.o global.o
g++ -o main main.o global.o
main.o: main.cpp global.h
g++ main.cpp
global.o: global.cpp global.h
g++ global.cpp
clean:
rm -f global.o main.o main
The code above throws the output:
global.o:(.bss+0x0): multiple definition of `test'
What makes the different here?
You've int test; in a header which is included in 2 TUs, hence the error. Both the translation units main.c (or .cpp depending upon the compiler used) and global.c have global.h included, which leads to two definitions of the same variable in two object files, thus the linker error.
Pass test as an arguement to test_fun, thereby avoiding the usage of a global.
If you absolutely have to share the variable between the TUs, then remove int test; from global.h and in main.cpp do
int test;
and in global.cpp do
extern int test;
As an aside, since it's a global variable, test would be initialized to 0 and hence in main when you test_fun();, it should print 0 and then after setting it to 1, it'll print 1.
It's illegal in both C and C++ from a language standpoint, but as for why it works with a C compilers (like GCC) is because they implement a common extension, a legacy cruft.
... You are using a different programming language

Resources