How to compile C code with C headers and CUDA code? - c

I have a main code wich uses some libraries and I been compiling it like this:
gcc importedCFile1.c importedCFile2.c mainCode.c -O3 -lm -Wall -o maincode -lrt
Now I have added CUDA code in mainCode and changed its extension to .cu... So, how can I compile the whole thing?
I tried:
nvcc importedCFile1.c importedCFile2.c mainCode.cu -o maincode
but I got a lot of "undefined reference" to my functions in the imported C files.
To include my C files I am using:
extern "C" {
#include "importedCFile1.h"
#include "importedCFile2.h"
}
And ´importedCFile1.c´ is using some functions and variables declared in ´importedCFile2.c´ and ´mainCode.cu´. Like this:
extern int **se; // Variables from mainCode
extern int *n;
extern int numNodes;
extern int *getVector(int n); // Function from mainCode
extern int iRand(int high); // Function from importedCFile2
This functions are the cause of the undefined references. What should I do?
Also, how do I add the flags I need for the C code, such as -lrt, O3, lm and Wall??
EDIT: You can find a reduced example of the problem here:
https://github.com/mvnarvaezt/cuda/tree/master/minimalExample
If you compile the mainCode.c and importedCFile.c with gcc it works fine. If you compile mainCode.cu and importedCFile.c with nvcc you will get an undefined reference to anExample() (the function in importedCFile.c).
And you comment the header importing importedCFile.c and the call to anExampled() function it would work find.

