Home | History | Annotate | Download | only in modules
      1 include(ExternalProject)
      2 
      3 # llvm_ExternalProject_BuildCmd(out_var target)
      4 #   Utility function for constructing command lines for external project targets
      5 function(llvm_ExternalProject_BuildCmd out_var target)
      6   if (CMAKE_GENERATOR MATCHES "Make")
      7     # Use special command for Makefiles to support parallelism.
      8     set(${out_var} "$(MAKE)" "${target}" PARENT_SCOPE)
      9   else()
     10     set(${out_var} ${CMAKE_COMMAND} --build . --target ${target}
     11                                     --config $<CONFIGURATION> PARENT_SCOPE)
     12   endif()
     13 endfunction()
     14 
     15 # llvm_ExternalProject_Add(name source_dir ...
     16 #   USE_TOOLCHAIN
     17 #     Use just-built tools (see TOOLCHAIN_TOOLS)
     18 #   EXCLUDE_FROM_ALL
     19 #     Exclude this project from the all target
     20 #   NO_INSTALL
     21 #     Don't generate install targets for this project
     22 #   CMAKE_ARGS arguments...
     23 #     Optional cmake arguments to pass when configuring the project
     24 #   TOOLCHAIN_TOOLS targets...
     25 #     Targets for toolchain tools (defaults to clang;lld)
     26 #   DEPENDS targets...
     27 #     Targets that this project depends on
     28 #   EXTRA_TARGETS targets...
     29 #     Extra targets in the subproject to generate targets for
     30 #   )
     31 function(llvm_ExternalProject_Add name source_dir)
     32   cmake_parse_arguments(ARG "USE_TOOLCHAIN;EXCLUDE_FROM_ALL;NO_INSTALL"
     33     "SOURCE_DIR"
     34     "CMAKE_ARGS;TOOLCHAIN_TOOLS;RUNTIME_LIBRARIES;DEPENDS;EXTRA_TARGETS" ${ARGN})
     35   canonicalize_tool_name(${name} nameCanon)
     36   if(NOT ARG_TOOLCHAIN_TOOLS)
     37     set(ARG_TOOLCHAIN_TOOLS clang lld)
     38   endif()
     39   foreach(tool ${ARG_TOOLCHAIN_TOOLS})
     40     if(TARGET ${tool})
     41       list(APPEND TOOLCHAIN_TOOLS ${tool})
     42       list(APPEND TOOLCHAIN_BINS $<TARGET_FILE:${tool}>)
     43     endif()
     44   endforeach()
     45 
     46   if(NOT ARG_RUNTIME_LIBRARIES)
     47     set(ARG_RUNTIME_LIBRARIES compiler-rt libcxx)
     48   endif()
     49   foreach(lib ${ARG_RUNTIME_LIBRARIES})
     50     if(TARGET ${lib})
     51       list(APPEND RUNTIME_LIBRARIES ${lib})
     52     endif()
     53   endforeach()
     54 
     55   list(FIND TOOLCHAIN_TOOLS clang FOUND_CLANG)
     56   if(FOUND_CLANG GREATER -1)
     57     set(CLANG_IN_TOOLCHAIN On)
     58   endif()
     59 
     60   if(RUNTIME_LIBRARIES AND CLANG_IN_TOOLCHAIN)
     61     list(APPEND TOOLCHAIN_BINS ${RUNTIME_LIBRARIES})
     62   endif()
     63 
     64   if(CMAKE_VERSION VERSION_GREATER 3.1.0)
     65     set(cmake_3_1_EXCLUDE_FROM_ALL EXCLUDE_FROM_ALL 1)
     66   endif()
     67 
     68   if(CMAKE_VERSION VERSION_GREATER 3.3.20150708)
     69     set(cmake_3_4_USES_TERMINAL_OPTIONS
     70       USES_TERMINAL_CONFIGURE 1
     71       USES_TERMINAL_BUILD 1
     72       USES_TERMINAL_INSTALL 1
     73       )
     74     set(cmake_3_4_USES_TERMINAL USES_TERMINAL 1)
     75   endif()
     76 
     77   if(CMAKE_VERSION VERSION_GREATER 3.1.20141116)
     78     set(cmake_3_2_USES_TERMINAL USES_TERMINAL)
     79   endif()
     80 
     81   set(STAMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/${name}-stamps/)
     82   set(BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${name}-bins/)
     83 
     84   add_custom_target(${name}-clear
     85     COMMAND ${CMAKE_COMMAND} -E remove_directory ${BINARY_DIR}
     86     COMMAND ${CMAKE_COMMAND} -E remove_directory ${STAMP_DIR}
     87     COMMENT "Clobbering ${name} build and stamp directories"
     88     ${cmake_3_2_USES_TERMINAL}
     89     )
     90 
     91   # Find all variables that start with COMPILER_RT and populate a variable with
     92   # them.
     93   get_cmake_property(variableNames VARIABLES)
     94   foreach(variableName ${variableNames})
     95     if(variableName MATCHES "^${nameCanon}")
     96       string(REPLACE ";" "\;" value "${${variableName}}")
     97       list(APPEND PASSTHROUGH_VARIABLES
     98         -D${variableName}=${value})
     99     endif()
    100   endforeach()
    101 
    102   if(ARG_USE_TOOLCHAIN)
    103     if(CLANG_IN_TOOLCHAIN)
    104       set(compiler_args -DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang
    105                         -DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++)
    106     endif()
    107     list(APPEND ARG_DEPENDS ${TOOLCHAIN_TOOLS})
    108   endif()
    109 
    110   add_custom_command(
    111     OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
    112     DEPENDS ${ARG_DEPENDS}
    113     COMMAND ${CMAKE_COMMAND} -E touch ${BINARY_DIR}/CMakeCache.txt
    114     COMMAND ${CMAKE_COMMAND} -E touch ${STAMP_DIR}/${name}-mkdir
    115     COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
    116     COMMENT "Clobbering bootstrap build and stamp directories"
    117     )
    118 
    119   add_custom_target(${name}-clobber
    120     DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
    121 
    122   if(ARG_EXCLUDE_FROM_ALL)
    123     set(exclude ${cmake_3_1_EXCLUDE_FROM_ALL})
    124   endif()
    125 
    126   ExternalProject_Add(${name}
    127     DEPENDS ${ARG_DEPENDS}
    128     ${name}-clobber
    129     PREFIX ${CMAKE_BINARY_DIR}/projects/${name}
    130     SOURCE_DIR ${source_dir}
    131     STAMP_DIR ${STAMP_DIR}
    132     BINARY_DIR ${BINARY_DIR}
    133     ${exclude}
    134     CMAKE_ARGS ${${nameCanon}_CMAKE_ARGS}
    135                ${compiler_args}
    136                -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
    137                ${ARG_CMAKE_ARGS}
    138                ${PASSTHROUGH_VARIABLES}
    139     INSTALL_COMMAND ""
    140     STEP_TARGETS configure build
    141     ${cmake_3_4_USES_TERMINAL_OPTIONS}
    142     )
    143 
    144   if(ARG_USE_TOOLCHAIN)
    145     ExternalProject_Add_Step(${name} force-rebuild
    146       COMMENT "Forcing rebuild becaues tools have changed"
    147       DEPENDERS configure
    148       DEPENDS ${TOOLCHAIN_BINS}
    149       ${cmake_3_4_USES_TERMINAL} )
    150   endif()
    151 
    152   if(ARG_USE_TOOLCHAIN)
    153     set(force_deps DEPENDS ${TOOLCHAIN_BINS})
    154   endif()
    155 
    156   llvm_ExternalProject_BuildCmd(run_clean clean)
    157   ExternalProject_Add_Step(${name} clean
    158     COMMAND ${run_clean}
    159     COMMENT "Cleaning ${name}..."
    160     DEPENDEES configure
    161     ${force_deps}
    162     WORKING_DIRECTORY ${BINARY_DIR}
    163     ${cmake_3_4_USES_TERMINAL}
    164     )
    165   ExternalProject_Add_StepTargets(${name} clean)
    166 
    167   if(ARG_USE_TOOLCHAIN)
    168     add_dependencies(${name}-clean ${name}-clobber)
    169     set_target_properties(${name}-clean PROPERTIES
    170       SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
    171   endif()
    172 
    173   if(NOT ARG_NO_INSTALL)
    174     install(CODE "execute_process\(COMMAND \${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=\${CMAKE_INSTALL_PREFIX} -P ${BINARY_DIR}/cmake_install.cmake \)"
    175       COMPONENT ${name})
    176 
    177     add_custom_target(install-${name}
    178                       DEPENDS ${name}
    179                       COMMAND "${CMAKE_COMMAND}"
    180                                -DCMAKE_INSTALL_COMPONENT=${name}
    181                                -P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
    182                       ${cmake_3_2_USES_TERMINAL})
    183   endif()
    184 
    185   # Add top-level targets
    186   foreach(target ${ARG_EXTRA_TARGETS})
    187     llvm_ExternalProject_BuildCmd(build_runtime_cmd ${target})
    188     add_custom_target(${target}
    189       COMMAND ${build_runtime_cmd}
    190       DEPENDS ${name}-configure
    191       WORKING_DIRECTORY ${BINARY_DIR}
    192       VERBATIM
    193       ${cmake_3_2_USES_TERMINAL})
    194   endforeach()
    195 endfunction()
    196