1include(AddLLVM)
2include(ExternalProject)
3include(CompilerRTUtils)
4
5# Tries to add an "object library" target for a given list of OSs and/or
6# architectures with name "<name>.<arch>" for non-Darwin platforms if
7# architecture can be targeted, and "<name>.<os>" for Darwin platforms.
8# add_compiler_rt_object_libraries(<name>
9#                                  OS <os names>
10#                                  ARCHS <architectures>
11#                                  SOURCES <source files>
12#                                  CFLAGS <compile flags>
13#                                  DEFS <compile definitions>)
14function(add_compiler_rt_object_libraries name)
15  cmake_parse_arguments(LIB "" "" "OS;ARCHS;SOURCES;CFLAGS;DEFS" ${ARGN})
16  set(libnames)
17  if(APPLE)
18    foreach(os ${LIB_OS})
19      set(libname "${name}.${os}")
20      set(libnames ${libnames} ${libname})
21      set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS})
22    endforeach()
23  else()
24    foreach(arch ${LIB_ARCHS})
25      set(libname "${name}.${arch}")
26      set(libnames ${libnames} ${libname})
27      set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS})
28      if(NOT CAN_TARGET_${arch})
29        message(FATAL_ERROR "Archtecture ${arch} can't be targeted")
30        return()
31      endif()
32    endforeach()
33  endif()
34
35  foreach(libname ${libnames})
36    add_library(${libname} OBJECT ${LIB_SOURCES})
37    set_target_compile_flags(${libname}
38      ${CMAKE_CXX_FLAGS} ${extra_cflags_${libname}} ${LIB_CFLAGS})
39    set_property(TARGET ${libname} APPEND PROPERTY
40      COMPILE_DEFINITIONS ${LIB_DEFS})
41    if(APPLE)
42      set_target_properties(${libname} PROPERTIES OSX_ARCHITECTURES "${LIB_ARCHS}")
43    endif()
44  endforeach()
45endfunction()
46
47# Adds static or shared runtime for a given architecture and puts it in the
48# proper directory in the build and install trees.
49# add_compiler_rt_runtime(<name> <arch> {STATIC,SHARED}
50#                         SOURCES <source files>
51#                         CFLAGS <compile flags>
52#                         DEFS <compile definitions>
53#                         OUTPUT_NAME <output library name>)
54macro(add_compiler_rt_runtime name arch type)
55  if(CAN_TARGET_${arch})
56    cmake_parse_arguments(LIB "" "OUTPUT_NAME" "SOURCES;CFLAGS;LINKFLAGS;DEFS" ${ARGN})
57    add_library(${name} ${type} ${LIB_SOURCES})
58    # Setup compile flags and definitions.
59    set_target_compile_flags(${name}
60      ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS})
61    set_target_link_flags(${name}
62      ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS} ${LIB_LINKFLAGS})
63    set_property(TARGET ${name} APPEND PROPERTY
64      COMPILE_DEFINITIONS ${LIB_DEFS})
65    # Setup correct output directory in the build tree.
66    set_target_properties(${name} PROPERTIES
67      ARCHIVE_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR}
68      LIBRARY_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR}
69      RUNTIME_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR})
70    if ("${LIB_OUTPUT_NAME}" STREQUAL "")
71      set_target_properties(${name} PROPERTIES
72        OUTPUT_NAME ${name}${COMPILER_RT_OS_SUFFIX})
73    else()
74      set_target_properties(${name} PROPERTIES
75        OUTPUT_NAME ${LIB_OUTPUT_NAME})
76    endif()
77    # Add installation command.
78    install(TARGETS ${name}
79      ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}
80      LIBRARY DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}
81      RUNTIME DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
82  else()
83    message(FATAL_ERROR "Archtecture ${arch} can't be targeted")
84  endif()
85endmacro()
86
87# Same as add_compiler_rt_runtime(... STATIC), but creates a universal library
88# for several architectures.
89# add_compiler_rt_osx_static_runtime(<name> ARCHS <architectures>
90#                                    SOURCES <source files>
91#                                    CFLAGS <compile flags>
92#                                    DEFS <compile definitions>)
93macro(add_compiler_rt_osx_static_runtime name)
94  cmake_parse_arguments(LIB "" "" "ARCHS;SOURCES;CFLAGS;DEFS" ${ARGN})
95  add_library(${name} STATIC ${LIB_SOURCES})
96  set_target_compile_flags(${name} ${LIB_CFLAGS})
97  set_property(TARGET ${name} APPEND PROPERTY
98    COMPILE_DEFINITIONS ${LIB_DEFS})
99  set_target_properties(${name} PROPERTIES
100    OSX_ARCHITECTURES "${LIB_ARCHS}"
101    ARCHIVE_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR})
102  install(TARGETS ${name}
103    ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
104endmacro()
105
106# Adds dynamic runtime library on osx/iossim, which supports multiple
107# architectures.
108# add_compiler_rt_darwin_dynamic_runtime(<name> <os>
109#                                        ARCHS <architectures>
110#                                        SOURCES <source files>
111#                                        CFLAGS <compile flags>
112#                                        DEFS <compile definitions>
113#                                        LINKFLAGS <link flags>)
114macro(add_compiler_rt_darwin_dynamic_runtime name os)
115  cmake_parse_arguments(LIB "" "" "ARCHS;SOURCES;CFLAGS;DEFS;LINKFLAGS" ${ARGN})
116  add_library(${name} SHARED ${LIB_SOURCES})
117  set_target_compile_flags(${name} ${LIB_CFLAGS} ${DARWIN_${os}_CFLAGS})
118  set_target_link_flags(${name} ${LIB_LINKFLAGS} ${DARWIN_${os}_LINKFLAGS})
119  set_property(TARGET ${name} APPEND PROPERTY
120    COMPILE_DEFINITIONS ${LIB_DEFS})
121  set_target_properties(${name} PROPERTIES
122    OSX_ARCHITECTURES "${LIB_ARCHS}"
123    LIBRARY_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR})
124  install(TARGETS ${name}
125    LIBRARY DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
126endmacro()
127
128set(COMPILER_RT_TEST_CFLAGS)
129
130# Unittests support.
131set(COMPILER_RT_GTEST_PATH ${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest)
132set(COMPILER_RT_GTEST_SOURCE ${COMPILER_RT_GTEST_PATH}/src/gtest-all.cc)
133set(COMPILER_RT_GTEST_CFLAGS
134  -DGTEST_NO_LLVM_RAW_OSTREAM=1
135  -DGTEST_HAS_RTTI=0
136  -I${COMPILER_RT_GTEST_PATH}/include
137  -I${COMPILER_RT_GTEST_PATH}
138)
139
140append_list_if(COMPILER_RT_DEBUG -DSANITIZER_DEBUG=1 COMPILER_RT_TEST_CFLAGS)
141
142if(MSVC)
143  # clang doesn't support exceptions on Windows yet.
144  list(APPEND COMPILER_RT_TEST_CFLAGS -D_HAS_EXCEPTIONS=0)
145
146  # We should teach clang to understand "#pragma intrinsic", see PR19898.
147  list(APPEND COMPILER_RT_TEST_CFLAGS -Wno-undefined-inline)
148
149  # Clang doesn't support SEH on Windows yet.
150  list(APPEND COMPILER_RT_GTEST_CFLAGS -DGTEST_HAS_SEH=0)
151
152  # gtest use a lot of stuff marked as deprecated on Windows.
153  list(APPEND COMPILER_RT_GTEST_CFLAGS -Wno-deprecated-declarations)
154
155  # Visual Studio 2012 only supports up to 8 template parameters in
156  # std::tr1::tuple by default, but gtest requires 10
157  if(MSVC_VERSION EQUAL 1700)
158    list(APPEND COMPILER_RT_GTEST_CFLAGS -D_VARIADIC_MAX=10)
159  endif()
160endif()
161
162# Link objects into a single executable with COMPILER_RT_TEST_COMPILER,
163# using specified link flags. Make executable a part of provided
164# test_suite.
165# add_compiler_rt_test(<test_suite> <test_name>
166#                      SUBDIR <subdirectory for binary>
167#                      OBJECTS <object files>
168#                      DEPS <deps (e.g. runtime libs)>
169#                      LINK_FLAGS <link flags>)
170macro(add_compiler_rt_test test_suite test_name)
171  cmake_parse_arguments(TEST "" "SUBDIR" "OBJECTS;DEPS;LINK_FLAGS" "" ${ARGN})
172  if(TEST_SUBDIR)
173    set(output_bin "${CMAKE_CURRENT_BINARY_DIR}/${TEST_SUBDIR}/${test_name}")
174  else()
175    set(output_bin "${CMAKE_CURRENT_BINARY_DIR}/${test_name}")
176  endif()
177  if(MSVC)
178    set(output_bin "${output_bin}.exe")
179  endif()
180  # Use host compiler in a standalone build, and just-built Clang otherwise.
181  if(NOT COMPILER_RT_STANDALONE_BUILD)
182    list(APPEND TEST_DEPS clang)
183  endif()
184  # If we're not on MSVC, include the linker flags from CMAKE but override them
185  # with the provided link flags. This ensures that flags which are required to
186  # link programs at all are included, but the changes needed for the test
187  # trump. With MSVC we can't do that because CMake is set up to run link.exe
188  # when linking, not the compiler. Here, we hack it to use the compiler
189  # because we want to use -fsanitize flags.
190  if(NOT MSVC)
191    set(TEST_LINK_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${TEST_LINK_FLAGS}")
192    separate_arguments(TEST_LINK_FLAGS)
193  endif()
194  add_custom_target(${test_name}
195    COMMAND ${COMPILER_RT_TEST_COMPILER} ${TEST_OBJECTS}
196            -o "${output_bin}"
197            ${TEST_LINK_FLAGS}
198    DEPENDS ${TEST_DEPS})
199  # Make the test suite depend on the binary.
200  add_dependencies(${test_suite} ${test_name})
201endmacro()
202
203macro(add_compiler_rt_resource_file target_name file_name)
204  set(src_file "${CMAKE_CURRENT_SOURCE_DIR}/${file_name}")
205  set(dst_file "${COMPILER_RT_OUTPUT_DIR}/${file_name}")
206  add_custom_command(OUTPUT ${dst_file}
207    DEPENDS ${src_file}
208    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src_file} ${dst_file}
209    COMMENT "Copying ${file_name}...")
210  add_custom_target(${target_name} DEPENDS ${dst_file})
211  # Install in Clang resource directory.
212  install(FILES ${file_name} DESTINATION ${COMPILER_RT_INSTALL_PATH})
213endmacro()
214
215macro(add_compiler_rt_script name)
216  set(dst ${COMPILER_RT_EXEC_OUTPUT_DIR}/${name})
217  set(src ${CMAKE_CURRENT_SOURCE_DIR}/${name})
218  add_custom_command(OUTPUT ${dst}
219    DEPENDS ${src}
220    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst}
221    COMMENT "Copying ${name}...")
222  add_custom_target(${name} DEPENDS ${dst})
223  install(FILES ${dst}
224    PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
225    DESTINATION ${COMPILER_RT_INSTALL_PATH}/bin)
226endmacro(add_compiler_rt_script src name)
227
228# Builds custom version of libc++ and installs it in <prefix>.
229# Can be used to build sanitized versions of libc++ for running unit tests.
230# add_custom_libcxx(<name> <prefix>
231#                   DEPS <list of build deps>
232#                   CFLAGS <list of compile flags>)
233macro(add_custom_libcxx name prefix)
234  if(NOT COMPILER_RT_HAS_LIBCXX_SOURCES)
235    message(FATAL_ERROR "libcxx not found!")
236  endif()
237
238  cmake_parse_arguments(LIBCXX "" "" "DEPS;CFLAGS" ${ARGN})
239  foreach(flag ${LIBCXX_CFLAGS})
240    set(flagstr "${flagstr} ${flag}")
241  endforeach()
242  set(LIBCXX_CFLAGS ${flagstr})
243
244  if(NOT COMPILER_RT_STANDALONE_BUILD)
245    list(APPEND LIBCXX_DEPS clang)
246  endif()
247
248  ExternalProject_Add(${name}
249    PREFIX ${prefix}
250    SOURCE_DIR ${COMPILER_RT_LIBCXX_PATH}
251    CMAKE_ARGS -DCMAKE_C_COMPILER=${COMPILER_RT_TEST_COMPILER}
252               -DCMAKE_CXX_COMPILER=${COMPILER_RT_TEST_COMPILER}
253               -DCMAKE_C_FLAGS=${LIBCXX_CFLAGS}
254               -DCMAKE_CXX_FLAGS=${LIBCXX_CFLAGS}
255               -DCMAKE_BUILD_TYPE=Release
256               -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
257    LOG_BUILD 1
258    LOG_CONFIGURE 1
259    LOG_INSTALL 1
260    )
261
262  ExternalProject_Add_Step(${name} force-reconfigure
263    DEPENDERS configure
264    ALWAYS 1
265    )
266
267  ExternalProject_Add_Step(${name} clobber
268    COMMAND ${CMAKE_COMMAND} -E remove_directory <BINARY_DIR>
269    COMMAND ${CMAKE_COMMAND} -E make_directory <BINARY_DIR>
270    COMMENT "Clobberring ${name} build directory..."
271    DEPENDERS configure
272    DEPENDS ${LIBCXX_DEPS}
273    )
274endmacro()
275