Creating CUDA C library using CMake - c

I've the following code structure for my library
|-build
|-example
|-CMakeLists.txt
|-main_VecAdd.cu
|-include
|-VonNeumann
|-utils.h
|-VecAdd.h
|-CMakeLists.txt
|-src
|-CMakeLists.txt
|-utils.c
|-VecAdd.c
|-CMakeLists.txt
CMakeLists.txt for folders example, include, src and main_folder are as follows (in order respectively):
project(VonNeumann LANGUAGES CUDA C)
add_executable(main_VecAdd main_VecAdd.cu)
set_target_properties(VonNeumann PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
target_link_libraries(main_VecAdd
PRIVATE
VonNeumann)
project(VonNeumann LANGUAGES CUDA C)
project(VonNeumann LANGUAGES CUDA C)
add_library(VonNeumann utils.c VecAdd.c)
target_include_directories(VonNeumann
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../include)
cmake_minimum_required(VERSION 3.16.3)
project(VonNeumann LANGUAGES CUDA C)
# Adding subdirectories
add_subdirectory(include)
add_subdirectory(src)
# Giving an option to include code in examples or not
option(BUILD_EXAMPLES "Whether or not to build examples" ON)
if (BUILD_EXAMPLES)
message(STATUS "Building examples...")
add_subdirectory(example)
endif()
When I run cmake .. from build directory, everything works well however I get the following error when I run make command:
[ 16%] Linking C static library libVonNeumann.a
[ 50%] Built target VonNeumann
[ 66%] Linking CUDA device code CMakeFiles/main_VecAdd.dir/cmake_device_link.o
[ 83%] Linking CUDA executable main_VecAdd
/usr/bin/ld: CMakeFiles/main_VecAdd.dir/main_VecAdd.cu.o: in function `main':
tmpxft_000058c9_00000000-6_main_VecAdd.cudafe1.cpp:(.text+0x111): undefined reference to `RandVecFP32(float*, int)'
/usr/bin/ld: tmpxft_000058c9_00000000-6_main_VecAdd.cudafe1.cpp:(.text+0x122): undefined reference to `RandVecFP32(float*, int)'
/usr/bin/ld: tmpxft_000058c9_00000000-6_main_VecAdd.cudafe1.cpp:(.text+0x133): undefined reference to `ZeroVecFP32(float*, int)'
/usr/bin/ld: tmpxft_000058c9_00000000-6_main_VecAdd.cudafe1.cpp:(.text+0x144): undefined reference to `PrintVec(float*, int)'
/usr/bin/ld: tmpxft_000058c9_00000000-6_main_VecAdd.cudafe1.cpp:(.text+0x155): undefined reference to `PrintVec(float*, int)'
/usr/bin/ld: tmpxft_000058c9_00000000-6_main_VecAdd.cudafe1.cpp:(.text+0x166): undefined reference to `PrintVec(float*, int)'
/usr/bin/ld: tmpxft_000058c9_00000000-6_main_VecAdd.cudafe1.cpp:(.text+0x17d): undefined reference to `VecAddFP32(float*, float*, float*, int)'
/usr/bin/ld: tmpxft_000058c9_00000000-6_main_VecAdd.cudafe1.cpp:(.text+0x19a): undefined reference to `PrintVec(float*, int)'
collect2: error: ld returned 1 exit status
make[2]: *** [example/CMakeFiles/main_VecAdd.dir/build.make:105: example/main_VecAdd] Error 1
make[1]: *** [CMakeFiles/Makefile2:163: example/CMakeFiles/main_VecAdd.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
I know that the error is because of failed linking but I can't figure out how to resolve this.
P.S. I've tested this same code without CUDA part and it works just fine.

As #talonmies suggests, the problem is likely you trying to use functions implemented in your .cu file, in your .c file: CUDA uses "C++ linkage", that the function symbols appear in a certain way in the compiled object file, which differs from how function symbols appear when compiled using C.
To allow your C code to be used by C++ code, you must adapt the declarations to be read differently in C++ (or CUDA), in utils.h and VecAdd.h like so:
#ifdef __cplusplus
extern "C"
{
#endif
void PrintVec(float*, int);
// ... or whatever you're defining
#ifdef __cplusplus
}
#endif
See also:
https://isocpp.org/wiki/faq/mixing-c-and-cpp
How to use C code in C++
By the way - you're using too many CMakeLists.txt files. You don't need one of these for every folder. In fact, for a project as small as yours, a top-level CMakeLists.txt and perhaps another one for the examples would have sufficed. Subdirectory-specific CMakeLists.txt files are appropriate where the contents of the subdirectory is worked on relatively independently, and the top-level CMakeLists.txt does not need to be aware of the dependencies and other configuration work towards producing the targets that do get used outside.

Related

How do i resolve this error I am trying to compile some functions and create a static library but I am getting this error

/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.0: in function '_start' :
(.text+0x24): undefined reference to 'main'
Collect2: error: ld returned to 1 exit status
If you're using CMake check if you're really compiling a library not an executable. This error can occur if you have
add_executable(${PROJECT_NAME} ${SOURCES})
instead of
add_library(${PROJECT_NAME} ${SOURCES})
The latter should compile a library; a library doesn't have the main().

CMake undefined and duplicate symbols when building executable. Fortran77 C mix

I have a fortran 90 program which calls Sundials CVODE via the FCVODE inteface. Sundials is written in C, but they provide two interfaces to fortran. One interface is for fortran 77 applications, and one uses modern fortran methods (iso_c_binding).
My code uses the fortran 77 interface (just the way it ended up, I know iso_c_binding would be better)
Here is my project (dev branch): https://github.com/Nicholaswogan/PhotochemPy/tree/dev
My goal is to write a CMakesLists.txt which compiles all the fortran and C in one swoop. I have done this, but it only works with some compiler combinations and opperating systems. For example, on MacOS with clang 12.0.5 and gfortran 11.1.0, everything works great. But, on MacOS, when I switch to gcc 11.1.0 (instead of clang), I get an error when linking my executable:
[ 98%] Building Fortran object CMakeFiles/photo.run.dir/src/main.f90.o
[100%] Linking Fortran executable photo.run
duplicate symbol '_F2C_CVODE_linsol' in:
lib/libsundials_fcvode.a(fsunlinsol_band.c.o)
lib/libsundials_fcvode.a(fcvnulllinsol.c.o)
duplicate symbol '_F2C_CVODE_matrix' in:
lib/libsundials_fcvode.a(fsunmatrix_band.c.o)
lib/libsundials_fcvode.a(fcvnullmatrix.c.o)
ld: 2 duplicate symbols for architecture x86_64
collect2: error: ld returned 1 exit status
make[2]: *** [photo.run] Error 1
make[1]: *** [CMakeFiles/photo.run.dir/all] Error 2
make: *** [all] Error 2
I have looked at libsundials_fcvode.a and libsundials_fcvode.a, and they do contain these duplicate symbols. However, when I compile with clang + gfortran, these libraries also have these duplicate symbols, but, these compilers don't seem bothered by it in this case.
Also, on Ubuntu 20.04 with gcc 9 and gfortran 9, I get an undefined symbol:
[ 98%] Building Fortran object CMakeFiles/photo.run.dir/src/main.f90.o
[100%] Linking Fortran executable photo.run
/usr/bin/ld: lib/libsundials_fcvode.a(fcvband.c.o): in function `FCVBandJac':
fcvband.c:(.text+0x141): undefined reference to `fcvbjac_'
/usr/bin/ld: lib/libsundials_fcvode.a(fcvode.c.o): in function `FCVf':
fcvode.c:(.text+0x50): undefined reference to `fcvfun_'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/photo.run.dir/build.make:91: photo.run] Error 1
make[1]: *** [CMakeFiles/Makefile2:711: CMakeFiles/photo.run.dir/all] Error 2
make: *** [Makefile:130: all] Error 2
This missing symbol is very puzzling because It is not missing! I've used nm to to interogate the library I'm linking to, and the symbols are there:
...
cvode_funcs.f90.o:
0000000000000250 T fcvbjac_
0000000000000000 T fcvfun_
...
My question: What common items are missing from a CMakesList.txt, that cause these sorts of problems? Or is this sort of problem bound to happen when mixing fortran and C without iso_c_binding?
EDIT:
I ended up spending the time switching from the fortran 77 interface to the modern fortran C interface, which uses iso_c_binding. Every compiler I have tried works.

Sqlite amalgamation C file doesn't compile on Raspbian

I am using a Raspberry Pi to run a C program that interacts with a can interface, and stores values in a database as part of a project.
I started C one month ago, and I am still a bit lost with everything.
Description of my workspace and problem :
I have my test file test virtual.c that includes a homemade file handler_code.c that includes the sqlite3.c amalgamation file(via #include "sqlite3.c").
Then I have a CMakeLists.txt that was provided to me :
if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
set( STANDALONE TRUE )
cmake_minimum_required(VERSION 3.13)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
find_package(CARLOS REQUIRED)
else()
include_directories(${CMAKE_SOURCE_DIR}/core/include)
include_directories(${CMAKE_BINARY_DIR}/include)
include_directories(${CMAKE_SOURCE_DIR}/gui/include)
endif()
add_definitions(-DRESOURCES_DIR="${CMAKE_CURRENT_SOURCE_DIR}/resources")
add_executable(test_example "test virtual.c")
target_link_libraries(test_example carlos)
set_target_properties(
test_example
PROPERTIES
C_STANDARD 99
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/examples_bin
)
It imports all libraries I need. All the files are in the same directory.
I then go in the subdirectory build and run cmake .. which succeeds and then make. This is what happens :
pi#raspberrypi:~/Desktop/examples/build $ make
[ 50%] Building C object CMakeFiles/test_example.dir/test_virtual.c.o
In file included from /home/pi/Desktop/examples/handler_code.c:5,
from /home/pi/Desktop/examples/test virtual.c:8:
/home/pi/Desktop/examples/sqlite3.c:34058:42: error: ‘mremap’ undeclared here (not in a function); did you mean ‘munmap’?
{ "mremap", (sqlite3_syscall_ptr)mremap, 0 },
^~~~~~
munmap
/home/pi/Desktop/examples/sqlite3.c: In function ‘unixRemapfile’:
/home/pi/Desktop/examples/sqlite3.c:38625:42: error: ‘MREMAP_MAYMOVE’ undeclared (first use in this function)
pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
^~~~~~~~~~~~~~
/home/pi/Desktop/examples/sqlite3.c:38625:42: note: each undeclared identifier is reported only once for each function it appears in
/home/pi/Desktop/examples/sqlite3.c:38625:42: warning: passing argument 4 of ‘(void * (*)(void *, size_t, size_t, int, ...))aSyscall[24].pCurrent’ makes integer from pointer without a cast [-Wint-conversion]
/home/pi/Desktop/examples/sqlite3.c:38625:42: note: expected ‘int’ but argument is of type ‘struct unix_syscall *’
make[2]: *** [CMakeFiles/test_example.dir/build.make:63: CMakeFiles/test_example.dir/test_virtual.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:73: CMakeFiles/test_example.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
I tried only compiling sqlite3.c with gcc and I got this :
pi#raspberrypi:~/Desktop/examples $ gcc sqlite3.c
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabihf/8/../../../arm-linux-gnueabihf/crt1.o: in function `_start':
(.text+0x34): undefined reference to `main'
/usr/bin/ld: /tmp/cc6Quw7S.o: in function `pthreadMutexAlloc':
sqlite3.c:(.text+0x5098): undefined reference to `pthread_mutexattr_init'
/usr/bin/ld: sqlite3.c:(.text+0x50a8): undefined reference to `pthread_mutexattr_settype'
/usr/bin/ld: sqlite3.c:(.text+0x50c8): undefined reference to `pthread_mutexattr_destroy'
/usr/bin/ld: /tmp/cc6Quw7S.o: in function `pthreadMutexTry':
sqlite3.c:(.text+0x51b8): undefined reference to `pthread_mutex_trylock'
/usr/bin/ld: /tmp/cc6Quw7S.o: in function `sqlite3ThreadCreate':
sqlite3.c:(.text+0x9fcc): undefined reference to `pthread_create'
/usr/bin/ld: /tmp/cc6Quw7S.o: in function `sqlite3ThreadJoin':
sqlite3.c:(.text+0xa084): undefined reference to `pthread_join'
/usr/bin/ld: /tmp/cc6Quw7S.o: in function `unixDlOpen':
sqlite3.c:(.text+0x148c0): undefined reference to `dlopen'
/usr/bin/ld: /tmp/cc6Quw7S.o: in function `unixDlError':
sqlite3.c:(.text+0x148f4): undefined reference to `dlerror'
/usr/bin/ld: /tmp/cc6Quw7S.o: in function `unixDlSym':
sqlite3.c:(.text+0x14970): undefined reference to `dlsym'
/usr/bin/ld: /tmp/cc6Quw7S.o: in function `unixDlClose':
sqlite3.c:(.text+0x1498c): undefined reference to `dlclose'
collect2: error: ld returned 1 exit status
I also did some tests on my windows computer. The file named config.c includes the amalgamation just like handler_code.c did.
PS C:\Users\p107770\Desktop\projects\hmi-rapid-prototyping\C> gcc sqlite3.c
C:/MATLAB/V_R2016b/TDM-GCC-64/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-crt0_c.o): In function `main':
C:/crossdev/src/mingw-w64-v3-git/mingw-w64-crt/crt/crt0_c.c:18: undefined reference to `WinMain'
collect2.exe: error: ld returned 1 exit status
PS C:\Users\p107770\Desktop\projects\hmi-rapid-prototyping\C> gcc config.c
PS C:\Users\p107770\Desktop\projects\hmi-rapid-prototyping\C>
So here, it successfully compiles the file that includes the amalgamation file (which is what I'd want on my raspberry pi, even though it's not the same file), but it does not compile the amalgamation file alone (which I don't understand).
Ideas I found while searching
Using sqlite as a library/package in CMake file
Something looking like this. But looking at my CMake file, I realized that my sqlite amalgamation file was not a "package" in the same way CARLOS and Threads are (I installed CARLOS with .deb files provided to me). So my question here is how to transform the amalgamtion file into a package ?
Compiling sqlite so it would be imported globally
I remember reading something about this. If I recall correctly, I can compile the sqlite amalgamation file into a .dll and make it available in any C file with the #include <sqlite3.c> line instead of #include "sqlite3.c", but I don't know if it would work here because I think this was working when compiling with gcc and not with make.
Thank you in advance for any help you could bring, I can add bits of code if needed.

Is there an easier way to compile this project

Under Linux(Ubuntu) I'm writing a CMakeLists.txt with CLion to compile my project which is a little game written in C. How do I fix these errors?
Here's a link to the entire source code.
Any help will be greatly appreciated
I have tried to rewrite my .h files. It was primarily an issue about linking SDL and SDL_images.
I have tried to compile the main with gcc main.c -o main -lSDL -lSDL_image.
Here's the CMakeLists.txt
cmake_minimum_required(VERSION 3.7)
project(SOKOBAN)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -lmingw32")
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")
include_directories(${PROJECT_SOURCE_DIR}/include)
link_directories(${PROJECT_SOURCE_DIR}/lib)
find_package(SDL REQUIRED)
find_package(SDL)
find_package(SDL_image)
set(SOURCE_FILES main.c jeu.c jeu.h editeur.c editeur.h
fichiers.c fichiers.h Constantes.h hsokoban.h)
add_executable(SOKOBANR ${SOURCE_FILES})
target_link_libraries(SOKOBANR SDL_image SDL)
The error is:
[ 20%] Linking C executable SOKOBANR
CMakeFiles/SOKOBANR.dir/jeu.c.o: In function `jouer':
/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:12: multiple definition of `jouer'
CMakeFiles/SOKOBANR.dir/main.c.o:/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:12: first defined here
/usr/bin/ld: skipping incompatible /home/mahamad/github/SOKOBAN/SOKOBAN/lib/libSDL.a when searching for -lSDL
CMakeFiles/SOKOBANR.dir/main.c.o: In function `jouer':
/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:72: undefined reference to `deplacerJoueur'
/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:76: undefined reference to `deplacerJoueur'
/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:80: undefined reference to `deplacerJoueur'
/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:84: undefined reference to `deplacerJoueur'
CMakeFiles/SOKOBANR.dir/jeu.c.o: In function `jouer':
/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:72: undefined reference to `deplacerJoueur'
CMakeFiles/SOKOBANR.dir/jeu.c.o:/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:76: more undefined references to `deplacerJoueur' follow
CMakeFiles/SOKOBANR.dir/fichiers.c.o: In function `sauvegarderNiveau':
/home/mahamad/github/SOKOBAN/SOKOBAN/fichiers.c:67: undefined reference to `fprint'
collect2: error: ld returned 1 exit status
CMakeFiles/SOKOBANR.dir/build.make:128: recipe for target 'SOKOBANR' failed
make[3]: *** [SOKOBANR] Error 1
CMakeFiles/Makefile2:72: recipe for target 'CMakeFiles/SOKOBANR.dir/all' failed
make[2]: *** [CMakeFiles/SOKOBANR.dir/all] Error 2
CMakeFiles/Makefile2:84: recipe for target 'CMakeFiles/SOKOBANR.dir/rule' failed
make[1]: *** [CMakeFiles/SOKOBANR.dir/rule] Error 2
Makefile:118: recipe for target 'SOKOBANR' failed
make: *** [SOKOBANR] Error 2```
If you get such errors you need to look into each of them:
CMakeFiles/SOKOBANR.dir/jeu.c.o: In function `jouer':
/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:12: multiple definition of `jouer'
CMakeFiles/SOKOBANR.dir/main.c.o:/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:12: first defined here
The linker thinks that you have (at least) two definitions of jouer. Since both referenced locations are the same I assume that you 1. include "jeu.c" instead of "jeu.h" in your "main.c", and 2. link both "main.o" and "jeu.o".
/usr/bin/ld: skipping incompatible /home/mahamad/github/SOKOBAN/SOKOBAN/lib/libSDL.a when searching for -lSDL
The library "libSDL.a" you provide is not compatible to the target system. Your target system seems to be Linux.
For which system is the library?
Did you compile it yourself or did you download it?
CMakeFiles/SOKOBANR.dir/main.c.o: In function `jouer':
/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:72: undefined reference to `deplacerJoueur'
/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:76: undefined reference to `deplacerJoueur'
/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:80: undefined reference to `deplacerJoueur'
/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:84: undefined reference to `deplacerJoueur'
CMakeFiles/SOKOBANR.dir/jeu.c.o: In function `jouer':
/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:72: undefined reference to `deplacerJoueur'
CMakeFiles/SOKOBANR.dir/jeu.c.o:/home/mahamad/github/SOKOBAN/SOKOBAN/jeu.c:76: more undefined references to `deplacerJoueur' follow
There are references (calls) of deplacerJoueur but you don't define it. Or the source file with the definition (implementation) is not added to the list of modules.
CMakeFiles/SOKOBANR.dir/fichiers.c.o: In function `sauvegarderNiveau':
/home/mahamad/github/SOKOBAN/SOKOBAN/fichiers.c:67: undefined reference to `fprint'
This is clearly a typo. You mean fprintf() with a trailing 'f' for sure.
collect2: error: ld returned 1 exit status
Because of all the errors the linker is not successful, and it tells you.
CMakeFiles/SOKOBANR.dir/build.make:128: recipe for target 'SOKOBANR' failed
Because of all the errors the build is not successful, and it tells you.

Installing AODV protocol on Raspberry pi (https://github.com/erimatnor/aodv-uu)

I'm trying to install AODV protocol on Raspberry pi. After completing git clone from "https://github.com/erimatnor/aodv-uu" when I tried to do "make" and I am getting below error. Expecting your suggestion. Thank you!
make
gcc -Wall -O3 -g -DDEBUG -DCONFIG_GATEWAY -DDEBUG -o aodvd main.o list.o debug.o timer_queue.o aodv_socket.o aodv_hello.o aodv_neighbor.o aodv_timeout.o routing_table.o seek_list.o aodv_rreq.o aodv_rrep.o aodv_rerr.o nl.o locality.o
aodv_neighbor.o: In function neighbor_add':
/home/pi/aodv-uu/aodv_neighbor.c:68: undefined reference tohello_update_timeout'
aodv_timeout.o: In function route_discovery_timeout':
/home/pi/aodv-uu/aodv_timeout.c:98: undefined reference tort_table_update_timeout'
aodv_rreq.o: In function rreq_route_discovery':
/home/pi/aodv-uu/aodv_rreq.c:460: undefined reference tort_table_update_timeout'
aodv_rreq.o: In function rreq_local_repair':
/home/pi/aodv-uu/aodv_rreq.c:521: undefined reference tort_table_update_timeout'
aodv_rrep.o: In function rrep_forward':
/home/pi/aodv-uu/aodv_rrep.c:231: undefined reference tort_table_update_timeout'
nl.o: In function nl_kaodv_callback':
/home/pi/aodv-uu/nl.c:282: undefined reference tort_table_update_timeout'
collect2: error: ld returned 1 exit status
Makefile:112: recipe for target 'aodvd' failed
make: *** [aodvd] Error 1
The code available from sourceforge is the same code that is on github. If you download the archive, you'll see that the latest modification date of any file there is 2010. Given the age of this code, I wouldn't be surprised to find that things simply don't work anymore.
However, here's a quick workaround for your problem. The root cause appears to be that the problem functions, like rt_table_update_timeout, are declared as inline, but that information seems to get lost somewhere in the build process such that other object files are trying to reference these as non-inline functions.
You can avoid this by opening defs.h, looking for this line:
#define NS_INLINE inline
And replace it with:
#define NS_INLINE
This will allow aodvd to compile correctly (make aodvd). On my system, the kernel module will subsequently fail to compile:
cc1: fatal error: /lib/modules/4.13.15-100.fc25.x86_64/build/include/linux/modversions.h: No such file or directory
As far as I can tell, the modversions.h file is no longer produced by modern Linux kernels.

Resources