From 390e8e0e225faaab079fe434f5cf869fcda08e85 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 11 Jun 2019 15:41:42 -0500 Subject: [PATCH 1/2] WebAssembly: Prepare library to be used with wasm32-wasi It is the changes I made to make compilation work for clang with "wasm32-wasi" target and the wasi-sdk. --- Makefile | 30 +++++++++++++++++++++++++++--- src/file.cpp | 16 ++++++++++++++++ src/plugins.cpp | 7 ++++++- src/plugins.hpp | 2 ++ src/sass.hpp | 5 +++++ wasm/libcxxabi_stubs.c | 25 +++++++++++++++++++++++++ 6 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 wasm/libcxxabi_stubs.c diff --git a/Makefile b/Makefile index 0c874e2c3b..25e69790d4 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,14 @@ else endif CAT ?= $(if $(filter $(OS),Windows_NT),type,cat) +ifdef WASM + CFLAGS += -D_WASM + CXXFLAGS += -D_WASM +endif + +ifdef WASM + UNAME := WebAssembly +else ifneq (,$(findstring /cygdrive/,$(PATH))) UNAME := Cygwin else @@ -44,6 +52,7 @@ endif endif endif endif +endif ifndef LIBSASS_VERSION ifneq ($(wildcard ./.git/ ),) @@ -163,18 +172,28 @@ ifeq (Windows,$(UNAME)) LIB_SHARED = $(SASS_LIBSASS_PATH)/lib/libsass.dll endif else +ifdef WASM + SASSC_BIN = $(SASS_SASSC_PATH)/bin/sassc.wasm + SHAREDLIB = lib/libsass.wasm + LIB_SHARED = $(SASS_LIBSASS_PATH)/lib/libsass.wasm +else ifneq (Cygwin,$(UNAME)) CFLAGS += -fPIC CXXFLAGS += -fPIC LDFLAGS += -fPIC endif endif +endif include Makefile.conf OBJECTS = $(addprefix src/,$(SOURCES:.cpp=.o)) COBJECTS = $(addprefix src/,$(CSOURCES:.c=.o)) RCOBJECTS = $(RESOURCES:.rc=.o) +ifdef WASM +WASMOBJECTS = wasm/libcxxabi_stubs.o +endif + DEBUG_LVL ?= NONE CLEANUPS ?= @@ -200,8 +219,8 @@ debug-shared: shared lib: $(MKDIR) lib -lib/libsass.a: $(COBJECTS) $(OBJECTS) | lib - $(AR) rcvs $@ $(COBJECTS) $(OBJECTS) +lib/libsass.a: $(COBJECTS) $(OBJECTS) $(WASMOBJECTS) | lib + $(AR) rcvs $@ $(COBJECTS) $(OBJECTS) $(WASMOBJECTS) lib/libsass.so: $(COBJECTS) $(OBJECTS) | lib $(CXX) -shared $(LDFLAGS) -o $@ $(COBJECTS) $(OBJECTS) $(LDLIBS) @@ -209,6 +228,9 @@ lib/libsass.so: $(COBJECTS) $(OBJECTS) | lib lib/libsass.dll: $(COBJECTS) $(OBJECTS) $(RCOBJECTS) | lib $(CXX) -shared $(LDFLAGS) -o $@ $(COBJECTS) $(OBJECTS) $(RCOBJECTS) $(LDLIBS) -s -Wl,--subsystem,windows,--out-implib,lib/libsass.a +lib/libsass.wasm: $(COBJECTS) $(OBJECTS) $(WASMOBJECTS) | lib + $(CXX) $(LDFLAGS) -o $@ $(COBJECTS) $(OBJECTS) $(WASMOBJECTS) $(LDLIBS) + %.o: %.c $(CC) $(CFLAGS) -c -o $@ $< @@ -271,7 +293,9 @@ $(SASSC_BIN): $(BUILD) $(MAKE) -C $(SASS_SASSC_PATH) build-$(BUILD)-dev sassc: $(SASSC_BIN) +ifndef WASM $(SASSC_BIN) -v +endif version: $(SASSC_BIN) $(SASSC_BIN) -v @@ -288,7 +312,7 @@ test_probe: $(SASSC_BIN) $(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass --probe-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR) clean-objects: | lib - -$(RM) lib/*.a lib/*.so lib/*.dll lib/*.la + -$(RM) lib/*.a lib/*.so lib/*.dll lib/*.la lib/*.wasm -$(RMDIR) lib clean: clean-objects $(RM) $(CLEANUPS) diff --git a/src/file.cpp b/src/file.cpp index 02e728031e..de0d2e7de7 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "file.hpp" #include "context.hpp" @@ -48,6 +49,15 @@ inline static std::string wstring_to_string(const std::wstring &wstr) # endif #endif +#ifdef _WASM +inline static std::string get_cwd_from_env() +{ + char* value = getenv("PWD"); + if (!value) return "/"; + return value; +} +#endif + namespace Sass { namespace File { @@ -56,6 +66,11 @@ namespace Sass { // always with trailing slash std::string get_cwd() { + #ifdef _WASM + // the WASI does not implement getcwd() yet -- + // check the environment variables or default to "/". + std::string cwd = get_cwd_from_env(); + #else const size_t wd_len = 4096; #ifndef _WIN32 char wd[wd_len]; @@ -72,6 +87,7 @@ namespace Sass { //convert backslashes to forward slashes replace(cwd.begin(), cwd.end(), '\\', '/'); #endif + #endif if (cwd[cwd.length() - 1] != '/') cwd += '/'; return cwd; } diff --git a/src/plugins.cpp b/src/plugins.cpp index b6f004242d..56ed6125ac 100644 --- a/src/plugins.cpp +++ b/src/plugins.cpp @@ -13,8 +13,10 @@ #include #include #include +#ifndef _WASM #include #endif +#endif namespace Sass { @@ -57,7 +59,7 @@ namespace Sass { // load one specific plugin bool Plugins::load_plugin (const std::string& path) { - +#ifdef ENABLE_LOAD_PLUGINS typedef const char* (*__plugin_version__)(void); typedef Sass_Function_List (*__plugin_load_fns__)(void); typedef Sass_Importer_List (*__plugin_load_imps__)(void); @@ -107,6 +109,9 @@ namespace Sass { std::cerr << "failed loading plugin <" << path << ">" << std::endl; if (const char* dlopen_error = dlerror()) std::cerr << dlopen_error << std::endl; } +#else + std::cerr << "plugins loading is unsupported <" << path << ">" << std::endl; +#endif return false; diff --git a/src/plugins.hpp b/src/plugins.hpp index fe4eed010c..4eb3196eaa 100644 --- a/src/plugins.hpp +++ b/src/plugins.hpp @@ -6,6 +6,7 @@ #include "utf8_string.hpp" #include "sass/functions.h" +#ifdef ENABLE_LOAD_PLUGINS #ifdef _WIN32 #define LOAD_LIB(var, path) HMODULE var = LoadLibraryW(UTF_8::convert_to_utf16(path).c_str()) @@ -24,6 +25,7 @@ #define CLOSE_LIB(var) dlclose(var) #endif +#endif namespace Sass { diff --git a/src/sass.hpp b/src/sass.hpp index 1598d954a1..7f1133ef26 100644 --- a/src/sass.hpp +++ b/src/sass.hpp @@ -38,6 +38,11 @@ # endif #endif +// enable loading of plugins for non-wasm +#ifndef _WASM +# define ENABLE_LOAD_PLUGINS +#endif + // path separation char #ifndef PATH_SEP # ifdef _WIN32 diff --git a/wasm/libcxxabi_stubs.c b/wasm/libcxxabi_stubs.c new file mode 100644 index 0000000000..ec6da71d63 --- /dev/null +++ b/wasm/libcxxabi_stubs.c @@ -0,0 +1,25 @@ +#include + +// -fno-exceptions is not an option with libsass yet, +// stubbing libc++abi functions + +void __cxa_throw(void *thrown_exception, void *tinfo, + void (*dest)(void *)) +{ + abort(); +} + +void *__cxa_allocate_exception(size_t thrown_size) +{ + abort(); +} + +void __cxa_rethrow() +{ + abort(); +} + +void* __cxa_begin_catch(void* exceptionObject) +{ + abort(); +} From 82ad4c53bc13e8d3b4e4038ddf5f66c30c7ea720 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 19 Jun 2019 09:15:34 -0700 Subject: [PATCH 2/2] Allow as CWD for preopen --- src/file.cpp | 12 +++++++----- src/sass.hpp | 2 ++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/file.cpp b/src/file.cpp index de0d2e7de7..d589f46a73 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -50,10 +50,10 @@ inline static std::string wstring_to_string(const std::wstring &wstr) #endif #ifdef _WASM -inline static std::string get_cwd_from_env() +inline static std::string get_cwd_from_env(const char* default_pwd) { char* value = getenv("PWD"); - if (!value) return "/"; + if (!value) return default_pwd; return value; } #endif @@ -68,8 +68,8 @@ namespace Sass { { #ifdef _WASM // the WASI does not implement getcwd() yet -- - // check the environment variables or default to "/". - std::string cwd = get_cwd_from_env(); + // check the environment variables or default to "./". + std::string cwd = get_cwd_from_env("./"); #else const size_t wd_len = 4096; #ifndef _WIN32 @@ -189,7 +189,9 @@ namespace Sass { while((pos = path.find("/./", pos)) != std::string::npos) path.erase(pos, 2); // remove all leading and trailing self references - while(path.size() >= 2 && path[0] == '.' && path[1] == '/') path.erase(0, 2); + #ifndef PREOPEN_COMPATIBLE + while(path.size() >= 2 && path[0] == '.' && path[1] == '/') path.erase(0, 2); + #endif while((pos = path.length()) > 1 && path[pos - 2] == '/' && path[pos - 1] == '.') path.erase(pos - 2); diff --git a/src/sass.hpp b/src/sass.hpp index 7f1133ef26..b7de522d25 100644 --- a/src/sass.hpp +++ b/src/sass.hpp @@ -41,6 +41,8 @@ // enable loading of plugins for non-wasm #ifndef _WASM # define ENABLE_LOAD_PLUGINS +#else +# define PREOPEN_COMPATIBLE #endif // path separation char