1

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...

Trung Ta
  • 1,582
  • 1
  • 16
  • 25
  • 2
    "The tricky part for me is the backtick" - For evaluate command line, use `execute_process`, like described [here](https://stackoverflow.com/questions/34524255/pass-output-of-command-line-utility-to-compiler-linker) or [here](https://stackoverflow.com/questions/34524255/pass-output-of-command-line-utility-to-compiler-linker). After that, the most tricky part is to use this output properly: as it contains not only compiler options, but also a linker ones, you cannot just assign `CMAKE_CXX_FLAGS`. You should also use `CMAKE_EXE_LINKER_FLAGS` and commands `link_directories` and `link_libraries`. – Tsyvarev Sep 13 '18 at 10:09
  • I have try the command like `execute_process(COMMAND bash "-c" "llvm-config --cxxflags --ldflags --libs" OUTPUT_VARIABLE CMD_OUTPUT)`, and seet it to both `CMAKE_CXX_FLAGS` and `CMAKE_EXE_LINKER_FLAGS` but it doesn't work. – Trung Ta Sep 13 '18 at 12:07
  • Should be `COMMAND llvm-config --cxxflags --ldflags --libs` - wrapping with quotes is wrong. Also you may use *RESULT_VARIABLE* option for `execute_process` for check, whether command execution succeeded. – Tsyvarev Sep 13 '18 at 13:31
  • 1
    Sorry, didn't see your update. Approach with `link_directories` and `target_link_libraries` should work. Could you explain, what exactly "doesn't work" in that case? (error from CMake, compiler or linker). Also, with `make VERBOSE=1` you may see the command lines which CMake generates for compiling and linking your executable. – Tsyvarev Sep 13 '18 at 14:38
  • 1
    KDevelop has a neat module for finding LLVM and Clang: https://cgit.kde.org/kdevelop.git/tree/cmake/modules/FindLLVM.cmake – arrowd Sep 13 '18 at 15:47
  • @arrowd: Thanks for the suggestion. I will try it out. – Trung Ta Sep 14 '18 at 03:12
  • @Tsyvarev: Some how the feature `link_directories` doesn't work with new CMake (in my case is 3.10.2). I saw another comment in this post confirmed this issue with the new CMake: https://stackoverflow.com/a/28606916/3631532. Currently, I have to use the command `set_target_properties...` and the absolute path of LLVM. – Trung Ta Sep 14 '18 at 03:18
  • Well, I remember that: `link_directories` should be issued **before** creating the target (`add_executable` in your case). If this is not convinient for you, you may use `find_library` command for seach a library by the name, given with `-l` flag, in the directories, given with `-L` flag in `llvm-config` output. Something similar is performed by [FindPkgConfig.cmake](https://github.com/Kitware/CMake/blob/master/Modules/FindPkgConfig.cmake) module, which transforms output of `pkg-config` for CMake. – Tsyvarev Sep 14 '18 at 09:39
  • LLVM/Clang use CMake to build itself and provide an exported targets. That you need is to `find_package` and get these targets into a scope. No need to use any external tools... – zaufi Sep 17 '18 at 18:02

1 Answers1

3

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.

zaufi
  • 6,811
  • 26
  • 34