diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 0f7926bad2..9e89cf8b69 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -2,8 +2,8 @@ "version": 1, "isRoot": true, "tools": { - "fantomas-tool": { - "version": "4.7.9", + "fantomas": { + "version": "6.2.0", "commands": [ "fantomas" ] diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000000..8f99df5399 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,106 @@ +# We use a custom dev container for Fable, because we want to be able to +# control the version of each target language we use. +# This also allow to have a consistent development environment for +# contributors and avoid problems like having some tools not compilable +# because of .NET specificities on OSX ARM for example. + +# To debug this DockerFile, you can use the following commands: +# +# Should be run from the .devcontainer folder +# +# Build the docker file with the fable-dev tag +# docker build --tag fable-dev . +# or if you want to see the progress (useful for debugging) +# docker build --tag fable-dev . --progress=plain +# +# Run the docker file and delete it on exit: +# docker run -it --rm fable-dev + +# Use x86_64 architecture to avoid all the small pains +# coming from alpine over ARM --platform=linux/amd64 +FROM mcr.microsoft.com/devcontainers/base:debian +# Install the xz-utils package +RUN apt-get update && apt-get install -y xz-utils + +# Options +# Let it here to avoid conflicts with Microsoft options !!! +ARG DOTNET_VERSION=6.0.406 +ARG NODE_VERSION=18.8.0 +ARG PYTHON_VERSION=3.11.5 +ARG DART_VERSION=3.1.2 + +USER vscode + +# Change the default shell to zsh +SHELL ["/bin/zsh", "-c"] + +# # Install .NET +WORKDIR /home/vscode +RUN sudo apt install wget +RUN wget -qO- https://dot.net/v1/dotnet-install.sh | bash -s - --version $DOTNET_VERSION +RUN echo "# Load dotnet path" >> .zshrc +RUN echo "export PATH=$PATH:/home/vscode/.dotnet" >> .zshrc +# Trigger the dotnet first run experience by running a command +RUN source .zshrc && dotnet --help +# Add dotnet zsh completion +COPY scripts/zsh_dotnet_completion.sh /home/vscode/zsh_dotnet_completion.sh +RUN cat /home/vscode/zsh_dotnet_completion.sh >> .zshrc +RUN rm /home/vscode/zsh_dotnet_completion.sh + +# Install Node.js +RUN wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash +# Even, if we changed the default shell to ZSH, nvm install script +# still uses bash, so we manually need to add the nvm path to zsh +RUN echo "# Load nvm path" >> .zshrc +RUN echo 'export NVM_DIR="$HOME/.nvm"' >> .zshrc +RUN echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm' >> .zshrc +RUN echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion"' >> .zshrc +# We need to source the zshrc and execute nvm install in the same RUN command +# Otherwise, the nvm command will not be available +RUN source .zshrc && nvm install $NODE_VERSION + +# Install python +# Install Python build dependencies +RUN sudo apt-get install -y build-essential libssl-dev zlib1g-dev \ +libbz2-dev libreadline-dev libsqlite3-dev curl \ +libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev +# Install pyenv +RUN curl https://pyenv.run | bash +RUN echo "# Load pyenv path" >> .zshrc +RUN echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc +RUN echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc +RUN echo 'eval "$(pyenv init -)"' >> ~/.zshrc +RUN source .zshrc && pyenv install $PYTHON_VERSION +# Make python point to the installed version +RUN source .zshrc && pyenv global $PYTHON_VERSION +RUN source .zshrc && curl -sSL https://install.python-poetry.org | python +RUN echo "# Load poetry path" >> .zshrc +RUN echo 'export PATH="$HOME/.local/bin:$PATH"' >> .zshrc + +# Install rust +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s - -y +RUN echo "# Load rust path" >> .zshrc +RUN echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> .zshrc + +# Instal dart +# Use custom dsm install script, because we broke it while +# trying to fix another issue with dsm +# See https://github.com/Yakiyo/dsm/issues/26 +COPY scripts/install_dsm.sh /home/vscode/install_dsm.sh +RUN sudo chmod +x /home/vscode/install_dsm.sh +RUN /home/vscode/install_dsm.sh +# RUN curl -fsSL https://dsm-vm.vercel.app/install.sh | bash +RUN echo "# Load dart path" >> .zshrc +RUN echo 'export PATH="/home/vscode/.dsm:$PATH"' >> .zshrc +RUN echo 'eval "`dsm env zsh`"' >> .zshrc +# Workaround dsm bug (see script for more details) +COPY scripts/install_dart.sh /home/vscode/install_dart.sh +RUN sudo chmod +x /home/vscode/install_dart.sh +RUN source .zshrc && /home/vscode/install_dart.sh $DART_VERSION +RUN source .zshrc && dsm use $DART_VERSION +RUN rm /home/vscode/install_dsm.sh +RUN rm /home/vscode/install_dart.sh + +# Force docker to load the zsh profile +# This should be the last steps +CMD [ "/bin/zsh" ] \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000000..6be9018a12 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,72 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/docker-outside-of-docker +{ + "name": "Docker outside of Docker", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + // "image": "mcr.microsoft.com/devcontainers/base:bullseye", + "build": { + "dockerfile": "Dockerfile" + }, + "customizations": { + "vscode": { + "extensions": [ + "Ionide.Ionide-fsharp", + "adpyke.codesnap", + "Dart-Code.dart-code", + "EditorConfig.EditorConfig", + "GitHub.copilot", + "christian-kohler.npm-intellisense", + "ionutvmi.path-autocomplete", + "ms-python.vscode-pylance", + "rust-lang.rust-analyzer", + "tintoy.msbuild-project-tools", + "eamodio.gitlens", + "tamasfe.even-better-toml" + ], + "settings": { + "terminal.integrated.defaultProfile.linux": "zsh", + // I don't know why but Ionide and C# extension don't find + // the installed dotnet version. + // For Ionide, we guide it using the following setting + "FSharp.dotnetRoot": "/home/vscode/.dotnet", + // For C#, we disable the warning as we don't seems to need it. + // If this is a problem, we can probably use the C#/F# dockerfile + // as the base and keep our way to install the different target version + // .NET included to respect the global.json requirements + "csharp.suppressDotnetInstallWarning": true + } + } + }, + + "mounts": [ + // Mount .npmrc from the host machine, to be able to use the host session + // This allow the user to login on their own machine once and not each time + // they build a new devcontainer + "source=${localEnv:HOME}${localEnv:USERPROFILE}/.npmrc,target=/home/vscode/.npmrc,type=bind,consistency=cached" + ], + + "containerEnv": { + // Expose the local environment variable to the container + // They are used for releasing and publishing from the container + "GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}", + "FABLE_NUGET_KEY": "${localEnv:FABLE_NUGET_KEY}" + }, + + // Restore the dotnet tools when the container is attached + // This makes fanomas available directly without having the user needing to + // run `dotnet tool restore` or build the project once + "postAttachCommand": "/bin/zsh -c 'source ~/.zshrc && dotnet tool restore'" + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "docker --version", + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root", + +} diff --git a/.devcontainer/scripts/install_dart.sh b/.devcontainer/scripts/install_dart.sh new file mode 100644 index 0000000000..75fd09fda0 --- /dev/null +++ b/.devcontainer/scripts/install_dart.sh @@ -0,0 +1,11 @@ +#!/bin/zsh + +# dsm seems to incorrectly detect the architecture on Mac M1 +# The if statement below is a workaround for this issue +# See https://github.com/Yakiyo/dsm/issues/26 + +if [[ $(uname -m) == 'aarch64' ]]; then + dsm install --arch arm64 $1; +else + dsm install $1; +fi \ No newline at end of file diff --git a/.devcontainer/scripts/install_dsm.sh b/.devcontainer/scripts/install_dsm.sh new file mode 100644 index 0000000000..6df0a17228 --- /dev/null +++ b/.devcontainer/scripts/install_dsm.sh @@ -0,0 +1,191 @@ +#!/bin/bash + +# set -e + +OS=$(echo `uname -s`|tr '[:upper:]' '[:lower:]') + +case "$OS" in + mingw*) OS='windows';; + msys*) OS='windows';; +esac + +VERSION="latest" +INSTALL_DIR="$HOME/.dsm" +FILE="" + +# TODO: Implement this +show_help() { + echo "dsm installation script" + echo "" + echo "USAGE:" + echo " ./install.sh [OPTIONS]" + echo "" + echo "OPTIONS:" + echo " -d, --install-dir Directory to install to." + echo " -s, --skip-shell Skip shell setup" + echo " -v, --version The version of dsm to install" + echo " -F, --filename Manually override the filename of dsm to use." + echo "" + echo "For any queries, help or bug, please open an issue at https://github.com/Yakiyo/dsm/issues" + + exit 0 +} + +clap() { + while [[ $# -gt 0 ]]; do + key="$1" + + case $key in + -h | --help) + show_help + ;; + -d | --install-dir) + INSTALL_DIR="$2" + shift + shift + ;; + -s | --skip-shell) + SKIP_SHELL="true" + shift + ;; + -v | --version) + VERSION="v$2" + shift + shift + ;; + -F | --filename) + FILENAME="$2" + shift + shift + ;; + *) + echo "Unrecognized argument $key. Use the `--help` flag to see usage" + exit 1 + ;; + esac + done +} + +# Duct taped this to somewhat work +filename() { + if [ "$OS" = "linux" ]; then + case "$(uname -m)" in + arm | armv7*) + FILENAME="arm-unknown-linux-gnueabihf" + ;; + *) + FILENAME="x86_64-unknown-linux-musl" + esac + elif [ "$OS" = "darwin" ]; then + FILENAME="x86_64-apple-darwin" + elif [ "$OS" = "windows" ]; then + FILENAME="x86_64-pc-windows-msvc.exe" + else + echo "OS $OS is not supported." + echo "If you think that's a bug - please file an issue to https://github.com/Yakiyo/dsm/issues" + exit 1 + fi + FILE="dsm-$FILENAME" +} + +download () { + if [ "$VERSION" = "latest" ]; then + URL="https://github.com/Yakiyo/dsm/releases/latest/download/$FILE" + else + URL="https://github.com/Yakiyo/dsm/releases/download/$VERSION/$FILE" + fi + echo "Downloading from $URL ...." + + TMP=$(mktemp -d) + mkdir -p "$INSTALL_DIR" &>/dev/null + + if ! curl --progress-bar --fail -L "$URL" -o "$TMP/$FILE"; then + echo "Download failed. Check that the release/filename are correct." + exit 1 + fi + + EXE="" + if [ "$OS" = "windows" ]; then + EXE=".exe" + fi + + mv "$TMP/$FILE" "$INSTALL_DIR/dsm$EXE" + + chmod u+x "$INSTALL_DIR/dsm$EXE" +} + +ensure_dir () { + local CONTAINING_DIR + CONTAINING_DIR="$(dirname "$1")" + if [ ! -d "$CONTAINING_DIR" ]; then + echo " >> Creating directory $CONTAINING_DIR" + mkdir -p "$CONTAINING_DIR" + fi +} + +# Courtesy of https://github.com/Schniz/fnm/blob/master/.ci/install.sh +setup_shell() { + CURRENT_SHELL="$(basename "$SHELL")" + + if [ "$CURRENT_SHELL" = "zsh" ]; then + CONF_FILE=${ZDOTDIR:-$HOME}/.zshrc + ensure_dir "$CONF_FILE" + echo "Installing for Zsh. Appending the following to $CONF_FILE:" + echo "" + echo ' # dsm' + echo ' export PATH="'"$INSTALL_DIR"':$PATH"' + echo ' eval "`dsm env zsh`"' + + echo '' >>$CONF_FILE + echo '# dsm' >>$CONF_FILE + echo 'export PATH="'$INSTALL_DIR':$PATH"' >>$CONF_FILE + echo 'eval "`dsm env zsh`"' >>$CONF_FILE + + elif [ "$CURRENT_SHELL" = "fish" ]; then + CONF_FILE=$HOME/.config/fish/conf.d/dsm.fish + ensure_dir "$CONF_FILE" + echo "Installing for Fish. Appending the following to $CONF_FILE:" + echo "" + echo ' # dsm' + echo ' set PATH "'"$INSTALL_DIR"'" $PATH' + echo ' dsm env fish | source' + + echo '# dsm' >>$CONF_FILE + echo 'set PATH "'"$INSTALL_DIR"'" $PATH' >>$CONF_FILE + echo 'dsm env fish | source' >>$CONF_FILE + + elif [ "$CURRENT_SHELL" = "bash" ]; then + if [ "$OS" = "darwin" ]; then + CONF_FILE=$HOME/.profile + else + CONF_FILE=$HOME/.bashrc + fi + ensure_dir "$CONF_FILE" + echo "Installing for Bash. Appending the following to $CONF_FILE:" + echo "" + echo ' # dsm' + echo ' export PATH="'"$INSTALL_DIR"':$PATH"' + echo ' eval "`dsm env bash`"' + + echo '' >>$CONF_FILE + echo '# dsm' >>$CONF_FILE + echo 'export PATH="'"$INSTALL_DIR"':$PATH"' >>$CONF_FILE + echo 'eval "`dsm env bash`"' >>$CONF_FILE + + else + echo "Could not infer shell type. Please set up manually." + exit 1 + fi + + echo "" + echo "In order to apply the changes, open a new terminal or run the following command:" + echo "" + echo " source $CONF_FILE" +} + +filename +clap "$@" +download +if [ "$SKIP_SHELL" != "true" ]; then + setup_shell +fi \ No newline at end of file diff --git a/.devcontainer/scripts/zsh_dotnet_completion.sh b/.devcontainer/scripts/zsh_dotnet_completion.sh new file mode 100644 index 0000000000..0d8569b939 --- /dev/null +++ b/.devcontainer/scripts/zsh_dotnet_completion.sh @@ -0,0 +1,18 @@ +# zsh parameter completion for the dotnet CLI + +_dotnet_zsh_complete() +{ + local completions=("$(dotnet complete "$words")") + + # If the completion list is empty, just continue with filename selection + if [ -z "$completions" ] + then + _arguments '*::arguments: _normal' + return + fi + + # This is not a variable assignment, don't remove spaces! + _values = "${(ps:\n:)completions}" +} + +compdef _dotnet_zsh_complete dotnet diff --git a/.editorconfig b/.editorconfig index 0c4f918b4a..8ac2072ccb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,11 +3,15 @@ # All files [*] indent_style = space +trim_trailing_whitespace = true +insert_final_newline = true # TS files [*.ts] indent_size = 2 # Fantomas (see https://github.com/fsprojects/fantomas/blob/master/docs/Documentation.md) -[*.fs] -max_line_length=140 +[*.{fs,fsx,fsi}] +max_line_length = 80 +fsharp_multi_line_lambda_closing_newline = true +fsharp_multiline_bracket_style = stroustrup diff --git a/.fantomasignore b/.fantomasignore new file mode 100644 index 0000000000..1dbcd51f14 --- /dev/null +++ b/.fantomasignore @@ -0,0 +1,3 @@ +src/** +tests/** +tests_external/** diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 532b1642d6..0a055ea5ce 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,7 +23,7 @@ jobs: uses: actions/setup-node@v2.4.1 - name: Fable Tests - JavaScript - run: dotnet fsi build.fsx test-js + run: ./build.sh test javascript # Separate build job for TypeScript build-typescript: @@ -41,7 +41,7 @@ jobs: uses: actions/setup-node@v2.4.1 - name: Fable Tests - TypeScript - run: dotnet fsi build.fsx test-ts + run: ./build.sh test typescript # - name: Fable Tests - TypeScript # run: dotnet fsi build.fsx test-ts @@ -62,7 +62,7 @@ jobs: uses: actions/setup-node@v2.4.1 - name: Fable Tests - run: dotnet fsi build.fsx test-integration + run: ./build.sh test integration # Separate build job for Python since we use a test matrix (will run in parallell) build-python: @@ -91,7 +91,7 @@ jobs: python-version: ${{ matrix.python-version }} - name: Fable Library - Python - run: dotnet fsi build.fsx library-py + run: ./build.sh fable-library --python - name: Install dependencies run: | @@ -99,7 +99,8 @@ jobs: poetry install - name: Fable Tests - Python - run: dotnet fsi build.fsx test-py + # + run: ./build.sh test python --skip-fable-library # Separate build job for Rust (will run in parallel) build-rust: @@ -124,9 +125,13 @@ jobs: with: toolchain: stable + - name: Fable Library - Rust + run: ./build.sh fable-library --rust + - name: Fable Tests - Rust - run: dotnet fsi build.fsx test-rust-${{ matrix.test }} + run: ./build.sh test rust --skip-fable-library --${{ matrix.test }} + # Separate build job for Dart build-dart: runs-on: ubuntu-latest @@ -142,4 +147,4 @@ jobs: uses: dart-lang/setup-dart@v1.3 - name: Fable Tests - Dart - run: dotnet fsi build.fsx test-dart + run: ./build.sh test dart diff --git a/.gitignore b/.gitignore index a4188a14ee..37a82426c0 100644 --- a/.gitignore +++ b/.gitignore @@ -11,8 +11,10 @@ temp*/ *.fs.dart src/fable-library/*.js src/fable-library/BigInt/*.js +src/quicktest/**/*.js src/quicktest-py/**/*.py src/quicktest-rust/**/*.rs +src/quicktest-dart/**/*.dart **/fable_modules/** ## Ignore Visual Studio temporary files, build results, and @@ -33,7 +35,6 @@ src/quicktest-rust/**/*.rs [Dd]ebug/ [Rr]elease/ x64/ -build/ [Bb]in/ [Oo]bj/ @@ -215,4 +216,4 @@ __pycache__/ .hypothesis # Compilation tests -tests/**/*.actual \ No newline at end of file +tests/**/*.actual diff --git a/.vscode/launch.json b/.vscode/launch.json index 83f97874df..ba7fb16a7d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,160 +1,269 @@ { - // Use IntelliSense to learn about possible Node.js debug attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Quicktest", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build", - "program": "${workspaceFolder}/src/Fable.Cli/bin/Debug/net6.0/fable.dll", - // "args": ["watch", "--cwd", "src/quicktest", "--exclude", "Fable.Core", "--noCache", "--runScript"], - "args": ["src/fable-library", "--outDir", "build/fable-library-ts", "--fableLib", "build/fable-library-ts", "--lang", "TypeScript", "--typedArrays", "false", "--exclude", "Fable.Core", "--define", "FX_NO_BIGINT", "--define", "FABLE_LIBRARY"], - "cwd": "${workspaceFolder}", - "stopAtEntry": true, - "console": "internalConsole" - }, - { - "name": "Quicktest - JavaScript", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build", - "program": "${workspaceFolder}/src/Fable.Cli/bin/Debug/net6.0/fable.dll", - "args": ["src/quicktest", "--exclude", "Fable.Core", "--noCache"], - "cwd": "${workspaceFolder}", - "console": "internalConsole" - }, - { - "name": "Attach to Node", - "port": 9229, - "request": "attach", - "skipFiles": [ - "/**" - ], - "type": "node" - }, - { - "args": [ - "${workspaceFolder}/build/tests", - "--reporter", - "dot", - "--timeout", - "10000" - ], - "internalConsoleOptions": "openOnSessionStart", - "name": "Run Mocha tests", - "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", - "request": "launch", - "skipFiles": [ - "/**" - ], - "type": "node" - }, - { - "args": [ - "${workspaceFolder}/build/tests/TypeScriptCompiled/build/tests/TypeScript", - "--reporter", - "dot", - "--timeout", - "10000" - ], - "internalConsoleOptions": "openOnSessionStart", - "name": "Run Mocha TS tests", - "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", - "request": "launch", - "skipFiles": [ - "/**" - ], - "type": "node" - }, - { - "name": "Run Fable.Cli", - "type": "coreclr", - "request": "launch", - "program": "${workspaceRoot}/src/Fable.Cli/bin/Debug/net6.0/fable.dll", - "args": ["watch", "--exclude", "Fable.Core"], - "cwd": "${workspaceRoot}/src/quicktest", - "stopAtEntry": false, - "console": "internalConsole" - }, - { - "type": "node", - "request": "launch", - "name": "Run bench-compiler JS test", - "program": "${workspaceFolder}/src/fable-standalone/test/bench-compiler/out-test/src/test.js" - }, - { - "type": "node", - "request": "launch", - "name": "Run bench-compiler JS tests", - "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", - "args": ["out-tests"], - "cwd": "${workspaceRoot}/src/fable-standalone/test/bench-compiler" - }, - { - "type": "node", - "request": "launch", - "name": "Run bench-compiler (Node)", - "program": "${workspaceRoot}/src/fable-standalone/test/bench-compiler/out-node/app.js", - "args": ["${workspaceRoot}/../fable-test/fable-test.fsproj", "out-test", "--fableLib", "out-lib"], - // "args": ["${workspaceRoot}/tests/Main/Fable.Tests.fsproj", "out-tests", "--fableLib", "out-lib"], - // "args": ["${workspaceRoot}/src/fcs-fable/fcs-fable.fsproj", "out-fcs", "--fableLib", "out-lib"], - "cwd": "${workspaceRoot}/src/fable-standalone/test/bench-compiler" - }, - { - "type": "coreclr", - "request": "launch", - "name": "Run bench-compiler (.NET)", - "program": "${workspaceFolder}/src/fable-standalone/test/bench-compiler/bin/Debug/net7.0/bench-compiler.dll", - "args": ["${workspaceRoot}/../fable-test/fable-test.fsproj", "out-test", "--fableLib", "out-lib"], - // "args": ["${workspaceRoot}/tests/Main/Fable.Tests.fsproj", "out-tests", "--fableLib", "out-lib"], - // "args": ["${workspaceRoot}/src/fcs-fable/fcs-fable.fsproj", "out-fcs", "--fableLib", "out-lib"], - "cwd": "${workspaceFolder}/src/fable-standalone/test/bench-compiler" - }, - { - // src/fable-compiler-js/ tests/Main/Fable.Tests.fsproj build/tests-js - "type": "node", - "request": "launch", - "name": "Run compiler-js", - "program": "${workspaceRoot}/build/fable-compiler-js/src/fable-compiler-js/dist/app.js", - "args": ["${workspaceRoot}/tests/Main/Fable.Tests.fsproj", "build/tests-js"], - "stopOnEntry": true - }, - { - "name": "Run Fable.Cli on fable-test", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build", - "program": "${workspaceRoot}/src/Fable.Cli/bin/Debug/net6.0/fable.dll", - "args": ["--outDir", "${workspaceRoot}/../fable-test", "--fableLib", "../../Fable/build/fable-library-rust", "--exclude", "Fable.Core", "--lang", "Rust", "--noCache"], - "cwd": "${workspaceRoot}/../fable-test", - "stopAtEntry": false, - "console": "internalConsole" - }, - { - "name": "Run Fable.Cli on tests/Rust", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build", - "program": "${workspaceRoot}/src/Fable.Cli/bin/Debug/net6.0/fable.dll", - "args": ["--outDir", "${workspaceRoot}/build/tests/Rust", "--exclude", "Fable.Core", "--lang", "Rust", "--noCache"], - "cwd": "${workspaceRoot}/tests/Rust", - "stopAtEntry": false, - "console": "internalConsole" - }, - { - "name": "Run Fable.Cli on library-rust", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build", - "program": "${workspaceRoot}/src/Fable.Cli/bin/Debug/net6.0/fable.dll", - "args": ["--outDir", "${workspaceRoot}/build/fable-library-rust/src", "--fableLib", ".", "--exclude", "Fable.Core", "--lang", "Rust", "--noCache", "--define", "FABLE_LIBRARY"], - "cwd": "${workspaceRoot}/src/fable-library-rust/src", - "stopAtEntry": false, - "console": "internalConsole" - }, - - ] + // Use IntelliSense to learn about possible Node.js debug attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Quicktest - Dart", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/src/Fable.Cli/bin/Debug/net6.0/fable.dll", + "args": [ + "src/quicktest-dart", + "--lang", + "dart", + "--extension", + ".dart", + "--exclude", + "Fable.Core", + "--noCache", + "--runScript" + ], + "cwd": "${workspaceFolder}", + "console": "internalConsole" + }, + { + "name": "Quicktest - JavaScript", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/src/Fable.Cli/bin/Debug/net6.0/fable.dll", + "args": [ + "src/quicktest", + "--exclude", + "Fable.Core", + "--noCache", + "--runScript" + ], + "cwd": "${workspaceFolder}", + "console": "internalConsole" + }, + { + "name": "Quicktest - TypeScript", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/src/Fable.Cli/bin/Debug/net6.0/fable.dll", + "args": [ + "src/quicktest", + "--lang", + "TypeScript", + "--exclude", + "Fable.Core", + "--noCache" + ], + "cwd": "${workspaceFolder}", + "console": "internalConsole" + }, + { + "name": "Quicktest - Python", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/src/Fable.Cli/bin/Debug/net6.0/fable.dll", + "args": [ + "src/quicktest-py", + "--lang", + "python", + "--extension", + ".py", + "--exclude", + "Fable.Core", + "--noCache", + "--runScript" + ], + "cwd": "${workspaceFolder}", + "console": "internalConsole" + }, + { + "name": "Quicktest - Rust (default)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/src/Fable.Cli/bin/Debug/net6.0/fable.dll", + "args": [ + "src/quicktest-rust", + "--lang", + "rust", + "--extension", + ".rs", + "--exclude", + "Fable.Core", + "--noCache", + "--runScript" + ], + "cwd": "${workspaceFolder}", + "console": "internalConsole" + }, + { + "name": "Quicktest - Rust (no_std)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/src/Fable.Cli/bin/Debug/net6.0/fable.dll", + "args": [ + "src/quicktest-rust", + "--lang", + "rust", + "--extension", + ".rs", + "--exclude", + "Fable.Core", + "--noCache", + "--runScript", + "--features", + "no_std" + ], + "cwd": "${workspaceFolder}", + "console": "internalConsole" + }, + { + "name": "Quicktest - Rust (threaded)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/src/Fable.Cli/bin/Debug/net6.0/fable.dll", + "args": [ + "src/quicktest-rust", + "--lang", + "rust", + "--extension", + ".rs", + "--exclude", + "Fable.Core", + "--noCache", + "--runScript", + "--features", + "threaded" + ], + "cwd": "${workspaceFolder}", + "console": "internalConsole" + }, + // { + // "type": "node", + // "request": "launch", + // "name": "Run bench-compiler JS test", + // "program": "${workspaceFolder}/src/fable-standalone/test/bench-compiler/out-test/src/test.js" + // }, + // { + // "type": "node", + // "request": "launch", + // "name": "Run bench-compiler JS tests", + // "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", + // "args": ["out-tests"], + // "cwd": "${workspaceRoot}/src/fable-standalone/test/bench-compiler" + // }, + // { + // "type": "node", + // "request": "launch", + // "name": "Run bench-compiler (Node)", + // "program": "${workspaceRoot}/src/fable-standalone/test/bench-compiler/out-node/app.js", + // "args": ["${workspaceRoot}/../fable-test/fable-test.fsproj", "out-test", "--fableLib", "out-lib"], + // // "args": ["${workspaceRoot}/tests/Main/Fable.Tests.fsproj", "out-tests", "--fableLib", "out-lib"], + // // "args": ["${workspaceRoot}/src/fcs-fable/fcs-fable.fsproj", "out-fcs", "--fableLib", "out-lib"], + // "cwd": "${workspaceRoot}/src/fable-standalone/test/bench-compiler" + // }, + { + "name": "Fable.Cli - fable-library-dart", + "type": "coreclr", + "request": "launch", + "program": "dotnet", + "args": [ + "run", + "--project", + "${workspaceRoot}/src/Fable.Cli", + "--", + "src/fable-library-dart", + "--outDir", + "temp/fable-library-dart", + "--fableLib", + "./temp/fable-library-dart", + "--lang", + "dart", + "--exclude", + "Fable.Core", + "--define", + "FABLE_LIBRARY", + "--noCache" + ] + }, + { + "name": "Fable.Cli - fable-library-ts", + "type": "coreclr", + "request": "launch", + "program": "dotnet", + "args": [ + "run", + "--project", + "${workspaceRoot}/src/Fable.Cli", + "--", + "src/fable-library", + "--outDir", + "temp/fable-library-ts", + "--fableLib", + "./temp/fable-library-ts", + "--lang", + "typescript", + "--exclude", + "Fable.Core", + "--define", + "FABLE_LIBRARY", + "--noCache", + "--typedArrays", + "false", + "--define", + "FX_NO_BIGINT" + ] + }, + { + "name": "Fable.Cli - fable-library-py", + "type": "coreclr", + "request": "launch", + "program": "dotnet", + "args": [ + "run", + "--project", + "${workspaceRoot}/src/Fable.Cli", + "--", + "src/fable-library-py/fable_library", + "--outDir", + "temp/fable-library-py/fable_library", + "--fableLib", + ".", + "--lang", + "python", + "--exclude", + "Fable.Core", + "--define", + "FABLE_LIBRARY", + "--noCache" + ] + }, + { + "name": "Fable.Cli - fable-library-rust", + "type": "coreclr", + "request": "launch", + "program": "dotnet", + "args": [ + "run", + "--project", + "${workspaceRoot}/src/Fable.Cli", + "--", + "src/fable-library-rust/src", + "--outDir", + "temp/fable-library-rust/src", + "--fableLib", + ".", + "--lang", + "rust", + "--exclude", + "Fable.Core", + "--define", + "FABLE_LIBRARY", + "--noCache" + ] + } + ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 58410f3558..c33642fdef 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -24,8 +24,9 @@ "src/fcs-fable" ], "rust-analyzer.linkedProjects": [ - "build/fable-library-rust/Cargo.toml", - "build/tests/Rust/Cargo.toml" + "temp/fable-library-rust/Cargo.toml", + "temp/tests/Rust/Cargo.toml" ], - "editor.inlayHints.enabled": "offUnlessPressed" + "editor.inlayHints.enabled": "offUnlessPressed", + "dotnet.defaultSolution": "disable" } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index ce45ff89b4..96159b0c6d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -9,9 +9,7 @@ "type": "shell", "args": [ "build", - // Ask dotnet build to generate full paths for file names. "/property:GenerateFullPaths=true", - // Do not generate summary otherwise it leads to duplicate errors in Problems panel "/consoleloggerparameters:NoSummary", "src/Fable.Cli" ], @@ -21,6 +19,96 @@ }, "problemMatcher": "$msCompile" }, + { + "label": "Build fable-library - JavaScript", + "type": "shell", + "args": [ + "fable-library", + "--javascript" + ], + "linux": { + "command": "${workspaceFolder}/build.sh" + }, + "osx": { + "command": "${workspaceFolder}/build.sh" + }, + "windows": { + "command": "${workspaceFolder}/build.cmd" + }, + "problemMatcher": [] + }, + { + "label": "Build fable-library - TypeScript", + "type": "shell", + "args": [ + "fable-library", + "--typescript" + ], + "linux": { + "command": "${workspaceFolder}/build.sh" + }, + "osx": { + "command": "${workspaceFolder}/build.sh" + }, + "windows": { + "command": "${workspaceFolder}/build.cmd" + }, + "problemMatcher": [] + }, + { + "label": "Build fable-library - Python", + "type": "shell", + "args": [ + "fable-library", + "--python" + ], + "linux": { + "command": "${workspaceFolder}/build.sh" + }, + "osx": { + "command": "${workspaceFolder}/build.sh" + }, + "windows": { + "command": "${workspaceFolder}/build.cmd" + }, + "problemMatcher": [] + }, + { + "label": "Build fable-library - Dart", + "type": "shell", + "args": [ + "fable-library", + "--dart" + ], + "linux": { + "command": "${workspaceFolder}/build.sh" + }, + "osx": { + "command": "${workspaceFolder}/build.sh" + }, + "windows": { + "command": "${workspaceFolder}/build.cmd" + }, + "problemMatcher": [] + }, + { + "label": "Build fable-library - Rust", + "type": "shell", + "args": [ + "fable-library", + "--rust" + ], + "linux": { + "command": "${workspaceFolder}/build.sh" + }, + "osx": { + "command": "${workspaceFolder}/build.sh" + }, + "windows": { + "command": "${workspaceFolder}/build.cmd" + }, + "problemMatcher": [] + }, { "label": "build bench-compiler", "command": "dotnet", @@ -44,7 +132,6 @@ "src/Fable.Transforms/Rust/AST/Tests" ], "problemMatcher": "$msCompile" - }, - + } ] -} \ No newline at end of file +} diff --git a/Fable.sln b/Fable.sln index 550a366e9b..56e2ee0075 100644 --- a/Fable.sln +++ b/Fable.sln @@ -60,6 +60,8 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fable.Tests.TypeScript", "t EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Fable.Tests.Spaces", "tests\Js\Project With Spaces\Fable.Tests.Spaces.fsproj", "{C90E23AF-4B5B-44A7-ADCC-3BF89547395B}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Build", "build\Build.fsproj", "{CF96D8D2-105D-4B18-92FF-9CF68FA33E65}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -154,6 +156,10 @@ Global {C90E23AF-4B5B-44A7-ADCC-3BF89547395B}.Debug|Any CPU.Build.0 = Debug|Any CPU {C90E23AF-4B5B-44A7-ADCC-3BF89547395B}.Release|Any CPU.ActiveCfg = Release|Any CPU {C90E23AF-4B5B-44A7-ADCC-3BF89547395B}.Release|Any CPU.Build.0 = Release|Any CPU + {CF96D8D2-105D-4B18-92FF-9CF68FA33E65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CF96D8D2-105D-4B18-92FF-9CF68FA33E65}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CF96D8D2-105D-4B18-92FF-9CF68FA33E65}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CF96D8D2-105D-4B18-92FF-9CF68FA33E65}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/README.md b/README.md index 077593f683..c066119d0c 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,34 @@ Check [this page](https://fable.io/docs/2-steps/setup.html). ## Building +### Requirements + +#### Use VSCode Dev Container + +You can use VSCode Dev Container to get a preconfigured environment both with requirements and VSCode extensions. + +1. You need to have docker installed and running. +2. [Install the Dev Container extension in VSCode](vscode:extension/ms-vscode-remote.remote-containers) +3. Open the project in VSCode and click on the green button at the bottom left corner. + +#### Use your machine + Make sure the following **requirements** are installed in your system: - [dotnet SDK 6 or higher](https://dotnet.microsoft.com/download) - [node.js](https://nodejs.org) with npm +- [Python 3](https://www.python.org/) is installed and available as `python` +- [Poetry](https://python-poetry.org/) +- [Rust](https://www.rust-lang.org/tools/install) +- [Dart](https://dart.dev/get-dart) + +### Build + +Run `./builsh.sh` or `./build.cmd` to see the build options. + +When using VSCode, you can also run the build tasks from the command palette (Ctrl+Shift+P) by typing `Run Task` and selecting the task you want to run. -Then run `dotnet fsi build.fsx` at the root folder to see the build options. +We also configured several debug configurations that you can use from the debug panel (Ctrl+Shift+D). This is useful as you can attach the debugger to the Fable compiler process to check what's going on. ## Contributing diff --git a/build copy.fsx b/build copy.fsx new file mode 100644 index 0000000000..6ab551a2df --- /dev/null +++ b/build copy.fsx @@ -0,0 +1,383 @@ +#load "src/Fable.PublishUtils/PublishUtils.fs" + +open System +open System.Text.RegularExpressions +open PublishUtils + +// ncave FCS fork +let FCS_REPO = "https://github.com/ncave/fsharp" +let FCS_REPO_LOCAL = "../fsharp_fable" +let FCS_REPO_FABLE_BRANCH = "fable" +let FCS_REPO_SERVICE_SLIM_BRANCH = "service_slim" + +let BUILD_ARGS = + fsi.CommandLineArgs + |> Array.skip 1 + |> List.ofArray + +let BUILD_ARGS_LOWER = + BUILD_ARGS + |> List.map (fun x -> x.ToLower()) + +module Util = + let cleanDirs dirs = + for dir in dirs do + printfn $"Clean {dir}" + removeDirRecursive dir + + // TODO: move to PublishUtils.fs ? + let copyFiles sourceDir searchPattern destDir = + printfn $"Copy {sourceDir searchPattern} to {destDir}" + for source in IO.Directory.GetFiles(sourceDir, searchPattern) do + let fileName = IO.Path.GetFileName(source) + let target = destDir fileName + IO.File.Copy(source, target, true) + + let resolveDir dir = + __SOURCE_DIRECTORY__ dir + + let updateVersionsInFableTransforms compilerVersion (libraryVersions: (string * string) list) = + let mutable updated = Set.empty + + let replaceVersion (lang: string option) version fileContent = + let prefix = + match lang with + | None -> "" + | Some lang -> $"{lang.ToUpperInvariant()}_LIBRARY_" + + Regex.Replace( + fileContent, + $@"^(\s*)let \[] {prefix}VERSION = ""(.*?)""", + (fun (m: Match) -> + match lang with + | Some lang when m.Groups[2].Value <> version -> + updated <- Set.add lang updated + | _ -> () + m.Groups[1].Value + $"let [] {prefix}VERSION = \"{version}\"" + ), + RegexOptions.Multiline) + + let filePath = "src/Fable.Transforms/Global/Compiler.fs" + readFile filePath + |> replaceVersion None compilerVersion + |> List.foldBack (fun (lang, version) fileContent -> + replaceVersion (Some lang) version fileContent) libraryVersions + |> writeFile filePath + + updated + + let updatePkgVersionInFsproj projFile version = + readFile projFile + |> replaceRegex Publish.NUGET_PACKAGE_VERSION (fun m -> + m.Groups[1].Value + version + m.Groups[3].Value) + |> writeFile projFile + + let runTSLint projectDir = + run ("npm run tslint -- --project " + projectDir) + + let runTypeScript projectDir = + run ("npm run tsc -- --project " + projectDir) + + let runTypeScriptWithArgs projectDir args = + run ("npm run tsc -- --project " + projectDir + " " + String.concat " " args) + + let runFableWithArgs projectDir args = + run ("dotnet run -c Release --project src/Fable.Cli -- " + projectDir + " " + String.concat " " args) + + let watchFableWithArgs projectDir args = + run ("dotnet watch --project src/Fable.Cli run -- " + projectDir + " --cwd ../.. " + String.concat " " args) + + let runFableWithArgsInDirAs release projectDir args = + let cliDir = resolveDir "src/Fable.Cli" + let cliArgs = args |> String.concat " " + let cliCmd = $"""dotnet run {if release then "-c Release" else ""} --project {cliDir} -- {cliArgs}""" + runInDir (resolveDir projectDir) cliCmd + + let runFableWithArgsInDir projectDir args = + runFableWithArgsInDirAs true projectDir args + + let runFableWithArgsAsync projectDir args = + runAsync ("dotnet run -c Release --project src/Fable.Cli -- " + projectDir + " " + String.concat " " args) + + let runNpx command args = + run ("npx " + command + " " + (String.concat " " args)) + + let runNpmScript script args = + run ("npm run " + script + " -- " + (String.concat " " args)) + + let runNpmScriptAsync script args = + runAsync ("npm run " + script + " -- " + (String.concat " " args)) + + let runFable projectDir = + runFableWithArgs projectDir [] + + let runMocha testDir = + runNpmScript "mocha" [$"{testDir} --reporter dot -t 10000"] + +open Util + +module Unused = + let downloadAndExtractTo (url: string) (targetDir: string) = + $"npx download --extract --out %s{targetDir} \"%s{url}\"" |> run + + let coverage() = + // report converter + // https://github.com/danielpalme/ReportGenerator + // dotnet tool install dotnet-reportgenerator-globaltool --tool-path tools + if not (pathExists "./bin/tools/reportgenerator") && not (pathExists "./bin/tools/reportgenerator.exe") then + runInDir "." "dotnet tool install dotnet-reportgenerator-globaltool --tool-path bin/tools" + let reportGen = + if pathExists "./bin/tools/reportgenerator" then "bin/tools/reportgenerator" + else "bin\\tools\\reportgenerator.exe" + + // if not (pathExists "build/fable-library") then + // buildLibrary() + + cleanDirs ["build/tests"] + runFable "tests" + + // JS + run "npx nyc mocha build/tests --require source-map-support/register --reporter dot -t 10000" + runInDir "." (reportGen + " \"-reports:build/coverage/nyc/lcov.info\" -reporttypes:Html \"-targetdir:build/coverage/nyc/html\" ") + + // .NET + //runInDir "tests/Main" "dotnet build /t:Collect_Coverage" + cleanDirs ["build/coverage/netcoreapp2.0/out"] + runInDir "." (reportGen + " \"-reports:build/coverage/netcoreapp2.0/coverage.xml\" -reporttypes:Html \"-targetdir:build/coverage/netcoreapp2.0/html\" ") + + + +let buildWorker (opts: {| minify: bool; watch: bool |}) = + printfn "Building worker%s..." (if opts.minify then "" else " (no minification)") + + let projectDir = "src/fable-standalone/src" + let buildDir = "build/fable-standalone" + let distDir = "src/fable-standalone/dist" + + runFableWithArgs (projectDir + "/Worker") [ + "--outDir " + buildDir + "/worker" + ] + + let rollupTarget = + match opts.minify with + | true -> buildDir "worker.js" + | false -> distDir "worker.min.js" + + // make standalone worker dist + runNpmScript "rollup" [$"""{buildDir}/worker/Worker.js -o {rollupTarget} --format iife"""] + + if opts.minify then + // runNpx "webpack" [sprintf "--entry ./%s/worker.js --output ./%s/worker.min.js --config ./%s/../worker.config.js" buildDir distDir projectDir] + runNpmScript "terser" [$"{buildDir}/worker.js -o {distDir}/worker.min.js --mangle --compress"] + + // Put fable-library files next to bundle + printfn "Copying fable-library..." + // buildLibraryTsIfNotExists() + let libraryDir = "build/fable-library" + let libraryTarget = distDir "fable-library" + copyDirRecursive libraryDir libraryTarget + +let buildStandalone (opts: {| minify: bool; watch: bool |}) = + // buildLibraryTs() + + printfn "Building standalone%s..." (if opts.minify then "" else " (no minification)") + + let projectDir = "src/fable-standalone/src" + let buildDir = "build/fable-standalone" + let distDir = "src/fable-standalone/dist" + + let rollupTarget = + match opts.watch, opts.minify with + | true, _ -> + match BUILD_ARGS with + | _::rollupTarget::_ -> rollupTarget + | _ -> failwith "Pass the bundle output, e.g.: npm run build watch-standalone ../repl3/public/js/repl/bundle.min.js" + | false, true -> buildDir "bundle.js" + | false, false -> distDir "bundle.min.js" + + let rollupArgs = [ + buildDir "bundle/Main.js" + "-o " + rollupTarget + "--format umd" + "--name __FABLE_STANDALONE__" + ] + + // cleanup + if not opts.watch then + cleanDirs [buildDir; distDir] + makeDirRecursive distDir + + // build standalone bundle + runFableWithArgs projectDir [ + "--outDir " + buildDir "bundle" + if opts.watch then + "--watch" + "--run rollup" + yield! rollupArgs + "--watch" + ] + + // make standalone bundle dist + runNpmScript "rollup" rollupArgs + if opts.minify then + runNpmScript "terser" [ + buildDir "bundle.js" + "-o " + distDir "bundle.min.js" + "--mangle" + "--compress" + ] + + // build standalone worker + buildWorker opts + + // print bundle size + fileSizeInBytes (distDir "bundle.min.js") / 1000. |> printfn "Bundle size: %fKB" + fileSizeInBytes (distDir "worker.min.js") / 1000. |> printfn "Worker size: %fKB" + +let buildCompilerJs(minify: bool) = + let projectDir = "src/fable-compiler-js/src" + let buildDir = "build/fable-compiler-js" + let distDir = "src/fable-compiler-js/dist" + + if not (pathExists "build/fable-standalone") then + buildStandalone {|minify=minify; watch=false|} + + cleanDirs [buildDir; distDir] + makeDirRecursive distDir + + runFableWithArgs projectDir [ + "--outDir " + buildDir + "--exclude Fable.Core" + ] + + let rollupTarget = if minify then distDir "app.js" else distDir "app.min.js" + run $"npx rollup {buildDir}/app.js -o {rollupTarget} --format umd --name Fable" + if minify then + run $"npx terser {distDir}/app.js -o {distDir}/app.min.js --mangle --compress" + + // Copy fable-library + copyDirRecursive ("build/fable-library") (distDir "fable-library") + // Copy fable-metadata + copyDirRecursive ("src/fable-metadata/lib") (distDir "fable-metadata") + +let testStandalone(minify) = + let fableDir = "src/fable-compiler-js" + let buildDir = "build/tests/Standalone" + + if not (pathExists "build/fable-compiler-js") then + buildCompilerJs(minify) + + cleanDirs [buildDir] + + // Link fable-compiler-js to local packages + runInDir fableDir "npm link ../fable-metadata" + runInDir fableDir "npm link ../fable-standalone" + + // Test fable-compiler-js locally + run $"node {fableDir} tests/Js/Main/Fable.Tests.fsproj {buildDir}" + runMocha buildDir + + // // Another local fable-compiler-js test + // runInDir (fableDir "test") "node .. test_script.fsx" + // runInDir (fableDir "test") "node test_script.fsx.js" + + // Unlink local packages after test + runInDir fableDir "npm unlink ../fable-metadata && cd ../fable-metadata && npm unlink" + runInDir fableDir "npm unlink ../fable-standalone && cd ../fable-standalone && npm unlink" + +let buildLocalPackageWith pkgDir pkgCommand fsproj action = + let version = Publish.loadReleaseVersion "src/Fable.Cli" + "-local-build-" + DateTime.Now.ToString("yyyyMMdd-HHmm") + action version + updatePkgVersionInFsproj fsproj version + run $"dotnet pack {fsproj} -p:Pack=true -c Release -o {pkgDir}" + + // Return install command + $"""dotnet {pkgCommand} --version "{version}" --add-source {fullPath pkgDir}""" + +let buildLocalPackage pkgDir = + buildLocalPackageWith pkgDir + "tool install fable" + (resolveDir "src/Fable.Cli/Fable.Cli.fsproj") (fun version -> + updateVersionsInFableTransforms version [] |> ignore + // buildLibraryTs() + ) + +let testRepos() = + let repos = [ + "https://github.com/alfonsogarciacaro/FsToolkit.ErrorHandling:update-fable-3", "npm i && npm test" + "https://github.com/fable-compiler/fable-promise:master", "npm i && npm test" + "https://github.com/alfonsogarciacaro/Thoth.Json:nagareyama", "dotnet paket restore && npm i && dotnet fable tests -o tests/bin --run mocha tests/bin" + "https://github.com/alfonsogarciacaro/FSharp.Control.AsyncSeq:nagareyama", "cd tests/fable && npm i && npm test" + "https://github.com/alfonsogarciacaro/Fable.Extras:nagareyama", "dotnet paket restore && npm i && npm test" + "https://github.com/alfonsogarciacaro/Fable.Jester:nagareyama", "npm i && npm test" + "https://github.com/Zaid-Ajaj/Fable.SimpleJson:master", "npm i && npm run test-nagareyama" + ] + + let testDir = tempPath() "fable-repos" + printfn $"Cloning repos to: {testDir}" + + cleanDirs [testDir] + makeDirRecursive testDir + let pkgInstallCmd = buildLocalPackage (testDir "pkg") + + for (repo, command) in repos do + let url, branch = let i = repo.LastIndexOf(":") in repo[..i-1], repo[i+1..] + let name = url[url.LastIndexOf("/") + 1..] + runInDir testDir $"git clone {url} {name}" + let repoDir = testDir name + runInDir repoDir ("git checkout " + branch) + runInDir repoDir "dotnet tool uninstall fable" + runInDir repoDir pkgInstallCmd + runInDir repoDir "dotnet tool restore" + runInDir repoDir command + + +let hasFlag flag = + BUILD_ARGS_LOWER |> List.contains flag + +match BUILD_ARGS_LOWER with +// | "check-sourcemaps"::_ -> +// ("src/quicktest/Quicktest.fs", "src/quicktest/bin/Quicktest.js", "src/quicktest/bin/Quicktest.js.map") +// |||> sprintf "nodemon --watch src/quicktest/bin/Quicktest.js --exec 'source-map-visualization --sm=\"%s;%s;%s\"'" +// |> List.singleton |> quicktest +// | "coverage"::_ -> coverage() + +// | "test-standalone-fast"::_ -> testStandaloneFast() +| "test-repos"::_ -> testRepos() + +| "package"::_ -> + let pkgInstallCmd = buildLocalPackage (resolveDir "temp/pkg") + printfn $"\nPackage has been created, use the following command to install it:\n {pkgInstallCmd}\n" +| "package-core"::_ -> + let pkgInstallCmd = buildLocalPackageWith (resolveDir "temp/pkg") "add package Fable.Core" (resolveDir "src/Fable.Core/Fable.Core.fsproj") ignore + printfn $"\nFable.Core package has been created, use the following command to install it:\n {pkgInstallCmd}\n" + +| ("fable-compiler-js"|"compiler-js")::_ -> + let minify = hasFlag "--no-minify" |> not + buildCompilerJs(minify) +| ("fable-standalone"|"standalone")::_ -> + let minify = hasFlag "--no-minify" |> not + buildStandalone {|minify=minify; watch=false|} +| ("fable-worker"|"worker")::_ -> + let minify = hasFlag "--no-minify" |> not + buildWorker {|minify=minify; watch=false|} +| "watch-standalone"::_ -> buildStandalone {|minify=false; watch=true|} + + +| _ -> + printfn """Please pass a target name. Examples: + +- Use `test` to run tests: + dotnet fsi build.fsx test + +- Use `package` to build a local package: + dotnet fsi build.fsx package + +- Use `run` to compile a project with development version: + dotnet fsi build.fsx run ../path/to/my/project [Fable options] + +- Use `quicktest` to quickly test development version with src/quicktest project: + dotnet fsi build.fsx quicktest +""" + +printfn "Build finished successfully" diff --git a/build.bat b/build.bat new file mode 100644 index 0000000000..206327a3e3 --- /dev/null +++ b/build.bat @@ -0,0 +1,4 @@ +@echo off + +dotnet tool restore +dotnet run --project build/Build.fsproj -- %* diff --git a/build.fsx b/build.fsx deleted file mode 100644 index 86f54609ae..0000000000 --- a/build.fsx +++ /dev/null @@ -1,892 +0,0 @@ -#load "src/Fable.PublishUtils/PublishUtils.fs" - -open System -open System.Text.RegularExpressions -open PublishUtils - -// ncave FCS fork -let FCS_REPO = "https://github.com/ncave/fsharp" -let FCS_REPO_LOCAL = "../fsharp_fable" -let FCS_REPO_FABLE_BRANCH = "fable" -let FCS_REPO_SERVICE_SLIM_BRANCH = "service_slim" - -let BUILD_ARGS = - fsi.CommandLineArgs - |> Array.skip 1 - |> List.ofArray - -let BUILD_ARGS_LOWER = - BUILD_ARGS - |> List.map (fun x -> x.ToLower()) - -module Util = - let cleanDirs dirs = - for dir in dirs do - printfn $"Clean {dir}" - removeDirRecursive dir - - // TODO: move to PublishUtils.fs ? - let copyFiles sourceDir searchPattern destDir = - printfn $"Copy {sourceDir searchPattern} to {destDir}" - for source in IO.Directory.GetFiles(sourceDir, searchPattern) do - let fileName = IO.Path.GetFileName(source) - let target = destDir fileName - IO.File.Copy(source, target, true) - - let resolveDir dir = - __SOURCE_DIRECTORY__ dir - - let updateVersionsInFableTransforms compilerVersion (libraryVersions: (string * string) list) = - let mutable updated = Set.empty - - let replaceVersion (lang: string option) version fileContent = - let prefix = - match lang with - | None -> "" - | Some lang -> $"{lang.ToUpperInvariant()}_LIBRARY_" - - Regex.Replace( - fileContent, - $@"^(\s*)let \[] {prefix}VERSION = ""(.*?)""", - (fun (m: Match) -> - match lang with - | Some lang when m.Groups[2].Value <> version -> - updated <- Set.add lang updated - | _ -> () - m.Groups[1].Value + $"let [] {prefix}VERSION = \"{version}\"" - ), - RegexOptions.Multiline) - - let filePath = "src/Fable.Transforms/Global/Compiler.fs" - readFile filePath - |> replaceVersion None compilerVersion - |> List.foldBack (fun (lang, version) fileContent -> - replaceVersion (Some lang) version fileContent) libraryVersions - |> writeFile filePath - - updated - - let updatePkgVersionInFsproj projFile version = - readFile projFile - |> replaceRegex Publish.NUGET_PACKAGE_VERSION (fun m -> - m.Groups[1].Value + version + m.Groups[3].Value) - |> writeFile projFile - - let runTSLint projectDir = - run ("npm run tslint -- --project " + projectDir) - - let runTypeScript projectDir = - run ("npm run tsc -- --project " + projectDir) - - let runTypeScriptWithArgs projectDir args = - run ("npm run tsc -- --project " + projectDir + " " + String.concat " " args) - - let runFableWithArgs projectDir args = - run ("dotnet run -c Release --project src/Fable.Cli -- " + projectDir + " " + String.concat " " args) - - let watchFableWithArgs projectDir args = - run ("dotnet watch --project src/Fable.Cli run -- " + projectDir + " --cwd ../.. " + String.concat " " args) - - let runFableWithArgsInDirAs release projectDir args = - let cliDir = resolveDir "src/Fable.Cli" - let cliArgs = args |> String.concat " " - let cliCmd = $"""dotnet run {if release then "-c Release" else ""} --project {cliDir} -- {cliArgs}""" - runInDir (resolveDir projectDir) cliCmd - - let runFableWithArgsInDir projectDir args = - runFableWithArgsInDirAs true projectDir args - - let runFableWithArgsAsync projectDir args = - runAsync ("dotnet run -c Release --project src/Fable.Cli -- " + projectDir + " " + String.concat " " args) - - let runNpx command args = - run ("npx " + command + " " + (String.concat " " args)) - - let runNpmScript script args = - run ("npm run " + script + " -- " + (String.concat " " args)) - - let runNpmScriptAsync script args = - runAsync ("npm run " + script + " -- " + (String.concat " " args)) - - let runFable projectDir = - runFableWithArgs projectDir [] - - let runMocha testDir = - runNpmScript "mocha" [$"{testDir} --reporter dot -t 10000"] - -open Util - -module Unused = - let downloadAndExtractTo (url: string) (targetDir: string) = - $"npx download --extract --out %s{targetDir} \"%s{url}\"" |> run - - let coverage() = - // report converter - // https://github.com/danielpalme/ReportGenerator - // dotnet tool install dotnet-reportgenerator-globaltool --tool-path tools - if not (pathExists "./bin/tools/reportgenerator") && not (pathExists "./bin/tools/reportgenerator.exe") then - runInDir "." "dotnet tool install dotnet-reportgenerator-globaltool --tool-path bin/tools" - let reportGen = - if pathExists "./bin/tools/reportgenerator" then "bin/tools/reportgenerator" - else "bin\\tools\\reportgenerator.exe" - - // if not (pathExists "build/fable-library") then - // buildLibrary() - - cleanDirs ["build/tests"] - runFable "tests" - - // JS - run "npx nyc mocha build/tests --require source-map-support/register --reporter dot -t 10000" - runInDir "." (reportGen + " \"-reports:build/coverage/nyc/lcov.info\" -reporttypes:Html \"-targetdir:build/coverage/nyc/html\" ") - - // .NET - //runInDir "tests/Main" "dotnet build /t:Collect_Coverage" - cleanDirs ["build/coverage/netcoreapp2.0/out"] - runInDir "." (reportGen + " \"-reports:build/coverage/netcoreapp2.0/coverage.xml\" -reporttypes:Html \"-targetdir:build/coverage/netcoreapp2.0/html\" ") - -// TARGETS --------------------------- - -// let buildLibraryJsWithOptions (opts: {| watch: bool |}) = -// let baseDir = __SOURCE_DIRECTORY__ - -// let projectDir = baseDir "src/fable-library" -// let buildDir = baseDir "build/fable-library" -// let fableOpts = [ -// "--outDir " + buildDir -// "--fableLib " + buildDir -// "--exclude Fable.Core" -// "--define FX_NO_BIGINT" -// "--define FABLE_LIBRARY" -// if opts.watch then "--watch" -// ] - -// cleanDirs [buildDir] -// runInDir baseDir "npm install" -// makeDirRecursive buildDir - -// copyFile (projectDir "package.json") buildDir - -// if opts.watch then -// Async.Parallel [ -// runNpmScriptAsync "tsc" [ -// "--project " + projectDir -// "--watch" -// ] -// runFableWithArgsAsync projectDir fableOpts -// ] |> runAsyncWorkflow -// else -// runTSLint projectDir -// runTypeScript projectDir -// runFableWithArgs projectDir fableOpts -// removeDirRecursive (buildDir ".fable") - -// let buildLibraryJs() = buildLibraryJsWithOptions {| watch = false |} - -// let buildLibraryJsIfNotExists() = -// if not (pathExists (__SOURCE_DIRECTORY__ "build/fable-library")) then -// buildLibraryJs() - -let buildLibraryTs() = - let baseDir = __SOURCE_DIRECTORY__ - let sourceDir = "./src/fable-library" - let buildDirTs = "./build/fable-library-ts" - let buildDirJs = "./build/fable-library" - - cleanDirs [buildDirTs; buildDirJs] - runInDir baseDir "npm install" - - runFableWithArgs sourceDir [ - "--outDir " + buildDirTs - "--fableLib " + buildDirTs - "--lang TypeScript" - "--typedArrays false" - "--exclude Fable.Core" - "--define FX_NO_BIGINT" - "--define FABLE_LIBRARY" - ] - - copyFiles sourceDir "*.ts" buildDirTs - copyFiles (sourceDir "ts") "*.json" buildDirTs - copyDirRecursive (sourceDir "lib") (buildDirTs "lib") - copyFile (sourceDir "package.json") buildDirTs - - // runTSLint buildDirTs - runTypeScriptWithArgs buildDirTs ["--outDir " + buildDirJs] - copyFile (buildDirTs "lib/big.d.ts") (buildDirJs "lib/big.d.ts") - copyFile (buildDirTs "package.json") buildDirJs - - copyFile (sourceDir "README.md") buildDirJs - -let buildLibraryTsIfNotExists() = - if not (pathExists (__SOURCE_DIRECTORY__ "build/fable-library-ts")) then - buildLibraryTs() - -let buildLibraryPy() = - let libraryDir = "./src/fable-library-py" - let projectDir = libraryDir "fable_library" - let buildDirPy = "./build/fable-library-py" - - cleanDirs [buildDirPy] - - runFableWithArgs projectDir [ - "--outDir " + buildDirPy "fable_library" - "--fableLib " + buildDirPy "fable_library" - "--lang Python" - "--exclude Fable.Core" - "--define FABLE_LIBRARY" - ] - - // Copy python related files from projectDir to buildDir - copyFiles libraryDir "*" buildDirPy - copyFiles projectDir "*.py" (buildDirPy "fable_library") - - // Fix issues with Fable .fsproj not supporting links - copyDirNonRecursive (buildDirPy "fable_library/fable-library") (buildDirPy "fable_library") - removeDirRecursive (buildDirPy "fable_library/fable-library") - -let buildLibraryPyIfNotExists() = - let baseDir = __SOURCE_DIRECTORY__ - if not (pathExists (baseDir "build/fable-library-py")) then - buildLibraryPy() - -let buildLibraryRust() = - let libraryDir = "src/fable-library-rust" - let sourceDir = libraryDir "src" - let buildDir = "build/fable-library-rust" - let outDir = buildDir "src" - let fableLib = "." - - cleanDirs [buildDir] - - runFableWithArgsInDir sourceDir [ - "--outDir " + resolveDir outDir - "--fableLib " + fableLib - "--lang Rust" - "--exclude Fable.Core" - "--define FABLE_LIBRARY" - "--noCache" - ] - - copyFiles libraryDir "*.toml" buildDir - copyFiles sourceDir "*.rs" outDir - copyDirRecursive (libraryDir "vendored") (buildDir "vendored") - - runInDir buildDir "cargo fmt" - runInDir buildDir "cargo fix --allow-no-vcs" - runInDir buildDir "cargo build" - -let buildLibraryRustIfNotExists() = - if not (pathExists (__SOURCE_DIRECTORY__ "build/fable-library-rust")) then - buildLibraryRust() - -let buildLibraryDart(clean: bool) = - let sourceDir = resolveDir "src/fable-library-dart" - let buildDir = resolveDir "build/fable-library-dart" - - if clean then - cleanDirs [buildDir] - makeDirRecursive buildDir - copyFiles sourceDir "pubspec.*" buildDir - copyFiles sourceDir "analysis_options.yaml" buildDir - - copyFiles sourceDir "*.dart" buildDir - - runFableWithArgsInDir sourceDir [ - "--outDir " + buildDir - "--fableLib " + buildDir - "--lang Dart" - "--exclude Fable.Core" - "--define FABLE_LIBRARY" - if clean then "--noCache" - ] - -let buildLibraryDartIfNotExists() = - if not (pathExists (__SOURCE_DIRECTORY__ "build/fable-library-dart")) then - buildLibraryDart(true) - -// Like testStandalone() but doesn't create bundles/packages for fable-standalone & friends -// Mainly intended for CI -let testStandaloneFast() = - runFableWithArgs "src/fable-standalone/src" [ - "--noCache" - ] - - runFableWithArgs "src/fable-compiler-js/src" [ - "--exclude Fable.Core" - "--define LOCAL_TEST" - ] - - let fableJs = "./src/fable-compiler-js/src/app.fs.js" - let testProj = "tests/Js/Main/Fable.Tests.fsproj" - let buildDir = "build/tests/Standalone" - run $"node {fableJs} {testProj} {buildDir}" - runMocha buildDir - -let buildWorker (opts: {| minify: bool; watch: bool |}) = - printfn "Building worker%s..." (if opts.minify then "" else " (no minification)") - - let projectDir = "src/fable-standalone/src" - let buildDir = "build/fable-standalone" - let distDir = "src/fable-standalone/dist" - - runFableWithArgs (projectDir + "/Worker") [ - "--outDir " + buildDir + "/worker" - ] - - let rollupTarget = - match opts.minify with - | true -> buildDir "worker.js" - | false -> distDir "worker.min.js" - - // make standalone worker dist - runNpmScript "rollup" [$"""{buildDir}/worker/Worker.js -o {rollupTarget} --format iife"""] - - if opts.minify then - // runNpx "webpack" [sprintf "--entry ./%s/worker.js --output ./%s/worker.min.js --config ./%s/../worker.config.js" buildDir distDir projectDir] - runNpmScript "terser" [$"{buildDir}/worker.js -o {distDir}/worker.min.js --mangle --compress"] - - // Put fable-library files next to bundle - printfn "Copying fable-library..." - buildLibraryTsIfNotExists() - let libraryDir = "build/fable-library" - let libraryTarget = distDir "fable-library" - copyDirRecursive libraryDir libraryTarget - -let buildStandalone (opts: {| minify: bool; watch: bool |}) = - buildLibraryTs() - - printfn "Building standalone%s..." (if opts.minify then "" else " (no minification)") - - let projectDir = "src/fable-standalone/src" - let buildDir = "build/fable-standalone" - let distDir = "src/fable-standalone/dist" - - let rollupTarget = - match opts.watch, opts.minify with - | true, _ -> - match BUILD_ARGS with - | _::rollupTarget::_ -> rollupTarget - | _ -> failwith "Pass the bundle output, e.g.: npm run build watch-standalone ../repl3/public/js/repl/bundle.min.js" - | false, true -> buildDir "bundle.js" - | false, false -> distDir "bundle.min.js" - - let rollupArgs = [ - buildDir "bundle/Main.js" - "-o " + rollupTarget - "--format umd" - "--name __FABLE_STANDALONE__" - ] - - // cleanup - if not opts.watch then - cleanDirs [buildDir; distDir] - makeDirRecursive distDir - - // build standalone bundle - runFableWithArgs projectDir [ - "--outDir " + buildDir "bundle" - if opts.watch then - "--watch" - "--run rollup" - yield! rollupArgs - "--watch" - ] - - // make standalone bundle dist - runNpmScript "rollup" rollupArgs - if opts.minify then - runNpmScript "terser" [ - buildDir "bundle.js" - "-o " + distDir "bundle.min.js" - "--mangle" - "--compress" - ] - - // build standalone worker - buildWorker opts - - // print bundle size - fileSizeInBytes (distDir "bundle.min.js") / 1000. |> printfn "Bundle size: %fKB" - fileSizeInBytes (distDir "worker.min.js") / 1000. |> printfn "Worker size: %fKB" - -let buildCompilerJs(minify: bool) = - let projectDir = "src/fable-compiler-js/src" - let buildDir = "build/fable-compiler-js" - let distDir = "src/fable-compiler-js/dist" - - if not (pathExists "build/fable-standalone") then - buildStandalone {|minify=minify; watch=false|} - - cleanDirs [buildDir; distDir] - makeDirRecursive distDir - - runFableWithArgs projectDir [ - "--outDir " + buildDir - "--exclude Fable.Core" - ] - - let rollupTarget = if minify then distDir "app.js" else distDir "app.min.js" - run $"npx rollup {buildDir}/app.js -o {rollupTarget} --format umd --name Fable" - if minify then - run $"npx terser {distDir}/app.js -o {distDir}/app.min.js --mangle --compress" - - // Copy fable-library - copyDirRecursive ("build/fable-library") (distDir "fable-library") - // Copy fable-metadata - copyDirRecursive ("src/fable-metadata/lib") (distDir "fable-metadata") - -let testStandalone(minify) = - let fableDir = "src/fable-compiler-js" - let buildDir = "build/tests/Standalone" - - if not (pathExists "build/fable-compiler-js") then - buildCompilerJs(minify) - - cleanDirs [buildDir] - - // Link fable-compiler-js to local packages - runInDir fableDir "npm link ../fable-metadata" - runInDir fableDir "npm link ../fable-standalone" - - // Test fable-compiler-js locally - run $"node {fableDir} tests/Js/Main/Fable.Tests.fsproj {buildDir}" - runMocha buildDir - - // // Another local fable-compiler-js test - // runInDir (fableDir "test") "node .. test_script.fsx" - // runInDir (fableDir "test") "node test_script.fsx.js" - - // Unlink local packages after test - runInDir fableDir "npm unlink ../fable-metadata && cd ../fable-metadata && npm unlink" - runInDir fableDir "npm unlink ../fable-standalone && cd ../fable-standalone && npm unlink" - -let testReact() = - runFableWithArgs "tests/React" ["--noCache"] - runInDir "tests/React" "npm i && npm test" - -let compileAndRunTestsWithMocha clean projectName = - let projectDir = "tests/Js/" + projectName - let buildDir = "build/tests/Js/" + projectName - - if clean then - cleanDirs [buildDir] - - runFableWithArgs projectDir [ - "--outDir " + buildDir - "--exclude Fable.Core" - ] - - runMocha buildDir - -let testProjectConfigs() = - [ "tests/Integration/ProjectConfigs/DebugWithExtraDefines", "Debug" - "tests/Integration/ProjectConfigs/CustomConfiguration", "Test" - "tests/Integration/ProjectConfigs/ReleaseNoExtraDefines", String.Empty - "tests/Integration/ProjectConfigs/ConsoleApp", String.Empty - ] - |> List.iter (fun (projectDir, configuration) -> - let buildDir = "build/"+ projectDir - - cleanDirs [ buildDir ] - runFableWithArgs projectDir [ - "--outDir " + buildDir - "--exclude Fable.Core" - if not(String.IsNullOrEmpty configuration) then - "--configuration " + configuration - ] - - runMocha buildDir - ) - -let testIntegration() = - buildLibraryTsIfNotExists() - runInDir "tests/Integration/Integration" "dotnet run -c Release" - runInDir "tests/Integration/Compiler" "dotnet run -c Release" - testProjectConfigs() - -let testJs() = - buildLibraryTsIfNotExists() - - compileAndRunTestsWithMocha true "Main" - - runInDir "tests/Js/Main" "dotnet run -c Release" - - // Adaptive tests must go in a different project to avoid conflicts with Queue shim, see #2559 - compileAndRunTestsWithMocha true "Adaptive" - - testReact() - - if envVarOrNone "CI" |> Option.isSome then - testStandaloneFast() - -let testTypeScript isWatch = - buildLibraryTsIfNotExists() - - let projectDir = "tests/TypeScript" - let buildDir = "build/tests/TypeScript" - let buildDir2 = "build/tests/TypeScriptCompiled" - - cleanDirs [buildDir; buildDir2] - - copyFile (projectDir "tsconfig.json") (buildDir "tsconfig.json") - - runFableWithArgsInDirAs (not isWatch) "." [ - projectDir - "--lang ts" - "--outDir " + buildDir - "--exclude Fable.Core" - if isWatch then - "--watch" - $"--runWatch npm run test-ts" - ] - - runNpmScript "test-ts" [] - -let testPython() = - buildLibraryPyIfNotExists() // NOTE: fable-library-py needs to be built separately. - - let projectDir = "tests/Python" - let buildDir = "build/tests/Python" - - cleanDirs [buildDir] - runInDir projectDir "dotnet test -c Release" - runFableWithArgs projectDir [ - "--outDir " + buildDir - "--exclude Fable.Core" - "--lang Python" - ] - - runInDir buildDir "poetry run pytest -x" - // Testing in Windows - // runInDir buildDir "python -m pytest -x" - -type RustTestMode = - | NoStd - | Default - | Threaded - -let testRust testMode = - // buildLibraryRustIfNotExists() - buildLibraryRust() - - let testAstDir = "src/Fable.Transforms/Rust/AST/Tests" - let projectDir = "tests/Rust" - let buildDir = "build/tests/Rust" - - // limited cleanup to reduce IO churn, speed up rebuilds, - // and save the ssd (target folder can get huge) - cleanDirs [buildDir "src"] - cleanDirs [buildDir "tests"] - cleanDirs [buildDir ".fable"] - - // copy rust only tests files (these must be present when running dotnet test as import expr tests for file presence) - makeDirRecursive (buildDir "tests" "src") - copyFiles (projectDir "tests/src") "*.rs" (buildDir "tests/src") - - // run .NET tests - runInDir testAstDir "dotnet test -c Release" - runInDir projectDir "dotnet test -c Release" - - // build Fable Rust tests - runFableWithArgs projectDir [ - "--outDir " + buildDir - "--exclude Fable.Core" - "--lang Rust" - "--fableLib fable-library-rust" - "--noCache" - if testMode = NoStd then "--define NO_STD_NO_EXCEPTIONS" - ] - - // copy project file - copyFile (projectDir "Cargo.toml") buildDir - - // rustfmt all tests - runInDir buildDir "cargo fmt" - // runInDir buildDir "cargo fix --allow-no-vcs" - runInDir buildDir "cargo build" - - // run Fable Rust tests - match testMode with - | Default -> - runInDir buildDir "cargo test" - | NoStd -> - runInDir buildDir "cargo test --features no_std" - | Threaded -> - runInDir buildDir "cargo test --features threaded" - -let testDart isWatch = - if not (pathExists "build/fable-library-dart") then - buildLibraryDart(true) - - let buildDir = resolveDir "build/tests/Dart" - let sourceDir = resolveDir "tests/Dart" - - cleanDirs [buildDir] - makeDirRecursive buildDir - copyFiles sourceDir "pubspec.*" buildDir - copyFiles sourceDir "analysis_options.yaml" buildDir - copyFiles sourceDir "*.dart" buildDir - - runFableWithArgsInDirAs (not isWatch) sourceDir [ - "src" - "--outDir " + (buildDir "src") - "--exclude Fable.Core" - "--lang Dart" - "--noCache" - if isWatch then - "--watch" - $"--runWatch dart test {buildDir}/main.dart" - ] - runInDir buildDir "dart test main.dart" - -let buildLocalPackageWith pkgDir pkgCommand fsproj action = - let version = Publish.loadReleaseVersion "src/Fable.Cli" + "-local-build-" + DateTime.Now.ToString("yyyyMMdd-HHmm") - action version - updatePkgVersionInFsproj fsproj version - run $"dotnet pack {fsproj} -p:Pack=true -c Release -o {pkgDir}" - - // Return install command - $"""dotnet {pkgCommand} --version "{version}" --add-source {fullPath pkgDir}""" - -let buildLocalPackage pkgDir = - buildLocalPackageWith pkgDir - "tool install fable" - (resolveDir "src/Fable.Cli/Fable.Cli.fsproj") (fun version -> - updateVersionsInFableTransforms version [] |> ignore - buildLibraryTs()) - -let testRepos() = - let repos = [ - "https://github.com/alfonsogarciacaro/FsToolkit.ErrorHandling:update-fable-3", "npm i && npm test" - "https://github.com/fable-compiler/fable-promise:master", "npm i && npm test" - "https://github.com/alfonsogarciacaro/Thoth.Json:nagareyama", "dotnet paket restore && npm i && dotnet fable tests -o tests/bin --run mocha tests/bin" - "https://github.com/alfonsogarciacaro/FSharp.Control.AsyncSeq:nagareyama", "cd tests/fable && npm i && npm test" - "https://github.com/alfonsogarciacaro/Fable.Extras:nagareyama", "dotnet paket restore && npm i && npm test" - "https://github.com/alfonsogarciacaro/Fable.Jester:nagareyama", "npm i && npm test" - "https://github.com/Zaid-Ajaj/Fable.SimpleJson:master", "npm i && npm run test-nagareyama" - ] - - let testDir = tempPath() "fable-repos" - printfn $"Cloning repos to: {testDir}" - - cleanDirs [testDir] - makeDirRecursive testDir - let pkgInstallCmd = buildLocalPackage (testDir "pkg") - - for (repo, command) in repos do - let url, branch = let i = repo.LastIndexOf(":") in repo[..i-1], repo[i+1..] - let name = url[url.LastIndexOf("/") + 1..] - runInDir testDir $"git clone {url} {name}" - let repoDir = testDir name - runInDir repoDir ("git checkout " + branch) - runInDir repoDir "dotnet tool uninstall fable" - runInDir repoDir pkgInstallCmd - runInDir repoDir "dotnet tool restore" - runInDir repoDir command - -let githubRelease() = - match envVarOrNone "GITHUB_USER", envVarOrNone "GITHUB_TOKEN" with - | Some user, Some token -> - try - let version, notes = Publish.loadReleaseVersionAndNotes "src/Fable.Cli" - let notes = notes |> Array.map (fun n -> $"""'{n.Replace("'", @"\'").Replace("`", @"\`")}'""") |> String.concat "," - run $"git commit -am \"Release {version}\" && git push" - runSilent $"""node --eval "require('ghreleases').create({{ user: '{user}', token: '{token}', }}, 'fable-compiler', 'Fable', {{ tag_name: '{version}', name: '{version}', body: [{notes}].join('\n'), }}, (err, res) => {{ if (err != null) {{ console.error(err) }} }})" """ - printfn $"Github release %s{version} created successfully" - with ex -> - printfn $"Github release failed: %s{ex.Message}" - | _ -> failwith "Expecting GITHUB_USER and GITHUB_TOKEN enviromental variables" - -let copyFcsRepo sourceDir = - let targetDir = "src/fcs-fable" - let path1 = "fcs/fcs-fable" - let path2 = "src/Compiler" - cleanDirs [targetDir] - copyDirRecursive (sourceDir path1) targetDir - copyDirRecursive (sourceDir path2) (targetDir path2) - removeFile (targetDir ".gitignore") - let projPath = (targetDir "fcs-fable.fsproj") - let projText = readFile projPath - let projText = - Regex.Replace(projText, - @"(\$\(MSBuildProjectDirectory\)).*?(<\/FSharpSourcesRoot>)", - "$1/src/Compiler$2") - // let projText = - // Regex.Replace(projText, - // @"artifacts\/bin\/FSharp.Core\/Release\/netstandard2.0", - // "lib/fcs") - projText |> writeFile projPath - -let syncFcsRepo() = - // FAKE is giving lots of problems with the dotnet SDK version, ignore it - let cheatWithDotnetSdkVersion dir f = - let path = dir "build.fsx" - let script = readFile path - Regex.Replace(script, @"let dotnetExePath =[\s\S]*DotNetCli\.InstallDotNetSDK", "let dotnetExePath = \"dotnet\" //DotNetCli.InstallDotNetSDK") |> writeFile path - f () - runInDir dir "git reset --hard" - - printfn $"Expecting %s{FCS_REPO} repo to be cloned at %s{FCS_REPO_LOCAL}" - - // TODO: Prompt to reset --hard changes - // service_slim - runInDir FCS_REPO_LOCAL ("git checkout " + FCS_REPO_SERVICE_SLIM_BRANCH) - runInDir FCS_REPO_LOCAL "git pull" - cheatWithDotnetSdkVersion (FCS_REPO_LOCAL "fcs") (fun () -> - runBashOrCmd (FCS_REPO_LOCAL "fcs") "build" "") - copyFile (FCS_REPO_LOCAL "artifacts/bin/FSharp.Compiler.Service/Release/netstandard2.0/FSharp.Compiler.Service.dll") "../fable/lib/fcs/" - copyFile (FCS_REPO_LOCAL "artifacts/bin/FSharp.Compiler.Service/Release/netstandard2.0/FSharp.Compiler.Service.xml") "../fable/lib/fcs/" - copyFile (FCS_REPO_LOCAL "artifacts/bin/FSharp.Compiler.Service/Release/netstandard2.0/FSharp.Core.dll") "../fable/lib/fcs/" - copyFile (FCS_REPO_LOCAL "artifacts/bin/FSharp.Compiler.Service/Release/netstandard2.0/FSharp.Core.xml") "../fable/lib/fcs/" - - // fcs-fable - runInDir FCS_REPO_LOCAL ("git checkout " + FCS_REPO_FABLE_BRANCH) - runInDir FCS_REPO_LOCAL "git pull" - cheatWithDotnetSdkVersion (FCS_REPO_LOCAL "fcs") (fun () -> - runBashOrCmd (FCS_REPO_LOCAL "fcs") "build" "CodeGen.Fable") - copyFcsRepo FCS_REPO_LOCAL - -let packages() = - ["Fable.AST", doNothing - "Fable.Core", doNothing - "Fable.Cli", (fun () -> - // TODO: Add library versions for other languages - let compilerVersion = Publish.loadReleaseVersion "src/Fable.Cli" - let updatedLibs = updateVersionsInFableTransforms compilerVersion [ - "js", getNpmVersion "src/fable-library" - ] - buildLibraryTs() - buildLibraryPy() - buildLibraryRust() - buildLibraryDart true - if updatedLibs.Contains("js") then - pushNpmWithoutReleaseNotesCheck "build/fable-library" - ) - "Fable.PublishUtils", doNothing - "fable-metadata", doNothing - "fable-standalone", fun () -> buildStandalone {|minify=true; watch=false|} - "fable-compiler-js", fun () -> buildCompilerJs true - ] - -let publishPackages restArgs = - let packages = - match List.tryHead restArgs with - | Some pkg -> packages() |> List.filter (fun (name,_) -> name = pkg) - | None -> packages() - for (pkg, buildAction) in packages do - if Char.IsUpper pkg[0] then - let projFile = "src" pkg pkg + ".fsproj" - pushFableNuget projFile ["Pack", "true"] buildAction - else - pushNpm ("src" pkg) buildAction - -let hasFlag flag = - BUILD_ARGS_LOWER |> List.contains flag - -match BUILD_ARGS_LOWER with -// | "check-sourcemaps"::_ -> -// ("src/quicktest/Quicktest.fs", "src/quicktest/bin/Quicktest.js", "src/quicktest/bin/Quicktest.js.map") -// |||> sprintf "nodemon --watch src/quicktest/bin/Quicktest.js --exec 'source-map-visualization --sm=\"%s;%s;%s\"'" -// |> List.singleton |> quicktest -// | "coverage"::_ -> coverage() -| ("test"|"test-js")::_ -> testJs() -| "test-mocha"::_ -> compileAndRunTestsWithMocha true "Main" -| "test-mocha-fast"::_ -> compileAndRunTestsWithMocha false "Main" -| "test-react"::_ -> testReact() -| "test-standalone"::_ -> - let minify = hasFlag "--no-minify" |> not - testStandalone(minify) -| "test-standalone-fast"::_ -> testStandaloneFast() -| "test-configs"::_ -> testProjectConfigs() -| "test-integration"::_ -> testIntegration() -| "test-repos"::_ -> testRepos() -| ("test-ts"|"test-typescript")::_ -> testTypeScript(false) -| ("watch-test-ts"|"watch-test-typescript")::_ -> testTypeScript(true) -| "test-py"::_ -> testPython() -| "test-rust"::_ -> testRust Default -| "test-rust-no_std"::_ -> testRust NoStd -| "test-rust-default"::_ -> testRust Default -| "test-rust-threaded"::_ -> testRust Threaded -| "test-dart"::_ -> testDart(false) -| "watch-test-dart"::_ -> testDart(true) - -| "quicktest"::_ -> - buildLibraryTsIfNotExists() - watchFableWithArgs "src/quicktest" ["--watch --exclude Fable.Core --noCache --runScript"] -| "quicktest-ts"::_ -> - buildLibraryTsIfNotExists() - let srcDir = "src/quicktest" - let outPath = "build/quicktest-ts/Quicktest.fs.js" - // Make sure outPath exists so nodemon doesn't complain - if not(pathExists outPath) then - makeDirRecursive (dirname outPath) - writeFile outPath "" - let runCmd = $"npx concurrently \"tsc -w -p {srcDir} --outDir {dirname outPath}\" \"nodemon -w {outPath} {outPath}\"" - watchFableWithArgs srcDir ["--lang ts --watch --exclude Fable.Core --noCache --run"; runCmd] -| ("quicktest-py"|"quicktest-python")::_ -> - buildLibraryPyIfNotExists() - watchFableWithArgs "src/quicktest-py" ["--lang py --watch --exclude Fable.Core --noCache --runScript"] -| "quicktest-dart"::_ -> - buildLibraryDartIfNotExists() - watchFableWithArgs "src/quicktest-dart" ["--lang dart --watch --exclude Fable.Core --noCache --runScript"] -| ("quicktest-rs"|"quicktest-rust")::_ -> - buildLibraryRustIfNotExists() - watchFableWithArgs "src/quicktest-rust" ["--lang rs -e .rs --watch --exclude Fable.Core --noCache --runScript"] -| "run"::_ -> - buildLibraryTsIfNotExists() - // Don't take args from pattern matching because they're lowered - let restArgs = BUILD_ARGS |> List.skip 1 |> String.concat " " - run $"""dotnet run -c Release --project {resolveDir "src/Fable.Cli"} -- {restArgs}""" - -| "package"::_ -> - let pkgInstallCmd = buildLocalPackage (resolveDir "temp/pkg") - printfn $"\nPackage has been created, use the following command to install it:\n {pkgInstallCmd}\n" -| "package-core"::_ -> - let pkgInstallCmd = buildLocalPackageWith (resolveDir "temp/pkg") "add package Fable.Core" (resolveDir "src/Fable.Core/Fable.Core.fsproj") ignore - printfn $"\nFable.Core package has been created, use the following command to install it:\n {pkgInstallCmd}\n" - -| ("fable-library"|"library")::_ -| ("fable-library-ts"|"library-ts")::_ -> buildLibraryTs() -| ("fable-library-py"|"library-py")::_ -> buildLibraryPy() -| ("fable-library-rust" | "library-rust")::_ -> buildLibraryRust() -| ("fable-library-dart" | "library-dart")::_ -> - let clean = hasFlag "--no-clean" |> not - buildLibraryDart(clean) - -| ("fable-compiler-js"|"compiler-js")::_ -> - let minify = hasFlag "--no-minify" |> not - buildCompilerJs(minify) -| ("fable-standalone"|"standalone")::_ -> - let minify = hasFlag "--no-minify" |> not - buildStandalone {|minify=minify; watch=false|} -| ("fable-worker"|"worker")::_ -> - let minify = hasFlag "--no-minify" |> not - buildWorker {|minify=minify; watch=false|} -| "watch-standalone"::_ -> buildStandalone {|minify=false; watch=true|} - -| "sync-fcs-repo"::_ -> syncFcsRepo() -| "copy-fcs-repo"::_ -> copyFcsRepo FCS_REPO_LOCAL - -| "publish"::restArgs -> publishPackages restArgs -| "github-release"::_ -> - publishPackages [] - githubRelease () - -| _ -> - printfn """Please pass a target name. Examples: - -- Use `test` to run tests: - dotnet fsi build.fsx test - -- Use `package` to build a local package: - dotnet fsi build.fsx package - -- Use `run` to compile a project with development version: - dotnet fsi build.fsx run ../path/to/my/project [Fable options] - -- Use `quicktest` to quickly test development version with src/quicktest project: - dotnet fsi build.fsx quicktest -""" - -printfn "Build finished successfully" diff --git a/build.sh b/build.sh index 3d92fafb60..546c1de0e3 100755 --- a/build.sh +++ b/build.sh @@ -1,3 +1,4 @@ #!/bin/sh -x -dotnet fsi build.fsx $@ \ No newline at end of file +dotnet tool restore +dotnet run --project build/Build.fsproj -- $@ diff --git a/build/Build.fsproj b/build/Build.fsproj new file mode 100644 index 0000000000..611f6d9eef --- /dev/null +++ b/build/Build.fsproj @@ -0,0 +1,51 @@ + + + Exe + net6.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/FableLibrary/Core.fs b/build/FableLibrary/Core.fs new file mode 100644 index 0000000000..2515776d0a --- /dev/null +++ b/build/FableLibrary/Core.fs @@ -0,0 +1,90 @@ +namespace Build.FableLibrary + +open BlackFox.CommandLine +open Fake.IO +open System.IO +open Build.Utils +open Build.Utils +open System.Diagnostics +open SimpleExec +open Spectre.Console +open SpectreCoff + +/// +/// Building fable-library is similar enough for all the targets +/// that we can use this class to standardise the process. +/// +type BuildFableLibrary + ( + language: string, + libraryDir: string, + sourceDir: string, + buildDir: string, + outDir: string, + ?fableLibArg: string + ) = + + // It seems like the different target have a different way of supporting + // --fableLib argument. + // For example, + // If we provide `--fableLib < out dir path>`, then the Dart target + // generates import './Option.dart' as option; + // Bt if we provides `--fableLib .`, then the Dart target + // generates import '../../src/fable-library-dart/Option.dart' as option; + // Python seems to ignore completely the --fableLib argument. + // Investigation are required to make all the targets behave the same way. + // For now, I am providing a way to override the --fableLib argument in the + // build system but it should be removed once the issue is fixed. + let fableLibArg = defaultArg fableLibArg "." + + member val LibraryDir = libraryDir + member val SourceDir = sourceDir + member val BuildDir = buildDir + member val OutDir = outDir + + // Allow language to be orverriden from "do constructor" + // Useful for JavaScript target which is a specialisation of the TypeScript + member val Language = language with get, set + + abstract member FableArgsBuilder: (CmdLine -> CmdLine) + default _.FableArgsBuilder = id + + abstract member PostFableBuildStage: unit -> unit + default _.PostFableBuildStage() = () + + abstract member CopyStage: unit -> unit + default _.CopyStage() = () + + member this.Run(?skipIfExist : bool) = + let skipIfExist = defaultArg skipIfExist false + + if skipIfExist && Directory.Exists outDir then + Calm "Skipping Fable build stage" |> toConsole + + else + + Calm "Cleaning build directory" |> toConsole + + if Directory.Exists buildDir then + Directory.Delete(buildDir, true) + + Calm "Building Fable.Library" |> toConsole + + let args = + CmdLine.appendRaw sourceDir + >> CmdLine.appendPrefix "--outDir" outDir + >> CmdLine.appendPrefix "--fableLib" fableLibArg + >> CmdLine.appendPrefix "--lang" language + >> CmdLine.appendPrefix "--exclude" "Fable.Core" + >> CmdLine.appendPrefix "--define" "FABLE_LIBRARY" + >> CmdLine.appendRaw "--noCache" + // Target implementation can require additional arguments + >> this.FableArgsBuilder + + Command.Fable(args) + + Calm "Copy stage" |> toConsole + this.CopyStage() + + Calm "Post Fable build stage" |> toConsole + this.PostFableBuildStage() diff --git a/build/FableLibrary/Dart.fs b/build/FableLibrary/Dart.fs new file mode 100644 index 0000000000..b2a77532e3 --- /dev/null +++ b/build/FableLibrary/Dart.fs @@ -0,0 +1,26 @@ +namespace Build.FableLibrary + +open System.IO +open Fake.IO + +type BuildFableLibraryDart() = + inherit + BuildFableLibrary( + "dart", + Path.Combine("src", "fable-library-dart"), + Path.Combine("src", "fable-library-dart"), + Path.Combine("temp", "fable-library-dart"), + Path.Combine("temp", "fable-library-dart"), + Path.Combine(".", "temp", "fable-library-dart") + ) + + override this.CopyStage() = + Directory.GetFiles(this.SourceDir, "pubspec.*") + |> Shell.copyFiles this.BuildDir + + Shell.copyFile + this.BuildDir + (Path.Combine(this.LibraryDir, "analysis_options.yaml")) + + Directory.GetFiles(this.SourceDir, "*.dart") + |> Shell.copyFiles this.OutDir diff --git a/build/FableLibrary/JavaScript.fs b/build/FableLibrary/JavaScript.fs new file mode 100644 index 0000000000..689ed1c298 --- /dev/null +++ b/build/FableLibrary/JavaScript.fs @@ -0,0 +1,44 @@ +namespace Build.FableLibrary + +open System.IO +open Fake.IO +open BlackFox.CommandLine +open SimpleExec + +type BuildFableLibraryJavaScript() = + // JavaScript is a specialisation of the TypeScript target + inherit BuildFableLibraryTypeScript() + + let jsOutDir = Path.Combine("temp", "fable-library") + do base.Language <- "javascript" + + override this.PostFableBuildStage() = + // Alias to make it clear which directory is referred to + let tsBuildDir = this.BuildDir + + // Make sure to work with a clean build directory + // We need to delete the directy here because JavaScript is + // a bit special compared to other targets. + // JavaScript things happens after the Fable.Library to TypeScript compilation + if Directory.Exists jsOutDir then + Directory.Delete(jsOutDir, true) + + Command.Run("npm", "install", workingDirectory = Build.Workspace.root) + + // Compile the library to JavaScript using the TypeScript compiler + let args = + CmdLine.empty + |> CmdLine.appendRaw "tsc" + |> CmdLine.appendPrefix "--project" tsBuildDir + |> CmdLine.appendPrefix "--outDir" jsOutDir + |> CmdLine.toString + + Command.Run("npx", args) + + // Copy lib/big.d.ts to the JavaScript build directory + let bigDts = Path.Combine(tsBuildDir, "lib", "big.d.ts") + Shell.copyFile bigDts jsOutDir + + Shell.copyFile jsOutDir (Path.Combine(this.SourceDir, "package.json")) + Shell.copyFile jsOutDir (Path.Combine(this.SourceDir, "CHANGELOG.md")) + Shell.copyFile jsOutDir (Path.Combine(this.SourceDir, "README.md")) diff --git a/build/FableLibrary/Python.fs b/build/FableLibrary/Python.fs new file mode 100644 index 0000000000..6cb4179a14 --- /dev/null +++ b/build/FableLibrary/Python.fs @@ -0,0 +1,32 @@ +namespace Build.FableLibrary + +open System.IO +open Fake.IO +open Build.Utils + +type BuildFableLibraryPython() = + inherit + BuildFableLibrary( + "python", + Path.Combine("src", "fable-library-py"), + Path.Combine("src", "fable-library-py", "fable_library"), + Path.Combine("temp", "fable-library-py"), + Path.Combine("temp", "fable-library-py", "fable_library") + ) + + override this.CopyStage() = + // // Copy all *.rs files to the build directory + Directory.GetFiles(this.LibraryDir, "*") + |> Shell.copyFiles this.BuildDir + + Directory.GetFiles(this.SourceDir, "*.py") + |> Shell.copyFiles this.OutDir + + override this.PostFableBuildStage() = + // Fix issues with Fable .fsproj not supporting links + let linkedFileFolder = + Path.Combine(this.BuildDir, "fable_library", "fable-library") + + Directory.GetFiles(linkedFileFolder, "*") |> Shell.copyFiles this.OutDir + + Shell.deleteDir (this.BuildDir "fable_library/fable-library") diff --git a/build/FableLibrary/Rust.fs b/build/FableLibrary/Rust.fs new file mode 100644 index 0000000000..73c36fc685 --- /dev/null +++ b/build/FableLibrary/Rust.fs @@ -0,0 +1,41 @@ +namespace Build.FableLibrary + +open System.IO +open Fake.IO +open Build.Utils +open SimpleExec + +type BuildFableLibraryRust() = + inherit + BuildFableLibrary( + "rust", + Path.Combine("src", "fable-library-rust"), + Path.Combine("src", "fable-library-rust", "src"), + Path.Combine("temp", "fable-library-rust"), + Path.Combine("temp", "fable-library-rust", "src") + ) + + override this.PostFableBuildStage() = + Command.Run("cargo", "fmt", workingDirectory = this.BuildDir) + + Command.Run( + "cargo", + "fix --allow-no-vcs", + workingDirectory = this.BuildDir + ) + + Command.Run("cargo", "build", workingDirectory = this.BuildDir) + + override this.CopyStage() = + // Copy all *.rs files to the build directory + Directory.GetFiles(this.SourceDir, "*.rs") + |> Shell.copyFiles this.OutDir + + Shell.copyFile + this.BuildDir + (Path.Combine(this.LibraryDir, "Cargo.toml")) + + Shell.copyDir + (Path.Combine(this.BuildDir, "vendored")) + (Path.Combine(this.LibraryDir, "vendored")) + FileFilter.allFiles diff --git a/build/FableLibrary/TypeScript.fs b/build/FableLibrary/TypeScript.fs new file mode 100644 index 0000000000..dfdcbeb924 --- /dev/null +++ b/build/FableLibrary/TypeScript.fs @@ -0,0 +1,47 @@ +namespace Build.FableLibrary + +open System.IO +open Fake.IO +open BlackFox.CommandLine +open SimpleExec + +type BuildFableLibraryTypeScript() = + inherit + BuildFableLibrary( + "typescript", + Path.Combine("src", "fable-library"), + Path.Combine("src", "fable-library"), + Path.Combine("temp", "fable-library-ts"), + Path.Combine("temp", "fable-library-ts"), + Path.Combine(".", "temp", "fable-library-ts") + ) + + override _.FableArgsBuilder = + CmdLine.appendPrefix "--typedArrays" "false" + >> CmdLine.appendPrefix "--define" "FX_NO_BIGINT" + + override this.CopyStage() = + Command.Run("npm", "install", workingDirectory = Build.Workspace.root) + + // Copy all *.ts files to the build directory from source directory + Directory.GetFiles(this.SourceDir, "*.ts") + |> Shell.copyFiles this.OutDir + + // Copy the tsconfig.json file to the build directory + let typeScriptConfig = + Path.Combine(this.SourceDir, "ts", "tsconfig.json") + + Shell.copyFile this.OutDir typeScriptConfig + + // Copy the lib folder to the build directory + let libSourceFolder = Path.Combine(this.SourceDir, "lib") + let libDestinationFolder = Path.Combine(this.OutDir, "lib") + Shell.copyDir libDestinationFolder libSourceFolder FileFilter.allFiles + + // Copy the package.json file to the build directory + let packageJson = Path.Combine(this.SourceDir, "package.json") + Shell.copyFile this.OutDir packageJson + + // Copy the README.md file to the build directory + let readme = Path.Combine(this.SourceDir, "README.md") + Shell.copyFile this.OutDir readme diff --git a/build/FcsRepo.fs b/build/FcsRepo.fs new file mode 100644 index 0000000000..c9efdc5d81 --- /dev/null +++ b/build/FcsRepo.fs @@ -0,0 +1,71 @@ +module Build.FcsRepo + +open SimpleExec +open Build.Utils + +[] +let FCS_REPO = "https://github.com/ncave/fsharp" + +let FCS_REPO_LOCAL = Path.Resolve("../fsharp_fable") + +[] +let FCS_REPO_FABLE_BRANCH = "fable" + +[] +let FCS_REPO_SERVICE_SLIM_BRANCH = "service_slim" + +let sync () = + printfn "Waiting for ncave support on how to use the FCS repo in Fable" + printfn "See: https://github.com/fable-compiler/Fable/issues/3531" +// printfn +// $"""Expecting {FCS_REPO} repo to be cloned at {FCS_REPO_LOCAL} + +// Run the following command to clone the repo: +// git clone {FCS_REPO} {FCS_REPO_LOCAL} +// """ + +// Command.Run( +// "git", +// $"checkout {FCS_REPO_SERVICE_SLIM_BRANCH}", +// workingDirectory = FCS_REPO_LOCAL +// ) + +// Command.Run( +// "git", +// "pull", +// workingDirectory = FCS_REPO_LOCAL +// ) + +// let program, args = +// if Environment.isWindows () then +// "cmd.exe", "/c build.cmd" +// else +// "sh", "build.sh" + +// Command.Run( +// program, +// args, +// workingDirectory = (FCS_REPO_LOCAL "fcs") +// ) + +// Command.Run( +// "git", +// $"checkout {FCS_REPO_FABLE_BRANCH}", +// workingDirectory = FCS_REPO_LOCAL +// ) + +// Command.Run( +// "git", +// "pull", +// workingDirectory = FCS_REPO_LOCAL +// ) + +// Command.Run( +// program, +// $"{args} CodeGen.Fable", +// workingDirectory = (FCS_REPO_LOCAL "fcs") +// ) + +let copy () = + printfn "Waiting for ncave support on how to use the FCS repo in Fable" + printfn "See: https://github.com/fable-compiler/Fable/issues/3531" diff --git a/build/GithubRelease.fs b/build/GithubRelease.fs new file mode 100644 index 0000000000..8c65473813 --- /dev/null +++ b/build/GithubRelease.fs @@ -0,0 +1,79 @@ +module Build.GithubRelease + +open Build.Utils +open Octokit +open System +open Build.Workspace +open SimpleExec +open BlackFox.CommandLine + +let private createGithubRelease + (githubToken: string) + (version: ChangelogParser.Types.Version) + = + + let githubClient = GitHubClient(ProductHeaderValue("fable-release-tool")) + githubClient.Credentials <- Credentials(githubToken) + + let newRelease = NewRelease(version.Version.ToString()) + newRelease.Name <- version.Version.ToString() + newRelease.Body <- ChangelogParser.Version.bodyAsMarkdown version + newRelease.Draft <- false + newRelease.Prerelease <- false // TODO: Detect if this is a prerelease + + githubClient.Repository.Release.Create( + "fable-compiler", + "Fable", + newRelease + ) + |> Async.AwaitTask + |> Async.RunSynchronously + |> ignore + +let private createTag (version: ChangelogParser.Types.Version) = + let versionText = version.Version.ToString() + + Command.Run( + "git", + CmdLine.empty + |> CmdLine.appendRaw "commit" + |> CmdLine.appendPrefix "-am" $"Release {versionText}" + |> CmdLine.toString + ) + + Command.Run( + "git", + CmdLine.empty + |> CmdLine.appendRaw "tag" + |> CmdLine.appendPrefix "-a" (versionText) + |> CmdLine.appendPrefix "-m" $"Release {versionText}" + |> CmdLine.toString + ) + + Command.Run( + "git", + "push" + ) + + Command.Run( + "git", + CmdLine.empty + |> CmdLine.appendRaw "push" + |> CmdLine.appendRaw "origin" + |> CmdLine.appendRaw versionText + |> CmdLine.toString + ) + + +let handle (args: string list) = + Publish.handle args + + let githubToken = Environment.GetEnvironmentVariable("GITHUB_TOKEN") + + if githubToken = null then + failwith "Missing GITHUB_TOKEN environment variable" + + let versionInfo = Changelog.getLastVersion Changelog.fableCLi + + createGithubRelease githubToken versionInfo + createTag versionInfo diff --git a/build/Main.fs b/build/Main.fs new file mode 100644 index 0000000000..00236e28b1 --- /dev/null +++ b/build/Main.fs @@ -0,0 +1,119 @@ +module Build.Main + +open Build.FableLibrary + +// This is a basic help message, as the CLI parser is not a "real" CLI parser +// For now, it is enough as this is just a dev tool +let printHelp () = + let helpText = + """ +Usage: dotnet run [] + +Available commands: + fable-library + + Options: + --javascript Build fable-library for JavaScript + --typescript Build fable-library for TypeScript + --python Build fable-library for Python + --dart Build fable-library for Dart + --rust Build fable-library for Rust + + quicktest Watch for changes and re-run the quicktest + This is useful to work on a feature in an isolated + manner to avoid all the noise coming from the main tests + + Subcommands: + javascript Run for JavaScript + typescript Run for TypeScript + python Run for Python + dart Run for Dart + rust Run for Rust + + Options: + --skip-fable-library Skip building fable-library if folder already exists + + test Run the main tests suite + Subcommands: + javascript Run the tests for JavaScript + typescript Run the tests for TypeScript + python Run the tests for Python + dart Run the tests for Dart + rust Run the tests for Rust + integration Run the integration test suite + standalone Tests the standalone version of Fable + (Fable running on top of Node.js) + + Options for all except integration and standalone: + --watch Watch for changes and re-run the tests + --skip-fable-library Skip building fable-library if folder already exists + --no-dotnet When in watch mode, do not run the .NET tests + + Options for JavaScript: + --reat-only Run only the tests for React (can be run in watch mode) + + Options for Rust: + --ast-only Run only the tests for the AST (can be run in watch mode) + --no_std Compile and run the tests without the standard library + --threaded Compile and run the tests with the threaded runtime + + standalone Compile standalone version of Fable running + on top of of Node.js + + Options: + --no-minify Don't minify the JavaScript output + --watch Watch for changes and recompile + + publish Publish the different packages to NuGet and NPM + based on the CHANGELOG.md files + If the last version in the CHANGELOG.md is + different from the version in the packages, + the package will be published + + github-release Create a GitHub release based on the CHANGELOG.md + file and the version in the package.json + This will also invoke the publish command + """ + + printfn "%s" helpText + +[] +let main argv = + let argv = argv |> Array.map (fun x -> x.ToLower()) |> Array.toList + + match argv with + | "fable-library" :: args -> + match args with + | "--javascript" :: _ -> BuildFableLibraryJavaScript().Run() + | "--typescript" :: _ -> BuildFableLibraryTypeScript().Run() + | "--python" :: _ -> BuildFableLibraryPython().Run() + | "--dart" :: _ -> BuildFableLibraryDart().Run() + | "--rust" :: _ -> BuildFableLibraryRust().Run() + | _ -> printHelp () + | "test" :: args -> + match args with + | "javascript" :: args -> Test.JavaScript.handle args + | "typescript" :: args -> Test.TypeScript.handle args + | "python" :: args -> Test.Python.handle args + | "dart" :: args -> Test.Dart.handle args + | "rust" :: args -> Test.Rust.handle args + | "integration" :: args -> Test.Integration.handle args + | "standalone" :: _ -> Test.Standalone.handle args + | _ -> printHelp () + | "quicktest" :: args -> + match args with + | "javascript" :: _ -> Quicktest.JavaScript.handle args + | "typescript" :: _ -> Quicktest.TypeScript.handle args + | "python" :: _ -> Quicktest.Python.handle args + | "dart" :: _ -> Quicktest.Dart.handle args + | "rust" :: _ -> Quicktest.Rust.handle args + | _ -> printHelp () + | "standalone" :: args -> Standalone.handle args + | "sync-fcs-repo":: _ -> FcsRepo.sync () + | "copy-fcs-repo":: _ -> FcsRepo.copy () + | "publish" :: args -> Publish.handle args + | "github-release" :: args -> GithubRelease.handle args + | "--help" :: _ + | _ -> printHelp () + + 0 diff --git a/build/Publish.fs b/build/Publish.fs new file mode 100644 index 0000000000..7ac6b1a76e --- /dev/null +++ b/build/Publish.fs @@ -0,0 +1,154 @@ +module Build.Publish + +open Build.Utils +open System.IO +open System.Text.RegularExpressions +open Build.FableLibrary +open System +open Build.Workspace + +let private updateLibraryVersionInFableTransforms + (compilerVersion: string) + (librariesVersion: {| JavaScript: string |}) + = + let filePath = + Path.Resolve("src", "Fable.Transforms", "Global", "Compiler.fs") + + // Use a mutable variable for simplicity + // Allows to keep track of successive replacements + let mutable fileContent = File.ReadAllText filePath + + // Replace compiler version + fileContent <- + Regex.Replace( + fileContent, + $@"^(?'indentation'\s*)let \[\] VERSION = ""(?'version'.*?)""", + (fun (m: Match) -> + m.Groups.["indentation"].Value + + $"let [] VERSION = \"{compilerVersion}\"" + ), + RegexOptions.Multiline + ) + + let replaceLangVersion (langPrefix: string) (version: string) = + let prefix = langPrefix.ToUpperInvariant() + + fileContent <- + Regex.Replace( + fileContent, + $@"^(?'indentation'\s*)let \[\] {prefix}_LIBRARY_VERSION = ""(?'version'.*?)""", + (fun (m: Match) -> + m.Groups.["indentation"].Value + + $"let [] {prefix}_LIBRARY_VERSION = \"{version}\"" + ), + RegexOptions.Multiline + ) + + replaceLangVersion "js" librariesVersion.JavaScript + + // Save changes on the disk + File.WriteAllText(filePath, fileContent) + +let private publishNuget (fsprojDir : string) = + let fsprojFiles = Directory.GetFiles(fsprojDir, "*.fsproj") + + if Array.length fsprojFiles <> 1 then + failwithf + $"Expected to find exactly one fsproj file in %s{fsprojDir}" + + let fsprojPath = fsprojFiles[0] + let fsprojContent = File.ReadAllText fsprojPath + let changelogPath = Path.Combine(fsprojDir, "CHANGELOG.md") + let lastChangelogVersion = + Changelog.getLastVersion changelogPath + |> fun v -> v.Version.ToString() + + printfn $"Publishing: %s{fsprojDir}" + + let nugetKey = Environment.GetEnvironmentVariable("FABLE_NUGET_KEY") + + if nugetKey = null then + failwithf $"Missing FABLE_NUGET_KEY environment variable" + + + if Fsproj.needPublishing fsprojContent lastChangelogVersion then + let updatedFsprojContent = Fsproj.replaceVersion fsprojContent lastChangelogVersion + File.WriteAllText(fsprojPath, updatedFsprojContent) + let nupkgPath = Dotnet.pack fsprojDir + let nupkgFolder = Path.GetDirectoryName nupkgPath + Dotnet.Nuget.push(nupkgFolder, nugetKey) + printfn $"Published!" + else + printfn $"Already up-to-date, skipping..." + +let private publishNpm (projectDir : string) = + let packageJsonPath = Path.Combine(projectDir, "package.json") + let packageJsonContent = File.ReadAllText(packageJsonPath) + let changelogPath = Path.Combine(projectDir, "CHANGELOG.md") + let lastChangelogVersion = + Changelog.getLastVersion changelogPath + |> fun v -> v.Version.ToString() + + printfn $"Publishing: %s{projectDir}" + + if Npm.needPublishing packageJsonContent lastChangelogVersion then + let updatedPackageJsonContent = Npm.replaceVersion packageJsonContent lastChangelogVersion + File.WriteAllText(packageJsonPath, updatedPackageJsonContent) + Npm.publish projectDir + printfn $"Published!" + else + printfn $"Already up-to-date, skipping..." + +let private updateFableLibraryPackageJsonVersion () = + let packageJsonPath = Path.Combine(ProjectDir.fable_library, "package.json") + let packageJsonContent = File.ReadAllText(packageJsonPath) + let changelogPath = Path.Combine(ProjectDir.fable_library, "CHANGELOG.md") + let lastChangelogVersion = + Changelog.getLastVersion changelogPath + |> fun v -> v.Version.ToString() + + let updatedPackageJsonContent = Npm.replaceVersion packageJsonContent lastChangelogVersion + File.WriteAllText(packageJsonPath, updatedPackageJsonContent) + +let handle (args: string list) = + // Build all the fable-libraries + BuildFableLibraryDart().Run() + BuildFableLibraryJavaScript().Run() + BuildFableLibraryPython().Run() + BuildFableLibraryRust().Run() + BuildFableLibraryTypeScript().Run() + + // Handle the NPM packages + + // For fable-library, we use the compiled version of the project for publishing + // This i because we want to publish the JavaScript code and not a mix of F# and TypeScript + publishNpm ProjectDir.temp_fable_library + // We need also want to update the original package.json if needed + // This is to keep the versions consistent across the project + // and also will be used when updating libraries version inside of Fable compiler + updateFableLibraryPackageJsonVersion () + + publishNpm ProjectDir.fable_metadata + + // Disabled because standalone terser optimisation seems to never end + // Standalone.handle [] + // publishNpm ProjectDir.fable_standalone + + // Disabled as we need standalone + // TODO: Build fable compiler js + // publishNpm ProjectDir.fable_compiler_js + + // Update embedded version (both compiler and libraries) + let changelogPath = Path.Combine(ProjectDir.fableCli, "CHANGELOG.md") + let compilerVersion = + Changelog.getLastVersion changelogPath + |> fun v -> v.Version.ToString() + + updateLibraryVersionInFableTransforms compilerVersion {| + JavaScript = Npm.getVersionFromProjectDir ProjectDir.temp_fable_library + |} + + publishNuget ProjectDir.fableAst + publishNuget ProjectDir.fableCore + publishNuget ProjectDir.fableCli + publishNuget ProjectDir.fablePublishUtils diff --git a/build/Quicktest/Core.fs b/build/Quicktest/Core.fs new file mode 100644 index 0000000000..6886c9a063 --- /dev/null +++ b/build/Quicktest/Core.fs @@ -0,0 +1,59 @@ +module Build.Quicktest.Core + +open Build.FableLibrary +open SimpleExec +open BlackFox.CommandLine +open Build.Utils + +type RunMode = + | RunScript + | RunCommand of string + +type QuicktestConfig = { + Language: string + FableLibBuilder: BuildFableLibrary + ProjectDir: string + Extension: string + RunMode: RunMode +} + +let genericQuicktest (config: QuicktestConfig) (args: string list) = + let skipFableLibrary = args |> List.contains "--skip-fable-library" + + config.FableLibBuilder.Run(skipFableLibrary) + + let appendRunMode (cmdLine: CmdLine) = + match config.RunMode with + | RunScript -> cmdLine |> CmdLine.appendRaw "--runScript" + | RunCommand command -> + cmdLine + // Use appendRaw to avoid quoting the command + |> CmdLine.appendRaw "--run" + |> CmdLine.appendRaw command + + let projectDir = Path.Resolve config.ProjectDir + + Command.Fable( + CmdLine.empty + |> CmdLine.appendRaw "clean" + + |> CmdLine.appendRaw projectDir + |> CmdLine.appendPrefix "--lang" config.Language + |> CmdLine.appendPrefix "--extension" config.Extension + |> CmdLine.appendRaw "--yes" + , workingDirectory = projectDir + ) + + Command.WatchFableAsync( + CmdLine.empty + |> CmdLine.appendRaw projectDir + |> CmdLine.appendPrefix "--lang" config.Language + |> CmdLine.appendPrefix "--extension" config.Extension + |> CmdLine.appendPrefix "--exclude" "Fable.Core" + |> CmdLine.appendRaw "--noCache" + |> CmdLine.appendRaw "--watch" + |> appendRunMode, + workingDirectory = projectDir + ) + |> Async.AwaitTask + |> Async.RunSynchronously diff --git a/build/Quicktest/Dart.fs b/build/Quicktest/Dart.fs new file mode 100644 index 0000000000..0b626e5ad6 --- /dev/null +++ b/build/Quicktest/Dart.fs @@ -0,0 +1,15 @@ +module Build.Quicktest.Dart + +open Build.FableLibrary +open Build.Quicktest.Core + +let handle (args: string list) = + genericQuicktest + { + Language = "dart" + FableLibBuilder = BuildFableLibraryDart() + ProjectDir = "src/quicktest-dart" + Extension = ".dart" + RunMode = RunScript + } + args \ No newline at end of file diff --git a/build/Quicktest/JavaScript.fs b/build/Quicktest/JavaScript.fs new file mode 100644 index 0000000000..0b7ff02299 --- /dev/null +++ b/build/Quicktest/JavaScript.fs @@ -0,0 +1,18 @@ +module Build.Quicktest.JavaScript + +open Build.FableLibrary +open BlackFox.CommandLine +open Build.Utils +open SimpleExec +open Build.Quicktest.Core + +let handle (args: string list) = + genericQuicktest + { + Language = "javascript" + FableLibBuilder = BuildFableLibraryJavaScript() + ProjectDir = "src/quicktest" + Extension = ".js" + RunMode = RunScript + } + args \ No newline at end of file diff --git a/build/Quicktest/Python.fs b/build/Quicktest/Python.fs new file mode 100644 index 0000000000..f4d90f0a56 --- /dev/null +++ b/build/Quicktest/Python.fs @@ -0,0 +1,18 @@ +module Build.Quicktest.Python + +open Build.FableLibrary +open Build.Quicktest.Core +open SimpleExec + +let handle (args: string list) = + Command.Run("poetry", "install") + + genericQuicktest + { + Language = "python" + FableLibBuilder = BuildFableLibraryPython() + ProjectDir = "src/quicktest-py" + Extension = ".py" + RunMode = RunScript + } + args \ No newline at end of file diff --git a/build/Quicktest/Rust.fs b/build/Quicktest/Rust.fs new file mode 100644 index 0000000000..19bc18317c --- /dev/null +++ b/build/Quicktest/Rust.fs @@ -0,0 +1,15 @@ +module Build.Quicktest.Rust + +open Build.FableLibrary +open Build.Quicktest.Core + +let handle (args: string list) = + genericQuicktest + { + Language = "rust" + FableLibBuilder = BuildFableLibraryRust() + ProjectDir = "src/quicktest-rust" + Extension = ".rs" + RunMode = RunScript + } + args \ No newline at end of file diff --git a/build/Quicktest/TypeScript.fs b/build/Quicktest/TypeScript.fs new file mode 100644 index 0000000000..4c6a8701f6 --- /dev/null +++ b/build/Quicktest/TypeScript.fs @@ -0,0 +1,59 @@ +module Build.Quicktest.TypeScript + +open Build.FableLibrary +open Build.Quicktest.Core +open BlackFox.CommandLine +open Build.Utils +open System.IO + +let handle (args: string list) = + + let srcDir = Path.Resolve "src/quicktest" + let outDir = Path.Resolve "temp/quicktest-ts" + let mainFile = outDir "Quicktest.fs.js" + + // Make sure the output directory exists, so nodemon doesn't complain + Directory.CreateDirectory(outDir) |> ignore + FileInfo(mainFile).Create() |> ignore + + let tscCommand = + CmdLine.empty + |> CmdLine.appendRaw "npx" + |> CmdLine.appendRaw "tsc" + |> CmdLine.appendRaw "-w" + |> CmdLine.appendPrefix "-p" srcDir + |> CmdLine.appendPrefix "--outDir" outDir + |> CmdLine.toString + + let nodemonCommand = + CmdLine.empty + |> CmdLine.appendRaw "npx" + |> CmdLine.appendRaw "nodemon" + |> CmdLine.appendPrefix "--delay" "500ms" + |> CmdLine.appendPrefix "-w" outDir + |> CmdLine.appendRaw mainFile + |> CmdLine.toString + + let appendQuotedCommand (arg: string) (cmd: CmdLine) = + cmd + |> CmdLine.appendRaw "\"" + |> CmdLine.appendRaw arg + |> CmdLine.appendRaw "\"" + + let runCommand = + CmdLine.empty + |> CmdLine.appendRaw "npx" + |> CmdLine.appendRaw "concurrently" + |> appendQuotedCommand tscCommand + |> appendQuotedCommand nodemonCommand + |> CmdLine.toString + + genericQuicktest + { + Language = "typescript" + FableLibBuilder = BuildFableLibraryTypeScript() + ProjectDir = "src/quicktest" + Extension = ".fs.ts" + RunMode = RunCommand runCommand + } + args diff --git a/build/SimpleExec.Extensions.fs b/build/SimpleExec.Extensions.fs new file mode 100644 index 0000000000..a7fe7ee6f4 --- /dev/null +++ b/build/SimpleExec.Extensions.fs @@ -0,0 +1,154 @@ +module SimpleExec + +open SimpleExec +open BlackFox.CommandLine +open Build.Utils + +type Command with + + static member Fable + ( + args: CmdLine, + ?workingDirectory: string, + ?noEcho, + ?echoPrefix + ) = + let localFableDir = + __SOURCE_DIRECTORY__ ".." "src" "Fable.Cli" + + let args = + CmdLine.concat [ + CmdLine.empty + |> CmdLine.appendRaw "run" + |> CmdLine.appendPrefix "-c" "Release" + |> CmdLine.appendPrefix "--project" localFableDir + |> CmdLine.appendRaw "--" + + args + + ] + |> CmdLine.toString + + Command.Run( + "dotnet", + args, + ?workingDirectory = workingDirectory, + ?noEcho = noEcho, + ?echoPrefix = echoPrefix + ) + + static member Fable + ( + ?argsBuilder: CmdLine -> CmdLine, + ?workingDirectory: string, + ?noEcho, + ?echoPrefix + ) = + let localFableDir = + __SOURCE_DIRECTORY__ ".." "src" "Fable.Cli" + + let argsBuilder = defaultArg argsBuilder id + + let args = + CmdLine.empty + |> CmdLine.appendRaw "run" + |> CmdLine.appendPrefix "-c" "Release" + |> CmdLine.appendPrefix "--project" localFableDir + |> CmdLine.appendRaw "--" + |> argsBuilder + |> CmdLine.toString + + Command.Run( + "dotnet", + args, + ?workingDirectory = workingDirectory, + ?noEcho = noEcho, + ?echoPrefix = echoPrefix + ) + + static member FableAsync + ( + argsBuilder: CmdLine -> CmdLine, + ?workingDirectory, + ?noEcho, + ?echoPrefix + ) = + let localFableDir = + __SOURCE_DIRECTORY__ ".." "src" "Fable.Cli" + + let argsBuilder = + CmdLine.empty + |> CmdLine.appendRaw "run" + |> CmdLine.appendPrefix "-c" "Release" + |> CmdLine.appendPrefix "--project" localFableDir + |> CmdLine.appendRaw "--" + |> argsBuilder + |> CmdLine.toString + + Command.RunAsync( + "dotnet", + argsBuilder, + ?workingDirectory = workingDirectory, + ?noEcho = noEcho, + ?echoPrefix = echoPrefix + ) + + static member WatchFableAsync + ( + argsBuilder: CmdLine -> CmdLine, + ?workingDirectory, + ?noEcho, + ?echoPrefix + ) = + let localFableDir = + __SOURCE_DIRECTORY__ ".." "src" "Fable.Cli" + + let argsBuilder = + CmdLine.empty + |> CmdLine.appendRaw "watch" + |> CmdLine.appendPrefix "--project" localFableDir + |> CmdLine.appendRaw "run" + // Without the release mode, Fable stack overflow when compiling the tests + |> CmdLine.appendPrefix "-c" "Release" + |> CmdLine.appendRaw "--" + |> argsBuilder + |> CmdLine.toString + + Command.RunAsync( + "dotnet", + argsBuilder, + ?workingDirectory = workingDirectory, + ?noEcho = noEcho, + ?echoPrefix = echoPrefix + ) + + static member WatchFableAsync + ( + args: CmdLine, + ?workingDirectory, + ?noEcho, + ?echoPrefix + ) = + let localFableDir = + __SOURCE_DIRECTORY__ ".." "src" "Fable.Cli" + + let args = + CmdLine.concat [ + CmdLine.empty + |> CmdLine.appendRaw "run" + |> CmdLine.appendPrefix "-c" "Release" + |> CmdLine.appendPrefix "--project" localFableDir + |> CmdLine.appendRaw "--" + + args + + ] + |> CmdLine.toString + + Command.RunAsync( + "dotnet", + args, + ?workingDirectory = workingDirectory, + ?noEcho = noEcho, + ?echoPrefix = echoPrefix + ) \ No newline at end of file diff --git a/build/Standalone.fs b/build/Standalone.fs new file mode 100644 index 0000000000..59d97e0894 --- /dev/null +++ b/build/Standalone.fs @@ -0,0 +1,78 @@ +module Build.Standalone + +open SimpleExec +open Build.Utils +open BlackFox.CommandLine +open System.IO + +let private projectDir = Path.Resolve("src", "fable-standalone", "src") + +let private buildDir = Path.Resolve("temp", "fable-standalone") + +let private distDir = Path.Resolve("src", "fable-standalone", "dist") + +let handle (args: string list) = + let minify = args |> List.contains "--no-minify" |> not + let isWatch = args |> List.contains "--watch" + + let rollupOutput = + match isWatch, minify with + | true, _ -> failwith "Not supported yet" + | false, true -> distDir "bundle.min.js" + | false, false -> buildDir "bundle.js" + + let rollupArgs = + CmdLine.empty + |> CmdLine.appendRaw (buildDir "bundle/Main.js") + |> CmdLine.appendPrefix "--output" rollupOutput + |> CmdLine.appendPrefix "--format" "umd" + |> CmdLine.appendPrefix "--name" "__FABLE_STANDALONE__" + |> CmdLine.toString + + let fableArgs = + CmdLine.concat [ + CmdLine.empty + |> CmdLine.appendPrefix "--outDir" (buildDir "bundle") + |> CmdLine.appendPrefix "--lang" "javascript" + + if isWatch then + CmdLine.empty + |> CmdLine.appendRaw "--watch" + |> CmdLine.appendPrefix "--run" "rollup" + |> CmdLine.appendRaw rollupArgs + |> CmdLine.appendRaw "--watch" + ] + + // Clean destination folders and ensure they exist + Directory.clean buildDir + Directory.clean distDir + + if isWatch then + failwith "Not supported yet" + else + // Build standalone bundle + Command.Fable(fableArgs, workingDirectory = projectDir) + + Command.Run("npx", $"rollup {rollupArgs}") + + if minify then + Command.Run( + "npx", + CmdLine.empty + |> CmdLine.appendRaw "terser" + |> CmdLine.appendPrefix "--output" (distDir "bundle.min.js") + |> CmdLine.appendRaw "--mangle" + |> CmdLine.appendRaw "--compress" + |> CmdLine.toString + ) + + // let printFileSize (fileName: string) = + // let fileInfo = FileInfo(distDir fileName) + + // let size = + // float (fileInfo.Length) / 1000.0 + + // printfn $"Bundle size: %.2f{size} KB" + + // printFileSize "bundle.min.js" + // printFileSize "working.min.js" diff --git a/build/Test/Dart.fs b/build/Test/Dart.fs new file mode 100644 index 0000000000..be0b4c0ca3 --- /dev/null +++ b/build/Test/Dart.fs @@ -0,0 +1,75 @@ +module Build.Test.Dart + +open Build.FableLibrary +open System.IO +open Build.Utils +open BlackFox.CommandLine +open SimpleExec +open Fake.IO + +let private buildDir = Path.Resolve("temp", "tests", "Dart") +let private testsFolder = Path.Resolve("tests", "Dart") +let private testsFsprojFolder = Path.Resolve("tests", "Dart", "src") + +let handle (args: string list) = + let skipFableLibrary = args |> List.contains "--skip-fable-library" + let isWatch = args |> List.contains "--watch" + let noDotnet = args |> List.contains "--no-dotnet" + + BuildFableLibraryDart().Run(skipFableLibrary) + + Directory.clean buildDir + + Directory.GetFiles(testsFolder, "pubspec.*") + |> Seq.iter (Shell.copyFile buildDir) + + Shell.copyFile buildDir (testsFolder "analysis_options.yaml") + + Directory.GetFiles(testsFolder, "*.dart") + |> Seq.iter (Shell.copyFile buildDir) + + let testCmd = $"dart test {buildDir}/main.dart" + + let fableArgs = + CmdLine.concat [ + CmdLine.empty + |> CmdLine.appendRaw testsFsprojFolder + |> CmdLine.appendPrefix "--outDir" (buildDir "src") + |> CmdLine.appendPrefix "--lang" "dart" + |> CmdLine.appendPrefix "--exclude" "Fable.Core" + |> CmdLine.appendRaw "--noCache" + + if isWatch then + CmdLine.empty + |> CmdLine.appendRaw "--watch" + |> CmdLine.appendRaw "--runWatch" + |> CmdLine.appendRaw testCmd + else + CmdLine.empty + |> CmdLine.appendRaw "--run" + |> CmdLine.appendRaw testCmd + ] + + if isWatch then + Async.Parallel [ + if not noDotnet then + Command.RunAsync( + "dotnet", + "watch test -c Release", + workingDirectory = testsFsprojFolder + ) + |> Async.AwaitTask + + Command.WatchFableAsync(fableArgs, workingDirectory = buildDir) + |> Async.AwaitTask + ] + |> Async.RunSynchronously + |> ignore + else + Command.Run( + "dotnet", + "test -c Release", + workingDirectory = testsFsprojFolder + ) + + Command.Fable(fableArgs, workingDirectory = buildDir) diff --git a/build/Test/Integration.fs b/build/Test/Integration.fs new file mode 100644 index 0000000000..75aaf90558 --- /dev/null +++ b/build/Test/Integration.fs @@ -0,0 +1,56 @@ +module Build.Test.Integration + +open Build.FableLibrary +open System.IO +open System +open BlackFox.CommandLine +open Build.Utils +open Build +open SimpleExec + +let private integrationProjectDir = + Path.Resolve("tests", "Integration", "Integration") + +let private compilerProjectDir = + Path.Resolve("tests", "Integration", "Compiler") + +let private testProjectConfig (projectDirName : string) (configuration : string option) = + let projectDir = Path.Resolve("tests", "Integration", "ProjectConfigs", projectDirName) + let destinationDir = Path.Resolve("temp", "tests", "Integration", "ProjectConfigs", projectDirName) + + Directory.clean destinationDir + + let fableArgs = + CmdLine.empty + |> CmdLine.appendRaw projectDir + |> CmdLine.appendPrefix "--outDir" destinationDir + |> CmdLine.appendPrefix "--exclude" "Fable.Core" + |> CmdLine.appendPrefixIfSome "--configuration" configuration + + Command.Fable(fableArgs) + + Command.Run( + "npx", + "npx mocha . --reporter dot -t 10000", + workingDirectory = destinationDir + ) + +let handle (args: string list) = + BuildFableLibraryJavaScript().Run() + + Command.Run( + "dotnet", + "run -c Release", + workingDirectory = integrationProjectDir + ) + + Command.Run( + "dotnet", + "run -c Release", + workingDirectory = compilerProjectDir + ) + + testProjectConfig "DebugWithExtraDefines" (Some "Debug") + testProjectConfig "CustomConfiguration" (Some "Test") + testProjectConfig "ReleaseNoExtraDefines" None + testProjectConfig "ConsoleApp" None diff --git a/build/Test/JavaScript.fs b/build/Test/JavaScript.fs new file mode 100644 index 0000000000..94c693bdf4 --- /dev/null +++ b/build/Test/JavaScript.fs @@ -0,0 +1,131 @@ +module Build.Test.JavaScript + +open Build.FableLibrary +open System.IO +open System +open BlackFox.CommandLine +open Build.Utils +open Build +open SimpleExec + +let private mainTestSourceDir = Path.Resolve("tests", "Js", "Main") + +let private mainTestProject = + Path.Resolve("tests", "Js", "Main", "Fable.Tests.fsproj") + +let private mochaCommand = "npx mocha . --reporter dot -t 10000" + +let private testReact (isWatch: bool) = + let workingDirectoy = Path.Resolve("tests", "React") + + Command.Run("npm", "install", workingDirectory = workingDirectoy) + + if isWatch then + Async.Parallel [ + Command.WatchFableAsync( + CmdLine.appendRaw "--noCache", + workingDirectory = workingDirectoy + ) + |> Async.AwaitTask + + Command.RunAsync( + "npx", + "jest --watch", + workingDirectory = workingDirectoy + ) + |> Async.AwaitTask + ] + |> Async.RunSynchronously + |> ignore + else + Command.Fable( + CmdLine.appendRaw "--noCache", + workingDirectory = workingDirectoy + ) + + Command.Run("npx", "jest", workingDirectory = workingDirectoy) + +let private handleMainTests (isWatch: bool) (noDotnet: bool) = + let folderName = "Main" + let sourceDir = Path.Resolve("tests", "Js", folderName) + + let destinationDir = + Path.Resolve("temp", "tests", "JavaScript", folderName) + + Directory.clean destinationDir + + let fableArgs = + CmdLine.concat [ + CmdLine.empty + |> CmdLine.appendRaw sourceDir + |> CmdLine.appendPrefix "--outDir" destinationDir + |> CmdLine.appendPrefix "--lang" "javascript" + |> CmdLine.appendPrefix "--exclude" "Fable.Core" + |> CmdLine.appendRaw "--noCache" + + if isWatch then + CmdLine.empty + |> CmdLine.appendRaw "--watch" + |> CmdLine.appendRaw "--runWatch" + |> CmdLine.appendRaw mochaCommand + else + CmdLine.empty + |> CmdLine.appendRaw "--run" + |> CmdLine.appendRaw mochaCommand + ] + + if isWatch then + // In watch mode, we only test the Main tests to not pollute the logs too much + Async.Parallel [ + if not noDotnet then + Command.RunAsync( + "dotnet", + "watch run -c Release", + workingDirectory = Path.Combine("tests", "Js", "Main") + ) + |> Async.AwaitTask + + Command.WatchFableAsync( + fableArgs, + workingDirectory = destinationDir + ) + |> Async.AwaitTask + ] + |> Async.RunSynchronously + |> ignore + else + Command.Run( + "dotnet", + "run -c Release", + workingDirectory = Path.Combine("tests", "Js", "Main") + ) + + // Test the Main tests against JavaScript + Command.Fable(fableArgs, workingDirectory = destinationDir) + + testReact false + + let isCI = Environment.GetEnvironmentVariable("CI") |> Option.ofObj + + if isCI.IsSome then + Standalone.handleStandaloneFast () + +let handle (args: string list) = + let isReactOnly = args |> List.contains "--react-only" + let isStandaloneOnly = args |> List.contains "--standalone-only" + let skipFableLibrary = args |> List.contains "--skip-fable-library" + let isWatch = args |> List.contains "--watch" + let noDotnet = args |> List.contains "--no-dotnet" + + if isStandaloneOnly && isReactOnly then + failwith + "Cannot use --react-only and --standalone-only at the same time" + + BuildFableLibraryJavaScript().Run(skipFableLibrary) + + if isReactOnly then + testReact isWatch + else if isStandaloneOnly then + Standalone.handleStandaloneFast () + else + handleMainTests isWatch noDotnet diff --git a/build/Test/Python.fs b/build/Test/Python.fs new file mode 100644 index 0000000000..f962293af0 --- /dev/null +++ b/build/Test/Python.fs @@ -0,0 +1,64 @@ +module Build.Test.Python + +open Build.FableLibrary +open System.IO +open Build.Utils +open BlackFox.CommandLine +open SimpleExec + +let private buildDir = Path.Resolve("temp", "tests", "Python") +let private sourceDir = Path.Resolve("tests", "Python") + +let handle (args: string list) = + let skipFableLibrary = args |> List.contains "--skip-fable-library" + let isWatch = args |> List.contains "--watch" + let noDotnet = args |> List.contains "--no-dotnet" + + BuildFableLibraryPython().Run(skipFableLibrary) + + Directory.clean buildDir + + Command.Run("poetry", "install") + + let fableArgs = + CmdLine.concat [ + CmdLine.empty + |> CmdLine.appendRaw sourceDir + |> CmdLine.appendPrefix "--outDir" buildDir + |> CmdLine.appendPrefix "--lang" "python" + |> CmdLine.appendPrefix "--exclude" "Fable.Core" + |> CmdLine.appendRaw "--noCache" + + if isWatch then + CmdLine.empty + |> CmdLine.appendRaw "--watch" + |> CmdLine.appendRaw "--runWatch" + |> CmdLine.appendRaw "poetry run pytest -x" + else + CmdLine.empty + |> CmdLine.appendRaw "--run" + |> CmdLine.appendRaw "poetry run pytest -x" + ] + + if isWatch then + Async.Parallel [ + if not noDotnet then + Command.RunAsync( + "dotnet", + "watch test -c Release", + workingDirectory = sourceDir + ) + |> Async.AwaitTask + + Command.WatchFableAsync(fableArgs, workingDirectory = buildDir) + |> Async.AwaitTask + ] + |> Async.RunSynchronously + |> ignore + else + + // Test against .NET + Command.Run("dotnet", "test -c Release", workingDirectory = sourceDir) + + // Test against Python + Command.Fable(fableArgs, workingDirectory = buildDir) diff --git a/build/Test/Rust.fs b/build/Test/Rust.fs new file mode 100644 index 0000000000..e691a5aefa --- /dev/null +++ b/build/Test/Rust.fs @@ -0,0 +1,135 @@ +module Build.Test.Rust + +open Build.FableLibrary +open System.IO +open Build.Utils +open BlackFox.CommandLine +open Fake.IO +open Fake.IO.Globbing +open Fake.IO.Globbing.Operators +open SimpleExec + +let private testAst isWatch = + + let projectDir = + Path.Resolve("src", "Fable.Transforms", "Rust", "AST", "Tests") + + if isWatch then + Command.RunAsync( + "dotnet", + "watch test -c Release", + workingDirectory = projectDir + ) + |> Async.AwaitTask + |> ignore + else + Command.Run("dotnet", "test -c Release", workingDirectory = projectDir) + +let mainTestsDestinationDir = Path.Resolve("temp", "tests", "Rust") +let mainTestsProjectDir = Path.Resolve("tests", "Rust") + +let handle (args: string list) = + let skipFableLibrary = args |> List.contains "--skip-fable-library" + let isWatch = args |> List.contains "--watch" + let astOnly = args |> List.contains "--ast-only" + let noStd = args |> List.contains "--no_std" + let threaded = args |> List.contains "--threaded" + let noDotnet = args |> List.contains "--no-dotnet" + + if noStd && threaded then + failwith "Cannot use --no-std and --threaded at the same time" + + BuildFableLibraryRust().Run(skipFableLibrary) + + if astOnly then + testAst isWatch + else + // limited cleanup to reduce IO churn, speed up rebuilds, + // and save the ssd (target folder can get huge) + Directory.clean (mainTestsDestinationDir "tests" "src") + Directory.clean (mainTestsDestinationDir "tests" "tests") + Directory.clean (mainTestsDestinationDir "tests" ".fable") + + // copy rust only tests files (these must be present when running dotnet test as import expr tests for file presence) + Directory.CreateDirectory(mainTestsDestinationDir "tests" "src") + |> ignore + + Shell.copyFile + mainTestsDestinationDir + (mainTestsProjectDir "Cargo.toml") + + !!(mainTestsProjectDir "tests" "src" "*.rs") + |> Seq.iter (fun file -> + let destination = mainTestsDestinationDir "tests" "src" + + Shell.copyFile destination file + ) + + let cargoTestArgs = + if noStd then + "cargo test --features no_std" + elif threaded then + "cargo test --features threaded" + else + "cargo test" + + let fableArgs = + CmdLine.concat [ + CmdLine.empty + |> CmdLine.appendRaw mainTestsProjectDir + |> CmdLine.appendPrefix "--outDir" mainTestsDestinationDir + |> CmdLine.appendPrefix "--lang" "rust" + |> CmdLine.appendPrefix "--exclude" "Fable.Core" + |> CmdLine.appendRaw "--noCache" + |> CmdLine.appendPrefixIf noStd "--define" "NO_STD_NO_EXCEPTIONS" + + if isWatch then + CmdLine.empty + |> CmdLine.appendRaw "--watch" + |> CmdLine.appendRaw "--runWatch" + |> CmdLine.appendRaw cargoTestArgs + else + CmdLine.empty + |> CmdLine.appendRaw "--run" + |> CmdLine.appendRaw cargoTestArgs + ] + + if isWatch then + Async.Parallel [ + if not noDotnet then + Command.RunAsync( + "dotnet", + "watch test -c Release", + workingDirectory = mainTestsProjectDir + ) + |> Async.AwaitTask + + Command.WatchFableAsync( + fableArgs, workingDirectory = mainTestsDestinationDir + ) + |> Async.AwaitTask + ] + |> Async.RunSynchronously + |> ignore + else + Command.Run( + "dotnet", + "test -c Release", + workingDirectory = mainTestsProjectDir + ) + + Command.Fable(fableArgs, workingDirectory = mainTestsDestinationDir) + + // Old build system was running cargo fmt and cargo build + // Is it still needed? + // Command.Run( + // "cargo", + // "fmt", + // workingDirectory = mainTestsDestinationDir + // ) + + // Command.Run( + // "cargo", + // "temp", + // workingDirectory = mainTestsDestinationDir + // ) diff --git a/build/Test/Standalone.fs b/build/Test/Standalone.fs new file mode 100644 index 0000000000..fb355da7d6 --- /dev/null +++ b/build/Test/Standalone.fs @@ -0,0 +1,50 @@ +module Build.Test.Standalone + +open Build.FableLibrary +open System.IO +open System +open BlackFox.CommandLine +open Build.Utils +open Build +open SimpleExec + +let private mainTestProject = + Path.Resolve("tests", "Js", "Main", "Fable.Tests.fsproj") + +let private mochaCommand = "npx mocha . --reporter dot -t 10000" + +let handleStandaloneFast () = + let fableCompilerJsDir = Path.Resolve("src", "fable-compiler-js", "src") + let fableCompilerJsEntry = Path.Combine(fableCompilerJsDir, "app.fs.js") + let standaloneBuildDest = Path.Resolve("temp", "tests", "Standalone") + + Command.Fable( + CmdLine.appendRaw "--noCache", + workingDirectory = Path.Resolve("src", "fable-standalone", "src") + ) + + Command.Fable( + CmdLine.appendPrefix "--exclude" "Fable.Core" + >> CmdLine.appendPrefix "--define" "LOCAL_TEST" + >> CmdLine.appendRaw "--noCache", + workingDirectory = fableCompilerJsDir + ) + + // Make sure the projects are restored + // Otherwise, on a first VM dependencies can be missing + Command.Run("dotnet", $"restore {mainTestProject}") + + Command.Run( + "node", + CmdLine.empty + |> CmdLine.appendRaw fableCompilerJsEntry + |> CmdLine.appendRaw mainTestProject + |> CmdLine.appendRaw standaloneBuildDest + |> CmdLine.toString, + workingDirectory = fableCompilerJsDir + ) + + Command.Run("npx", mochaCommand, workingDirectory = standaloneBuildDest) + +let handle (args: string list) = + handleStandaloneFast () diff --git a/build/Test/TypeScript.fs b/build/Test/TypeScript.fs new file mode 100644 index 0000000000..15f9b7bc7a --- /dev/null +++ b/build/Test/TypeScript.fs @@ -0,0 +1,84 @@ +module Build.Test.TypeScript + +open Build.FableLibrary +open System.IO +open Build.Utils +open BlackFox.CommandLine +open SimpleExec +open Fake.IO + +let private projectDir = Path.Resolve("tests", "TypeScript") +let private fableDest = Path.Resolve("temp", "tests", "TypeScript") +let private tscDest = Path.Resolve("temp", "tests", "TypeScriptCompiled") + +let handle (args: string list) = + let skipFableLibrary = args |> List.contains "--skip-fable-library" + let isWatch = args |> List.contains "--watch" + let noDotnet = args |> List.contains "--no-dotnet" + + BuildFableLibraryTypeScript().Run(skipFableLibrary) + + Directory.clean fableDest + Directory.clean tscDest + + Shell.copyFile fableDest (projectDir "tsconfig.json") + + let tscArgs = $"tsc --outDir {tscDest}" + let mochaArgs = "mocha temp/tests/TypeScript --reporter dot -t 10000" + + let fableArgs = + CmdLine.concat [ + CmdLine.empty + |> CmdLine.appendRaw projectDir + |> CmdLine.appendPrefix "--outDir" fableDest + |> CmdLine.appendPrefix "--lang" "typescript" + |> CmdLine.appendPrefix "--exclude" "Fable.Core" + |> CmdLine.appendRaw "--noCache" + + // Let Fable handle the TypeScript invocation + if isWatch then + CmdLine.empty + |> CmdLine.appendRaw "--watch" + |> CmdLine.appendRaw "--runWatch" + |> CmdLine.appendRaw $"npx {tscArgs}" + ] + + let nodemonArgs = + CmdLine.empty + |> CmdLine.appendRaw "nodemon" + |> CmdLine.appendPrefix "-e" "js" + |> CmdLine.appendPrefix "--watch" tscDest + // Avoid polluting the logs when a lot of files change at once + |> CmdLine.appendPrefix "--delay" "1s" + |> CmdLine.appendRaw "--exec" + |> CmdLine.appendRaw "\"" + |> CmdLine.appendRaw mochaArgs + |> CmdLine.appendRaw "\"" + |> CmdLine.toString + + if isWatch then + Async.Parallel [ + if not noDotnet then + Command.RunAsync( + "dotnet", + "watch test -c Release", + workingDirectory = projectDir + ) + |> Async.AwaitTask + + Command.WatchFableAsync(fableArgs, workingDirectory = fableDest) + |> Async.AwaitTask + + Command.RunAsync("npx", nodemonArgs, workingDirectory = tscDest) + |> Async.AwaitTask + ] + |> Async.RunSynchronously + |> ignore + else + Command.Run("dotnet", "test -c Release", workingDirectory = projectDir) + + Command.Fable(fableArgs, workingDirectory = fableDest) + + Command.Run("npx", tscArgs, workingDirectory = fableDest) + + Command.Run("npx", mochaArgs, workingDirectory = tscDest) diff --git a/build/Utils.fs b/build/Utils.fs new file mode 100644 index 0000000000..d6892b5404 --- /dev/null +++ b/build/Utils.fs @@ -0,0 +1,128 @@ +namespace Build.Utils + +open BlackFox.CommandLine +open System +open System.IO + +[] +module Operators = + + let () (p1: string) (p2: string) : string = Path.Combine(p1, p2) + +type Path = + + /// + /// Resolve a path relative to the repository root + /// + static member Resolve([] segments: string array) : string = + let paths = Array.concat [ [| __SOURCE_DIRECTORY__; ".." |]; segments ] + + // Use GetFullPath to clean the path + Path.GetFullPath(Path.Combine(paths)) + +type Cmd = + + /// Build a command line to invoke the local Fable build + /// + /// + /// If true then dotnet watch will be use + /// If false then dotnet run will be use + /// + /// + /// Returns the command line with the arguments to invoke Fable + /// + static member fable + ( + ?argsBuilder: CmdLine -> CmdLine, + ?watchMode: bool + ) : CmdLine = + let argsBuilder = defaultArg argsBuilder id + // Use absolute path so we can invoke the command from anywhere + let localFableDir = + __SOURCE_DIRECTORY__ ".." "src" "Fable.Cli" + + let watchMode = defaultArg watchMode false + + if watchMode then + CmdLine.empty + |> CmdLine.appendRaw "dotnet" + |> CmdLine.appendRaw "watch" + |> CmdLine.appendPrefix "--project" localFableDir + |> CmdLine.appendRaw "run" + // Without the release mode, Fable stack overflow when compiling the tests + |> CmdLine.appendPrefix "-c" "Release" + |> CmdLine.appendRaw "--" + |> argsBuilder + else + CmdLine.empty + |> CmdLine.appendRaw "dotnet" + |> CmdLine.appendRaw "run" + |> CmdLine.appendPrefix "-c" "Release" + |> CmdLine.appendPrefix "--project" localFableDir + |> CmdLine.appendRaw "--" + |> argsBuilder + + static member node(?argsBuilder: CmdLine -> CmdLine) : CmdLine = + let argsBuilder = defaultArg argsBuilder id + + CmdLine.empty |> CmdLine.appendRaw "node" |> argsBuilder + + static member tsc(?argsBuilder: CmdLine -> CmdLine) : CmdLine = + let argsBuilder = defaultArg argsBuilder id + + CmdLine.empty + |> CmdLine.appendRaw "npx" + |> CmdLine.appendRaw "tsc" + |> argsBuilder + + static member mocha(?argsBuilder: CmdLine -> CmdLine) : CmdLine = + let argsBuilder = defaultArg argsBuilder id + + CmdLine.empty + |> CmdLine.appendRaw "npx" + |> CmdLine.appendRaw "mocha" + |> argsBuilder + + static member nodemon(?argsBuilder: CmdLine -> CmdLine) : CmdLine = + let argsBuilder = defaultArg argsBuilder id + + CmdLine.empty + |> CmdLine.appendRaw "npx" + |> CmdLine.appendRaw "nodemon" + |> argsBuilder + + static member dotnet(?argsBuilder: CmdLine -> CmdLine) : CmdLine = + let argsBuilder = defaultArg argsBuilder id + + CmdLine.empty |> CmdLine.appendRaw "dotnet" |> argsBuilder + + static member jest(?argsBuilder: CmdLine -> CmdLine) : CmdLine = + let argsBuilder = defaultArg argsBuilder id + + CmdLine.empty + |> CmdLine.appendRaw "npx" + |> CmdLine.appendRaw "jest" + |> argsBuilder + + static member npx(?argsBuilder: CmdLine -> CmdLine) : CmdLine = + let argsBuilder = defaultArg argsBuilder id + + CmdLine.empty |> CmdLine.appendRaw "npx" |> argsBuilder + +module Directory = + + /// Delete the directory if exist and ensure it exists + /// Name of the directory + /// + let clean (dir: string) : unit = + if Directory.Exists(dir) then + Directory.Delete(dir, true) + + Directory.CreateDirectory(dir) |> ignore + +module Environment = + + open System.Runtime + + let isWindows () = + InteropServices.RuntimeInformation.IsOSPlatform(InteropServices.OSPlatform.Windows) \ No newline at end of file diff --git a/build/Utils/Changelog.fs b/build/Utils/Changelog.fs new file mode 100644 index 0000000000..98cd5409d5 --- /dev/null +++ b/build/Utils/Changelog.fs @@ -0,0 +1,23 @@ +module Changelog + +open System.IO + +let getLastVersion (changelogPath: string) = + let content = File.ReadAllText changelogPath + + match ChangelogParser.parse content with + | Ok changelog -> + changelog.Versions + |> List.tryFind (fun v -> v.Title <> "Unreleased") + |> Option.defaultWith (fun () -> + failwithf + $"""Failed to find version in changelog: +File: %s{changelogPath}""" + ) + + | Error msg -> + failwithf + $"""Failed to parse changelog: +File: %s{changelogPath} +Error: +%s{msg}""" diff --git a/build/Utils/ChangelogParser.fs b/build/Utils/ChangelogParser.fs new file mode 100644 index 0000000000..376813e813 --- /dev/null +++ b/build/Utils/ChangelogParser.fs @@ -0,0 +1,441 @@ +[] +module ChangelogParser + +open Fable.Core +open System +open System.Text.RegularExpressions +open Semver + +[] +module Types = + + type CategoryBody = + | ListItem of string + | Text of string + + type OtherItem = { + ListItem: string + TextBody: string option + } + + type Categories = { + Added: CategoryBody list + Changed: CategoryBody list + Deprecated: CategoryBody list + Removed: CategoryBody list + Improved: CategoryBody list + Fixed: CategoryBody list + Security: CategoryBody list + Custom: Map + } + + type Version = { + Version: SemVersion + Title: string + Date: DateTime option + Categories: Categories + OtherItems: OtherItem list + } + + type Changelog = { + Title: string + Description: string + Versions: Version list + } with + + static member Empty = { + Title = "" + Description = "" + Versions = [] + } + + [] + type Symbols = + | Title of title: string + | RawText of body: string + | SectionHeader of + title: string * + version: string option * + date: string option + | SubSection of tag: string + | ListItem of content: string + + +[] +module Lexer = + + let private (|Match|_|) pattern input = + let m = Regex.Match(input, pattern) + if m.Success then Some m else None + + let private (|Title|_|) (input: string) = + match input with + | Match "^# ?[^#]" _ -> input.Substring(1).Trim() |> Some + | _ -> None + + let private (|Semver|_|) (input: string) = + match input with + | Match "\\[?v?([\\w\\d.-]+\\.[\\w\\d.-]+[a-zA-Z0-9])\\]?" m -> + Some m.Groups.[1].Value + | _ -> None + + let private (|Date|_|) (input: string) = + match input with + | Match "(\\d{4}-\\d{2}-\\d{2})" m -> Some m.Groups.[0].Value + | _ -> None + + let private (|Version|_|) (input: string) = + match input with + | Match "^##? ?[^#]" _ -> + let version = + match input with + | Semver version -> Some version + | _ -> None + + let date = + match input with + | Date date -> Some date + | _ -> None + + let title = input.Substring(2).Trim() + + Some(title, version, date) + + | _ -> None + + let private (|SubSection|_|) (input: string) = + match input with + | Match "^###" _ -> input.Substring(3).Trim() |> Some + | _ -> None + + let private (|ListItem|_|) (input: string) = + match input with + | Match "^[*-]" _ -> input.Substring(1).Trim() |> Some + | _ -> None + + let toSymbols (lines: string list) = + lines + |> List.map ( + function + | Title title -> Symbols.Title title + | Version(title, version, date) -> + Symbols.SectionHeader(title, version, date) + | SubSection tag -> Symbols.SubSection tag + | ListItem content -> Symbols.ListItem content + | rawText -> Symbols.RawText(rawText.TrimEnd()) + ) + +[] +module Transform = + + let rec private parseCategoryBody + (symbols: Symbols list) + (sectionContent: CategoryBody list) + = + match symbols with + | Symbols.ListItem item :: tail -> + + parseCategoryBody + tail + (sectionContent @ [ CategoryBody.ListItem item ]) + // If this is the beginning of a text block + | Symbols.RawText _ :: _ -> + // Capture all the lines of the text block + let textLines = + symbols + |> List.takeWhile ( + function + | Symbols.RawText _ -> true + | _ -> false + ) + + // Regroup everything into a single string + let content = + textLines + |> List.map ( + function + | Symbols.RawText text -> text + | _ -> + failwith "Should not happen the list has been filtered" + ) + // Skip empty lines at the beginning + |> List.skipWhile String.IsNullOrEmpty + // Skip empty lines at the end + |> List.rev + |> List.skipWhile String.IsNullOrEmpty + |> List.rev + // Join the lines + |> String.concat "\n" + + // Remove already handle symbols + let rest = symbols |> List.skip textLines.Length + + // If details is an empty line don't store it + if String.IsNullOrEmpty content then + parseCategoryBody rest sectionContent + else + parseCategoryBody + rest + (sectionContent @ [ CategoryBody.Text content ]) + + // End of the Section, return the built content + | _ -> symbols, sectionContent + + let rec private tryEatRawText (symbols: Symbols list) = + match symbols with + // If this is the beginning of a text block + | Symbols.RawText _ :: _ -> + // Capture all the lines of the text block + let textLines = + symbols + |> List.takeWhile ( + function + | Symbols.RawText _ -> true + | _ -> false + ) + + // Regroup everything into a single string + let content = + textLines + |> List.map ( + function + | Symbols.RawText text -> text + | _ -> + failwith "Should not happen the list has been filtered" + ) + // Skip empty lines at the beginning + |> List.skipWhile String.IsNullOrEmpty + // Skip empty lines at the end + |> List.rev + |> List.skipWhile String.IsNullOrEmpty + |> List.rev + // Join the lines + |> String.concat "\n" + + // Remove already handle symbols + let rest = symbols |> List.skip textLines.Length + + rest, Some content + // End of the Section, return the built content + | _ -> symbols, None + + let rec private parse (symbols: Symbols list) (changelog: Changelog) = + match symbols with + | Symbols.Title title :: tail -> + if String.IsNullOrEmpty changelog.Title then + { changelog with Title = title } + else + changelog + |> parse tail + + | Symbols.SectionHeader(title, version, date) :: tail -> + let version = { + Version = + match version with + | Some version -> + SemVersion.Parse(version, SemVersionStyles.Strict) + | None -> + // If no version is provided, use a dummy version + // This happens when handling the unreleased section + SemVersion.Parse( + "0.0.0-Unreleased", + SemVersionStyles.Strict + ) + Title = title + Date = date |> Option.map DateTime.Parse + Categories = { + Added = [] + Changed = [] + Deprecated = [] + Removed = [] + Improved = [] + Fixed = [] + Security = [] + Custom = Map.empty + } + OtherItems = [] + } + + parse tail { + changelog with + Versions = version :: changelog.Versions + } + + | Symbols.SubSection tag :: tail -> + let (unparsedSymbols, categoryBody) = parseCategoryBody tail [] + + match changelog.Versions with + | currentVersion :: otherVersions -> + let updatedCategories = + match tag.ToLower() with + | "added" -> { + currentVersion.Categories with + Added = + currentVersion.Categories.Added @ categoryBody + } + | "changed" -> { + currentVersion.Categories with + Changed = + currentVersion.Categories.Changed @ categoryBody + } + | "deprecated" -> { + currentVersion.Categories with + Deprecated = + currentVersion.Categories.Deprecated + @ categoryBody + } + | "removed" -> { + currentVersion.Categories with + Removed = + currentVersion.Categories.Removed @ categoryBody + } + | "improved" -> { + currentVersion.Categories with + Improved = + currentVersion.Categories.Improved + @ categoryBody + } + | "fixed" -> { + currentVersion.Categories with + Fixed = + currentVersion.Categories.Fixed @ categoryBody + } + | "security" -> { + currentVersion.Categories with + Security = + currentVersion.Categories.Security + @ categoryBody + } + | unknown -> { + currentVersion.Categories with + Custom = + currentVersion.Categories.Custom.Add( + unknown, + categoryBody + ) + } + + let versions = + { + currentVersion with + Categories = updatedCategories + } + :: otherVersions + + parse unparsedSymbols { changelog with Versions = versions } + | _ -> Error "A category should always be under a version" + + | Symbols.RawText _ :: _ -> + // Capture all the lines of the text block + let textLines = + symbols + |> List.takeWhile ( + function + | Symbols.RawText _ -> true + | _ -> false + ) + + // Regroup everything into a single string + let content = + textLines + |> List.map ( + function + | Symbols.RawText text -> text + | _ -> + failwith "Should not happen the list has been filtered" + ) + |> String.concat "\n" + + // Remove already handle symbols + let rest = symbols |> List.skip textLines.Length + + parse rest { changelog with Description = content } + + | Symbols.ListItem text :: tail -> + match changelog.Versions with + | currentVersion :: otherVersions -> + let (unparsedSymbols, textBody) = tryEatRawText tail + + let otherItemItem = { ListItem = text; TextBody = textBody } + + let versions = + { + currentVersion with + OtherItems = + currentVersion.OtherItems @ [ otherItemItem ] + } + :: otherVersions + + parse unparsedSymbols { changelog with Versions = versions } + | _ -> + + sprintf + "A list item should always be under version. The following list item made the parser failed:\n\n%s\n" + text + |> Error + + | [] -> + Ok { + changelog with + Versions = changelog.Versions |> List.rev + } + + let fromSymbols (symbols: Symbols list) = parse symbols Changelog.Empty + +let parse (changelogContent: string) = + changelogContent.Split([| '\r'; '\n' |]) + |> Array.toList + |> Lexer.toSymbols + |> Transform.fromSymbols + +module Version = + + let bodyAsMarkdown (version: Types.Version) = + let renderCategoryBody + (categoryLabel: string) + (items: CategoryBody list) + = + if items.IsEmpty then + "" + else + let categoryBody = + items + |> List.map ( + function + | ListItem item -> sprintf "- %s" item + | Text text -> text + ) + |> String.concat "\n" + + $"## {categoryLabel}\n\n{categoryBody}\n\n" + + let mutable body = "" + + body <- body + renderCategoryBody "Added" version.Categories.Added + body <- body + renderCategoryBody "Changed" version.Categories.Changed + + body <- + body + renderCategoryBody "Deprecated" version.Categories.Deprecated + + body <- body + renderCategoryBody "Removed" version.Categories.Removed + body <- body + renderCategoryBody "Improved" version.Categories.Improved + body <- body + renderCategoryBody "Fixed" version.Categories.Fixed + body <- body + renderCategoryBody "Security" version.Categories.Security + + for unkownCategory in version.Categories.Custom.Keys do + let items = version.Categories.Custom.[unkownCategory] + body <- body + renderCategoryBody unkownCategory items + + if not version.OtherItems.IsEmpty then + body <- body + "\n" + + for otherItems in version.OtherItems do + body <- body + sprintf "- %s" otherItems.ListItem + + match otherItems.TextBody with + | Some textBody -> body <- body + sprintf "\n%s" textBody + | None -> () + + body <- body + "\n" + + body diff --git a/build/Utils/Fsproj.fs b/build/Utils/Fsproj.fs new file mode 100644 index 0000000000..df2cafe7d9 --- /dev/null +++ b/build/Utils/Fsproj.fs @@ -0,0 +1,32 @@ +module Fsproj + +open System.IO +open SimpleExec +open System.Text.RegularExpressions + +module Regex = + + [] + let VERSION = "(?'version'.*?)" + +let tryGetVersion (fsprojContent: string) = + let m = Regex.Match(fsprojContent, Regex.VERSION) + if m.Success then + Some m.Groups.["version"].Value + else + None + +let needPublishing (fsprojContent: string) (versionToCheck: string) = + match tryGetVersion fsprojContent with + | Some currentVersion -> + currentVersion <> versionToCheck + | None -> failwith "Could not find ... in fsproj file" + +let replaceVersion (fsprojContent: string) (version: string) = + Regex.Replace( + fsprojContent, + Regex.VERSION, + (fun (m: Match) -> + $"{version}" + ) + ) diff --git a/build/Utils/Npm.fs b/build/Utils/Npm.fs new file mode 100644 index 0000000000..340303fcb5 --- /dev/null +++ b/build/Utils/Npm.fs @@ -0,0 +1,52 @@ +namespace Build.Utils + +open Thoth.Json.Net +open System.IO +open SimpleExec +open System.Text.RegularExpressions + +module Regex = + + [] + let VERSION = "\"version\":\s*\"(?'version'.*)\"" + +module Npm = + + let getVersion (packageJsonContent: string) = + let versionDecoder = Decode.field "version" Decode.string + + match Decode.fromString versionDecoder packageJsonContent with + | Ok version -> version + | Error msg -> + failwithf + $"""Failed to find version in package.json + +Error: +%s{msg}""" + + let getVersionFromProjectDir (projectDir: string) = + let packageJsonPath = Path.Combine(projectDir, "package.json") + let packageJsonContent = File.ReadAllText packageJsonPath + + getVersion packageJsonContent + + let tryGetVersion (packageJsonContent: string) (version: string) = + let m = Regex.Match(packageJsonContent, Regex.VERSION) + if m.Success then Some m.Groups.["version"].Value else None + + let needPublishing (packageJsonContent: string) (versionToCheck: string) = + let version = getVersion packageJsonContent + + version <> versionToCheck + + let publish (projectDir: string) = + Command.Run("npm", "publish", workingDirectory = projectDir) + + let replaceVersion (packageJsonContent: string) (version: string) = + Regex.Replace( + packageJsonContent, + Regex.VERSION, + (fun (m: Match) -> + $"\"version\": \"{version}\"" + ) + ) diff --git a/build/Utils/Nuget.fs b/build/Utils/Nuget.fs new file mode 100644 index 0000000000..153c799285 --- /dev/null +++ b/build/Utils/Nuget.fs @@ -0,0 +1,44 @@ +namespace Build.Utils + +open SimpleExec +open System.Text.RegularExpressions + +module Dotnet = + + type Nuget = + + static member push(projectDir: string, nugetKey : string) = + Command.Run( + "dotnet", + "nuget push *.nupkg -s https://api.nuget.org/v3/index.json", + workingDirectory = projectDir + ) + + static member push + ( + projectDir: string, + nugetKey : string, + preBuildAction: unit -> unit + ) = + preBuildAction () + Nuget.push(projectDir, nugetKey) + + let pack (projectDir: string) = + let struct (standardOutput, _) = + Command.ReadAsync( + "dotnet", + "pack -c Release", + workingDirectory = projectDir + ) + |> Async.AwaitTask + |> Async.RunSynchronously + + let m = Regex.Match(standardOutput, "'(?'nupkgPath'.*\.nupkg)'") + + if m.Success then + m.Groups.["nupkgPath"].Value + else + failwithf + $"""Failed to find nupkg path in output: +Output: +{standardOutput}""" diff --git a/build/Workspace.fs b/build/Workspace.fs new file mode 100644 index 0000000000..4297e974c4 --- /dev/null +++ b/build/Workspace.fs @@ -0,0 +1,26 @@ +module Build.Workspace + +open Build.Utils +open System.IO + +let root = Path.Resolve() + +module ProjectDir = + + let fableAst = Path.Resolve("src", "Fable.AST") + let fableCore = Path.Resolve("src", "Fable.Core") + let fableCli = Path.Resolve("src", "Fable.Cli") + let fablePublishUtils = Path.Resolve("src", "Fable.PublishUtils") + let temp_fable_library = Path.Resolve("temp", "fable-library") + let fable_library = Path.Resolve("src", "fable-library") + let fable_metadata = Path.Resolve("src", "fable-metadata") + let fable_standalone = Path.Resolve("src", "fable-standalone") + let fable_compiler_js = Path.Resolve("src", "fable-compiler-js") + +module Fsproj = + + let fableCli = Path.Combine(ProjectDir.fableCli, "Fable.Cli.fsproj") + +module Changelog = + + let fableCLi = Path.Combine(ProjectDir.fableCli, "CHANGELOG.md") diff --git a/poetry.lock b/poetry.lock index 5f97e88755..02d778fcae 100644 --- a/poetry.lock +++ b/poetry.lock @@ -77,7 +77,7 @@ python-dateutil = "^2.8.2" [package.source] type = "directory" -url = "build/fable-library-py" +url = "temp/fable-library-py" [[package]] name = "iniconfig" diff --git a/pyproject.toml b/pyproject.toml index a1fc56df5a..9d76d62334 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ fable-library = "*" python-dateutil = "^2.8.2" [tool.poetry.dev-dependencies] -fable-library = {path = "./build/fable-library-py", develop = true} +fable-library = {path = "./temp/fable-library-py", develop = true} pytest = "^6.2.4" black = {version = "^22.6.0", allow-prereleases = true} isort = "^5.10.1" diff --git a/src/Directory.Build.props b/src/Directory.Build.props index aeaa11e744..dcef6ff4fb 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -11,10 +11,10 @@ - + snupkg @@ -24,4 +24,4 @@ - \ No newline at end of file + diff --git a/src/Fable.AST/RELEASE_NOTES.md b/src/Fable.AST/CHANGELOG.md similarity index 55% rename from src/Fable.AST/RELEASE_NOTES.md rename to src/Fable.AST/CHANGELOG.md index 2d1eedadf4..b42d46774d 100644 --- a/src/Fable.AST/RELEASE_NOTES.md +++ b/src/Fable.AST/CHANGELOG.md @@ -1,60 +1,68 @@ -### 4.2.1 +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased + +## 4.2.1 * Get sources from PluginHelper -### 4.2.0 +## 4.2.0 * Add Entity.DeclaringEntity -### 4.1.0 +## 4.1.0 * Add IsInternal/IsPrivate to Entity and MemberFunctionOrValue -### 4.0.0 +## 4.0.0 * Stable AST for Fable 4 -### 4.0.0-snake-island-alpha-001 +## 4.0.0-snake-island-alpha-001 * Snake Island alpha release -### 3.1.1 +## 3.1.1 * Publish with icon and symbols @cartermp -### 3.1.0 +## 3.1.0 * Add GetOutputPath to PluginHelper -### 3.0.0 +## 3.0.0 * Official release -### 3.0.0-nagareyama-rc-001 +## 3.0.0-nagareyama-rc-001 * Add `Expr.LetRec` * Add `ScanForPluginsAttribute` * Add `AST.Fable.File` argument to `MemberDeclarationPlugin.Transform` -### 3.0.0-nagareyama-beta-002 +## 3.0.0-nagareyama-beta-002 * Add `MemberDecl.ExportDefault` -### 3.0.0-nagareyama-beta-001 +## 3.0.0-nagareyama-beta-001 * Beta release * Use string literals in ImportInfo -### 3.0.0-nagareyama-alpha-003 +## 3.0.0-nagareyama-alpha-003 * Add optional string tag to TypeCast * Add methods from Compiler to PluginHelper * Add CallMemberInfo to Call expr -### 3.0.0-nagareyama-alpha-002 +## 3.0.0-nagareyama-alpha-002 * Merge Member/Call plugins -### 3.0.0-nagareyama-alpha-001 +## 3.0.0-nagareyama-alpha-001 * First alpha release diff --git a/src/Fable.AST/Fable.AST.fsproj b/src/Fable.AST/Fable.AST.fsproj index 69455c7010..227814fea9 100644 --- a/src/Fable.AST/Fable.AST.fsproj +++ b/src/Fable.AST/Fable.AST.fsproj @@ -6,7 +6,6 @@ netstandard2.0 true 4.2.1 - 4.2.1 diff --git a/src/Fable.Cli/RELEASE_NOTES.md b/src/Fable.Cli/CHANGELOG.md similarity index 87% rename from src/Fable.Cli/RELEASE_NOTES.md rename to src/Fable.Cli/CHANGELOG.md index 8d9560f3af..a0d8a215d0 100644 --- a/src/Fable.Cli/RELEASE_NOTES.md +++ b/src/Fable.Cli/CHANGELOG.md @@ -1,4 +1,10 @@ -### Unreleased +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased * Fix #3480: Function decorated with `[]` without arguments provided should take an empty object * Fix #3494: Calling an attached parametrized getter fails in transpiled javascript @@ -12,8 +18,12 @@ * Fix #3482: Remove `Py.python` and `Py.expr_python` use `emitPyStatement` and `emitPyExpr` instead * Restrict replacements to accept only functions from their target language module * Fix #3528: Consider functions hidden by a signature file as private (@nojaf) +* Improve error message when Fable doesn't find the `fable-library` folder. + + This is especially useful when working on Fable itself, and should save time to others. + Each time I got this is error, I needed several minutes to remember the cause of it. -### 4.1.4 +## 4.1.4 * Fix #3438: Source maps * Fix #3440: Don't curry arity-1 functions @@ -35,7 +45,7 @@ * Rust: Updated TimeSpan * Rust: Added DateTimeOffset -### 4.1.3 +## 4.1.3 * JS/TS/Rust: Added bigint log, log2, log10, minMag, maxMag * TS: Fix extension of files in fable_modules with out dir @@ -43,20 +53,20 @@ * JS/TS: Output JS docs * Fix range of inlined functions -### 4.1.2 +## 4.1.2 * Print minimum fable-library version from npm -### 4.1.1 +## 4.1.1 * Fix fable-library package.json -### 4.1.0 +## 4.1.0 * Set TypeScript compilation as stable * Added Map.minKeyValue and maxKeyValue -### 4.1.0-beta-001 +## 4.1.0-beta-001 * Fix #3418: Single-Case Union Reflection * Include declaration .d.ts files in fable-library @@ -68,19 +78,19 @@ * TS: Get generic types of generated members * TS/JS: Sanitize class fields -### 4.0.6 +## 4.0.6 * JS Hotfix: Skip compiler generated decls * TS: Fixes for unions, pattern matching and interface function getters -### 4.0.5 +## 4.0.5 * Use native JS BigInt for int64/uint64 * Fix #3402: Rust type mismatch error when compiling F# closure code * Improve optional field and argument typing in TypeScript * Fix fable-library-ts when used with Vite -### 4.0.4 +## 4.0.4 * Fix #3397: Curry only user imports * Fix: Compiler Exception when `!!`, Anon Record, and aliased `Ux` (also behind option) @Booksbaum @@ -89,13 +99,13 @@ * Optimize compile time equality and testing (union, list, options) * TypeScript: enable Comparison, Convert and Event tests -### 4.0.3 +## 4.0.3 * Fix #3389: Don't wrap TemplateStringArray * Rust: Fix recursive closures and some type tests, * TypeScript: Emit interfaces and anonymous record annotations -### 4.0.2 +## 4.0.2 * Enable Unicode identifiers @kant2002 * Add ability for plugins to remove member declaration @Zaid-Ajaj @@ -103,42 +113,42 @@ * Rust: Enable applicative tests and other fixes * TypeScript: Enable 1909 tests -### 4.0.1 +## 4.0.1 * Fix #3371: Copying struct records * Php: Improve output @entropitor * Rust: string improvements * TypeScript: Fix applicative tests -### 4.0.0 +## 4.0.0 * Fable JS stable release -### 4.0.0-theta-018 +## 4.0.0-theta-018 * When using a .csproj, make sure the project is restored before parsing * Rust, added Stack, Queue -### 4.0.0-theta-017 +## 4.0.0-theta-017 * Use TargetFramework from .fsproj and ask users to upgrade from netstandard2.0 if necessary * Update FCS (F# 7) * Python, handling static getters * Rust, fix deprecated API -### 4.0.0-theta-016 +## 4.0.0-theta-016 * Attempt to improve project parsing * Added Double.Pow static -### 4.0.0-theta-015 +## 4.0.0-theta-015 * JS, enable calls with `importValueDynamic` * JS, Support System.Delegate.DynamicInvoke * Rust, Added feature for func_type_enum * Rust, Added Func type wrappers (#3250) -### 4.0.0-theta-014 +## 4.0.0-theta-014 * Try to fix #3244 (cannot parse .fsproj) * Rust, added small string type @@ -146,7 +156,7 @@ * JS, don't mangle idents from imports in emitted code * JS, optimize some array transforms -### 4.0.0-theta-012 +## 4.0.0-theta-012 * Python, option fixes * Python, fixes for reference equals with literals @@ -154,7 +164,7 @@ * Rust, Added bigint support * Use Buildalyzer for parsing .fsproj -### 4.0.0-theta-011 +## 4.0.0-theta-011 * Python, add read/write files * Python, fix URI and number types @@ -162,11 +172,11 @@ * JS, improve import path resolution (interpolation, inlined functions) * TypeScript, fix arithmetic tests -### 4.0.0-theta-010 +## 4.0.0-theta-010 * Use StringTemplate expr in Fable AST for Python -### 4.0.0-theta-009 +## 4.0.0-theta-009 * Add language status to version * Make --runScript compatible with Python, Rust and Dart @@ -174,7 +184,7 @@ * Compile as net6 binary * TypeScript, type-safe union types and other fixes -### 4.0.0-theta-008 +## 4.0.0-theta-008 * Enable emitExpr/Statement with interpolation, @alfonsogarciacaro * Python, fix imported interfaces from other modules, @dbrattli @@ -183,18 +193,18 @@ * TypeScript, added library-ts to packages, @ncave * Python, do not trim emitted statements -### 4.0.0-theta-007 +## 4.0.0-theta-007 * TypeScript, fix fable-library-ts @ncave * Python, fix regex tests @dbrattli * Python, fix emit expressions * JS, helpers for JSX/React apps -### 4.0.0-theta-006 +## 4.0.0-theta-006 * Python, regex fixes for group collection -### 4.0.0-theta-005 +## 4.0.0-theta-005 * Python, fix type annotation for imports of erased interfaces * Python, better regex handling @@ -202,16 +212,16 @@ * Allow alias for default/namespace imports * TypeScript, added some interface annotations -### 4.0.0-theta-004 +## 4.0.0-theta-004 * JS, allow alias for default/namespace imports -### 4.0.0-theta-003 +## 4.0.0-theta-003 * Python, fix regression when building on Windows * Rust, added Default for array, string, hashmap, hashset, guid -### 4.0.0-theta-002 +## 4.0.0-theta-002 * Rust, removed cloning after emit * Python, make sure module names are valid @@ -219,20 +229,20 @@ * Python, fixes for .ToArray and is_array_like * Rust, fixed TimeSpan fields -### 4.0.0-theta-001 +## 4.0.0-theta-001 * JSX, enable dynamic children * Python, fix dict remove * Rust, updated module visibility -### 4.0.0-snake-island-alpha-026 +## 4.0.0-snake-island-alpha-026 * Rust, more dates, @alexswan10k * Python, fix slice of string statements, @dbrattli * Python add task RunSynchronously, @dbrattli * Rust, ade startup an opt-in dependency, @ncave -### 4.0.0-snake-island-alpha-025 +## 4.0.0-snake-island-alpha-025 * Added IsInternal and IsPrivate properties in AST, @ncave * Rust, better datetime comparison + conversion. DateTimeOffset first, @alexswan10k @@ -240,12 +250,12 @@ * Python, async/await fixes for Task returning functions, @dbrattli * Rust, another problematic ref counting scenario + fix, @alexswan10k -### 4.0.0-snake-island-alpha-024 +## 4.0.0-snake-island-alpha-024 * Fable.AST 4.0 stable * Rust, StringBuilder, Dates, ref counting -### 4.0.0-snake-island-alpha-023 +## 4.0.0-snake-island-alpha-023 * Update F# compiler * Make Fable 4 compatible with Feliz plugins @@ -261,7 +271,7 @@ * Rust, Fixed closure ident cloning (#3106) * Rust, Fixed static, member and interface imports (#3105) -### 4.0.0-snake-island-alpha-021 +## 4.0.0-snake-island-alpha-021 * Rust, fixed curried apply, @ncave * Python, allow modules with uppercase letters, @dbrattli @@ -271,7 +281,7 @@ * Rust, union fix for import prefixes, @alexswan10k * Rust, fixed build dependency for wasm32, @ncave -### 4.0.0-snake-island-alpha-020 +## 4.0.0-snake-island-alpha-020 * Rust, added Display trait, @ncave * Rust, Initial type testing support, @ncave @@ -285,14 +295,14 @@ * Rust, implement unsafe-cells feature switch + Monitor, @alexswan10k * Rust, initial support for object expressions, @ncave -### 4.0.0-snake-island-alpha-019 +## 4.0.0-snake-island-alpha-019 * Python, use --fableLib to choose between embedded or site-packages, @dbrattli * Rust - Make Map and Set support PartialEq, @alexswan10k * Rust, List/Map/Set cleanup, @ncave * Rust - more collection interop improvements, @alexswan10k -### 4.0.0-snake-island-alpha-018 +## 4.0.0-snake-island-alpha-018 * Python, array, list and resize-array fixes, @dbrattli * Rust, fable-library-rust cleanup, @ncave @@ -302,22 +312,22 @@ * Rust, - More work on collection interop (Set, List, Map), @alexswan10k * Rust, - First pass at getting the interop experience with built in collections a little better, @alexswan10k -### 4.0.0-snake-island-alpha-017 +## 4.0.0-snake-island-alpha-017 * Python, reverted back to using modules instead of packages, @dbrattli * Rust, Fixed overload suffix for anon records, @ncave -### 4.0.0-snake-island-alpha-016 +## 4.0.0-snake-island-alpha-016 * Python, fixes for requirements.txt -### 4.0.0-snake-island-alpha-015 +## 4.0.0-snake-island-alpha-015 * Python, generate requirements.txt within fable_modules, @dbrattli * Rust, represent self as a Lrc[T] for method calls using double pointer indirection, @alexswan10k * Rust, fixed build issue, @ncave -### 4.0.0-snake-island-alpha-014 +## 4.0.0-snake-island-alpha-014 * Python, import fixes, @dbrattli * Rust, records and Unions now are correctly unwrapped when Struct attribute is used to tag as value, @alexswan10k @@ -330,12 +340,12 @@ * Make CancellationTokenSource implement IDisposable, @alfonsogarciacaro * Fixed Array.compareWith issue, @alfonsogarciacaro -### 4.0.0-snake-island-alpha-013 +## 4.0.0-snake-island-alpha-013 * Python, import fixes and package generation, @dbrattli * Python, use poetry for Python, @dbrattli -### 4.0.0-snake-island-alpha-012 +## 4.0.0-snake-island-alpha-012 * Update to latest FCS @ncave * Rust Support module imports @ncave @@ -343,52 +353,52 @@ * Rust: Async builder, tasks, configurable pointer types @alexswan10k * Rust: attribute support @ncave -### 4.0.0-snake-island-alpha-011 +## 4.0.0-snake-island-alpha-011 * Fix import paths in Python -### 4.0.0-snake-island-alpha-010 +## 4.0.0-snake-island-alpha-010 * Use wrapping options for Dart -### 4.0.0-snake-island-alpha-008 +## 4.0.0-snake-island-alpha-008 * Rust and Dart fixes -### 4.0.0-snake-island-alpha-007 +## 4.0.0-snake-island-alpha-007 * JSX string templates -### 4.0.0-snake-island-alpha-006 +## 4.0.0-snake-island-alpha-006 * Dart: compile union cases as child classes -### 4.0.0-snake-island-alpha-005 +## 4.0.0-snake-island-alpha-005 * Dart fixes -### 4.0.0-snake-island-alpha-004 +## 4.0.0-snake-island-alpha-004 * Don't destructure props arg in JSX components -### 4.0.0-snake-island-alpha-003 +## 4.0.0-snake-island-alpha-003 * JSX Support -### 4.0.0-snake-island-alpha-002 +## 4.0.0-snake-island-alpha-002 * Snake Island alpha release 2 -### 4.0.0-snake-island-alpha-001 +## 4.0.0-snake-island-alpha-001 * Snake Island alpha release -### 3.7.18 +## 3.7.18 * Fix #3052: Nested options with Option.orElse #3052 @IanManske * Fix Fix #3078: Nested interpolation -### 3.7.17 +## 3.7.17 * Fix #2961: Make Array.compareWith behaviour consistent with dotnet F# * Fix #2955: units of mesure with unsigned ints @@ -396,83 +406,83 @@ * Fix #2879: Make CancellationTokenSource implement IDisposable * Don't print multiple sourceMappingURL comments -### 3.7.16 +## 3.7.16 * Fix #2869: Don't update maps @hensou * Fix #2869: Use deterministic names for compiler-generate variables * Update FCS @ncave -### 3.7.15 +## 3.7.15 * Fix #2869: Avoid unnecessary updates @hensou * Fix #2931: Array.IndexOf with non-primitive -### 3.7.14 +## 3.7.14 * Fix #2924: Invalidate cache if source maps option changes * Fix #2925: Always set unicode flag for Regex * Enable non-booleans in Emit optional syntax -### 3.7.12 +## 3.7.12 * Resolve `defaultArg` at compile time when possible * Fix #2900: Equality with prototype-less JS objects * Fix #2895: FableLibDir in cached info is empty when using --precompiledLib * Fix #2880: Trait call with unit of measure -### 3.7.11 +## 3.7.11 * Fix generic param user/compiler generated name conflicts -### 3.7.10 +## 3.7.10 * Fix #2864: Interface names don't conflict in JS * Fix #2855: duplicate idents from witness in inline expr * Fix #2868: don't write empty files * Add warning when duplicated generic params are detected -### 3.7.9 +## 3.7.9 * Fix #2851: References captured by >> eagerly eval * Fix wrong out paths when using lower case drive letter -### 3.7.8 +## 3.7.8 * Fix #2845: Cover more edge cases @Prunkles -### 3.7.7 +## 3.7.7 * Fix #2840: Keep delegates of arity 1 curried @JaggerJo * Fix #2844: 1-len array slices starting at 0 work @jpacker * Fix #2845: Regex.Matches infinite loop @Prunkles -### 3.7.6 +## 3.7.6 * Type.IsInstanceOfType works for interfaces decorated with Global/Import @chkn -### 3.7.5 +## 3.7.5 * Prevent combining absolute paths -### 3.7.4 +## 3.7.4 * Change intro message -### 3.7.3 +## 3.7.3 * Fix #2832: Adding a converted char to string * Fix Type.IsSubclassOf(obj) @chkn -### 3.7.2 +## 3.7.2 * Fix the fixes in the previous release -### 3.7.1 +## 3.7.1 * Fix #2809: Generic trait calls in multiple nested inlined functions * Fix #2817: Optimization - Remove wrapping lambdas when possible -### 3.7.0 +## 3.7.0 * Cache .fsproj parsing result * Run F# type check and Fable in parallel (use --noParallelTypeCheck flag to disable) @@ -485,40 +495,40 @@ * Fix #2709: error when using JsInterop.import in inlined functions * Fix #2719: use with null disposable -### 3.7.0-beta-015 +## 3.7.0-beta-015 * Run sub-process even if compilation was skipped -### 3.7.0-beta-014 +## 3.7.0-beta-014 * Add --noParallelTypeCheck option to disable F#/Fable parallel compilation -### 3.7.0-beta-012 +## 3.7.0-beta-012 * Disable uncurrying functions passed as arguments to local lambdas * Fix typeof(obj).IsInstanceOfType @chkn -### 3.7.0-beta-011 +## 3.7.0-beta-011 * Fixes for precompiling inline expressions * Fix #2719: use with null disposable * Fix #2727: don't write in same line when output redirected -### 3.7.0-beta-009 +## 3.7.0-beta-009 * Fix #2718 * Other stability issues and add more verbose logs -### 3.7.0-beta-008 +## 3.7.0-beta-008 * Prevent Fable from getting stuck on fatal errors * Show File compiled messages in CI -### 3.7.0-beta-007 +## 3.7.0-beta-007 * Lock file for outDir (mainly intended for parallel processes precompiling the same library) -### 3.7.0-beta-006 +## 3.7.0-beta-006 * Allow inlined functions accessing internal values in Fable.Precompiled.dll (FCS) * Shorten logs in same line if longer than 80 chars (so they don't jump to next line) @@ -526,39 +536,39 @@ * Add flag to disable reflection * Fix #2709: error when using JsInterop.import in inlined functions -### 3.7.0-beta-005 +## 3.7.0-beta-005 * Fix cache issues * Seeded random -### 3.7.0-beta-004 +## 3.7.0-beta-004 * Fix watch mode and runFast optimization -### 3.7.0-beta-003 +## 3.7.0-beta-003 * Fix precompile errors -### 3.7.0-beta-002 +## 3.7.0-beta-002 * Performance improvements -### 3.7.0-beta-001 +## 3.7.0-beta-001 * Add precompile command -### 3.6.3 +## 3.6.3 * New FSharp.Core 6 APIs: updateAt/insertAt/insertManyAt/removeAt/removeManyAt * Support thousand separators in String.Format * Fix #2628 @stroborobo -### 3.6.2 +## 3.6.2 * TypescriptTaggedUnion @cannorin * Speed up recompilation when adding/removing files -### 3.6.1 +## 3.6.1 * Fix #2614: Char addition * Fix #2615: Math.DivRem @@ -566,26 +576,26 @@ * Improve Regex.Match/IsMatch/Matches * Update FCS -### 3.6.0 +## 3.6.0 * Support F# 6 * Support DateOnly/TimeOnly @kerams * Improve watch mode * Cache project options -### 3.6.0-beta-003 +## 3.6.0-beta-003 * Add Fable.Core.Compiler.triggeredByDependency flag * Support DefaultParameterValue attribute (not for JS interop) * Update F# compiler -### 3.6.0-beta-002 +## 3.6.0-beta-002 * Fix watch mode when saving multiple files at same time * TimeOnly.FromDateTime @kerams * Remove --watchDeps flag -### 3.6.0-beta-001 +## 3.6.0-beta-001 * Support F# 6 * Support DateOnly/TimeOnly @kerams @@ -593,21 +603,21 @@ * Add `--watchDeps` flag * Cache project options -### 3.4.10 +## 3.4.10 * Add support for StringSplitOptions.TrimEntries @steveofficer * Fix #2587: DateTimeOffset.Parse issues with some locales @ncave * Use Process.ArgumentList to escape args passed to subprocess * Print paths relative to --cwd if set -### 3.4.9 +## 3.4.9 * Add CLI arg --watchDelay * Show relative paths in logs * Fixed Seq.toArray @ncave * Fix FullName/Name/Namespace of complex array types -### 3.4.8 +## 3.4.8 * Fix #2572 #2579: Watch .fsi files and referenced .fsproj * Fix #2576: Last file can omit module declaration @@ -615,23 +625,23 @@ * Fix DateTime Offset parsing with date only and hyphens * Set NODE_ENV when running a sub-process -### 3.4.7 +## 3.4.7 * Fix #2571: Forward slash not escaped when creating regex -### 3.4.6 +## 3.4.6 * Small improvements in Async.ts -### 3.4.5 +## 3.4.5 * Accept ${entryDir} macro in imports -### 3.4.4 +## 3.4.4 * Use relative paths for source maps -### 3.4.3 +## 3.4.3 * Add support of System.Activator for primitive types @Happypig375 * Fix #2566: HashSet.IntersectWith does not respect custom comparer @@ -640,19 +650,19 @@ * Pass Fable compiled name to ReflectedDecorator * Remove void wrapper in expression statements -### 3.4.2 +## 3.4.2 * Fix #2561: Case insensitive args and check * Fix generic parameters with JS.ReflectedDecorator -### 3.4.1 +## 3.4.1 * Support System.Collections.Generic.Queue @davedawkins * Fix custom array equality * Remove class restriction for ParamObject * Skip parens in emit if placeholder is already surrounded by parens -### 3.4.0 +## 3.4.0 * ParamObject attribute * Rename .fable folder to fable_modules @@ -660,7 +670,7 @@ * Add Type.IsInstanceOfType @chkn * Fix #2229: Parsing succeeded for some invalid dates @njlr -### 3.3.1 +## 3.3.1 * Fix #2097: Async.StartChild does not apply timeout @njlr * Fix #2530: System.Collections.Generic.Stack @njlr @@ -668,7 +678,7 @@ * Fix #2549: Native ESM support * Serialize compiler_info as JSON -### 3.3.0 +## 3.3.0 * JS.Decorator/ReflectedDecorator attributes * Fix isSubclassOf to walk up the inheritance chain @chkn @@ -676,25 +686,25 @@ * Fix #2532: Measure products * Optimize interpolate strings without formatting into JS templates -### 3.2.14 +## 3.2.14 * Fix #2480: Include package.json in fable-library * Fix #2522: Warn if user sets .fable as outDir * Fix #2525: Support infinite arity for currying/uncurrying * Fix plugin version check -### 3.2.12 +## 3.2.12 * Fix #2505: Make String.Split match .NET with no or null separators * Add TimeSpan.Divide and Multiply @0x53A * Add Async.Sequential @0x53A * Compile `FormattableString` as JS Templates -### 3.2.11 +## 3.2.11 * Add --rootModule CLI flag -### 3.2.10 +## 3.2.10 * Support System.Uri.TryCreate @Choc13 * Fix #2477: Don't drop "DEBUG" and "TRACE" DefineConstants @stroborobo @@ -703,68 +713,68 @@ * Fix #2491: Unchecked.defaultof with struct tuples * Fix #2496: Custom Pow operator -### 3.2.9 +## 3.2.9 * Don't print JS files in watch mode if there're F# errors * Fix SRTP with local inline functions -### 3.2.8 +## 3.2.8 * Fix regression in FCS: passing __SOURCE_IDENTIFIER__ to static parameters in type providers -### 3.2.7 +## 3.2.7 * Fix regression: all files were recompiled in watch mode in 3.2.5 * Fix #2472: Tuple-related methods -### 3.2.6 +## 3.2.6 * Fix #2471: Trait call regression -### 3.2.5 +## 3.2.5 * Fix #2468: SRTP Parser * Only show Compile file log in watch compilations -### 3.2.4 +## 3.2.4 * Fix #2438: Print JS sequence expressions always between parentheses * Don't jump over mutable idents when inlining -### 3.2.3 +## 3.2.3 * Experimental.namesofLambda -### 3.2.2 +## 3.2.2 * Check for correct types in Anonymous Record when assigning to Interface with [] via !! @Booksbaum * Fix #1973: FormattableString support -### 3.2.1 +## 3.2.1 * Fix Event issues and and implement FSharpEvent`2 @chkn * Fix #2451: throw exception when sequence is empty @MNie * Fix #2445: Improve error message when fable doesn't implement an API -### 3.2.0 +## 3.2.0 * Update to net5.0 and FCS, @ncave -### 3.1.16 +## 3.1.16 * Publish with icon and symbols @cartermp -### 3.1.15 +## 3.1.15 * Add a --sourceMapsRoot CLI option to set source maps sourceRoot @mlaily * Fix #2433: Improve type info for plugins like Fable.SvelteStore * Fix #2431: Pass output directory info to plugins -### 3.1.14 +## 3.1.14 * Experimental `casenameWithFieldIndex` -### 3.1.12 +## 3.1.12 * Fix #1678: BigInt native JS JSON serialization with toJSON * Fix #2151: Implement DateTimeOffset.toOffset @Booksbaum @@ -775,29 +785,29 @@ * Update big.js (decimals) @ncave * Update source-map-sharp to 1.0.5 -### 3.1.11 +## 3.1.11 * Fix watch compilation issues * Fix #2398: two successive string format placeholders and value of first one ends in `%` -### 3.1.10 +## 3.1.10 * Revert breaking change, configuration should default to Debug only in watch mode @forki -### 3.1.9 +## 3.1.9 * Fix crash with delegate alias -### 3.1.8 +## 3.1.8 * Fix #2234: Recompile dependencies in watch mode when Emit/Import attributes change * Fix #2406: Check --outDir argument when running clean command -### 3.1.7 +## 3.1.7 * Fix for Fable.Core.JsInterop.importValueDynamic -### 3.1.6 +## 3.1.6 * Support setting a Build configuration with --configuration cli arg @stroborobo * Log compiled files in same line @@ -808,16 +818,16 @@ * Fix: Accessing named capture group in Regex only works with string constant @Booksbaum * Fable library improvements and other fixes @ncave -### 3.1.5 +## 3.1.5 * Fix #2384: Polling file watcher @mlaily * Fix static constructors with attached members -### 3.1.4 +## 3.1.4 * Fix #2045: Aliasing a function wrapping a multi-arity function in point-free style -### 3.1.3 +## 3.1.3 * Add support for named capture groups in Regexes @Booksbaum * Babel AST: cleanup and refactor @dbrattli @@ -834,7 +844,7 @@ * Fix #2046: Assigning a function to scoped mutable variable * Fix #2045: Raise warning for point-free function declarations -### 3.1.2 +## 3.1.2 * Fast copy for typed arrays @GordonBGood * Return error exit code when wront arguments passed @@ -843,24 +853,24 @@ * Fix #2355: System.Math.Ceiling() and System.Math.Floor returning incorrect values for some Decimals @ncave * Fix #2357: Remove duplicate switch branches -### 3.1.1 +## 3.1.1 * Fix #2343: Remove conflicting export default * Fix #2336: Parameretized padding * Fix reflection for int64/decimal with units of measure -### 3.1.0 +## 3.1.0 * Source map support @delneg * Fix #2342: recompile union tests in watch mode @tomcl * Fix #2332: watch broken for certain directory structures @jwosty -### 3.1.0-beta-001 +## 3.1.0-beta-001 * Source map support @delneg * Fix #2332: watch broken for certain directory structures @jwosty -### 3.0.5 +## 3.0.5 * Fixed compiler option parsing @ncave * Fix #2329: Class getters with import function helpers @@ -868,41 +878,41 @@ * Fix #2327: Inherit global class in nested module * Fix #2325: `AttachMembers` attribute -### 3.0.4 +## 3.0.4 * Opt-in polling watcher @mlaily * Fix #2323: Uncurrying Emit obj args -### 3.0.3 +## 3.0.3 * Fix #2318: char ranges @inosik * Fix #2320: `--yes` CLI arg * Fix (partially) #2321: `System.Type.GetInterface` -### 3.0.2 +## 3.0.2 * Fix #2313: Measure abbreviations * Fix #2311: Arrow function printing -### 3.0.1 +## 3.0.1 * Fix spread wrapped by parens @do-wa * Add runtime check for Option.Value * Remove equals/compare "fast" helper (sometimes fails) -### 3.0.0 +## 3.0.0 * Official release * Fix #2293: Fix case of path passed as cli argument @tomcl * Fix #2277: Make FsWatcher case-insensitive @reinux * Fix local imports with `import` function helpers -### 3.0.0-nagareyama-rc-011 +## 3.0.0-nagareyama-rc-011 * Fix #2303: spreading complex expressions * Fix #2302: Fable.JsonProvider -### 3.0.0-nagareyama-rc-010 +## 3.0.0-nagareyama-rc-010 * Moar beta reduction improvements * Use caching only in watch mode @@ -910,7 +920,7 @@ * Fix watch dependencies when order of union cases changes * Fix #2295: Disable errors affecting Fable 2-compliant code -### 3.0.0-nagareyama-rc-009 +## 3.0.0-nagareyama-rc-009 * Improve lambda beta reduction * Fix #1962: Find entities by core assembly name @@ -919,7 +929,7 @@ * Fix #2288: Ignore --warnaserror from project references * Fix #2291: Default hashing for classes -### 3.0.0-nagareyama-rc-008 +## 3.0.0-nagareyama-rc-008 * Fix FSharpType.IsTuple for array of tuples @kerams * In watch mode, recompile all files if F# failed previously @@ -928,16 +938,16 @@ * Fix #2278: Optimize `createObj` * Fix #2276: Formatting Decimals -### 3.0.0-nagareyama-rc-007 +## 3.0.0-nagareyama-rc-007 * Always lower case ToString -### 3.0.0-nagareyama-rc-006 +## 3.0.0-nagareyama-rc-006 * Fix #2136: Type Provider invalidation @zanaptak * Support Nullables -### 3.0.0-nagareyama-rc-005 +## 3.0.0-nagareyama-rc-005 * Fix #2267: Allow direct console output preserving colors @zanaptak * Fix #2259: File conflict in outDir @@ -945,40 +955,40 @@ * StringBuilder.Append overloads @gusty * Make file watcher more robust -### 3.0.0-nagareyama-rc-004 +## 3.0.0-nagareyama-rc-004 * LeanWork.IO.FileSystem.Watcher by Peter Meinl -### 3.0.0-nagareyama-rc-003 +## 3.0.0-nagareyama-rc-003 * Fix #1962: FSharp.UMX measure annotated types * Fix #2250: Math.Clamp * Fix #2257: Remove warnings in keyValueList -### 3.0.0-nagareyama-rc-002 +## 3.0.0-nagareyama-rc-002 * Patch FCS witness error @ncave * Set always --langversion:preview -### 3.0.0-nagareyama-rc-001 +## 3.0.0-nagareyama-rc-001 * Release candidate * FCS witnesses! * Other fixes -### 3.0.0-nagareyama-beta-005 +## 3.0.0-nagareyama-beta-005 * Fix #2238: Normalize paths on Windows * Fix #2212 (3rd attempt): Killing subprocess on Windows -### 3.0.0-nagareyama-beta-004 +## 3.0.0-nagareyama-beta-004 * Typescript-related updates @ncave * Omit module prefix in imports @Zaid-Ajaj * Write compiler options to .fable/compiler_info.txt * Compatibility with Fable.AST beta-002 -### 3.0.0-nagareyama-beta-003 +## 3.0.0-nagareyama-beta-003 * Fix #2226: Wrong decimal separator depending on regional setting @bklop * Fix #2228: Remove unused values generated by imports meant for side effects @@ -986,26 +996,26 @@ * Fix #2216: Remove empty else blocks * Fix #2212: Ctrl+C doesn't kill subprocess in Windows -### 3.0.0-nagareyama-beta-002 +## 3.0.0-nagareyama-beta-002 * Compatibility with Fable.AST beta-001 -### 3.0.0-nagareyama-beta-001 +## 3.0.0-nagareyama-beta-001 * Beta release * Fix .fsx compilation -### 3.0.0-nagareyama-alpha-017 +## 3.0.0-nagareyama-alpha-017 * Only use cached (precompiled) files in debug mode -### 3.0.0-nagareyama-alpha-016 +## 3.0.0-nagareyama-alpha-016 * Only use cached (precompiled) files in debug mode * Optimize list construction * Compatibility with latest Fable.AST -### 3.0.0-nagareyama-alpha-015 +## 3.0.0-nagareyama-alpha-015 * Fix #2211: File extension in dynamic imports @Zaid-Ajaj * Fix #2212: Kill subprocess in Windows @Zaid-Ajaj @@ -1013,68 +1023,68 @@ * Compatibility with latest Fable.AST release * Minor improvements in code generation -### 3.0.0-nagareyama-alpha-014 +## 3.0.0-nagareyama-alpha-014 * Fixed entity resolution @ncave * Cli improvements -### 3.0.0-nagareyama-alpha-012 +## 3.0.0-nagareyama-alpha-012 * Fix plugins -### 3.0.0-nagareyama-alpha-011 +## 3.0.0-nagareyama-alpha-011 * Plugins -### 3.0.0-nagareyama-alpha-010 +## 3.0.0-nagareyama-alpha-010 * Fix #2202: Using System.Type as Dictionary key @Zaid-Ajaj * Fix #2203: Comparing large sets @Zaid-Ajaj * Keep only entity refs in Fable AST -### 3.0.0-nagareyama-alpha-009 +## 3.0.0-nagareyama-alpha-009 * Detect if command after `--run` is in `node_modules/.bin` dir * Set typedArrays=true as default again -### 3.0.0-nagareyama-alpha-008 +## 3.0.0-nagareyama-alpha-008 * Use latest FCS @ncave * Disable file caching when compiler version changes * Add back base class for Union/Record * Fix calls to static members of imported classes -### 3.0.0-nagareyama-alpha-007 +## 3.0.0-nagareyama-alpha-007 * --runScript option * Fix uncurrying of Emit calls * Fix type testing performance * Fix union/record string formattin -### 3.0.0-nagareyama-alpha-006 +## 3.0.0-nagareyama-alpha-006 * Fix running process -### 3.0.0-nagareyama-alpha-005 +## 3.0.0-nagareyama-alpha-005 * Fix watcher * Use latest implementation of FSharpMap and FSharpSet * Fix generic equality -### 3.0.0-nagareyama-alpha-004 +## 3.0.0-nagareyama-alpha-004 * Improve CLI and other fixes -### 3.0.0-nagareyama-alpha-003 +## 3.0.0-nagareyama-alpha-003 * Fix: Add names with $reflection suffix to root scope * Fix deriving from imported JS classes * Keep support for ParamList attribute until removed from Fable.React -### 3.0.0-nagareyama-alpha-002 +## 3.0.0-nagareyama-alpha-002 * Ignore warnings from packages (as before) -### 3.0.0-nagareyama-alpha-001 +## 3.0.0-nagareyama-alpha-001 * Nagareyama alpha diff --git a/src/Fable.Cli/Fable.Cli.fsproj b/src/Fable.Cli/Fable.Cli.fsproj index 986fde43f3..9f6f17f59a 100644 --- a/src/Fable.Cli/Fable.Cli.fsproj +++ b/src/Fable.Cli/Fable.Cli.fsproj @@ -5,7 +5,6 @@ Exe net6.0 4.1.4 - 4.1.4 * Fix #3438: Source maps * Fix #3440: Don't curry arity-1 functions * Fix #3452: DateTimeOffset conversion to DateTime @@ -35,11 +34,11 @@ $(OtherFlags) --nowarn:3536 - - - - - + + + + + @@ -52,7 +51,7 @@ - + @@ -66,4 +65,4 @@ - \ No newline at end of file + diff --git a/src/Fable.Cli/ProjectCracker.fs b/src/Fable.Cli/ProjectCracker.fs index d4ddffa1f1..065ba8cdf2 100644 --- a/src/Fable.Cli/ProjectCracker.fs +++ b/src/Fable.Cli/ProjectCracker.fs @@ -617,8 +617,8 @@ let getFableLibraryPath (opts: CrackerOptions) = let fableLibrarySource = let baseDir = AppContext.BaseDirectory baseDir - |> File.tryFindNonEmptyDirectoryUpwards {| matches = [buildDir; "build/" + buildDir]; exclude = ["src"] |} - |> Option.defaultWith (fun () -> Fable.FableError $"Cannot find [build/]{buildDir} from {baseDir}" |> raise) + |> File.tryFindNonEmptyDirectoryUpwards {| matches = [buildDir; "temp/" + buildDir]; exclude = ["src"] |} + |> Option.defaultWith (fun () -> Fable.FableError $"Cannot find [temp/]{buildDir} from {baseDir}.\nPlease, make sure you build {buildDir}" |> raise) let fableLibraryTarget = IO.Path.Combine(opts.FableModulesDir, libDir) // Always overwrite fable-library in case it has been updated, see #3208 diff --git a/src/Fable.Cli/Properties/launchSettings.json b/src/Fable.Cli/Properties/launchSettings.json index 5510cc8c87..c8e25749fb 100644 --- a/src/Fable.Cli/Properties/launchSettings.json +++ b/src/Fable.Cli/Properties/launchSettings.json @@ -5,14 +5,14 @@ "workingDirectory": "../..", // fable-library-ts - // "commandLineArgs": "src/fable-library --outDir build/fable-library-ts --fableLib build/fable-library-ts --lang TypeScript --typedArrays false --exclude Fable.Core --define FX_NO_BIGINT --define FABLE_LIBRARY --noCache" + // "commandLineArgs": "src/fable-library --outDir temp/fable-library-ts --fableLib temp/fable-library-ts --lang TypeScript --typedArrays false --exclude Fable.Core --define FX_NO_BIGINT --define FABLE_LIBRARY --noCache" // test-ts - //"commandLineArgs": "tests/TypeScript --outDir build/tests/TypeScript --lang TypeScript --exclude Fable.Core --noCache", + //"commandLineArgs": "tests/TypeScript --outDir temp/tests/TypeScript --lang TypeScript --exclude Fable.Core --noCache", // quicktest-ts "commandLineArgs": "src/quicktest --lang TypeScript --exclude Fable.Core --noCache" } } -} \ No newline at end of file +} diff --git a/src/Fable.Core/RELEASE_NOTES.md b/src/Fable.Core/CHANGELOG.md similarity index 84% rename from src/Fable.Core/RELEASE_NOTES.md rename to src/Fable.Core/CHANGELOG.md index 6095c6bfd8..b591c1d7a2 100644 --- a/src/Fable.Core/RELEASE_NOTES.md +++ b/src/Fable.Core/CHANGELOG.md @@ -1,4 +1,10 @@ -### Unreleased +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased * Fix #3482: Remove `Py.python` and `Py.expr_python` * Add `!^` to `Fable.Core.RustInterop` module @@ -6,137 +12,137 @@ * Fix #3484: Rename `emitExpr` to `emitPyExpr` in `PyInterop` * Fix #3484: Replace `Rust.emitExpr` with `RustInterop.emitRustExpr` -### 4.0.0 +## 4.0.0 * Fable 4 stable -### 4.0.0-theta-007 +## 4.0.0-theta-007 * Fix #3249 by enabling uncurrying for functions with multiple parameters @inosik -### 4.0.0-theta-006 +## 4.0.0-theta-006 * Python fixes for decorator attribute -### 4.0.0-theta-005 +## 4.0.0-theta-005 * Add JSX.jsx function -### 4.0.0-theta-004 +## 4.0.0-theta-004 * Add ??= operator to JsInterop -### 4.0.0-theta-003 +## 4.0.0-theta-003 * Python fixes for Interactive -### 4.0.0-theta-002 +## 4.0.0-theta-002 * Python helpers for Interactive * JS helpers for JSX/React integration -### 4.0.0-theta-001 +## 4.0.0-theta-001 * Fable 4 theta release -### 4.0.0-snake-island-alpha-007 +## 4.0.0-snake-island-alpha-007 * Snake Island alpha release -### 4.0.0-snake-island-alpha-006 +## 4.0.0-snake-island-alpha-006 * Some Rust helpers -### 4.0.0-snake-island-alpha-005 +## 4.0.0-snake-island-alpha-005 * DartNullable and other Dart helpers -### 4.0.0-snake-island-alpha-004 +## 4.0.0-snake-island-alpha-004 * JSX string templates -### 4.0.0-snake-island-alpha-003 +## 4.0.0-snake-island-alpha-003 * Add Dart print/Future/Stream -### 4.0.0-snake-island-alpha-002 +## 4.0.0-snake-island-alpha-002 * JSX Support -### 4.0.0-snake-island-alpha-001 +## 4.0.0-snake-island-alpha-001 * Snake Island alpha release -### 3.7.1 +## 3.7.1 * Add `AsyncIterable` to Fable.Core.JS -### 3.7.0 +## 3.7.0 * Fix #2863: Add a nestable union type U9 @cannorin * Fix links in doc comments -### 3.6.2 +## 3.6.2 * Fix #2805: Improve jsNative error messages * Revert changes in Core.JS, see Fulma/issues/294 -### 3.6.1 +## 3.6.1 * TypescriptTaggedUnion @cannorin -### 3.6.0 +## 3.6.0 * Add Fable.Core.Compiler.triggeredByDependency flag -### 3.4.0 +## 3.4.0 * ParamObject attribute -### 3.3.1 +## 3.3.1 * JS.Decorator/ReflectedDecorator attributes * JS.Function -### 3.2.9 +## 3.2.9 * Add `FormattableString.GetStrings()` extension -### 3.2.8 +## 3.2.8 * Experimental.namesofLambda -### 3.2.7 +## 3.2.7 * Publish with icon and symbols @cartermp -### 3.2.6 +## 3.2.6 * Experimental `casenameWithFieldIndex` -### 3.2.5 +## 3.2.5 * Add `Compiler.extension` -### 3.2.4 +## 3.2.4 * Add Object.values, Object.entries @kerams * Add JsInterop.jsTypeof/jsInstanceof * Add JS.Constructors.Array.Create/from -### 3.2.3 +## 3.2.3 * Fix incompatibility with Feliz @TIHan -### 3.2.2 +## 3.2.2 * `AttachMembers` attribute -### 3.2.1 +## 3.2.1 * Lower FSharp.Core requirement to 4.7.2 -### 3.2.0 +## 3.2.0 * New helpers for Fable 3 * `Mangle` attribute @@ -144,36 +150,36 @@ * `emitJsExpr` and `emitJsStatement` helpers * Access compiler options in `Compiler` module -### 3.1.6 +## 3.1.6 * Fixed TypedArray.set signature @Shmew -### 3.1.5 +## 3.1.5 * Fixed missing indexer in JS TypedArray. -### 3.1.4 +## 3.1.4 * Fix JS Map constructor @Luiz-Monad -### 3.1.3 +## 3.1.3 * PR #1935: Put JS constructors in different module to prevent conflicts @pauldorehill -### 3.1.2 +## 3.1.2 * Add CaseRules.SnakeCase -### 3.1.1 +## 3.1.1 * Fix TypedArray bindings @Titaye -### 3.1.0 +## 3.1.0 * Add JS Typed Arrays @Titaye * Fix names of arguments in Testing.Assert @zanaptak -### 3.0.0 +## 3.0.0 * Add `JsInterop.importValueDynamic` * Move `nameof` operators to Experimental module @@ -181,155 +187,155 @@ * Add Emit and Import attribute aliases * Namespace restructure -### 3.0.0-beta-006 +## 3.0.0-beta-006 * Add `JsInterop.importValueDynamic` -### 3.0.0-beta-005 +## 3.0.0-beta-005 * Move `nameof` operators to Experimental module -### 3.0.0-beta-004 +## 3.0.0-beta-004 * Move JS extensions to Fable.Core.Extensions file -### 3.0.0-beta-003 +## 3.0.0-beta-003 * Add some missing JS APIs -### 3.0.0-beta-002 +## 3.0.0-beta-002 * Array .buffer extension * Add Emit and Import attribute aliases -### 3.0.0-beta-001 +## 3.0.0-beta-001 * Namespace restructure -### 2.1.0-alpha-002 +## 2.1.0-alpha-002 * Clean Fable.Import.JS module and rename it to Fable.Core.JS * Add unions of measure for non-numeric primitive types -### 2.0.3 +## 2.0.3 * Add `Fable.Core.Reflection` module -### 2.0.2 +## 2.0.2 * Add `nameof2` and `exportDefault` -### 2.0.1 +## 2.0.1 * Fix `ReadonlyArray` spelling -### 2.0.0 +## 2.0.0 * Fable 2 -### 1.3.7 +## 1.3.7 * See dotnet-fable 1.3.7 release notes -### 1.3.0-beta-009 +## 1.3.0-beta-009 * See dotnet-fable 1.3.0-beta-009 release notes -### 1.2.4 +## 1.2.4 * See dotnet-fable 1.2.4 release notes -### 1.2.3 +## 1.2.3 * Fix #1135, #1136: `unit option` hack doesn't work with generic functions -### 1.2.2 +## 1.2.2 * See Fable.Compiler 1.2.2 -### 1.2.1 +## 1.2.1 * Guid validation and byte[] conversion * Date Fix #1139 -### 1.2.0 +## 1.2.0 * Add support for String.filter #1133 * Fix #1131: DateTime.ToString not working without separator -### 1.2.0-beta-004 +## 1.2.0-beta-004 * Fix format over local dates #1129 * Fix 2 digits years datetime #1127 -### 1.2.0-beta-003 +## 1.2.0-beta-003 * Don't calculate relative path for paths in different drive letters on Windows -### 1.2.0-beta-002 +## 1.2.0-beta-002 * Target netstandard1.6 again -### 1.2.0-beta-001 +## 1.2.0-beta-001 * Upgrade to netstandard2.0 -### 1.1.15 +## 1.1.15 * Fix #1113: Set.union -### 1.1.14 +## 1.1.14 * Fix #1104: JSON serialization of Long and BigInt -### 1.1.12 +## 1.1.12 * Add DateTime ticks constructor * Convert to and from Base64String -### 1.1.11 +## 1.1.11 * Fix #1094: Implement "indexed" in collection modules -### 1.1.10 +## 1.1.10 * Fix recursive functions in Seq module -### 1.1.9 +## 1.1.9 * Add constructors to JsFunc -### 1.1.8 +## 1.1.8 * Small refactoring * Add `DateTime.IsDaylightSavingTime` replacement (#1082, #1083) -### 1.1.7 +## 1.1.7 * Support String.Join with objects (#1058) -### 1.1.6 +## 1.1.6 * Fix #1046: Parse time-only strings * Support some System.Uri static methods (#1048) -### 1.1.5 +## 1.1.5 * Fix #1028: Arguments of auto-generated lambdas conflicting with outer variables -### 1.1.4 +## 1.1.4 * Fix fable-import/#9: Don't try to replace method calls in bindings -### 1.1.3 +## 1.1.3 * Add System.Console reference -### 1.1.2 +## 1.1.2 * Fix Paket groups for Fable.Core -### 1.1.1 +## 1.1.1 * Fix F# compiler errors in recompilation * Fix Elmish.Browser parser (#1003) @@ -338,143 +344,143 @@ * Add replacement for System.Environment.NewLine (#993) * Expose Console among JS import globals -### 1.1.0 +## 1.1.0 * Fable stablish, yeah! -### 1.1.0-rc-002 +## 1.1.0-rc-002 * Fix #996: Don't wrap dynamic CurriedLambdas -### 1.1.0-rc-001 +## 1.1.0-rc-001 * Support Paket groups and move Browser and Node bindings out of Fable.Core -### 1.0.8 +## 1.0.8 * Fix #940: Compilation of multiple projects in parallel -### 1.0.7 +## 1.0.7 * Fix #952: Don't remove non-null unit arguments * Fix #944: Import and Emit on same function -### 1.0.6 +## 1.0.6 * Propagate subprocess exit code -### 1.0.5 +## 1.0.5 * Fix #946: --port free throws exception -### 1.0.4 +## 1.0.4 * Don't redirect dotnet-fable commands but check version and locate fable-core JS files in packages/Fable.Core -### 1.0.0-narumi-917 +## 1.0.0-narumi-917 * Fix location of fable-core files -### 1.0.0-narumi-916 +## 1.0.0-narumi-916 * We're going PAKET! -### 1.0.0-narumi-915 +## 1.0.0-narumi-915 * Fix curried lambdas assigned to generic params (see #888) -### 0.7.49 +## 0.7.49 * Fix #744: CLI argument flags -### 0.7.48 +## 0.7.48 * Fix #736: Case testing with erased unions -### 0.7.47 +## 0.7.47 * Tailcall optimizes function arguments: #681 -### 0.7.45 +## 0.7.45 * Fix import expressions with methods with function arguments: #721 -### 0.7.43 +## 0.7.43 * Add reflection methods (see ReflectionTests.fs) * Improve import expressions #721 -### 0.7.42 +## 0.7.42 * Tailcall optimizations: PR #669 + Fixes -### 0.7.37 +## 0.7.37 * Add FSharp.Core.dll to fable-compiler package * Improve handling of `jsThis` -### 0.7.35 +## 0.7.35 * Only show Rollup warnings in `--verbose` mode * Minor fixes -### 0.7.34 +## 0.7.34 * Fix #660: `Option.fold` and `Option.foldBack` -### 0.7.33 +## 0.7.33 * Add operator `enum` -### 0.7.32 +## 0.7.32 * Fixed default comparer: PR #658 -### 0.7.31 +## 0.7.31 * Added BigInt conversions: PR #650 -### 0.7.30 +## 0.7.30 * Fix #649: Int64 serialization * Fix #648: Caching of namespace F# entities * Fix #646: Zero fill shift right (>>>) for uint32 -### 0.7.29 +## 0.7.29 * Add `BigInteger` support -### 0.7.28 +## 0.7.28 * Fix #640: Omitted non optional nulls * Fix #638: Inlined methods with `this` argument -### 0.7.27 +## 0.7.27 * Add `--includeJs` compiler argument * Fix #629: Visual Studio error format * Fix #637: IEnumerable runtime issue -### 0.7.26 +## 0.7.26 * Fixed Option.foldBack (#634) * Improve .NET Enumerator/JS Iterator compatibility * Fix #633: jsThis * Fixed Option.foldBack (PR #634) -### 0.7.25 +## 0.7.25 * Fix #623: JS Global properties * Fix #624: Aether compilation -### 0.7.24 +## 0.7.24 * Fix module generic methods without arguments * Added `String.IndexOfAny/Compare/Equals` with `StringComparison` enum * Fix generic types when compiling to ES2015 * Unify `Equals` and `CompareTo` methods of `Long.ts` -### 0.7.23 +## 0.7.23 * Fix #348 #608 Double/Int32 Parse & TryParse * Fix #609: Event unsubscription @@ -486,23 +492,23 @@ * Fix #237: Recursive value definitions * Added char to int (#594) -### 0.7.22 +## 0.7.22 * Fix secondary constructors of imported classes * Improvements in option handling -### 0.7.20 +## 0.7.20 * Prevent infinite loops for bundle errors in watch mode -### 0.7.19 +## 0.7.19 * Fix #509: Add KeyValuePattern * Fix #544 #585: Bundling in watch mode * Fix #589: Regex Provider with Fable 0.7 * Add optional argument to GlobalAttribute -### 0.7.18 +## 0.7.18 * Add validation to `ofJson` * Make `Assert.AreEqual` work with F# equality @@ -511,217 +517,217 @@ * Fix sprintf "%X" (#580) * Fix #579: Printf.printfn -### 0.7.17 +## 0.7.17 * Add `Pojo` union types -### 0.7.16 +## 0.7.16 * Fix issues in generic resolution -### 0.7.15 +## 0.7.15 * Issue warning when calling `typeof` on a generic parameter * Use absolute paths for assembly references in `node_modules` -### 0.7.14 +## 0.7.14 * Use "umd" distribution of fable-core and other libs when compiling for umd modules * Fix #569: Types with circular dependencies -### 0.7.12 +## 0.7.12 * Fix #568: Types with `StructAttribute` (compiled as records) * Better checking when calling functions with `PassGenericsAttribute` -### 0.7.11 +## 0.7.11 * Some adjustments in attribute resolution -### 0.7.10 +## 0.7.10 * Fix #565, #566: Only watch F# files * Fix #564: Don't overload methods from imported classes * Fix #563: Overloads with `PassGenericsAttribute` -### 0.7.9 +## 0.7.9 * Fix `Array.rev` (see #559) * Added UnboxFast intrinsic / List.truncate (see #561) -### 0.7.8 +## 0.7.8 * `System.Exception` translates to JS `Error` * Fix #556: inline methods placed after calls -### 0.7.7 +## 0.7.7 * Fix ES2015 imports -### 0.7.6 +## 0.7.6 * Too many changes to be listed, check the [migration guide](http://fable.io/blog/Introducing-0-7.html) -### 0.7.5-alpha.41 +## 0.7.5-alpha.41 * Fix cyclic dependencies in fable-core -### 0.7.5-alpha.40 +## 0.7.5-alpha.40 * Minor fix -### 0.7.5-alpha.39 +## 0.7.5-alpha.39 * Simplify Reflection system * Add `PojoAttribute` * Replace baseDir of references with --refs argument -### 0.7.5-alpha.38 +## 0.7.5-alpha.38 * Fix #547: Ignored entities conflicting when calculating root namespace -### 0.7.5-alpha.37 +## 0.7.5-alpha.37 * Mangle class methods when they conflict with an implemented interface -### 0.7.5-alpha.35 +## 0.7.5-alpha.35 * Fix #545: Using `Microsoft.FSharp` namespace -### 0.7.5-alpha.34 +## 0.7.5-alpha.34 * Add `import: selector->path->'T` to import expressions * Make arguments of JsConstructor statically typed * Add logs when compiling files for bundling -### 0.7.5-alpha.33 +## 0.7.5-alpha.33 * Fix default watch directories * Ignore interfaces -### 0.7.5-alpha.32 +## 0.7.5-alpha.32 * Compile scripts referenced as plugins * Apply Replace plugins to any call * Include in compilation JS files with relative paths -### 0.7.5-alpha.31 +## 0.7.5-alpha.31 * Fix #535: Script referenced entity replacements -### 0.7.5-alpha.30 +## 0.7.5-alpha.30 * Allow configuration of watching dirs -### 0.7.5-alpha.29 +## 0.7.5-alpha.29 * Fix infinite recursion when resolving generic parameters -### 0.7.5-alpha.28 +## 0.7.5-alpha.28 * More meaningful runtime representation of non-declared types -### 0.7.5-alpha.27 +## 0.7.5-alpha.27 * When inlining, assign arguments referenced more than once to a temp var * `Array.zeroCreate` fills non-numeric arrays with null -### 0.7.5-alpha.26 +## 0.7.5-alpha.26 * Resolve trait calls as normal method calls (check EmitAttribute, etc) -### 0.7.5-alpha.24 +## 0.7.5-alpha.24 * Fix mangled interfaces * Improve error messages -### 0.7.5-alpha.23 +## 0.7.5-alpha.23 * Add `MangleAttribute` to prevent conflicts with interfaces * Allow combination of `ImportAttribute` and `EmitAttribute` * Several fixes -### 0.7.5-alpha.22 +## 0.7.5-alpha.22 * Add catch-all for missing replacements when referencing types of the BCL or FSharp.Core * Omit `.js` extension again in imports to keep compatibility with Require.js -### 0.7.5-alpha.21 +## 0.7.5-alpha.21 * Don't print warnings in process.stderr (see #516) * Add `String/formatError` (see #519) * Add `.js` extension to `fable-core` and internal imports -### 0.7.5-alpha.19 +## 0.7.5-alpha.19 * Distribute fable-core with ES2015 (default) and UMD module formats -### 0.7.5-alpha.18 +## 0.7.5-alpha.18 * Don't deem interface setters as overloads (see #505) -### 0.7.5-alpha.17 +## 0.7.5-alpha.17 * Update FCS and use Forge to read .fsproj files (removes MSBuild dependency) * Bug fixes and optimizations -### 0.7.5-alpha.16 +## 0.7.5-alpha.16 * Add JsFunc and JsCons to Fable.Core.JsInterop -### 0.7.5-alpha.15 +## 0.7.5-alpha.15 * Use outDir to place the generated dll with .fsproj projects * Only emit warnings when generating dlls in verbose mode * Fix error when reading Rollup options -### 0.7.5-alpha.14 +## 0.7.5-alpha.14 * Fix errors in Fable JS API -### 0.7.5-alpha.12 +## 0.7.5-alpha.12 * Change `--bundle` option to `--rollup` * `--rollup` can accept an object (in fableconfig.json) with Rollup config * Improve plugin resolution for Babel and Rollup -### 0.7.5-alpha.11 +## 0.7.5-alpha.11 * Add a block scope to switch cases (see #483) -### 0.7.5-alpha.10 +## 0.7.5-alpha.10 * Fix invalid identifiers in top level members (see #482) * Generate `dll` also for `fsproj` files * Expose Fable library to JS API -### 0.7.5-alpha.9 +## 0.7.5-alpha.9 * Fix issues with bundling and `System.Exception` -### 0.7.5-alpha.8 +## 0.7.5-alpha.8 * Fix problems with `dll` generation -### 0.7.5-alpha.7 +## 0.7.5-alpha.7 * Add experimental `--dll` compiler option to generate assemblies -### 0.7.5-alpha.6 +## 0.7.5-alpha.6 * Fix path resolution when referencing assemblies -### 0.7.5-alpha.5 +## 0.7.5-alpha.5 * Fix partial patterns not returning any value (see #478) -### 0.7.5-alpha.4 +## 0.7.5-alpha.4 * Minor fixes -### 0.7.5-alpha.2 +## 0.7.5-alpha.2 * Resolve relative paths of referenced projects/dlls as if they were pointing to generated JS code from the fsproj/dll file @@ -730,34 +736,34 @@ * Always resolve relative paths in command line options with the directory from where fable is called -### 0.7.5-alpha.1 +## 0.7.5-alpha.1 * Fix prerelease semver. See: https://docs.npmjs.com/misc/semver#prerelease-tags -### 0.7.5-alpha +## 0.7.5-alpha * Add `typedefof<>`, `.IsGenericType`, `.GetGenericTypeDefinition` -### 0.7.4-alpha +## 0.7.4-alpha * Resolve import relative paths so they can be reached from `outDir` if they don't point to an internal file (see #472) -### 0.7.3-alpha +## 0.7.3-alpha * Add warning when creating references of types unknown at compile time -### 0.7.2-alpha +## 0.7.2-alpha * Convert functions to delegates when passed as arguments to EmitAttribute * Add warning when passing generic param to Serialize.ofJson/inflate -### 0.7.1-alpha +## 0.7.1-alpha * Add `--bundle` compiler option * Bring back JSON serialization with `$type` info -### 0.7.0-alpha +## 0.7.0-alpha * Add type info to JS constructors: cases (unions) and properties (records and classes) * Extend type references with generic info when calling `typeof` @@ -765,25 +771,25 @@ * Add `MutatingUpdateAttribute` to compile record updates as mutations * Add `EntryModuleAttribute` to mark assemblies as Fable libraries -### 0.6.15 +## 0.6.15 * Revert change from 0.6.14: ES6 modules automatically enable strict mode, so the directive is not needed -### 0.6.14 +## 0.6.14 * Add always "use strict" directive -### 0.6.12 +## 0.6.12 * Now fableconfig.json can be in JSON5 format (comments!) * Omit lambda argument when it's of unit type -### 0.6.11 +## 0.6.11 * Don't wait until "postbuild-once" script is finished (see #432) -### 0.6.9 +## 0.6.9 * Fix #431: Add --babelrc compiler option * Fix #432: Add "postbuild-once" script @@ -793,34 +799,34 @@ * Fix #439: IDE locking project file and preventing watch compilations * Change compilation defaults: module=commonjs & loose=true -### 0.6.7 +## 0.6.7 * Fix #416: Can't ifdef around a load directive * Fix List.unfold: PR #428 * Use reference hint paths for netcore: PR #423 -### 0.6.6 +## 0.6.6 * Support ResizeArray.FindAll: PR #412 -### 0.6.5 +## 0.6.5 * Support decimal (converted to JS number): PR #413 * Support recursive records: PR #417 -### 0.6.4 +## 0.6.4 * Fix #411: for .. downto -### 0.6.3 +## 0.6.3 * Fix watch compilation on Windows -### 0.6.2 +## 0.6.2 * Integer conversions (see #407) -### 0.6.1 +## 0.6.1 * Multiple bug fixes * Internal Fable AST additions @@ -828,25 +834,25 @@ * Use let/const when compiling value bindings to ES6 * Compile pattern matching with string or number literals as switch statements -### 0.5.11 +## 0.5.11 * Fix #382 (partially): Exclude files in "node_modules" when calculating the base directory of referenced dlls. -### 0.5.10 +## 0.5.10 * Fix #369: Extra blank lines when running postbuild script * Fix #375: Add warning when replacements change semantics (printf, Async.Start...) * Fix #377: Remove null args at the end of method/constructor calls also with macros -### 0.5.9 +## 0.5.9 * Fix type testing with Erased Unions * Erase assigments generated for tuple, record and union gets * Fix #370: Add warning when using unions or records with Dictionary (as keys) or HashSet * Internal cleanup -### 0.5.8 +## 0.5.8 * Use chokidar to watch for file changes * Fix calculation of relative paths with special characters (like "#") diff --git a/src/Fable.Core/Fable.Core.fsproj b/src/Fable.Core/Fable.Core.fsproj index a8f342ecb8..6f0fe8fd82 100644 --- a/src/Fable.Core/Fable.Core.fsproj +++ b/src/Fable.Core/Fable.Core.fsproj @@ -6,7 +6,7 @@ netstandard2.0 true 4.0.0 - 4.0.0 + true @@ -21,7 +21,7 @@ - + diff --git a/src/Fable.PublishUtils/RELEASE_NOTES.md b/src/Fable.PublishUtils/CHANGELOG.md similarity index 53% rename from src/Fable.PublishUtils/RELEASE_NOTES.md rename to src/Fable.PublishUtils/CHANGELOG.md index 4279033abc..ea19550b8c 100644 --- a/src/Fable.PublishUtils/RELEASE_NOTES.md +++ b/src/Fable.PublishUtils/CHANGELOG.md @@ -1,35 +1,43 @@ -### 2.4.0 +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased + +## 2.4.0 * Remove node compatibility and async methods -### 2.3.0 +## 2.3.0 * Publish as Nuget package -### 2.2.0 +## 2.2.0 * Add explicit `pushFableNuget` helper that uses FABLE_NUGET_KEY envVar @MangelMaxime -### 2.1.0 +## 2.1.0 * Publish symbols for Nuget packages @cartermp -### 2.0.0 +## 2.0.0 * Compatibility both with dotnet and nodejs -### 1.2.1 +## 1.2.1 * Update to Fable.Core 3.1.5 -### 1.2.0 +## 1.2.0 * Use npm token when publishing an npm package -### 1.1.1 +## 1.1.1 * Several additions for Fable build -### 1.0.5 +## 1.0.5 * First publish \ No newline at end of file diff --git a/src/Fable.PublishUtils/Fable.PublishUtils.fsproj b/src/Fable.PublishUtils/Fable.PublishUtils.fsproj index 8300b4bea8..c3063d9931 100644 --- a/src/Fable.PublishUtils/Fable.PublishUtils.fsproj +++ b/src/Fable.PublishUtils/Fable.PublishUtils.fsproj @@ -4,7 +4,6 @@ net6.0 true 2.4.0 - 2.4.0 diff --git a/src/fable-compiler-js/RELEASE_NOTES.md b/src/fable-compiler-js/CHANGELOG.md similarity index 66% rename from src/fable-compiler-js/RELEASE_NOTES.md rename to src/fable-compiler-js/CHANGELOG.md index 3021186a09..b7f9b95767 100644 --- a/src/fable-compiler-js/RELEASE_NOTES.md +++ b/src/fable-compiler-js/CHANGELOG.md @@ -1,133 +1,139 @@ -### Unreleased +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased * Remove `--typescript` options support, use `--lang ` instead -### 3.0.1 +## 3.0.1 * Reduced package dependencies -### 3.0.0 +## 3.0.0 * Nagareyama official release -### 3.0.0-rc +## 3.0.0-rc * Nagareyama RC -### 3.0.0-alpha +## 3.0.0-alpha * Nagareyama -### 1.3.1 +## 1.3.1 * Improve globbing support (by @ncave) -### 1.3.0 +## 1.3.0 * Add globbing support in fsproj -### 1.2.4 +## 1.2.4 * fable-metadata 1.4.0 -### 1.2.3 +## 1.2.3 * Update to fable-babel-plugins 2.3.0 -### 1.2.2 +## 1.2.2 * fable-metadata 1.3.0 -### 1.2.1 +## 1.2.1 * fable-standalone 1.3.0 * Removed perf_hooks dependency * Added support for source maps -### 1.2.0 +## 1.2.0 * Added NuGet packages support -### 1.1.1 +## 1.1.1 * Update to fable-metadata 1.2.0 & fable-standalone 1.2.3 -### 1.1.0 +## 1.1.0 * fable-standalone 1.2.0 * Define FABLE_COMPILER_JS constant -### 1.0.6 +## 1.0.6 * fable-standalone 1.1.8 -### 1.0.5 +## 1.0.5 * fable-standalone 1.1.5 -### 1.0.4 +## 1.0.4 * fable-metadata 1.1.2 * fable-standalone 1.1.4 -### 1.0.3 +## 1.0.3 * fable-metadata 1.0.1 * fable-standalone 1.0.3 -### 1.0.2 +## 1.0.2 * Fixed duplicate project references -### 1.0.1 +## 1.0.1 * Fixed fable-library reference * Added warn level and warnaserror options -### 1.0.0 +## 1.0.0 * Publish stable -### 1.0.0-beta-002 +## 1.0.0-beta-002 * Added project options parsing @ncave -### 1.0.0-beta-001 +## 1.0.0-beta-001 * Beta release @ncave -### 1.0.0-alpha-017 +## 1.0.0-alpha-017 * Update dependencies and other fixes -### 1.0.0-alpha-016 +## 1.0.0-alpha-016 * Add fable-standalone and fable-metadata dependencies -### 1.0.0-alpha-014 +## 1.0.0-alpha-014 * End process with exit code -1 if --run fails -### 1.0.0-alpha-012 +## 1.0.0-alpha-012 * Fix argument parsing and update deps -### 1.0.0-alpha-010 +## 1.0.0-alpha-010 * Fix #1674: paths on Windows @ncave -### 1.0.0-alpha-008 +## 1.0.0-alpha-008 * Add fable-babel-plugins -### 1.0.0-alpha-005 +## 1.0.0-alpha-005 * Fix Fable.Core method calls -### 1.0.0-alpha-003 +## 1.0.0-alpha-003 * Add `--run` option and other changes -### 1.0.0-alpha-002 +## 1.0.0-alpha-002 * First release as `fable-compiler-js` package diff --git a/src/fable-compiler-js/src/app.fs b/src/fable-compiler-js/src/app.fs index d372793430..9caedb785d 100644 --- a/src/fable-compiler-js/src/app.fs +++ b/src/fable-compiler-js/src/app.fs @@ -14,7 +14,7 @@ let inline getCurrentFilePath() = fileURLToPath(importMetaUrl()) let currentDirName = getCurrentFilePath() |> dirname let getMetadataDir(): string = join currentDirName "../../fable-metadata/lib/" -let getFableLibDir(): string = join currentDirName "../../../build/fable-library/" +let getFableLibDir(): string = join currentDirName "../../../temp/fable-library/" let getVersion(): string = ".next" let initFable (): Fable.Standalone.IFableManager = import "init" "../../fable-standalone/src/Main.fs.js" #else diff --git a/src/fable-library-py/fable_library/Fable.Library.csproj b/src/fable-library-py/fable_library/Fable.Library.csproj new file mode 100644 index 0000000000..0ed8766140 --- /dev/null +++ b/src/fable-library-py/fable_library/Fable.Library.csproj @@ -0,0 +1,35 @@ + + + + Library + netstandard2.0 + $(DefineConstants);FABLE_COMPILER + $(DefineConstants);FX_NO_BIGINT + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/fable-library/CHANGELOG.md b/src/fable-library/CHANGELOG.md new file mode 100644 index 0000000000..504086f892 --- /dev/null +++ b/src/fable-library/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased + +## 1.1.1 + +* Initialising the changelog diff --git a/src/fable-library/tsconfig.json b/src/fable-library/tsconfig.json index dd4987e216..bf843e96fc 100644 --- a/src/fable-library/tsconfig.json +++ b/src/fable-library/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { // "skipLibCheck": true, /* Basic Options */ - "outDir": "../../build/fable-library", /* Redirect output structure to the directory. */ + "outDir": "../../temp/fable-library", /* Redirect output structure to the directory. */ "target": "es2020", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ "module": "es2020", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ "allowJs": true, /* Allow javascript files to be compiled. */ diff --git a/src/fable-metadata/RELEASE_NOTES.md b/src/fable-metadata/CHANGELOG.md similarity index 60% rename from src/fable-metadata/RELEASE_NOTES.md rename to src/fable-metadata/CHANGELOG.md index 19f5959269..c05a4f724a 100644 --- a/src/fable-metadata/RELEASE_NOTES.md +++ b/src/fable-metadata/CHANGELOG.md @@ -1,50 +1,58 @@ -### 2.0.0 +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased + +## 2.0.0 * Updated Fable.Core to latest * Updated FSharp.Core to 5.0.0 * Updated .NET Core to 5.0.100 -### 1.5.0 +## 1.5.0 * Updated FSharp.Core to 4.7.2 * Updated .NET Core to 3.1.300 -### 1.4.0 +## 1.4.0 * Updated FSharp.Core to 4.7.1 * Updated .NET Core to 3.1.201 -### 1.3.0 +## 1.3.0 * Updated Fable.Core to 3.1.5 * Fix #1972 * Updated .NET Core to 3.1.101 -### 1.2.0 +## 1.2.0 * Update FSharp.Core to 4.7.0 * Add System.Net.Requests & System.Net.WebClient -### 1.1.2 +## 1.1.2 * Add Recharts to Fable.Repl.Lib -### 1.1.1 +## 1.1.1 * Fable.Repl.Lib -### 1.1.0 +## 1.1.0 * Fable.Core 3 and Fable.Browser.Dom 1.0 -### 1.0.1 +## 1.0.1 * .NET Core 2.2.105, FSharp.Core 4.6.2, Fable.Core 3.0.0-beta -### 1.0.0 +## 1.0.0 * Add System.Globalization -### 1.0.0-beta-002 +## 1.0.0-beta-002 * First publish \ No newline at end of file diff --git a/src/fable-standalone/RELEASE_NOTES.md b/src/fable-standalone/CHANGELOG.md similarity index 65% rename from src/fable-standalone/RELEASE_NOTES.md rename to src/fable-standalone/CHANGELOG.md index 0df428fba5..7777a10b3e 100644 --- a/src/fable-standalone/RELEASE_NOTES.md +++ b/src/fable-standalone/CHANGELOG.md @@ -1,180 +1,186 @@ -### Unreleased +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased * Remove `--typescript` options support, use `--lang ` instead -### 3.2.11 +## 3.2.11 * Enable Fable.Repl.Lib -### 3.1.12 +## 3.1.12 * Sync with Fable dotnet tool -### 3.0.0 +## 3.0.0 * Nagareyama official release -### 3.0.0-nagareyama-rc-008 +## 3.0.0-nagareyama-rc-008 * Fable.Transforms 3.0.0-nagareyama-rc-007 -### 1.3.18 +## 1.3.18 * fable-compiler 2.13.0 -### 1.3.17 +## 1.3.17 * fable-compiler 2.11.0 -### 1.3.16 +## 1.3.16 * fable-compiler 2.10.1 -### 1.3.15 +## 1.3.15 * fable-compiler 2.8.3 -### 1.3.14 +## 1.3.14 * fable-compiler 2.8.1 -### 1.3.13 +## 1.3.13 * fable-compiler 2.8.0 -### 1.3.12 +## 1.3.12 * fable-compiler 2.7.0 -### 1.3.11 +## 1.3.11 * fable-compiler 2.6.0 -### 1.3.10 +## 1.3.10 * fable-compiler 2.5.1 -### 1.3.9 +## 1.3.9 * fable-compiler 2.4.23 * Use fable-splitter and rollup to generate the bundles -### 1.3.8 +## 1.3.8 * fable-compiler 2.4.22 -### 1.3.8 +## 1.3.8 * fable-compiler 2.4.21 -### 1.3.7 +## 1.3.7 * fable-compiler 2.4.20 -### 1.3.6 +## 1.3.6 * fable-compiler 2.4.19 -### 1.3.5 +## 1.3.5 * fable-compiler 2.4.18 -### 1.3.4 +## 1.3.4 * fable-compiler 2.4.17 -### 1.3.3 +## 1.3.3 * fable-compiler 2.4.16 -### 1.3.2 +## 1.3.2 * fable-compiler 2.4.15 -### 1.3.1 +## 1.3.1 * fable-compiler 2.4.14 -### 1.3.0 +## 1.3.0 * Catch up with fable-compiler 2.4.11 -### 1.2.3 +## 1.2.3 * Include System.Net.Requests & System.Net.WebClient in references -### 1.2.2 +## 1.2.2 * Enable passing otherFSharpOptions -### 1.2.0 +## 1.2.0 * fable-compiler 2.4.2 -### 1.1.8 +## 1.1.8 * fable-compiler 2.3.25 -### 1.1.7 +## 1.1.7 * fable-compiler 2.3.24 -### 1.1.6 +## 1.1.6 * fable-compiler 2.3.21 -### 1.1.5 +## 1.1.5 * fable-compiler 2.3.19 -### 1.1.4 +## 1.1.4 * fable-compiler 2.3.12 -### 1.1.3 +## 1.1.3 * Don't crash REPL compilation on Babel errors -### 1.1.2 +## 1.1.2 * fable-compiler 2.3.10 -### 1.1.1 +## 1.1.1 * Update bundle and Worker dependencies -### 1.0.4 +## 1.0.4 * Fixed optimized patterns -### 1.0.3 +## 1.0.3 * fcs-fable sync -### 1.0.1 +## 1.0.1 * Decimal fixes -### 1.0.0 +## 1.0.0 * Publish stable -### 1.0.0-beta-009 +## 1.0.0-beta-009 * Anonymous records -### 1.0.0-beta-004 +## 1.0.0-beta-004 * Compile tests with fable-compiler-js @ncave -### 1.0.0-beta-003 +## 1.0.0-beta-003 * Fix web worker -### 1.0.0-beta-002 +## 1.0.0-beta-002 * Update sources and add worker -### 1.0.0-beta-001 +## 1.0.0-beta-001 * First publish diff --git a/src/fable-standalone/test/bench-compiler/app.fs b/src/fable-standalone/test/bench-compiler/app.fs index 87a70491f1..f2e82670c2 100644 --- a/src/fable-standalone/test/bench-compiler/app.fs +++ b/src/fable-standalone/test/bench-compiler/app.fs @@ -4,7 +4,7 @@ open Fable.Compiler.Platform open Fable.Compiler.ProjectParser let getMetadataDir(): string = __SOURCE_DIRECTORY__ + "/../../../fable-metadata/lib/" -let getFableLibDir(): string = __SOURCE_DIRECTORY__ + "/../../../../build/fable-library" +let getFableLibDir(): string = __SOURCE_DIRECTORY__ + "/../../../../temp/fable-library" let getVersion(): string = ".next" let initFable (): Fable.Standalone.IFableManager = Fable.Standalone.Main.init () @@ -260,7 +260,7 @@ let run opts projectFileName outDir = sourceMaps = (opts |> hasFlag "--sourceMaps") || (opts |> hasFlag "-s") typedArrays = opts |> tryFlag "--typedArrays" language = opts |> argValue ["--language"; "--lang"] - |> Option.map (fun _ -> "TypeScript")) + |> Option.map (fun _ -> "TypeScript") |> Option.defaultValue "JavaScript" printAst = opts |> hasFlag "--printAst" // watch = opts |> hasFlag "--watch" diff --git a/src/quicktest-rust/Cargo.lock b/src/quicktest-rust/Cargo.lock new file mode 100644 index 0000000000..03f5bb0842 --- /dev/null +++ b/src/quicktest-rust/Cargo.lock @@ -0,0 +1,409 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "fable_library_rust" +version = "0.1.0" +dependencies = [ + "chrono", + "getrandom", + "num-bigint", + "num-integer", + "num-traits", + "regex", + "rust_decimal", + "uuid", +] + +[[package]] +name = "fable_quicktest_rust" +version = "0.1.0" +dependencies = [ + "fable_library_rust", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.148" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "proc-macro2" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "rust_decimal" +version = "1.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c4216490d5a413bc6d10fa4742bd7d4955941d062c0ef873141d6b0e7b30fd" +dependencies = [ + "arrayvec", + "num-traits", +] + +[[package]] +name = "syn" +version = "2.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "uuid" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +dependencies = [ + "getrandom", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/src/quicktest-rust/Cargo.toml b/src/quicktest-rust/Cargo.toml index cff844029b..dd9243f458 100644 --- a/src/quicktest-rust/Cargo.toml +++ b/src/quicktest-rust/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] -fable_library_rust = { path = "../../build/fable-library-rust" } +fable_library_rust = { path = "../../temp/fable-library-rust" } diff --git a/src/quicktest-rust/target/.rustc_info.json b/src/quicktest-rust/target/.rustc_info.json new file mode 100644 index 0000000000..3e257d11e7 --- /dev/null +++ b/src/quicktest-rust/target/.rustc_info.json @@ -0,0 +1 @@ +{"rustc_fingerprint":14023084682591498796,"outputs":{"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.72.1 (d5c2e9c34 2023-09-13)\nbinary: rustc\ncommit-hash: d5c2e9c342b358556da91d61ed4133f6f50fc0c3\ncommit-date: 2023-09-13\nhost: aarch64-unknown-linux-gnu\nrelease: 1.72.1\nLLVM version: 16.0.5\n","stderr":""},"15729799797837862367":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/vscode/.rustup/toolchains/stable-aarch64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"neon\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}} \ No newline at end of file diff --git a/src/quicktest-rust/target/CACHEDIR.TAG b/src/quicktest-rust/target/CACHEDIR.TAG new file mode 100644 index 0000000000..20d7c319cd --- /dev/null +++ b/src/quicktest-rust/target/CACHEDIR.TAG @@ -0,0 +1,3 @@ +Signature: 8a477f597d28d172789f06886806bc55 +# This file is a cache directory tag created by cargo. +# For information about cache directory tags see https://bford.info/cachedir/ diff --git a/tests/Js/Main/TailCallTests.fs b/tests/Js/Main/TailCallTests.fs index 825425d44c..be25f1e726 100644 --- a/tests/Js/Main/TailCallTests.fs +++ b/tests/Js/Main/TailCallTests.fs @@ -128,6 +128,10 @@ type Element = let tests = testList "TailCalls" [ + // The tests belows only past in release mode + // Remove the compiler directive when + // https://github.com/fable-compiler/Fable/issues/3522 is fixed + #if RELEASE testCase "Tailcall works in tail position" <| fun () -> Issue3301.simple 100000 1 |> equal 100001 @@ -136,6 +140,7 @@ let tests = testCase "Tailcall works with tuple deconstruction" <| fun () -> Issue3301.tupleDeconstruction 100000 1 |> equal 100001 + #endif testCase "Recursive functions can be tailcall optimized" <| fun () -> factorial1 1 10 |> equal 3628800