CMakeLists.txt revision 2f66ab25cbb000289b79bca042b4136d92331b44
1# Testing rules for AddressSanitizer.
2#
3# These are broken into two buckets. One set of tests directly interacts with
4# the runtime library and checks its functionality. These are the
5# no-instrumentation tests.
6#
7# Another group of tests relies upon the ability to compile the test with
8# address sanitizer instrumentation pass. These tests form "integration" tests
9# and have some elements of version skew -- they test the *host* compiler's
10# instrumentation against the just-built runtime library.
11
12include(CheckCXXCompilerFlag)
13include(CompilerRTCompile)
14include(CompilerRTUnittests)
15
16include_directories(..)
17include_directories(../..)
18
19set(ASAN_UNITTEST_COMMON_CFLAGS
20  ${COMPILER_RT_GTEST_INCLUDE_CFLAGS}
21  -I${COMPILER_RT_SOURCE_DIR}/include
22  -I${COMPILER_RT_SOURCE_DIR}/lib
23  -I${COMPILER_RT_SOURCE_DIR}/lib/asan
24  -Wall
25  -Wno-format
26  -Werror
27  -g
28  -O2
29)
30
31if(SUPPORTS_NO_VARIADIC_MACROS_FLAG)
32  list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -Wno-variadic-macros)
33endif()
34
35# Use -D instead of definitions to please custom compile command.
36if(ANDROID)
37  list(APPEND ASAN_UNITTEST_COMMON_CFLAGS
38    -DASAN_LOW_MEMORY=1
39    -DASAN_HAS_BLACKLIST=1
40    -DASAN_HAS_EXCEPTIONS=1
41    -DASAN_NEEDS_SEGV=0
42    -DASAN_UAR=0
43    -fPIE
44  )
45else()
46  list(APPEND ASAN_UNITTEST_COMMON_CFLAGS
47    -DASAN_HAS_BLACKLIST=1
48    -DASAN_HAS_EXCEPTIONS=1
49    -DASAN_NEEDS_SEGV=1
50    -DASAN_UAR=0
51  )
52endif()
53
54set(ASAN_LINK_FLAGS)
55if(ANDROID)
56  # On Android, we link with ASan runtime manually
57  list(APPEND ASAN_LINK_FLAGS -pie)
58else()
59  # On other platforms, we depend on Clang driver behavior,
60  # passing -fsanitize=address flag.
61  list(APPEND ASAN_LINK_FLAGS -fsanitize=address)
62endif()
63# Unit tests on Mac depend on Foundation.
64if(APPLE)
65  list(APPEND ASAN_LINK_FLAGS -framework Foundation)
66endif()
67# Unit tests require libstdc++.
68list(APPEND ASAN_LINK_FLAGS -lstdc++)
69
70set(ASAN_BLACKLIST_FILE "${CMAKE_CURRENT_SOURCE_DIR}/asan_test.ignore")
71
72set(ASAN_UNITTEST_INSTRUMENTED_CFLAGS
73  ${ASAN_UNITTEST_COMMON_CFLAGS}
74  -fsanitize=address
75  -mllvm "-asan-blacklist=${ASAN_BLACKLIST_FILE}"
76  -mllvm -asan-stack=1
77  -mllvm -asan-globals=1
78  -mllvm -asan-mapping-scale=0        # default will be used
79  -mllvm -asan-mapping-offset-log=-1  # default will be used
80  -mllvm -asan-use-after-return=0
81)
82
83# Compile source for the given architecture, using compiler
84# options in ${ARGN}, and add it to the object list.
85macro(asan_compile obj_list source arch)
86  get_filename_component(basename ${source} NAME)
87  set(output_obj "${basename}.${arch}.o")
88  get_target_flags_for_arch(${arch} TARGET_CFLAGS)
89  clang_compile(${output_obj} ${source}
90                CFLAGS ${ARGN} ${TARGET_CFLAGS}
91                DEPS gtest ${ASAN_RUNTIME_LIBRARIES}
92                           ${ASAN_BLACKLIST_FILE})
93  list(APPEND ${obj_list} ${output_obj})
94endmacro()
95
96# Link ASan unit test for a given architecture from a set
97# of objects in ${ARGN}.
98macro(add_asan_test test_suite test_name arch)
99  get_target_flags_for_arch(${arch} TARGET_LINK_FLAGS)
100  add_compiler_rt_test(${test_suite} ${test_name}
101                       OBJECTS ${ARGN}
102                       DEPS ${ASAN_RUNTIME_LIBRARIES}
103                       LINK_FLAGS ${ASAN_LINK_FLAGS}
104                                  ${TARGET_LINK_FLAGS})
105endmacro()
106
107# Main AddressSanitizer unit tests.
108add_custom_target(AsanUnitTests)
109set_target_properties(AsanUnitTests PROPERTIES FOLDER "ASan unit tests")
110# ASan benchmarks (not actively used now).
111add_custom_target(AsanBenchmarks)
112set_target_properties(AsanBenchmarks PROPERTIES FOLDER "Asan benchmarks")
113
114# Adds ASan unit tests and benchmarks for architecture.
115macro(add_asan_tests_for_arch arch)
116  # Build gtest instrumented with ASan.
117  set(ASAN_INST_GTEST)
118  asan_compile(ASAN_INST_GTEST ${COMPILER_RT_GTEST_SOURCE} ${arch} 
119                               ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
120  # Instrumented tests.
121  set(ASAN_INST_TEST_OBJECTS)
122  asan_compile(ASAN_INST_TEST_OBJECTS asan_globals_test.cc ${arch}
123               ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
124  asan_compile(ASAN_INST_TEST_OBJECTS asan_test.cc ${arch}
125               ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
126  if (APPLE)
127    asan_compile(ASAN_INST_TEST_OBJECTS asan_mac_test.mm ${arch}
128                 ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} -ObjC)
129  endif()
130  # Uninstrumented tests.
131  set(ASAN_NOINST_TEST_OBJECTS)
132  asan_compile(ASAN_NOINST_TEST_OBJECTS asan_noinst_test.cc ${arch}
133               ${ASAN_UNITTEST_COMMON_CFLAGS})
134  asan_compile(ASAN_NOINST_TEST_OBJECTS asan_test_main.cc ${arch}
135               ${ASAN_UNITTEST_COMMON_CFLAGS})
136  # Link everything together.
137  add_asan_test(AsanUnitTests "Asan-${arch}-Test" ${arch}
138                ${ASAN_NOINST_TEST_OBJECTS}
139                ${ASAN_INST_TEST_OBJECTS} ${ASAN_INST_GTEST})
140
141  # Instrumented benchmarks.
142  set(ASAN_BENCHMARKS_OBJECTS)
143  asan_compile(ASAN_BENCHMARKS_OBJECTS asan_benchmarks_test.cc ${arch}
144               ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
145  # Link benchmarks.
146  add_asan_test(AsanBenchmarks "Asan-${arch}-Benchmark" ${arch}
147                ${ASAN_BENCHMARKS_OBJECTS} ${ASAN_INST_GTEST})
148endmacro()
149
150# We only support building instrumented tests when we're not cross compiling
151# and targeting a unix-like system where we can predict viable compilation and
152# linking strategies.
153# We use a different approach to build these tests for Android. See below.
154if("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND UNIX AND NOT ANDROID)
155  if(CAN_TARGET_X86_64)
156    add_asan_tests_for_arch(x86_64)
157  endif()
158  if(CAN_TARGET_I386)
159    add_asan_tests_for_arch(i386)
160  endif()
161endif()
162
163if(ANDROID)
164  # We assume that unit tests on Android are built in a build
165  # tree with fresh Clang as a host compiler.
166  set(ASAN_NOINST_TEST_SOURCES asan_noinst_test.cc asan_test_main.cc)
167  set(ASAN_INST_TEST_SOURCES asan_globals_test.cc asan_test.cc)
168  add_library(asan_noinst_test OBJECT ${ASAN_NOINST_TEST_SOURCES})
169  set_target_compile_flags(asan_noinst_test ${ASAN_UNITTEST_COMMON_CFLAGS})
170  add_library(asan_inst_test OBJECT
171              ${ASAN_INST_TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE})  
172  set_target_compile_flags(asan_inst_test ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
173  add_executable(AsanTest
174    $<TARGET_OBJECTS:asan_noinst_test>
175    $<TARGET_OBJECTS:asan_inst_test>
176  )
177  # Setup correct output directory and link flags.
178  get_unittest_directory(OUTPUT_DIR)
179  set_target_properties(AsanTest PROPERTIES
180    RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR})
181  set_target_link_flags(AsanTest ${ASAN_LINK_FLAGS})
182  target_link_libraries(AsanTest clang_rt.asan-arm-android)
183  # Add unit test to test suite.
184  add_dependencies(AsanUnitTests AsanTest)
185endif()
186