diff --git a/.gitignore b/.gitignore index 7e3ea34..3069ebb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ /dll /lib +/defaultlib /__build +/__build.pre-triple /node_modules /tsconfig.json *.exe diff --git a/README.md b/README.md index 31d931b..f81b5b6 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,20 @@ build.bat # x64, release and debug, all three memory models build.bat release gc # x64, just that one ``` +Every build stages into one tree, `__build\defaultlib`, which a program takes with +`--default-lib-path=__build`. The binaries are split by target, as its LLVM triple names it +(arch, vendor, OS, environment), then by build mode, then by memory model: + +``` +__build\defaultlib\{lib,dll}\\\\\\\ + e.g. lib\x86_64\pc\windows\msvc\release\gc\TypeScriptDefaultLib.lib + lib\aarch64\unknown\linux\android\release\gc\libTypeScriptDefaultLib.a +__build\defaultlib\*.d.ts, generics\ ... (the declarations, shared by every build) +``` + +The scripts do not spell these folders out: they ask the compiler, which looks the library up +the same way (`tslang --print-default-lib-dir= [-mtriple=...] [--di] -mm=`). + For 32-bit Windows, set `TSLANG_ARCH=x86` before calling `build.bat` (it is an environment variable, not a positional argument, the same idiom as `TSLANG_TOOLCHAIN`): @@ -21,8 +35,8 @@ PowerShell) - since it is a session-wide environment variable, not a one-shot argument: a later plain `build.bat` or `tslang --install-default-lib` run in the same shell would otherwise silently build only the x86 tree. -This stages into `__build\defaultlib\{lib,dll}\x86\\\`, -alongside the existing x64 tree. It requires two things already built in the compiler +This stages into `__build\defaultlib\{lib,dll}\i386\pc\windows\msvc\\\`, +alongside the x64 tree. It requires two things already built in the compiler repo: - the x86 Boehm GC: `prepare_3rdParty.bat x86` in `TypeScriptCompiler`; @@ -39,9 +53,9 @@ scripts\build_android.bat # arm64-v8a and x86_64, release scripts\build_android.bat arm64-v8a release gc # just that one ``` -This builds for API level 29 (the lowest with `timespec_get`) into -`__build\android\\defaultlib\lib\\\`, one complete tree -per ABI. It needs a `tslang.exe` that can target Android (`TOOL_PATH`, default: the compiler's +This builds for API level 29 (the lowest with `timespec_get`) into the same tree as every +other target: `__build\defaultlib\lib\\unknown\linux\android\\\`. +It needs a `tslang.exe` that can target Android (`TOOL_PATH`, default: the compiler's release build tree). Android has no libcurl, so HTTP is `src\wrappers\http_stub.cpp`: `fetch()` throws. Only the static library is built: tslang links it into every Android binary. @@ -52,7 +66,7 @@ arm64-v8a under `gc`, a shared library an app loads, or an executable: ``` tslang --emit=dll -mtriple=aarch64-linux-android29 --opt -mm=gc ^ - --default-lib-path=__build\android\arm64-v8a ^ + --default-lib-path=__build ^ --gc-lib-path=\3rdParty\gc\android\arm64-v8a\release\lib ^ --tslang-lib-path=\__build\tslang-runtime\release\android\arm64-v8a ^ mylib.ts -o libmylib.so @@ -62,11 +76,12 @@ tslang --emit=dll -mtriple=aarch64-linux-android29 --opt -mm=gc ^ static default library, collector and libc++ are linked in, so it needs only Bionic's libc, libm and libdl. The triple has to carry the API level (`...-android29`). -The Windows release zip carries all of this prebuilt, per ABI (`arm64-v8a`, `x86_64`): the -default library in every mode and model, the collector and async runtime as release builds: +The Windows release zip carries all of this prebuilt for both ABIs (`arm64-v8a`, `x86_64`): the +default library in every mode and model, in its `defaultlib` tree beside the Windows one, and the +collector and async runtime as release builds: ``` -android\\defaultlib\... --default-lib-path=\android\ +defaultlib\... --default-lib-path= android\\lib\libgc.a --gc-lib-path=\android\\lib android\\lib\libTypeScriptAsyncRuntime.a --tslang-lib-path=\android\\lib ``` diff --git a/build.bat b/build.bat index dcf7ba8..28a68bf 100644 --- a/build.bat +++ b/build.bat @@ -13,14 +13,17 @@ @rem set TSLANG_ARCH=x86 @rem build.bat release gc @rem Like TSLANG_TOOLCHAIN, it is an environment variable, not a positional argument - -@rem %1/%2 stay "mode model" either way. x86 stages into lib\x86\... and dll\x86\..., -@rem alongside the x64 tree, and needs the x86 Boehm GC prerequisite (see README.md). +@rem %1/%2 stay "mode model" either way. x86 stages into lib\i386\pc\windows\msvc\... and +@rem dll\i386\..., alongside the x64 tree (lib\x86_64\pc\windows\msvc\...), and needs the x86 +@rem Boehm GC prerequisite (see README.md). @rem @rem Set TSLANG_DEBUG_CRT=/MT to build the debug archive against the release C runtime, for a @rem package whose runtime/collector/LLVM libraries are all release builds (the compiler's @rem release zip). The default, /MTd, matches a debug tslang build. See scripts\build_core.bat. @rem -@rem See tslang/include/TypeScript/Defines.h for the resulting layout. +@rem See tslang/include/TypeScript/Defines.h for the resulting layout: +@rem __build\defaultlib\{lib,dll}\\\\\{debug,release}\{gc,rc,none}, as +@rem tslang --print-default-lib-dir names each folder, and the declarations at the defaultlib root. if /I "%TSLANG_TOOLCHAIN%" == "llvm" ( set "BUILD_SCRIPT=scripts\build_llvm.bat" @@ -28,10 +31,12 @@ if /I "%TSLANG_TOOLCHAIN%" == "llvm" ( set "BUILD_SCRIPT=scripts\build_vs.bat" ) -if not "%2" == "" ( - cmd /c %BUILD_SCRIPT% %1 %2 - exit /b %errorlevel% -) +rem Not inside a ( ) block: there %errorlevel% is expanded when the block is read, before the +rem build runs, so a failed single-model build returned 0. +if "%2" == "" goto all_models +cmd /c %BUILD_SCRIPT% %1 %2 +exit /b %errorlevel% +:all_models if "%1" == "debug" ( call :build_all_models debug diff --git a/scripts/build.sh b/scripts/build.sh index 4e73892..72fceca 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -62,28 +62,39 @@ if [ -z "${TSLANG_LIB_PATH}" ]; then export TSLANG_LIB_PATH=$BUILD_PATH/$TOOL_NAME/ninja/$BUILD/lib fi -rm -rf dll/$BUILD/$MM lib/$BUILD/$MM -mkdir -p dll/$BUILD/$MM -mkdir -p lib/$BUILD/$MM -$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/io.cpp -o $OUTPUT/lib/$BUILD/$MM/io.o -$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/datetime.cpp -o $OUTPUT/lib/$BUILD/$MM/datetime.o -$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/regex.cpp -o $OUTPUT/lib/$BUILD/$MM/regex.o -$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/thread.cpp -o $OUTPUT/lib/$BUILD/$MM/thread.o -$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/http_linux.cpp -o $OUTPUT/lib/$BUILD/$MM/http_linux.o -$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/memory.cpp -o $OUTPUT/lib/$BUILD/$MM/memory.o - -$BIN_PATH/$TOOL_NAME $DBG_OPTS $MM_OPT --emit=obj --export=none --nowarn --no-default-lib $SRC/src/lib.linux.ts $PIC -o $OUTPUT/lib/$BUILD/$MM/lib.linux.o +# The output folders, from tslang itself (--print-default-lib-dir), with the same build and model +# flags it compiles with below: defaultlib/{lib,dll}//////, composed +# the way tslang later looks the library up (see tslang/include/TypeScript/Defines.h). Spelled out +# here, the two would drift apart. +LIB_OUT=$($BIN_PATH/$TOOL_NAME --print-default-lib-dir=lib $DBG_OPTS $MM_OPT) +DLL_OUT=$($BIN_PATH/$TOOL_NAME --print-default-lib-dir=dll $DBG_OPTS $MM_OPT) +if [ -z "$LIB_OUT" ] || [ -z "$DLL_OUT" ] ; then + echo "$BIN_PATH/$TOOL_NAME cannot name the output folders (--print-default-lib-dir): it predates the per-target layout, or is missing" + exit 1 +fi + +rm -rf $DLL_OUT $LIB_OUT +mkdir -p $DLL_OUT +mkdir -p $LIB_OUT +$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/io.cpp -o $OUTPUT/$LIB_OUT/io.o +$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/datetime.cpp -o $OUTPUT/$LIB_OUT/datetime.o +$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/regex.cpp -o $OUTPUT/$LIB_OUT/regex.o +$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/thread.cpp -o $OUTPUT/$LIB_OUT/thread.o +$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/http_linux.cpp -o $OUTPUT/$LIB_OUT/http_linux.o +$TOOL $DBG_GCC $CPP_FLAGS -c $SRC/src/wrappers/memory.cpp -o $OUTPUT/$LIB_OUT/memory.o + +$BIN_PATH/$TOOL_NAME $DBG_OPTS $MM_OPT --emit=obj --export=none --nowarn --no-default-lib $SRC/src/lib.linux.ts $PIC -o $OUTPUT/$LIB_OUT/lib.linux.o # Build Lib -$BIN_PATH/$TOOL_NAME $DBG_OPTS $MM_OPT --emit=obj --export=none --nowarn --no-default-lib $SRC/src/lib.ts $PIC -o $OUTPUT/lib/$BUILD/$MM/lib.o -$ARC rcs $OUTPUT/lib/$BUILD/$MM/libTypeScriptDefaultLibCore.a $OUTPUT/lib/$BUILD/$MM/lib.o $OUTPUT/lib/$BUILD/$MM/lib.linux.o $OUTPUT/lib/$BUILD/$MM/io.o $OUTPUT/lib/$BUILD/$MM/datetime.o $OUTPUT/lib/$BUILD/$MM/regex.o $OUTPUT/lib/$BUILD/$MM/thread.o $OUTPUT/lib/$BUILD/$MM/http_linux.o $OUTPUT/lib/$BUILD/$MM/memory.o +$BIN_PATH/$TOOL_NAME $DBG_OPTS $MM_OPT --emit=obj --export=none --nowarn --no-default-lib $SRC/src/lib.ts $PIC -o $OUTPUT/$LIB_OUT/lib.o +$ARC rcs $OUTPUT/$LIB_OUT/libTypeScriptDefaultLibCore.a $OUTPUT/$LIB_OUT/lib.o $OUTPUT/$LIB_OUT/lib.linux.o $OUTPUT/$LIB_OUT/io.o $OUTPUT/$LIB_OUT/datetime.o $OUTPUT/$LIB_OUT/regex.o $OUTPUT/$LIB_OUT/thread.o $OUTPUT/$LIB_OUT/http_linux.o $OUTPUT/$LIB_OUT/memory.o # A static archive cannot record its own dependencies on ELF (there is no ld.bfd equivalent of # the `#pragma comment(lib, ...)` http.cpp uses on Windows), so programs linking # -lTypeScriptDefaultLib failed with undefined curl_* references. libTypeScriptDefaultLib.a is # therefore a GNU linker script (as glibc's libc.so is) that pulls in the real archive plus the # system libraries it needs. The compiler keeps passing -lTypeScriptDefaultLib unchanged. -cat > $OUTPUT/lib/$BUILD/$MM/libTypeScriptDefaultLib.a < $OUTPUT/$LIB_OUT/libTypeScriptDefaultLib.a < $BUILD_LIB_PATH/COMPILER_VERSION.txt 2>&1 # cleanup intermediate object files -rm $OUTPUT/lib/$BUILD/$MM/*.o +rm $OUTPUT/$LIB_OUT/*.o -cp -r $SRC/dll/$BUILD/$MM/* $BUILD_LIB_PATH/dll/$BUILD/$MM/ -cp -r $SRC/lib/$BUILD/$MM/* $BUILD_LIB_PATH/lib/$BUILD/$MM/ +cp -r $SRC/$DLL_OUT/* $STAGE_PATH/$DLL_OUT/ +cp -r $SRC/$LIB_OUT/* $STAGE_PATH/$LIB_OUT/ cp -r $SRC/src/* $BUILD_LIB_PATH diff --git a/scripts/build_android.bat b/scripts/build_android.bat index 8daed45..77b7ff5 100644 --- a/scripts/build_android.bat +++ b/scripts/build_android.bat @@ -12,10 +12,11 @@ @rem TOOL_PATH the directory holding a tslang.exe with Android support (#506); defaults @rem to the compiler's release build tree next to this repository @rem -@rem Output, one complete default-library tree per ABI (a program compiled for that ABI takes -@rem --default-lib-path=__build\android\, the directory holding defaultlib\): -@rem __build\android\\defaultlib\lib\\\libTypeScriptDefaultLib.a -@rem __build\android\\defaultlib\*.d.ts ... +@rem Output, into the one default-library tree every target shares (a program compiled for Android +@rem takes --default-lib-path=__build, the directory holding defaultlib\, as any other does): +@rem __build\defaultlib\lib\\unknown\linux\android\\\libTypeScriptDefaultLib.a +@rem (arch: aarch64 for arm64-v8a, x86_64 for x86_64; tslang --print-default-lib-dir names it) +@rem __build\defaultlib\*.d.ts ... (shared by every target) @rem @rem Differences from build.sh: @rem - HTTP is src\wrappers\http_stub.cpp, not http_linux.cpp: libcurl is not part of Android, so @@ -93,9 +94,19 @@ set CXX="%NDK_BIN%\clang++.exe" --target=%TRIPLE% -fPIC -std=c++17 %DBG_CXX% set AR="%NDK_BIN%\llvm-ar.exe" set TSC=%TSLANG% -mtriple=%TRIPLE% -relocation-model=pic %DBG% -mm=%MM% --emit=obj --export=none --nowarn --no-default-lib -set OUT=%ROOT%\__build\android\%ABI%\defaultlib -set OBJ=%ROOT%\__build\android\%ABI%\obj-%MODE%-%MM% -set LIB_OUT=%OUT%\lib\%MODE%\%MM% +rem The archive's folder, from tslang itself with the flags it compiles with below, composed the +rem way tslang later looks it up (see tslang/include/TypeScript/Defines.h). +set LIB_DIR= +for /f "usebackq delims=" %%d in (`"%TOOL_PATH%\tslang.exe" --print-default-lib-dir=lib -mtriple=%TRIPLE% %DBG% -mm=%MM%`) do set "LIB_DIR=%%d" +if "%LIB_DIR%"=="" ( + echo %TSLANG% cannot name the output folder ^(--print-default-lib-dir^): it predates the per-target layout + exit /b 1 +) +set "LIB_DIR=%LIB_DIR:/=\%" + +set OUT=%ROOT%\__build\defaultlib +set OBJ=%ROOT%\__build\obj-android-%ABI%-%MODE%-%MM% +set LIB_OUT=%ROOT%\__build\%LIB_DIR% echo === %ABI% %MODE% %MM% if exist "%OBJ%" rd /s /q "%OBJ%" @@ -114,7 +125,8 @@ set OBJS="%OBJ%\lib.o" "%OBJ%\lib.linux.o" "%OBJ%\io.o" "%OBJ%\datetime.o" "%OBJ rd /s /q "%OBJ%" -rem the declarations a program compiled against this tree reads, and which compiler built it +rem the declarations a program compiled against this tree reads (the same for every target), and +rem which compiler built this ABI's archives, beside the other targets' records xcopy /E /I /Y /Q "%ROOT%\src" "%OUT%" > nul || exit /b 1 -%TSLANG% --version > "%OUT%\COMPILER_VERSION.txt" 2>&1 +%TSLANG% --version > "%OUT%\COMPILER_VERSION.android-%ABI%.txt" 2>&1 exit /b 0 diff --git a/scripts/build_core.bat b/scripts/build_core.bat index 9a8069b..9db23c4 100644 --- a/scripts/build_core.bat +++ b/scripts/build_core.bat @@ -30,13 +30,10 @@ if not "%ARCH%"=="x64" if not "%ARCH%"=="x86" ( echo "" exit /b 1 ) -rem ARCH_DIR nests the x86 tree one level under lib\ and dll\, next to today's flat -rem x64 layout (defaultlib/{lib,dll}/x86/...; see tslang/include/TypeScript/Defines.h). -rem TRIPLE_OPT tells tslang.exe to target i686 instead of its host x64. -set ARCH_DIR= +rem TRIPLE_OPT tells tslang.exe to target i686 instead of its host x64; it also picks the +rem target's tree in the output layout (see LIB_OUT below). set TRIPLE_OPT= if "%ARCH%"=="x86" ( - set ARCH_DIR=\x86 set TRIPLE_OPT=-mtriple=i686-pc-windows-msvc ) rem clang-cl targets x64 regardless of which vcvarsall was called, so an x86 LLVM build @@ -89,12 +86,6 @@ set MM=gc if not "%2"=="" set MM=%2 set MM_OPT=-mm=%MM% -rem One variable per output tree, set once here and used everywhere below (rd, md, /Fo, -rem -o, --obj, del, xcopy, the final exist check), so an x86 build never lands a file in -rem the x64 tree by way of a spot that forgot to add ARCH_DIR. -set LIB_OUT=lib%ARCH_DIR%\%BUILD%\%MM% -set DLL_OUT=dll%ARCH_DIR%\%BUILD%\%MM% - rem The DLL build below links TypeScriptAsyncRuntime.lib. TSLANG_LIB_PATH (set further rem down) defaults to the compiler's own build tree, which has no x86 subdirectory, so rem an x86 build points --tslang-lib-path at the separate tslang-runtime tree instead @@ -134,6 +125,31 @@ if "%TSLANG_LIB_PATH%"=="" ( set TSLANG_LIB_PATH=%BUILD_PATH%\%TOOL_NAME%\windows-msbuild%VER%-%BUILD%\lib ) +rem One variable per output tree, set once here and used everywhere below (rd, md, /Fo, +rem -o, --obj, del, xcopy, the final exist check), so an x86 build never lands a file in +rem the x64 tree by way of a spot that spells the path differently. tslang names the folders +rem (--print-default-lib-dir) with the same target, build and model flags it compiles with +rem below, composed the way it later looks the library up: +rem defaultlib\{lib,dll}\\\\\\ (see +rem tslang/include/TypeScript/Defines.h). Spelled out here, the two would drift apart. +set LIB_OUT= +set DLL_OUT= +for /f "usebackq delims=" %%d in (`"%TOOL_PATH%\%TOOL_NAME%.exe" --print-default-lib-dir=lib %TRIPLE_OPT% %DBG% %MM_OPT%`) do set "LIB_OUT=%%d" +for /f "usebackq delims=" %%d in (`"%TOOL_PATH%\%TOOL_NAME%.exe" --print-default-lib-dir=dll %TRIPLE_OPT% %DBG% %MM_OPT%`) do set "DLL_OUT=%%d" +if "%LIB_OUT%"=="" goto no_layout +if "%DLL_OUT%"=="" goto no_layout +set "LIB_OUT=%LIB_OUT:/=\%" +set "DLL_OUT=%DLL_OUT:/=\%" +goto layout_done +:no_layout +echo "" +echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +echo "XXX %TOOL_PATH%\%TOOL_NAME%.exe cannot name the output folders (--print-default-lib-dir): it predates the per-target layout, or is missing" +echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +echo "" +exit /b 1 +:layout_done + rem Check if Visual Studio is installed at default locations. Both toolchains need this: rem clang-cl compiles against the MSVC headers and the Windows SDK just as cl does. if not "%VSWHERE_PATH%"=="" goto vswhere_done @@ -232,14 +248,17 @@ del %OUTPUT%\%LIB_OUT%\thread.obj del %OUTPUT%\%LIB_OUT%\http.obj del %OUTPUT%\%LIB_OUT%\memory.obj -rem Stage into a single shared defaultlib tree with per-build subfolders under -rem dll\ and lib\. Only the current build's subfolders are refreshed so the -rem other mode (debug/release) staged by a separate run is preserved. -set BUILD_LIB_PATH=.\__build\defaultlib -rd /S /Q %BUILD_LIB_PATH%\%DLL_OUT% -rd /S /Q %BUILD_LIB_PATH%\%LIB_OUT% -md %BUILD_LIB_PATH%\%DLL_OUT% -md %BUILD_LIB_PATH%\%LIB_OUT% +rem Stage into a single shared defaultlib tree with per-target, per-build, per-model subfolders +rem under dll\ and lib\. Only the current build's subfolders are refreshed so the other +rem targets, modes and models staged by separate runs are preserved. LIB_OUT/DLL_OUT start +rem with defaultlib\, so they go under STAGE_PATH; the declarations go to its defaultlib\ root, +rem shared by every build. +set STAGE_PATH=.\__build +set BUILD_LIB_PATH=%STAGE_PATH%\defaultlib +rd /S /Q %STAGE_PATH%\%DLL_OUT% +rd /S /Q %STAGE_PATH%\%LIB_OUT% +md %STAGE_PATH%\%DLL_OUT% +md %STAGE_PATH%\%LIB_OUT% rem Record which compiler built this library, so a mismatch (e.g. after an ABI or rem codegen change in tslang) can be diagnosed from the artifact alone. The wrapper @@ -255,8 +274,8 @@ if "%ARCH%"=="x86" set VERSION_FILE=COMPILER_VERSION.x86.txt echo wrappers: %TSLANG_TOOLCHAIN% (%TSLANG_CC%, %TSLANG_AR%) >> %BUILD_LIB_PATH%\%VERSION_FILE% echo arch: %ARCH% >> %BUILD_LIB_PATH%\%VERSION_FILE% -xcopy %SRC%\%DLL_OUT% %BUILD_LIB_PATH%\%DLL_OUT% /h /i /c /k /e /r /y -xcopy %SRC%\%LIB_OUT% %BUILD_LIB_PATH%\%LIB_OUT% /h /i /c /k /e /r /y +xcopy %SRC%\%DLL_OUT% %STAGE_PATH%\%DLL_OUT% /h /i /c /k /e /r /y +xcopy %SRC%\%LIB_OUT% %STAGE_PATH%\%LIB_OUT% /h /i /c /k /e /r /y xcopy %SRC%\src\*.d.ts %BUILD_LIB_PATH% /h /c /k /e /r /y xcopy %SRC%\src\generics\*.ts %BUILD_LIB_PATH%\generics /h /c /k /e /r /y diff --git a/tests.ps1 b/tests.ps1 index a6aab4b..9dae9af 100644 --- a/tests.ps1 +++ b/tests.ps1 @@ -45,7 +45,7 @@ function Test([string]$config, [string]$mode, [string]$fileName) } else { $TOOL_PATH=$Env:TOOL_PATH $BUILD_PATH=$TOOL_PATH - # Compiled default lib is staged under .\__build\defaultlib\{dll,lib}\ + # Compiled default lib is staged under .\__build\defaultlib\{dll,lib}\\\ # relative to the DefaultLib repo root (the tests working directory). $DEFAULTLIB_BUILD_PATH=".\__build" } diff --git a/tests.sh b/tests.sh index 2825a2d..c98cd0e 100755 --- a/tests.sh +++ b/tests.sh @@ -49,7 +49,7 @@ function test_script() { BUILD_PATH="$TOOL_PATH" fi - # Compiled default lib is staged under ./__build/defaultlib/{dll,lib}/ + # Compiled default lib is staged under ./__build/defaultlib/{dll,lib}/// # relative to the DefaultLib repo root (the tests working directory). DEFAULTLIB_BUILD_PATH="./__build"