diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index dd731e5e..bedbfabb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -35,6 +35,8 @@ jobs: cp /opt/flang/emfc ./host/bin/emfc - name: Setup Emscripten PATH run: echo "/opt/emsdk:/opt/emsdk/upstream/emscripten" >> $GITHUB_PATH + - name: Set Emscripten EM_NODE_JS + run: echo "EM_NODE_JS=$(which node)" >> $GITHUB_ENV - name: Set the webR CDN URL as the BASE_URL run: echo "BASE_URL=https://webr.r-wasm.org/${{ github.ref_name }}/" > "$HOME/.webr-config.mk" shell: bash diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 7a3fd7dc..8003242a 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -26,6 +26,8 @@ jobs: cp /opt/flang/emfc ./host/bin/emfc - name: Setup Emscripten PATH run: echo "/opt/emsdk:/opt/emsdk/upstream/emscripten" >> $GITHUB_PATH + - name: Set Emscripten EM_NODE_JS + run: echo "EM_NODE_JS=$(which node)" >> $GITHUB_ENV - name: Build webR env: EMSDK: /opt/emsdk diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9be40108..f887eae7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,6 +25,8 @@ jobs: cp /opt/flang/emfc ./host/bin/emfc - name: Setup Emscripten PATH run: echo "/opt/emsdk:/opt/emsdk/upstream/emscripten" >> $GITHUB_PATH + - name: Set Emscripten EM_NODE_JS + run: echo "EM_NODE_JS=$(which node)" >> $GITHUB_ENV - name: Build webR env: EMSDK: /opt/emsdk diff --git a/R/Makefile b/R/Makefile index a22a3cd8..6a0f9daf 100644 --- a/R/Makefile +++ b/R/Makefile @@ -30,8 +30,17 @@ WASM_OPT ?= -Oz WASM_OPT_LDADD ?= $(WASM_OPT) WASM_OPT_LDADD += -s DECLARE_ASM_MODULE_EXPORTS=0 +WASM_CPPFLAGS := $(WASM_CPPFLAGS) +WASM_CPPFLAGS += -fwasm-exceptions +WASM_CPPFLAGS += -s SUPPORT_LONGJMP=wasm + WASM_CFLAGS := $(WASM_CFLAGS) -WASM_CFLAGS += -fPIC -fno-exceptions -fno-rtti $(WASM_OPT) +WASM_CFLAGS += $(WASM_OPT) +WASM_CFLAGS += -fPIC + +WASM_LDFLAGS := $(WASM_LDFLAGS) +WASM_LDFLAGS += -fwasm-exceptions +WASM_LDFLAGS += -s SUPPORT_LONGJMP=wasm .PHONY: all all: R @@ -93,6 +102,7 @@ $(BUILD)/state/R-$(R_VERSION)/r-stage1: $(BUILD)/state/R-$(R_VERSION)/r-stage1-c touch $@ STAGE2_CPPFLAGS := $(STAGE2_CPPFLAGS) +STAGE2_CPPFLAGS += $(WASM_CPPFLAGS) STAGE2_CPPFLAGS += -I$(WASM)/include STAGE2_CPPFLAGS += -DEXPEL_OLD_TO_NEW=1 STAGE2_CPPFLAGS += -s USE_BZIP2=1 @@ -100,9 +110,11 @@ STAGE2_CPPFLAGS += -s USE_ZLIB=1 STAGE2_CPPFLAGS += -s USE_FREETYPE=1 STAGE2_CFLAGS := $(STAGE2_CFLAGS) -STAGE2_CFLAGS += $(STAGE2_CPPFLAGS) $(WASM_CFLAGS) +STAGE2_CFLAGS += $(WASM_CFLAGS) +STAGE2_CFLAGS += $(STAGE2_CPPFLAGS) STAGE2_LDFLAGS := $(STAGE2_LDFLAGS) +STAGE2_LDFLAGS += $(WASM_LDFLAGS) STAGE2_LDFLAGS += -L$(WASM)/lib STAGE2_LDFLAGS +=-s USE_FREETYPE=1 diff --git a/libs/Makefile b/libs/Makefile index 36f05564..381102ea 100644 --- a/libs/Makefile +++ b/libs/Makefile @@ -9,20 +9,48 @@ TOOLS = $(WEBR_ROOT)/tools HOST = $(WEBR_ROOT)/host WASM = $(WEBR_ROOT)/wasm -export EM_PKG_CONFIG_PATH = $(WASM)/lib/pkgconfig +EM_LIBS := -s USE_BZIP2=1 +EM_LIBS += -s USE_ZLIB=1 WASM_OPT ?= -Oz WASM_OPT_LDADD ?= $(WASM_OPT) +WASM_COMMON_FLAGS := $(WASM_OPT) +WASM_COMMON_FLAGS += -fPIC +WASM_COMMON_FLAGS += -fwasm-exceptions +WASM_COMMON_FLAGS += -s SUPPORT_LONGJMP=wasm + WASM_CFLAGS := $(WASM_CFLAGS) -WASM_CFLAGS += -fPIC -fno-exceptions -fno-rtti $(WASM_OPT) -WASM_CFLAGS += -s USE_BZIP2=1 -s USE_ZLIB=1 +WASM_CFLAGS += $(WASM_COMMON_FLAGS) + +WASM_CXXFLAGS := $(WASM_CXXFLAGS) +WASM_CXXFLAGS += $(WASM_COMMON_FLAGS) + +WASM_CPPFLAGS := $(WASM_CPPFLAGS) +WASM_CPPFLAGS += -I$(WASM)/include +WASM_CPPFLAGS += $(EM_LIBS) + +WASM_LDFLAGS := $(WASM_LDFLAGS) +WASM_LDFLAGS += -L$(WASM)/lib +WASM_LDFLAGS += $(EM_LIBS) +WASM_LDFLAGS += -fwasm-exceptions +WASM_LDFLAGS += -s SUPPORT_LONGJMP=wasm + +export CPPFLAGS = $(WASM_CPPFLAGS) +export CFLAGS = $(WASM_CFLAGS) +export CXXFLAGS = $(WASM_CXXFLAGS) +export LDFLAGS = $(WASM_LDFLAGS) +export EM_PKG_CONFIG_PATH = $(WASM)/lib/pkgconfig include recipes/**/targets.mk include recipes/**/rules.mk -all: $(DEFAULT_WASM_LIBS) $(WASM)/usr/share/fonts -.DEFAULT_GOAL := all +.PHONY: default +default: $(DEFAULT_WASM_LIBS) $(WASM)/usr/share/fonts +.DEFAULT_GOAL := default + +.PHONY: all +all: default $(OPTIONAL_WASM_LIBS) $(EM_PKG_CONFIG_PATH)/%.pc: recipes/**/%.pc mkdir -p $(EM_PKG_CONFIG_PATH) @@ -32,6 +60,7 @@ $(EM_PKG_CONFIG_PATH)/%.pc: recipes/**/%.pc clean: rm -rf $(DOWNLOAD) $(BUILD) rm -f $(DEFAULT_WASM_LIBS) + rm -f $(OPTIONAL_WASM_LIBS) rm -f $(EM_PKG_CONFIG_PATH)/*.pc # Print Makefile variable diff --git a/libs/recipes/cairo/rules.mk b/libs/recipes/cairo/rules.mk index 90a89b84..7b4c074b 100644 --- a/libs/recipes/cairo/rules.mk +++ b/libs/recipes/cairo/rules.mk @@ -16,8 +16,8 @@ $(CAIRO_WASM_LIB): $(CAIRO_TARBALL) $(PIXMAN_WASM_LIB) $(FC_DEPS) cp -r "$(WEBR_ROOT)/patches/cairo-$(CAIRO_VERSION)/." \ "$(BUILD)/cairo-$(CAIRO_VERSION)/patches" cd $(BUILD)/cairo-$(CAIRO_VERSION)/build && quilt push -a && \ - CFLAGS="$(WASM_CFLAGS) -DCAIRO_NO_MUTEX=1" \ - LDFLAGS="-sUSE_FREETYPE=1 -sUSE_PTHREADS=0" \ + CFLAGS="$(CFLAGS) -DCAIRO_NO_MUTEX=1" \ + LDFLAGS="$(LDFLAGS) -sUSE_FREETYPE=1 -sUSE_PTHREADS=0" \ emconfigure ../configure \ ax_cv_c_float_words_bigendian=no \ --enable-shared=no \ diff --git a/libs/recipes/fontconfig/rules.mk b/libs/recipes/fontconfig/rules.mk index 815ad16e..a78b62b2 100644 --- a/libs/recipes/fontconfig/rules.mk +++ b/libs/recipes/fontconfig/rules.mk @@ -13,8 +13,7 @@ $(FC_DEPS): $(FC_TARBALL) $(LIBXML2_WASM_LIB) $(EM_PKG_CONFIG_PATH)/freetype2.pc mkdir -p $(BUILD)/fontconfig-$(FC_VERSION)/build tar -C $(BUILD) -xf $(FC_TARBALL) --exclude=fcobjshash.h cd $(BUILD)/fontconfig-$(FC_VERSION)/build && \ - CFLAGS="$(WASM_CFLAGS)" \ - LDFLAGS="-sUSE_FREETYPE=1 -sUSE_PTHREADS=0" \ + LDFLAGS="$(LDFLAGS) -sUSE_FREETYPE=1 -sUSE_PTHREADS=0" \ PTHREAD_CFLAGS=" " \ emconfigure ../configure \ ac_cv_func_fstatfs=no \ diff --git a/libs/recipes/gdal/rules.mk b/libs/recipes/gdal/rules.mk new file mode 100644 index 00000000..8486a9d9 --- /dev/null +++ b/libs/recipes/gdal/rules.mk @@ -0,0 +1,45 @@ +GDAL_VERSION = 3.6.4 +GDAL_TARBALL = $(DOWNLOAD)/gdal-$(GDAL_VERSION).tar.gz +GDAL_URL = https://github.com/OSGeo/gdal/releases/download/v$(GDAL_VERSION)/gdal-$(GDAL_VERSION).tar.gz + +.PHONY: gdal +gdal: $(GDAL_WASM_LIB) + +$(GDAL_TARBALL): + mkdir -p $(DOWNLOAD) + wget $(GDAL_URL) -O $@ + +# https://gdal.org/development/building_from_source.html + +# There is one configure helper that makes an erroneous conclusion +# about the signature of an iconv function because building the test +# file fails with an unrelated Emscripten error about a missing symbol. +# To work around, we just fix the setting directly in `cpl_config.h`. + +# The `CONFIG_DEP_LIBS` field in `gdal-config` needs two edits. First +# remove `-lproj` to avoid duplicates in build command that include +# both `gdal-config --dep-libs` and `pkg-config proj --libs`. +# Emscripten expands those flags to the `libproj.a` archive file, +# which causes duplicate symbols errors. +# +# Second, remove the `-L/path/to/emscripten/sysroot/wasm32-emscripten` +# flag. This directory contains non-fPIC libraries. Not sure why the +# `pic` subfolder isn't selected. + +$(GDAL_WASM_LIB): $(GDAL_TARBALL) $(PROJ_WASM_LIB) + mkdir -p $(BUILD)/gdal-$(GDAL_VERSION)/build + tar -C $(BUILD) -xf $(GDAL_TARBALL) + cd $(BUILD)/gdal-$(GDAL_VERSION)/build && \ + emcmake cmake --debug-find \ + -DCMAKE_FIND_ROOT_PATH=$(WASM) \ + -DCMAKE_INSTALL_PREFIX:PATH=$(WASM) \ + -DBUILD_TESTING=OFF \ + -DBUILD_APPS=OFF \ + -DGDAL_ENABLE_DRIVER_HDF5=OFF \ + -DGDAL_USE_HDF4=OFF \ + -DGDAL_USE_HDF5=OFF \ + .. && \ + sed -i.bak 's/#define ICONV_CPP_CONST const/#define ICONV_CPP_CONST/' port/cpl_config.h && \ + emmake make install && \ + sed -i.bak 's/\(^CONFIG_DEP_LIBS=.*\) -lproj\(.*\)/\1\2/' $(WASM)/bin/gdal-config && \ + sed -i.bak 's/\(^CONFIG_DEP_LIBS=.*\)-L.*wasm32-emscripten\(.*\)/\1 \2/' $(WASM)/bin/gdal-config diff --git a/libs/recipes/gdal/targets.mk b/libs/recipes/gdal/targets.mk new file mode 100644 index 00000000..e664d565 --- /dev/null +++ b/libs/recipes/gdal/targets.mk @@ -0,0 +1,2 @@ +GDAL_WASM_LIB = $(WASM)/lib/libgdal.a +OPTIONAL_WASM_LIBS += $(GDAL_WASM_LIB) diff --git a/libs/recipes/openssl/rules.mk b/libs/recipes/openssl/rules.mk index 732ba3d1..a819a617 100644 --- a/libs/recipes/openssl/rules.mk +++ b/libs/recipes/openssl/rules.mk @@ -13,7 +13,6 @@ $(OPENSSL_WASM_LIB): $(OPENSSL_TARBALL) mkdir -p $(BUILD)/openssl-openssl-$(OPENSSL_VERSION)/build tar -C $(BUILD) -xf $(OPENSSL_TARBALL) cd $(BUILD)/openssl-openssl-$(OPENSSL_VERSION)/build && \ - CFLAGS="$(WASM_CFLAGS)" \ emconfigure ../Configure \ darwin-i386 \ CC="cc" \ diff --git a/libs/recipes/openssl/targets.mk b/libs/recipes/openssl/targets.mk index d92c9c77..ac47fe22 100644 --- a/libs/recipes/openssl/targets.mk +++ b/libs/recipes/openssl/targets.mk @@ -1 +1,2 @@ OPENSSL_WASM_LIB = $(WASM)/lib/libssl.a +OPTIONAL_WASM_LIBS += $(OPENSSL_WASM_LIB) diff --git a/libs/recipes/pcre/rules.mk b/libs/recipes/pcre/rules.mk index b78d9b1b..b51b85d7 100644 --- a/libs/recipes/pcre/rules.mk +++ b/libs/recipes/pcre/rules.mk @@ -13,7 +13,6 @@ $(PCRE_WASM_LIB): $(PCRE_TARBALL) mkdir -p $(BUILD)/pcre2-$(PCRE_VERSION)/build tar -C $(BUILD) -xf $(PCRE_TARBALL) cd $(BUILD)/pcre2-$(PCRE_VERSION)/build && \ - CFLAGS="$(WASM_CFLAGS)" \ emconfigure ../configure \ --enable-shared=no \ --enable-static=yes \ diff --git a/libs/recipes/pixman/rules.mk b/libs/recipes/pixman/rules.mk index 8c4ae41e..e438ee23 100644 --- a/libs/recipes/pixman/rules.mk +++ b/libs/recipes/pixman/rules.mk @@ -15,7 +15,6 @@ $(PIXMAN_WASM_LIB): $(PIXMAN_TARBALL) $(LIBPNG_WASM_LIB) sed -i.bak 's/support_for_pthreads=yes/support_for_pthreads=no/g' \ $(BUILD)/pixman-$(PIXMAN_VERSION)/configure cd $(BUILD)/pixman-$(PIXMAN_VERSION)/build && \ - CFLAGS="$(WASM_CFLAGS)" \ emconfigure ../configure \ --enable-shared=no \ --enable-static=yes \ diff --git a/libs/recipes/png/rules.mk b/libs/recipes/png/rules.mk index 2750a800..ed1bb81d 100644 --- a/libs/recipes/png/rules.mk +++ b/libs/recipes/png/rules.mk @@ -13,7 +13,6 @@ $(LIBPNG_WASM_LIB): $(LIBPNG_TARBALL) $(EM_PKG_CONFIG_PATH)/zlib.pc mkdir -p $(BUILD)/libpng-$(LIBPNG_VERSION)/build tar -C $(BUILD) -xf $(LIBPNG_TARBALL) cd $(BUILD)/libpng-$(LIBPNG_VERSION)/build && \ - CFLAGS="$(WASM_CFLAGS)" \ emconfigure ../configure \ --enable-shared=no \ --enable-static=yes \ diff --git a/libs/recipes/proj/rules.mk b/libs/recipes/proj/rules.mk new file mode 100644 index 00000000..1f8455da --- /dev/null +++ b/libs/recipes/proj/rules.mk @@ -0,0 +1,37 @@ +PROJ_VERSION = 9.2.0 +PROJ_TARBALL = $(DOWNLOAD)/proj-$(PROJ_VERSION).tar.gz +PROJ_URL = https://github.com/OSGeo/PROJ/releases/download/$(PROJ_VERSION)/proj-$(PROJ_VERSION).tar.gz + +.PHONY: proj +proj: $(PROJ_WASM_LIB) + +$(PROJ_TARBALL): + mkdir -p $(DOWNLOAD) + wget -q -O $@ $(PROJ_URL) + +# https://github.com/OSGeo/PROJ/blob/master/docs/source/install.rst + +# Somehow `-DBUILD_APPS` doesn't work and we need to turn off each app +# individually. TIFF support is disabled but we probably should enable +# it once we have built libtiff as a wasm lib. +$(PROJ_WASM_LIB): $(PROJ_TARBALL) $(SQLITE3_WASM_LIB) + mkdir -p $(BUILD)/proj-$(PROJ_VERSION)/build + tar -C $(BUILD) -xf $(PROJ_TARBALL) + cd $(BUILD)/proj-$(PROJ_VERSION)/build && \ + emcmake cmake \ + -DCMAKE_INSTALL_PREFIX:PATH="$(WASM)" \ + -DSQLITE3_INCLUDE_DIR="$(WASM)/include" \ + -DSQLITE3_LIBRARY="$(SQLITE3_WASM_LIB)" \ + -DENABLE_TIFF=OFF \ + -DENABLE_CURL=OFF \ + -DBUILD_APPS=OFF \ + -DBUILD_CCT=OFF \ + -DBUILD_CS2CS=OFF \ + -DBUILD_GEOD=OFF \ + -DBUILD_GIE=OFF \ + -DBUILD_PROJ=OFF \ + -DBUILD_PROJINFO=OFF \ + -DBUILD_PROJSYNC=OFF \ + -DBUILD_TESTING=OFF \ + .. && \ + emmake make install diff --git a/libs/recipes/proj/targets.mk b/libs/recipes/proj/targets.mk new file mode 100644 index 00000000..c2c374a7 --- /dev/null +++ b/libs/recipes/proj/targets.mk @@ -0,0 +1,2 @@ +PROJ_WASM_LIB = $(WASM)/lib/libproj.a +OPTIONAL_WASM_LIBS += $(PROJ_WASM_LIB) diff --git a/libs/recipes/sqlite3/rules.mk b/libs/recipes/sqlite3/rules.mk new file mode 100644 index 00000000..191a58fe --- /dev/null +++ b/libs/recipes/sqlite3/rules.mk @@ -0,0 +1,22 @@ +SQLITE3_VERSION = 3.41.2 +SQLITE3_VERSION2 = 3410200 +SQLITE3_FILE_NAME = sqlite-autoconf-$(SQLITE3_VERSION2) +SQLITE3_TARBALL = $(DOWNLOAD)/$(SQLITE3_FILE_NAME).tar.gz +SQLITE3_URL = https://sqlite.org/2023/$(SQLITE3_FILE_NAME).tar.gz + +.PHONY: sqlite3 +sqlite3: $(SQLITE3_WASM_LIB) + +$(SQLITE3_TARBALL): + mkdir -p $(DOWNLOAD) + wget $(SQLITE3_URL) -O $@ + +$(SQLITE3_WASM_LIB): $(SQLITE3_TARBALL) + mkdir -p $(BUILD)/$(SQLITE3_FILE_NAME)/build + tar -C $(BUILD) -xf $(SQLITE3_TARBALL) + cd $(BUILD)/$(SQLITE3_FILE_NAME)/build && \ + emconfigure ../configure \ + --enable-shared=no \ + --enable-static=yes \ + --prefix=$(WASM) && \ + emmake make install diff --git a/libs/recipes/sqlite3/targets.mk b/libs/recipes/sqlite3/targets.mk new file mode 100644 index 00000000..82bc35a3 --- /dev/null +++ b/libs/recipes/sqlite3/targets.mk @@ -0,0 +1,2 @@ +SQLITE3_WASM_LIB = $(WASM)/lib/libsqlite3.a +OPTIONAL_WASM_LIBS += $(SQLITE3_WASM_LIB) diff --git a/libs/recipes/xml2/rules.mk b/libs/recipes/xml2/rules.mk index 62e4fe0f..4d9607bc 100644 --- a/libs/recipes/xml2/rules.mk +++ b/libs/recipes/xml2/rules.mk @@ -15,7 +15,6 @@ $(LIBXML2_WASM_LIB): $(LIBXML2_TARBALL) $(XZ_WASM_LIB) mkdir -p $(BUILD)/libxml2-$(LIBXML2_VERSION)/build tar -C $(BUILD) -xf $(LIBXML2_TARBALL) cd $(BUILD)/libxml2-$(LIBXML2_VERSION)/build && \ - CFLAGS="$(WASM_CFLAGS)" \ emconfigure ../configure \ --enable-shared=no \ --enable-static=yes \ diff --git a/libs/recipes/xz/rules.mk b/libs/recipes/xz/rules.mk index a213f0dd..688fd8af 100644 --- a/libs/recipes/xz/rules.mk +++ b/libs/recipes/xz/rules.mk @@ -13,7 +13,6 @@ $(XZ_WASM_LIB): $(XZ_TARBALL) mkdir -p $(BUILD)/xz-$(XZ_VERSION)/build tar -C $(BUILD) -xf $(XZ_TARBALL) cd $(BUILD)/xz-$(XZ_VERSION)/build && \ - CFLAGS="$(WASM_CFLAGS)" \ emconfigure ../configure \ --enable-shared=no \ --enable-static=yes \