From 2f0877351d3db5bbc47054090c2bd2830e14af5c Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 13:57:09 -0700 Subject: [PATCH 01/19] feat: github actions for building --- .github/workflows/main.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..9945806 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,26 @@ +name: main + +on: + pull_request: + +jobs: + typos-check: + name: Typos Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: crate-ci/typos@cfe759ac8dd421e203cc293a373396fbc6fe0d4b # v1.22.7 + + formatting-check: + name: Formatting Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: greut/eclint-action@v0 + + build-script-windows: + name: 'build.cmd' + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - run: .\build.cmd From 4bca7ed6393484b3276afb31f6931352cbd74560 Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 13:57:45 -0700 Subject: [PATCH 02/19] chore: typos --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 97f42e6..7edc787 100755 --- a/build.sh +++ b/build.sh @@ -57,7 +57,7 @@ fi log_info "using libcxx build root $CPP2B_LIBCXX_BUILD_ROOT" if ! [ -d $CPP2B_LIBCXX_BUILD_ROOT ]; then - log_fatal "directory $CPP2B_LIBCXX_BUILD_ROOT does not exixt" + log_fatal "directory $CPP2B_LIBCXX_BUILD_ROOT does not exist" fi function ensure_gh_repo() { From 6bfac0ce15ea7c3d40da0c94492a8b1e7d554e77 Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:03:00 -0700 Subject: [PATCH 03/19] chore: formatting --- .editorconfig | 18 +++--- build.cmd | 82 ++++++++++++------------ build.sh | 168 +++++++++++++++++++++++++------------------------- 3 files changed, 136 insertions(+), 132 deletions(-) diff --git a/.editorconfig b/.editorconfig index ca93d68..eccc2b6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,7 +1,11 @@ -root = true - -[*] -end_of_line = lf -insert_final_newline = true -indent_style = tab -indent_size = 4 +root = true + +[*] +end_of_line = lf +insert_final_newline = true +indent_style = tab +indent_size = 4 + +[*.{sh,cmd}] +indent_size = 4 +indent_style = space diff --git a/build.cmd b/build.cmd index ccad0f5..ef289fe 100644 --- a/build.cmd +++ b/build.cmd @@ -18,40 +18,40 @@ if not exist dist\debug ( mkdir dist\debug ) set vswhere="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" for /f "usebackq tokens=*" %%i in (`%vswhere% -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do ( - set vs_install_dir=%%i + set vs_install_dir=%%i ) if exist "%vs_install_dir%\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt" ( - set /p vs_tools_version=<"%vs_install_dir%\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt" + set /p vs_tools_version=<"%vs_install_dir%\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt" ) if "%vs_tools_version%"=="" ( - echo ERROR: cannot find VC tools installed on your system - exit 1 + echo ERROR: cannot find VC tools installed on your system + exit 1 ) set vs_tools_dir=%vs_install_dir%\VC\Tools\MSVC\%vs_tools_version% if exist .cache\repos\cppfront\ ( - @rem TODO - report which cppfront version is being used + @rem TODO - report which cppfront version is being used ) else ( - git clone https://github.com/hsutter/cppfront.git .cache/repos/cppfront --quiet + git clone https://github.com/hsutter/cppfront.git .cache/repos/cppfront --quiet ) call "%vs_install_dir%\Common7\Tools\vsdevcmd.bat" /no_logo if not exist "%modules_dir%\std.ifc" ( - echo Compiling std module... - pushd %modules_dir% - cl /D"_CRT_SECURE_NO_WARNINGS=1" /std:c++latest /EHsc /nologo /W4 /MDd /c "%vs_tools_dir%\modules\std.ixx" - popd + echo Compiling std module... + pushd %modules_dir% + cl /D"_CRT_SECURE_NO_WARNINGS=1" /std:c++latest /EHsc /nologo /W4 /MDd /c "%vs_tools_dir%\modules\std.ixx" + popd ) if not exist "%modules_dir%\std.compat.ifc" ( - echo Compiling std.compat module... - pushd %modules_dir% - cl /std:c++latest /EHsc /nologo /W4 /MDd /c "%vs_tools_dir%\modules\std.compat.ixx" - popd + echo Compiling std.compat module... + pushd %modules_dir% + cl /std:c++latest /EHsc /nologo /W4 /MDd /c "%vs_tools_dir%\modules\std.compat.ixx" + popd ) if not exist "%root_dir%.cache\cpp2\source\_build" ( mkdir "%root_dir%.cache\cpp2\source\_build" ) @@ -72,37 +72,37 @@ endlocal pushd %modules_dir% cl /nologo ^ - /std:c++latest /W4 /MDd /EHsc ^ - /reference "%modules_dir%\std.ifc" ^ - /reference "%modules_dir%\std.compat.ifc" ^ - /c "%root_dir%.cache\cpp2\source\_build\cpp2b.ixx" > NUL + /std:c++latest /W4 /MDd /EHsc ^ + /reference "%modules_dir%\std.ifc" ^ + /reference "%modules_dir%\std.compat.ifc" ^ + /c "%root_dir%.cache\cpp2\source\_build\cpp2b.ixx" > NUL popd if %ERRORLEVEL% neq 0 ( - echo ERROR: failed to compile cpp2b module - exit %ERRORLEVEL% + echo ERROR: failed to compile cpp2b module + exit %ERRORLEVEL% ) echo INFO: compiling dylib module... pushd %modules_dir% cl /nologo ^ - /std:c++latest /W4 /MDd /EHsc ^ - /reference "%modules_dir%\std.ifc" ^ - /reference "%modules_dir%\std.compat.ifc" ^ - /c /interface /TP "%root_dir%src\dylib.cppm" > NUL + /std:c++latest /W4 /MDd /EHsc ^ + /reference "%modules_dir%\std.ifc" ^ + /reference "%modules_dir%\std.compat.ifc" ^ + /c /interface /TP "%root_dir%src\dylib.cppm" > NUL popd if %ERRORLEVEL% neq 0 ( - echo ERROR: failed to compile dylib module - exit %ERRORLEVEL% + echo ERROR: failed to compile dylib module + exit %ERRORLEVEL% ) if not exist %cppfront% ( - pushd .cache\repos\cppfront\source - echo INFO: compiling cppfront... - cl /nologo /std:c++latest /EHsc cppfront.cpp - xcopy cppfront.exe %tools_dir% /Y /Q - popd + pushd .cache\repos\cppfront\source + echo INFO: compiling cppfront... + cl /nologo /std:c++latest /EHsc cppfront.cpp + xcopy cppfront.exe %tools_dir% /Y /Q + popd ) if not exist "%root_dir%.cache/cpp2/source/src" ( mkdir "%root_dir%.cache/cpp2/source/src" ) @@ -113,16 +113,16 @@ if %ERRORLEVEL% neq 0 exit %ERRORLEVEL% cl /nologo "%root_dir%.cache/cpp2/source/src/main.cpp" ^ - /diagnostics:column /permissive- ^ - /reference "%modules_dir%\std.ifc" "%modules_dir%\std.obj" ^ - /reference "%modules_dir%\std.compat.ifc" "%modules_dir%\std.compat.obj" ^ - /reference "%modules_dir%\dylib.ifc" "%modules_dir%\dylib.obj" ^ - /reference "%modules_dir%\cpp2b.ifc" "%modules_dir%\cpp2b.obj" ^ - /std:c++latest /W4 /MDd /EHsc ^ - /DEBUG:FULL /Zi /FC ^ - -I"%cppfront_include_dir%" ^ - /Fe"%cpp2b_dist%" ^ - /Fd"%cpp2b_dist%.pdb" + /diagnostics:column /permissive- ^ + /reference "%modules_dir%\std.ifc" "%modules_dir%\std.obj" ^ + /reference "%modules_dir%\std.compat.ifc" "%modules_dir%\std.compat.obj" ^ + /reference "%modules_dir%\dylib.ifc" "%modules_dir%\dylib.obj" ^ + /reference "%modules_dir%\cpp2b.ifc" "%modules_dir%\cpp2b.obj" ^ + /std:c++latest /W4 /MDd /EHsc ^ + /DEBUG:FULL /Zi /FC ^ + -I"%cppfront_include_dir%" ^ + /Fe"%cpp2b_dist%" ^ + /Fd"%cpp2b_dist%.pdb" if %ERRORLEVEL% neq 0 exit %ERRORLEVEL% diff --git a/build.sh b/build.sh index 7edc787..66ff9e6 100755 --- a/build.sh +++ b/build.sh @@ -22,24 +22,24 @@ mkdir -p $ROOT_DIR/.cache/cpp2/source/_build CPP2B_COMPILER=${CC:=clang} function log_info() { - echo "INFO: $1" + echo "INFO: $1" } function log_error() { - echo "ERROR: $1" + echo "ERROR: $1" } function fatal() { - echo "FATAL: $1" - exit 1 + echo "FATAL: $1" + exit 1 } if ! [ -x "$(command -v $CPP2B_COMPILER)" ]; then - fatal "cannot find $CPP2B_COMPILER in your PATH" + fatal "cannot find $CPP2B_COMPILER in your PATH" fi if ! [[ $CPP2B_COMPILER == *"clang"* ]]; then - fatal "only clang is supported: detected $CPP2B_COMPILER" + fatal "only clang is supported: detected $CPP2B_COMPILER" fi COMPILER_VERSION=$($CPP2B_COMPILER --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n 1) @@ -49,37 +49,37 @@ if [ "$COMPILER_MAJOR_VERSION" -lt 18 ]; then fi if [[ -z "${CPP2B_LIBCXX_BUILD_ROOT}" ]]; then - log_error "libcxx with module support must be built from source" - log_error "follow these instructions https://github.com/llvm/llvm-project/blob/main/libcxx/docs/Modules.rst" - fatal "missing CPP2B_LIBCXX_BUILD_ROOT environment variable" + log_error "libcxx with module support must be built from source" + log_error "follow these instructions https://github.com/llvm/llvm-project/blob/main/libcxx/docs/Modules.rst" + fatal "missing CPP2B_LIBCXX_BUILD_ROOT environment variable" fi log_info "using libcxx build root $CPP2B_LIBCXX_BUILD_ROOT" if ! [ -d $CPP2B_LIBCXX_BUILD_ROOT ]; then - log_fatal "directory $CPP2B_LIBCXX_BUILD_ROOT does not exist" + log_fatal "directory $CPP2B_LIBCXX_BUILD_ROOT does not exist" fi function ensure_gh_repo() { - local repo=$1 - local repo_path=$ROOT_DIR/.cache/repos/$repo - if ! [ -d $repo_path ]; then - mkdir -p $repo_path - git clone --quiet --depth=1 --filter=blob:none --sparse https://github.com/$repo $repo_path - fi + local repo=$1 + local repo_path=$ROOT_DIR/.cache/repos/$repo + if ! [ -d $repo_path ]; then + mkdir -p $repo_path + git clone --quiet --depth=1 --filter=blob:none --sparse https://github.com/$repo $repo_path + fi } function ensure_gh_repo_subdir() { - local repo=$1 - local repo_path=$ROOT_DIR/.cache/repos/$repo - local repo_subdir=$2 - local repo_subdir_path=$repo_path/$repo_subdir - if ! [ -d $repo_subdir_path ]; then - cd $repo_path - log_info "checking out repo $repo/$reposubdir" - git sparse-checkout add $repo_subdir - cd $ROOT_DIR - fi + local repo=$1 + local repo_path=$ROOT_DIR/.cache/repos/$repo + local repo_subdir=$2 + local repo_subdir_path=$repo_path/$repo_subdir + if ! [ -d $repo_subdir_path ]; then + cd $repo_path + log_info "checking out repo $repo/$reposubdir" + git sparse-checkout add $repo_subdir + cd $ROOT_DIR + fi } ensure_gh_repo "hsutter/cppfront" @@ -93,26 +93,26 @@ LIBCXX_INCLUDE_DIR=$CPP2B_LIBCXX_BUILD_ROOT/include LIBCXX_LIB_DIR=$CPP2B_LIBCXX_BUILD_ROOT/lib if ! [ -x $CPPFRONT ]; then - log_info "compiling cppfront..." - cd $ROOT_DIR/.cache/repos/hsutter/cppfront/source - $CPP2B_COMPILER -lstdc++ -lc -lm -fuse-ld=lld -std=c++23 cppfront.cpp -o $CPPFRONT - cd $ROOT_DIR + log_info "compiling cppfront..." + cd $ROOT_DIR/.cache/repos/hsutter/cppfront/source + $CPP2B_COMPILER -lstdc++ -lc -lm -fuse-ld=lld -std=c++23 cppfront.cpp -o $CPPFRONT + cd $ROOT_DIR fi if ! [ -f $MODULES_DIR/std.pcm ]; then - cd $LIBCXX_MODULES_DIR/c++/v1 - log_info "compiling std module..." - - $CPP2B_COMPILER \ - -stdlib=libc++ \ - -std=c++23 \ - -fexperimental-library \ - -isystem $LIBCXX_INCLUDE_DIR/c++/v1 \ - -Wno-reserved-module-identifier \ - std.cppm \ - --precompile -o $MODULES_DIR/std.pcm - - cd $ROOT_DIR + cd $LIBCXX_MODULES_DIR/c++/v1 + log_info "compiling std module..." + + $CPP2B_COMPILER \ + -stdlib=libc++ \ + -std=c++23 \ + -fexperimental-library \ + -isystem $LIBCXX_INCLUDE_DIR/c++/v1 \ + -Wno-reserved-module-identifier \ + std.cppm \ + --precompile -o $MODULES_DIR/std.pcm + + cd $ROOT_DIR fi if ! [ -f $MODULES_DIR/std.compat.pcm ]; then @@ -133,60 +133,60 @@ if ! [ -f $MODULES_DIR/std.compat.pcm ]; then fi if ! [ -f $MODULES_DIR/dylib.pcm ]; then - cd $LIBCXX_MODULES_DIR/c++/v1 - log_info "compiling dylib module..." + cd $LIBCXX_MODULES_DIR/c++/v1 + log_info "compiling dylib module..." + + $CPP2B_COMPILER \ + -stdlib=libc++ \ + -std=c++23 \ + -fexperimental-library \ + -isystem $LIBCXX_INCLUDE_DIR/c++/v1 \ + -fprebuilt-module-path=$MODULES_DIR \ + "$ROOT_DIR/src/dylib.cppm" \ + --precompile -o $MODULES_DIR/dylib.pcm - $CPP2B_COMPILER \ - -stdlib=libc++ \ - -std=c++23 \ - -fexperimental-library \ - -isystem $LIBCXX_INCLUDE_DIR/c++/v1 \ - -fprebuilt-module-path=$MODULES_DIR \ - "$ROOT_DIR/src/dylib.cppm" \ - --precompile -o $MODULES_DIR/dylib.pcm - - cd $ROOT_DIR + cd $ROOT_DIR fi log_info "compiling cpp2b module..." if [ -f "$ROOT_DIR/.cache/cpp2/source/_build/cpp2b.cppm" ]; then - rm "$ROOT_DIR/.cache/cpp2/source/_build/cpp2b.cppm" + rm "$ROOT_DIR/.cache/cpp2/source/_build/cpp2b.cppm" fi cat "$ROOT_DIR/share/cpp2b.cppm.tpl" | sed "s\`@CPP2B_PROJECT_ROOT@\`$ROOT_DIR\`g" > "$ROOT_DIR/.cache/cpp2/source/_build/cpp2b.cppm" -$CPP2B_COMPILER \ - -stdlib=libc++ \ - -std=c++23 \ - -fexperimental-library \ - -isystem $LIBCXX_INCLUDE_DIR/c++/v1 \ - -fprebuilt-module-path=$MODULES_DIR \ - "$ROOT_DIR/.cache/cpp2/source/_build/cpp2b.cppm" \ - --precompile -o $MODULES_DIR/cpp2b.pcm +$CPP2B_COMPILER \ + -stdlib=libc++ \ + -std=c++23 \ + -fexperimental-library \ + -isystem $LIBCXX_INCLUDE_DIR/c++/v1 \ + -fprebuilt-module-path=$MODULES_DIR \ + "$ROOT_DIR/.cache/cpp2/source/_build/cpp2b.cppm" \ + --precompile -o $MODULES_DIR/cpp2b.pcm log_info "running cppfront..." $CPPFRONT src/main.cpp2 -pure -import-std -l -format-colon-errors -o "$ROOT_DIR/.cache/cpp2/source/src/main.cpp" log_info "compiling..." -$CPP2B_COMPILER \ - -stdlib=libc++ \ - "$MODULES_DIR/cpp2b.pcm" \ - "$MODULES_DIR/dylib.pcm" \ - "$MODULES_DIR/std.compat.pcm" \ - "$ROOT_DIR/.cache/cpp2/source/src/main.cpp" \ - -std=c++23 \ - -fexperimental-library \ - -Wno-unused-result \ - -Wno-deprecated-declarations \ - -fprebuilt-module-path=$MODULES_DIR \ - -L$LIBCXX_LIB_DIR \ - -isystem $LIBCXX_INCLUDE_DIR/c++/v1 \ - -lc++abi \ - -lc++ \ - -lm \ - -static \ - -fuse-ld=lld \ - -I"$CPPFRONT_INCLUDE_DIR" \ - -o $CPP2B_DIST +$CPP2B_COMPILER \ + -stdlib=libc++ \ + "$MODULES_DIR/cpp2b.pcm" \ + "$MODULES_DIR/dylib.pcm" \ + "$MODULES_DIR/std.compat.pcm" \ + "$ROOT_DIR/.cache/cpp2/source/src/main.cpp" \ + -std=c++23 \ + -fexperimental-library \ + -Wno-unused-result \ + -Wno-deprecated-declarations \ + -fprebuilt-module-path=$MODULES_DIR \ + -L$LIBCXX_LIB_DIR \ + -isystem $LIBCXX_INCLUDE_DIR/c++/v1 \ + -lc++abi \ + -lc++ \ + -lm \ + -static \ + -fuse-ld=lld \ + -I"$CPPFRONT_INCLUDE_DIR" \ + -o $CPP2B_DIST log_info "successfully built $CPP2B_DIST" From 8156aec519cd9200ca187a40f224f35c63919c7b Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:08:49 -0700 Subject: [PATCH 04/19] chore: formatting for yml --- .editorconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.editorconfig b/.editorconfig index eccc2b6..37d3b10 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,3 +9,7 @@ indent_size = 4 [*.{sh,cmd}] indent_size = 4 indent_style = space + +[*.yml] +indent_size = 2 +indent_style = space From b1b02ac107513acd0e8586f5aa3b3cf0f738277b Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:08:58 -0700 Subject: [PATCH 05/19] feat: build self windows --- .github/workflows/main.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9945806..5660ed2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,3 +24,20 @@ jobs: steps: - uses: actions/checkout@v4 - run: .\build.cmd + - uses: actions/upload-artifact@v4 + with: + name: cpp2b.exe + path: dist/debug/cpp2b.exe + if-no-files-found: error + retention-days: 0 + + build-self-windows: + name: 'build self (windows)' + needs: build-script-windows + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: 'cpp2b.exe' + - run: .\cpp2b.exe build + From d71862a1427f3c37dc9d1b25a5448845c197cbe6 Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:10:46 -0700 Subject: [PATCH 06/19] fix: add missing runs-on --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5660ed2..0d26849 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -34,6 +34,7 @@ jobs: build-self-windows: name: 'build self (windows)' needs: build-script-windows + runs-on: windows-latest steps: - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 From 6a104d987408833fe4ebc1660877ede536c14730 Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:16:07 -0700 Subject: [PATCH 07/19] feat: build self with self with self --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0d26849..1cb8448 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -41,4 +41,5 @@ jobs: with: name: 'cpp2b.exe' - run: .\cpp2b.exe build + - run: .\cache\cpp2\bin\cpp2b.exe build From 34acec2a49c2e6bf8a1386429b1a0c210846f267 Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:19:03 -0700 Subject: [PATCH 08/19] chore: formatting --- .clang-format | 3 + build.sh | 4 +- run.cmd | 20 +- share/cpp2b.build.def | 6 +- share/run_with_msvc_env.cmd | 8 +- src/dylib.cppm | 487 +++++++++++++++++++----------------- 6 files changed, 276 insertions(+), 252 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..053f31e --- /dev/null +++ b/.clang-format @@ -0,0 +1,3 @@ +UseTab: Always +IndentWidth: 4 +TabWidth: 4 diff --git a/build.sh b/build.sh index 66ff9e6..34d557d 100755 --- a/build.sh +++ b/build.sh @@ -112,7 +112,7 @@ if ! [ -f $MODULES_DIR/std.pcm ]; then std.cppm \ --precompile -o $MODULES_DIR/std.pcm - cd $ROOT_DIR + cd $ROOT_DIR fi if ! [ -f $MODULES_DIR/std.compat.pcm ]; then @@ -129,7 +129,7 @@ if ! [ -f $MODULES_DIR/std.compat.pcm ]; then std.compat.cppm \ --precompile -o $MODULES_DIR/std.compat.pcm - cd $ROOT_DIR + cd $ROOT_DIR fi if ! [ -f $MODULES_DIR/dylib.pcm ]; then diff --git a/run.cmd b/run.cmd index 45c3753..b568234 100644 --- a/run.cmd +++ b/run.cmd @@ -1,10 +1,10 @@ -@echo off - -set root_dir=%~dp0 -set cpp2b_dist=%~dp0dist\debug\cpp2b - -if not exist "%cpp2b_dist%.exe" ( - call %~dp0build.cmd -) - -"%cpp2b_dist%.exe" %* +@echo off + +set root_dir=%~dp0 +set cpp2b_dist=%~dp0dist\debug\cpp2b + +if not exist "%cpp2b_dist%.exe" ( + call %~dp0build.cmd +) + +"%cpp2b_dist%.exe" %* diff --git a/share/cpp2b.build.def b/share/cpp2b.build.def index e1bf057..9baa60b 100644 --- a/share/cpp2b.build.def +++ b/share/cpp2b.build.def @@ -1,4 +1,4 @@ EXPORTS - cpp2b::detail::build::create - cpp2b::detail::build::destroy - cpp2b::detail::build::binary_name + cpp2b::detail::build::create + cpp2b::detail::build::destroy + cpp2b::detail::build::binary_name diff --git a/share/run_with_msvc_env.cmd b/share/run_with_msvc_env.cmd index d736b2b..994a43b 100644 --- a/share/run_with_msvc_env.cmd +++ b/share/run_with_msvc_env.cmd @@ -3,16 +3,16 @@ set vswhere="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" for /f "usebackq tokens=*" %%i in (`%vswhere% -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do ( - set vs_install_dir=%%i + set vs_install_dir=%%i ) if exist "%vs_install_dir%\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt" ( - set /p vs_tools_version=<"%vs_install_dir%\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt" + set /p vs_tools_version=<"%vs_install_dir%\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt" ) if "%vs_tools_version%"=="" ( - echo ERROR: cannot find VC tools installed on your system - exit 1 + echo ERROR: cannot find VC tools installed on your system + exit 1 ) set vs_tools_dir=%vs_install_dir%\VC\Tools\MSVC\%vs_tools_version% diff --git a/src/dylib.cppm b/src/dylib.cppm index 03ad5a0..04ab811 100644 --- a/src/dylib.cppm +++ b/src/dylib.cppm @@ -3,7 +3,7 @@ * @version 2.2.1 * @brief C++ cross-platform wrapper around dynamic loading of shared libraries * @link https://github.com/martin-olivier/dylib - * + * * @author Martin Olivier * @copyright (c) 2023 Martin Olivier * @@ -54,252 +54,273 @@ import std; * allowing the access of symbols like functions or global variables */ export class dylib { -public: - struct filename_components { - static constexpr const char *prefix = DYLIB_WIN_OTHER("", "lib"); - static constexpr const char *suffix = DYLIB_WIN_MAC_OTHER(".dll", ".dylib", ".so"); - }; - using native_handle_type = DYLIB_WIN_OTHER(HINSTANCE, void *); - using native_symbol_type = DYLIB_WIN_OTHER(FARPROC, void *); - - static_assert(std::is_pointer::value, "Expecting HINSTANCE to be a pointer"); - static_assert(std::is_pointer::value, "Expecting FARPROC to be a pointer"); - - static constexpr bool add_filename_decorations = true; - static constexpr bool no_filename_decorations = false; - - /** - * This exception is raised when a library fails to load or a symbol fails to resolve - */ - class exception : public std::runtime_error { - using std::runtime_error::runtime_error; - }; - - /** - * This exception is raised when a library fails to load - */ - class load_error : public exception { - using exception::exception; - }; - - /** - * This exception is raised when a symbol fails to resolve - */ - class symbol_error : public exception { - using exception::exception; - }; - - dylib(const dylib&) = delete; - dylib& operator=(const dylib&) = delete; - - dylib(dylib &&other) noexcept : m_handle(other.m_handle) { - other.m_handle = nullptr; - } - - dylib& operator=(dylib &&other) noexcept { - if (this != &other) - std::swap(m_handle, other.m_handle); - return *this; - } - - /** - * Loads a dynamic library - * - * @throws `dylib::load_error` if the library could not be opened (including - * the case of the library file not being found) - * @throws `std::invalid_argument` if the arguments are null - * - * @param dir_path the directory path where the dynamic library is located - * @param name the name of the dynamic library to load - * @param decorations adds OS-specific decorations to the library name - */ - ///@{ - dylib(const char *dir_path, const char *lib_name, bool decorations = add_filename_decorations) { - if (!dir_path) - throw std::invalid_argument("The directory path is null"); - if (!lib_name) - throw std::invalid_argument("The library name is null"); - - std::string final_name = lib_name; - std::string final_path = dir_path; - - if (decorations) - final_name = filename_components::prefix + final_name + filename_components::suffix; - - if (!final_path.empty() && final_path.find_last_of('/') != final_path.size() - 1) - final_path += '/'; - - m_handle = open((final_path + final_name).c_str()); - - if (!m_handle) - throw load_error("Could not load library \"" + final_path + final_name + "\"\n" + get_error_description()); - } - - dylib(const std::string &dir_path, const std::string &lib_name, bool decorations = add_filename_decorations) - : dylib(dir_path.c_str(), lib_name.c_str(), decorations) {} - - dylib(const std::string &dir_path, const char *lib_name, bool decorations = add_filename_decorations) - : dylib(dir_path.c_str(), lib_name, decorations) {} - - dylib(const char *dir_path, const std::string &lib_name, bool decorations = add_filename_decorations) - : dylib(dir_path, lib_name.c_str(), decorations) {} - - explicit dylib(const std::string &lib_name, bool decorations = add_filename_decorations) - : dylib("", lib_name.c_str(), decorations) {} - - explicit dylib(const char *lib_name, bool decorations = add_filename_decorations) - : dylib("", lib_name, decorations) {} - - explicit dylib(const std::filesystem::path &lib_path) - : dylib("", lib_path.string().c_str(), no_filename_decorations) {} - - dylib(const std::filesystem::path &dir_path, const std::string &lib_name, bool decorations = add_filename_decorations) - : dylib(dir_path.string().c_str(), lib_name.c_str(), decorations) {} - - dylib(const std::filesystem::path &dir_path, const char *lib_name, bool decorations = add_filename_decorations) - : dylib(dir_path.string().c_str(), lib_name, decorations) {} - ///@} - - ~dylib() { - if (m_handle) - close(m_handle); - } - - /** - * Get a symbol from the currently loaded dynamic library - * - * @throws `dylib::symbol_error` if the symbol could not be found - * @throws `std::invalid_argument` if the argument or library handle is null - * - * @param symbol_name the symbol name to lookup - * - * @return a pointer to the requested symbol - */ - native_symbol_type get_symbol(const char *symbol_name) const { - if (!symbol_name) - throw std::invalid_argument("The symbol name to lookup is null"); - if (!m_handle) - throw std::logic_error("The dynamic library handle is null. This object may have been moved from."); - - auto symbol = locate_symbol(m_handle, symbol_name); - - if (symbol == nullptr) - throw symbol_error("Could not get symbol \"" + std::string(symbol_name) + "\"\n" + get_error_description()); - return symbol; - } - - native_symbol_type get_symbol(const std::string &symbol_name) const { - return get_symbol(symbol_name.c_str()); - } - - /** - * Get a function from the currently loaded dynamic library - * - * @throws `dylib::symbol_error` if the function could not be found - * @throws `std::invalid_argument` if the argument is null - * - * @tparam T the function type, e.g., `double(int, int)` - * @param symbol_name the function name to lookup - * - * @return a pointer to the requested function - */ - template - T *get_function(const char *symbol_name) const { + public: + struct filename_components { + static constexpr const char *prefix = DYLIB_WIN_OTHER("", "lib"); + static constexpr const char *suffix = + DYLIB_WIN_MAC_OTHER(".dll", ".dylib", ".so"); + }; + using native_handle_type = DYLIB_WIN_OTHER(HINSTANCE, void *); + using native_symbol_type = DYLIB_WIN_OTHER(FARPROC, void *); + + static_assert(std::is_pointer::value, + "Expecting HINSTANCE to be a pointer"); + static_assert(std::is_pointer::value, + "Expecting FARPROC to be a pointer"); + + static constexpr bool add_filename_decorations = true; + static constexpr bool no_filename_decorations = false; + + /** + * This exception is raised when a library fails to load or a symbol fails + * to resolve + */ + class exception : public std::runtime_error { + using std::runtime_error::runtime_error; + }; + + /** + * This exception is raised when a library fails to load + */ + class load_error : public exception { + using exception::exception; + }; + + /** + * This exception is raised when a symbol fails to resolve + */ + class symbol_error : public exception { + using exception::exception; + }; + + dylib(const dylib &) = delete; + dylib &operator=(const dylib &) = delete; + + dylib(dylib &&other) noexcept : m_handle(other.m_handle) { + other.m_handle = nullptr; + } + + dylib &operator=(dylib &&other) noexcept { + if (this != &other) + std::swap(m_handle, other.m_handle); + return *this; + } + + /** + * Loads a dynamic library + * + * @throws `dylib::load_error` if the library could not be opened + * (including the case of the library file not being found) + * @throws `std::invalid_argument` if the arguments are null + * + * @param dir_path the directory path where the dynamic library is located + * @param name the name of the dynamic library to load + * @param decorations adds OS-specific decorations to the library name + */ + ///@{ + dylib(const char *dir_path, const char *lib_name, + bool decorations = add_filename_decorations) { + if (!dir_path) + throw std::invalid_argument("The directory path is null"); + if (!lib_name) + throw std::invalid_argument("The library name is null"); + + std::string final_name = lib_name; + std::string final_path = dir_path; + + if (decorations) + final_name = filename_components::prefix + final_name + + filename_components::suffix; + + if (!final_path.empty() && + final_path.find_last_of('/') != final_path.size() - 1) + final_path += '/'; + + m_handle = open((final_path + final_name).c_str()); + + if (!m_handle) + throw load_error("Could not load library \"" + final_path + + final_name + "\"\n" + get_error_description()); + } + + dylib(const std::string &dir_path, const std::string &lib_name, + bool decorations = add_filename_decorations) + : dylib(dir_path.c_str(), lib_name.c_str(), decorations) {} + + dylib(const std::string &dir_path, const char *lib_name, + bool decorations = add_filename_decorations) + : dylib(dir_path.c_str(), lib_name, decorations) {} + + dylib(const char *dir_path, const std::string &lib_name, + bool decorations = add_filename_decorations) + : dylib(dir_path, lib_name.c_str(), decorations) {} + + explicit dylib(const std::string &lib_name, + bool decorations = add_filename_decorations) + : dylib("", lib_name.c_str(), decorations) {} + + explicit dylib(const char *lib_name, + bool decorations = add_filename_decorations) + : dylib("", lib_name, decorations) {} + + explicit dylib(const std::filesystem::path &lib_path) + : dylib("", lib_path.string().c_str(), no_filename_decorations) {} + + dylib(const std::filesystem::path &dir_path, const std::string &lib_name, + bool decorations = add_filename_decorations) + : dylib(dir_path.string().c_str(), lib_name.c_str(), decorations) {} + + dylib(const std::filesystem::path &dir_path, const char *lib_name, + bool decorations = add_filename_decorations) + : dylib(dir_path.string().c_str(), lib_name, decorations) {} + ///@} + + ~dylib() { + if (m_handle) + close(m_handle); + } + + /** + * Get a symbol from the currently loaded dynamic library + * + * @throws `dylib::symbol_error` if the symbol could not be found + * @throws `std::invalid_argument` if the argument or library handle is + * null + * + * @param symbol_name the symbol name to lookup + * + * @return a pointer to the requested symbol + */ + native_symbol_type get_symbol(const char *symbol_name) const { + if (!symbol_name) + throw std::invalid_argument("The symbol name to lookup is null"); + if (!m_handle) + throw std::logic_error( + "The dynamic library handle is null. This object " + "may have been moved from."); + + auto symbol = locate_symbol(m_handle, symbol_name); + + if (symbol == nullptr) + throw symbol_error("Could not get symbol \"" + + std::string(symbol_name) + "\"\n" + + get_error_description()); + return symbol; + } + + native_symbol_type get_symbol(const std::string &symbol_name) const { + return get_symbol(symbol_name.c_str()); + } + + /** + * Get a function from the currently loaded dynamic library + * + * @throws `dylib::symbol_error` if the function could not be found + * @throws `std::invalid_argument` if the argument is null + * + * @tparam T the function type, e.g., `double(int, int)` + * @param symbol_name the function name to lookup + * + * @return a pointer to the requested function + */ + template T *get_function(const char *symbol_name) const { #if (defined(__GNUC__) && __GNUC__ >= 8) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-function-type" #endif - return reinterpret_cast(get_symbol(symbol_name)); + return reinterpret_cast(get_symbol(symbol_name)); #if (defined(__GNUC__) && __GNUC__ >= 8) #pragma GCC diagnostic pop #endif - } - - template - T *get_function(const std::string &symbol_name) const { - return get_function(symbol_name.c_str()); - } - - /** - * Get a variable from the currently loaded dynamic library - * - * @throws `dylib::symbol_error` if the variable could not be found - * @throws `std::invalid_argument` if the argument is null - * - * @tparam T the variable type - * @param symbol_name the variable name to lookup - * - * @return a reference to the requested variable - */ - template - T &get_variable(const char *symbol_name) const { - return *reinterpret_cast(get_symbol(symbol_name)); - } - - template - T &get_variable(const std::string &symbol_name) const { - return get_variable(symbol_name.c_str()); - } - - /** - * Check if a symbol exists in the currently loaded dynamic library. - * This method will return false if no dynamic library is currently loaded - * or if the symbol name is nullptr - * - * @param symbol_name the symbol name to look for - * - * @return true if the symbol exists in the dynamic library, false otherwise - */ - bool has_symbol(const char *symbol_name) const noexcept { - if (!m_handle || !symbol_name) - return false; - return locate_symbol(m_handle, symbol_name) != nullptr; - } - - bool has_symbol(const std::string &symbol) const noexcept { - return has_symbol(symbol.c_str()); - } - - /** - * @return the dynamic library handle - */ - native_handle_type native_handle() noexcept { - return m_handle; - } - -protected: - native_handle_type m_handle{nullptr}; - - static native_handle_type open(const char *path) noexcept { + } + + template + T *get_function(const std::string &symbol_name) const { + return get_function(symbol_name.c_str()); + } + + /** + * Get a variable from the currently loaded dynamic library + * + * @throws `dylib::symbol_error` if the variable could not be found + * @throws `std::invalid_argument` if the argument is null + * + * @tparam T the variable type + * @param symbol_name the variable name to lookup + * + * @return a reference to the requested variable + */ + template T &get_variable(const char *symbol_name) const { + return *reinterpret_cast(get_symbol(symbol_name)); + } + + template + T &get_variable(const std::string &symbol_name) const { + return get_variable(symbol_name.c_str()); + } + + /** + * Check if a symbol exists in the currently loaded dynamic library. + * This method will return false if no dynamic library is currently loaded + * or if the symbol name is nullptr + * + * @param symbol_name the symbol name to look for + * + * @return true if the symbol exists in the dynamic library, false + * otherwise + */ + bool has_symbol(const char *symbol_name) const noexcept { + if (!m_handle || !symbol_name) + return false; + return locate_symbol(m_handle, symbol_name) != nullptr; + } + + bool has_symbol(const std::string &symbol) const noexcept { + return has_symbol(symbol.c_str()); + } + + /** + * @return the dynamic library handle + */ + native_handle_type native_handle() noexcept { return m_handle; } + + protected: + native_handle_type m_handle{nullptr}; + + static native_handle_type open(const char *path) noexcept { #if (defined(_WIN32) || defined(_WIN64)) - return LoadLibraryA(path); + return LoadLibraryA(path); #else - return dlopen(path, RTLD_NOW | RTLD_LOCAL); + return dlopen(path, RTLD_NOW | RTLD_LOCAL); #endif - } + } - static native_symbol_type locate_symbol(native_handle_type lib, const char *name) noexcept { - return DYLIB_WIN_OTHER(GetProcAddress, dlsym)(lib, name); - } + static native_symbol_type locate_symbol(native_handle_type lib, + const char *name) noexcept { + return DYLIB_WIN_OTHER(GetProcAddress, dlsym)(lib, name); + } - static void close(native_handle_type lib) noexcept { - DYLIB_WIN_OTHER(FreeLibrary, dlclose)(lib); - } + static void close(native_handle_type lib) noexcept { + DYLIB_WIN_OTHER(FreeLibrary, dlclose)(lib); + } - static std::string get_error_description() noexcept { + static std::string get_error_description() noexcept { #if (defined(_WIN32) || defined(_WIN64)) - constexpr const size_t BUF_SIZE = 512; - const auto error_code = GetLastError(); - if (!error_code) - return "No error reported by GetLastError"; - char description[BUF_SIZE]; - const auto lang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); - const DWORD length = - FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, error_code, lang, description, BUF_SIZE, nullptr); - return (length == 0) ? "Unknown error (FormatMessage failed)" : description; + constexpr const size_t BUF_SIZE = 512; + const auto error_code = GetLastError(); + if (!error_code) + return "No error reported by GetLastError"; + char description[BUF_SIZE]; + const auto lang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); + const DWORD length = + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, error_code, + lang, description, BUF_SIZE, nullptr); + return (length == 0) ? "Unknown error (FormatMessage failed)" + : description; #else - const auto description = dlerror(); - return (description == nullptr) ? "No error reported by dlerror" : description; + const auto description = dlerror(); + return (description == nullptr) ? "No error reported by dlerror" + : description; #endif - } + } }; From 9d3657c509d7c60752d4c57da05901beaaaa2f3d Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:20:02 -0700 Subject: [PATCH 09/19] chore: restore dylib formatting --- src/dylib.cppm | 487 +++++++++++++++++++++++-------------------------- 1 file changed, 233 insertions(+), 254 deletions(-) diff --git a/src/dylib.cppm b/src/dylib.cppm index 04ab811..03ad5a0 100644 --- a/src/dylib.cppm +++ b/src/dylib.cppm @@ -3,7 +3,7 @@ * @version 2.2.1 * @brief C++ cross-platform wrapper around dynamic loading of shared libraries * @link https://github.com/martin-olivier/dylib - * + * * @author Martin Olivier * @copyright (c) 2023 Martin Olivier * @@ -54,273 +54,252 @@ import std; * allowing the access of symbols like functions or global variables */ export class dylib { - public: - struct filename_components { - static constexpr const char *prefix = DYLIB_WIN_OTHER("", "lib"); - static constexpr const char *suffix = - DYLIB_WIN_MAC_OTHER(".dll", ".dylib", ".so"); - }; - using native_handle_type = DYLIB_WIN_OTHER(HINSTANCE, void *); - using native_symbol_type = DYLIB_WIN_OTHER(FARPROC, void *); - - static_assert(std::is_pointer::value, - "Expecting HINSTANCE to be a pointer"); - static_assert(std::is_pointer::value, - "Expecting FARPROC to be a pointer"); - - static constexpr bool add_filename_decorations = true; - static constexpr bool no_filename_decorations = false; - - /** - * This exception is raised when a library fails to load or a symbol fails - * to resolve - */ - class exception : public std::runtime_error { - using std::runtime_error::runtime_error; - }; - - /** - * This exception is raised when a library fails to load - */ - class load_error : public exception { - using exception::exception; - }; - - /** - * This exception is raised when a symbol fails to resolve - */ - class symbol_error : public exception { - using exception::exception; - }; - - dylib(const dylib &) = delete; - dylib &operator=(const dylib &) = delete; - - dylib(dylib &&other) noexcept : m_handle(other.m_handle) { - other.m_handle = nullptr; - } - - dylib &operator=(dylib &&other) noexcept { - if (this != &other) - std::swap(m_handle, other.m_handle); - return *this; - } - - /** - * Loads a dynamic library - * - * @throws `dylib::load_error` if the library could not be opened - * (including the case of the library file not being found) - * @throws `std::invalid_argument` if the arguments are null - * - * @param dir_path the directory path where the dynamic library is located - * @param name the name of the dynamic library to load - * @param decorations adds OS-specific decorations to the library name - */ - ///@{ - dylib(const char *dir_path, const char *lib_name, - bool decorations = add_filename_decorations) { - if (!dir_path) - throw std::invalid_argument("The directory path is null"); - if (!lib_name) - throw std::invalid_argument("The library name is null"); - - std::string final_name = lib_name; - std::string final_path = dir_path; - - if (decorations) - final_name = filename_components::prefix + final_name + - filename_components::suffix; - - if (!final_path.empty() && - final_path.find_last_of('/') != final_path.size() - 1) - final_path += '/'; - - m_handle = open((final_path + final_name).c_str()); - - if (!m_handle) - throw load_error("Could not load library \"" + final_path + - final_name + "\"\n" + get_error_description()); - } - - dylib(const std::string &dir_path, const std::string &lib_name, - bool decorations = add_filename_decorations) - : dylib(dir_path.c_str(), lib_name.c_str(), decorations) {} - - dylib(const std::string &dir_path, const char *lib_name, - bool decorations = add_filename_decorations) - : dylib(dir_path.c_str(), lib_name, decorations) {} - - dylib(const char *dir_path, const std::string &lib_name, - bool decorations = add_filename_decorations) - : dylib(dir_path, lib_name.c_str(), decorations) {} - - explicit dylib(const std::string &lib_name, - bool decorations = add_filename_decorations) - : dylib("", lib_name.c_str(), decorations) {} - - explicit dylib(const char *lib_name, - bool decorations = add_filename_decorations) - : dylib("", lib_name, decorations) {} - - explicit dylib(const std::filesystem::path &lib_path) - : dylib("", lib_path.string().c_str(), no_filename_decorations) {} - - dylib(const std::filesystem::path &dir_path, const std::string &lib_name, - bool decorations = add_filename_decorations) - : dylib(dir_path.string().c_str(), lib_name.c_str(), decorations) {} - - dylib(const std::filesystem::path &dir_path, const char *lib_name, - bool decorations = add_filename_decorations) - : dylib(dir_path.string().c_str(), lib_name, decorations) {} - ///@} - - ~dylib() { - if (m_handle) - close(m_handle); - } - - /** - * Get a symbol from the currently loaded dynamic library - * - * @throws `dylib::symbol_error` if the symbol could not be found - * @throws `std::invalid_argument` if the argument or library handle is - * null - * - * @param symbol_name the symbol name to lookup - * - * @return a pointer to the requested symbol - */ - native_symbol_type get_symbol(const char *symbol_name) const { - if (!symbol_name) - throw std::invalid_argument("The symbol name to lookup is null"); - if (!m_handle) - throw std::logic_error( - "The dynamic library handle is null. This object " - "may have been moved from."); - - auto symbol = locate_symbol(m_handle, symbol_name); - - if (symbol == nullptr) - throw symbol_error("Could not get symbol \"" + - std::string(symbol_name) + "\"\n" + - get_error_description()); - return symbol; - } - - native_symbol_type get_symbol(const std::string &symbol_name) const { - return get_symbol(symbol_name.c_str()); - } - - /** - * Get a function from the currently loaded dynamic library - * - * @throws `dylib::symbol_error` if the function could not be found - * @throws `std::invalid_argument` if the argument is null - * - * @tparam T the function type, e.g., `double(int, int)` - * @param symbol_name the function name to lookup - * - * @return a pointer to the requested function - */ - template T *get_function(const char *symbol_name) const { +public: + struct filename_components { + static constexpr const char *prefix = DYLIB_WIN_OTHER("", "lib"); + static constexpr const char *suffix = DYLIB_WIN_MAC_OTHER(".dll", ".dylib", ".so"); + }; + using native_handle_type = DYLIB_WIN_OTHER(HINSTANCE, void *); + using native_symbol_type = DYLIB_WIN_OTHER(FARPROC, void *); + + static_assert(std::is_pointer::value, "Expecting HINSTANCE to be a pointer"); + static_assert(std::is_pointer::value, "Expecting FARPROC to be a pointer"); + + static constexpr bool add_filename_decorations = true; + static constexpr bool no_filename_decorations = false; + + /** + * This exception is raised when a library fails to load or a symbol fails to resolve + */ + class exception : public std::runtime_error { + using std::runtime_error::runtime_error; + }; + + /** + * This exception is raised when a library fails to load + */ + class load_error : public exception { + using exception::exception; + }; + + /** + * This exception is raised when a symbol fails to resolve + */ + class symbol_error : public exception { + using exception::exception; + }; + + dylib(const dylib&) = delete; + dylib& operator=(const dylib&) = delete; + + dylib(dylib &&other) noexcept : m_handle(other.m_handle) { + other.m_handle = nullptr; + } + + dylib& operator=(dylib &&other) noexcept { + if (this != &other) + std::swap(m_handle, other.m_handle); + return *this; + } + + /** + * Loads a dynamic library + * + * @throws `dylib::load_error` if the library could not be opened (including + * the case of the library file not being found) + * @throws `std::invalid_argument` if the arguments are null + * + * @param dir_path the directory path where the dynamic library is located + * @param name the name of the dynamic library to load + * @param decorations adds OS-specific decorations to the library name + */ + ///@{ + dylib(const char *dir_path, const char *lib_name, bool decorations = add_filename_decorations) { + if (!dir_path) + throw std::invalid_argument("The directory path is null"); + if (!lib_name) + throw std::invalid_argument("The library name is null"); + + std::string final_name = lib_name; + std::string final_path = dir_path; + + if (decorations) + final_name = filename_components::prefix + final_name + filename_components::suffix; + + if (!final_path.empty() && final_path.find_last_of('/') != final_path.size() - 1) + final_path += '/'; + + m_handle = open((final_path + final_name).c_str()); + + if (!m_handle) + throw load_error("Could not load library \"" + final_path + final_name + "\"\n" + get_error_description()); + } + + dylib(const std::string &dir_path, const std::string &lib_name, bool decorations = add_filename_decorations) + : dylib(dir_path.c_str(), lib_name.c_str(), decorations) {} + + dylib(const std::string &dir_path, const char *lib_name, bool decorations = add_filename_decorations) + : dylib(dir_path.c_str(), lib_name, decorations) {} + + dylib(const char *dir_path, const std::string &lib_name, bool decorations = add_filename_decorations) + : dylib(dir_path, lib_name.c_str(), decorations) {} + + explicit dylib(const std::string &lib_name, bool decorations = add_filename_decorations) + : dylib("", lib_name.c_str(), decorations) {} + + explicit dylib(const char *lib_name, bool decorations = add_filename_decorations) + : dylib("", lib_name, decorations) {} + + explicit dylib(const std::filesystem::path &lib_path) + : dylib("", lib_path.string().c_str(), no_filename_decorations) {} + + dylib(const std::filesystem::path &dir_path, const std::string &lib_name, bool decorations = add_filename_decorations) + : dylib(dir_path.string().c_str(), lib_name.c_str(), decorations) {} + + dylib(const std::filesystem::path &dir_path, const char *lib_name, bool decorations = add_filename_decorations) + : dylib(dir_path.string().c_str(), lib_name, decorations) {} + ///@} + + ~dylib() { + if (m_handle) + close(m_handle); + } + + /** + * Get a symbol from the currently loaded dynamic library + * + * @throws `dylib::symbol_error` if the symbol could not be found + * @throws `std::invalid_argument` if the argument or library handle is null + * + * @param symbol_name the symbol name to lookup + * + * @return a pointer to the requested symbol + */ + native_symbol_type get_symbol(const char *symbol_name) const { + if (!symbol_name) + throw std::invalid_argument("The symbol name to lookup is null"); + if (!m_handle) + throw std::logic_error("The dynamic library handle is null. This object may have been moved from."); + + auto symbol = locate_symbol(m_handle, symbol_name); + + if (symbol == nullptr) + throw symbol_error("Could not get symbol \"" + std::string(symbol_name) + "\"\n" + get_error_description()); + return symbol; + } + + native_symbol_type get_symbol(const std::string &symbol_name) const { + return get_symbol(symbol_name.c_str()); + } + + /** + * Get a function from the currently loaded dynamic library + * + * @throws `dylib::symbol_error` if the function could not be found + * @throws `std::invalid_argument` if the argument is null + * + * @tparam T the function type, e.g., `double(int, int)` + * @param symbol_name the function name to lookup + * + * @return a pointer to the requested function + */ + template + T *get_function(const char *symbol_name) const { #if (defined(__GNUC__) && __GNUC__ >= 8) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-function-type" #endif - return reinterpret_cast(get_symbol(symbol_name)); + return reinterpret_cast(get_symbol(symbol_name)); #if (defined(__GNUC__) && __GNUC__ >= 8) #pragma GCC diagnostic pop #endif - } - - template - T *get_function(const std::string &symbol_name) const { - return get_function(symbol_name.c_str()); - } - - /** - * Get a variable from the currently loaded dynamic library - * - * @throws `dylib::symbol_error` if the variable could not be found - * @throws `std::invalid_argument` if the argument is null - * - * @tparam T the variable type - * @param symbol_name the variable name to lookup - * - * @return a reference to the requested variable - */ - template T &get_variable(const char *symbol_name) const { - return *reinterpret_cast(get_symbol(symbol_name)); - } - - template - T &get_variable(const std::string &symbol_name) const { - return get_variable(symbol_name.c_str()); - } - - /** - * Check if a symbol exists in the currently loaded dynamic library. - * This method will return false if no dynamic library is currently loaded - * or if the symbol name is nullptr - * - * @param symbol_name the symbol name to look for - * - * @return true if the symbol exists in the dynamic library, false - * otherwise - */ - bool has_symbol(const char *symbol_name) const noexcept { - if (!m_handle || !symbol_name) - return false; - return locate_symbol(m_handle, symbol_name) != nullptr; - } - - bool has_symbol(const std::string &symbol) const noexcept { - return has_symbol(symbol.c_str()); - } - - /** - * @return the dynamic library handle - */ - native_handle_type native_handle() noexcept { return m_handle; } - - protected: - native_handle_type m_handle{nullptr}; - - static native_handle_type open(const char *path) noexcept { + } + + template + T *get_function(const std::string &symbol_name) const { + return get_function(symbol_name.c_str()); + } + + /** + * Get a variable from the currently loaded dynamic library + * + * @throws `dylib::symbol_error` if the variable could not be found + * @throws `std::invalid_argument` if the argument is null + * + * @tparam T the variable type + * @param symbol_name the variable name to lookup + * + * @return a reference to the requested variable + */ + template + T &get_variable(const char *symbol_name) const { + return *reinterpret_cast(get_symbol(symbol_name)); + } + + template + T &get_variable(const std::string &symbol_name) const { + return get_variable(symbol_name.c_str()); + } + + /** + * Check if a symbol exists in the currently loaded dynamic library. + * This method will return false if no dynamic library is currently loaded + * or if the symbol name is nullptr + * + * @param symbol_name the symbol name to look for + * + * @return true if the symbol exists in the dynamic library, false otherwise + */ + bool has_symbol(const char *symbol_name) const noexcept { + if (!m_handle || !symbol_name) + return false; + return locate_symbol(m_handle, symbol_name) != nullptr; + } + + bool has_symbol(const std::string &symbol) const noexcept { + return has_symbol(symbol.c_str()); + } + + /** + * @return the dynamic library handle + */ + native_handle_type native_handle() noexcept { + return m_handle; + } + +protected: + native_handle_type m_handle{nullptr}; + + static native_handle_type open(const char *path) noexcept { #if (defined(_WIN32) || defined(_WIN64)) - return LoadLibraryA(path); + return LoadLibraryA(path); #else - return dlopen(path, RTLD_NOW | RTLD_LOCAL); + return dlopen(path, RTLD_NOW | RTLD_LOCAL); #endif - } + } - static native_symbol_type locate_symbol(native_handle_type lib, - const char *name) noexcept { - return DYLIB_WIN_OTHER(GetProcAddress, dlsym)(lib, name); - } + static native_symbol_type locate_symbol(native_handle_type lib, const char *name) noexcept { + return DYLIB_WIN_OTHER(GetProcAddress, dlsym)(lib, name); + } - static void close(native_handle_type lib) noexcept { - DYLIB_WIN_OTHER(FreeLibrary, dlclose)(lib); - } + static void close(native_handle_type lib) noexcept { + DYLIB_WIN_OTHER(FreeLibrary, dlclose)(lib); + } - static std::string get_error_description() noexcept { + static std::string get_error_description() noexcept { #if (defined(_WIN32) || defined(_WIN64)) - constexpr const size_t BUF_SIZE = 512; - const auto error_code = GetLastError(); - if (!error_code) - return "No error reported by GetLastError"; - char description[BUF_SIZE]; - const auto lang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); - const DWORD length = - FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, error_code, - lang, description, BUF_SIZE, nullptr); - return (length == 0) ? "Unknown error (FormatMessage failed)" - : description; + constexpr const size_t BUF_SIZE = 512; + const auto error_code = GetLastError(); + if (!error_code) + return "No error reported by GetLastError"; + char description[BUF_SIZE]; + const auto lang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); + const DWORD length = + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, error_code, lang, description, BUF_SIZE, nullptr); + return (length == 0) ? "Unknown error (FormatMessage failed)" : description; #else - const auto description = dlerror(); - return (description == nullptr) ? "No error reported by dlerror" - : description; + const auto description = dlerror(); + return (description == nullptr) ? "No error reported by dlerror" : description; #endif - } + } }; From 430e3a8849acdd071d1a7655f531059a74a465fd Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:20:57 -0700 Subject: [PATCH 10/19] chore: remove formatting --- .github/workflows/main.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1cb8448..58a693a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,13 +11,6 @@ jobs: - uses: actions/checkout@v4 - uses: crate-ci/typos@cfe759ac8dd421e203cc293a373396fbc6fe0d4b # v1.22.7 - formatting-check: - name: Formatting Check - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: greut/eclint-action@v0 - build-script-windows: name: 'build.cmd' runs-on: windows-latest From 2c2a2fd6be937e40bfefeab4bcfb2810c3ad90e5 Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:22:09 -0700 Subject: [PATCH 11/19] chore: undo some formatting changes --- share/cpp2b.build.def | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/share/cpp2b.build.def b/share/cpp2b.build.def index 9baa60b..e1bf057 100644 --- a/share/cpp2b.build.def +++ b/share/cpp2b.build.def @@ -1,4 +1,4 @@ EXPORTS - cpp2b::detail::build::create - cpp2b::detail::build::destroy - cpp2b::detail::build::binary_name + cpp2b::detail::build::create + cpp2b::detail::build::destroy + cpp2b::detail::build::binary_name From 9af1148323de96c843472a6fb3ddf7241f070229 Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:25:25 -0700 Subject: [PATCH 12/19] feat: add build script linux --- .github/workflows/main.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 58a693a..d839f1a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -34,5 +34,18 @@ jobs: with: name: 'cpp2b.exe' - run: .\cpp2b.exe build - - run: .\cache\cpp2\bin\cpp2b.exe build + - run: .\.cache\cpp2\bin\cpp2b.exe build + + build-script-linux: + name: 'build.sh' + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: CC=clang-18 ./build.sh + - uses: actions/upload-artifact@v4 + with: + name: cpp2b + path: dist/debug/cpp2b + if-no-files-found: error + retention-days: 0 From bcc0951672b5cfd433df14ba44822b78de52ef06 Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:45:49 -0700 Subject: [PATCH 13/19] feat: compile libcxx in gh actions --- .github/workflows/main.yml | 46 +++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d839f1a..ea14809 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,6 +3,11 @@ name: main on: pull_request: +env: + # libcxx version to match whats already installed + # https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md + LLVM_VERSION: '18.1.3' + jobs: typos-check: name: Typos Check @@ -40,12 +45,41 @@ jobs: name: 'build.sh' runs-on: ubuntu-24.04 steps: + - run: sudo apt-get install libclang-dev ninja-build -y + - uses: actions/cache@v4 + id: libcxx_with_modules + with: + path: /tmp/llvm-project/build + key: libcxx-${{ env.LLVM_VERSION }} + - name: compiling libcxx ${{ env.LLVM_VERSION }} with modules + if: steps.libcxx_with_modules.outputs.cache-hit != 'true' + run: | + git clone --depth 1 --branch llvmorg-${{ env.LLVM_VERSION }} https://github.com/llvm/llvm-project.git /tmp/llvm-project + cd /tmp/llvm-project + mkdir build + CC=clang-18 CXX=clang++-18 cmake -G Ninja -S runtimes -B build -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" + ninja -C build + - uses: actions/checkout@v4 + - run: CPP2B_LIBCXX_BUILD_ROOT=/tmp/llvm-project/build CC=clang-18 ./build.sh + - uses: actions/upload-artifact@v4 + with: + name: cpp2b + path: dist/debug/cpp2b + if-no-files-found: error + retention-days: 0 + + build-self-linux: + name: 'build self (linux)' + needs: build-script-linux + runs-on: ubuntu-24.04 + steps: + - uses: actions/cache/restore@v4 + with: + path: /tmp/llvm-project/build + key: libcxx-${{ env.LLVM_VERSION }} - uses: actions/checkout@v4 - - run: CC=clang-18 ./build.sh - - uses: actions/upload-artifact@v4 + - uses: actions/download-artifact@v4 with: name: cpp2b - path: dist/debug/cpp2b - if-no-files-found: error - retention-days: 0 - + - run: CPP2B_LIBCXX_BUILD_ROOT=/tmp/llvm-project/build ./cpp2b build + - run: CPP2B_LIBCXX_BUILD_ROOT=/tmp/llvm-project/build ./.cache/cpp2/bin/cpp2b build From 1f0efd10c7fb760214959fedc5fc8ae263d5e4ba Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:48:03 -0700 Subject: [PATCH 14/19] fix: copy self so that we can re-build ourself --- .github/workflows/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ea14809..4b2b69b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -39,7 +39,8 @@ jobs: with: name: 'cpp2b.exe' - run: .\cpp2b.exe build - - run: .\.cache\cpp2\bin\cpp2b.exe build + - run: Copy-Item .\.cache\cpp2\bin\cpp2b.exe -Destination .\cpp2b-self.exe + - run: .\cpp2b-self.exe build build-script-linux: name: 'build.sh' From 2e1f4b11e324ceaf270be1cfd9d6e9e89a600e19 Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:48:55 -0700 Subject: [PATCH 15/19] fix: yaml issue with key --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4b2b69b..b04466f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -51,7 +51,7 @@ jobs: id: libcxx_with_modules with: path: /tmp/llvm-project/build - key: libcxx-${{ env.LLVM_VERSION }} + key: 'libcxx-${{ env.LLVM_VERSION }}' - name: compiling libcxx ${{ env.LLVM_VERSION }} with modules if: steps.libcxx_with_modules.outputs.cache-hit != 'true' run: | @@ -77,7 +77,7 @@ jobs: - uses: actions/cache/restore@v4 with: path: /tmp/llvm-project/build - key: libcxx-${{ env.LLVM_VERSION }} + key: 'libcxx-${{ env.LLVM_VERSION }}' - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 with: From 8bdc0c1e29d58c38d395f96ffdc21ceaaec2580a Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:52:32 -0700 Subject: [PATCH 16/19] fix: typo in yaml --- .editorconfig | 2 +- .github/workflows/{main.yml => main.yaml} | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) rename .github/workflows/{main.yml => main.yaml} (88%) diff --git a/.editorconfig b/.editorconfig index 37d3b10..88ce455 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,6 +10,6 @@ indent_size = 4 indent_size = 4 indent_style = space -[*.yml] +[*.{yml,yaml}] indent_size = 2 indent_style = space diff --git a/.github/workflows/main.yml b/.github/workflows/main.yaml similarity index 88% rename from .github/workflows/main.yml rename to .github/workflows/main.yaml index b04466f..ae3790d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yaml @@ -60,14 +60,14 @@ jobs: mkdir build CC=clang-18 CXX=clang++-18 cmake -G Ninja -S runtimes -B build -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" ninja -C build - - uses: actions/checkout@v4 - - run: CPP2B_LIBCXX_BUILD_ROOT=/tmp/llvm-project/build CC=clang-18 ./build.sh - - uses: actions/upload-artifact@v4 - with: - name: cpp2b - path: dist/debug/cpp2b - if-no-files-found: error - retention-days: 0 + - uses: actions/checkout@v4 + - run: CPP2B_LIBCXX_BUILD_ROOT=/tmp/llvm-project/build CC=clang-18 ./build.sh + - uses: actions/upload-artifact@v4 + with: + name: cpp2b + path: dist/debug/cpp2b + if-no-files-found: error + retention-days: 0 build-self-linux: name: 'build self (linux)' From ab97a3b00f9d0c3a4ff502a37d5e32da034cf54d Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 14:56:49 -0700 Subject: [PATCH 17/19] fix: set cpp2b as executable --- .github/workflows/main.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index ae3790d..b8cbaa2 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -82,5 +82,6 @@ jobs: - uses: actions/download-artifact@v4 with: name: cpp2b + - run: chmod +x cpp2b - run: CPP2B_LIBCXX_BUILD_ROOT=/tmp/llvm-project/build ./cpp2b build - run: CPP2B_LIBCXX_BUILD_ROOT=/tmp/llvm-project/build ./.cache/cpp2/bin/cpp2b build From 70896615a9afb7f2ed959ad930a04cf5cf07b00a Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 15:26:31 -0700 Subject: [PATCH 18/19] feat: start on supporting more module extensions --- src/main.cpp2 | 47 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/src/main.cpp2 b/src/main.cpp2 index f280a77..35365ae 100644 --- a/src/main.cpp2 +++ b/src/main.cpp2 @@ -103,6 +103,13 @@ module_source_extension: (compiler: cpp2b::compiler_type) -> std::string_view = std::abort(); } +bmi_extension: (compiler: cpp2b::compiler_type) -> std::string_view = { + if compiler == cpp2b::compiler_type::msvc { return ".ifc"; } + if compiler == cpp2b::compiler_type::clang { return ".pcm"; } + if compiler == cpp2b::compiler_type::gcc { return ".pcm"; } // TODO: Is this right? + std::abort(); +} + generate_cpp2b_module: () = { cpp2b_module_template_path: fs::path = share_dir() / "cpp2b.cppm.tpl"; cpp2b_module_source_path: fs::path = ".cache/cpp2/source/_build/cpp2b(module_source_extension(cpp2b::compiler()))$"; @@ -171,21 +178,41 @@ get_vs_tools_dir: () -> fs::path = { return getenv_sv("VCToolsInstallDir").expect("missing 'VCToolsInstallDir' environment variable"); } -ensure_std_modules: () = { - d := modules_dir(); - std_bmi: fs::path = d / "std.ifc"; - std_compat_bmi: fs::path = d / "std.compat.ifc"; - vs_tools_dir := get_vs_tools_dir(); +get_libcxx_build_root: () -> fs::path = { + return getenv_sv("CPP2B_LIBCXX_BUILD_ROOT").expect("missing 'CPP2B_LIBCXX_BUILD_ROOT' environment variable"); +} - if !fs::exists(std_bmi) { - build_cpp1_module("std", :std::vector=(vs_tools_dir / "modules" / "std.ixx"), :std::vector = ()); - } +get_system_modules_dir: () -> fs::path = { + compiler :== cpp2b::compiler(); + if compiler == cpp2b::compiler_type::msvc { return get_vs_tools_dir() / "modules"; } + if compiler == cpp2b::compiler_type::clang { return get_libcxx_build_root() / "modules"; } + log_error("cannot find system cpp20 modules directory"); + std::abort(); +} + +ensure_system_module: (name: std::string) = { + ensure_system_module(name, :std::vector = ()); +} - if !fs::exists(std_compat_bmi) { - build_cpp1_module("std.compat", :std::vector=(vs_tools_dir / "modules" / "std.compat.ixx"), :std::vector=("std")); +ensure_system_module: (name: std::string, deps) = { + d := modules_dir(); + bmi := d / std::format("{}{}", name, bmi_extension(cpp2b::compiler())); + system_modules_dir := get_system_modules_dir(); + + if !fs::exists(bmi) { + build_cpp1_module( + name, + :std::vector=(system_modules_dir / std::format("{}{}", name, module_source_extension(cpp2b::compiler()))), + deps + ); } } +ensure_std_modules: () = { + ensure_system_module("std"); + ensure_system_module("std.compat", :std::vector=("std")); +} + build_cpp1_module: (name: std::string, sources, module_deps) = { d := fs::absolute(modules_dir()); bmi := d / ("(name)$.ifc"); From 637b1b634392d69a2d7fd103a0ac141b44e769d9 Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Sat, 10 Aug 2024 15:52:25 -0700 Subject: [PATCH 19/19] chore: add some TODOs --- src/main.cpp2 | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main.cpp2 b/src/main.cpp2 index 35365ae..51b33db 100644 --- a/src/main.cpp2 +++ b/src/main.cpp2 @@ -182,8 +182,7 @@ get_libcxx_build_root: () -> fs::path = { return getenv_sv("CPP2B_LIBCXX_BUILD_ROOT").expect("missing 'CPP2B_LIBCXX_BUILD_ROOT' environment variable"); } -get_system_modules_dir: () -> fs::path = { - compiler :== cpp2b::compiler(); +get_system_modules_dir: (compiler: cpp2b::compiler_type) -> fs::path = { if compiler == cpp2b::compiler_type::msvc { return get_vs_tools_dir() / "modules"; } if compiler == cpp2b::compiler_type::clang { return get_libcxx_build_root() / "modules"; } log_error("cannot find system cpp20 modules directory"); @@ -197,7 +196,7 @@ ensure_system_module: (name: std::string) = { ensure_system_module: (name: std::string, deps) = { d := modules_dir(); bmi := d / std::format("{}{}", name, bmi_extension(cpp2b::compiler())); - system_modules_dir := get_system_modules_dir(); + system_modules_dir := get_system_modules_dir(cpp2b::compiler()); if !fs::exists(bmi) { build_cpp1_module( @@ -214,6 +213,11 @@ ensure_std_modules: () = { } build_cpp1_module: (name: std::string, sources, module_deps) = { + if cpp2b::compiler() != cpp2b::compiler_type::msvc { + log_error("TODO: build_cpp1_module non-msvc support"); + std::abort(); + } + d := fs::absolute(modules_dir()); bmi := d / ("(name)$.ifc"); cmd_str: std::string = "cl /nologo /std:c++latest /W4 /MDd /EHsc /c /interface /TP"; @@ -496,6 +500,11 @@ build_binary: (info: cpp2b_source_binary_info) -> build_binary_result = { ensure_dir(log_path.parent_path()); ensure_dir(bin_outpath.parent_path()); + if cpp2b::compiler() != cpp2b::compiler_type::msvc { + log_error("TODO: build_binary non-msvc support"); + std::abort(); + } + d := fs::absolute(modules_dir()); cmd_str: std::string = "cl /nologo /std:c++latest /W4 /MDd /EHsc /DEBUG:full /Zi /FC"; for info.imports do (imp: std::string) { @@ -548,6 +557,11 @@ build_build_script: (info: cpp2b_source_build_info) -> build_binary_result = { ensure_dir(log_path.parent_path()); ensure_dir(bin_outpath.parent_path()); + if cpp2b::compiler() != cpp2b::compiler_type::msvc { + log_error("TODO: build_build_script non-msvc support"); + std::abort(); + } + d := fs::absolute(modules_dir()); cmd_str: std::string = "cl /nologo /std:c++latest /W4 /MDd /EHsc /LDd /DLL"; for info.imports do (imp: std::string) {