I have an existing project in Rust / C and I want to migrate some low level hashing stuff to CUDA, but I can't get it to finish compiling.
I believe the compile part is working, as the error only appears in the linker if I call the function from the .cu file
build.rs
fn main() {
let mut cfg = cc::Build::new();
cfg.cuda(true);
cfg.include("project/include")
.include("project/src")
.file("project/src/HelloWorld.cu")
.file("project/src/Validate.c")
//more C files...
.out_dir(dst.join("lib"))
.flag("-O2")
.compile("libproject.a");
println!("cargo:root={}", dst.display());
println!("cargo:include={}", dst.join("include").display());
println!(
"cargo:rerun-if-changed={}",
env::current_dir().unwrap().to_string_lossy()
);
println!("cargo:rerun-if-env-changed=PC_CC");
if let Ok(cuda_path) = env::var("CUDA_HOME") {
println!("cargo:rustc-link-search=native={}/lib64", cuda_path);
} else {
println!("cargo:rustc-link-search=native=/usr/local/cuda/lib64");
}
println!("cargo:rustc-link-lib=dylib=cudart");
}
HelloWorld.h
#ifndef CUDA_HELLO_WORLD_H
#define CUDA_HELLO_WORLD_H
#include <stdio.h>
#include "cuda_runtime.h"
void cudaTest();
#endif
HelloWorld.cu
#include "HelloWorld.h"
__global__ void mykernel(void){
}
void cudaTest(){
mykernel<<<1,1>>>();
printf("Hello World!\n");
}
error:
error: linking with `cc` failed: exit status: 1
[...] really big compile command
= note: /usr/bin/ld: project/target/debug/deps/libproject-673a2f9d363593e3.rlib(File.o): in function `call_to_cuda_file`:
project/project/src/File.c:168: undefined reference to `cudaTest`
collect2: error: ld returned 1 exit status
There was a linking problem as CUDA uses C++ linkage
The solution was to modify HelloWorld.h to
#ifndef CUDA_HELLO_WORLD_H
#define CUDA_HELLO_WORLD_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
#include "cuda_runtime.h"
void cudaTest();
#ifdef __cplusplus
}
#endif
#endif
There was no need to modify anything on HelloWorld.cu
Related
I'm testing an antidebug solution with ptrace method; and i compile the program by using ndk21e cross-compile.
The problem is that it compiles successfully with gcc, but fails with ndk cross-compile.
ndk cross-compile compiles all other programs without problems
#include <stdlib.h>
#include <stdio.h>
#include<sys/ptrace.h>
#include <dlfcn.h>
#include <string.h>
int main(int argc, char **argv) {
void *handle;
long (*go)(enum __ptrace_request request, pid_t pid);
// get a handle to the library that contains 'ptrace'
handle = dlopen ("/lib/x86_64-linux-gnu/libc.so.6", RTLD_LAZY);
// reference to the dynamically-resolved function 'ptrace'
go = dlsym(handle, "ptrace");
if (go(PTRACE_TRACEME, 0) < 0) {
puts("being traced");
exit(1);
}
puts("not being traced");
// cleanup
dlclose(handle);
return 0;
}
And it shows the error like the picture as follow:
gcc compileresult and cross-compile error result
How can i solve this problem. Thanks.
my vm system is ubuntu 16.04, and i have download the kernel header files,i have write the code,but don't know how to edit gcc code or Makefile
#include <linux/netdevice.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(){
struct net_device *dev = dev_base;
struct in_device *mydevice;
struct in_ifaddr *myifaddr;
while( dev != NULL ){
printf("dev name: %s\n", dev->name);
mydevice = dev->ip_ptr;
myifaddr = mydevice->ifa_list;
while(myifaddr != NULL){
printf("ip: %s\n", inet_ntoa((struct in_addr)(myifaddr->ifa_local)));
myifaddr = myifaddr->ifa_next;
}
dev = dev->next;
}
return 0;
}
if i use gcc test.c it will come out some error like this
yq#ubuntu:~/test$ gcc test.c
In file included from /usr/include/linux/netdevice.h:28:0,
from test.c:1:
/usr/include/linux/if.h:234:19: error: field ‘ifru_addr’ has incomplete type
struct sockaddr ifru_addr;
^
......
test.c: In function ‘main’:
test.c:8:27: error: ‘dev_base’ undeclared (first use in this function)
struct net_device *dev = dev_base;
I have found a strange behavior (probably an issue) while trying to compile a simple application with MS VC 15.3.1 (after applying VC 2017 Upgrade 3):
#include <iostream>
#include <algorithm>
#include <string>
// compiles if commenting out the line below
#include <vector>
#include <list>
class A
{
std::string s;
public:
A(const std::string& str) : s(str)
{
}
A(A&& other)
{
// compiles if changing std::swap<std::string>() to std::swap()
std::swap<std::string>(s, other.s);
}
};
int main(int argc, char *argv[])
{
return 0;
}
the compiler emits error :
1>d:\program files (x86)\microsoft visual studio\2017\enterprise\vc\tools\msvc\14.11.25503\include\vector(2131):
error C2039: '_Alloc': is not a member of 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>'
This code compiles without any issues with VC 15.2, VS2015 and VS2013 toolsets.
I've searched for the error LNK2005 "already defined in .obj" but can't find content related to the specific problem I am facing. Hope someone can help me on this...
I've a header foo.h
// foo.h
#ifndef FOO_H
#define FOO_H
void foo() {
print("foo\n");
}
#endif
and main file... main.cpp
// main.cpp
#include <thread>
#include "foo.h"
int main() {
std::thread t(foo);
t.join();
return 0;
}
Now, it compile without any errors and gives the gives output to the console...
foo
But if I create another file foo.cpp and just include the header foo.h and do nothing else...
// foo.cpp
#include "foo.h"
...I get linker error LNK2005 "void __cdecl foo(void)" (?foo##YAXXZ) already defined in main.obj
Don't know what's going wrong here.?!!
You must place only the prototype of the foo() function in the header file, and the implementation once in the .cpp.
Thus, foo.h must contain:
#pragma once
void foo();
And foo.cpp:
#include "foo.h"
void foo() {
printf("Whatever");
}
I'm going to implement my custom module in which information for CPU is printed using print_cpu_info(). In order to call print_cpu_info(), I have included the needed header file, but it doesn't work. Here is my module.
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/alternative.h>
#include <asm/bugs.h>
#include <asm/processor.h>
#include <asm/mtrr.h>
#include <asm/cacheflush.h>
extern struct cpuinfo_x86 boot_cpu_data;
int cpuinfox86_init(void)
{
print_cpu_info(&boot_cpu_data);
return 0;
}
void cpuinfox86_exit(void)
{
printk("good bye cpu\n");
}
module_init(cpuinfox86_init);
module_exit(cpuinfox86_exit);
MODULE_LICENSE("GPL");
After compiling this module, I get
make -C /lib/modules/3.2.28-2009720166/build SUBDIRS=/home/tracking/1031_oslab modules
make[1]: Entering directory `/usr/src/linux-3.2.28'
CC [M] /home/tracking/1031_oslab/module.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: "print_cpu_info" [/home/tracking/1031_oslab/module.ko] undefined!
CC /home/tracking/1031_oslab/module.mod.o
LD [M] /home/tracking/1031_oslab/module.ko
make[1]: Leaving directory `/usr/src/linux-3.2.28'
any idea?
"print_cpu_info" is not exported symbol, so it can not be used by modules. However, you can use "kallsyms_lookup_name", which is exported, to get the address of "print_cpu_info" and execute the function call using a function pointer.
static void* find_sym( const char *sym ) { // find address kernel symbol sym
static unsigned long faddr = 0; // static !!!
// ----------- nested functions are a GCC extension ---------
int symb_fn( void* data, const char* sym, struct module* mod, unsigned long addr ) {
if( 0 == strcmp( (char*)data, sym ) ) {
faddr = addr;
return 1;
}
else return 0;
};
// --------------------------------------------------------
kallsyms_on_each_symbol( symb_fn, (void*)sym );
return (void*)faddr;
}
static void (*cpuInfo)(struct cpuinfo_x86 *);
How to use it:
unsigned int cpu = 0;
struct cpuinfo_x86 *c;
cpuInfo = find_sym("print_cpu_info");
for_each_online_cpu(cpu)
{
c = &cpu_data(cpu);
cpuInfo(c);
}