Using Cuda Object Linking with Cmake - c++

Right now I am working on a project that uses the object linking capabilities of Cuda 5. Since the project is starting to get complex, I wanted to switch to using cmake to compile the code. However I can't seem to get object linking to work correctly for me.
I ended up creating a toy version of the project which gets the same kind of errors as the original project. The toy project consists of a main file (TextureMain.cu) that calls a kernel function to run on the GPU. In each GPU thread an instance of a user-defined class (TextureFunc) is referenced, where the class exists in a separate folder from the main file. The class consists of a TextureFunc.cu and TextureFunc.h file in that folder.
Here are the CMakeList.txt files I am using:
In the project directory (contains src directory):
project(TextureMain)
cmake_minimum_required(VERSION 2.8)
find_package(CUDA REQUIRED)
#-------------------------------------------------------------------------------
set(CUDA_NVCC_FLAGS "-arch=compute_20; -code=sm_20; -rdc=true; -lcudadevrt")
include_directories(src/TextureFunc)
#-------------------------------------------------------------------------------
add_subdirectory(src/TextureFunc)
add_subdirectory(src)
In the src directory (contains TextureMain.cu and TextureFunc directory):
cuda_add_executable(TextureMain TextureMain.cu)
target_link_libraries(TextureMain TextureFunc)
install(TARGETS TextureMain DESTINATION bin)
In TextureFunc directory (contains TextureFunc.h and TextureFunc.cu):
cuda_add_library(TextureFunc TextureFunc.cu )
target_link_libraries(TextureFunc)
When I try to compile this code using the above CMakeList.txt files, I get the following error.
Linking CXX executable TextureMain
CMakeFiles/TextureMain.dir/./TextureMain_generated_TextureMain.cu.o: In function `__sti____cudaRegisterAll_46_tmpxft_00004c15_00000000_6_TextureMain_cpp1_ii_texRef':
/tmp/tmpxft_00004c15_00000000-3_TextureMain.cudafe1.stub.c:2: undefined reference to `__cudaRegisterLinkedBinary_46_tmpxft_00004c15_00000000_6_TextureMain_cpp1_ii_texRef'
TextureFunc/libTextureFunc.a(TextureFunc_generated_TextureFunc.cu.o): In function `__sti____cudaRegisterAll_46_tmpxft_00004bd8_00000000_6_TextureFunc_cpp1_ii_421ca072':
/tmp/tmpxft_00004bd8_00000000-3_TextureFunc.cudafe1.stub.c:8: undefined reference to `__cudaRegisterLinkedBinary_46_tmpxft_00004bd8_00000000_6_TextureFunc_cpp1_ii_421ca072'
collect2: ld returned 1 exit status
make[2]: *** [src/TextureMain] Error 1
make[1]: *** [src/CMakeFiles/TextureMain.dir/all] Error 2
This is obviously a linking error, and it probably has to do with the way that I compile the code using cmake. I think the flags for nvcc are right since I was able to compile this project using a Makefile with the same flags. However, I'm not really sure what else I could be doing wrong. I did notice that the error message references some non-existent .cpp files, but I don't know what to do with that.
Any advice that can be given would be greatly appreciated. I'm using cmake version 2.8.8.

