support Windows by using the bundled libunwind

- use static libraries instead of "compile" pragmas
This commit is contained in:
Ștefan Talpalaru 2019-12-19 21:14:59 +01:00
parent d298f29528
commit c04aedb805
No known key found for this signature in database
GPG Key ID: CBF7934204F1B6F9
10 changed files with 116 additions and 59 deletions

View File

@ -30,7 +30,7 @@ install:
- curl -o vendor\libbacktrace\config.sub -L -s -S "http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD"
test_script:
- mingw32-make -j2 V=1 test
- mingw32-make -j2 test
build: off
deploy: off

109
Makefile
View File

@ -27,29 +27,53 @@ ifneq ($(USE_SYSTEM_LIBS), 0)
endif
ECHO_AND_RUN = echo -e "\n$(CMD)\n"; $(CMD) $(MACOS_DEBUG_SYMBOLS) && ./build/$@
LIBDIR := install/usr/lib
INCLUDEDIR := install/usr/include
CFLAGS += -g -O3 -std=gnu99 -pipe -Wall -Wextra
CXXFLAGS += -g -O3 -std=gnu++11 -pipe -Wall -Wextra
CPPFLAGS := -I"$(CURDIR)/$(INCLUDEDIR)"
LDLIBS := -L"$(CURDIR)/$(LIBDIR)"
AR := ar
# for Mingw-w64
CC := gcc
CXX := g++
TESTS := test1
.PHONY: all libbacktrace libunwind clean test $(TESTS)
.PHONY: all clean test $(TESTS)
ifeq ($(USE_SYSTEM_LIBS), 0)
all: libbacktrace
LIBBACKTRACE_DEP := $(LIBDIR)/libbacktrace.a
else
all:
LIBBACKTRACE_DEP :=
endif
$(SILENT_TARGET_PREFIX).SILENT:
all: $(LIBBACKTRACE_DEP) $(LIBDIR)/libbacktracenim.a $(LIBDIR)/libbacktracenimcpp.a
libbacktrace: install/usr/lib/libbacktrace.a
$(LIBDIR)/libbacktracenim.a: libbacktrace_wrapper.o | $(LIBDIR)
echo -e $(BUILD_MSG) "$@" && \
rm -f $@ && \
$(AR) rcs $@ $<
# it doesn't link to libbacktrace.a, but it needs the headers installed by that target
libbacktrace_wrapper.o: libbacktrace_wrapper.c $(LIBBACKTRACE_DEP)
$(LIBDIR)/libbacktracenimcpp.a: libbacktrace_wrapper_cpp.o | $(LIBDIR)
echo -e $(BUILD_MSG) "$@" && \
rm -f $@ && \
$(AR) rcs $@ $<
# implicit rule doesn't kick in
libbacktrace_wrapper_cpp.o: libbacktrace_wrapper.cpp $(LIBBACKTRACE_DEP)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
$(LIBDIR):
mkdir -p $@
#########
# macOS #
#########
ifeq ($(shell uname), Darwin)
# libbacktrace needs to find libunwind during compilation
export CPPFLAGS := $(CPPFLAGS) -I"$(CURDIR)/install/usr/include"
export LDFLAGS := $(LDFLAGS) -L"$(CURDIR)/install/usr/lib"
# TODO: disable when this issue is fixed: https://github.com/nim-lang/Nim/issues/12735
MACOS_DEBUG_SYMBOLS = && dsymutil build/$@
@ -57,38 +81,59 @@ BUILD_MSG := "Building:"
#- macOS Clang needs the LLVM libunwind variant
# (GCC comes with its own, in libgcc_s.so.1, used even by Clang itself, on other platforms)
#- this library doesn't support parallel builds, hence the "-j1"
#- libtool can't handle paths with spaces on Windows, so we can't do `mingw32-make install`
install/usr/lib/libbacktrace.a: install/usr/lib/libunwind.a
else
install/usr/lib/libbacktrace.a:
USE_VENDORED_LIBUNWIND := 1
endif # macOS
echo -e $(BUILD_MSG) "libbacktrace" && \
###########
# Windows #
###########
ifeq ($(OS), Windows_NT)
BUILD_MSG := "Building:"
CPPFLAGS += -D__STDC_FORMAT_MACROS -D_WIN32_WINNT=0x0600
CMAKE_ARGS := -G "MinGW Makefiles" -DCMAKE_SH="CMAKE_SH-NOTFOUND"
# the GCC one doesn't seem to work on 64 bit Windows
USE_VENDORED_LIBUNWIND := 1
LIBBACKTRACE_SED := sed -i 's/\$$[({]SHELL[)}]/"$$(SHELL)"/g' Makefile
else
LIBBACKTRACE_SED := true
endif # Windows
ifeq ($(USE_VENDORED_LIBUNWIND), 1)
# libbacktrace needs to find libunwind during compilation
export CPPFLAGS
export LDLIBS
# CMake ignores CPPFLAGS in the environment
export CFLAGS += $(CPPFLAGS)
export CXXFLAGS += $(CPPFLAGS)
#- this library doesn't support parallel builds, hence the "-j1"
#- the "Git for Windows" Bash is usually installed in a path with spaces, which messes up the Makefile. Add quotes.
$(LIBDIR)/libbacktrace.a: $(LIBDIR)/libunwind.a
else
$(LIBDIR)/libbacktrace.a:
endif # USE_VENDORED_LIBUNWIND
echo -e $(BUILD_MSG) "$@" && \
cd vendor/libbacktrace && \
./configure --prefix="/usr" --disable-shared --enable-static MAKE="$(MAKE)" $(HANDLE_OUTPUT) && \
$(MAKE) -j1 clean all $(HANDLE_OUTPUT) && \
mkdir -p "$(CURDIR)"/install/usr/{include,lib} && \
cp -a backtrace.h backtrace-supported.h "$(CURDIR)/install/usr/include/" && \
cp -a .libs/libbacktrace.a libbacktrace.la "$(CURDIR)/install/usr/lib/"
$(LIBBACKTRACE_SED) && \
$(MAKE) -j1 DESTDIR="$(CURDIR)/install" clean all install $(HANDLE_OUTPUT)
libunwind: install/usr/lib/libunwind.a
install/usr/lib/libunwind.a:
+ echo -e $(BUILD_MSG) "libunwind" && \
# DESTDIR does not work on Windows for a CMake-generated Makefile
$(LIBDIR)/libunwind.a:
+ echo -e $(BUILD_MSG) "$@" && \
cd vendor/libunwind && \
rm -f CMakeCache.txt && \
cmake -DLIBUNWIND_ENABLE_SHARED=OFF -DLIBUNWIND_ENABLE_STATIC=ON -DLIBUNWIND_INCLUDE_DOCS=OFF \
-DLIBUNWIND_LIBDIR_SUFFIX="" -DCMAKE_INSTALL_PREFIX=/usr . $(HANDLE_OUTPUT) && \
$(MAKE) DESTDIR="$(CURDIR)/install" clean install $(HANDLE_OUTPUT) && \
-DLIBUNWIND_LIBDIR_SUFFIX="" -DCMAKE_INSTALL_PREFIX="$(CURDIR)/install/usr" $(CMAKE_ARGS) . $(HANDLE_OUTPUT) && \
$(MAKE) VERBOSE=$(V) clean install $(HANDLE_OUTPUT) && \
cp -a include "$(CURDIR)/install/usr/"
test: $(TESTS)
ifeq ($(USE_SYSTEM_LIBS), 0)
$(TESTS): libbacktrace
else
$(TESTS):
endif
$(TESTS): all
$(eval CMD := nim c $(NIM_PARAMS) tests/$@.nim) $(ECHO_AND_RUN)
$(eval CMD := nim c $(NIM_PARAMS) --debugger:native tests/$@.nim) $(ECHO_AND_RUN)
$(eval CMD := nim c $(NIM_PARAMS) --debugger:native --stackTrace:off tests/$@.nim) $(ECHO_AND_RUN)
@ -99,5 +144,7 @@ endif
$(eval CMD := nim cpp $(NIM_PARAMS) --debugger:native tests/$@.nim) $(ECHO_AND_RUN)
clean:
rm -rf install build
rm -rf install build *.o
$(SILENT_TARGET_PREFIX).SILENT:

