Fix KiCad WASM build and runtime errors
Build improvements: - Change -O0 to -O1 to fix "local count too large" asyncify error - Add wasm-emscripten-finalize to host (Docker OOMs on large WASM) - Use -gseparate-dwarf for smaller main binary with debug info - Build native protoc for code generation - Add more functions to asyncify removelist Runtime fixes: - Add inject-dyncall-shims.sh to fix "dynCall_* is not defined" in Emscripten 4.x - Update wxwidgets with browserInfo.name fix New stubs and bindings: - Add Embind bindings for JavaScript interop - Add stubs for scripting, API plugin, PCB frame, navlib 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
898e079ef2
commit
9c271996c2
17 changed files with 699 additions and 13 deletions
120
wasm/stubs/api_plugin_stub.cpp
Normal file
120
wasm/stubs/api_plugin_stub.cpp
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* API Plugin stubs for KiCad WASM build
|
||||
* API plugins and server are not available in WASM (no sockets/IPC)
|
||||
*/
|
||||
|
||||
#include <api/api_plugin_manager.h>
|
||||
#include <api/api_server.h>
|
||||
|
||||
// Forward declare and provide minimal definition for KINNG_REQUEST_SERVER
|
||||
// This is needed because unique_ptr requires a complete type for deletion
|
||||
class KINNG_REQUEST_SERVER {};
|
||||
|
||||
// Event definitions
|
||||
wxDEFINE_EVENT( API_REQUEST_EVENT, wxCommandEvent );
|
||||
wxDEFINE_EVENT( EDA_EVT_PLUGIN_MANAGER_JOB_FINISHED, wxCommandEvent );
|
||||
wxDEFINE_EVENT( EDA_EVT_PLUGIN_AVAILABILITY_CHANGED, wxCommandEvent );
|
||||
|
||||
// Static member initialization
|
||||
wxString KICAD_API_SERVER::s_logFileName;
|
||||
|
||||
// KICAD_API_SERVER stub implementation
|
||||
KICAD_API_SERVER::KICAD_API_SERVER() :
|
||||
m_readyToReply( false )
|
||||
{
|
||||
// m_server intentionally left as nullptr - API server not available in WASM
|
||||
}
|
||||
|
||||
KICAD_API_SERVER::~KICAD_API_SERVER()
|
||||
{
|
||||
// m_server is nullptr, nothing to clean up
|
||||
}
|
||||
|
||||
void KICAD_API_SERVER::Start()
|
||||
{
|
||||
// No-op: API server not available in WASM
|
||||
}
|
||||
|
||||
void KICAD_API_SERVER::Stop()
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
bool KICAD_API_SERVER::Running() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void KICAD_API_SERVER::RegisterHandler( API_HANDLER* aHandler )
|
||||
{
|
||||
(void)aHandler;
|
||||
}
|
||||
|
||||
void KICAD_API_SERVER::DeregisterHandler( API_HANDLER* aHandler )
|
||||
{
|
||||
(void)aHandler;
|
||||
}
|
||||
|
||||
std::string KICAD_API_SERVER::SocketPath() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void KICAD_API_SERVER::onApiRequest( std::string* aRequest )
|
||||
{
|
||||
(void)aRequest;
|
||||
}
|
||||
|
||||
void KICAD_API_SERVER::handleApiEvent( wxCommandEvent& aEvent )
|
||||
{
|
||||
(void)aEvent;
|
||||
}
|
||||
|
||||
void KICAD_API_SERVER::log( const std::string& aOutput )
|
||||
{
|
||||
(void)aOutput;
|
||||
}
|
||||
|
||||
// API_PLUGIN_MANAGER stub implementation
|
||||
API_PLUGIN_MANAGER::API_PLUGIN_MANAGER( wxEvtHandler* aParent ) :
|
||||
m_parent( aParent ),
|
||||
m_lastPid( 0 ),
|
||||
m_raiseTimer( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
void API_PLUGIN_MANAGER::ReloadPlugins()
|
||||
{
|
||||
// No-op: plugins not available in WASM
|
||||
}
|
||||
|
||||
void API_PLUGIN_MANAGER::RecreatePluginEnvironment( const wxString& aIdentifier )
|
||||
{
|
||||
(void)aIdentifier;
|
||||
}
|
||||
|
||||
void API_PLUGIN_MANAGER::InvokeAction( const wxString& aIdentifier )
|
||||
{
|
||||
(void)aIdentifier;
|
||||
}
|
||||
|
||||
std::optional<const PLUGIN_ACTION*> API_PLUGIN_MANAGER::GetAction( const wxString& aIdentifier )
|
||||
{
|
||||
(void)aIdentifier;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::vector<const PLUGIN_ACTION*> API_PLUGIN_MANAGER::GetActionsForScope( PLUGIN_ACTION_SCOPE aScope )
|
||||
{
|
||||
(void)aScope;
|
||||
return {};
|
||||
}
|
||||
|
||||
void API_PLUGIN_MANAGER::processPluginDependencies()
|
||||
{
|
||||
}
|
||||
|
||||
void API_PLUGIN_MANAGER::processNextJob( wxCommandEvent& aEvent )
|
||||
{
|
||||
(void)aEvent;
|
||||
}
|
||||
26
wasm/stubs/nl_pcbnew_plugin_stub.cpp
Normal file
26
wasm/stubs/nl_pcbnew_plugin_stub.cpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* SpaceNavigator plugin stubs for KiCad WASM build
|
||||
* 3D mouse support is not available in WASM
|
||||
*/
|
||||
|
||||
// Minimal definition for NL_PCBNEW_PLUGIN_IMPL
|
||||
// Required because unique_ptr destructor needs a complete type
|
||||
class NL_PCBNEW_PLUGIN_IMPL {};
|
||||
|
||||
#include <navlib/nl_pcbnew_plugin.h>
|
||||
|
||||
// NL_PCBNEW_PLUGIN stub implementation
|
||||
NL_PCBNEW_PLUGIN::NL_PCBNEW_PLUGIN( PCB_DRAW_PANEL_GAL* aViewport )
|
||||
{
|
||||
(void)aViewport;
|
||||
// No implementation - 3D mouse not available in WASM
|
||||
}
|
||||
|
||||
NL_PCBNEW_PLUGIN::~NL_PCBNEW_PLUGIN()
|
||||
{
|
||||
}
|
||||
|
||||
void NL_PCBNEW_PLUGIN::SetFocus( bool aFocus )
|
||||
{
|
||||
(void)aFocus;
|
||||
}
|
||||
73
wasm/stubs/pcb_frame_stub.cpp
Normal file
73
wasm/stubs/pcb_frame_stub.cpp
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* PCB Frame stubs for KiCad WASM build
|
||||
* Python action plugins are not available in WASM
|
||||
*
|
||||
* These stubs provide implementations for methods that are declared in headers
|
||||
* but whose implementations depend on scripting features not available in WASM.
|
||||
*/
|
||||
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <pcb_base_frame.h>
|
||||
#include <footprint.h>
|
||||
#include <action_plugin.h>
|
||||
#include <board.h>
|
||||
|
||||
class ACTION_MENU;
|
||||
|
||||
// PCB_EDIT_FRAME static method implementations
|
||||
// These are called from panel_pcbnew_action_plugins.cpp
|
||||
|
||||
std::vector<LEGACY_OR_API_PLUGIN> PCB_EDIT_FRAME::GetOrderedActionPlugins()
|
||||
{
|
||||
// Return empty list: no plugins available in WASM
|
||||
return {};
|
||||
}
|
||||
|
||||
bool PCB_EDIT_FRAME::GetActionPluginButtonVisible( const wxString& aPluginPath, bool aPluginDefault )
|
||||
{
|
||||
(void)aPluginPath;
|
||||
// Return the default value since we can't check settings for non-existent plugins
|
||||
return aPluginDefault;
|
||||
}
|
||||
|
||||
void PCB_EDIT_FRAME::buildActionPluginMenus( ACTION_MENU* aActionMenu )
|
||||
{
|
||||
(void)aActionMenu;
|
||||
// No-op: action plugins not available in WASM
|
||||
}
|
||||
|
||||
// PCB_BASE_FRAME protected method implementation
|
||||
// The declaration is NOT guarded by wxUSE_FSWATCHER but the implementation IS,
|
||||
// so we need a stub when filesystem watcher is not available.
|
||||
#if !wxUSE_FSWATCHER
|
||||
void PCB_BASE_FRAME::setFPWatcher( FOOTPRINT* aFootprint )
|
||||
{
|
||||
(void)aFootprint;
|
||||
// No-op: filesystem watcher not available in WASM
|
||||
}
|
||||
#endif
|
||||
|
||||
// Scripting helper functions stub
|
||||
// These are in pcbnew_scripting_helpers.cpp which is only compiled with KICAD_SCRIPTING
|
||||
BOARD* LoadBoard( const wxString& aFileName, bool aSetActive )
|
||||
{
|
||||
(void)aFileName;
|
||||
(void)aSetActive;
|
||||
// Scripting not available in WASM
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool SaveBoard( wxString& aFileName, BOARD* aBoard, bool aSkipSettings )
|
||||
{
|
||||
(void)aFileName;
|
||||
(void)aBoard;
|
||||
(void)aSkipSettings;
|
||||
// Scripting not available in WASM
|
||||
return false;
|
||||
}
|
||||
|
||||
BOARD* CreateEmptyBoard()
|
||||
{
|
||||
// Scripting not available in WASM
|
||||
return nullptr;
|
||||
}
|
||||
43
wasm/stubs/python_manager_stub.cpp
Normal file
43
wasm/stubs/python_manager_stub.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Python Manager stubs for KiCad WASM build
|
||||
* Python scripting is not available in WASM
|
||||
*/
|
||||
|
||||
#include <python_manager.h>
|
||||
|
||||
// Implementation
|
||||
|
||||
PYTHON_MANAGER::PYTHON_MANAGER( const wxString& aInterpreterPath ) :
|
||||
m_interpreterPath( aInterpreterPath )
|
||||
{
|
||||
}
|
||||
|
||||
long PYTHON_MANAGER::Execute( const std::vector<wxString>& aArgs,
|
||||
const std::function<void(int, const wxString&, const wxString&)>& aCallback,
|
||||
const wxExecuteEnv* aEnv,
|
||||
bool aSaveOutput )
|
||||
{
|
||||
(void)aArgs;
|
||||
(void)aCallback;
|
||||
(void)aEnv;
|
||||
(void)aSaveOutput;
|
||||
// Return 0: no process created (Python not available in WASM)
|
||||
return 0;
|
||||
}
|
||||
|
||||
wxString PYTHON_MANAGER::FindPythonInterpreter()
|
||||
{
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
std::optional<wxString> PYTHON_MANAGER::GetPythonEnvironment( const wxString& aNamespace )
|
||||
{
|
||||
(void)aNamespace;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<wxString> PYTHON_MANAGER::GetVirtualPython( const wxString& aNamespace )
|
||||
{
|
||||
(void)aNamespace;
|
||||
return std::nullopt;
|
||||
}
|
||||
65
wasm/stubs/scripting_stub.cpp
Normal file
65
wasm/stubs/scripting_stub.cpp
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Scripting stubs for KiCad WASM build
|
||||
* Python scripting is not available in WASM
|
||||
*
|
||||
* These stubs provide implementations for methods declared in pcb_scripting_tool.h
|
||||
* that are called from panel_pcbnew_action_plugins.cpp
|
||||
*/
|
||||
|
||||
#include <python/scripting/pcb_scripting_tool.h>
|
||||
|
||||
// Constructor/Destructor implementations
|
||||
SCRIPTING_TOOL::SCRIPTING_TOOL() :
|
||||
PCB_TOOL_BASE( "pcbnew.ScriptingTool" )
|
||||
{
|
||||
}
|
||||
|
||||
SCRIPTING_TOOL::~SCRIPTING_TOOL()
|
||||
{
|
||||
}
|
||||
|
||||
// Virtual method implementations
|
||||
bool SCRIPTING_TOOL::Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void SCRIPTING_TOOL::Reset( RESET_REASON aReason )
|
||||
{
|
||||
(void)aReason;
|
||||
}
|
||||
|
||||
// Static method implementations - these are called from panel_pcbnew_action_plugins.cpp
|
||||
void SCRIPTING_TOOL::ReloadPlugins()
|
||||
{
|
||||
// No-op: Python plugins not available in WASM
|
||||
}
|
||||
|
||||
void SCRIPTING_TOOL::ShowPluginFolder()
|
||||
{
|
||||
// No-op: Plugin folder not accessible in WASM
|
||||
}
|
||||
|
||||
// Private method implementations
|
||||
int SCRIPTING_TOOL::reloadPlugins( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
(void)aEvent;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SCRIPTING_TOOL::showPluginFolder( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
(void)aEvent;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SCRIPTING_TOOL::setTransitions()
|
||||
{
|
||||
// No transitions: scripting not available
|
||||
}
|
||||
|
||||
// Private static method - must be provided since it's declared in header
|
||||
void SCRIPTING_TOOL::callLoadPlugins()
|
||||
{
|
||||
// No-op: Python not available in WASM
|
||||
}
|
||||
34
wasm/stubs/wasm-emscripten-finalize-stub.sh
Executable file
34
wasm/stubs/wasm-emscripten-finalize-stub.sh
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
#!/bin/bash
|
||||
# Stub wasm-emscripten-finalize that just copies input to output
|
||||
# The real finalize runs on the host where more RAM is available
|
||||
|
||||
# Handle --version query
|
||||
if [[ "$1" == "--version" ]]; then
|
||||
echo "wasm-emscripten-finalize version 121"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Parse arguments to find input/output files
|
||||
# wasm-emscripten-finalize <input.wasm> -o <output.wasm> [options]
|
||||
INPUT=""
|
||||
OUTPUT=""
|
||||
PREV_ARG=""
|
||||
|
||||
for arg in "$@"; do
|
||||
if [ "$PREV_ARG" = "-o" ]; then
|
||||
OUTPUT="$arg"
|
||||
elif [[ "$arg" != -* ]] && [[ "$arg" == *.wasm ]]; then
|
||||
INPUT="$arg"
|
||||
fi
|
||||
PREV_ARG="$arg"
|
||||
done
|
||||
|
||||
# Copy input to output (no transformation)
|
||||
if [ -n "$INPUT" ] && [ -n "$OUTPUT" ]; then
|
||||
cp "$INPUT" "$OUTPUT"
|
||||
elif [ -n "$INPUT" ]; then
|
||||
# In-place mode: nothing to do
|
||||
:
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Loading…
Reference in a new issue