Your problem is that the C code in importedFile.c is trying to call back C++ functions in mainCode.cu.
In order to be callable from C, C++ functions must have C linkage. Declare getVector() as
extern "C" int *getVector(int n) {
in mainCode.cu, and your example will compile fine.

Related

Is it possible to declare a weak function by passing an argument to gcc?

We can declare weak function by using __attribute__((weak)) in C code files. I wonder if there exists a way to declare this during compile time from gcc and not write anything in the code files?
For e.g.
File: foo.h
int foo();
File: foo.c
#include<stdio.h>
int foo(){
printf("foo called from file\n");
return 1;
}
File: main.c
#include<stdio.h>
#include"foo.h"
int foo(){
printf("foo called from main");
return 1;
}
int main(){
foo();
return 0;
}
Is it possible to compile above code and export foo as weak from command line?
E.g. gcc --weak=foo.c:foo foo.c main.c
./a.out produces foo called from main.
I know that writing__attribute__((weak)) above foo() declaration in foo.c will call foo() in main.
The blog:
blog.microjoe.org/2017/unit-tests-c-cmocka-coverage-cmake.html
says that it is possible to do so....
There are two ways of declaring a weak symbol:
By passing an argument to GCC, telling it to export the symbol of this function as a weak symbol.
By putting a attribute((weak)) annotation before the function implementation.
I would say no, there is no such option.
This sounds a little bit like an XY-problem, perhaps you should state more clearly what problem you are trying to solve, instead of which solution you want to make work.
As an aside, your example would not work, since you're providing two definitions and not saying which one should be considered weak. It would have to be
# Remember this doesn't really work!
$ gcc --weak=foo.c:foo foo.c main.c
or something, i.e. you need to indicate in which file the weak definition resides.

Compiling C programs with static files

I am trying to compile a c program with a static library and its not working .
This is the error :
undefined reference to `calculatearea'
collect2.exe: error: ld returned 1 exit status .
The static files were made with the gcc / g++ compilers .
This is the main code :
#include <stdio.h>
#include <stdint.h>
int calculatearea(int a , int b);
int main()
{
int c = calculatearea(2,4);
printf("%d",c);
getchar();
return 0;
}
edit :
: screenshot of compiler error
From the above code we can see that you have declared the function int calculatearea(int a , int b); but have not written any definition for the same. and you are calling this function in the main. compiler is not finding the definition for the function calculatearea and giving error.
To solve this:
1) Write the definition for function calculatearea in the same file.
2) Make use of extern specifier with this function declaration and make sure that definition is present with the link library at the time of compilation.
3) As mentioned in the picture if the area.o have the definition of function calculatearea, then compile as below, this will generate a.out in linux:
gcc filename.c area.o

How can I LD_PRELOAD my own compiled library?

I was wondering how this works, creating a library and preloading it so a program can use it instead of the one in the include statement.
here is what I am doing and is not working so far .
//shared.cpp
int rand(){
return 33;
}
//prograndom.cpp
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(){
srand(time(NULL));
int i = 10;
while(i--) printf("%d\n", rand()%100);
return 0;
}
Then in the terminal:
$ gcc -shared -fPIC shared.cpp -o libshared.so
$ gcc prograndom.cpp -o prograndom
$ export LD_PRELOAD=/home/bob/desarrollo/libshared.so
and finally
$ LD_PRELOAD=/home/bob/desarrollo/libshared.so ./prograndom
which doesnt print 33, just random numbers...
Your programs are C programs, but the cpp file extension implies C++, and GCC will interpret it that way.
That's an issue because it means that your function rand (in shared.cpp) will be compiled as a C++ function, with its name mangled to include its type-signature. However, in main you #include <stdlib.h>, which has the effect of declaring:
extern "C" int rand();
and that is the rand that the linker will look for. So your PRELOAD will have no effect.
If you change the name of the file from shared.cpp to shared.c, then it will work as expected.
Other alternatives, of dubious value, are:
Declare rand to be extern "C" in your shared.cpp file. You can then compile it as C++.
Force compilation as C by using the GCC option -x c.

SystemVerilog: How to connect C function using DPI call in VCS simulator?

I have the following files:
C file with functions:
// funcs.c
#include <stdio.h>
void something() {
printf("something\n");
sayHello();
}
System verilog file:
// hello_world.v
module kuku;
export "DPI-C" function sayHello;
import "DPI-C" function void something();
initial something();
function int sayHello ();
$display("hello world");
sayHello = 1;
endfunction
endmodule
How can I compile it and make this work so when I call something() from SV, it will call the C function, and when I call sayHello() from C, it will call the SV function?
Answering myself:
When SV code is compiled using VCS, it is first translated into C code.
When exporting a function out of SV, it generates a C header file vc_hdrs.h that should be included by the C file.
So a change I made in the C file is to add the line:
#include "vc_hdrs.h"
Then, I just added the C functions file to the VCS compilation command:
> vcs -sverilog hello_world.v funcs.c
It works!
The output I get is:
something
hello world
.
A solution that works with all simulator that follow IEEE Std 1800-2012 is to have #include "svdpi.h" and prefix the extern keyword in front of all methods being exported to C. funcs.c should look like:
#include <stdio.h>
#include "svdpi.h"
extern int sayHello();
void something() {
printf("something\n");
sayHello();
}
Examples from IEEE Std 1800-2012
§ H.10.2 Example 2—Simple packed array application
§ H.10.3 Example 3—Application with complex mix of types
I see you've named SystemVerilog file as .v extension. Not sure if that works or not. But lets say if its hello_world.sv
Your command line should look like this (for Questa Simulator),
qverilog hello_world.sv funcs.c
"qverilog " is to compile and run SystemVerilog files.
That's all. No need to add extra header files
Hi I have provided a nice example under this post
https://stackoverflow.com/a/46441794/5842403
Synopsys VCS
1) You compile the C code using flags and introducing the defines you want to add.
In our case our C code need the define PYTHON_PATH
#GCC in two steps for shared object
gcc -g -D 'PYTHON_PATH="'$PYTHON_DIR'"' -fPIC -Wall -I${VCS_HOME}/include -I/usr/include/python2.6/ -lpython2.6 -c ${PROJECTDIR}/verification/PVE/keycontrol/tb/keycontrol_C_code_wrapper.c
gcc -fPIC -shared -o keycontrol_C_code_wrapper.so keycontrol_C_code_wrapper.o
2) You do the VCS elaboration linking the python lybrary with -LDFLAGS '-lpython2.6'
vcs -timescale=1ps/1ps -ntb_opts uvm -lca -kdb -full64 keycontrol_tb_top -debug_access+all+reverse -LDFLAGS '-lpython2.6'
3) You run the created simulation file. You call simv including -sv_lib keycontrol_C_code_wrapper to import the C shared object.
#RUN C CODE
./simv -gui -ucli +DVE +UVM_NO_RELNOTES -l simv.log +UVM_TESTNAME=keycontrol_basic_test -do ../../verification/PVE/keycontrol/tools/keycontrol_ucli_init.synopsys -sv_lib keycontrol_C_code_wrapper

Compilation Error for extern variable initialized in other file

I have these two different program where I want to access the static variable declared in program1 from program2.
Program1. (
/* file a.c */)
#include<stdio.h>
static int a = 100; /* global static variable not visible outside this file.*/
int *b = &a; /* global int pointer, pointing to global static*/
Program2
#include<stdio.h>
/* file b.c */
extern int *b; /* only declaration, b is defined in other file.*/
int main()
{
printf("%d\n",*b); /* dereferencing b will give the value of variable a in file a.c */
return 0;
}
While I compile program1 , gcc a.c , no compilation error, but while I compile program2 ( gcc b.c) I am getting compilation error .
test_b.c:(.text+0x7): undefined reference to `b'
collect2: error: ld returned 1 exit status
Why there is compile error ? Here is the link of program static
Thanks in advance.
EDIT 1:
My intention to use static variable from other program. I thought every .c program must have main() function and only .h program have declaration , I am wrong at that point. So I remove main() function from a.c program and instead of compiling two different program separately , now I compile only once using gcc a.c b.c as per suggestion of Filip. Now it's working fine. Thanks all of you.
You have to link against a.c while compiling b.c:
gcc a.c b.c
You can't expect the linker to magically find the C file where b is defined. extern means it is defined elsewhere - you have to say where. By compiling and linking with a.c, the linker can now find a declaration for b.
Of course, you can't have 2 main() functions.
Well, your code already said it. b.cpp only has a declaration, not a definition, of the symbol in question.
Since these are clearly meant to be source files from two separate projects, I would suggest moving your definition to its own .cpp file which may then be shared between the two projects.
$ gcc a.c myIntPointerIsHere.c
$ gcc b.c myIntPointerIsHere.c
However, there are clearer ways to share code between two different projects.
The both modules contain the definition of main. It seems that the compiler did not include the first module in your project. Otherwise I think it would issue an error that main was redefined.

Resources