How to add the option `llvm-config --cxxflags --ldflags --libs` in CMake? - cmake

Does anyone know how to add the option `llvm-config --cxxflags --ldflags --libs` into CMake? The tricky part for me is the backtick `.
I need to config my CMake files to obtain a compilation command like:
g++ test.cpp -lclangBasic -I/usr/lib/llvm-6.0/include
-Wall `llvm-config --cxxflags --ldflags --libs`
I tried to use the following options, but they don't work:
add_compile_options(`llvm-config --cxxflags --ldflags --libs`)
# or
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} `llvm-config --cxxflags --ldflags --libs`")
Thank you in advance.
===============
Update 1.
Using the output from `llvm-config --cxxflags --ldflags --libs`, I can compile successfully with the following command:
g++ test.cpp -lclangBasic -I/usr/lib/llvm-6.0/include
-Wall -I/usr/lib/llvm-6.0/include -L/usr/lib/llvm-6.0/lib -lLLVM-6.0
I can pass -I/usr/lib/llvm-6.0/include by using include_directories(usr/lib/llvm-6.0/include).
But still, I don't know how to pass the part -L/usr/lib/llvm-6.0/lib -lLLVM-6.0 to CMake. Using link_directories and target_link_libraries like the following doesn't work for me:
link_directories(/usr/lib/llvm-6.0/lib)
target_link_libraries(test PUBLIC "LLVM-6.0")
Does anyone know to make them work in CMake?
===============
Update 2.
I have to add the following code into the file CMakeLists.txt to make CMake work.
add_library(LLVM-6.0 SHARED IMPORTED) # or STATIC instead of SHARED
set_target_properties(LLVM-6.0 PROPERTIES
IMPORTED_LOCATION "/usr/lib/llvm-6.0/lib/libLLVM-6.0.so"
INTERFACE_INCLUDE_DIRECTORIES "/usr/lib/llvm-6.0/include"
)
add_library(clangBasic SHARED IMPORTED) # or STATIC instead of SHARED
set_target_properties(clangBasic PROPERTIES
IMPORTED_LOCATION "/usr/lib/llvm-6.0/lib/libclangBasic.a"
INTERFACE_INCLUDE_DIRECTORIES "/usr/lib/llvm-6.0/include"
)
target_link_libraries(solidity PUBLIC "LLVM-6.0;clangBasic")
However, this looks manually, and I'm still looking for better solutions...

LLVM/Clang use CMake and provide a config module, so any project trying to use LLVM/Clang just need a find_package(Clang...) to bring the exported targets into a scope (and don't need to use any external tools (like llvm-config or pkg-config blah-blah)). Meaning that after Clang has found, you can use target_link_libraries(blah Clang::clangBasic ...) and no need to do any "manual import" or whatever ppl suggest in the comments...
As a quick check one may use the following command:
$ cmake --find-package -DNAME=Clang -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=EXIST
Clang found.
$ cmake --find-package -DNAME=Clang -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=COMPILE
-I/usr/lib/llvm-6.0/include
I used Clang 6.0 installed from the deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-6.0 main repo.

Related

Include an external library in cmake from flags

I am trying to link an external library, let's call it foo, which is not compiled with cmake.
foo is installed and I can access its cxx flags and link flags via
foo-config --cflags
foo-config --libs
I can easily use the above in a Makefile, but I want to switch to cmake.
What would be the correct approach to create an imported library called foo in my CMakeLists.txt?
I would like to use a modern cmake approach if possible (using targets instead of global cmake variables).
I tried the following:
execute_process(
COMMAND foo-config --cflags
RESULT_VARIABLE FOO_EXISTS
OUTPUT_VARIABLE FOO_FLAGS_RAW
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(
COMMAND foo-config --libs
RESULT_VARIABLE FOO_EXISTS
OUTPUT_VARIABLE FOO_LIBS_RAW
OUTPUT_STRIP_TRAILING_WHITESPACE)
if (FOO_EXISTS EQUAL "0")
separate_arguments(FOO_FLAGS UNIX_COMMAND "${FOO_FLAGS_RAW}")
separate_arguments(FOO_LIBS UNIX_COMMAND "${FOO_LIBS_RAW}")
endif()
MARK_AS_ADVANCED(
FOO_FLAGS_RAW
FOO_LIBS_RAW
)
add_library(foo SHARED IMPORTED)
target_compile_options(foo PUBLIC ${FOO_FLAGS})
set_target_properties(foo PROPERTIES
LINK_FLAGS ${FOO_LIBS}
)
but when I link the library to my target it seems that the compilation flags are not passed (they do not show up when I use VERBOSE=1).
Thank you in advance!
I found a workaround, I did not want to write the whole find module myself.
I just created a pkg-config file and used the cmake module already written for that purpose.
Thanks #Tsyvarev for the suggestion!

how do i specify libraries's path to cmake which are used by target_link_libraries

I have some codebase which has cmake build system .while building iam getting an error as below
/usr/bin/ld: cannot find -lcurl
below is the sample cmakelist.txt
cmake_minimum_required(VERSION 2.8.6)
project(oci_object_test)
set(IB_HOME /home/user/sample_cmake/usr/lib)
include_directories(${LIB_HOME}/include)
link_directories(${LIB_HOME}/lib64)
link_directories(/home/user/sample_cmake/usr/lib/lib64)
link_directories(/home/user/)
set(SOURCES
sample.cpp
)
add_executable(demo ${SOURCES})
target_link_libraries(demo curl openssl)
for the above cmakelist.txt below is the link.txt generated by cmake
/usr/bin/c++ CMakeFiles/demo.dir/sample.cpp.o -o demo -L/home/user/sample_cmake/usr/lib/lib64 -L/home/user -rdynamic -lcurl -lopenssl -Wl,-rpath,/home/user/sample_cmake/usr/lib/lib64:/home/user
this issue is due to -lcurl getting added in link.txt generated by cmake . if i remove -lcurl from link.txt manually and build ,build will get success with no linker error . So is there any way i can get rid off this -lcurl in link.txt or is it possible to define -lcurl path where it actual libcurl present ( for example suppose libcurl present inside /usr/curl_path/curl) so that cmake could generate link.txt as below?
/usr/bin/c++ CMakeFiles/demo.dir/sample.cpp.o -o demo -L/home/user/sample_cmake/usr/lib/lib64 -L/home/user -rdynamic /usr/curl_path/curl -lopenssl -Wl,-rpath,/home/user/sample_cmake/usr/lib/lib64:/home/user
i know i can define libucrl path directly as below which will solve my issue ,
target_link_libraries(demo /usr/curl_path/curl openssl)
but iam looking for something like SET or any other cmake environment variable which i can define inside toolchain.cmake file so that cmakelist.txt is untouched ,in simple words how do i specify those libraries's path to cmake which are going use inside target_link_libraries
If your CMake version is less than 3.12, you need to use this old method. See:
https://cmake.org/cmake/help/v3.10/module/FindCURL.html
cmake_minimum_required(VERSION 3.10)
project(program)
find_package(CURL REQUIRED)
if (CURL_FOUND)
add_executable(program main.cpp)
target_link_libraries(program ${CURL_LIBRARIES})
target_include_directories(program PRIVATE ${CURL_INCLUDE_DIRS})
endif()
There is a new method for CMake 3.12 and later using imported targets. See the new alternative FindCurl.
cmake_minimum_required(VERSION 3.12)
project(program)
find_package(CURL REQUIRED)
if (CURL_FOUND)
add_executable(program main.cpp)
target_link_libraries(program CURL::libcurl)
endif()
I found out that this issue can be solved by two methods (first method is similar to this)
second method is by adding below two lines of code to your cmakelist.txt file before calling target_link_directories
add_library( curl SHARED IMPORTED)
set_property(TARGET curl PROPERTY IMPORTED_LOCATION "${CURL_LIBRARY}")
where CURL_LIBRARY is the path for libcurl.so specified in toolchain.cmake
unfortunately i didn't find any solution to solve this issue without touching cmakelist.txt.

How to get cmake generate -std=c++14 flag for qcc compiler

I'm trying to cross compile some c++ library for QNX neutrino using cmake. In CMakeLists.txt file I specified CMAKE_CXX_STANDARD 14 required, but the resulting compiler command line does not contain the -std=c++14 option.
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
I've tried using target compile features:
target_compile_features(my_library PRIVATE cxx_std_14)
but that gives me the following error:
CMake Error at CMakeLists.txt:53 (target_compile_features):
target_compile_features no known features for CXX compiler
"QCC"
version 5.4.0.
When I'm using check_cxx_compiler_flag feature, it seems to recognize the option:
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-std=c++14 CXX14_SUPPORT)
if(CXX14_SUPPORT)
message("c++14 support found")
else()
message("c++14 unsupported")
endif()
This outputs message
c++14 support found
Running qcc manually it accepts the -std=c++14 option just fine and the code using std::make_unique compiles just fine.
Also using the native compiler (Ubuntu 18.04, gcc) everything work fine with cmake generated makefiles. make VERBOSE=1 displays the following command line (I removed some directories):
/usr/local/bin/c++ -Dshm_transfer_EXPORTS -I... -fPIC -std=gnu++14 -o CMakeFiles/shm_transfer.dir/src/SharedMemoryTransfer.cpp.o -c .../SharedMemoryTransfer.cpp
as opposed to the command line using qcc toolchain:
.../qnx700/host/linux/x86_64/usr/bin/qcc -lang-c++ -Vgcc_ntox86_64 -lang-c++ -Dshm_transfer_EXPORTS -I... -fPIC -o CMakeFiles/shm_transfer.dir/src/SharedMemoryTransfer.cpp.o -c .../SharedMemoryTransfer.cpp
I would have expected the cmake command to recognize that qcc supports the -std=c++14 option and generates the corresponding command lines because of the CMAKE_CXX_STANDARD setting.
Use
set_property(TARGET ${PROJECT_NAME} PROPERTY LINKER_LANGUAGE CXX)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14)
. Using this you can stick the compiler setting to the target, while global flags are dis encouraged and can be overwritten by other cmake consumers. This the reason I assume why the deprecated set(CMAKE_CXX_STANDARD 14) did not help you: I can not see your full CMakeLists.txt and bet you have many sub folders and other targets, which could reset the CMAKE_CXX_STANDARD them selfs. Also make sure of the ordering of the CMake commands.
And you can replace ${PROJECT_NAME} with my_library if you want.
add_compile_options(-std=gnu++14)
Add this to your project level CMakeLists.txt file, not in toolchain.

Disable -Werror for one of CMakeLists.txt

I have the following CMake file:
project(MyLib)
cmake_minimum_required(VERSION 2.8)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "release")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Werror")
set(ROOT_DIR ${CMAKE_SOURCE_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${ROOT_DIR}/bin/${CMAKE_BUILD_TYPE})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ROOT_DIR}/bin/${CMAKE_BUILD_TYPE})
set(MAIN_LIBRARY_NAME "mylib")
add_subdirectory(src)
add_subdirectory(test_app)
add_subdirectory(test_app1) <--- I want to disable -Werror flag for CMakeLists.txt in this folder.
add_subdirectory(test_app2)
How to disable -Werror flag for one of subdirectories? In the each of sub directories I have CMakeLists.txt too.
Turning my comment into an answer
All variables and directory properties are copied to the subdirectory's context at the moment you call add_subdirectory(). Either modify CMAKE_CXX_FLAGS before this call with something like
string(REPLACE " -Werror" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
add_subdirectory(test_app1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
Or use the "old way" were compiler flags could be given with add_definitions() and removed with remove_definitions()
add_definitions(-std=c++11 -Wall -Werror)
...
remove_definitions(-Werror)
add_subdirectory(test_app1)
add_definitions(-Werror)
But you can - in contradiction to my first comment - change flags added add_compile_options() only on target level COMPILE_OPTIONS property and not for complete directories. When the target is created the property is copied as-is from the directory to the target and changing the directory property later won't automatically update the target's property.
If you have a newer CMake version that supports SOURCE_DIR target property you can alternatively go by some crazy generator expression:
add_compile_options(
-std=c++11
-Wall
$<$<NOT:$<STREQUAL:$<TARGET_PROPERTY:SOURCE_DIR>,${CMAKE_SOURCE_DIR}/test_app1>>:-Werror>
)
Reference
Is Cmake set variable recursive?
If you are using CMake v3.24's new CMAKE_COMPILE_WARNING_AS_ERROR variable, which initializes the corresponding target property, you can simply set the variable to FALSE in the CMakeLists.txt file of any subdirectories where you won't want warnings to be errors.
There are two nice things about using this variable:
Cross-platform with less boilerplate: No more explicitly written generator expressions to use the right flag for each compiler.
Allows user-override: Not all users will want to build with warnings as errors. This new feature comes with a --compile-no-warning-as-error command-line flag that users can use to disable any effects of this variable/target-property when set by a dev in a CMakeLists.txt file.
we have a project setup which configured Werror and Wall at the top level as compiler flags. What I ended up doing for a temporary test program which I wanted to skip Werror was:
add_executable(test_program ...)
target_compile_options(test_program PRIVATE -Wno-error)
that ended up generating a compile line like:
g++ ... -Wall -Werror -Wno-error test.cpp -o test
where the -Wno-error cancels out the -Werror, without affecting the CXXFLAGS for the rest of the project.

CMake, static library and link time optimization

I'm trying to create static library with link time optimization using cmake and g++.
set(
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wall -Werror -Wextra -pedantic -std=c++11"
)
if (CMAKE_COMPILER_IS_GNUCXX)
set(
CMAKE_STATIC_LINKER_FLAGS_RELEASE
"${CMAKE_STATIC_LINKER_FLAGS_RELEASE} -flto -fwhole-program"
)
endif()
add_library(
mylib STATIC
mylib.cpp
)
But when running typical
cmake -DCMAKE_BUILD_TYPE=Release ..
make
I'm getting following error:
/usr/bin/ar: two different operation options specified
link.txt file contains following commands:
/usr/bin/ar cq libmylib.a -flto -fwhole-program CMakeFiles/mylib.cpp.o
/usr/bin/ranlib libmylib.a
From what I understand from running ar --help the -flto -fwhole-program should be before libmylib.a in the first line. But I have no idea how to force CMake to put it there.
Is my assumption correct? And how can I resolve this?
EDIT: I'd like to add that I'm completely new to using LTO so if it doesn't make sense to use it for static libraries, please do tell me so.
-flto isn't a valid option for ar. You should instead use these flags for CMAKE_EXE_LINKER_FLAGS.