Skip to content

Commit 71a7da1

Browse files
authored
Merge branch 'main' into Reduce-Emscripten-shared-library-size
2 parents e748750 + c849ba4 commit 71a7da1

File tree

11 files changed

+315
-16
lines changed

11 files changed

+315
-16
lines changed

.github/workflows/deploy-pages.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ jobs:
168168
emrun --browser="Google Chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" CppInterOpTests.html
169169
echo "Running DynamicLibraryManagerTests in Google Chrome"
170170
emrun --browser="Google Chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" DynamicLibraryManagerTests.html
171+
sudo safaridriver --enable
172+
python -m pip install selenium
173+
echo "Running CppInterOpTests in Safari"
174+
emrun --no_browser --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" CppInterOpTests.html &
175+
python ../../../scripts/browser_tests_safari.py CppInterOpTests.html
176+
echo "Running DynamicLibraryManagerTests in Safari"
177+
emrun --no_browser --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" DynamicLibraryManagerTests.html &
178+
python ../../../scripts/browser_tests_safari.py DynamicLibraryManagerTests.html
171179
172180
cd ../../
173181
emmake make -j ${{ env.ncpus }} install

.github/workflows/emscripten.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,10 +320,12 @@ jobs:
320320
{
321321
git apply -v emscripten-clang19-2-shift-temporary-files-to-tmp-dir.patch
322322
git apply -v emscripten-clang19-3-remove-zdefs.patch
323+
git apply -v emscripten-clang19-4-enable_exception_handling.patch
323324
}
324325
elseif ( "${{ matrix.clang-runtime }}" -imatch "20" )
325326
{
326327
git apply -v emscripten-clang20-2-shift-temporary-files-to-tmp-dir.patch
328+
git apply -v emscripten-clang20-3-enable_exception_handling.patch
327329
}
328330
cd build
329331
echo "Apply clang${{ matrix.clang-runtime }}-*.patch patches:"
@@ -587,6 +589,14 @@ jobs:
587589
emrun --browser="Google Chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" CppInterOpTests.html
588590
echo "Running DynamicLibraryManagerTests in Google Chrome"
589591
emrun --browser="Google Chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" DynamicLibraryManagerTests.html
592+
sudo safaridriver --enable
593+
python -m pip install selenium
594+
echo "Running CppInterOpTests in Safari"
595+
emrun --no_browser --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" CppInterOpTests.html &
596+
python ../../../scripts/browser_tests_safari.py CppInterOpTests.html
597+
echo "Running DynamicLibraryManagerTests in Safari"
598+
emrun --no_browser --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" DynamicLibraryManagerTests.html &
599+
python ../../../scripts/browser_tests_safari.py DynamicLibraryManagerTests.html
590600
else
591601
export ARCHITECHURE=$(uname -m)
592602
if [[ "$ARCHITECHURE" != "aarch64" ]]; then
@@ -727,6 +737,12 @@ jobs:
727737
emrun --browser="Google Chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" CppInterOpTests.html
728738
echo "Running DynamicLibraryManagerTests in Google Chrome"
729739
emrun --browser="Google Chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" DynamicLibraryManagerTests.html
740+
echo "Running CppInterOpTests in Safari"
741+
emrun --no_browser --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" CppInterOpTests.html &
742+
python ../../../scripts/browser_tests_safari.py CppInterOpTests.html
743+
echo "Running DynamicLibraryManagerTests in Safari"
744+
emrun --no_browser --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" DynamicLibraryManagerTests.html &
745+
python ../../../scripts/browser_tests_safari.py DynamicLibraryManagerTests.html
730746
else
731747
export ARCHITECHURE=$(uname -m)
732748
if [[ "$ARCHITECHURE" != "aarch64" ]]; then

Emscripten-build-instructions.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ On Windows execute the following
6464
cd .\llvm-project\
6565
cp -r ..\patches\llvm\emscripten-clang20*
6666
git apply -v emscripten-clang20-2-shift-temporary-files-to-tmp-dir.patch
67+
git apply -v emscripten-clang20-3-enable_exception_handling.patch
6768
```
6869

6970
We are now in a position to build an emscripten build of llvm by executing the following on Linux
@@ -225,7 +226,7 @@ It is possible to run the Emscripten tests in a headless browser. To do this we
225226
cd ./unittests/CppInterOp/
226227
```
227228

