I am trying to compile from source and experiment with the examples in boost::sml. The visitor example in particular will not compile, so my application with sml is missing a straightforward way to just status which states its state machines are in.
I am running on a machine with the following statuses when doing the initial cmake setup:
-- The CXX compiler identification is GNU 7.5.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
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test HAS_CXX14_FLAG
-- Performing Test HAS_CXX14_FLAG - Success
-- Performing Test HAS_CXX17_FLAG
-- Performing Test HAS_CXX17_FLAG - Success
-- Performing Test HAS_CXX20_FLAG
-- Performing Test HAS_CXX20_FLAG - Failed
-- Boost version: 1.65.1
-- Configuring done
-- Generating done
Most of the code compiles, but for example/visitor.cpp, I get these errors:
In file included from /data/sml/example/visitor.cpp:8:0:
/data/sml/include/boost/sml.hpp: In instantiation of ‘struct boost::ext::sml::v1_1_4::back::sm_impl<boost::ext::sml::v1_1_4::back::sm_policy<state_name_visitor<boost::ext::sml::v1_1_4::back::sm<boost::ext::sml::v1_1_4::back::sm_policy<composite> > > > >’:
/data/sml/include/boost/sml.hpp:1789:72: required from ‘boost::ext::sml::v1_1_4::back::sm< <template-parameter-1-1> >::operator T&() [with T = state_name_visitor<boost::ext::sml::v1_1_4::back::sm<boost::ext::sml::v1_1_4::back::sm_policy<composite> > >; TSM = boost::ext::sml::v1_1_4::back::sm_policy<composite>]’
/data/sml/example/visitor.cpp:68:62: required from here
/data/sml/include/boost/sml.hpp:1362:68: error: no matching function for call to ‘state_name_visitor<boost::ext::sml::v1_1_4::back::sm<boost::ext::sml::v1_1_4::back::sm_policy<composite> > >::operator()()’
compilation terminated due to -Wfatal-errors.
Any suggestions? Is C++20 required?
C++20 is not required. The current revision on Github contains:
#error "[Boost::ext].SML requires C++14 support (Clang-3.4+, GCC-5.1+, MSVC-2015+)"
And indeed, it compiles fine with -std=c++14, even with GCC 7.5 on my Ubuntu 18.04 box.
However, since your CMake output suggests that C++17 is selected, I tried, and that gives the same problem. I might try to find a fix (after dinner)
UPDATE
I cannot say I fully understand this, but the following change makes it work:
const auto state_name = state_name_visitor<decltype(sm)>{sm};
Should be
const auto state_name = state_name_visitor<decltype((sm))>{sm};
Or alternatively
const auto state_name = state_name_visitor<decltype(sm)&>{sm};
Now it compiles in C++17 mode on GCC 7.5.
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.
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 trying to use the xlc compiler for my cpp code on AIX.
I want the cc compiler for my C code
output:
user#AIX> cmake -DCMAKE_CXX_COMPILER=/usr/vac/bin/xlc ..
-- The C compiler identification is XL 11.1.0
-- The CXX compiler identification is XL 11.1.0
-- Check for working C compiler: /usr/vac/bin/cc
-- Check for working C compiler: /usr/vac/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/vac/bin/xlc
-- Check for working CXX compiler: /usr/vac/bin/xlc -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
but when I run make ( right after the above output), it seems to be using the gcc compiler.
user#AIX> make
[ 0%] Building CXX object ../libs/shrxml/CMakeFiles/shrxml.dir/XML.cpp.o
gcc: unrecognized option '-+'
gcc: unrecognized option '-qthreaded'
gcc: unrecognized option '-qhalt=e'
gcc: unrecognized option '-qnamemangling=v6'
gcc: unrecognized option '-qmaxmem=9216'
gcc: unrecognized option '-qnamemangling=v6'
gcc: unrecognized option '-qmaxmem=9216'
gcc: unrecognized option '-qpic'
In file included from /opt/freeware/lib/gcc/powerpc-ibm-
aix6.1.0.0/4.4.5/include/c++/backward/strstream:47,
from
/home/user/workspace/bitbucket/ark/src/libs/shrxml/XML.cpp:105:
/opt/freeware/lib/gcc/powerpc-ibm-
aix6.1.0.0/4.4.5/include/c++/backward/backward_warning.h:28:2: warning:
#warning This file includes at least one deprecated or antiquated header
which may be removed without further notice at a future date. Please use a
non-deprecated interface with equivalent functionality instead. For a
listing of replacement headers and interfaces, consult the file
backward_warning.h. To disable this warning use -Wno-deprecated.
I have tried adding the set inside my CMakeLists.txt file
set(CMAKE_CXX_COMPILER /usr/vac/bin/xlc CACHE PATH "" FORCE)
set(CMAKE_CC_COMPILER /usr/vac/bin/cc CACHE PATH "" FORCE)
I have also exported the environment variable:
user#AIX> echo $CMAKE_CXX_COMPILER
/usr/vac/bin/xlc
user#AIX>
Any thoughts?
There are no links for cc or xlc in the /usr/vac/bin directory.
When I grep for gcc and xlc in the shrxlm directory all I can find is gcc. Why isn't cmake honoring my request for the xlc compiler?
Check the cc symlink on your system to make sure it points to XL and not gcc. Do a which cc and then ls -l that.
According to the CMake FAQ "How do I use a different compiler?" section, there are 3 methods. It looks like you have tried to use all 3, including Method 3 (set()), which is marked "avoid".
Could you try Method 1: use environment variables again, but this time with the environment variables listed there, CC (for C) and CXX (for C++) environment variables?
I'm creating cmake toolchain description for my compiler (for example let's name it MYCC) based on clang, so it's identified as Clang during compiler identification:
-- The C compiler identification is Clang 3.8.0
-- The CXX compiler identification is Clang 3.8.0
But MYCC doesn't really supports all the things (flags like -fPIC), that Clang does, and I want it to be identified as MYCC, not Clang. I also want my clients to see:
-- The C compiler identification is MYCC
-- The CXX compiler identification is MYCC
I can't use CMakeForceCompiler because it is deprecated (https://cmake.org/cmake/help/v3.0/module/CMakeForceCompiler.html).
I found that IDs is hardcoded in https://github.com/Kitware/CMake/blob/master/Modules/CMakeCompilerIdDetection.cmake
Is there any way to have my own compiler ID without patching this file?
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.