Use a special test launcher that links the sanitize runtime library directly
This commit is contained in:
parent
ba7a6e8106
commit
788f09e855
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,3 +7,4 @@ build
|
||||
README.html
|
||||
linux-package
|
||||
logo/*.iconset
|
||||
test-launcher
|
||||
|
||||
48
.travis.yml
48
.travis.yml
@ -6,7 +6,7 @@ matrix:
|
||||
group: beta
|
||||
sudo: false
|
||||
env:
|
||||
- CC=gcc ASANLIB=libasan.so.0 ASAN_ARG=--asan
|
||||
- CC=gcc SANITIZE_ARG=--sanitize
|
||||
language: python
|
||||
python: "3.5"
|
||||
addons:
|
||||
@ -24,7 +24,25 @@ matrix:
|
||||
group: beta
|
||||
sudo: false
|
||||
env:
|
||||
- CC=clang RUN_FLAKE=1 BUILD_PKG=1
|
||||
- CC=clang SANITIZE_ARG=--sanitize
|
||||
language: python
|
||||
python: "3.5"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libfontconfig1-dev
|
||||
- libglew-dev
|
||||
- libxi-dev
|
||||
- libxrandr-dev
|
||||
- libxinerama-dev
|
||||
- libxcursor-dev
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
group: beta
|
||||
sudo: false
|
||||
env:
|
||||
- RUN_FLAKE=1 BUILD_PKG=1
|
||||
language: python
|
||||
python: "3.5"
|
||||
addons:
|
||||
@ -45,6 +63,13 @@ matrix:
|
||||
language: generic
|
||||
env: USE_BREW=1 BUILD_PKG=1
|
||||
|
||||
env:
|
||||
global:
|
||||
- PYTHON=python3
|
||||
- PKG_CONFIG_PATH=$HOME/glfw/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
- LD_LIBRARY_PATH=$HOME/glfw/lib:$LD_LIBRARY_PATH
|
||||
- ASAN_OPTIONS=leak_check_at_exit=0
|
||||
|
||||
install: |
|
||||
set -e
|
||||
if [[ "$RUN_FLAKE" == "1" ]]; then pip install flake8; fi
|
||||
@ -59,7 +84,7 @@ install: |
|
||||
fi
|
||||
else
|
||||
wget -O glfw-3.2.1.zip https://github.com/glfw/glfw/archive/3.2.1.zip
|
||||
unzip glfw-3.2.1.zip
|
||||
unzip -q glfw-3.2.1.zip
|
||||
cd glfw-3.2.1
|
||||
cmake -DBUILD_SHARED_LIBS=ON -DGLFW_BUILD_EXAMPLES=OFF -DGLFW_BUILD_TESTS=OFF -DGLFW_BUILD_DOCS=OFF -DCMAKE_INSTALL_PREFIX=$HOME/glfw
|
||||
make
|
||||
@ -67,17 +92,18 @@ install: |
|
||||
cd ..
|
||||
fi
|
||||
pkg-config --cflags glfw3
|
||||
if [[ "$TRAVIS_OS_NAME" != 'osx' ]]; then
|
||||
PLIB=$(ldd `which python` | grep libpython | cut -d ' ' -f 3)
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`dirname $PLIB`
|
||||
fi
|
||||
set +e
|
||||
|
||||
env:
|
||||
global:
|
||||
- PKG_CONFIG_PATH=$HOME/glfw/lib/pkgconfig
|
||||
- LD_LIBRARY_PATH=$HOME/glfw/lib
|
||||
- ASAN_OPTIONS=leak_check_at_exit=0
|
||||
- PYTHON=python3
|
||||
before_script:
|
||||
- $PYTHON setup.py build --debug $ASAN_ARG;
|
||||
- echo $LD_LIBRARY_PATH
|
||||
- $PYTHON setup.py build --debug $SANITIZE_ARG;
|
||||
- if [[ "$TRAVIS_OS_NAME" != 'osx' ]]; then ldd ./test-launcher `which $PYTHON`; fi
|
||||
|
||||
script:
|
||||
- LD_PRELOAD=$ASANLIB $PYTHON setup.py test
|
||||
- ./test-launcher
|
||||
- if [[ "$RUN_FLAKE" == "1" ]]; then flake8 --count .; fi
|
||||
- if [[ "$BUILD_PKG" == "1" ]]; then $PYTHON setup.py linux-package; fi
|
||||
|
||||
@ -140,7 +140,7 @@ static PyStructSequence_Field gm_fields[] = {
|
||||
};
|
||||
|
||||
static PyStructSequence_Desc gm_desc = {"GlpyhMetrics", NULL, gm_fields, 8};
|
||||
static PyTypeObject GlpyhMetricsType = {0};
|
||||
static PyTypeObject GlpyhMetricsType = {{{0}}};
|
||||
|
||||
static PyObject*
|
||||
glyph_metrics(Face *self) {
|
||||
@ -167,7 +167,7 @@ static PyStructSequence_Field bm_fields[] = {
|
||||
{NULL}
|
||||
};
|
||||
static PyStructSequence_Desc bm_desc = {"Bitmap", NULL, bm_fields, 7};
|
||||
static PyTypeObject BitmapType = {0};
|
||||
static PyTypeObject BitmapType = {{{0}}};
|
||||
|
||||
static PyObject*
|
||||
bitmap(Face *self) {
|
||||
|
||||
@ -95,7 +95,7 @@ index_type historybuf_push(HistoryBuf *self) {
|
||||
|
||||
bool
|
||||
historybuf_resize(HistoryBuf *self, index_type lines) {
|
||||
HistoryBuf t = {0};
|
||||
HistoryBuf t = {{0}};
|
||||
t.xnum=self->xnum;
|
||||
t.ynum=lines;
|
||||
if (t.ynum > 0 && t.ynum != self->ynum) {
|
||||
|
||||
@ -423,7 +423,7 @@ copy_old(LineBuf *self, PyObject *y) {
|
||||
if (!PyObject_TypeCheck(y, &LineBuf_Type)) { PyErr_SetString(PyExc_TypeError, "Not a LineBuf object"); return NULL; }
|
||||
LineBuf *other = (LineBuf*)y;
|
||||
if (other->xnum != self->xnum) { PyErr_SetString(PyExc_ValueError, "LineBuf has a different number of columns"); return NULL; }
|
||||
Line sl = {0}, ol = {0};
|
||||
Line sl = {{0}}, ol = {{0}};
|
||||
sl.xnum = self->xnum; ol.xnum = other->xnum;
|
||||
|
||||
for (index_type i = 0; i < MIN(self->ynum, other->ynum); i++) {
|
||||
|
||||
62
setup.py
62
setup.py
@ -53,7 +53,7 @@ def cc_version():
|
||||
ver = tuple(map(int, ver))
|
||||
except Exception:
|
||||
ver = (0, 0)
|
||||
return ver
|
||||
return cc, ver
|
||||
|
||||
|
||||
def get_python_flags(cflags):
|
||||
@ -88,36 +88,43 @@ def get_python_flags(cflags):
|
||||
return libs
|
||||
|
||||
|
||||
def init_env(debug=False, asan=False, native_optimizations=True):
|
||||
def get_sanitize_args(cc, ccver):
|
||||
sanitize_args = set()
|
||||
sanitize_args.add('-fno-omit-frame-pointer')
|
||||
sanitize_args.add('-fsanitize=address')
|
||||
if (cc == 'gcc' and ccver >= (5, 0)) or cc == 'clang':
|
||||
sanitize_args.add('-fsanitize=undefined')
|
||||
# if cc == 'gcc' or (cc == 'clang' and ccver >= (4, 2)):
|
||||
# sanitize_args.add('-fno-sanitize-recover=all')
|
||||
return sanitize_args
|
||||
|
||||
|
||||
def init_env(debug=False, sanitize=False, native_optimizations=True):
|
||||
global cflags, ldflags, cc, ldpaths
|
||||
native_optimizations = native_optimizations and not asan and not debug
|
||||
ccver = cc_version()
|
||||
native_optimizations = native_optimizations and not sanitize and not debug
|
||||
cc, ccver = cc_version()
|
||||
print('CC:', cc, ccver)
|
||||
stack_protector = '-fstack-protector'
|
||||
if ccver >= (4, 9):
|
||||
if ccver >= (4, 9) and cc == 'gcc':
|
||||
stack_protector += '-strong'
|
||||
missing_braces = ''
|
||||
if ccver < (5, 2):
|
||||
if ccver < (5, 2) and cc == 'gcc':
|
||||
missing_braces = '-Wno-missing-braces'
|
||||
cc = os.environ.get('CC', 'gcc')
|
||||
optimize = '-O3'
|
||||
if debug or asan:
|
||||
optimize = '-ggdb'
|
||||
if asan:
|
||||
optimize += ' -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer'
|
||||
optimize = '-ggdb' if debug or sanitize else '-O3'
|
||||
sanitize_args = get_sanitize_args(cc, ccver) if sanitize else set()
|
||||
cflags = os.environ.get(
|
||||
'OVERRIDE_CFLAGS', (
|
||||
'-Wextra -Wno-missing-field-initializers -Wall -std=c99 -D_XOPEN_SOURCE=700'
|
||||
' -pedantic-errors -Werror {} -DNDEBUG -fwrapv {} {} -pipe {}'
|
||||
' -pedantic-errors -Werror {} {} -DNDEBUG -fwrapv {} {} -pipe {}'
|
||||
).format(
|
||||
optimize, stack_protector, missing_braces, '-march=native'
|
||||
optimize, ' '.join(sanitize_args), stack_protector, missing_braces, '-march=native'
|
||||
if native_optimizations else ''
|
||||
)
|
||||
)
|
||||
cflags = shlex.split(cflags
|
||||
) + shlex.split(sysconfig.get_config_var('CCSHARED'))
|
||||
ldflags = os.environ.get(
|
||||
'OVERRIDE_LDFLAGS', '-Wall ' +
|
||||
('-fsanitize=address -fsanitize=undefined' if asan else ('' if debug else '-O3'))
|
||||
'OVERRIDE_LDFLAGS', '-Wall ' + ' '.join(sanitize_args) + ('' if debug else ' -O3')
|
||||
)
|
||||
ldflags = shlex.split(ldflags)
|
||||
cflags += shlex.split(os.environ.get('CFLAGS', ''))
|
||||
@ -230,11 +237,13 @@ def option_parser():
|
||||
help='Build extension modules with debugging symbols'
|
||||
)
|
||||
p.add_argument(
|
||||
'--asan',
|
||||
'--sanitize',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help='Turn on address sanitization to detect memory access errors. Note that if you do turn it on,'
|
||||
' you have to run kitty with the environment variable LD_PRELOAD=/usr/lib/libasan.so'
|
||||
help='Turn on sanitization to detect memory access errors and undefined behavior. Note that if you do turn it on,'
|
||||
' a special executable will be built for running the test suite. If you want to run normal kitty'
|
||||
' with sanitization, use LD_PRELOAD=libasan.so (for gcc) and'
|
||||
' LD_PRELOAD=/usr/lib/clang/4.0.0/lib/linux/libclang_rt.asan-x86_64.so (for clang, changing path as appropriate).'
|
||||
)
|
||||
p.add_argument(
|
||||
'--prefix',
|
||||
@ -268,7 +277,7 @@ def find_c_files():
|
||||
|
||||
|
||||
def build(args, native_optimizations=True):
|
||||
init_env(args.debug, args.asan, native_optimizations)
|
||||
init_env(args.debug, args.sanitize, native_optimizations)
|
||||
compile_c_extension(
|
||||
'kitty/fast_data_types', args.incremental, *find_c_files()
|
||||
)
|
||||
@ -281,6 +290,18 @@ def safe_makedirs(path):
|
||||
pass
|
||||
|
||||
|
||||
def build_test_launcher(args):
|
||||
cc, ccver = cc_version()
|
||||
cflags = '-g -Wall -Werror -fpie'.split()
|
||||
pylib = get_python_flags(cflags)
|
||||
sanitize_lib = (['-lasan'] if cc == 'gcc' else []) if args.sanitize else []
|
||||
cflags.extend(get_sanitize_args(cc, ccver) if args.sanitize else [])
|
||||
cmd = [cc] + cflags + [
|
||||
'test-launcher.c', '-o', 'test-launcher',
|
||||
] + sanitize_lib + pylib
|
||||
run_tool(cmd)
|
||||
|
||||
|
||||
def package(args, for_bundle=False): # {{{
|
||||
ddir = args.prefix
|
||||
libdir = os.path.join(ddir, 'lib', 'kitty')
|
||||
@ -360,6 +381,7 @@ def main():
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
if args.action == 'build':
|
||||
build(args)
|
||||
build_test_launcher(args)
|
||||
elif args.action == 'test':
|
||||
os.execlp(
|
||||
sys.executable, sys.executable, os.path.join(base, 'test.py')
|
||||
|
||||
13
test-launcher.c
Normal file
13
test-launcher.c
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* linux-launcher.c
|
||||
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
|
||||
*
|
||||
* Distributed under terms of the GPL3 license.
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
wchar_t *wargv[2] = {L"kitty-test", L"test.py"};
|
||||
return Py_Main(2, wargv);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user