228-
We will run our tests in a fresh installed browser. Installing the browsers, and running the tests within the installed browsers will be platform dependent. To do this on MacOS execute the following
229+
We will run our tests in a fresh installed browser. Installing the browsers, and running the tests within the installed browsers will be platform dependent. To do this for Chrome and Firefox on MacOS execute the following
229230

230231
```bash
231232
wget "https://download.mozilla.org/?product=firefox-latest&os=osx&lang=en-US" -O Firefox-latest.dmg
@@ -252,6 +253,19 @@ echo "Running DynamicLibraryManagerTests in Google Chrome"
252253
emrun --browser="Google Chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" DynamicLibraryManagerTests.html
253254
```
254255

256+
To run tests in Safari you can make use of safaridriver. How to enable this will depend on
257+
your MacOS operating system, and is best to consult [safaridriver](https://developer.apple.com/documentation/webkit/testing-with-webdriver-in-safari). You will also need to install the Selenium
258+
python package. This only needs to be enable once, and then you can execute the following to run the tests in Safari
259+
260+
```bash
261+
echo "Running CppInterOpTests in Safari"
262+
emrun --no_browser --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" CppInterOpTests.html &
263+
python ../../../scripts/browser_tests_safari.py CppInterOpTests.html
264+
echo "Running DynamicLibraryManagerTests in Safari"
265+
emrun --no_browser --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" DynamicLibraryManagerTests.html &
266+
python ../../../scripts/browser_tests_safari.py DynamicLibraryManagerTests.html
267+
```
268+
255269
To do this on Ubuntu x86 execute the following
256270

257271
```bash
@@ -323,12 +337,13 @@ emmake make -j $(nproc --all) install
323337
## Xeus-cpp-lite Wasm Build Instructions
324338

325339
A project which makes use of the wasm build of CppInterOp is xeus-cpp. xeus-cpp is a C++ Jupyter kernel. Assuming you are in
326-
the CppInterOp build folder, you can build the wasm version of xeus-cpp by executing (replace $LLVM_VERSION with the version
340+
the CppInterOp build folder, you can build the wasm version of xeus-cpp by executing (replace LLVM_VERSION with the version
327341
of llvm you are building against)
328342

329343
```bash
330344
cd ../..
331345
git clone --depth=1 https://github.com/compiler-research/xeus-cpp.git
346+
export LLVM_VERSION=20
332347
cd ./xeus-cpp
333348
mkdir build
334349
cd build
@@ -338,7 +353,7 @@ emcmake cmake \
338353
-DCMAKE_INSTALL_PREFIX=$PREFIX \
339354
-DXEUS_CPP_EMSCRIPTEN_WASM_BUILD=ON \
340355
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
341-
-DXEUS_CPP_RESOURCE_DIR=$LLVM_BUILD_DIR/lib/clang/$LLVM_VERSION \
356+
-DXEUS_CPP_RESOURCE_DIR="$LLVM_BUILD_DIR/lib/clang/$LLVM_VERSION" \
342357
-DSYSROOT_PATH=$SYSROOT_PATH \
343358
..
344359
emmake make -j $(nproc --all) install

docs/Emscripten-build-instructions.rst

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ On Windows execute the following
8383
cd .\llvm-project\
8484
cp -r ..\patches\llvm\emscripten-clang20*
8585
git apply -v emscripten-clang20-2-shift-temporary-files-to-tmp-dir.patch
86+
git apply -v emscripten-clang20-3-enable_exception_handling.patch
8687
8788
We are now in a position to build an emscripten build of llvm by executing the following on Linux
8889
and osx
@@ -248,7 +249,7 @@ It is possible to run the Emscripten tests in a headless browser. To do this we
248249
249250
cd ./unittests/CppInterOp/
250251
251-
We will run our tests in a fresh installed browser. Installing the browsers, and running the tests within the installed browsers will be platform dependent. To do this on MacOS execute the following
252+
We will run our tests in a fresh installed browser. Installing the browsers, and running the tests within the installed browsers will be platform dependent. To do this for Chrome and Firefox on MacOS execute the following
252253

253254
.. code:: bash
254255
@@ -275,6 +276,19 @@ We will run our tests in a fresh installed browser. Installing the browsers, and
275276
echo "Running DynamicLibraryManagerTests in Google Chrome"
276277
emrun --browser="Google Chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" DynamicLibraryManagerTests.html
277278
279+
To run tests in Safari you can make use of safaridriver. How to enable this will depend on
280+
your MacOS operating system, and is best to consult `safaridriver <https://developer.apple.com/documentation/webkit/testing-with-webdriver-in-safari>`_. You will also need to install the Selenium
281+
python package. This only needs to be enable once, and then you can execute the following to run the tests in Safari
282+
283+
.. code:: bash
284+
285+
echo "Running CppInterOpTests in Safari"
286+
emrun --no_browser --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" CppInterOpTests.html &
287+
python ../../../scripts/browser_tests_safari.py CppInterOpTests.html
288+
echo "Running DynamicLibraryManagerTests in Safari"
289+
emrun --no_browser --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" DynamicLibraryManagerTests.html &
290+
python ../../../scripts/browser_tests_safari.py DynamicLibraryManagerTests.html
291+
278292
To do this on Ubuntu x86 execute the following
279293

280294
.. code:: bash
@@ -345,12 +359,13 @@ Assuming it passes all test you can install by executing the following.
345359
A project which makes use of the wasm build of CppInterOp is xeus-cpp.
346360
xeus-cpp is a C++ Jupyter kernel. Assuming you are in the CppInterOp
347361
build folder, you can build the wasm version of xeus-cpp by executing
348-
(replace $LLVM_VERSION with the version of llvm you are building against)
362+
(replace LLVM_VERSION with the version of llvm you are building against)
349363

350364
.. code:: bash
351365
352366
cd ../..
353367
git clone --depth=1 https://github.com/compiler-research/xeus-cpp.git
368+
export LLVM_VERSION=20
354369
cd ./xeus-cpp
355370
mkdir build
356371
cd build
@@ -360,7 +375,7 @@ build folder, you can build the wasm version of xeus-cpp by executing
360375
-DCMAKE_INSTALL_PREFIX=$PREFIX \
361376
-DXEUS_CPP_EMSCRIPTEN_WASM_BUILD=ON \
362377
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ON \
363-
-DXEUS_CPP_RESOURCE_DIR=$LLVM_BUILD_DIR/lib/clang/$LLVM_VERSION \
378+
-DXEUS_CPP_RESOURCE_DIR="$LLVM_BUILD_DIR/lib/clang/$LLVM_VERSION" \
364379
-DSYSROOT_PATH=$SYSROOT_PATH \
365380
..
366381
emmake make -j $(nproc --all) install

include/CppInterOp/CppInterOp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,9 @@ void GetEnumConstantDatamembers(TCppScope_t scope,
573573
CPPINTEROP_API TCppScope_t LookupDatamember(const std::string& name,
574574
TCppScope_t parent);
575575

576+
/// Check if the given type is a lamda class
577+
CPPINTEROP_API bool IsLambdaClass(TCppType_t type);
578+
576579
/// Gets the type of the variable that is passed as a parameter.
577580
CPPINTEROP_API TCppType_t GetVariableType(TCppScope_t var);
578581

lib/CppInterOp/CppInterOp.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -854,9 +854,30 @@ static void GetClassDecls(TCppScope_t klass,
854854
for (Decl* DI : CXXRD->decls()) {
855855
if (auto* MD = dyn_cast<DeclType>(DI))
856856
methods.push_back(MD);
857-
else if (auto* USD = dyn_cast<UsingShadowDecl>(DI))
858-
if (auto* MD = dyn_cast<DeclType>(USD->getTargetDecl()))
857+
else if (auto* USD = dyn_cast<UsingShadowDecl>(DI)) {
858+
auto* MD = dyn_cast<DeclType>(USD->getTargetDecl());
859+
if (!MD)
860+
continue;
861+
862+
auto* CUSD = dyn_cast<ConstructorUsingShadowDecl>(DI);
863+
if (!CUSD) {
864+
methods.push_back(MD);
865+
continue;
866+
}
867+
868+
auto* CXXCD = dyn_cast_or_null<CXXConstructorDecl>(CUSD->getTargetDecl());
869+
if (!CXXCD) {
859870
methods.push_back(MD);
871+
continue;
872+
}
873+
if (CXXCD->isDeleted())
874+
continue;
875+
876+
// Result is appended to the decls, i.e. CXXRD, iterator
877+
// non-shadowed decl will be push_back later
878+
// methods.push_back(Result);
879+
getSema().findInheritingConstructor(SourceLocation(), CXXCD, CUSD);
880+
}
860881
}
861882
}
862883

@@ -1406,6 +1427,14 @@ TCppScope_t LookupDatamember(const std::string& name, TCppScope_t parent) {
14061427
return 0;
14071428
}
14081429

1430+
bool IsLambdaClass(TCppType_t type) {
1431+
QualType QT = QualType::getFromOpaquePtr(type);
1432+
if (auto* CXXRD = QT->getAsCXXRecordDecl()) {
1433+
return CXXRD->isLambda();
1434+
}
1435+
return false;
1436+
}
1437+
14091438
TCppType_t GetVariableType(TCppScope_t var) {
14101439
auto* D = static_cast<Decl*>(var);
14111440

@@ -1510,6 +1539,7 @@ intptr_t GetVariableOffset(compat::Interpreter& I, Decl* D,
15101539
cling::Interpreter::PushTransactionRAII RAII(&getInterp());
15111540
#endif // CPPINTEROP_USE_CLING
15121541
getSema().InstantiateVariableDefinition(SourceLocation(), VD);
1542+
VD = VD->getDefinition();
15131543
}
15141544
if (VD->hasInit() &&
15151545
(VD->isConstexpr() || VD->getType().isConstQualified())) {
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
2+
index 985d0b7c0..20a727893 100644
3+
--- a/clang/lib/Interpreter/Interpreter.cpp
4+
+++ b/clang/lib/Interpreter/Interpreter.cpp
5+
@@ -135,6 +135,48 @@ CreateCI(const llvm::opt::ArgStringList &Argv) {
6+
return std::move(Clang);
7+
}
8+
9+
+static llvm::Error HandleFrontendOptions(const CompilerInstance &CI) {
10+
+ const auto &FrontendOpts = CI.getFrontendOpts();
11+
+
12+
+ if (FrontendOpts.ShowHelp) {
13+
+ driver::getDriverOptTable().printHelp(
14+
+ llvm::outs(), "clang -cc1 [options] file...",
15+
+ "LLVM 'Clang' Compiler: http://clang.llvm.org",
16+
+ /*ShowHidden=*/false, /*ShowAllAliases=*/false,
17+
+ llvm::opt::Visibility(driver::options::CC1Option));
18+
+ return llvm::createStringError(llvm::errc::not_supported, "Help displayed");
19+
+ }
20+
+
21+
+ if (FrontendOpts.ShowVersion) {
22+
+ llvm::cl::PrintVersionMessage();
23+
+ return llvm::createStringError(llvm::errc::not_supported,
24+
+ "Version displayed");
25+
+ }
26+
+
27+
+ if (!FrontendOpts.LLVMArgs.empty()) {
28+
+ unsigned NumArgs = FrontendOpts.LLVMArgs.size();
29+
+ auto Args = std::make_unique<const char *[]>(NumArgs + 2);
30+
+ Args[0] = "clang-repl (LLVM option parsing)";
31+
+ for (unsigned i = 0; i != NumArgs; ++i) {
32+
+ Args[i + 1] = FrontendOpts.LLVMArgs[i].c_str();
33+
+ // remove the leading '-' from the option name
34+
+ if (Args[i + 1][0] == '-') {
35+
+ auto *option = static_cast<llvm::cl::opt<bool> *>(
36+
+ llvm::cl::getRegisteredOptions()[Args[i + 1] + 1]);
37+
+ if (option) {
38+
+ option->setInitialValue(true);
39+
+ } else {
40+
+ llvm::errs() << "Unknown LLVM option: " << Args[i + 1] << "\n";
41+
+ }
42+
+ }
43+
+ }
44+
+ Args[NumArgs + 1] = nullptr;
45+
+ llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
46+
+ }
47+
+
48+
+ return llvm::Error::success();
49+
+}
50+
+
51+
} // anonymous namespace
52+
53+
llvm::Expected<std::unique_ptr<CompilerInstance>>
54+
@@ -306,7 +348,12 @@ const char *const Runtimes = R"(
55+
56+
llvm::Expected<std::unique_ptr<Interpreter>>
57+
Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
58+
- llvm::Error Err = llvm::Error::success();
59+
+
60+
+ llvm::Error Err = HandleFrontendOptions(*CI);
61+
+ if (Err) {
62+
+ return std::move(Err);
63+
+ }
64+
+
65+
auto Interp =
66+
std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
67+
if (Err)
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
2+
index 3b81f9d70..2704edb8a 100644
3+
--- a/clang/lib/Interpreter/Interpreter.cpp
4+
+++ b/clang/lib/Interpreter/Interpreter.cpp
5+
@@ -142,6 +142,48 @@ CreateCI(const llvm::opt::ArgStringList &Argv) {
6+
return std::move(Clang);
7+
}
8+
9+
+static llvm::Error HandleFrontendOptions(const CompilerInstance &CI) {
10+
+ const auto &FrontendOpts = CI.getFrontendOpts();
11+
+
12+
+ if (FrontendOpts.ShowHelp) {
13+
+ driver::getDriverOptTable().printHelp(
14+
+ llvm::outs(), "clang -cc1 [options] file...",
15+
+ "LLVM 'Clang' Compiler: http://clang.llvm.org",
16+
+ /*ShowHidden=*/false, /*ShowAllAliases=*/false,
17+
+ llvm::opt::Visibility(driver::options::CC1Option));
18+
+ return llvm::createStringError(llvm::errc::not_supported, "Help displayed");
19+
+ }
20+
+
21+
+ if (FrontendOpts.ShowVersion) {
22+
+ llvm::cl::PrintVersionMessage();
23+
+ return llvm::createStringError(llvm::errc::not_supported,
24+
+ "Version displayed");
25+
+ }
26+
+
27+
+ if (!FrontendOpts.LLVMArgs.empty()) {
28+
+ unsigned NumArgs = FrontendOpts.LLVMArgs.size();
29+
+ auto Args = std::make_unique<const char *[]>(NumArgs + 2);
30+
+ Args[0] = "clang-repl (LLVM option parsing)";
31+
+ for (unsigned i = 0; i != NumArgs; ++i) {
32+
+ Args[i + 1] = FrontendOpts.LLVMArgs[i].c_str();
33+
+ // remove the leading '-' from the option name
34+
+ if (Args[i + 1][0] == '-') {
35+
+ auto *option = static_cast<llvm::cl::opt<bool> *>(
36+
+ llvm::cl::getRegisteredOptions()[Args[i + 1] + 1]);
37+
+ if (option) {
38+
+ option->setInitialValue(true);
39+
+ } else {
40+
+ llvm::errs() << "Unknown LLVM option: " << Args[i + 1] << "\n";
41+
+ }
42+
+ }
43+
+ }
44+
+ Args[NumArgs + 1] = nullptr;
45+
+ llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
46+
+ }
47+
+
48+
+ return llvm::Error::success();
49+
+}
50+
+
51+
} // anonymous namespace
52+
53+
namespace clang {
54+
@@ -456,7 +498,12 @@ const char *const Runtimes = R"(
55+
56+
llvm::Expected<std::unique_ptr<Interpreter>>
57+
Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
58+
- llvm::Error Err = llvm::Error::success();
59+
+
60+
+ llvm::Error Err = HandleFrontendOptions(*CI);
61+
+ if (Err) {
62+
+ return std::move(Err);
63+
+ }
64+
+
65+
auto Interp =
66+
std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
67+
if (Err)

scripts/browser_tests_safari.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import sys
2+
import time
3+
from selenium import webdriver
4+
5+
driver = webdriver.Safari()
6+
driver.get("http://localhost:6931/" + sys.argv[1])
7+
8+
time.sleep(60)
9+
driver.quit()

0 commit comments

Comments
 (0)