diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..fa8e2b6a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM ubuntu:24.04 + +RUN apt update -y +RUN apt upgrade -y +RUN apt install flex bison g++ make libpng-dev libicu-dev -y + +RUN mkdir /context-free +WORKDIR /context-free +COPY Makefile . +COPY src-agg ./src-agg +COPY src-common ./src-common +COPY src-unix ./src-unix +COPY input ./input +RUN make +COPY ./runtests.sh . +RUN make test diff --git a/Makefile b/Makefile index 4d18c351..6ba82d34 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,6 @@ all: cfdg - # # Dirs # @@ -20,6 +19,7 @@ vpath %.cfdg input INC_DIRS = $(COMMON_DIR) $(UNIX_DIR) $(DERIVED_DIR) $(COMMON_DIR)/agg-extras INC_DIRS += /usr/local/include +#INC_DIRS += /usr/local/include /emsdk/local/include # # Installation directories @@ -35,6 +35,7 @@ MAN_DIR = $(DESTDIR)$(prefix)/share/man # LIB_DIRS = /usr/local/lib +#LIB_DIRS += /emsdk/local/lib # # Sources and Objects @@ -72,11 +73,17 @@ INPUT_SRCS = ciliasun_v2.cfdg demo1_v2.cfdg demo2_v2.cfdg funky_flower_v2.cfdg \ LIBS = png m # Use the first one for clang and the second one for gcc +ifeq ($(TARGET), wasm) + LIBS += c++ + #LIBS += c++ icui18n icuuc icudata +else ifeq ($(shell uname -s), Darwin) LIBS += c++ icucore else LIBS += stdc++ atomic icui18n icuuc icudata endif +endif + # # FFmpeg support @@ -114,6 +121,12 @@ DEPS = $(patsubst %.o,%.d,$(OBJS)) LINKFLAGS += $(patsubst %,-L%,$(LIB_DIRS)) LINKFLAGS += $(patsubst %,-l%,$(LIBS)) LINKFLAGS += -fexceptions +ifeq ($(TARGET), wasm) +ifeq ($(WASM_DEBUG), 1) + LINKFLAGS += -s EXCEPTION_DEBUG=1 -s SYSCALL_DEBUG=1 -s FS_DEBUG=1 -s ASSERTIONS=2 -g -gsource-map +endif + LINKFLAGS += -fexceptions -s SUPPORT_LONGJMP=emscripten -s USE_LIBPNG=1 -s USE_ICU=1 -s INVOKE_RUN=0 -s EXPORTED_RUNTIME_METHODS=callMain,FS -s ALLOW_MEMORY_GROWTH=1 -s STACK_SIZE=104857600 +endif deps: $(OBJ_DIR) $(DEPS) @@ -132,9 +145,15 @@ $(OBJS): $(OBJ_DIR)/Sentry # # Under Cygwin replace strip $@ with strip $@.exe +ifeq ($(TARGET), wasm) +STRIP = echo +else +STRIP = strip +endif + cfdg: $(OBJS) $(LINK.o) $^ $(LINKFLAGS) -o $@ - strip $@ + $(STRIP) $@ # @@ -184,10 +203,13 @@ uninstall: # Tests # -.PHONY: test check +.PHONY: test test-mpeg check test: cfdg ./runtests.sh +test-mpeg: cfdg + ./runtests-mpeg.sh + check: cfdg ./runtests.sh @@ -197,8 +219,8 @@ check: cfdg CXXFLAGS += $(patsubst %,-I%,$(INC_DIRS)) CXXFLAGS += -O2 -Wall -Wextra -Wno-parentheses -std=c++17 -CXXFLAGS += -g -D_GLIBCXX_USE_C99_MATH=1 -CPPFLAGS += -DNDEBUG +CXXFLAGS += -D_GLIBCXX_USE_C99_MATH=1 +#CPPFLAGS += -DNDEBUG # Add this for clang ifeq ($(shell uname -s), Darwin) @@ -208,6 +230,13 @@ ifeq ($(shell uname -s), Darwin) # LDFLAGS += -framework CoreFoundation -framework CoreVideo -framework CoreMedia -framework VideoToolbox endif +ifeq ($(TARGET), wasm) +CXXFLAGS += -DNOSYSCTL=1 -DNONORMALIZE=1 -fexceptions -s SUPPORT_LONGJMP=emscripten +ifeq ($(WASM_DEBUG), 1) +CXXFLAGS += -g -gsource-map +endif +endif + $(OBJ_DIR)/%.o : %.cpp $(COMPILE.cpp) $(OUTPUT_OPTION) $< diff --git a/README b/README index c613aaaa..bba64284 100644 --- a/README +++ b/README @@ -127,3 +127,38 @@ will install cfdg and the cfdg.1 man page in /usr/local. FFmpeg BUILD NOTES Check out README.ffmpeg for building ffmpeg and enabling ffmpeg support + +~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ +DOCKER BUILD NOTES + +You can build and run the Linux/Posix version of cfdg inside a docker container +by running the command: + + $ docker build . -f Dockerfile + +This will install the operating system and all the build tools (GCC, Make, etc) +inside an image, copy the cfdg files needed for the build, compile it, then run +the tests. Note that to use cfdg inside a container, you need to mount your +files/folders into the container then execute the cfdg command on the mounted +files. + +~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ +WEBASSEMBLY + +You can compile cfdg to wasm by running the command: + + $ docker build . -f Wasm.Dockerfile + +This will install the operating system and all the build tools (Emscripten and +friends), then build and test cfdg wasm scripts/libraries. + +At the end, the docker file will produce two artifacts: + +(1) The browser-suitable library: + /context-free/web/cfdg.js + +(2) NodeJS executable script: + /context-free/cfdg + +The executable script is used for running the tests. The web library is not +tested here. diff --git a/Wasm.Dockerfile b/Wasm.Dockerfile new file mode 100644 index 00000000..1fbb9ba7 --- /dev/null +++ b/Wasm.Dockerfile @@ -0,0 +1,39 @@ +FROM ubuntu:24.04 + +RUN apt update -y +RUN apt upgrade -y +RUN apt install git -y +RUN git clone --depth=1 https://github.com/emscripten-core/emsdk.git +WORKDIR /emsdk +RUN apt install python3 -y +RUN apt install xz-utils -y +RUN ./emsdk install latest +RUN ./emsdk activate latest +ENV EMSDK=/emsdk +ENV PATH="/emsdk:/emsdk/upstream/emscripten:/emsdk/node/18.20.3_64bit/bin:${PATH}" +RUN echo 'int main(){return 0;}' > hello.cpp && em++ -s USE_LIBPNG=1 -s USE_ICU=1 hello.cpp && rm a.out.wasm a.out.js + +RUN apt install flex bison make g++ vim -y + +RUN cp /usr/include/FlexLexer.h /usr/local/include + +RUN mkdir /context-free +WORKDIR /context-free +COPY Makefile . +COPY src-agg ./src-agg +COPY src-common ./src-common +COPY src-unix ./src-unix +RUN mkdir ./input +COPY ./input/*.cfdg ./input + +RUN TARGET=wasm LINKFLAGS='-s ENVIRONMENT=web,worker -s WASM=1 -s SINGLE_FILE=1' emmake make +RUN mkdir web && mv cfdg cfdg.js && mv cfdg.* web + +RUN TARGET=wasm LINKFLAGS='-lnodefs.js -lnoderawfs.js' emmake make +RUN mv cfdg cfdg.js +COPY src-js/main.js cfdg +RUN touch cfdg # avoid make recompiling stuff +COPY ./input/*.SKIP ./input +COPY ./input/tests ./input/tests +COPY ./runtests.sh . +RUN make test diff --git a/runtests-mpeg.sh b/runtests-mpeg.sh new file mode 100755 index 00000000..73ba75ca --- /dev/null +++ b/runtests-mpeg.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +./cfdg -a150 -s640x480 --quicktime -vffgh input/mtree.cfdg output/mtree.mpeg diff --git a/runtests.sh b/runtests.sh index 92934b7a..a42b431d 100755 --- a/runtests.sh +++ b/runtests.sh @@ -1,9 +1,8 @@ #!/bin/sh - mkdir output for file in input/tests/*.cfdg input/*.cfdg do - ./cfdg -qP "$file" output/test.png + ./cfdg -P "$file" output/test.png if [ $? -eq 0 ] then echo "$file pass" @@ -12,5 +11,4 @@ do break fi done -./cfdg -a150 -s640x480 --quicktime -vffgh input/mtree.cfdg output/mtree.mpeg diff --git a/src-js/main.js b/src-js/main.js new file mode 100755 index 00000000..2611a7fc --- /dev/null +++ b/src-js/main.js @@ -0,0 +1,15 @@ +#!/usr/bin/env node + +var cfdg = require('./cfdg.js'); +var fs = require('fs'); + +cfdg.onRuntimeInitialized = () => { + // console.log(cfdg); + // console.log(cfdg.FS); + // console.log(process.cwd()); + // console.log(cfdg.FS.cwd()); + // console.log(cfdg.FS.readdir(cfdg.FS.cwd())); + var [_node, _script, ...args] = [...process.argv]; + cfdg.callMain(args); +}; + diff --git a/src-unix/posixSystem.cpp b/src-unix/posixSystem.cpp index bb9bf971..0b083c72 100644 --- a/src-unix/posixSystem.cpp +++ b/src-unix/posixSystem.cpp @@ -36,6 +36,9 @@ #define UCHAR_TYPE char16_t #include #include +#include +#include // ICU header for UnicodeString + #include #include @@ -45,6 +48,7 @@ #include #include +#ifndef NOSYSCTL #if defined(__GNU__) || (defined(__ILP32__) && defined(__x86_64__)) #define NOSYSCTL #else @@ -52,6 +56,7 @@ #include #endif #endif +#endif #include #include #include @@ -219,6 +224,17 @@ PosixSystem::~PosixSystem() ucnv_close(mConverter); } +#ifdef NONORMALIZE +std::wstring +PosixSystem::normalize(const std::string& u8name) { + icu::UnicodeString ustr = icu::UnicodeString::fromUTF8(icu::StringPiece(u8name.c_str())); + std::wstring wstr(ustr.length(), L' '); + for (int32_t i = 0; i < ustr.length(); ++i) { + wstr[i] = ustr.charAt(i); + } + return wstr; +} +#else std::wstring PosixSystem::normalize(const std::string& u8name) { @@ -226,13 +242,14 @@ PosixSystem::normalize(const std::string& u8name) UErrorCode status = U_ZERO_ERROR; if (!mConverter) mConverter = ucnv_open("utf-8", &status); - if (!mNormalizer && U_SUCCESS(status)) + if (U_FAILURE(status)) { + catastrophicError("No Converter"); + } + if (!mNormalizer) mNormalizer = unorm2_getNFKCInstance(&status); - if (!mConverter || !mNormalizer) { - if (!mErrorReported) - catastrophicError("String conversion initialization error"); - mErrorReported = true; - return std::wstring(); + if (U_FAILURE(status)) { + std::cerr << "Error getting NFKC normalizer: " << u_errorName(status) << std::endl; + catastrophicError("No Normalizer"); } // Convert from utf-8 to utf-16 @@ -273,4 +290,4 @@ PosixSystem::normalize(const std::string& u8name) } return ret; } - +#endif