Replies: 4 comments 7 replies
-
I'm working on it, but it is currently paused until the API changes for V3.0 are somewhat final. This is the repo responsible for building manifold and providing raw ffi bindings: https://github.com/NickUfer/manifold-sys-rs So far I did not try to build the project for wasm yet, I think there will be some hurdles too. There is also an open problem on the sys-rs crate regarding crate size I put on the side for now: NickUfer/manifold3d-sys-rs#1 |
Beta Was this translation helpful? Give feedback.
-
Yeah it would probably be easier to use cmake, but alot of rust devy complain about build errors when using cmake, especially on Windows. The last thing rust devs want to deal with is build errors of some C/C++ dependency. Thats why I am trying to use cc, as it is just working on linux and windows with minmal effort.
About crate size: I actually managed to fix it today by explicitly listing all files/folders which should be included in the upload. This reduced the overall size to ~650KB compressed, which is acceptable.
About assimp and the other libraries: I used static linking for now because I knew this will work and I figure this out on the way. But of course dynamic linking and just linking against the installed version in the environment is the next goal.
…On November 18, 2024 4:44:27 PM GMT+01:00, pca006132 ***@***.***> wrote:
@NickUfer I think it may be much simpler to use the [cmake crate](https://docs.rs/cmake/latest/cmake/) to build manifold, and supply the dependencies by specifying `MANIFOLD_USE_BUILTIN_TBB` and `FETCHCONTENT_SOURCE_DIR_TBB` for example. Our cmake already handles the cross-platform shenanigans, so you don't have to do it again :)
Regarding crate size, apparently other -sys crates cheat by downloading it elsewhere instead of using submodule: https://github.com/sfackler/rust-openssl/blob/master/openssl-sys/build/find_vendored.rs
And for `assimp`, I think if you depend on the system installed version (I don't think you are building assimp according to your code), you should just somehow find the package by either using cmake environment variables or pkg-config instead of pulling in the assimp git just for a single header file. Again, the package search is already handled by cmake...
--
Reply to this email directly or view it on GitHub:
#1046 (reply in thread)
You are receiving this because you were mentioned.
Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
An update on WASM support: Right now, I think it is very hard to support compilation for WASM in any way. There are different compilation targets available, like One possibility would be to write all the JS/TS binding code manually, but I wan't to avoid that. |
Beta Was this translation helpful? Give feedback.
-
WASM may not actually be that hard. I managed to compile to wasm using just clang and target Basically: MANIFOLD="manifold"
LIBCXX="llvm-project/libcxx" # we need the source because we need to compile several source files from here
WASMLIBC="mono-wasm-libc"
CLIPPER2="Clipper2"
INCLUDES="-isystem $LIBCXX/include -isystem $WASMLIBC/include -isystem $WASMLIBC/arch/wasm32 -I./ -I$CLIPPER2/CPP/Clipper2Lib/include -I$MANIFOLD/include -I$MANIFOLD/bindings/c/include "
WASMFLAGS="--target=wasm32-unknown-unknown -fno-exceptions -fno-rtti -nostdlib"
for f in $MANIFOLD/src/*.cpp $MANIFOLD/src/cross_section/*.cpp $MANIFOLD/bindings/c/*.cpp $CLIPPER2/CPP/Clipper2Lib/src/*.cpp $LIBCXX/src/{bind,hash,memory,new_helpers}.cpp; do
if [ "$(basename $f)" = "meshIOc.cpp" ]; then
continue
fi
echo compiling $f
clang -DCLIPPER2_MAX_DECIMAL_PRECISION=8 -DMANIFOLD_EXPORTS -DMANIFOLD_CROSS_SECTION -DMANIFOLD_PAR=-1 $INCLUDES -DNDEBUG -std=c++17 -Wall -Wno-unused -Werror $WASMFLAGS -o $(basename ${f/.cpp/.o}) -c $f
done
wasm-ld --no-entry --export-all --warn-unresolved-symbols *.o -o libmanifold.wasm 2>&1 | grep -o "undefined symbol: .*" | sort --unique Requires the following modifications for mono-wasm-libc: clang wants diff --git a/arch/wasm32/bits/alltypes.h b/arch/wasm32/bits/alltypes.h
index 06a3049e..a992894d 100644
--- a/arch/wasm32/bits/alltypes.h
+++ b/arch/wasm32/bits/alltypes.h
@@ -1,6 +1,6 @@
-#define _Addr int
+#define _Addr long
#define _Int64 long long
-#define _Reg int
+#define _Reg long
#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
typedef __builtin_va_list va_list;
@@ -79,6 +79,11 @@ typedef unsigned _Addr size_t;
#define __DEFINED_size_t
#endif
+#if defined(__NEED_max_align_t) && !defined(__DEFINED_max_align_t)
+typedef struct { long long __ll; long double __ld; } max_align_t;
+#define __DEFINED_max_align_t
+#endif
+
#if defined(__NEED_uintptr_t) && !defined(__DEFINED_uintptr_t)
typedef unsigned _Addr uintptr_t;
#define __DEFINED_uintptr_t Clipper2: Remove iostream diff --git a/CPP/Clipper2Lib/include/clipper2/clipper.core.h b/CPP/Clipper2Lib/include/clipper2/clipper.core.h
index 624de90..4ee072d 100644
--- a/CPP/Clipper2Lib/include/clipper2/clipper.core.h
+++ b/CPP/Clipper2Lib/include/clipper2/clipper.core.h
@@ -15,7 +15,6 @@
#include <cmath>
#include <vector>
#include <string>
-#include <iostream>
#include <algorithm>
#include <climits>
#include <numeric>
@@ -169,11 +168,11 @@ namespace Clipper2Lib
void SetZ(const z_type z_value) { z = z_value; }
- friend std::ostream& operator<<(std::ostream& os, const Point& point)
- {
- os << point.x << "," << point.y << "," << point.z;
- return os;
- }
+ // friend std::ostream& operator<<(std::ostream& os, const Point& point)
+ // {
+ // os << point.x << "," << point.y << "," << point.z;
+ // return os;
+ // }
#else
@@ -206,11 +205,11 @@ namespace Clipper2Lib
return Point(x * scale, y * scale);
}
- friend std::ostream& operator<<(std::ostream& os, const Point& point)
- {
- os << point.x << "," << point.y;
- return os;
- }
+ // friend std::ostream& operator<<(std::ostream& os, const Point& point)
+ // {
+ // os << point.x << "," << point.y;
+ // return os;
+ // }
#endif
friend bool operator==(const Point& a, const Point& b)
@@ -385,10 +384,10 @@ namespace Clipper2Lib
return result;
}
- friend std::ostream& operator<<(std::ostream& os, const Rect<T>& rect) {
- os << "(" << rect.left << "," << rect.top << "," << rect.right << "," << rect.bottom << ") ";
- return os;
- }
+ // friend std::ostream& operator<<(std::ostream& os, const Rect<T>& rect) {
+ // os << "(" << rect.left << "," << rect.top << "," << rect.right << "," << rect.bottom << ") ";
+ // return os;
+ // }
};
template <typename T1, typename T2>
@@ -487,26 +486,26 @@ namespace Clipper2Lib
return Rect<T>(xmin, ymin, xmax, ymax);
}
- template <typename T>
- std::ostream& operator << (std::ostream& outstream, const Path<T>& path)
- {
- if (!path.empty())
- {
- auto pt = path.cbegin(), last = path.cend() - 1;
- while (pt != last)
- outstream << *pt++ << ", ";
- outstream << *last << std::endl;
- }
- return outstream;
- }
-
- template <typename T>
- std::ostream& operator << (std::ostream& outstream, const Paths<T>& paths)
- {
- for (auto p : paths)
- outstream << p;
- return outstream;
- }
+ // template <typename T>
+ // std::ostream& operator << (std::ostream& outstream, const Path<T>& path)
+ // {
+ // if (!path.empty())
+ // {
+ // auto pt = path.cbegin(), last = path.cend() - 1;
+ // while (pt != last)
+ // outstream << *pt++ << ", ";
+ // outstream << *last << std::endl;
+ // }
+ // return outstream;
+ // }
+ //
+ // template <typename T>
+ // std::ostream& operator << (std::ostream& outstream, const Paths<T>& paths)
+ // {
+ // for (auto p : paths)
+ // outstream << p;
+ // return outstream;
+ // }
template <typename T1, typename T2>
diff --git a/CPP/Clipper2Lib/include/clipper2/clipper.engine.h b/CPP/Clipper2Lib/include/clipper2/clipper.engine.h
index 559f247..3e73816 100644
--- a/CPP/Clipper2Lib/include/clipper2/clipper.engine.h
+++ b/CPP/Clipper2Lib/include/clipper2/clipper.engine.h
@@ -12,7 +12,7 @@
#include <cstdlib>
#include <stdint.h> //#541
-#include <iostream>
+// #include <iostream>
#include <queue>
#include <vector>
#include <functional>
diff --git a/CPP/Clipper2Lib/include/clipper2/clipper.h b/CPP/Clipper2Lib/include/clipper2/clipper.h
index a2fe5c3..65a059d 100644
--- a/CPP/Clipper2Lib/include/clipper2/clipper.h
+++ b/CPP/Clipper2Lib/include/clipper2/clipper.h
@@ -311,35 +311,35 @@ namespace Clipper2Lib {
return true;
}
- static void OutlinePolyPath(std::ostream& os,
- size_t idx, bool isHole, size_t count, const std::string& preamble)
- {
- std::string plural = (count == 1) ? "." : "s.";
- if (isHole)
- os << preamble << "+- Hole (" << idx << ") contains " << count <<
- " nested polygon" << plural << std::endl;
- else
- os << preamble << "+- Polygon (" << idx << ") contains " << count <<
- " hole" << plural << std::endl;
- }
-
- static void OutlinePolyPath64(std::ostream& os, const PolyPath64& pp,
- size_t idx, std::string preamble)
- {
- OutlinePolyPath(os, idx, pp.IsHole(), pp.Count(), preamble);
- for (size_t i = 0; i < pp.Count(); ++i)
- if (pp.Child(i)->Count())
- details::OutlinePolyPath64(os, *pp.Child(i), i, preamble + " ");
- }
-
- static void OutlinePolyPathD(std::ostream& os, const PolyPathD& pp,
- size_t idx, std::string preamble)
- {
- OutlinePolyPath(os, idx, pp.IsHole(), pp.Count(), preamble);
- for (size_t i = 0; i < pp.Count(); ++i)
- if (pp.Child(i)->Count())
- details::OutlinePolyPathD(os, *pp.Child(i), i, preamble + " ");
- }
+ // static void OutlinePolyPath(std::ostream& os,
+ // size_t idx, bool isHole, size_t count, const std::string& preamble)
+ // {
+ // std::string plural = (count == 1) ? "." : "s.";
+ // if (isHole)
+ // os << preamble << "+- Hole (" << idx << ") contains " << count <<
+ // " nested polygon" << plural << std::endl;
+ // else
+ // os << preamble << "+- Polygon (" << idx << ") contains " << count <<
+ // " hole" << plural << std::endl;
+ // }
+ //
+ // static void OutlinePolyPath64(std::ostream& os, const PolyPath64& pp,
+ // size_t idx, std::string preamble)
+ // {
+ // OutlinePolyPath(os, idx, pp.IsHole(), pp.Count(), preamble);
+ // for (size_t i = 0; i < pp.Count(); ++i)
+ // if (pp.Child(i)->Count())
+ // details::OutlinePolyPath64(os, *pp.Child(i), i, preamble + " ");
+ // }
+ //
+ // static void OutlinePolyPathD(std::ostream& os, const PolyPathD& pp,
+ // size_t idx, std::string preamble)
+ // {
+ // OutlinePolyPath(os, idx, pp.IsHole(), pp.Count(), preamble);
+ // for (size_t i = 0; i < pp.Count(); ++i)
+ // if (pp.Child(i)->Count())
+ // details::OutlinePolyPathD(os, *pp.Child(i), i, preamble + " ");
+ // }
template<typename T, typename U>
inline constexpr void MakePathGeneric(const T an_array,
@@ -356,28 +356,28 @@ namespace Clipper2Lib {
} // end details namespace
- inline std::ostream& operator<< (std::ostream& os, const PolyTree64& pp)
- {
- std::string plural = (pp.Count() == 1) ? " polygon." : " polygons.";
- os << std::endl << "Polytree with " << pp.Count() << plural << std::endl;
- for (size_t i = 0; i < pp.Count(); ++i)
- if (pp.Child(i)->Count())
- details::OutlinePolyPath64(os, *pp.Child(i), i, " ");
- os << std::endl << std::endl;
- return os;
- }
-
- inline std::ostream& operator<< (std::ostream& os, const PolyTreeD& pp)
- {
- std::string plural = (pp.Count() == 1) ? " polygon." : " polygons.";
- os << std::endl << "Polytree with " << pp.Count() << plural << std::endl;
- for (size_t i = 0; i < pp.Count(); ++i)
- if (pp.Child(i)->Count())
- details::OutlinePolyPathD(os, *pp.Child(i), i, " ");
- os << std::endl << std::endl;
- if (!pp.Level()) os << std::endl;
- return os;
- }
+ // inline std::ostream& operator<< (std::ostream& os, const PolyTree64& pp)
+ // {
+ // std::string plural = (pp.Count() == 1) ? " polygon." : " polygons.";
+ // os << std::endl << "Polytree with " << pp.Count() << plural << std::endl;
+ // for (size_t i = 0; i < pp.Count(); ++i)
+ // if (pp.Child(i)->Count())
+ // details::OutlinePolyPath64(os, *pp.Child(i), i, " ");
+ // os << std::endl << std::endl;
+ // return os;
+ // }
+ //
+ // inline std::ostream& operator<< (std::ostream& os, const PolyTreeD& pp)
+ // {
+ // std::string plural = (pp.Count() == 1) ? " polygon." : " polygons.";
+ // os << std::endl << "Polytree with " << pp.Count() << plural << std::endl;
+ // for (size_t i = 0; i < pp.Count(); ++i)
+ // if (pp.Child(i)->Count())
+ // details::OutlinePolyPathD(os, *pp.Child(i), i, " ");
+ // os << std::endl << std::endl;
+ // if (!pp.Level()) os << std::endl;
+ // return os;
+ // }
inline Paths64 PolyTreeToPaths64(const PolyTree64& polytree)
{ As well as the following two files for libcxx: // __config_site
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___CONFIG_SITE
#define _LIBCPP___CONFIG_SITE
#define _LIBCPP_ABI_VERSION 1
#define _LIBCPP_ABI_NAMESPACE __1
#define _LIBCPP_HAS_NO_THREADS
#define _LIBCPP_HAS_NO_MONOTONIC_CLOCK
/* #define _LIBCPP_HAS_MUSL_LIBC */
/* #undef _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS */
#define _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS
/* #undef _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION */
#define _LIBCPP_HAS_NO_FILESYSTEM
#define _LIBCPP_HAS_NO_RANDOM_DEVICE
#define _LIBCPP_HAS_NO_LOCALIZATION
#define _LIBCPP_HAS_NO_WIDE_CHARACTERS
#define _LIBCPP_HAS_NO_STD_MODULES
#define _LIBCPP_HAS_NO_TIME_ZONE_DATABASE
/* #undef _LIBCPP_INSTRUMENTED_WITH_ASAN */
// PSTL backends
#define _LIBCPP_PSTL_CPU_BACKEND_SERIAL
/* #undef _LIBCPP_PSTL_CPU_BACKEND_THREAD */
/* #undef _LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH */
// Hardening.
#define _LIBCPP_HARDENING_MODE_DEFAULT 2
// __USE_MINGW_ANSI_STDIO gets redefined on MinGW
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wmacro-redefined"
#endif
#ifdef __clang__
# pragma clang diagnostic pop
#endif
#endif // _LIBCPP___CONFIG_SITE // __assertion_handler
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___ASSERTION_HANDLER
#define _LIBCPP___ASSERTION_HANDLER
#include <__config>
#include <__verbose_abort>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_ABORT("%s", message)
#else
// TODO(hardening): use `__builtin_verbose_trap(message)` once that becomes available.
# define _LIBCPP_ASSERTION_HANDLER(message) ((void)message, __builtin_trap())
#endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
#endif // _LIBCPP___ASSERTION_HANDLER
Anyway, at the end of the day, these are the remaining undefined symbols:
There are basically 3 categories:
I have no idea if this will work properly even when linked, especially when we have static variables that we should init. But one can probably write some simple c++ code to try... |
Beta Was this translation helpful? Give feedback.
-
Word on the street is that someone is writing Rust bindings? Curious how far along that is, and if I can help in anyway? At Arcol we want to use manifold in a Rust-on-WASM scenario.
@ncthbrt @NickUfer
Beta Was this translation helpful? Give feedback.
All reactions