diff --git a/Makefile b/Makefile index 57df5fbe04..99b83c320e 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/ ),) @@ -166,18 +175,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 ?= @@ -203,8 +222,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) @@ -217,6 +236,9 @@ 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 $@ $< @@ -283,7 +305,9 @@ $(SASSC_BIN): $(BUILD) $(MAKE) -C $(SASS_SASSC_PATH) build-$(BUILD) sassc: $(SASSC_BIN) +ifndef WASM $(SASSC_BIN) -v +endif version: $(SASSC_BIN) $(SASSC_BIN) -v @@ -311,7 +335,7 @@ test_interactive: $(SASSC_BIN) --interactive $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR) clean-objects: | lib - -$(RM) lib/*.a lib/*.so lib/*.dll lib/*.dylib lib/*.la + -$(RM) lib/*.a lib/*.so lib/*.dll lib/*.dylib lib/*.la lib/*.wasm -$(RMDIR) lib clean: clean-objects $(RM) $(CLEANUPS) diff --git a/src/file.cpp b/src/file.cpp index 02e728031e..d589f46a73 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(const char* default_pwd) +{ + char* value = getenv("PWD"); + if (!value) return default_pwd; + 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; } @@ -173,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/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..b7de522d25 100644 --- a/src/sass.hpp +++ b/src/sass.hpp @@ -38,6 +38,13 @@ # endif #endif +// enable loading of plugins for non-wasm +#ifndef _WASM +# define ENABLE_LOAD_PLUGINS +#else +# define PREOPEN_COMPATIBLE +#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(); +}