xref: /llvm-project/llvm/cmake/modules/LLVMExternalProjectUtils.cmake (revision 6655c53ff02f0ffca0fcaa3261e14c2a6417d3da)
1include(ExternalProject)
2
3# llvm_ExternalProject_BuildCmd(out_var target)
4#   Utility function for constructing command lines for external project targets
5function(llvm_ExternalProject_BuildCmd out_var target bin_dir stamp_dir)
6  cmake_parse_arguments(ARG "" "CONFIGURATION" "" ${ARGN})
7  if(NOT ARG_CONFIGURATION)
8    set(ARG_CONFIGURATION "$<CONFIG>")
9  endif()
10  if (CMAKE_GENERATOR MATCHES "Make")
11    # Use special command for Makefiles to support parallelism.
12    string(JOIN "@" make_cmd "$(MAKE)" "-C" "${bin_dir}" "${target}")
13    set(file_lock_script "${LLVM_CMAKE_DIR}/FileLock.cmake")
14    set(${out_var} ${CMAKE_COMMAND} "-DLOCK_FILE_PATH=${stamp_dir}/cmake.lock"
15                                    "-DCOMMAND=${make_cmd}"
16                                    "-P" "${file_lock_script}" PARENT_SCOPE)
17  else()
18    set(tool_args "${LLVM_EXTERNAL_PROJECT_BUILD_TOOL_ARGS}")
19    if(NOT tool_args STREQUAL "")
20      string(CONFIGURE "${tool_args}" tool_args @ONLY)
21      string(PREPEND tool_args "-- ")
22      separate_arguments(tool_args UNIX_COMMAND "${tool_args}")
23    endif()
24    set(${out_var} ${CMAKE_COMMAND} --build ${bin_dir} --target ${target}
25                                    --config ${ARG_CONFIGURATION} ${tool_args} PARENT_SCOPE)
26  endif()
27endfunction()
28
29# is_msvc_triple(out_var triple)
30#   Checks whether the passed triple refers to an MSVC environment
31function(is_msvc_triple out_var triple)
32  if (triple MATCHES ".*-windows-msvc.*")
33    set(${out_var} TRUE PARENT_SCOPE)
34  else()
35    set(${out_var} FALSE PARENT_SCOPE)
36  endif()
37endfunction()
38
39
40# llvm_ExternalProject_Add(name source_dir ...
41#   USE_TOOLCHAIN
42#     Use just-built tools (see TOOLCHAIN_TOOLS)
43#   EXCLUDE_FROM_ALL
44#     Exclude this project from the all target
45#   NO_INSTALL
46#     Don't generate install targets for this project
47#   ALWAYS_CLEAN
48#     Always clean the sub-project before building
49#   CMAKE_ARGS arguments...
50#     Optional cmake arguments to pass when configuring the project
51#   TOOLCHAIN_TOOLS targets...
52#     Targets for toolchain tools (defaults to clang;lld)
53#   DEPENDS targets...
54#     Targets that this project depends on
55#   EXTRA_TARGETS targets...
56#     Extra targets in the subproject to generate targets for
57#   PASSTHROUGH_PREFIXES prefix...
58#     Extra variable prefixes (name is always included) to pass down
59#   STRIP_TOOL path
60#     Use provided strip tool instead of the default one.
61#   TARGET_TRIPLE triple
62#     Optional target triple to pass to the compiler
63#   FOLDER
64#     For IDEs, the Folder to put the targets into.
65#   )
66function(llvm_ExternalProject_Add name source_dir)
67  cmake_parse_arguments(ARG
68    "USE_TOOLCHAIN;EXCLUDE_FROM_ALL;NO_INSTALL;ALWAYS_CLEAN"
69    "SOURCE_DIR;FOLDER"
70    "CMAKE_ARGS;TOOLCHAIN_TOOLS;RUNTIME_LIBRARIES;DEPENDS;EXTRA_TARGETS;PASSTHROUGH_PREFIXES;STRIP_TOOL;TARGET_TRIPLE"
71    ${ARGN})
72  canonicalize_tool_name(${name} nameCanon)
73
74  foreach(arg ${ARG_CMAKE_ARGS})
75    if(arg MATCHES "^-DCMAKE_SYSTEM_NAME=")
76      string(REGEX REPLACE "^-DCMAKE_SYSTEM_NAME=(.*)$" "\\1" _cmake_system_name "${arg}")
77    endif()
78  endforeach()
79
80  # If CMAKE_SYSTEM_NAME is not set explicitly in the arguments passed to us,
81  # reflect CMake's own default.
82  if (NOT _cmake_system_name)
83    set(_cmake_system_name "${CMAKE_HOST_SYSTEM_NAME}")
84  endif()
85
86  if(NOT ARG_TARGET_TRIPLE)
87    set(target_triple ${LLVM_DEFAULT_TARGET_TRIPLE})
88  else()
89    set(target_triple ${ARG_TARGET_TRIPLE})
90  endif()
91
92  is_msvc_triple(is_msvc_target "${target_triple}")
93
94  if(NOT ARG_TOOLCHAIN_TOOLS)
95    set(ARG_TOOLCHAIN_TOOLS clang)
96    # AIX 64-bit XCOFF and big AR format is not yet supported in some of these tools.
97    if(NOT _cmake_system_name STREQUAL AIX)
98      list(APPEND ARG_TOOLCHAIN_TOOLS lld llvm-ar llvm-ranlib llvm-nm llvm-objdump)
99      if(_cmake_system_name STREQUAL Darwin)
100        list(APPEND ARG_TOOLCHAIN_TOOLS llvm-libtool-darwin llvm-lipo)
101      elseif(is_msvc_target)
102        list(APPEND ARG_TOOLCHAIN_TOOLS llvm-lib llvm-rc)
103        if (LLVM_ENABLE_LIBXML2)
104          list(APPEND ARG_TOOLCHAIN_TOOLS llvm-mt)
105        endif()
106      else()
107        # TODO: These tools don't fully support Mach-O format yet.
108        list(APPEND ARG_TOOLCHAIN_TOOLS llvm-objcopy llvm-strip llvm-readelf)
109      endif()
110    endif()
111  endif()
112  foreach(tool ${ARG_TOOLCHAIN_TOOLS})
113    if(TARGET ${tool})
114      list(APPEND TOOLCHAIN_TOOLS ${tool})
115
116      # $<TARGET_FILE:tgt> only works on add_executable or add_library targets
117      # The below logic mirrors cmake's own implementation
118      get_target_property(target_type "${tool}" TYPE)
119      if(NOT target_type STREQUAL "OBJECT_LIBRARY" AND
120         NOT target_type STREQUAL "UTILITY" AND
121         NOT target_type STREQUAL "GLOBAL_TARGET" AND
122         NOT target_type STREQUAL "INTERFACE_LIBRARY")
123        list(APPEND TOOLCHAIN_BINS $<TARGET_FILE:${tool}>)
124      endif()
125
126    endif()
127  endforeach()
128
129  if(NOT ARG_RUNTIME_LIBRARIES)
130    set(ARG_RUNTIME_LIBRARIES compiler-rt libcxx)
131  endif()
132  foreach(lib ${ARG_RUNTIME_LIBRARIES})
133    if(TARGET ${lib})
134      list(APPEND RUNTIME_LIBRARIES ${lib})
135    endif()
136  endforeach()
137
138  if(ARG_ALWAYS_CLEAN)
139    set(always_clean clean)
140  endif()
141
142  if(clang IN_LIST TOOLCHAIN_TOOLS)
143    set(CLANG_IN_TOOLCHAIN On)
144  endif()
145
146  if(RUNTIME_LIBRARIES AND CLANG_IN_TOOLCHAIN)
147    list(APPEND TOOLCHAIN_BINS ${RUNTIME_LIBRARIES})
148  endif()
149
150  set(STAMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/${name}-stamps/)
151  set(BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${name}-bins/)
152
153  add_custom_target(${name}-clear
154    COMMAND ${CMAKE_COMMAND} -E remove_directory ${BINARY_DIR}
155    COMMAND ${CMAKE_COMMAND} -E remove_directory ${STAMP_DIR}
156    COMMENT "Clobbering ${name} build and stamp directories"
157    USES_TERMINAL
158    )
159  if (ARG_FOLDER)
160    set_target_properties(${name}-clear PROPERTIES FOLDER "${ARG_FOLDER}")
161  endif ()
162
163  set(DEFAULT_PASSTHROUGH_VARIABLES
164    LibEdit_INCLUDE_DIRS
165    LibEdit_LIBRARIES
166    ZLIB_INCLUDE_DIR
167    ZLIB_LIBRARY
168    zstd_INCLUDE_DIR
169    zstd_LIBRARY
170    LIBXML2_LIBRARY
171    LIBXML2_INCLUDE_DIR
172    CURL_INCLUDE_DIR
173    CURL_LIBRARY
174    HTTPLIB_INCLUDE_DIR
175    HTTPLIB_HEADER_PATH
176    Python3_EXECUTABLE
177    Python3_LIBRARIES
178    Python3_INCLUDE_DIRS
179    Python3_RPATH
180    )
181  foreach(variable ${DEFAULT_PASSTHROUGH_VARIABLES})
182    get_property(is_value_set CACHE ${variable} PROPERTY VALUE SET)
183    if(${is_value_set})
184      get_property(value CACHE ${variable} PROPERTY VALUE)
185      list(APPEND CMAKE_CACHE_DEFAULT_ARGS "-D${variable}:STRING=${value}")
186    endif()
187  endforeach()
188
189  # Find all variables that start with a prefix and propagate them through
190  get_cmake_property(variableNames VARIABLES)
191
192  list(APPEND ARG_PASSTHROUGH_PREFIXES ${nameCanon})
193  foreach(prefix ${ARG_PASSTHROUGH_PREFIXES})
194    foreach(variableName ${variableNames})
195      if(variableName MATCHES "^${prefix}")
196        string(REPLACE ";" "|" value "${${variableName}}")
197        list(APPEND PASSTHROUGH_VARIABLES
198          -D${variableName}=${value})
199      endif()
200    endforeach()
201  endforeach()
202
203  # Populate the non-project-specific passthrough variables
204  foreach(variableName ${LLVM_EXTERNAL_PROJECT_PASSTHROUGH})
205    if(DEFINED ${variableName})
206      if("${${variableName}}" STREQUAL "")
207        set(value "")
208      else()
209        string(REPLACE ";" "|" value "${${variableName}}")
210      endif()
211      list(APPEND PASSTHROUGH_VARIABLES
212        -D${variableName}=${value})
213    endif()
214  endforeach()
215
216  if(ARG_USE_TOOLCHAIN AND NOT CMAKE_CROSSCOMPILING)
217    if(CLANG_IN_TOOLCHAIN)
218      if(is_msvc_target)
219        set(compiler_args -DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang-cl${CMAKE_EXECUTABLE_SUFFIX}
220                          -DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang-cl${CMAKE_EXECUTABLE_SUFFIX}
221                          -DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang-cl${CMAKE_EXECUTABLE_SUFFIX})
222      else()
223        set(compiler_args -DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang${CMAKE_EXECUTABLE_SUFFIX}
224                          -DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++${CMAKE_EXECUTABLE_SUFFIX}
225                          -DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang${CMAKE_EXECUTABLE_SUFFIX})
226      endif()
227    endif()
228    if(lld IN_LIST TOOLCHAIN_TOOLS)
229      if(is_msvc_target)
230        list(APPEND compiler_args -DCMAKE_LINKER=${LLVM_RUNTIME_OUTPUT_INTDIR}/lld-link${CMAKE_EXECUTABLE_SUFFIX})
231      elseif(NOT _cmake_system_name STREQUAL Darwin)
232        list(APPEND compiler_args -DCMAKE_LINKER=${LLVM_RUNTIME_OUTPUT_INTDIR}/ld.lld${CMAKE_EXECUTABLE_SUFFIX})
233      endif()
234    endif()
235    if(llvm-ar IN_LIST TOOLCHAIN_TOOLS)
236      if(is_msvc_target)
237        list(APPEND compiler_args -DCMAKE_AR=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-lib${CMAKE_EXECUTABLE_SUFFIX})
238      else()
239        list(APPEND compiler_args -DCMAKE_AR=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ar${CMAKE_EXECUTABLE_SUFFIX})
240      endif()
241    endif()
242    if(llvm-libtool-darwin IN_LIST TOOLCHAIN_TOOLS)
243      list(APPEND compiler_args -DCMAKE_LIBTOOL=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-libtool-darwin${CMAKE_EXECUTABLE_SUFFIX})
244    endif()
245    if(llvm-lipo IN_LIST TOOLCHAIN_TOOLS)
246      list(APPEND compiler_args -DCMAKE_LIPO=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-lipo${CMAKE_EXECUTABLE_SUFFIX})
247    endif()
248    if(llvm-ranlib IN_LIST TOOLCHAIN_TOOLS)
249      list(APPEND compiler_args -DCMAKE_RANLIB=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ranlib${CMAKE_EXECUTABLE_SUFFIX})
250    endif()
251    if(llvm-nm IN_LIST TOOLCHAIN_TOOLS)
252      list(APPEND compiler_args -DCMAKE_NM=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-nm${CMAKE_EXECUTABLE_SUFFIX})
253    endif()
254    if(llvm-objdump IN_LIST TOOLCHAIN_TOOLS)
255      list(APPEND compiler_args -DCMAKE_OBJDUMP=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-objdump${CMAKE_EXECUTABLE_SUFFIX})
256    endif()
257    if(llvm-objcopy IN_LIST TOOLCHAIN_TOOLS)
258      list(APPEND compiler_args -DCMAKE_OBJCOPY=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-objcopy${CMAKE_EXECUTABLE_SUFFIX})
259    endif()
260    if(llvm-strip IN_LIST TOOLCHAIN_TOOLS AND NOT ARG_STRIP_TOOL)
261      list(APPEND compiler_args -DCMAKE_STRIP=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-strip${CMAKE_EXECUTABLE_SUFFIX})
262    endif()
263    if(llvm-readelf IN_LIST TOOLCHAIN_TOOLS)
264      list(APPEND compiler_args -DCMAKE_READELF=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-readelf${CMAKE_EXECUTABLE_SUFFIX})
265    endif()
266    if(llvm-mt IN_LIST TOOLCHAIN_TOOLS AND is_msvc_target)
267      list(APPEND compiler_args -DCMAKE_MT=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-mt${CMAKE_EXECUTABLE_SUFFIX})
268    endif()
269    if(llvm-rc IN_LIST TOOLCHAIN_TOOLS AND is_msvc_target)
270      list(APPEND compiler_args -DCMAKE_RC_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-rc${CMAKE_EXECUTABLE_SUFFIX})
271    endif()
272    list(APPEND ARG_DEPENDS ${TOOLCHAIN_TOOLS})
273    # Add LLVMgold.so dependency if it is available, as clang may need it for
274    # LTO.
275    if(CLANG_IN_TOOLCHAIN AND TARGET LLVMgold)
276      list(APPEND ARG_DEPENDS LLVMgold)
277    endif()
278  endif()
279
280  if(ARG_STRIP_TOOL)
281    list(APPEND compiler_args -DCMAKE_STRIP=${ARG_STRIP_TOOL})
282  endif()
283
284  add_custom_command(
285    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
286    DEPENDS ${ARG_DEPENDS}
287    COMMAND ${CMAKE_COMMAND} -E touch ${BINARY_DIR}/CMakeCache.txt
288    COMMAND ${CMAKE_COMMAND} -E touch ${STAMP_DIR}/${name}-mkdir
289    COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
290    COMMENT "Clobbering bootstrap build and stamp directories"
291    )
292
293  add_custom_target(${name}-clobber
294    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
295  if (ARG_FOLDER)
296    set_target_properties(${name}-clobber PROPERTIES FOLDER "${ARG_FOLDER}")
297  endif ()
298
299  if(ARG_EXCLUDE_FROM_ALL)
300    set(exclude EXCLUDE_FROM_ALL 1)
301  endif()
302
303  if(CMAKE_SYSROOT)
304    set(sysroot_arg -DCMAKE_SYSROOT=${CMAKE_SYSROOT})
305  endif()
306
307  if(CMAKE_CROSSCOMPILING)
308    set(compiler_args -DCMAKE_ASM_COMPILER=${CMAKE_ASM_COMPILER}
309                      -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
310                      -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
311                      -DCMAKE_LINKER=${CMAKE_LINKER}
312                      -DCMAKE_AR=${CMAKE_AR}
313                      -DCMAKE_RANLIB=${CMAKE_RANLIB}
314                      -DCMAKE_NM=${CMAKE_NM}
315                      -DCMAKE_OBJCOPY=${CMAKE_OBJCOPY}
316                      -DCMAKE_OBJDUMP=${CMAKE_OBJDUMP}
317                      -DCMAKE_STRIP=${CMAKE_STRIP}
318                      -DCMAKE_READELF=${CMAKE_READELF})
319    set(llvm_config_path ${LLVM_CONFIG_PATH})
320
321    if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
322      string(REGEX MATCH "^[0-9]+" CLANG_VERSION_MAJOR
323             ${PACKAGE_VERSION})
324      if(DEFINED CLANG_RESOURCE_DIR AND NOT CLANG_RESOURCE_DIR STREQUAL "")
325        set(resource_dir ${LLVM_TOOLS_BINARY_DIR}/${CLANG_RESOURCE_DIR})
326      else()
327        set(resource_dir "${LLVM_LIBRARY_DIR}/clang/${CLANG_VERSION_MAJOR}")
328      endif()
329      set(flag_types ASM C CXX MODULE_LINKER SHARED_LINKER EXE_LINKER)
330      foreach(type ${flag_types})
331        set(${type}_flag -DCMAKE_${type}_FLAGS_INIT=-resource-dir=${resource_dir})
332      endforeach()
333      string(REPLACE ";" "|" flag_string "${flag_types}")
334      foreach(arg ${ARG_CMAKE_ARGS})
335        if(arg MATCHES "^-DCMAKE_(${flag_string})_FLAGS")
336          foreach(type ${flag_types})
337            if(arg MATCHES "^-DCMAKE_${type}_FLAGS")
338              string(REGEX REPLACE "^-DCMAKE_${type}_FLAGS=(.*)$" "\\1" flag_value "${arg}")
339              set(${type}_flag "${${type}_flag} ${flag_value}")
340            endif()
341          endforeach()
342        else()
343          list(APPEND cmake_args ${arg})
344        endif()
345      endforeach()
346      foreach(type ${flag_types})
347        list(APPEND cmake_args ${${type}_flag})
348      endforeach()
349    else()
350      set(cmake_args ${ARG_CMAKE_ARGS})
351    endif()
352  else()
353    set(llvm_config_path "$<TARGET_FILE:llvm-config>")
354    set(cmake_args ${ARG_CMAKE_ARGS})
355  endif()
356
357  if(ARG_TARGET_TRIPLE)
358    list(APPEND compiler_args -DCMAKE_C_COMPILER_TARGET=${ARG_TARGET_TRIPLE})
359    list(APPEND compiler_args -DCMAKE_CXX_COMPILER_TARGET=${ARG_TARGET_TRIPLE})
360    list(APPEND compiler_args -DCMAKE_ASM_COMPILER_TARGET=${ARG_TARGET_TRIPLE})
361  endif()
362
363  if(CMAKE_VERBOSE_MAKEFILE)
364    set(verbose -DCMAKE_VERBOSE_MAKEFILE=ON)
365  endif()
366
367  ExternalProject_Add(${name}
368    DEPENDS ${ARG_DEPENDS} llvm-config
369    ${name}-clobber
370    PREFIX ${CMAKE_BINARY_DIR}/projects/${name}
371    SOURCE_DIR ${source_dir}
372    STAMP_DIR ${STAMP_DIR}
373    BINARY_DIR ${BINARY_DIR}
374    ${exclude}
375    CMAKE_ARGS ${${nameCanon}_CMAKE_ARGS}
376               --no-warn-unused-cli
377               ${compiler_args}
378               ${verbose}
379               -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
380               ${sysroot_arg}
381               -DLLVM_BINARY_DIR=${PROJECT_BINARY_DIR}
382               -DLLVM_CONFIG_PATH=${llvm_config_path}
383               -DLLVM_ENABLE_WERROR=${LLVM_ENABLE_WERROR}
384               -DLLVM_HOST_TRIPLE=${LLVM_HOST_TRIPLE}
385               -DLLVM_HAVE_LINK_VERSION_SCRIPT=${LLVM_HAVE_LINK_VERSION_SCRIPT}
386               -DLLVM_USE_RELATIVE_PATHS_IN_DEBUG_INFO=${LLVM_USE_RELATIVE_PATHS_IN_DEBUG_INFO}
387               -DLLVM_USE_RELATIVE_PATHS_IN_FILES=${LLVM_USE_RELATIVE_PATHS_IN_FILES}
388               -DLLVM_LIT_ARGS=${LLVM_LIT_ARGS}
389               -DLLVM_SOURCE_PREFIX=${LLVM_SOURCE_PREFIX}
390               -DPACKAGE_VERSION=${PACKAGE_VERSION}
391               -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
392               -DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}
393               -DCMAKE_EXPORT_COMPILE_COMMANDS=1
394               ${cmake_args}
395               ${PASSTHROUGH_VARIABLES}
396    CMAKE_CACHE_DEFAULT_ARGS ${CMAKE_CACHE_DEFAULT_ARGS}
397    INSTALL_COMMAND ""
398    STEP_TARGETS configure build
399    BUILD_ALWAYS 1
400    USES_TERMINAL_CONFIGURE 1
401    USES_TERMINAL_BUILD 1
402    USES_TERMINAL_INSTALL 1
403    LIST_SEPARATOR |
404    )
405  if (ARG_FOLDER)
406    set_target_properties(
407      ${name} ${name}-clobber ${name}-build ${name}-configure
408      PROPERTIES FOLDER "${ARG_FOLDER}"
409    )
410  endif ()
411
412  if(ARG_USE_TOOLCHAIN)
413    set(force_deps DEPENDS ${TOOLCHAIN_BINS})
414  endif()
415
416  llvm_ExternalProject_BuildCmd(run_clean clean ${BINARY_DIR} ${STAMP_DIR})
417  ExternalProject_Add_Step(${name} clean
418    COMMAND ${run_clean}
419    COMMENT "Cleaning ${name}..."
420    DEPENDEES configure
421    ${force_deps}
422    WORKING_DIRECTORY ${BINARY_DIR}
423    EXCLUDE_FROM_MAIN 1
424    USES_TERMINAL 1
425    )
426  ExternalProject_Add_StepTargets(${name} clean)
427  if (ARG_FOLDER)
428    set_target_properties(${name}-clean PROPERTIES FOLDER "${ARG_FOLDER}")
429  endif ()
430
431  if(ARG_USE_TOOLCHAIN)
432    add_dependencies(${name}-clean ${name}-clobber)
433    set_target_properties(${name}-clean PROPERTIES
434      SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
435  endif()
436
437  if(NOT ARG_NO_INSTALL)
438    install(CODE "execute_process\(COMMAND \${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=\${CMAKE_INSTALL_PREFIX} -DCMAKE_INSTALL_DO_STRIP=\${CMAKE_INSTALL_DO_STRIP} -P ${BINARY_DIR}/cmake_install.cmake\)"
439      COMPONENT ${name})
440
441    add_llvm_install_targets(install-${name}
442                             DEPENDS ${name}
443                             COMPONENT ${name})
444    if (ARG_FOLDER)
445       set_target_properties(install-${name} PROPERTIES FOLDER "${ARG_FOLDER}")
446    endif ()
447  endif()
448
449  # Add top-level targets
450  foreach(target ${ARG_EXTRA_TARGETS})
451    if(DEFINED ${target})
452      set(external_target "${${target}}")
453    else()
454      set(external_target "${target}")
455    endif()
456    llvm_ExternalProject_BuildCmd(build_runtime_cmd ${external_target} ${BINARY_DIR} ${STAMP_DIR})
457    add_custom_target(${target}
458      COMMAND ${build_runtime_cmd}
459      DEPENDS ${name}-configure
460      WORKING_DIRECTORY ${BINARY_DIR}
461      VERBATIM
462      USES_TERMINAL)
463    if (ARG_FOLDER)
464      set_target_properties(${target} PROPERTIES FOLDER "${ARG_FOLDER}")
465    endif ()
466  endforeach()
467endfunction()
468