3

I'm trying to write a CMake function that creates an object library of LLVM bitcode files. Here is what I have so far

function(build_llvm_lib OUTPUT SRC)
  if(NOT LLVM_FOUND)
    message(FATAL_ERROR "LLVM build requested but LLVM not found")
  endif()

  set(SRCS ${SRC} ${ARGN})

  set(CMAKE_C_OUTPUT_EXTENSION ".bc")
  set(CMAKE_CXX_OUTPUT_EXTENSION ".bc")
  set(CMAKE_STATIC_LIBRARY_SUFFIX ".bc")

  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -emit-llvm")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -emit-llvm")

  set(CMAKE_C_COMPILER ${LLVM_TOOLS_BINARY_DIR}/clang)
  set(CMAKE_CXX_COMPILER ${LLVM_TOOLS_BINARY_DIR}/clang++)
  set(CMAKE_AR ${LLVM_TOOLS_BINARY_DIR}/llvm-ar)
  set(CMAKE_RANLIB ${LLVM_TOOLS_BINARY_DIR}/llvm-ranlib)

  add_library(${OUTPUT} OBJECT ${SRCS})
endfunction(build_llvm_lib)

However, the problem that I'm having is that even though I am setting the CMake variables like CMAKE_CXX_FLAGS and CMAKE_CXX_OUTPUT_EXTENSION these don't seem to be having any affect (i.e. they are being ignore) when CMake is run. When I look at the generated Makefile these settings don't appear and when I run make a regular object file is built rather than an LLVM bitcode file.

I'm kind of a CMake newb, so can someone please explain what's going on here? Is there some sort of misunderstanding I'm making here with CMake functions?

Adrian
  • 98
  • 5
  • 3
    You need to add `PARENT_SCOPE`, cf. https://cmake.org/cmake/help/v3.7/command/set.html – usr1234567 Oct 26 '16 at 17:03
  • Excellent, thanks! For some reason `CMAKE__OUTPUT_EXTENSION` is still being ignored, but some Googling seems to show that this is not unusual. I don't _really_ understand why `PARENT_SCOPE` works though. Won't this mean that when `build_llvm_lib` returns future calls to `add_library` (outside of this function) will also create LLVM bitcode files, rather than regular object files? – Adrian Oct 26 '16 at 17:17

1 Answers1

3

While all CMake variables may have different values when you create different targets, CMake expects some of variables be the same for all targets. Examples of those variables:

  • CMAKE_<LANG>_COMPILER

  • CMAKE_AR

  • CMAKE_RANLIB

  • CMAKE_<LANG>_OUTPUT_EXTENSION

This means that you cannot use different compilers for different targets in the same project. See, e.g. this question.

Variables CMAKE_<LANG>_FLAGS also should be defined globally, for all targets.

Only CMake variables and functions which are propagated to the target's property have per-target meaning.

For example, you may define additional compiler options for concrete targets using commands add_compile_options, add_definitions or by manually setting target's properties COMPILE_FLAGS or COMPILE_DEFINITIONS.


In your build_llvm_lib function body only CMAKE_STATIC_LIBRARY_SUFFIX variable probably has per-target nature: while it is not stated in the documentation, I suspect it just sets SUFFIX property for newly-defined targets.

Community
  • 1
  • 1
Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • Thanks! Ok, so if I understand you correctly I should not be using this approach to begin with? And I would be better off following the answer [here](http://stackoverflow.com/questions/9542971/using-cmake-with-multiple-compilers-for-the-same-language) and run CMake twice? – Adrian Oct 27 '16 at 08:11
  • Yes, it is better to create distinct project for create libraries with llvm. – Tsyvarev Oct 27 '16 at 08:27