How about linking${CUDA_LIBRARIES} to whatever targets using `.cu files?
For example in your src directory you could try:
cuda_add_executable(TextureMain TextureMain.cu)
target_link_libraries(TextureMain TextureFunc ${CUDA_LIBRARIES})
install(TARGETS TextureMain DESTINATION bin)

Related

How to include files in a subdirectory of a CMake project, without using another CMakeLists.txt

I have a project added as a submodule to another project using CMake. The submodule is just two files (b.c, b.h) so the project structure is:
root/
| CMakeLists.txt
| main.cc
| a.cc
| a.h
| submodule/
| | b.c
| | b.h
I don't want to add another CMakeLists.txt to the submodule as it's just another git thing to maintain. The submodule will never grow beyond these two files so I just want something simple and CMake is overkill for some of my other projects, so I don't want it in the submodule's git repo.
If I try include_directories(submodule) and add submodule/b.c to the sources list of my add_executable block, I get undefined references to the functions inside b.c/h
Is there a quick and simple way to just add these extra files to the sources without getting undefined references? Or is there a better way of managing this tiny library?
I have
include_directories(${PROJECT_SOURCE_DIR}/submodule)
...
add_executable(${NAME}
submodule/b.c
main.cpp
server.cc
)
I have also tried adding
target_link_directories(${NAME} PUBLIC
${PROJECT_SOURCE_DIR}/submodule
)
The error is:
/usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/bin/ld: CMakeFiles/light.dir/
server.cc.obj: in function `tcpRecvCallback(void*, tcp_pcb*, pbuf*, signed char) [clon
e .part.0]':
server.cc:(.text._Z15tcpRecvCallbackPvP7tcp_pcbP4pbufa.part.0+0x62): undefined referen
ce to `http_req_parse(char*)'
collect2: error: ld returned 1 exit status
gmake[2]: *** [CMakeFiles/light.dir/build.make:3083: light.elf] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:1520: CMakeFiles/light.dir/all] Error 2
gmake: *** [Makefile:156: all] Error 2
where server.cc is in the project root, and http_req_parse is a function in b.c
main.cpp includes server.h which includes submodule/b.h
It may be relevant that I am building for a raspberry pi pico W.
new answer:
include_directories(${PROJECT_SOURCE_DIR}/submodule)
set(SOURCES submodule/b.c)
add_executable(${PROJECT_NAME} SOURCES)
old answer:
include_directories(${PROJECT_SOURCE_DIR}/submodule)
file(GLOB submodule_source submodule/*.c)
add_executable(${PROJECT_NAME} submodule_source)
It turns out that all the above answers were correct, I was forgot to use the language specific guards, since my library was in C, and my project was in C++.
IE, I didn't have
#ifdef _cplusplus
extern "C" {
#endif

Problem with CMake finding my header file

So I am trying to compile a small project that I am doing of a Sokoban Solver. For that, I have the following folder structure:
The CMakeLists file that I have generated is quite simple and contains the following lines of code:
project(Sokoban)
cmake_minimum_required(VERSION 3.16.3)
include_directories(include/)
add_executable(main src/main.cpp src/coord.cpp src/map.cpp src/node_data.cpp src/node.cpp src/search_methods.cpp)
As I understand it:
Executable needs to have the *.cpp files
The directory with the *.hpp files must be included somehow to the CMake so the compiler knows where to look for them.
When I try to compile, I obtain the following error:
[build] ../src/main.cpp:4:10: fatal error: include/search_methods.hpp: No such file or directory
[build] 4 | #include "include/search_methods.hpp"
[build] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] compilation terminated.
Does anyone know how or which other information would you need to solve this issue? I have been looking into similar problems, but did not solve the issue.
As #tkausl pointed out
Either drop the include folder from your #include statements or from your include path; can't have both.
Change #include "include/search_methods.hpp" to #include "search_methods.hpp" and it should work.
Also consider to use a more modern CMake approach using
target_include_directories(main
PUBLIC
include
)
and git rid of include_directories(include/)

Running multiple versions of OpenCV on the same computer

My computer is running Ubuntu-16.04-LTS and OpenCV-2.4.13 is already installed on it. However, I would like to use the functionalities of newer versions of OpenCV, such as OpenCV-3.2.0 without removing the older version.
So far I have downloaded OpenCV-3.2.0 and compiled and installed it. I am uing CMake to compile OpenCV, so I changed my CMakeLists.txt file to:
cmake_minimum_required (VERSION 3.2)
project(io)
find_package(OpenCV REQUIRED)
include_directories("/home/ubuntu/opencv-3.2.0/include") # directory of OpenCV-3.2.0
link_directories("/home/ubuntu/opencv-3.2.0/lib") # directory of OpenCV-3.2.0
add_executable(cv_io io.cpp)
target_link_libraries(cv_io ${OpenCV_LIBS})
Now, when I run this little piece of code,
#include <iostream>
#include "opencv2/core/version.hpp"
int main(int argc, char ** argv)
{
std::cout << "OpenCV version: "
<< CV_MAJOR_VERSION << "."
<< CV_MINOR_VERSION << "."
<< CV_SUBMINOR_VERSION
<< std::endl;
return 0;
}
I get
OpenCV version: 3.2.0
instead of
OpenCV version 2.4.13
So everything seems to be in order, except when I start running some actual OpenCV functions such as:
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
int main()
{
cv::Mat img = cv::imread("ferrari.jpg");
cv::Mat dst;
cv::Sobel(img, dst, CV_32F, 1, 1);
cv::imwrite("ferrari_sobel.png", dst);
cv::VideoCapture input(0);
}
I get all these undefined reference errors:
CMakeFiles/cv_io.dir/io.cpp.o: In function main':
io.cpp:(.text+0x40): undefined reference tocv::imread(cv::String
const&, int)' io.cpp:(.text+0xd4): undefined reference to
cv::imwrite(cv::String const&, cv::_InputArray const&,
std::vector<int, std::allocator<int> > const&)'
CMakeFiles/cv_io.dir/io.cpp.o: In functioncv::String::String(char
const*)':
io.cpp:(.text._ZN2cv6StringC2EPKc[_ZN2cv6StringC5EPKc]+0x40):
undefined reference to cv::String::allocate(unsigned long)'
CMakeFiles/cv_io.dir/io.cpp.o: In functioncv::String::~String()':
io.cpp:(.text._ZN2cv6StringD2Ev[_ZN2cv6StringD5Ev]+0x10): undefined
reference to cv::String::deallocate()' CMakeFiles/cv_io.dir/io.cpp.o:
In functioncv::String::operator=(cv::String const&)':
io.cpp:(.text.ZN2cv6StringaSERKS0[ZN2cv6StringaSERKS0]+0x2c):
undefined reference to `cv::String::deallocate()' collect2: error: ld
returned 1 exit status CMakeFiles/cv_io.dir/build.make:121: recipe for
target 'cv_io' failed make2: * [cv_io] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/cv_io.dir/all'
failed make1: * [CMakeFiles/cv_io.dir/all] Error 2 Makefile:83:
recipe for target 'all' failed make: *** [all] Error 2
Does anyone know how to solve this problem? I think the problem is that I'm still not linking all the libraries properly in the CMakeLists.txt. Also, I found a comment below this article mentioning something similar to what I'm experiencing, but I do not understand the page containing the solution it is referring to. I'm very new to OpenCV and CMake, so hopefully you can provide me instructions that are as explicit as possible. I've been stuck on this for forever, so any help is highly appreciated! Thank you very much!
I have a working CMakelists.txt for almost the same configuration as you describe except that I am running a dauntingly old Ubuntu 12.04 (its not my own computer).
I believe your problem comes from this line:
find_package(OpenCV REQUIRED)
Which gives you access to your distribution's OpenCV 2.4. Then you are linking against the manually installed 3.2.x version. So problems arise as soon as the interface of a function you use has changed between the two version. Your first piece of code run by chance I think.
Here is my CMakeList.txt:
cmake_minimum_required(VERSION 2.8)
project(demo)
find_package(OpenCV 3.2 REQUIRED PATHS "/path/to/OCV3.2/install/dir/")
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(main main.cpp)
target_link_libraries(main ${OpenCV_LIBS})
If you do not want to commit to your repository the hardcoded path to your install of OpenCV 3.2 you can refine this CMakeList.txt by changing the find_package line to:
if(DEFINED ENV{OPENCV_INSTALL_DIR})
find_package(OpenCV 3.2 REQUIRED PATHS $ENV{OPENCV_INSTALL_DIR})
else()
message("OPENCV_INSTALL_DIR not set, searching in default location(s)")
find_package(OpenCV 3.2 REQUIRED)
endif(DEFINED ENV{OPENCV_INSTALL_DIR})
Then you just have to define the variable OPENCV_INSTALL_DIR before running cmake. I do that by exporting it from my .bashrc
While you are setting up the include files to use the newly installed OpenCV headers, you are linking against the opencv on your system path. The version is just stored in the headers, which is why it's outputting the expected version but failing to link. Try setting the variable "OpenCV_DIR" to the location of the OpenCVConfig.cmake file you want to use before running the find module.
See the documentation for your version of cmake here. Note the two modes that find_package can be run in (Module or Config mode).
Unless you are linking to static libraries, you will still have problems running your library / application. To fix that, you'll need to add the libraries to your LD_LIBRARY_PATH.
Indeed, you're linking against system-default version of OpenCV.
Reconfigure your project by calling CMake with right path to file OpenCVConfig.cmake.
cmake /path/to/your/sources -DOpenCV_DIR=/home/ubuntu/opencv-3.2.0
Find file CMakeCache.txt in your build directory. It contains internal CMake variables, OpenCV paths are also there.
Also, it is incorrect to hardcode paths. Use include_directories(${OPENCV_INCLUDE_DIRS})
And quotation from OpenCVConfig.cmake
- OpenCV_LIB_DIR : The directory(es) where lib files are. Calling LINK_DIRECTORIES
with this path is NOT needed.

