[RISCV] Refactor predicates for rvv intrinsic patterns.
[llvm-project.git] / compiler-rt / cmake / Modules / AddCompilerRT.cmake
blob752ce2ff1c8f576932a42b4102c1790c92ad0dcb
1 include(ExternalProject)
2 include(CompilerRTUtils)
3 include(HandleCompilerRT)
5 # CMP0114: ExternalProject step targets fully adopt their steps.
6 # New in CMake 3.19: https://cmake.org/cmake/help/latest/policy/CMP0114.html
7 if(POLICY CMP0114)
8   cmake_policy(SET CMP0114 OLD)
9 endif()
11 function(set_target_output_directories target output_dir)
12   # For RUNTIME_OUTPUT_DIRECTORY variable, Multi-configuration generators
13   # append a per-configuration subdirectory to the specified directory.
14   # To avoid the appended folder, the configuration specific variable must be
15   # set 'RUNTIME_OUTPUT_DIRECTORY_${CONF}':
16   # RUNTIME_OUTPUT_DIRECTORY_DEBUG, RUNTIME_OUTPUT_DIRECTORY_RELEASE, ...
17   if(CMAKE_CONFIGURATION_TYPES)
18     foreach(build_mode ${CMAKE_CONFIGURATION_TYPES})
19       string(TOUPPER "${build_mode}" CONFIG_SUFFIX)
20       set_target_properties("${target}" PROPERTIES
21           "ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_SUFFIX}" ${output_dir}
22           "LIBRARY_OUTPUT_DIRECTORY_${CONFIG_SUFFIX}" ${output_dir}
23           "RUNTIME_OUTPUT_DIRECTORY_${CONFIG_SUFFIX}" ${output_dir})
24     endforeach()
25   else()
26     set_target_properties("${target}" PROPERTIES
27         ARCHIVE_OUTPUT_DIRECTORY ${output_dir}
28         LIBRARY_OUTPUT_DIRECTORY ${output_dir}
29         RUNTIME_OUTPUT_DIRECTORY ${output_dir})
30   endif()
31 endfunction()
33 # Tries to add an "object library" target for a given list of OSs and/or
34 # architectures with name "<name>.<arch>" for non-Darwin platforms if
35 # architecture can be targeted, and "<name>.<os>" for Darwin platforms.
36 # add_compiler_rt_object_libraries(<name>
37 #                                  OS <os names>
38 #                                  ARCHS <architectures>
39 #                                  SOURCES <source files>
40 #                                  CFLAGS <compile flags>
41 #                                  DEFS <compile definitions>
42 #                                  DEPS <dependencies>
43 #                                  ADDITIONAL_HEADERS <header files>)
44 function(add_compiler_rt_object_libraries name)
45   cmake_parse_arguments(LIB "" "" "OS;ARCHS;SOURCES;CFLAGS;DEFS;DEPS;ADDITIONAL_HEADERS"
46     ${ARGN})
47   set(libnames)
48   if(APPLE)
49     foreach(os ${LIB_OS})
50       set(libname "${name}.${os}")
51       set(libnames ${libnames} ${libname})
52       set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS})
53       list_intersect(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS)
54     endforeach()
55   else()
56     foreach(arch ${LIB_ARCHS})
57       set(libname "${name}.${arch}")
58       set(libnames ${libnames} ${libname})
59       set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS})
60       if(NOT CAN_TARGET_${arch})
61         message(FATAL_ERROR "Architecture ${arch} can't be targeted")
62         return()
63       endif()
64     endforeach()
65   endif()
67   # Add headers to LIB_SOURCES for IDEs
68   compiler_rt_process_sources(LIB_SOURCES
69     ${LIB_SOURCES}
70     ADDITIONAL_HEADERS
71       ${LIB_ADDITIONAL_HEADERS}
72   )
74   foreach(libname ${libnames})
75     add_library(${libname} OBJECT ${LIB_SOURCES})
76     if(LIB_DEPS)
77       add_dependencies(${libname} ${LIB_DEPS})
78     endif()
80     # Strip out -msse3 if this isn't macOS.
81     set(target_flags ${LIB_CFLAGS})
82     if(APPLE AND NOT "${libname}" MATCHES ".*\.osx.*")
83       list(REMOVE_ITEM target_flags "-msse3")
84     endif()
86     # Build the macOS sanitizers with Mac Catalyst support.
87     if (APPLE AND
88         "${COMPILER_RT_ENABLE_MACCATALYST}" AND
89         "${libname}" MATCHES ".*\.osx.*")
90       foreach(arch ${LIB_ARCHS_${libname}})
91         list(APPEND target_flags
92           "SHELL:-target ${arch}-apple-macos${DARWIN_osx_MIN_VER} -darwin-target-variant ${arch}-apple-ios13.1-macabi")
93       endforeach()
94     endif()
96     set_target_compile_flags(${libname}
97       ${extra_cflags_${libname}} ${target_flags})
98     set_property(TARGET ${libname} APPEND PROPERTY
99       COMPILE_DEFINITIONS ${LIB_DEFS})
100     set_target_properties(${libname} PROPERTIES FOLDER "Compiler-RT Libraries")
101     if(APPLE)
102       set_target_properties(${libname} PROPERTIES
103         OSX_ARCHITECTURES "${LIB_ARCHS_${libname}}")
104     endif()
105   endforeach()
106 endfunction()
108 # Takes a list of object library targets, and a suffix and appends the proper
109 # TARGET_OBJECTS string to the output variable.
110 # format_object_libs(<output> <suffix> ...)
111 macro(format_object_libs output suffix)
112   foreach(lib ${ARGN})
113     list(APPEND ${output} $<TARGET_OBJECTS:${lib}.${suffix}>)
114   endforeach()
115 endmacro()
117 function(add_compiler_rt_component name)
118   add_custom_target(${name})
119   set_target_properties(${name} PROPERTIES FOLDER "Compiler-RT Misc")
120   if(COMMAND runtime_register_component)
121     runtime_register_component(${name})
122   endif()
123   add_dependencies(compiler-rt ${name})
124 endfunction()
126 function(add_asm_sources output)
127   set(${output} ${ARGN} PARENT_SCOPE)
128   # CMake doesn't pass the correct architecture for Apple prior to CMake 3.19. https://gitlab.kitware.com/cmake/cmake/-/issues/20771
129   # MinGW didn't work correctly with assembly prior to CMake 3.17. https://gitlab.kitware.com/cmake/cmake/-/merge_requests/4287 and https://reviews.llvm.org/rGb780df052dd2b246a760d00e00f7de9ebdab9d09
130   # Workaround these two issues by compiling as C.
131   # Same workaround used in libunwind. Also update there if changed here.
132   if((APPLE AND CMAKE_VERSION VERSION_LESS 3.19) OR (MINGW AND CMAKE_VERSION VERSION_LESS 3.17))
133     set_source_files_properties(${ARGN} PROPERTIES LANGUAGE C)
134   endif()
135 endfunction()
137 macro(set_output_name output name arch)
138   if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
139     set(${output} ${name})
140   else()
141     if(ANDROID AND ${arch} STREQUAL "i386")
142       set(${output} "${name}-i686${COMPILER_RT_OS_SUFFIX}")
143     elseif("${arch}" MATCHES "^arm")
144       if(COMPILER_RT_DEFAULT_TARGET_ONLY)
145         set(triple "${COMPILER_RT_DEFAULT_TARGET_TRIPLE}")
146       else()
147         set(triple "${LLVM_TARGET_TRIPLE}")
148       endif()
149       # Except for baremetal, when using arch-suffixed runtime library names,
150       # clang only looks for libraries named "arm" or "armhf", see
151       # getArchNameForCompilerRTLib in clang. Therefore, try to inspect both
152       # the arch name and the triple if it seems like we're building an armhf
153       # target.
154       if (COMPILER_RT_BAREMETAL_BUILD)
155         set(${output} "${name}-${arch}${COMPILER_RT_OS_SUFFIX}")
156       elseif ("${arch}" MATCHES "hf$" OR "${triple}" MATCHES "hf$")
157         set(${output} "${name}-armhf${COMPILER_RT_OS_SUFFIX}")
158       else()
159         set(${output} "${name}-arm${COMPILER_RT_OS_SUFFIX}")
160       endif()
161     else()
162       set(${output} "${name}-${arch}${COMPILER_RT_OS_SUFFIX}")
163     endif()
164   endif()
165 endmacro()
167 # Adds static or shared runtime for a list of architectures and operating
168 # systems and puts it in the proper directory in the build and install trees.
169 # add_compiler_rt_runtime(<name>
170 #                         {OBJECT|STATIC|SHARED|MODULE}
171 #                         ARCHS <architectures>
172 #                         OS <os list>
173 #                         SOURCES <source files>
174 #                         CFLAGS <compile flags>
175 #                         LINK_FLAGS <linker flags>
176 #                         DEFS <compile definitions>
177 #                         DEPS <dependencies>
178 #                         LINK_LIBS <linked libraries> (only for shared library)
179 #                         OBJECT_LIBS <object libraries to use as sources>
180 #                         PARENT_TARGET <convenience parent target>
181 #                         ADDITIONAL_HEADERS <header files>)
182 function(add_compiler_rt_runtime name type)
183   if(NOT type MATCHES "^(OBJECT|STATIC|SHARED|MODULE)$")
184     message(FATAL_ERROR
185             "type argument must be OBJECT, STATIC, SHARED or MODULE")
186     return()
187   endif()
188   cmake_parse_arguments(LIB
189     ""
190     "PARENT_TARGET"
191     "OS;ARCHS;SOURCES;CFLAGS;LINK_FLAGS;DEFS;DEPS;LINK_LIBS;OBJECT_LIBS;ADDITIONAL_HEADERS"
192     ${ARGN})
193   set(libnames)
194   # Until we support this some other way, build compiler-rt runtime without LTO
195   # to allow non-LTO projects to link with it.
196   if(COMPILER_RT_HAS_FNO_LTO_FLAG)
197     set(NO_LTO_FLAGS "-fno-lto")
198   else()
199     set(NO_LTO_FLAGS "")
200   endif()
202   # By default do not instrument or use profdata for compiler-rt.
203   set(NO_PGO_FLAGS "")
204   if(NOT COMPILER_RT_ENABLE_PGO)
205     if(LLVM_PROFDATA_FILE AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_USE_FLAG)
206       list(APPEND NO_PGO_FLAGS "-fno-profile-instr-use")
207     endif()
208     if(LLVM_BUILD_INSTRUMENTED MATCHES IR AND COMPILER_RT_HAS_FNO_PROFILE_GENERATE_FLAG)
209       list(APPEND NO_PGO_FLAGS "-fno-profile-generate")
210     elseif((LLVM_BUILD_INSTRUMENTED OR LLVM_BUILD_INSTRUMENTED_COVERAGE) AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG)
211       list(APPEND NO_PGO_FLAGS "-fno-profile-instr-generate")
212       if(LLVM_BUILD_INSTRUMENTED_COVERAGE AND COMPILER_RT_HAS_FNO_COVERAGE_MAPPING_FLAG)
213         list(APPEND NO_PGO_FLAGS "-fno-coverage-mapping")
214       endif()
215     endif()
216   endif()
218   list(LENGTH LIB_SOURCES LIB_SOURCES_LENGTH)
219   if (${LIB_SOURCES_LENGTH} GREATER 0)
220     # Add headers to LIB_SOURCES for IDEs. It doesn't make sense to
221     # do this for a runtime library that only consists of OBJECT
222     # libraries, so only add the headers when source files are present.
223     compiler_rt_process_sources(LIB_SOURCES
224       ${LIB_SOURCES}
225       ADDITIONAL_HEADERS
226         ${LIB_ADDITIONAL_HEADERS}
227     )
228   endif()
230   if(APPLE)
231     foreach(os ${LIB_OS})
232       # Strip out -msse3 if this isn't macOS.
233       list(LENGTH LIB_CFLAGS HAS_EXTRA_CFLAGS)
234       if(HAS_EXTRA_CFLAGS AND NOT "${os}" MATCHES "^(osx)$")
235         list(REMOVE_ITEM LIB_CFLAGS "-msse3")
236       endif()
237       if(type STREQUAL "STATIC")
238         set(libname "${name}_${os}")
239       else()
240         set(libname "${name}_${os}_dynamic")
241         set(extra_link_flags_${libname} ${DARWIN_${os}_LINK_FLAGS} ${LIB_LINK_FLAGS})
242       endif()
243       list_intersect(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS)
244       if(LIB_ARCHS_${libname})
245         list(APPEND libnames ${libname})
246         set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS} ${NO_LTO_FLAGS} ${NO_PGO_FLAGS} ${LIB_CFLAGS})
247         set(output_name_${libname} ${libname}${COMPILER_RT_OS_SUFFIX})
248         set(sources_${libname} ${LIB_SOURCES})
249         format_object_libs(sources_${libname} ${os} ${LIB_OBJECT_LIBS})
250         get_compiler_rt_output_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} output_dir_${libname})
251         get_compiler_rt_install_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} install_dir_${libname})
252       endif()
254       # Build the macOS sanitizers with Mac Catalyst support.
255       if ("${COMPILER_RT_ENABLE_MACCATALYST}" AND
256           "${os}" MATCHES "^(osx)$")
257         foreach(arch ${LIB_ARCHS_${libname}})
258           list(APPEND extra_cflags_${libname}
259             "SHELL:-target ${arch}-apple-macos${DARWIN_osx_MIN_VER} -darwin-target-variant ${arch}-apple-ios13.1-macabi")
260           list(APPEND extra_link_flags_${libname}
261             "SHELL:-target ${arch}-apple-macos${DARWIN_osx_MIN_VER} -darwin-target-variant ${arch}-apple-ios13.1-macabi")
262         endforeach()
263       endif()
264     endforeach()
265   else()
266     foreach(arch ${LIB_ARCHS})
267       if(NOT CAN_TARGET_${arch})
268         message(FATAL_ERROR "Architecture ${arch} can't be targeted")
269         return()
270       endif()
271       if(type STREQUAL "OBJECT")
272         set(libname "${name}-${arch}")
273         set_output_name(output_name_${libname} ${name}${COMPILER_RT_OS_SUFFIX} ${arch})
274       elseif(type STREQUAL "STATIC")
275         set(libname "${name}-${arch}")
276         set_output_name(output_name_${libname} ${name} ${arch})
277       else()
278         set(libname "${name}-dynamic-${arch}")
279         set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS})
280         set(extra_link_flags_${libname} ${TARGET_${arch}_LINK_FLAGS} ${LIB_LINK_FLAGS})
281         if(WIN32)
282           set_output_name(output_name_${libname} ${name}_dynamic ${arch})
283         else()
284           set_output_name(output_name_${libname} ${name} ${arch})
285         endif()
286       endif()
287       if(COMPILER_RT_USE_BUILTINS_LIBRARY AND NOT type STREQUAL "OBJECT" AND
288          NOT name STREQUAL "clang_rt.builtins")
289         get_compiler_rt_target(${arch} target)
290         find_compiler_rt_library(builtins builtins_${libname} TARGET ${target})
291         if(builtins_${libname} STREQUAL "NOTFOUND")
292           message(FATAL_ERROR "Cannot find builtins library for the target architecture")
293         endif()
294       endif()
295       set(sources_${libname} ${LIB_SOURCES})
296       format_object_libs(sources_${libname} ${arch} ${LIB_OBJECT_LIBS})
297       set(libnames ${libnames} ${libname})
298       set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS} ${NO_LTO_FLAGS} ${NO_PGO_FLAGS} ${LIB_CFLAGS})
299       get_compiler_rt_output_dir(${arch} output_dir_${libname})
300       get_compiler_rt_install_dir(${arch} install_dir_${libname})
301     endforeach()
302   endif()
304   if(NOT libnames)
305     return()
306   endif()
308   if(LIB_PARENT_TARGET)
309     # If the parent targets aren't created we should create them
310     if(NOT TARGET ${LIB_PARENT_TARGET})
311       add_custom_target(${LIB_PARENT_TARGET})
312       set_target_properties(${LIB_PARENT_TARGET} PROPERTIES
313                             FOLDER "Compiler-RT Misc")
314     endif()
315   endif()
317   foreach(libname ${libnames})
318     # If you are using a multi-configuration generator we don't generate
319     # per-library install rules, so we fall back to the parent target COMPONENT
320     if(CMAKE_CONFIGURATION_TYPES AND LIB_PARENT_TARGET)
321       set(COMPONENT_OPTION COMPONENT ${LIB_PARENT_TARGET})
322     else()
323       set(COMPONENT_OPTION COMPONENT ${libname})
324     endif()
326     if(type STREQUAL "OBJECT")
327       if(CMAKE_C_COMPILER_ID MATCHES Clang AND CMAKE_C_COMPILER_TARGET)
328         list(APPEND extra_cflags_${libname} "--target=${CMAKE_C_COMPILER_TARGET}")
329       endif()
330       if(CMAKE_SYSROOT)
331         list(APPEND extra_cflags_${libname} "--sysroot=${CMAKE_SYSROOT}")
332       endif()
333       string(REPLACE ";" " " extra_cflags_${libname} "${extra_cflags_${libname}}")
334       string(REGEX MATCHALL "<[A-Za-z0-9_]*>" substitutions
335              ${CMAKE_C_COMPILE_OBJECT})
336       set(compile_command_${libname} "${CMAKE_C_COMPILE_OBJECT}")
338       set(output_file_${libname} ${output_name_${libname}}${CMAKE_C_OUTPUT_EXTENSION})
339       foreach(substitution ${substitutions})
340         if(substitution STREQUAL "<CMAKE_C_COMPILER>")
341           string(REPLACE "<CMAKE_C_COMPILER>" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}"
342                  compile_command_${libname} ${compile_command_${libname}})
343         elseif(substitution STREQUAL "<OBJECT>")
344           string(REPLACE "<OBJECT>" "${output_dir_${libname}}/${output_file_${libname}}"
345                  compile_command_${libname} ${compile_command_${libname}})
346         elseif(substitution STREQUAL "<SOURCE>")
347           string(REPLACE "<SOURCE>" "${sources_${libname}}"
348                  compile_command_${libname} ${compile_command_${libname}})
349         elseif(substitution STREQUAL "<FLAGS>")
350           string(REPLACE "<FLAGS>" "${CMAKE_C_FLAGS} ${extra_cflags_${libname}}"
351                  compile_command_${libname} ${compile_command_${libname}})
352         else()
353           string(REPLACE "${substitution}" "" compile_command_${libname}
354                  ${compile_command_${libname}})
355         endif()
356       endforeach()
357       separate_arguments(compile_command_${libname})
358       add_custom_command(
359           OUTPUT ${output_dir_${libname}}/${output_file_${libname}}
360           COMMAND ${compile_command_${libname}}
361           DEPENDS ${sources_${libname}}
362           COMMENT "Building C object ${output_file_${libname}}")
363       add_custom_target(${libname} DEPENDS ${output_dir_${libname}}/${output_file_${libname}})
364       install(FILES ${output_dir_${libname}}/${output_file_${libname}}
365         DESTINATION ${install_dir_${libname}}
366         ${COMPONENT_OPTION})
367     else()
368       add_library(${libname} ${type} ${sources_${libname}})
369       set_target_compile_flags(${libname} ${extra_cflags_${libname}})
370       set_target_link_flags(${libname} ${extra_link_flags_${libname}})
371       set_property(TARGET ${libname} APPEND PROPERTY
372                    COMPILE_DEFINITIONS ${LIB_DEFS})
373       set_target_output_directories(${libname} ${output_dir_${libname}})
374       install(TARGETS ${libname}
375         ARCHIVE DESTINATION ${install_dir_${libname}}
376                 ${COMPONENT_OPTION}
377         LIBRARY DESTINATION ${install_dir_${libname}}
378                 ${COMPONENT_OPTION}
379         RUNTIME DESTINATION ${install_dir_${libname}}
380                 ${COMPONENT_OPTION})
381     endif()
382     if(LIB_DEPS)
383       add_dependencies(${libname} ${LIB_DEPS})
384     endif()
385     set_target_properties(${libname} PROPERTIES
386         OUTPUT_NAME ${output_name_${libname}})
387     set_target_properties(${libname} PROPERTIES FOLDER "Compiler-RT Runtime")
388     if(LIB_LINK_LIBS)
389       target_link_libraries(${libname} PRIVATE ${LIB_LINK_LIBS})
390     endif()
391     if(builtins_${libname})
392       target_link_libraries(${libname} PRIVATE ${builtins_${libname}})
393     endif()
394     if(${type} STREQUAL "SHARED")
395       if(APPLE OR WIN32)
396         set_property(TARGET ${libname} PROPERTY BUILD_WITH_INSTALL_RPATH ON)
397       endif()
398       if(WIN32 AND NOT CYGWIN AND NOT MINGW)
399         set_target_properties(${libname} PROPERTIES IMPORT_PREFIX "")
400         set_target_properties(${libname} PROPERTIES IMPORT_SUFFIX ".lib")
401       endif()
402       if (APPLE AND NOT CMAKE_LINKER MATCHES ".*lld.*")
403         # Ad-hoc sign the dylibs when using Xcode versions older than 12.
404         # Xcode 12 shipped with ld64-609.
405         # FIXME: Remove whole conditional block once everything uses Xcode 12+.
406         set(LD_V_OUTPUT)
407         execute_process(
408           COMMAND sh -c "${CMAKE_LINKER} -v 2>&1 | head -1"
409           RESULT_VARIABLE HAD_ERROR
410           OUTPUT_VARIABLE LD_V_OUTPUT
411         )
412         if (HAD_ERROR)
413           message(FATAL_ERROR "${CMAKE_LINKER} failed with status ${HAD_ERROR}")
414         endif()
415         set(NEED_EXPLICIT_ADHOC_CODESIGN 1)
416         if ("${LD_V_OUTPUT}" MATCHES ".*ld64-([0-9.]+).*")
417           string(REGEX REPLACE ".*ld64-([0-9.]+).*" "\\1" HOST_LINK_VERSION ${LD_V_OUTPUT})
418           if (HOST_LINK_VERSION VERSION_GREATER_EQUAL 609)
419             set(NEED_EXPLICIT_ADHOC_CODESIGN 0)
420           endif()
421         endif()
422         if (NEED_EXPLICIT_ADHOC_CODESIGN)
423           add_custom_command(TARGET ${libname}
424             POST_BUILD
425             COMMAND codesign --sign - $<TARGET_FILE:${libname}>
426             WORKING_DIRECTORY ${COMPILER_RT_OUTPUT_LIBRARY_DIR}
427           )
428         endif()
429       endif()
430     endif()
432     set(parent_target_arg)
433     if(LIB_PARENT_TARGET)
434       set(parent_target_arg PARENT_TARGET ${LIB_PARENT_TARGET})
435     endif()
436     add_compiler_rt_install_targets(${libname} ${parent_target_arg})
438     if(APPLE)
439       set_target_properties(${libname} PROPERTIES
440       OSX_ARCHITECTURES "${LIB_ARCHS_${libname}}")
441     endif()
443     if(type STREQUAL "SHARED")
444       rt_externalize_debuginfo(${libname})
445     endif()
446   endforeach()
447   if(LIB_PARENT_TARGET)
448     add_dependencies(${LIB_PARENT_TARGET} ${libnames})
449   endif()
450 endfunction()
452 # Compile and register compiler-rt tests.
453 # generate_compiler_rt_tests(<output object files> <test_suite> <test_name>
454 #                           <test architecture>
455 #                           KIND <custom prefix>
456 #                           SUBDIR <subdirectory for testing binary>
457 #                           SOURCES <sources to compile>
458 #                           RUNTIME <tests runtime to link in>
459 #                           CFLAGS <compile-time flags>
460 #                           COMPILE_DEPS <compile-time dependencies>
461 #                           DEPS <dependencies>
462 #                           LINK_FLAGS <flags to use during linking>
463 # )
464 function(generate_compiler_rt_tests test_objects test_suite testname arch)
465   cmake_parse_arguments(TEST "" "KIND;RUNTIME;SUBDIR"
466     "SOURCES;COMPILE_DEPS;DEPS;CFLAGS;LINK_FLAGS" ${ARGN})
468   foreach(source ${TEST_SOURCES})
469     sanitizer_test_compile(
470       "${test_objects}" "${source}" "${arch}"
471       KIND ${TEST_KIND}
472       COMPILE_DEPS ${TEST_COMPILE_DEPS}
473       DEPS ${TEST_DEPS}
474       CFLAGS ${TEST_CFLAGS}
475       )
476   endforeach()
478   set(TEST_DEPS ${${test_objects}})
480   if(NOT "${TEST_RUNTIME}" STREQUAL "")
481     list(APPEND TEST_DEPS ${TEST_RUNTIME})
482     list(APPEND "${test_objects}" $<TARGET_FILE:${TEST_RUNTIME}>)
483   endif()
485   add_compiler_rt_test(${test_suite} "${testname}" "${arch}"
486     SUBDIR ${TEST_SUBDIR}
487     OBJECTS ${${test_objects}}
488     DEPS ${TEST_DEPS}
489     LINK_FLAGS ${TEST_LINK_FLAGS}
490     )
491   set("${test_objects}" "${${test_objects}}" PARENT_SCOPE)
492 endfunction()
494 # Link objects into a single executable with COMPILER_RT_TEST_COMPILER,
495 # using specified link flags. Make executable a part of provided
496 # test_suite.
497 # add_compiler_rt_test(<test_suite> <test_name> <arch>
498 #                      SUBDIR <subdirectory for binary>
499 #                      OBJECTS <object files>
500 #                      DEPS <deps (e.g. runtime libs)>
501 #                      LINK_FLAGS <link flags>)
502 function(add_compiler_rt_test test_suite test_name arch)
503   cmake_parse_arguments(TEST "" "SUBDIR" "OBJECTS;DEPS;LINK_FLAGS" "" ${ARGN})
504   set(output_dir ${CMAKE_CURRENT_BINARY_DIR})
505   if(TEST_SUBDIR)
506     set(output_dir "${output_dir}/${TEST_SUBDIR}")
507   endif()
508   set(output_dir "${output_dir}/${CMAKE_CFG_INTDIR}")
509   file(MAKE_DIRECTORY "${output_dir}")
510   set(output_bin "${output_dir}/${test_name}")
511   if(WIN32)
512     set(output_bin "${output_bin}.exe")
513   endif()
515   # Use host compiler in a standalone build, and just-built Clang otherwise.
516   if(NOT COMPILER_RT_STANDALONE_BUILD)
517     list(APPEND TEST_DEPS clang)
518   endif()
520   get_target_flags_for_arch(${arch} TARGET_LINK_FLAGS)
521   list(APPEND TEST_LINK_FLAGS ${TARGET_LINK_FLAGS})
523   # If we're not on MSVC, include the linker flags from CMAKE but override them
524   # with the provided link flags. This ensures that flags which are required to
525   # link programs at all are included, but the changes needed for the test
526   # trump. With MSVC we can't do that because CMake is set up to run link.exe
527   # when linking, not the compiler. Here, we hack it to use the compiler
528   # because we want to use -fsanitize flags.
530   # Only add CMAKE_EXE_LINKER_FLAGS when in a standalone bulid.
531   # Or else CMAKE_EXE_LINKER_FLAGS contains flags for build compiler of Clang/llvm.
532   # This might not be the same as what the COMPILER_RT_TEST_COMPILER supports.
533   # eg: the build compiler use lld linker and we build clang with default ld linker
534   # then to be tested clang will complain about lld options like --color-diagnostics.
535   if(NOT MSVC AND COMPILER_RT_STANDALONE_BUILD)
536     set(TEST_LINK_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${TEST_LINK_FLAGS}")
537     separate_arguments(TEST_LINK_FLAGS)
538   endif()
539   if(NOT COMPILER_RT_STANDALONE_BUILD AND COMPILER_RT_HAS_LLD AND "lld" IN_LIST LLVM_ENABLE_PROJECTS)
540     # CMAKE_EXE_LINKER_FLAGS may contain -fuse=lld
541     # FIXME: -DLLVM_ENABLE_LLD=ON and -DLLVM_ENABLE_PROJECTS without lld case.
542     list(APPEND TEST_DEPS lld)
543   endif()
544   add_custom_command(
545     OUTPUT "${output_bin}"
546     COMMAND ${COMPILER_RT_TEST_CXX_COMPILER} ${TEST_OBJECTS} -o "${output_bin}"
547             ${TEST_LINK_FLAGS}
548     DEPENDS ${TEST_DEPS}
549     )
550   add_custom_target(T${test_name} DEPENDS "${output_bin}")
551   set_target_properties(T${test_name} PROPERTIES FOLDER "Compiler-RT Tests")
553   # Make the test suite depend on the binary.
554   add_dependencies(${test_suite} T${test_name})
555 endfunction()
557 macro(add_compiler_rt_resource_file target_name file_name component)
558   set(src_file "${CMAKE_CURRENT_SOURCE_DIR}/${file_name}")
559   set(dst_file "${COMPILER_RT_OUTPUT_DIR}/share/${file_name}")
560   add_custom_command(OUTPUT ${dst_file}
561     DEPENDS ${src_file}
562     COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src_file} ${dst_file}
563     COMMENT "Copying ${file_name}...")
564   add_custom_target(${target_name} DEPENDS ${dst_file})
565   # Install in Clang resource directory.
566   install(FILES ${file_name}
567     DESTINATION ${COMPILER_RT_INSTALL_DATA_DIR}
568     COMPONENT ${component})
569   add_dependencies(${component} ${target_name})
571   set_target_properties(${target_name} PROPERTIES FOLDER "Compiler-RT Misc")
572 endmacro()
574 macro(add_compiler_rt_script name)
575   set(dst ${COMPILER_RT_EXEC_OUTPUT_DIR}/${name})
576   set(src ${CMAKE_CURRENT_SOURCE_DIR}/${name})
577   add_custom_command(OUTPUT ${dst}
578     DEPENDS ${src}
579     COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst}
580     COMMENT "Copying ${name}...")
581   add_custom_target(${name} DEPENDS ${dst})
582   install(FILES ${dst}
583     PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
584     DESTINATION ${COMPILER_RT_INSTALL_BINARY_DIR})
585 endmacro(add_compiler_rt_script src name)
587 # Builds custom version of libc++ and installs it in <prefix>.
588 # Can be used to build sanitized versions of libc++ for running unit tests.
589 # add_custom_libcxx(<name> <prefix>
590 #                   DEPS <list of build deps>
591 #                   CFLAGS <list of compile flags>
592 #                   USE_TOOLCHAIN)
593 macro(add_custom_libcxx name prefix)
594   if(NOT COMPILER_RT_LIBCXX_PATH)
595     message(FATAL_ERROR "libcxx not found!")
596   endif()
597   if(NOT COMPILER_RT_LIBCXXABI_PATH)
598     message(FATAL_ERROR "libcxxabi not found!")
599   endif()
601   cmake_parse_arguments(LIBCXX "USE_TOOLCHAIN" "" "DEPS;CFLAGS;CMAKE_ARGS" ${ARGN})
603   if(LIBCXX_USE_TOOLCHAIN)
604     set(compiler_args -DCMAKE_C_COMPILER=${COMPILER_RT_TEST_COMPILER}
605                       -DCMAKE_CXX_COMPILER=${COMPILER_RT_TEST_CXX_COMPILER})
606     if(NOT COMPILER_RT_STANDALONE_BUILD AND NOT LLVM_RUNTIMES_BUILD)
607       set(toolchain_deps $<TARGET_FILE:clang>)
608       set(force_deps DEPENDS $<TARGET_FILE:clang>)
609     endif()
610   else()
611     set(compiler_args -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
612                       -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER})
613   endif()
615   add_custom_target(${name}-clear
616     COMMAND ${CMAKE_COMMAND} -E remove_directory ${prefix}
617     COMMENT "Clobbering ${name} build directories"
618     USES_TERMINAL
619     )
620   set_target_properties(${name}-clear PROPERTIES FOLDER "Compiler-RT Misc")
622   add_custom_command(
623     OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
624     DEPENDS ${LIBCXX_DEPS} ${toolchain_deps}
625     COMMAND ${CMAKE_COMMAND} -E touch ${prefix}/CMakeCache.txt
626     COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
627     COMMENT "Clobbering bootstrap build directories"
628     )
630   add_custom_target(${name}-clobber
631     DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
632   set_target_properties(${name}-clobber PROPERTIES FOLDER "Compiler-RT Misc")
634   set(PASSTHROUGH_VARIABLES
635     CMAKE_C_COMPILER_TARGET
636     CMAKE_CXX_COMPILER_TARGET
637     CMAKE_SHARED_LINKER_FLAGS
638     CMAKE_MODULE_LINKER_FLAGS
639     CMAKE_EXE_LINKER_FLAGS
640     CMAKE_INSTALL_PREFIX
641     CMAKE_MAKE_PROGRAM
642     CMAKE_LINKER
643     CMAKE_AR
644     CMAKE_RANLIB
645     CMAKE_NM
646     CMAKE_OBJCOPY
647     CMAKE_OBJDUMP
648     CMAKE_STRIP
649     CMAKE_READELF
650     CMAKE_SYSROOT
651     LIBCXX_HAS_MUSL_LIBC
652     LIBCXX_HAS_GCC_S_LIB
653     LIBCXX_HAS_PTHREAD_LIB
654     LIBCXX_HAS_RT_LIB
655     LIBCXX_USE_COMPILER_RT
656     LIBCXXABI_HAS_PTHREAD_LIB
657     PYTHON_EXECUTABLE
658     Python3_EXECUTABLE
659     Python2_EXECUTABLE
660     CMAKE_SYSTEM_NAME)
661   foreach(variable ${PASSTHROUGH_VARIABLES})
662     get_property(is_value_set CACHE ${variable} PROPERTY VALUE SET)
663     if(${is_value_set})
664       get_property(value CACHE ${variable} PROPERTY VALUE)
665       list(APPEND CMAKE_PASSTHROUGH_VARIABLES -D${variable}=${value})
666     endif()
667   endforeach()
669   string(REPLACE ";" " " LIBCXX_C_FLAGS "${LIBCXX_CFLAGS}")
670   get_property(C_FLAGS CACHE CMAKE_C_FLAGS PROPERTY VALUE)
671   set(LIBCXX_C_FLAGS "${LIBCXX_C_FLAGS} ${C_FLAGS}")
673   string(REPLACE ";" " " LIBCXX_CXX_FLAGS "${LIBCXX_CFLAGS}")
674   get_property(CXX_FLAGS CACHE CMAKE_CXX_FLAGS PROPERTY VALUE)
675   set(LIBCXX_CXX_FLAGS "${LIBCXX_CXX_FLAGS} ${CXX_FLAGS}")
677   ExternalProject_Add(${name}
678     DEPENDS ${name}-clobber ${LIBCXX_DEPS}
679     PREFIX ${CMAKE_CURRENT_BINARY_DIR}/${name}
680     SOURCE_DIR ${LLVM_MAIN_SRC_DIR}/../runtimes
681     BINARY_DIR ${prefix}
682     CMAKE_ARGS ${CMAKE_PASSTHROUGH_VARIABLES}
683                ${compiler_args}
684                -DCMAKE_C_FLAGS=${LIBCXX_C_FLAGS}
685                -DCMAKE_CXX_FLAGS=${LIBCXX_CXX_FLAGS}
686                -DCMAKE_BUILD_TYPE=Release
687                -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY
688                -DLLVM_PATH=${LLVM_MAIN_SRC_DIR}
689                -DLLVM_ENABLE_RUNTIMES=libcxx|libcxxabi
690                -DLIBCXXABI_ENABLE_SHARED=OFF
691                -DLIBCXXABI_HERMETIC_STATIC_LIBRARY=ON
692                -DLIBCXXABI_INCLUDE_TESTS=OFF
693                -DLIBCXX_CXX_ABI=libcxxabi
694                -DLIBCXX_ENABLE_SHARED=OFF
695                -DLIBCXX_HERMETIC_STATIC_LIBRARY=ON
696                -DLIBCXX_INCLUDE_BENCHMARKS=OFF
697                -DLIBCXX_INCLUDE_TESTS=OFF
698                -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON
699                ${LIBCXX_CMAKE_ARGS}
700     INSTALL_COMMAND ""
701     STEP_TARGETS configure build
702     BUILD_ALWAYS 1
703     USES_TERMINAL_CONFIGURE 1
704     USES_TERMINAL_BUILD 1
705     USES_TERMINAL_INSTALL 1
706     LIST_SEPARATOR |
707     EXCLUDE_FROM_ALL TRUE
708     BUILD_BYPRODUCTS "${prefix}/lib/libc++.a" "${prefix}/lib/libc++abi.a"
709     )
711   if (CMAKE_GENERATOR MATCHES "Make")
712     set(run_clean "$(MAKE)" "-C" "${prefix}" "clean")
713   else()
714     set(run_clean ${CMAKE_COMMAND} --build ${prefix} --target clean
715                                    --config "$<CONFIG>")
716   endif()
718   ExternalProject_Add_Step(${name} clean
719     COMMAND ${run_clean}
720     COMMENT "Cleaning ${name}..."
721     DEPENDEES configure
722     ${force_deps}
723     WORKING_DIRECTORY ${prefix}
724     EXCLUDE_FROM_MAIN 1
725     USES_TERMINAL 1
726     )
727   ExternalProject_Add_StepTargets(${name} clean)
729   if(LIBCXX_USE_TOOLCHAIN)
730     add_dependencies(${name}-clean ${name}-clobber)
731     set_target_properties(${name}-clean PROPERTIES
732       SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
733   endif()
734 endmacro()
736 function(rt_externalize_debuginfo name)
737   if(NOT COMPILER_RT_EXTERNALIZE_DEBUGINFO)
738     return()
739   endif()
741   if(NOT COMPILER_RT_EXTERNALIZE_DEBUGINFO_SKIP_STRIP)
742     set(strip_command COMMAND xcrun strip -Sl $<TARGET_FILE:${name}>)
743   endif()
745   if(APPLE)
746     if(CMAKE_CXX_FLAGS MATCHES "-flto"
747       OR CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE} MATCHES "-flto")
749       set(lto_object ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${name}-lto.o)
750       set_property(TARGET ${name} APPEND_STRING PROPERTY
751         LINK_FLAGS " -Wl,-object_path_lto -Wl,${lto_object}")
752     endif()
753     add_custom_command(TARGET ${name} POST_BUILD
754       COMMAND xcrun dsymutil $<TARGET_FILE:${name}>
755       ${strip_command})
756   else()
757     message(FATAL_ERROR "COMPILER_RT_EXTERNALIZE_DEBUGINFO isn't implemented for non-darwin platforms!")
758   endif()
759 endfunction()
762 # Configure lit configuration files, including compiler-rt specific variables.
763 function(configure_compiler_rt_lit_site_cfg input output)
764   set_llvm_build_mode()
766   get_compiler_rt_output_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} output_dir)
768   string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} COMPILER_RT_RESOLVED_TEST_COMPILER ${COMPILER_RT_TEST_COMPILER})
769   string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR ${output_dir})
771   configure_lit_site_cfg(${input} ${output})
772 endfunction()