I am developing a C program that calls 2 functions, func1() and func2().
Here is the code
void func1(void){/*...*/}
void func2(void){/*...*/}
int main(){
func1();
func2();
return 0;
}
Is there a way that when I compile the program using make and a certain flag, it just executes func1() and if I compile using another flag then it only executes func2()?
How to make such a makefile? Can anyone provide me with a makefile that does this job?
You can use the -D flag of the compiler:
cc -o demo demo.c -Dfunc=func1
then
#include <stdio.h>
void func1(void) { puts("1"); }
void func2(void) { puts("2"); }
int main(void)
{
func();
return 0;
}
Output:
1
You can also pass the function as an argument to make:
CC = gcc
CFLAGS = -std=c11 -Wpedantic -Wall
action: demo.c
$(CC) $(CFLAGS) demo.c -o demo -Dfunc=$(argument)
clean:
rm -f demo
call make using:
make action argument=func1
or
make action argument=func2
But if you really want to do that:
int main(){
func1();
func2();
call both functions inside main, you should use another approach (although this solution seems quite sticky to me):
#include <stdio.h>
void func0(void) { /* do nothing */ }
void func1(void) { puts("1"); }
void func2(void) { puts("2"); }
#ifdef delete_func1
#define func1 func0
#endif
#ifdef delete_func2
#define func2 func0
#endif
int main(void)
{
func1();
func2();
return 0;
}
compile using:
cc -o demo demo.c -Ddelete_func1
or
cc -o demo demo.c -Ddelete_func2
then the Makefile should look like:
CC = gcc
CFLAGS = -std=c11 -Wpedantic -Wall
func1: demo.c
$(CC) $(CFLAGS) demo.c -o demo -Ddelete_func2
func2: demo.c
$(CC) $(CFLAGS) demo.c -o demo -Ddelete_func1
clean:
rm -f demo
call it using:
make func1
or
make func2
you can delete both functions using -D twice:
cc -o demo demo.c -Ddelete_func1 -Ddelete_func2
Related
In my project, I have two libraries and one program.
Lib1.c and Lib1.h are two files of first library(Lib1.so).
Lib2.c and Lib2.h are two files of second library(Lib2.so).
prog.c is the main file of program(prog).
The program(prog) is linked only to the second library(Lib2.so) and the second library(Lib2.so) is linked to the first library(Lib1.so).
In Lib1.c, I have a declaration of global variable (int var = 0;) and in Lib1.h, I have a declaration (extern int var;).
In Lib2.h, I have a declaration (extern int var;) in order to use var variable in main program.
In main() function, I include the Lib2.h in prog.c file and I have a declaration (var = 5;)
Lib1.c :
#include <stdio.h>
#include "Lib1.h"
int var = 0;
int funct(void)
{
printf("hello world \n");
return 0;
}
Lib1.h :
extern int var;
int funct(void);
Lib2.c :
#include <stdio.h>
#include "Lib2.h"
int funct2(void)
{
printf("Library 2 \n");
funct();
return 0;
}
Lib2.h :
#include "Lib1.h"
extern int var;
int funct2(void);
prog.c :
#include <stdio.h>
#include "Lib2.h"
int main()
{
var = 5;
printf("===>var=%d\n", var);
funct2();
return 1;
}
Commands :
gcc -c -Wall -Werror -fpic Lib1.c
gcc -shared -o Lib1.so Lib1.o
gcc -c -Wall -Werror -fpic Lib2.c
gcc -shared -o Lib2.so Lib2.o -ldl /home/test/Lib1.so
gcc prog.c -o prog -ldl /home/test/Lib2.so
When I try to compile the program(prog.c), I get an error in the link step as below.
/usr/bin/ld: /tmp/ccKaq16a.o: undefined reference to symbol 'var'
/home/test/Lib1.so: error adding symbols: DSO missing from command line
Is there a way to use var variable in the main function when its defined in the first library?
You link your program against Lib2 but not Lib1. You need to add that as well. You also don't need to explicitly link Lib1 when you create Lib2
gcc -c -Wall -Werror -fpic Lib1.c
gcc -shared -o Lib1.so Lib1.o
gcc -c -Wall -Werror -fpic Lib2.c
gcc -shared -o Lib2.so Lib2.o
gcc prog.c -o prog /home/test/Lib2.so /home/test/Lib1.so
There is a simple example to describe my problem:
I have 3 files, main, level1.so and level2.so. (My OS is solaris11.3, gcc version is 3.4.3)
In main, it calls execute() from level1.so. And the execute() calls run() from level2.so. And the run() calls fcloseall() which is redefined in level2.so.
fcloseall() is redefined to do nothing (it will close all opened fds include stdout, stdin and stderr originally).
Now I want print something around execute() in main, but only the message before execute() is printed.
The codes are shown below:
The level2.so is compiled from level2.c and level2depend.c.
level2.c:
#include <stdio.h>
int run()
{
fcloseall();
return 0;
}
level2depend.c:
#include <stdio.h>
int fcloseall() //redefine the std c function fcloseall
{
printf("in redefined fcloseall\n");
return 0;
}
The level1.so is compiled from level1.c.
level1.c
#include <dlfcn.h>
int execute()
{
int (*sofunc)(void);
void * lib_handle = NULL;
char *errorInfo;
lib_handle = dlopen("./liblevel2.so",RTLD_LAZY);
if(!lib_handle)
{
return 0;
}
sofunc = (int(*)(void))dlsym(lib_handle,"run");
errorInfo = dlerror();
if (errorInfo != NULL){
dlclose(lib_handle);
return 0;
}
int ret = sofunc();
dlclose(lib_handle);
return 0;
}
The main is compiled from main.c.
main.c
#include <dlfcn.h>
#include <stdio.h>
int main()
{
int (*sofunc)(void);
void * lib_handle = NULL;
char *errorInfo;
lib_handle = dlopen("./liblevel1.so",RTLD_LAZY);
if(!lib_handle)
{
return 0;
}
sofunc = (int(*)(void))dlsym(lib_handle,"execute");
errorInfo = dlerror();
if (errorInfo != NULL){
dlclose(lib_handle);
return 0;
}
printf("before\n");
int ret = sofunc();
printf("after\n");
dlclose(lib_handle);
return 0;
}
The makefile is:
all:
gcc level2depend.c -o level2depend.o -c -g -fPIC
gcc level2.c -o level2.o -c -g -fPIC
gcc -shared -g level2.o level2depend.o -o liblevel2.so -fPIC
gcc level1.c -o level1.o -c -g -fPIC
gcc level1.o -o liblevel1.so -shared -fPIC
gcc main.c -o main -g -ldl
clean:
rm level2depend.o level1.o liblevel1.so level2.o liblevel2.so main
I execute main and the result is:
root#solaris#./main
before
If I change the makefile as gcc main.c -o main -g -ldl -llevel2, the result is:
root#solaris#./main
before
in redefined fcloseall
after
And this is what I want.
I want know why this happen. Thanks!
You can use the wrap function provided by ld.
gcc -Wl,-wrap,fcloseall ....
and in your source code,
int __wrap_fcloseall(void)
{...}
I've been confused as to why this specific error is coming up.
The function being called looks the same so I don't think it is a type/case-sensitive error. I've included my makefile, the header in question, and the code snippet of the C file using the header + calling the function.
If anything else would be relevant I could supply it.
Thanks to anyone that helps!
game_state.h
#ifndef GAME_STATE_H
#define GAME_STATE_H
typedef struct Game_Condition_struct {
bool vertical_win;
bool down_diag_win;
bool up_diag_win;
char* player_char;
} GAME;
void Game_Over(BOARD* board);
void Win_Check(BOARD* board, GAME* game_condition);
#endif
moves.c snippet
#include "game_state.h"
... // other code above
else {
Make_Move(board, user_move, player_char);
Print_Board(board);
// IF-ELSE to change the player turn
if (*player_char == 'X') {
*player_char = 'O';
}
else {
*player_char = 'X';
}
Game_Over(board);
}
game_state.c
void Game_Over(BOARD* board) {
GAME game_condition;
Win_Check(board, &game_condition);
}
makefile
connectn.out: board.o main.o read_args.o moves.o game_state.o
gcc -g -Wall -o connectn.out board.o main.o read_args.o moves.o
main.o: board.h read_args.h moves.h game_state.h main.c
gcc -g -Wall -c -o main.o main.c
board.o: board.h board.c
gcc -g -Wall -c -o board.o board.c
read_args.o: read_args.h read_args.c
gcc -g -Wall -c -o read_args.o read_args.c
moves.o: moves.h board.h game_state.h moves.c
gcc -g -Wall -c -o moves.o moves.c
game_state.o: game_state.h board.h game_state.c
gcc -g -Wall -c -o game_state.o game_state.c
clean:
rm *.o *.out
The code works as I expect if I don't include the Game_Over(board) call, so I'm confused as to why it's not defined.
BOARD is a struct I made, similar to GAME.
You didn't link game_state.o into connectn.out. Add game_state.o to the end of the 2nd line of Makefile.
This is probably going to be embarrassing:
I am using library prelaoding in other projects, but I cannot get this minimal example to work:
weakref.h:
void f_weak() __attribute__((weak));
weakref.c:
#include <stdio.h>
#include "weakref.h"
void f_weak(){
printf("f_weak()\n");
fflush(stdout);
}
test_weakref.c:
#include <stdio.h>
#include "weakref.h"
int main(void)
{
if (f_weak) {
printf("main: f_weak()\n");
}
else {
printf("main: ---\n");
}
fflush(stdout);
return 0;
}
Here is what I do:
$ gcc weakref.c -shared -fPIC -o libweakref.so
$ nm libweakref.so | grep f_weak
0000000000000708 W f_weak
$ gcc test_weakref.c -o test_weakref
$ ./test_weakref
main: ---
$ LD_PRELOAD=./libweakref.so ./test_weakref
main: ---
The expected output of the last command is
main: f_weak()
What am I missing?
As far as I know, external functions are resolved only when you call them. So, your test if (f_weak) will always fail. If you do it the following way, you can see that it works:
weakref.c:
#include <stdio.h>
#include "weakref.h"
void f_weak(){
printf("original\n");
fflush(stdout);
}
weak2.c:
#include <stdio.h>
#include "weakref.h"
void f_weak(){
printf("overridden\n");
fflush(stdout);
}
test_weakref.c:
#include <stdio.h>
#include "weakref.h"
int main(void)
{
f_weak();
fflush(stdout);
return 0;
}
and then:
tmp> gcc weakref.c -shared -fPIC -o libweakref.so
tmp> gcc weak2.c -shared -fPIC -o libweak2.so
tmp> gcc -o test_weakref test_weakref.c ./libweakref.so
tmp> ./test_weakref
original
tmp> LD_PRELOAD=./libweak2.so !.
LD_PRELOAD=./libweak2.so ./test_weakref
overridden
I found the solution in an old Makefile: the program has also to be compiled with the -fPIC flag.
$ gcc weakref.c -shared -fPIC -o libweakref.so
$ nm libweakref.so | grep f_weak
0000000000000708 W f_weak
$ gcc test_weakref.c -o test_weakref -fPIC
$ ./test_weakref
main: ---
$ LD_PRELOAD=./libweakref.so ./test_weakref
main: f_weak()
I'm studying a tutorial how to link shared objects in C
Here's my make file
test: glenn.c libhala.so
gcc glenn.c -L. -o test
libhala.so: hala.o
gcc -shared hala.o -o libhala.so
hala.o: hala.c hala.h
gcc -c -Wall -Werror -fpic hala.c
clean:
rm *.o
rm *.so
rm test
hala.h
#ifndef HALA
#define HALA
extern void test(char*);
#endif
hala.c
#include "hala.h"
#include <stdio.h>
extern void test(char* s)
{
printf("%s", s);
}
glenn.c
#include <stdio.h>
#include "hala.h"
int main()
{
test("Hello There!");
return 0;
}
This stocks me up. Help me please..
You should add -lhaha when you link glenn.c.
gcc glenn.c -L. -lhala -o test
Add -lhala while compiling glenn.c, so update makefile as
test: glenn.c libhala.so
gcc glenn.c -L. -lhala -o test