How to include Octave .la files?

I copied only the Octave lib and include folders from the original build folders and pasted into another (toolbox) folder. The toolbox folder has C++ code that has embedded Octave functions. The LD flags and C flags for compiling the code are-
LD flags- "-L/path/to/lib -loctave -L/path/to/lib -loctinterp -Wl,-rpath=/path/to/lib/folder"
I flags- "-I/usr/include/scilab -I/path/include/octave-4.0.3 -I/path/include/octave-4.0.3/octave/"
When I compile the C++ code, I get the error
libtool: link: warning: library `/home/fossee/Desktop/FSOIToolbox/thirdparty/linux/lib/x64/octave/4.0.3/liboctave.la' was moved.`
libtool: link: warning: library `/home/fossee/Desktop/FSOIToolbox/thirdparty/linux/lib/x64/octave/4.0.3/liboctinterp.la' was moved.
/usr/bin/ld: cannot find -liboctave.la
/usr/bin/ld: cannot find -liboctinterp.la
I understand the issue is due to copying the lib files.
How do I include .la files in the flags so that the error is resolved for my system?
I need this code to work on any system. How do I include the Octave lib and include folders in the toolbox thirdparty folder such that it works on any system. When I go through the liboctave.la file, the paths in the file refer to my system. I need to make this general.
The source code is available here- https://github.com/shamikam/FOSSEE_Scilab_Octave_Interface_Toolbox
The Octave files are in thirdparty folder.

undefined function during cmake linking local file

I'm trying to compile a small Qt example to an executable (with the test.cpp containg main) and later add support for compiling the non-test.cpp code to its own library. I was using qmake, but now I'm trying to use cmake following the example here. Unfortunately, I'm getting a linking error. Looks like the constructors, which I define in the cpp files that are compiling aren't being found at link time.
$ make
Linking CXX executable test
CMakeFiles/test.dir/attribute_editor.cpp.o: In function `AttributeEditor::AttributeEditor(QWidget*)':
attribute_editor.cpp:(.text+0x2a): undefined reference to `vtable for AttributeEditor'
CMakeFiles/test.dir/bindable.cpp.o: In function `Bindable::Bindable(QObject*)':
bindable.cpp:(.text+0x50): undefined reference to `vtable for Bindable'
CMakeFiles/test.dir/bindable.cpp.o: In function `AttributeObject::AttributeObject()':
bindable.cpp:(.text._ZN15AttributeObjectC2Ev[_ZN15AttributeObjectC5Ev]+0x24): undefined reference to `vtable for AttributeObject'
collect2: error: ld returned 1 exit status
make[2]: *** [test] Error 1
make[1]: *** [CMakeFiles/test.dir/all] Error 2
make: *** [all] Error 2
This is my cmake file...
cmake_minimum_required(VERSION 2.8)
# http://qt-project.org/quarterly/view/using_cmake_to_build_qt_projects
PROJECT(qattrs)
FIND_PACKAGE(Qt4 REQUIRED)
SET(QT_USE_QTSCRIPT TRUE)
SET(qattrs_SOURCES test.cpp attribute_editor.cpp bindable.cpp)
SET(qattrs_HEADERS bindable.h attribute_editor.h)
QT4_WRAP_CPP(qattrs_HEADERS_MOC ${qattrs_HEADERS})
INCLUDE(${QT_USE_FILE})
ADD_DEFINITIONS(${QT_DEFINITIONS})
ADD_EXECUTABLE(test ${qattrs_SOURCES} ${qattrs_HEADER_MOC})
TARGET_LINK_LIBRARIES(test ${QT_LIBRARIES})
I know very little about cmake, but I assume it's not including the .o files during linking.
The entire code (five or six files) is on github.
It cannot find a vtable for something - this means it is looking for the entries a type would put in it's vtable if it existed, because it is a linker. (It is not talking about a type lacking a vtable at runtime because that'd make no sense at all, I don't even like that sentence)
Somewhere you have a pure-virtual method you have never defined.
That code is REALLY hard to read and reading it I couldn't see any virtuals even in bindable.h, this means there's a pure virtual function in the parent class and you never implement it, that is your error.
Well more specifically you never implement 3 of them.
I'd feel bad for not saying: wxWidgets FTW :P
I found the answer on another question. It wasn't in the example Qt doc, but I just needed to set another environment variable.
set(CMAKE_AUTOMOC ON)
Why am I getting "undefined reference to vtable..." errors when linking this Qt 5.0 application?