CMake failed to link submodule, undefined reference [duplicate] - cmake

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 14 days ago.
I don't know why error appears, i use target_link_libraries
c:/dev-tools/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\submoduleTest1.dir/objects.a(main.cpp.obj):main.cpp:(.text.startup+0x2c): undefined reference to `void fmt_println2<char [5]>(char const (&) [5])'
collect2.exe: error: ld returned 1 exit status
mingw32-make[3]: *** [CMakeFiles\submoduleTest1.dir\build.make:101: submoduleTest1.exe] Error 1
mingw32-make[2]: *** [CMakeFiles\Makefile2:99: CMakeFiles/submoduleTest1.dir/all] Error 2
mingw32-make[1]: *** [CMakeFiles\Makefile2:106: CMakeFiles/submoduleTest1.dir/rule] Error 2
mingw32-make: *** [Makefile:123: submoduleTest1] Error 2
Main CMake:
cmake_minimum_required(VERSION 3.24)
project(submoduleTest1)
add_subdirectory(fmt_formatter)
set(CMAKE_CXX_STANDARD 17)
add_executable(submoduleTest1 main.cpp)
target_link_libraries(submoduleTest1 fmt_formatter)
fmt_formatter CMake:
find_package(fmt CONFIG REQUIRED)
add_library(fmt_formatter STATIC fmt_formatter.cpp fmt_formatter.h)
target_link_libraries(fmt_formatter fmt::fmt)
fmt_formatter.cpp
#include "fmt_formatter.h"
template<typename... Args>
void fmt_println(const fmt::text_style &ts, bool color, const Args &... args) {
fmt::print(color ? ts : fmt::text_style(), args...);
fmt::print("\n");
fflush(stdout);
}
template<typename... Args>
void fmt_println2(const Args &... args) {
fmt::print(fmt::text_style(), args...);
fmt::print("\n");
fflush(stdout);
}
fmt_formatter.h
#include "fmt/core.h"
#include "fmt/color.h"
template<typename... Args>
void fmt_println(const fmt::text_style &ts, bool color = true, const Args &... args);
template<typename... Args>
void fmt_println2(const Args &... args);
main.cpp
#include <iostream>
#include "fmt_formatter/fmt_formatter.h"
int main() {
std::cout << "Hello, World!" << std::endl;
fmt_println2("test");
return 0;
}
Any ideas how can i solve it? I tried many solutions but any of them worked.

Move your template function definitions to the header file. For a template to be instantiated at compile time, the definition needs to be visible at that point, which it isn't if you put it in a cpp file and not the hpp file that gets included where the instantiation is happening.
For more info, see Why can templates only be implemented in the header file?

Related

Linker error in boost serialization of custom archive

I've tried to implement an own archive type for boost serialization following official boost example to write archives.
#include <iostream>
#include <vector>
#include <boost/serialization/nvp.hpp>
#include "boost/serialization/vector.hpp"
#include <boost/archive/detail/common_oarchive.hpp>
#include <boost/archive/detail/register_archive.hpp>
#include <boost/archive/detail/archive_serializer_map.hpp>
class complete_oarchive : public boost::archive::detail::common_oarchive<complete_oarchive>
{
friend class boost::archive::save_access;
template<class T>
void save(T & t){
std::cout << "saved data\n";
}
public:
void save_binary(void *address, std::size_t count){
}
};
template class boost::archive::detail::archive_serializer_map<complete_oarchive>;
template class boost::archive::detail::common_oarchive<complete_oarchive>;
BOOST_SERIALIZATION_REGISTER_ARCHIVE(complete_oarchive)
int main(int argc, char *argv[])
{
std::vector<double> testVector = {1, 2, 3, 4};
complete_oarchive oa;
std::vector<double>* pVec = &testVector;
oa << BOOST_SERIALIZATION_NVP(testVector);
oa << BOOST_SERIALIZATION_NVP(pVec);
return 0;
}
Compiling this example with
g++ -c -g -std=c++11 -MMD -MP -MF "build/Debug/GNU-Linux/demo.o.d" -o build/Debug/GNU-Linux/demo.o demo.cpp
g++ -o dist/Debug/GNU-Linux/serializationdemo build/Debug/GNU-Linux/demo.o -lboost_serialization
leads to the following linker error
build/Debug/GNU-Linux/demo.o: In function `boost::archive::detail::pointer_oserializer<complete_oarchive, std::vector<double, std::allocator<double> > >::pointer_oserializer()':
/opt/tools/boost/boostRdk-1.66.0/include/boost/archive/detail/oserializer.hpp:222: undefined reference to `boost::archive::detail::archive_serializer_map<complete_oarchive>::insert(boost::archive::detail::basic_serializer const*)'
build/Debug/GNU-Linux/demo.o: In function `boost::archive::detail::pointer_oserializer<complete_oarchive, std::vector<double, std::allocator<double> > >::~pointer_oserializer()':
/opt/tools/boost/boostRdk-1.66.0/include/boost/archive/detail/oserializer.hpp:227: undefined reference to `boost::archive::detail::archive_serializer_map<complete_oarchive>::erase(boost::archive::detail::basic_serializer const*)'
collect2: error: ld returned 1 exit status
It seems that serializing a pointer in
oa << BOOST_SERIALIZATION_NVP(pVec);
leads to this error. After deletion of this line everything works fine and the result is as expected.
Does anybody have experience in writting own serialization archives?
A simimal Problem was solved here
https://groups.google.com/forum/#!topic/boost-list/CMoDosGZUo8
but I wasn't able to solve this by forward declarations.
I solved the issue by replacing
#include <boost/archive/detail/archive_serializer_map.hpp>
by
#include <boost/archive/impl/archive_serializer_map.ipp>

Process finished with exit code -1073741515 (0xC0000135) while using SDL2 in CLion [duplicate]

I've been trying to run OpenCV using CLion IDE under Windows. When I try to run this sample code for loading and displaying an image
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
if( argc != 2)
{
cout <<" Usage: display_image ImageToLoadAndDisplay" << endl;
return -1;
}
Mat image;
image = imread("earth.jpg", CV_LOAD_IMAGE_COLOR); // Read the file
if(! image.data ) // Check for invalid input
{
cout << "Could not open or find the image" << std::endl ;
return -1;
}
namedWindow( "Display window", WINDOW_AUTOSIZE );// Create a window for display.
imshow( "Display window", image ); // Show our image inside it.
waitKey(0); // Wait for a keystroke in the window
return 0;
}
I get the error statement:
Process finished with exit code -1073741515 (0xC0000135)
As for the content in my CMakeLists.txt, it looks like this:
cmake_minimum_required(VERSION 3.6)
project(test)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
# Where to find CMake modules and OpenCV
set(OpenCV_DIR "C:\\opencv\\mingw-build\\install")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(openCV main.cpp)
# add libs you need
set(OpenCV_LIBS opencv_core opencv_imgproc opencv_highgui opencv_imgcodecs)
# linking
target_link_libraries(openCV ${OpenCV_LIBS})
Thanks for helping me with this.
You need to add OpenCV binary path with DLLs to your PATH BEFORE CLion start.
I do it from script:
=== CLionWithMingwAndOpenCV.bat ==========================
#echo off
set PATH=C:\mingw-w64\x86_64-5.2.0-win32-seh-rt_v4-rev0\mingw64\bin;D:\opencv\release\bin;%PATH%
"C:\Program Files (x86)\JetBrains\CLion XXXX\bin\clion64.exe"
=== ==========================

getting error in running cmake std Tutorial step 2 example

I am totally new to cmake and its syntax .But fortunately I am able to run the cmake tutorial step 1 as per the introductions mention on below links :
https://cmake.org/cmake/help/latest/guide/tutorial/index.html
But I am totally stucked at step 2 project to run using cmake.
I have created the step 2 project and understand the syntax to link the library for doing square root of a number, But I did not understand how to run this as I am getting below error :
user#server:~/TER_CMAKE/Tutorial/step2_build$ cmake ../step2
CMake Error at CMakeLists.txt:19 (add_subdirectory):
The binary directory
/home/user/TER_CMAKE/Tutorial/step2/MathFunctions
is already used to build a source directory. It cannot be used to build
source directory
/home/user/TER_CMAKE/Tutorial/step2/MathFunctions
Specify a unique binary directory name.
-- Configuring incomplete, errors occurred!
The example is available at below location for step 2 under heading Adding a Library (Step 2)..
https://moodle.rrze.uni-erlangen.de/pluginfile.php/14829/mod_resource/content/5/CMakeTutorial.pdf
My intention is to run my example this way
step2_build$ cmake ../step2
step2_build$ cmake --build .
step2_build$ ./Tutorial 121
As I am not sure that is it good to ask this way on this platform ,But as I do not have any other guidance .I am doing this by my own .
Note: I do not wants to use any tool to run my step 2 example.I wants to run everything using command prompt and cmake command only .where I can understand the cmake .
Edit:
Adding my CMakeLists.txt =
cmake_minimum_required(VERSION 3.5)
#set the project name
project(Tutorial VERSION 1.0)
#specify the c++ std
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
option(USE_MYMATH "Use tutorial provided math implementation" ON)
#Configure a header file to pass the version number to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
#add the MathFunctions Library
add_subdirectory(MathFunctions)
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()
#add the executable
add_executable(Tutorial tutorial.cpp)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
${EXTRA_LIBS}
)
My Source tutorial.cpp file:
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <string>
#ifdef USE_MYMATH
#include "MathFunctions.h"
#endif
#include "TutorialConfig.h"
using namespace std;
int main(int argc, char* argv[])
{
if (argc < 2) {
cout << "Usage: " << argv[0] << " number" << endl;
return 1;
}
// convert input to double
const double inputValue = atof(argv[1]);
// calculate square root
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
cout << "The square root of " << inputValue << " is " << outputValue << endl;
return 0;
}
ToturialConfig.h.in file :
#define Tutorial_VERSION_MAJOR #Tutorial_VERSION_MAJOR#
#define Tutorial_VERSION_MINOR #Tutorial_VERSION_MINOR#
#cmakedefine USE_MYMATH
EDIT:
Step2 has a folder MathFuctions,Which has Cmake file mysqrt.cpp file
/TER_CMAKE/Tutorial/step2/MathFunctions/CMakeLists.txt
add_library(MathFunctions mysqrt.cpp)
/TER_CMAKE/Tutorial/step2/MathFunctions/mysqrt.cpp
#include <iostream>
// a hack square root calculation using simple operations
double mysqrt(double x)
{
if (x <= 0) {
return 0;
}
double result = x;
// do ten iterations
for (int i = 0; i < 10; ++i) {
if (result <= 0) {
result = 0.1;
}
double delta = x - (result * result);
result = result + 0.5 * delta / result;
std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
}
return result;
}
In case USE_MYMATH variable is set add_subdirectory(MathFunctions) is invoked twice. You need to decide and remove one of the occurrences on lines 16 and 19 in you CMakeLists.txt.
Two issues I can see:
You're adding the subdirectory "MathFunctions" twice when you configure the build with -DUSE_MYMATH=ON. This is why you are getting "CMake Error at CMakeLists.txt:19 (add_subdirectory):"
To fix, remove
#add the MathFunctions Library
add_subdirectory(MathFunctions)
and rely on
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()
In your CMakeLists.txt file, you are doing
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
${EXTRA_LIBS}
)
Instead of
${EXTRA_LIBS}
It should be
${EXTRA_INCLUDES}
in Discourse Cmake Org -- help with tutorial step 2
Josef Angstenberger
jtxa said
The files in Step3 are the expected result if you do everything from Step2.
Can you please compare your files against the ones from Step3 to see if there are any relevant differences?
Blockquote
Marshallb's solution will solve nahesh relkar's problem
Loading Step2/CMakeLists.txt and Step3/CMakeLists.txt into vimdiff helped me to fix mine

Problem using Lloyd optimization and Mesh_domain::create_labeled_image_mesh_domain

I'm using CGAL 4.13 (Linux Fedora 29) to generate 3D meshes from segmented anathomical images. I would like to use Lloyd optimization, but I got in a reproductible way a runtime error.
In order to illustrate my problem, I modified the example mesh_3D_image.cpp by adding a Lloyd optimization step, as shown hereafter. The program compiles with no error/warning message.
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Mesh_triangulation_3.h>
#include <CGAL/Mesh_complex_3_in_triangulation_3.h>
#include <CGAL/Mesh_criteria_3.h>
#include <CGAL/Labeled_mesh_domain_3.h>
#include <CGAL/make_mesh_3.h>
#include <CGAL/Image_3.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Labeled_mesh_domain_3<K> Mesh_domain;
typedef CGAL::Sequential_tag Concurrency_tag;
typedef CGAL::Mesh_triangulation_3<Mesh_domain,CGAL::Default,Concurrency_tag>::type Tr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
using namespace CGAL::parameters;
int main(int argc, char* argv[])
{
const char* fname = (argc>1)?argv[1]:"data/liver.inr.gz";
CGAL::Image_3 image;
if(!image.read(fname)){
std::cerr << "Error: Cannot read file " << fname << std::endl;
return EXIT_FAILURE;
}
Mesh_domain domain = Mesh_domain::create_labeled_image_mesh_domain(image);
Mesh_criteria criteria(facet_angle=30, facet_size=6, facet_distance=4,
cell_radius_edge_ratio=3, cell_size=8);
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria);
// !!! THE FOLLOWING LINE MAKES THE PROGRAM CRASH !!!
CGAL::lloyd_optimize_mesh_3(c3t3, domain, time_limit=30);
std::ofstream medit_file("out.mesh");
c3t3.output_to_medit(medit_file);
return 0;
}
I compile it by using the following CMakeLists.txt file:
# Created by the script cgal_create_CMakeLists
project( executables )
cmake_minimum_required(VERSION 2.8.11)
find_package( CGAL QUIET COMPONENTS )
# !!! I had to add manually the following line !!!
find_package(CGAL COMPONENTS ImageIO)
include( ${CGAL_USE_FILE} )
find_package( Boost REQUIRED )
add_executable( executables lloyd.cpp )
add_to_cached_list( CGAL_EXECUTABLE_TARGETS executables )
target_link_libraries(executables ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} )
No mesh is generated. I obtain the following message:
$ ./build/mesh_3D_image
terminate called after throwing an instance of 'CGAL::Precondition_exception'
what(): CGAL ERROR: precondition violation!
Expr: std::distance(first,last) >= 3
File: /usr/include/CGAL/Mesh_3/Lloyd_move.h
Line: 419
Aborted (core dumped)
Where my code is wrong, and how can I trigger optimizations for meshes generated by 3D images?
actually, when CGAL::make_mesh_3() is called like this :
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria);
it internally launches CGAL::perturb_mesh_3() and CGAL::exude_mesh_3(). The latest changes the weights of vertices in the Regular triangulation, and should always be called last (see the Warning in the documentation of CGAL::exude_mesh_3().
The only limitation on the order is that exuder should be called last. So you can either call
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria, lloyd(time_limit=30));
or
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria, no_exude());
CGAL::lloyd_optimize_mesh_3(c3t3, domain, time_limit = 30);
CGAL::exude_mesh_3(c3t3);
You removed the part:
if(!image.read(fname)){
std::cerr << "Error: Cannot read file " << fname << std::endl;
return EXIT_FAILURE;
}
from the example, which is what actually reads the image from the file.

Why do I need separable compilation?

I have the code shown below. As far as I understood, separable compilation must be turned on when
CUDA device code is separated into .h and .cu files
Use ObjectA's device code into Object's B device code
however, in my main function I am not having any of the cases above. Could you tell me why do I have to set separable compilation for this sample project?
BitHelper.h
#pragma once
#include <cuda_runtime.h>
#define COMPILE_TARGET __host__ __device__
class BitHelper
{
public:
COMPILE_TARGET BitHelper();
COMPILE_TARGET ~BitHelper();
COMPILE_TARGET static void clear(unsigned int& val0);
};
BitHelper.cu
#include "bithelper.h"
BitHelper::BitHelper()
{}
BitHelper::~BitHelper()
{}
void BitHelper::clear(unsigned int& val0)
{
val0 = 0x0000;
}
Consume_BitHelper.h
#pragma once
class Consume_BitHelper
{
public:
void apply();
private:
bool test_cpu();
bool test_gpu();
};
Consume_BitHelper.cu
#include "consume_bithelper.h"
#include <cuda_runtime.h>
#include <iostream>
#include "bithelper.h"
__global__
void myKernel()
{
unsigned int FLAG_VALUE = 0x2222;
printf("GPU before: %d\n", FLAG_VALUE);
BitHelper::clear(FLAG_VALUE);
printf("GPU after: %d\n", FLAG_VALUE);
}
void Consume_BitHelper::apply()
{
test_cpu();
test_gpu();
cudaDeviceSynchronize();
}
bool Consume_BitHelper::test_cpu()
{
std::cout << "TEST CPU" << std::endl;
unsigned int FLAG_VALUE = 0x1111;
std::cout << "CPU before: " << FLAG_VALUE << std::endl;
BitHelper::clear(FLAG_VALUE);
std::cout << "CPU after : " << FLAG_VALUE << std::endl;
return true;
}
bool Consume_BitHelper::test_gpu()
{
std::cout << "TEST GPU" << std::endl;
myKernel << <1, 1 >> > ();
return true;
}
main.cu
#include "consume_bithelper.h"
#include "bithelper.h"
#include <iostream>
int main(int argc, char** argv)
{
Consume_BitHelper cbh;
cbh.apply();
std::cout << "\nPress any key to continue...";
std::cin.get();
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(cuda_class LANGUAGES CXX CUDA)
#BitHelper needs separable compilation because we have separated declaration from definition
add_library(bithelper_lib STATIC bithelper.cu)
set_property(TARGET bithelper_lib PROPERTY CUDA_SEPARABLE_COMPILATION ON)
#Consume_BitHelper needs separable compilation because we call BitHelper's device code
#from Consume_BitHelper's kernel
add_library(consume_bithelper_lib STATIC consume_bithelper.cu)
set_property(TARGET consume_bithelper_lib PROPERTY CUDA_SEPARABLE_COMPILATION ON)
target_link_libraries(consume_bithelper_lib bithelper_lib)
#We only call CPU code so no need of separable compilation?
add_executable(${PROJECT_NAME} main.cu)
target_link_libraries(${PROJECT_NAME} bithelper_lib consume_bithelper_lib)
The errors I'm getting are these
EDIT
According to Robert Crovella's post Consume_BitHelper.cu uses BitHelper::clear defined in a separate compilation unit.
Does it mean I have to activate only separate compilation for BitHelper?
Since separate compilation has to do only with device code called from device code.
Why am I getting the mentioned errors when separate compilation is NOT on for cuda_class? (which is the executable created from CMake and is not calling any device code)
Separable compilation has to do with how the compiler handles function calls. In exchange for a little bit of overhead, you get the ability to make true function calls and thus access code from other "compilation units" (i.e. .cu source files).
As GPU programmers are obsessed with performance (particularly the extra registers that get used when separable compilation is enabled) Nvidia made it an option instead of default.
You should only need separable compilation for .cu files that access functions/globals defined in other .cu files.