Here is a piece of code that I'm trying to run and understand. but it has a awkward error in the
setDefault function.
cmake_minimum_required(VERSION 3.19)
project(OpenCL_HPP)
set(CMAKE_CXX_STANDARD 14)
# find OpenCL
find_package(OpenCL REQUIRED)
find_package(Threads REQUIRED)
include_directories(SYSTEM ${OpenCL_INCLUDE_DIRS})
link_directories(${OpenCL_LIBRARIES})
add_executable(OpenCL_HPP main.cpp)
target_link_libraries(${PROJECT_NAME} ${OpenCL_LIBRARIES} Threads::Threads)
Code:
#define CL_HPP_ENABLE_EXCEPTIONS
#define CL_HPP_MINIMUM_OPENCL_VERSION 120
#define CL_HPP_TARGET_OPENCL_VERSION 200
#include <vector>
#include <memory>
#include <algorithm>
#include <iostream>
#ifdef __APPLE__
#include <OpenCL/cl.hpp>
#else
#include <CL/cl2.hpp>
#endif
constexpr int numElements = 32;
int main(void)
{
// Filter for a 2.0 platform and set it as the default
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
cl::Platform plat;
for (auto &p : platforms) {
std::string platver = p.getInfo<CL_PLATFORM_VERSION>();
if (platver.find("OpenCL 2.") != std::string::npos) {
plat = p;
}
}
if (plat() == 0) {
std::cout << "No OpenCL 2.0 platform found.";
return -1;
}
/*
The setDefault chrashes in the call_once function, with error code -1
*/
cl::Platform newP = cl::Platform::setDefault(platforms[0]);
//cl::Platform newP = plat;
if (newP != plat) {
std::cout << "Error setting default platform.";
return -1;
}
return 0;
}
ERROR:
/home/BLA/CLionProjects/OpenCL_HPP/cmake-build-debug/OpenCL_HPP
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
The error comes int the call_once function, as far as I understand this should be part of the pThread libs but all of that interferes with the stdlib. Correct me if I'm wrong.
The machine where I run this is Ubuntu 16.04, the Opencl comes from Intel, and I do not have any other OpenCL driver installed (for the GPU for example). This code is the main bind example in the OpenCL-HPP doxygen.
I'm wondering, is there a way to rectify this. Is OpenCL-HPP using Pthread lib or STD lib, for linking purposes?
After some debuging and reading about OpenCL-HPP I found the problem.
The main issue is that the OpenCL-HPP uses pthreads and if they are not included / linked one gets problems like described above.
Articles that helped:
cmake fails to configure with a pthread error
Cmake error undefined reference to `pthread_create'
Cmake gives me an error (pthread_create not found) while building BornAgain
The main issue is that the Call_once method crashes without any really understandable cause. The project will build though.
One thing that derails everything is the CMake it is not really helping with understanding the linking procedure.
Output from the CMake setup:
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for CL_VERSION_2_0
-- Looking for CL_VERSION_2_0 - found
-- Found OpenCL: /usr/lib/x86_64-linux-gnu/libOpenCL.so (found version "2.0")
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
The main point here is that pthreads are not really found, and that was not clear to me.
find_package(Threads REQUIRED)
target_link_libraries(${PROJECT_NAME} ${OpenCL_LIBRARIES} Threads::Threads)
The code is not really doing anything since the pthreads are not linked correctly. Or it is not recognized that the pthreads should be linked.
Once I added the following code to my CMake, the magic happens and the crashes go magically away.
if( CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -Werror=return-type")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
endif()
Here is where the next problem for me arises. Why does all of this does not give some more verbose warnings or error when linking?
The OpenCL-HPP documentation does not really express the need for linking to pthreads. As a consequence then one has a quite painful experience in searching for the problem.
Why does CMake have to have such a setup for the CMAKE_CXX_FLAGS and is not able to link int the target_link_libraries command?
Related
I've been struggling with this for longer than I care to admit and would really appreciate some help.
I'm trying to do a project which involves building a linker and scheduler, and thought if I could use some of the functionality that's already been build into LLVM that would be great. I'm using LLVM 10. To get started I did some reading and tried to build this example. Because I plan on embedding LLVM into another project, used this as a reference for 'how to build' the example (see below). I figured the dependencies are just the components from the example CMakeLists.txt.
If I'm not mistaken, I'm getting a linker error and that the component list is the problem, but I'm struggling to resolve it. The way it seems LLVM does linking is by mapping a component name to an library file, but since I don't know which missing library might be causing it I'm stuck. Also, I don't know what llvm_libs is, but adding it to the component list seemed to resolve some of the linker errors I was getting originally. Also also, changing the order of the component list will give me different amounts of errors, which absolutely confounds me.
CMakeLists.txt
cmake_minimum_required(VERSION 3.13.4)
project(HowToUseJIT)
find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
# Set your project compile flags.
# E.g. if using the C++ header files
# you will need to enable C++11 support
# for your compiler.
message(STATUS "INCLUDE ${LLVM_INCLUDE_DIRS}")
include_directories(${LLVM_INCLUDE_DIRS})
message(STATUS "DEFINITIONS ${LLVM_DEFINITIONS}\n${LLVM_DEFINITIONS_LIST}")
separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
add_definitions(${LLVM_DEFINITIONS_LIST})
# Now build our tools
add_executable(HowToUseJIT HowToUseJIT.cpp)
# Find the libraries that correspond to the LLVM components
# that we wish to use
llvm_map_components_to_libnames(llvm_libs support core interpreter nativecodegen executionengine)
# Link against LLVM libraries
message(STATUS "LIBS ${llvm_libs}")
target_link_libraries(HowToUseJIT ${llvm_libs})
Then from a subdir I run
$ cmake ../
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jeremy_arsenault/Documents/random/llvm_examples/HowToUseJIT/build
$ cmake --build .
[ 50%] Building CXX object CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o
[100%] Linking CXX executable HowToUseJIT
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `main':
HowToUseJIT.cpp:(.text+0x4b7): undefined reference to `llvm::EngineBuilder::EngineBuilder(std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >)'
/usr/bin/ld: HowToUseJIT.cpp:(.text+0x4dc): undefined reference to `llvm::EngineBuilder::~EngineBuilder()'
/usr/bin/ld: HowToUseJIT.cpp:(.text+0x693): undefined reference to `llvm::EngineBuilder::~EngineBuilder()'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::EngineBuilder::create()':
HowToUseJIT.cpp:(.text._ZN4llvm13EngineBuilder6createEv[_ZN4llvm13EngineBuilder6createEv]+0x18): undefined reference to `llvm::EngineBuilder::selectTarget()'
/usr/bin/ld: HowToUseJIT.cpp:(.text._ZN4llvm13EngineBuilder6createEv[_ZN4llvm13EngineBuilder6createEv]+0x2a): undefined reference to `llvm::EngineBuilder::create(llvm::TargetMachine*)'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::IRBuilderDefaultInserter::IRBuilderDefaultInserter()':
HowToUseJIT.cpp:(.text._ZN4llvm24IRBuilderDefaultInserterC2Ev[_ZN4llvm24IRBuilderDefaultInserterC5Ev]+0xf): undefined reference to `vtable for llvm::IRBuilderDefaultInserter'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::InitializeNativeTarget()':
HowToUseJIT.cpp:(.text._ZN4llvm22InitializeNativeTargetEv[_ZN4llvm22InitializeNativeTargetEv]+0x9): undefined reference to `LLVMInitializeX86TargetInfo'
/usr/bin/ld: HowToUseJIT.cpp:(.text._ZN4llvm22InitializeNativeTargetEv[_ZN4llvm22InitializeNativeTargetEv]+0xe): undefined reference to `LLVMInitializeX86Target'
/usr/bin/ld: HowToUseJIT.cpp:(.text._ZN4llvm22InitializeNativeTargetEv[_ZN4llvm22InitializeNativeTargetEv]+0x13): undefined reference to `LLVMInitializeX86TargetMC'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>::~IRBuilder()':
HowToUseJIT.cpp:(.text._ZN4llvm9IRBuilderINS_14ConstantFolderENS_24IRBuilderDefaultInserterEED2Ev[_ZN4llvm9IRBuilderINS_14ConstantFolderENS_24IRBuilderDefaultInserterEED5Ev]+0x1c): undefined reference to `llvm::IRBuilderDefaultInserter::~IRBuilderDefaultInserter()'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::IRBuilderFolder::IRBuilderFolder()':
HowToUseJIT.cpp:(.text._ZN4llvm15IRBuilderFolderC2Ev[_ZN4llvm15IRBuilderFolderC5Ev]+0xf): undefined reference to `vtable for llvm::IRBuilderFolder'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::ConstantFolder::ConstantFolder()':
HowToUseJIT.cpp:(.text._ZN4llvm14ConstantFolderC2Ev[_ZN4llvm14ConstantFolderC5Ev]+0x1f): undefined reference to `vtable for llvm::ConstantFolder'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>::IRBuilder(llvm::BasicBlock*, llvm::MDNode*, llvm::ArrayRef<llvm::OperandBundleDefT<llvm::Value*> >)':
HowToUseJIT.cpp:(.text._ZN4llvm9IRBuilderINS_14ConstantFolderENS_24IRBuilderDefaultInserterEEC2EPNS_10BasicBlockEPNS_6MDNodeENS_8ArrayRefINS_17OperandBundleDefTIPNS_5ValueEEEEE[_ZN4llvm9IRBuilderINS_14ConstantFolderENS_24IRBuilderDefaultInserterEEC5EPNS_10BasicBlockEPNS_6MDNodeENS_8ArrayRefINS_17OperandBundleDefTIPNS_5ValueEEEEE]+0xbb): undefined reference to `llvm::IRBuilderDefaultInserter::~IRBuilderDefaultInserter()'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::ConstantFolder::~ConstantFolder()':
HowToUseJIT.cpp:(.text._ZN4llvm14ConstantFolderD2Ev[_ZN4llvm14ConstantFolderD5Ev]+0x13): undefined reference to `vtable for llvm::ConstantFolder'
/usr/bin/ld: HowToUseJIT.cpp:(.text._ZN4llvm14ConstantFolderD2Ev[_ZN4llvm14ConstantFolderD5Ev]+0x26): undefined reference to `llvm::IRBuilderFolder::~IRBuilderFolder()'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/HowToUseJIT.dir/build.make:91: HowToUseJIT] Error 1
make[1]: *** [CMakeFiles/Makefile2:77: CMakeFiles/HowToUseJIT.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
If anyone knows what my problem is, has any advice on running these LLVM examples, or knows of any resources that might better my understanding of wtf is happening I will be eternally grateful :). Thanks in advance for any help!
Edit 1: I tried the same procedure on some other examples to see what would happen. On Fibonacci everything build fine then seg faulted on runtime. On ModuleMaker I build fails on undefined reference to main... I'm really bungling something up here I just don't know what.
Edit 2: Thank you for the responses. I'm currently attempting to get everything to build correctly using Alexs advice. Simply using the CMakeLists.txt and building using Ninja did not work :( (I updated the build process outputs above). I was getting similar errors as before. Since Alex mentioned that he needed to use a different version of llvm header files, I figured I'd just build an updated version from source - but LLVM bested me once again. The build from source procedure in the README bombs on every release version I try (I'm running Ubuntu 20.04 lts). I'm starting to think my best bet is to just cherry-pick files and hack something together myself because this is getting to be too much of a headache.
Edit 3: I got it working :)
Solution
Everything ran and built fine when I updated to the newest version of LLVM. I ran into a lot of build problems on Ubuntu 20.04 lts that were a product of missing dependencies. This kind soul posted all the deps he needed to install in order to build llvm without errors.
So the following build worked for me and should hopefully be a model for you re: how to use CMake...
cmake_minimum_required(VERSION 3.22)
project(test)
# Find LLVM and the components we require.
find_package(LLVM 10 REQUIRED)
llvm_map_components_to_libnames(
LLVM_LIBRARIES
Core
ExecutionEngine
Interpreter
MC
MCJIT
Support
nativecodegen
)
# Create a wrapper for the LLVM components we need in this
# project. This will allow us to link it to multiple targets
# without duplicating a lot of code. It's too bad that LLVM
# doesn't provide anything like this.
add_library(test::LLVM INTERFACE IMPORTED)
target_include_directories(test::LLVM INTERFACE ${LLVM_INCLUDE_DIRS})
target_compile_definitions(test::LLVM INTERFACE ${LLVM_DEFINITIONS})
target_link_libraries(test::LLVM INTERFACE ${LLVM_LIBRARIES})
# Create our actual executable and link LLVM to it.
add_executable(HowToUseJIT HowToUseJIT.cpp)
target_link_libraries(HowToUseJIT PRIVATE test::LLVM)
Notice the following:
LLVM does not provide its own imported targets (bad)
We therefore create our own imported target to wrap it, test::LLVM.
We add the MC and MCJIT components to the list of components.
We assign the package-provided variables and computed list of libraries to the relevant properties of our imported target.
We always call target_link_libraries with a visibility specifier (they are PRIVATE, INTERFACE, and PUBLIC. Omitting it is none of the above.)
We state the version number of LLVM we require in the find_package call and omit the unnecessary CONFIG argument. Every major version of LLVM breaks the API in significant ways.
At the terminal, I now see:
$ cmake -G Ninja -S . -B build -DCMAKE_BUILD_TYPE=Release
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/build
$ cmake --build build/ --verbose
[1/2] /usr/bin/c++ -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -isystem /usr/lib/llvm-10/include -O3 -DNDEBUG -MD -MT CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o -MF CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o.d -o CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o -c /path/to/HowToUseJIT.cpp
[2/2] : && /usr/bin/c++ -O3 -DNDEBUG CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o -o HowToUseJIT /usr/lib/llvm-10/lib/libLLVMInterpreter.a /usr/lib/x86_64-linux-gnu/libffi.so /usr/lib/llvm-10/lib/libLLVMMCJIT.a /usr/lib/llvm-10/lib/libLLVMExecutionEngine.a /usr/lib/llvm-10/lib/libLLVMRuntimeDyld.a /usr/lib/llvm-10/lib/libLLVMX86CodeGen.a /usr/lib/llvm-10/lib/libLLVMAsmPrinter.a /usr/lib/llvm-10/lib/libLLVMDebugInfoDWARF.a /usr/lib/llvm-10/lib/libLLVMCFGuard.a /usr/lib/llvm-10/lib/libLLVMGlobalISel.a /usr/lib/llvm-10/lib/libLLVMSelectionDAG.a /usr/lib/llvm-10/lib/libLLVMCodeGen.a /usr/lib/llvm-10/lib/libLLVMTarget.a /usr/lib/llvm-10/lib/libLLVMBitWriter.a /usr/lib/llvm-10/lib/libLLVMScalarOpts.a /usr/lib/llvm-10/lib/libLLVMAggressiveInstCombine.a /usr/lib/llvm-10/lib/libLLVMInstCombine.a /usr/lib/llvm-10/lib/libLLVMTransformUtils.a /usr/lib/llvm-10/lib/libLLVMAnalysis.a /usr/lib/llvm-10/lib/libLLVMProfileData.a /usr/lib/llvm-10/lib/libLLVMX86Desc.a /usr/lib/llvm-10/lib/libLLVMObject.a /usr/lib/llvm-10/lib/libLLVMBitReader.a /usr/lib/llvm-10/lib/libLLVMCore.a /usr/lib/llvm-10/lib/libLLVMRemarks.a /usr/lib/llvm-10/lib/libLLVMBitstreamReader.a /usr/lib/llvm-10/lib/libLLVMMCParser.a /usr/lib/llvm-10/lib/libLLVMTextAPI.a /usr/lib/llvm-10/lib/libLLVMX86Utils.a /usr/lib/llvm-10/lib/libLLVMMCDisassembler.a /usr/lib/llvm-10/lib/libLLVMMC.a /usr/lib/llvm-10/lib/libLLVMBinaryFormat.a /usr/lib/llvm-10/lib/libLLVMDebugInfoCodeView.a /usr/lib/llvm-10/lib/libLLVMDebugInfoMSF.a /usr/lib/llvm-10/lib/libLLVMX86Info.a /usr/lib/llvm-10/lib/libLLVMSupport.a -lz -lrt -ldl -ltinfo -lpthread -lm /usr/lib/llvm-10/lib/libLLVMDemangle.a && :
$ ./build/HowToUseJIT
We just constructed this LLVM module:
; ModuleID = 'test'
source_filename = "test"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
define i32 #add1(i32 %AnArg) {
EntryBlock:
%0 = add i32 1, %AnArg
ret i32 %0
}
define i32 #foo() {
EntryBlock:
%0 = tail call i32 #add1(i32 10)
ret i32 %0
}
Running foo: Result: 11
Note: I had to use the sources for HowToUseJIT from a more recent LLVM release (the one from 13.0.0) because the old one has a segfault on some systems. However, that bug is unrelated to the build process.
Problem Description
I'm working on porting several codebases over from Red Hat 5 to 6, and I've run into a cmake issue that I'm completely stumped by.
Cmake is consistently finding the 32-bit versions of libraries under /usr/lib instead of the 64-bit versions under /usr/lib64 on an RHEL6 system, while it correctly detects the lib64 versions on the an RHEL5 system.
Minimal Example
For example, I have a very minimal CMakeLists.txt file:
cmake_minimum_required(VERSION 2.8)
find_library(XTEST X11)
message("Found X11 at ${XTEST}")
On an RHEL6 system, running cmake on this results in:
$ cmake ..
-- The C compiler identification is GNU 4.4.7
-- The CXX compiler identification is GNU 4.4.7
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
Found X11 at /usr/lib/libX11.so
-- Configuring done
-- Generating done
-- Build files have been written to: $HOME/software/64bit_problem/build
(The key part here is the Found X11 at /usr/lib/libX11.so line)
However, if I do the same thing on an RHEL5 system, it correctly detects the /usr/lib64/ version: (Note that I'm clearing out the CMakeCache.txt and other temporary cmake-files in between runs.)
$ cmake ..
-- The C compiler identification is GNU 4.1.2
-- The CXX compiler identification is GNU 4.1.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
Found X11 at /usr/lib64/libX11.so
-- Configuring done
-- Generating done
-- Build files have been written to: $HOME/software/64bit_problem/build
Troubleshooting Info
The /usr/lib64 versions of the libraries exist on both systems. Here's the listing on the RHEL6 system:
$ ls /usr/lib64/libX11.so*
/usr/lib64/libX11.so.6 /usr/lib64/libX11.so.6.3.0
And on the RHEL5 system:
$ ls /usr/lib64/libX11.so*
/usr/lib64/libX11.so.6 /usr/lib64/libX11.so.6.3.0
Just to confirm that /usr/lib is indeed the 32-bit versions (also, it's not a symlink to another location):
$ file /usr/lib/libX11.so*
/usr/lib/libX11.so: symbolic link to `libX11.so.6.3.0'
/usr/lib/libX11.so.6: symbolic link to `libX11.so.6.3.0'
/usr/lib/libX11.so.6.3.0: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, stripped
$ file /usr/lib64/libX11.so*
/usr/lib64/libX11.so.6: symbolic link to `libX11.so.6.3.0'
/usr/lib64/libX11.so.6.3.0: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, stripped
This is probably due to an environment setting somewhere, but I'm a bit stumped as to where. I don't have LD_LIBRARY_PATH, LD_RUN_PATH, or LDFLAGS set. Same for CFLAGS and CXXFLAGS. My user environment should be identical, as my $HOME is an NFS share that's the same on both machines.
/usr/lib isn't in my $PATH, and regardless, limiting my path to a minimal subset doesn't seem to help:
$ export PATH=/bin:/usr/bin:$HOME/local/bin
$ cmake ..
<snip>
Found X11 at /usr/lib/libX11.so
-- Configuring done
<snip>
#SergyA had the excellent suggestion of checking which environment variables were being accessed by using ltrace. strace didn't turn up anything diagnostic from what I could see, but ltrace shows the environment variable access nicely. Here's a quick summary:
$ ltrace -o ltrace_output cmake ..
$ grep getenv ltrace_output
getenv("PWD") = "$HOME/software/64bit_problem"
getenv("PATH") = "/bin:/usr/bin:$HOME/local/bin"
getenv("CMAKE_ROOT") = NULL
getenv("MAKEFLAGS") = NULL
getenv("VERBOSE") = NULL
getenv("CFLAGS") = NULL
getenv("LDFLAGS") = NULL
getenv("LDFLAGS") = NULL
getenv("LDFLAGS") = NULL
getenv("CXXFLAGS") = NULL
getenv("LDFLAGS") = NULL
getenv("LDFLAGS") = NULL
getenv("LDFLAGS") = NULL
cmake-specific Trobleshooting
The cmake version is identical on both machines (in fact, it's the same executable for reasons I'll omit for brevity):
$ cmake --version
cmake version 2.8.11.2
$ which cmake
$HOME/local/bin/cmake
I've tried explicitly enabling FIND_LIBRARY_USE_LIB64_PATHS, but this doesn't seem to make a difference:
cmake_minimum_required(VERSION 2.8)
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS ON)
find_library(XTEST X11)
message("Found X11 at ${XTEST}")
As #Ravi mentioned, this is more likely due to some issue with CMAKE_LIBRARY_PATH, but it's not set, and changing it as either an environment variable or as a cmake variable doesn't seem to help. However, I fully admit I am largely ignorant of the various cmake configuration variables, so it's very likely that I'm missing something obvious here.
One key thing I've recently realized is that it's not all libraries... For example:
cmake_minimum_required(VERSION 2.8)
find_library(PNGTEST png)
message("Found libpng at ${PNGTEST}")
Finds /usr/lib64/libpng.so instead of /usr/lib/libpng.so.
This leads me to think it's something cmake-specific, at any rate.
find_package instead of find_library
Given the library-specific issues I mentioned above, I thought to try finding the entire X11 package instead of a single library (which is really what the codebase I was working with should have done anyway).
However, I'm getting even more confusing results... It seems to be detecting a mix of 64-bit and 32-bit libraries? For example:
cmake_minimum_required(VERSION 2.8)
FIND_PACKAGE(X11 REQUIRED)
message("X11_LIBRARIES: ${X11_LIBRARIES}")
We'll get:
$ cmake ..
<snip>
-- Looking for XOpenDisplay in /usr/lib/libX11.so;/usr/lib/libXext.so
-- Looking for XOpenDisplay in /usr/lib/libX11.so;/usr/lib/libXext.so - not found
<snip>
-- Found X11: /usr/lib/libX11.so
X11_LIBRARIES: /usr/lib64/libSM.so;/usr/lib64/libICE.so;/usr/lib/libX11.so;/usr/lib/libXext.so
-- Configuring done
<snip>
However, if we have a look at these specific libraries in X11_LIBRARIES, they're a mix of 32-bit and 64-bit versions!
$ file /usr/lib64/libSM.so.6.0.1
/usr/lib64/libSM.so.6.0.1: ELF 64-bit LSB shared object, x86-64, <snip>
$ file /usr/lib64/libICE.so.6.3.0
/usr/lib64/libICE.so.6.3.0: ELF 64-bit LSB shared object, x86-64, <snip>
$ file /usr/lib/libX11.so.6.3.0
/usr/lib/libX11.so.6.3.0: ELF 32-bit LSB shared object, Intel 80386, <snip>
$ file /usr/lib/libXext.so.6.4.0
/usr/lib/libXext.so.6.4.0: ELF 32-bit LSB shared object, Intel 80386, <snip>
In summary, what else should I try?
Am I missing a cmake-specific or possibly X11-specific configuration option?
You could try :
list(INSERT 0 CMAKE_SYSTEM_LIBRARY_PATH /usr/lib64)
The full list of variables used by find_library is available in the documentation: https://cmake.org/cmake/help/v3.5/command/find_library.html
It turns out that the root problem is the version suffix and the lack of a symlink to specifically /usr/lib64/libX11.so on the RHEL6 side.
cmake looks specifically for libX11.so and not libX11.so.6 or some other version-specific variant.
In this case, making the symlink wasn't an option, but I was able to prefer the specific version by listing the filename first:
cmake_minimum_required(VERSION 2.8)
find_library(XTEST NAMES libX11.so.6 X11)
message("Found X11 at ${XTEST}")
However, there are undoubtedly a variety of better ways of handling this, and I'd be very interested to hear them if anyone has any better approaches.
I want to do multi threading in one of my for loop using #pragma omp parallel. So, i am writing the following code:
#pragma omp parallel for
for(int i=0; i<square->total; i++)
{
......
}
My project have a CMakeList.txt and Makefile. I don't understand, how do i tell the compiler and linker to use openMP?
Updates:
I have edited my CMakeList.txt with following code
find_package(OpenMP)
if (OPENMP_FOUND)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()
and then i did cmake .. and got the following result at terminal:
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Try OpenMP C flag = [-fopenmp]
-- Performing Test OpenMP_FLAG_DETECTED
-- Performing Test OpenMP_FLAG_DETECTED - Success
-- Try OpenMP CXX flag = [-fopenmp]
-- Performing Test OpenMP_FLAG_DETECTED
-- Performing Test OpenMP_FLAG_DETECTED - Success
-- Found OpenMP: -fopenmp
-- Configuring done
-- Generating done
The #pragma ... should be on its own line.
#pragma omp parallel for
for(int i=0; i<square->total; i++)
{
......
}
Make sure you don't forget the for at the end of the #pragma.
First make sure it works with the #pragma line commented out, then adding the line should be fine (assuming everything inside the loop is OK to parallelize, no concurrency issues or whatnot).
Also make sure you pass -fopenmp to both the compiler and the linker, and you have #include <omp.h> at the top.
#user2440724
I wrote the code sample as you ask:
#include <string>
#include <iostream>
#include <vector>
#include <omp.h>
using namespace std;
using namespace cv;
//----------------------------------------------------------
// MAIN
//----------------------------------------------------------
int main(int argc, char* argv[])
{
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int i = 0; i < 10; i++)
{
std::cout << "A" << std::endl;
}
getchar();
return 0;
}
in vs2010 you need enable openmp as shown below:
Good tutorial for linux here: http://goulassoup.wordpress.com/2011/10/28/openmp-tutorial/
And GNU OpenMP docs: http://gcc.gnu.org/onlinedocs/libgomp/index.html#toc_Top
I am trying to compile a simple test project to make sure all my tools, such as CMake, Boost, Clang are working.
The source code I am trying to compile is LibLinkTest.cpp:
#include <boost/filesystem.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <assert.h>
using namespace boost::filesystem;
int main(int argc, char* argv[])
{
std::string str{"test passed"};
std::cout << str << std::endl;
boost::filesystem::path p{argv[1]};
try {
std::cout << p.string() << std::endl;
if (exists(p)) {
if (is_regular_file(p)) {
std::ifstream file{p.c_str()};
std::string line;
if (file.good() && file.is_open()) {
while (file >> line) {
std::cout << line << std::endl;
}
}
file.close();
} else if (is_directory(p)) {
std::cout << p.string() << " is a directory " << std::endl; // path stream inserter
} else
std::cout << p.string() << " exists, but is neither a regular file nor a directory" << std::endl;
}
else {
std::cout << p.string() << " does not exist" << std::endl;
}
}
catch (const filesystem_error& ex) {
std::cout << ex.what() << std::endl;
}
}
Running:
c++ -std=c++11 -I /usr/boost_1_54_0/boost/ LibLinkTest.cpp -o LibTest -L /usr/boost_1_54_0/lib/ -lboost_filesystem -lboost_system
compiles it just fine and the code runs (with a seg fault, but I'll address that separately).
However, I want to use CMake with my other projects. Trying to compile LibLinkTest.cpp with the following CMakeLists.txt causes linking errors.
CMAKE_MINIMUM_REQUIRED (VERSION 2.6)
PROJECT(BoostTest CXX)
SET(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++")
FIND_PACKAGE(Boost 1.54.0 COMPONENTS filesystem system REQUIRED)
INCLUDE_DIRECTORIES(
${Boost_INCLUDE_DIR}
/usr/include/
/usr/include/c++/4.2.1/
)
ADD_EXECUTABLE(
LibTest
LibLinkTest.cpp
)
TARGET_LINK_LIBRARIES(LibTest boost_filesystem boost_system)
The output from running cmake ../ is:
-- The CXX compiler identification is Clang 5.0.0
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Boost version: 1.54.0
-- Found the following Boost libraries:
-- filesystem
-- system
-- Configuring done
-- Generating done
And finally running make gives the error:
Scanning dependencies of target LibTest
[100%] Building CXX object CMakeFiles/LibTest.dir/LibLinkTest.cpp.o
Linking CXX executable LibTest
Undefined symbols for architecture x86_64:
"std::string::c_str() const", referenced from:
boost::system::system_error::what() const in LibLinkTest.cpp.o
boost::filesystem::path::c_str() const in LibLinkTest.cpp.o
"std::string::empty() const", referenced from:
boost::system::system_error::what() const in LibLinkTest.cpp.o
"std::basic_ios<char, std::char_traits<char> >::good() const", referenced from:
_main in LibLinkTest.cpp.o
It seems like a setting in CMake is not correct, perhaps something that points to the std c++ lib. Does anyone know how I can configure CMake correctly?
I have solved this by changing the line:
SET(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++")
to
SET(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libstdc++")
It seems like I had just made a typo in the CMakeLists.txt.
On a side note, does anyone know why I need to set this flag? Is it a C++11 thing? It also seems to have solved my issues with the seg fault that I was getting when compiling from the command line.
You should change the line
TARGET_LINK_LIBRARIES(LibTest boost_filesystem boost_system)
to
TARGET_LINK_LIBRARIES(LibTest ${Boost_LIBRARIES})
The FIND_PACKAGE command sets the Boost_LIBRARIES variable to what you need to link with.
If you see these two lines from the output
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
It tells you that it might not be clang that is used to compile the source. To see if it is, to e.g.
$ c++ --version
to see what compiler it actually is. If it doesn't say clearly you may want to do e.g.
$ ls -l /usr/bin/c++
and if it's a symbolic link then check the link (and so on). On my system (Ubuntu 13.10) the file /usr/bin/c++ is a symbolic link to /etc/alternatives/c++ which is a symbolic link to /usr/bin/g++, meaning that on my system the command c++ is actually the GCC C++ compiler.
To make sure you use clang, then redo the cmake command (from a clean folder, that you haven't run cmake in before) with the environment variable CXX set to clang++, like
$ CXX=clang++ cmake path/to/folder/with/CMakeLists.txt
Pro-tip: Make a separate folder for building, and run cmake from it. Then you can easily clean it up by just removing it if needed.
I want to use jsoncpp for writing a C++ code in order to parse a JSON file. Let me explain what I did. I created a CMakeLists.txt and I made a FindJsoncpp.cmake along with a simple c++ file to test jsoncpp. When I compile the C++ source without cmake using -I/usr/include/jsoncpp/ -ljsoncpp it works fine. but when I try to build it using cmake it cannot find json.h header file that I included in my c++ source code.
here is my CMakeLists.txt:
cmake_minimum_required (VERSION 2.6)
project (Parser)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
include(LibFindMacros)
message("----------- trying to find Jsoncpp-------------")
find_package(Jsoncpp)
if(Jsoncpp_FOUND)
message("INFO: we found LibJsoncpp on your pc.")
message(Jsoncpp_FOUND = ${Jsoncpp_FOUND})
message(Jsoncpp_INCLUDE_DIR = ${Jsoncpp_INCLUDE_DIR})
message(Jsoncpp_LIBRARY = ${Jsoncpp_LIBRARY})
else(Jsoncpp_FOUND)
message("WARNING: we couldn't find LibJsoncpp on your pc. DLC is disabled.")
endif(Jsoncpp_FOUND)
#set(LIBS ${Jsoncpp_LIBRARY})
# Set the include dir variables and the libraries and let libfind_process do the rest.
# NOTE: Singular variables for this library, plural for libraries this this lib depends on.
set(Jsoncpp_PROCESS_INCLUDES Jsoncpp_INCLUDE_DIR)
set(Jsoncpp_PROCESS_LIBS Jsoncpp_LIBRARY)
# add the executable
add_executable(jsonparser jsonparser.cpp)
And this is the FindJsoncpp.cmake that I wrote:
# - Try to find Jsoncpp
# Once done, this will define
#
# Jsoncpp_FOUND - system has Jsoncpp
# Jsoncpp_INCLUDE_DIRS - the Jsoncpp include directories
# Jsoncpp_LIBRARIES - link these to use Jsoncpp
include(LibFindMacros)
# Use pkg-config to get hints about paths
libfind_pkg_check_modules(Jsoncpp_PKGCONF jsoncpp)
# Include dir
find_path(Jsoncpp_INCLUDE_DIR
NAMES json/json.h
# PATHS ./jsoncpp/
PATHS ${Jsoncpp_PKGCONF_INCLUDE_DIRS} # /usr/include/jsoncpp/json
)
# Finally the library itself
find_library(Jsoncpp_LIBRARY
NAMES jsoncpp
PATHS ${Jsoncpp_PKGCONF_LIBRARY_DIRS}
# PATH ./jsoncpp/
)
set(Jsoncpp_PROCESS_INCLUDES Jsoncpp_INCLUDE_DIR)
set(Jsoncpp_PROCESS_LIBS Jsoncpp_LIBRARY)
libfind_process(Jsoncpp)
And finally a simple C++ code called jsonparser.cpp to test it:
#include <iostream>
#include <fstream>
#include <json/json.h>
using namespace std;
void printSongInfo(Json::Value song){
std::clog<<"\n-----------printing a song-------------\n";
std::clog<<"Name="<<song["name"];
std::clog<<"Artist="<<song["artist"];
}
int main(){
std::ifstream catalogFile("catalog.json");
Json::Value root; // will contains the root value after parsing.
Json::Reader reader;
bool parsingSuccessful = reader.parse( catalogFile, root );
if ( !parsingSuccessful ){
// report to the user the failure and their locations in the document.
std::cout << "Failed to parse configuration\n"
<< reader.getFormattedErrorMessages();
return 1;
}
//parsing songs
const Json::Value songs = root["songs"];
for ( int index = 0; index < songs.size(); ++index ){ // Iterates over the sequence elements.
printSongInfo(songs[index] );
}
return 0;
}
When I run the jsonparser.cpp with below command it works just fine.
g++ -I/usr/include/jsoncpp/ -ljsoncpp jsonparser.cpp
but when I try to make it using cmake I get this error:
$~/jsoncppTest/build$ cmake ..
-- The C compiler identification is GNU 4.7.3
-- The CXX compiler identification is GNU 4.7.3
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
----------- trying to find Jsoncpp-------------
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.26")
-- checking for module 'jsoncpp'
-- found jsoncpp, version 0.6.0
-- Found Jsoncpp
INFO: we found LibJsoncpp on your pc.
Jsoncpp_FOUND=TRUE
Jsoncpp_INCLUDE_DIR=/usr/include/jsoncpp
Jsoncpp_LIBRARY=/usr/lib/libjsoncpp.so
-- Configuring done
-- Generating done
-- Build files have been written to: ~/jsoncppTest/build
$~/jsoncppTest/build$ make
Scanning dependencies of target jsonparser
[100%] Building CXX object CMakeFiles/jsonparser.dir/jsonparser.cpp.o
~/jsoncppTest/jsonparser.cpp:3:23: fatal error: json/json.h: No such file or directory
compilation terminated.
make[2]: *** [CMakeFiles/jsonparser.dir/jsonparser.cpp.o] Error 1
make[1]: *** [CMakeFiles/jsonparser.dir/all] Error 2
make: *** [all] Error 2
It cannot find json/json.h header file but it has founded the jsoncpp library in cmake before. I checked jsoncpp.pc file and found ti OK. I don't know what I am doing wrong! any help would be appreciated.
I am using ubuntu 13.04 with multiarch support. I heard something about jsoncpp problem with 64bit compiler but don't know if that's the case.
Ok, I have a solution that compiles fine on my system. Finding jsoncpp is tricky, because json-c installs a header with the same name, and on my system, that header is located under /usr/include/json/json.h. To get it work, you have to make the following changes:
in FindJsoncpp.cmake:
# Include dir
find_path(Jsoncpp_INCLUDE_DIR
NAMES json/features.h
PATH_SUFFIXES jsoncpp
PATHS ${Jsoncpp_PKGCONF_INCLUDE_DIRS} # /usr/include/jsoncpp/json
)
Searching for json/features.h instead of json/json.h avoids finding the json.h file of json-c on my system, which is not compatible.
in CMakeLists.txt :
include_directories(${Jsoncpp_INCLUDE_DIR})
add_executable(jsonparser jsonparser.cpp)
target_link_libraries(jsonparser ${Jsoncpp_LIBRARY})
Here the found directories are set up, so CMake actually uses them.
in jsonparser.cpp:
const Json::Value songs = root["songs"];
for ( int index = 0; index < songs.size(); ++index ){ // Iterates over the sequence elements.
std::clog<<"Name="<<songs[index]["name"];
std::clog<<"Artist="<<songs[index]["artist"];
}
Your orginal code didn't compile, so I replaced the offending piece with the code above. Have you forgot to declare the song variable?
I also removed the getFormattedErrorMessages() call, because I have only jsoncpp 0.5.0, in which that function is not available. That shouldn't make a difference though.
Let me know if this works for you.
jsoncpp now builds with cmake.
cmake -DCMAKE_BUILD_TYPE=debug -DBUILD_STATIC_LIBS=ON -DBUILD_SHARED_LIBS=OFF -G "Unix Makefiles" ../..
supports pkg-config
builds static lib, dynamic lib, or both
can be included into other projects
If you have suggestions, open an issue at GitHub.