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.
Related
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?
I am a novice in C++ programming, now having to build the OpenCV from source. I am getting an error related to the cudatoolkit installation
[ 13%] Built target opencv_cudev
[ 13%] Building NVCC (Device) object modules/core/CMakeFiles/cuda_compile.dir/src/cuda/cuda_compile_generated_gpu_mat.cu.o
nvcc fatal : Path to libdevice library not specified
CMake Error at cuda_compile_generated_gpu_mat.cu.o.cmake:266 (message):
Error generating file
/home/bruce/opencv-4.2.0/build/modules/core/CMakeFiles/cuda_compile.dir/src/cuda/./cuda_compile_generated_gpu_mat.cu.o
I look inside the cuda_compile_generated_gpu_mat.cu.o.cmake file and see the following lines.
# Generate the code
cuda_execute_process(
"Generating ${generated_file}"
COMMAND "${CUDA_NVCC_EXECUTABLE}"
"${source_file}"
${format_flag} -o "${generated_file}"
${CCBIN}
${nvcc_flags}
${nvcc_host_compiler_flags}
${CUDA_NVCC_FLAGS}
-DNVCC
${CUDA_NVCC_INCLUDE_ARGS}
)
I want to dig into where it's looking for the libdevice library. I don't know the technique for printing out the meaning of all these parameters. How do I print them out as I execute make?
If you want to debug this, and print the values in each of these CMake variables, you can add the message command to this CMake file:
# Generate the code
cuda_execute_process(
"Generating ${generated_file}"
COMMAND "${CUDA_NVCC_EXECUTABLE}"
"${source_file}"
${format_flag} -o "${generated_file}"
${CCBIN}
${nvcc_flags}
${nvcc_host_compiler_flags}
${CUDA_NVCC_FLAGS}
-DNVCC
${CUDA_NVCC_INCLUDE_ARGS}
)
# Print all the above variables to the console.
message("generated_file: ${generated_file}")
message("CUDA_NVCC_EXECUTABLE: ${CUDA_NVCC_EXECUTABLE}")
message("source_file: ${source_file}")
message("format_flag: ${format_flag}")
message("CCBIN: ${CCBIN}")
message("nvcc_flags: ${nvcc_flags}")
message("nvcc_host_compiler_flags: ${nvcc_host_compiler_flags}")
message("CUDA_NVCC_FLAGS: ${CUDA_NVCC_FLAGS}")
message("CUDA_NVCC_INCLUDE_ARGS: ${CUDA_NVCC_INCLUDE_ARGS}")
If you can modify how cmake is called from the command line, you can add the trace-expand option to print all the CMake calls, and expand the variables used:
cmake --trace-expand ..
Here's the complete log:
/tmp/ccCvErNZ.o: In function `YAML::detail::node& YAML::detail::node_data::get<std::string>(std::string const&, std::shared_ptr<YAML::detail::memory_holder>)':
cricket.cpp:(.text._ZN4YAML6detail9node_data3getISsEERNS0_4nodeERKT_St10shared_ptrINS0_13memory_holderEE[_ZN4YAML6detail9node_data3getISsEERNS0_4nodeERKT_St10shared_ptrINS0_13memory_holderEE]+0x94): undefined reference to `YAML::detail::node_data::convert_to_map(std::shared_ptr<YAML::detail::memory_holder>)'
collect2: error: ld returned 1 exit status
The code I'm trying to compile is simple
#include <iostream>
#include <yaml-cpp/yaml.h>
using namespace std;
int main() {
YAML::Node test = YAML::LoadFile("test.yaml");
if (test["date"]) {
cout << "HELLO";
}
return 0;
}
The YAML I'm using is the example from http://www.yaml.org/start.html
If I just try to load the YAML, it loads fine. But if I try to access any data I get the same error. So it's not a linking problem.
EDIT: I can do things like cout << test and cout << test.type() and other functions. I think the problem is in using a string based map for accessing internal nodes.
It seems that you are not properly linking the yaml-cpp library. Add the argument -lyaml-cpp when compiling. For example:
g++ -I/usr/local/include -L/usr/local/lib -lyaml-cpp -o test main.cpp
EDIT
Another option is to include this cmake to your CMakeLists.txt:
# attempt to find static library first if this is set
if(YAMLCPP_STATIC_LIBRARY)
set(YAMLCPP_STATIC libyaml-cpp.a)
endif()
# find the yaml-cpp include directory
find_path(YAMLCPP_INCLUDE_DIR yaml-cpp/yaml.h
PATH_SUFFIXES include
PATHS
~/Library/Frameworks/yaml-cpp/include/
/Library/Frameworks/yaml-cpp/include/
/usr/local/include/
/usr/include/
/sw/yaml-cpp/ # Fink
/opt/local/yaml-cpp/ # DarwinPorts
/opt/csw/yaml-cpp/ # Blastwave
/opt/yaml-cpp/
${YAMLCPP_DIR}/include/)
# find the yaml-cpp library
find_library(YAMLCPP_LIBRARY
NAMES ${YAMLCPP_STATIC} yaml-cpp
PATH_SUFFIXES lib64 lib
PATHS ~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/sw
/opt/local
/opt/csw
/opt
${YAMLCPP_DIR}/lib)
# handle the QUIETLY and REQUIRED arguments and set YAMLCPP_FOUND to TRUE if all listed variables are TRUE
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(YAMLCPP DEFAULT_MSG YAMLCPP_INCLUDE_DIR YAMLCPP_LIBRARY)
mark_as_advanced(YAMLCPP_INCLUDE_DIR YAMLCPP_LIBRARY)
I experienced something similar to this when trying to compile OpenXcom on a Debian system. It turned out that I was using a mix of testing and stable packages, the yaml package was from stable, and the combination somehow made linking fail if there were more than just a few initial functions.
If that is what you're experiencing (and you're using Debian too), try compiling a source package from stable with
apt-get --build source libyaml-cpp0.5/stable
This command will build .deb packages for libyaml, and you can then insert them with dpkg like this:
dpkg -i libyaml-cpp0.5*.deb
as root.
Compiling libyaml from source will make it link to the testing libraries you already have, instead of expecting stable libraries, and so should solve the problem above. It did for me, at least.
Even if you don't use Debian, compiling yaml-cpp from source (e.g. a tarball) might work for similar reasons.
Make sure these two files exist:
/usr/local/lib/libyaml-cpp.a
/usr/local/include/yaml-cpp/yaml.h
My CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 3.4)
FIND_PACKAGE(yaml-cpp REQUIRED)
ADD_EXECUTABLE(yaml_cpp_test yaml_cpp_test.cpp)
TARGET_LINK_LIBRARIES(yaml_cpp_test yaml-cpp)
The content of yaml_cpp_test.cpp is same as mentioned in the question.
I try to reappear the problem on vps (Ubuntu 14.04.1 LTS)
wget -c https://github.com/jbeder/yaml-cpp/archive/release-0.5.1.tar.gz
tar xvf release-0.5.1.tar.gz yaml-cpp-release-0.5.1/
cd yaml-cpp-release-0.5.1/
sudo apt-get install cmake
sudo apt-get install libboost-dev
cmake .
make
make install
after that, yaml-cpp install to /usr/local/lib and /usr/local/include
files in my working directory:
fqlgy#li407-86:~/yaml-cpp$ ll
total 12
-rw-r--r-- 1 fqlgy fqlgy 162 May 8 03:29 CMakeLists.txt
-rw-r--r-- 1 fqlgy fqlgy 10 May 8 03:11 test.yaml
-rw-r--r-- 1 fqlgy fqlgy 240 May 8 03:11 yaml_cpp_test.cpp
As i tried to run "cmake .", there is some error, so i delete the line CMakeFiles/CMakeOutput.log, the content of CMakeLists.txt is :
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
ADD_EXECUTABLE(yaml_cpp_test yaml_cpp_test.cpp)
TARGET_LINK_LIBRARIES(yaml_cpp_test yaml-cpp)
The following output is as expected:
fqlgy#li407-86:~/yaml-cpp$ cmake .
-- Configuring done
-- Generating done
-- Build files have been written to: /home/fqlgy/yaml-cpp
fqlgy#li407-86:~/yaml-cpp$ make
Scanning dependencies of target yaml_cpp_test
[100%] Building CXX object CMakeFiles/yaml_cpp_test.dir/yaml_cpp_test.cpp.o
Linking CXX executable yaml_cpp_test
[100%] Built target yaml_cpp_test
fqlgy#li407-86:~/yaml-cpp$ ./yaml_cpp_test
HELLO
I confirm that certain versions of yaml-cpp library contain this issue (and it is not about improper linking).
It is rather dirty, but I've resolved it by defining empty functions in my code, it looks like
YAML::BadConversion::~BadConversion()
{
}
void YAML::detail::node_data::convert_to_map(std::shared_ptr<YAML::detail::memory_holder>)
{
}
The approach is not perfect (e.g. because it causes duplicates if another library version is used).
In my case, I run the exact same code on two computer which only give error on one of them and that almost make me crazy. This is not a compilation error, linking error or something, I think the code is dirty or something else.
I tried all option:
regular building from source and installing using cmake .. => make => make install
same as 1, with CC=$(which gcc) CXX=$(which g++) cmake -DBUILD_SHARED_LIBS=ON ..
uninstalling the default package from apt (i use ubuntu 16.04)
all failed, until I find Ilya Golshtein's answer, then in my code which will use yaml-cpp I added this code jsut before YAML::LoadFIle Line
YAML::BadConversion::~BadConversion()
{
}
void YAML::detail::node_data::convert_to_map(std::shared_ptr<YAML::detail::memory_holder>)
{
}
This is the only solution that worked
I'm late to the party here and have no idea what I'm doing but for those of you on Windows, make sure your IDE likes your mingw-g++. Mine auto-defaulted to strawberry perl (?) and when I changed it to mingw-g++ everything started working. I suppose it has something to do with the versioning?
It bothered me, too. I met it when version of yaml-cpp was "0.7.0". I solved it by using "0.6.0" instead.
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 am trying to make a simple TUI using newt. I have installed the newt-dev package: apt-get install libnewt-dev and I beleive it is installed correctly since if I do build using gcc with following commands, it works just fine:
gcc -o test main.cpp -lnewt
But my simple code does not compile when I try with cmake using new CLion IDE. Here are the source code, CMakeLists.txt and compiler output:
#include <newt.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
/* required variables and string */
int uiRows, uiCols;
const char pcText[] = "Welcome to Newt and FLOSS !!!";
/* initialization stuff */
newtInit();
newtCls();
/* determine current terminal window size */
uiRows = uiCols = 0;
newtGetScreenSize(&uiCols, &uiRows);
/* draw standard help and string on root window */
newtPushHelpLine(NULL);
newtDrawRootText((uiCols-strlen(pcText))/2, uiRows/2, pcText);
/* cleanup after getting a keystroke */
newtWaitForKey();
newtFinished();
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(TemparatureMonitoring)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
add_library(newt) #this does nothing!
set(SOURCE_FILES main.cpp)
add_executable(TemparatureMonitoring ${SOURCE_FILES})
Compiler output:
/opt/clion-1.0/bin/cmake/bin/cmake --build /home/saeid/.clion10/system/cmake/generated/9c100db8/9c100db8/Debug --target all -- -j 4
You have called ADD_LIBRARY for library newt without any source files. This typically indicates a problem with your CMakeLists.txt file
-- Configuring done
CMake Error: Cannot determine link language for target "newt".
CMake Error: CMake can not determine linker language for target: newt
-- Generating done
-- Build files have been written to: /home/saeid/.clion10/system/cmake/generated/9c100db8/9c100db8/Debug
make: *** [cmake_check_build_system] Error 1
I think I have to somehow add a reference to newt package, but no idea how! So basically I am looking for a equivalent to -l switch of gcc for CMakeLists.txt
In addition to my comment, after searching a little bit, I think you need the command ''target_link_libraries''
http://www.cmake.org/cmake/help/v3.0/command/target_link_libraries.html