CMakeLists.txt revision c47a45154543b5eba68c9473d3ed807927027cf3
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 -fsanitize=address)
55if(ANDROID)
56  list(APPEND ASAN_LINK_FLAGS -pie)
57elseif(APPLE)
58  # Unit tests on Mac depend on Foundation.
59  list(APPEND ASAN_LINK_FLAGS -framework Foundation)
60endif()
61# Unit tests require libstdc++.
62list(APPEND ASAN_LINK_FLAGS -lstdc++)
63
64set(ASAN_BLACKLIST_FILE "${CMAKE_CURRENT_SOURCE_DIR}/asan_test.ignore")
65
66set(ASAN_UNITTEST_INSTRUMENTED_CFLAGS
67  ${ASAN_UNITTEST_COMMON_CFLAGS}
68  -fsanitize=address
69  -mllvm "-asan-blacklist=${ASAN_BLACKLIST_FILE}"
70  -mllvm -asan-stack=1
71  -mllvm -asan-globals=1
72  -mllvm -asan-mapping-scale=0        # default will be used
73  -mllvm -asan-mapping-offset-log=-1  # default will be used
74  -mllvm -asan-use-after-return=0
75)
76
77# Compile source for the given architecture, using compiler
78# options in ${ARGN}, and add it to the object list.
79macro(asan_compile obj_list source arch)
80  get_filename_component(basename ${source} NAME)
81  set(output_obj "${basename}.${arch}.o")
82  get_target_flags_for_arch(${arch} TARGET_CFLAGS)
83  clang_compile(${output_obj} ${source}
84                CFLAGS ${ARGN} ${TARGET_CFLAGS}
85                DEPS gtest ${ASAN_RUNTIME_LIBRARIES}
86                           ${ASAN_BLACKLIST_FILE})
87  list(APPEND ${obj_list} ${output_obj})
88endmacro()
89
90# Link ASan unit test for a given architecture from a set
91# of objects in ${ARGN}.
92macro(add_asan_test test_suite test_name arch)
93  get_target_flags_for_arch(${arch} TARGET_LINK_FLAGS)
94  add_compiler_rt_test(${test_suite} ${test_name}
95                       OBJECTS ${ARGN}
96                       DEPS ${ASAN_RUNTIME_LIBRARIES}
97                       LINK_FLAGS ${ASAN_LINK_FLAGS}
98                                  ${TARGET_LINK_FLAGS})
99endmacro()
100
101# Main AddressSanitizer unit tests.
102add_custom_target(AsanUnitTests)
103set_target_properties(AsanUnitTests PROPERTIES FOLDER "ASan unit tests")
104# ASan benchmarks (not actively used now).
105add_custom_target(AsanBenchmarks)
106set_target_properties(AsanBenchmarks PROPERTIES FOLDER "Asan benchmarks")
107
108# Adds ASan unit tests and benchmarks for architecture.
109macro(add_asan_tests_for_arch arch)
110  # Build gtest instrumented with ASan.
111  set(ASAN_INST_GTEST)
112  asan_compile(ASAN_INST_GTEST ${COMPILER_RT_GTEST_SOURCE} ${arch} 
113                               ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
114  # Instrumented tests.
115  set(ASAN_INST_TEST_OBJECTS)
116  asan_compile(ASAN_INST_TEST_OBJECTS asan_globals_test.cc ${arch}
117               ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
118  asan_compile(ASAN_INST_TEST_OBJECTS asan_test.cc ${arch}
119               ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
120  if (APPLE)
121    asan_compile(ASAN_INST_TEST_OBJECTS asan_mac_test.mm ${arch}
122                 ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} -ObjC)
123  endif()
124  # Uninstrumented tests.
125  set(ASAN_NOINST_TEST_OBJECTS)
126  asan_compile(ASAN_NOINST_TEST_OBJECTS asan_noinst_test.cc ${arch}
127               ${ASAN_UNITTEST_COMMON_CFLAGS})
128  asan_compile(ASAN_NOINST_TEST_OBJECTS asan_test_main.cc ${arch}
129               ${ASAN_UNITTEST_COMMON_CFLAGS})
130  # Link everything together.
131  add_asan_test(AsanUnitTests "Asan-${arch}-Test" ${arch}
132                ${ASAN_NOINST_TEST_OBJECTS}
133                ${ASAN_INST_TEST_OBJECTS} ${ASAN_INST_GTEST})
134
135  # Instrumented benchmarks.
136  set(ASAN_BENCHMARKS_OBJECTS)
137  asan_compile(ASAN_BENCHMARKS_OBJECTS asan_benchmarks_test.cc ${arch}
138               ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
139  # Link benchmarks.
140  add_asan_test(AsanBenchmarks "Asan-${arch}-Benchmark" ${arch}
141                ${ASAN_BENCHMARKS_OBJECTS} ${ASAN_INST_GTEST})
142endmacro()
143
144# We only support building instrumented tests when we're not cross compiling
145# and targeting a unix-like system where we can predict viable compilation and
146# linking strategies.
147# We use a different approach to build these tests for Android. See below.
148if("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND UNIX AND NOT ANDROID)
149  if(CAN_TARGET_X86_64)
150    add_asan_tests_for_arch(x86_64)
151  endif()
152  if(CAN_TARGET_I386)
153    add_asan_tests_for_arch(i386)
154  endif()
155endif()
156
157if(ANDROID)
158  # We assume that unit tests on Android are built in a build
159  # tree with fresh Clang as a host compiler.
160  set(ASAN_NOINST_TEST_SOURCES asan_noinst_test.cc asan_test_main.cc)
161  set(ASAN_INST_TEST_SOURCES asan_globals_test.cc asan_test.cc)
162  add_library(asan_noinst_test OBJECT ${ASAN_NOINST_TEST_SOURCES})
163  set_target_compile_flags(asan_noinst_test ${ASAN_UNITTEST_COMMON_CFLAGS})
164  add_library(asan_inst_test OBJECT
165              ${ASAN_INST_TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE})  
166  set_target_compile_flags(asan_inst_test ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
167  add_executable(AsanTest
168    $<TARGET_OBJECTS:asan_noinst_test>
169    $<TARGET_OBJECTS:asan_inst_test>
170  )
171  # Setup correct output directory and link flags.
172  get_unittest_directory(OUTPUT_DIR)
173  set_target_properties(AsanTest PROPERTIES
174    RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR})
175  set_target_link_flags(AsanTest ${ASAN_LINK_FLAGS})
176  target_link_libraries(AsanTest clang_rt.asan-arm-android)
177  # Add unit test to test suite.
178  add_dependencies(AsanUnitTests AsanTest)
179endif()
180