View File

@ -38,10 +38,8 @@ power!)
## Supported platforms
Tested with GCC and LLVM on Linux and macOS.
libbacktrace can't find debugging symbols in Mingw-w64 8.1.0 (posix-seh-rev0)
64-bit PE-COFF binaries, for some unknown reason.
Tested with GCC and LLVM on Linux, macOS and Windows (with Mingw-w64 and the
MSYS that comes with "Git for Windows").
## Usage
@ -86,8 +84,7 @@ You need Make, CMake and, of course, Nim up and running.
The other dependencies are bundled, for your convenience. We use a [libbacktrace
fork](https://github.com/rust-lang-nursery/libbacktrace/tree/rust-snapshot-2018-05-22)
with macOS support and [LLVM's libunwind
variant](https://github.com/llvm-mirror/libunwind) that's only needed on,
you've guessed it, macOS.
variant](https://github.com/llvm-mirror/libunwind) that's needed on macOS and Windows.
If you know better and want to use your system's libbacktrace package instead
of the bundled one, you can, with `make USE_SYSTEM_LIBS=1` and by passing

View File

@ -1,7 +1,7 @@
# Copyright (c) 2019 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
# * Apache License, version 2.0,
# * MIT license
# at your option.
# This file may not be copied, modified, or distributed except according to
# those terms.
@ -12,22 +12,23 @@
import libbacktrace_wrapper, os, system/ansi_c
const installPath = currentSourcePath.parentDir() / "install" / "usr"
{.passc: "-I" & currentSourcePath.parentDir().}
when defined(cpp):
{.compile: "libbacktrace_wrapper.cpp".}
{.passl: installPath / "lib" / "libbacktracenimcpp.a".}
else:
{.compile: "libbacktrace_wrapper.c".}
{.passl: installPath / "lib" / "libbacktracenim.a".}
when defined(libbacktraceUseSystemLibs):
{.passl: "-lbacktrace".}
when defined(macosx):
{.passl: "-lunwind".}
else:
const installPath = currentSourcePath.parentDir() / "install" / "usr"
{.passc: "-I" & installPath / "include".}
{.passl: installPath / "lib" / "libbacktrace.a".}
when defined(macosx):
when defined(macosx) or defined(windows):
{.passl: installPath / "lib" / "libunwind.a".}

View File

@ -1,7 +1,7 @@
# Copyright (c) 2019 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
# * Apache License, version 2.0,
# * MIT license
# at your option.
# This file may not be copied, modified, or distributed except according to
# those terms.

View File

@ -1,8 +1,8 @@
/*
* Copyright (c) 2019 Status Research & Development GmbH
* Licensed under either of
* * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
* * MIT license ([LICENSE-MIT](LICENSE-MIT))
* * Apache License, version 2.0,
* * MIT license
* at your option.
* This file may not be copied, modified, or distributed except according to
* those terms.
@ -11,18 +11,30 @@
#include <backtrace-supported.h>
#include <backtrace.h>
#include <errno.h>
#include <inttypes.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libbacktrace_wrapper.h"
// https://stackoverflow.com/a/44383330
#ifdef _WIN32
# ifdef _WIN64
# define PRI_SIZET PRIu64
# else
# define PRI_SIZET PRIu32
# endif
#else
# define PRI_SIZET "zu"
#endif
// macOS Clang wants this before the WAI_MALLOC define
static void *xmalloc(size_t size)
{
void *res = malloc(size);
if (res == NULL) {
fprintf(stderr, "FATAL: malloc() failed to allocate %lu bytes.\n", size);
fprintf(stderr, "FATAL: malloc() failed to allocate %" PRI_SIZET " bytes.\n", size);
exit(1);
}
return res;
@ -198,7 +210,7 @@ char *get_backtrace_c(void)
// using https://github.com/gpakosz/whereami
int self_exec_path_length = wai_getExecutablePath(NULL, 0, NULL);
if (self_exec_path_length == -1)
return "whereami error: could not get the program's path on this platform.\n";
return xstrdup("whereami error: could not get the program's path on this platform.\n");
char *self_exec_path = (char*)xmalloc(self_exec_path_length + 1);
wai_getExecutablePath(self_exec_path, self_exec_path_length, NULL);
self_exec_path[self_exec_path_length] = '\0';
@ -215,7 +227,7 @@ char *get_backtrace_c(void)
if (cb_data.state != NULL)
backtrace_full(cb_data.state, 2, success_callback, error_callback, &cb_data);
else
return ""; // the error callback has already been called
return xstrdup(""); // the error callback has already been called
if (cb_data.bt_lineno == MAX_BACKTRACE_LINES)
cb_data.bt_lineno--;

View File

@ -1,8 +1,8 @@
/*
* Copyright (c) 2019 Status Research & Development GmbH
* Licensed under either of
* * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
* * MIT license ([LICENSE-MIT](LICENSE-MIT))
* * Apache License, version 2.0,
* * MIT license
* at your option.
* This file may not be copied, modified, or distributed except according to
* those terms.

View File

@ -1,8 +1,8 @@
/*
* Copyright (c) 2019 Status Research & Development GmbH
* Licensed under either of
* * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
* * MIT license ([LICENSE-MIT](LICENSE-MIT))
* * Apache License, version 2.0,
* * MIT license
* at your option.
* This file may not be copied, modified, or distributed except according to
* those terms.

View File

@ -1,7 +1,7 @@
# Copyright (c) 2019 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
# * Apache License, version 2.0,
# * MIT license
# at your option.
# This file may not be copied, modified, or distributed except according to
# those terms.

View File

@ -1,7 +1,7 @@
# Copyright (c) 2019 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
# * Apache License, version 2.0,
# * MIT license
# at your option.
# This file may not be copied, modified, or distributed except according to
# those terms.