diff --git a/CMakeLists.txt b/CMakeLists.txt index 23071ba725..a1eea87d7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,16 @@ option(KICAD_TESTING_VERSION "set this option to ON to build the stable version of KICAD. mainly used to set version ID (default OFF)" ) +option(KICAD_SCRIPTING + "set this option ON to build the scripting support inside kicad binaries" + ) + +option(KICAD_SCRIPTING_MODULES + "set this option ON to build kicad modules that can be used from scripting languages" + ) + + + #Set version option (stable or testing) if (KICAD_STABLE_VERSION ) diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index e203b2e1b0..bda556d348 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -1,11 +1,14 @@ add_definitions(-DPCBNEW) -FIND_PACKAGE(SWIG REQUIRED) -INCLUDE(${SWIG_USE_FILE}) - -FIND_PACKAGE(PythonLibs) -INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) +if (KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES) + FIND_PACKAGE(SWIG REQUIRED) + INCLUDE(${SWIG_USE_FILE}) + + FIND_PACKAGE(PythonLibs) + INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) + add_definitions(-DPCBNEW -DKICAD_SCRIPTING) +endif() ### # Includes @@ -223,79 +226,78 @@ set(PCBNEW_COMMON_SRCS ## # Scripting sources ## -set(PCBNEW_SCRIPTING_PYTHON_HELPERS - scripting/wx_python_helpers.cpp - scripting/python_scripting.cpp - ) -set(PCBNEW_SCRIPTING_SRCS -# kicad_wrap.cxx - pcbnew_wrap.cxx - ${PCBNEW_SCRIPTING_PYTHON_HELPERS} - ) +if (KICAD_SCRIPTING) + + set(PCBNEW_SCRIPTING_PYTHON_HELPERS + scripting/wx_python_helpers.cpp + scripting/pcbnew_scripting_helpers.cpp + scripting/python_scripting.cpp + ) + + set(PCBNEW_SCRIPTING_SRCS + pcbnew_wrap.cxx + ${PCBNEW_SCRIPTING_PYTHON_HELPERS} + ) +endif() ## # Scripting build ## +if (KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES) -set(SWIG_FLAGS -I${CMAKE_CURRENT_SOURCE_DIR}/../.. -I${CMAKE_CURRENT_SOURCE_DIR} -I${CMAKE_CURRENT_SOURCE_DIR}/../include -DDEBUG) + set(SWIG_FLAGS -I${CMAKE_CURRENT_SOURCE_DIR}/../.. -I${CMAKE_CURRENT_SOURCE_DIR} -I${CMAKE_CURRENT_SOURCE_DIR}/../include -DDEBUG) + + # collect CFLAGS , and pass them to swig later + + get_directory_property( DirDefs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS ) + foreach( d ${DirDefs} ) + SET(SWIG_FLAGS ${SWIG_FLAGS} -D${d} ) + endforeach() + + # check if we have IO_MGR and KICAD_PLUGIN available + if ( USE_NEW_PCBNEW_LOAD OR USE_NEW_PCBNEW_SAVE ) + SET(SWIG_FLAGS ${SWIG_FLAGS} -DBUILD_WITH_PLUGIN) + endif() -# collect CFLAGS , and pass them to swig later - -get_directory_property( DirDefs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS ) -foreach( d ${DirDefs} ) - SET(SWIG_FLAGS ${SWIG_FLAGS} -D${d} ) -endforeach() - -# check if we have IO_MGR and KICAD_PLUGIN available -if ( USE_NEW_PCBNEW_LOAD OR USE_NEW_PCBNEW_SAVE ) - SET(SWIG_FLAGS ${SWIG_FLAGS} -DBUILD_WITH_PLUGIN) endif() - - -foreach( d ${SWIG_FLAGS} ) - message(STATUS "Swig options:" ${d}) -endforeach() - -SET(SWIG_OPTS -python -c++ -outdir ${CMAKE_CURRENT_BINARY_DIR} ${SWIG_FLAGS} ) - - -# we checked the posibility to build kicad thinks in a separate module, but it -# will be easier in just one "pcbnew" for now -# -#add_custom_command( -# OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/kicad_wrap.cxx -# COMMAND ${SWIG_EXECUTABLE} ${SWIG_OPTS} -o ${CMAKE_CURRENT_BINARY_DIR}/kicad_wrap.cxx scripting/kicad.i -# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -#) - -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/pcbnew_wrap.cxx - COMMAND ${SWIG_EXECUTABLE} ${SWIG_OPTS} -o ${CMAKE_CURRENT_BINARY_DIR}/pcbnew_wrap.cxx scripting/pcbnew.i - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) + +if (KICAD_SCRIPTING) + + SET(SWIG_OPTS -python -c++ -outdir ${CMAKE_CURRENT_BINARY_DIR} ${SWIG_FLAGS} ) + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/pcbnew_wrap.cxx + COMMAND ${SWIG_EXECUTABLE} ${SWIG_OPTS} -o ${CMAKE_CURRENT_BINARY_DIR}/pcbnew_wrap.cxx scripting/pcbnew.i + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + +endif(KICAD_SCRIPTING) ### # _pcbnew DLL/DSO file creation ### -SET(CMAKE_SWIG_FLAGS ${SWIG_FLAGS}) -SET_SOURCE_FILES_PROPERTIES(scripting/pcbnew.i PROPERTIES CPLUSPLUS ON) -SWIG_ADD_MODULE(pcbnew python scripting/pcbnew.i ${PCBNEW_SCRIPTING_PYTHON_HELPERS} ${PCBNEW_SRCS}) -SWIG_LINK_LIBRARIES(pcbnew - 3d-viewer - pcbcommon - common - bitmaps - polygon - kbool - ${wxWidgets_LIBRARIES} - ${OPENGL_LIBRARIES} - ${GDI_PLUS_LIBRARIES} - ${PYTHON_LIBRARIES}) +if (KICAD_SCRIPTING_MODULES) + SET(CMAKE_SWIG_FLAGS ${SWIG_FLAGS}) + SET_SOURCE_FILES_PROPERTIES(scripting/pcbnew.i PROPERTIES CPLUSPLUS ON) + SWIG_ADD_MODULE(pcbnew python scripting/pcbnew.i ${PCBNEW_SCRIPTING_PYTHON_HELPERS} ${PCBNEW_SRCS}) + SWIG_LINK_LIBRARIES(pcbnew + 3d-viewer + pcbcommon + common + bitmaps + polygon + kbool + ${wxWidgets_LIBRARIES} + ${OPENGL_LIBRARIES} + ${GDI_PLUS_LIBRARIES} + ${PYTHON_LIBRARIES}) + +endif (KICAD_SCRIPTING_MODULES) ### # Windows resource file @@ -390,6 +392,14 @@ install(TARGETS pcbnew DESTINATION ${KICAD_BIN} COMPONENT binary) +if (KICAD_SCRIPTING_MODULES) + install(FILES ${CMAKE_BINARY_DIR}/pcbnew/pcbnew.py + DESTINATION share/python) + + install(FILES ${CMAKE_BINARY_DIR}/pcbnew/_pcbnew.so + DESTINATION share/python) +endif(KICAD_SCRIPTING_MODULES) + # The specctra test fails to build properly using MS Visual Studio. if(NOT MSVC) diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp index 14ef6c7420..db36f29b9c 100644 --- a/pcbnew/pcbnew.cpp +++ b/pcbnew/pcbnew.cpp @@ -49,6 +49,7 @@ #include #include +#include // Colors for layers and items COLORS_DESIGN_SETTINGS g_ColorsSettings; @@ -113,8 +114,11 @@ bool EDA_APP::OnInit() PCB_EDIT_FRAME* frame = NULL; int i=0; - + +#ifdef KICAD_SCRIPTING pcbnewInitPythonScripting(); +#endif + InitEDA_Appl( wxT( "Pcbnew" ), APP_PCBNEW_T ); @@ -150,6 +154,11 @@ Changing extension to .brd." ), GetChars( fn.GetFullPath() ) ); ReadHotkeyConfig( wxT( "PcbFrame" ), g_Board_Editor_Hokeys_Descr ); frame = new PCB_EDIT_FRAME( NULL, wxT( "Pcbnew" ), wxPoint( 0, 0 ), wxSize( 600, 400 ) ); + + #ifdef KICAD_SCRIPTING + ScriptingSetPcbEditFrame(frame); /* give the scripting helpers access to our frame */ + #endif + frame->UpdateTitle(); SetTopWindow( frame ); @@ -202,7 +211,7 @@ Changing extension to .brd." ), GetChars( fn.GetFullPath() ) ); */ frame->SetFocus(); frame->GetCanvas()->SetFocus(); - pythonSetPcbEditFrame(frame); + DIALOG_SCRIPTING* sw = new DIALOG_SCRIPTING(frame); sw->Show(true); return true; diff --git a/pcbnew/scripting/kicad.i b/pcbnew/scripting/kicad.i index e2f6805f60..77d9ab4731 100644 --- a/pcbnew/scripting/kicad.i +++ b/pcbnew/scripting/kicad.i @@ -25,17 +25,23 @@ #include #include #include - #include + #include using namespace std; + #include + #include %} +/* all the wx wrappers for wxString, wxPoint, wxRect, wxChar .. */ +%include + + %include %include %include +%include +%include -/* all the wx wrappers for wxString, wxPoint, wxRect, wxChar .. */ -%include /* namespace std diff --git a/pcbnew/scripting/pcbnew.i b/pcbnew/scripting/pcbnew.i index 27428fce27..7ba2e627b4 100644 --- a/pcbnew/scripting/pcbnew.i +++ b/pcbnew/scripting/pcbnew.i @@ -1,23 +1,26 @@ %module pcbnew - %include "kicad.i" -%{ - #include +// this is what it must be included in the wrapper .cxx code to compile + +%{ + #include #include #include #include #include #include #include - #include + #include #include #include + #include + #include + #include + #include + #include - - - - BOARD *GetBoard(); + BOARD *GetBoard(); /* get current editor board */ %} #ifdef BUILD_WITH_PLUGIN @@ -27,7 +30,6 @@ %} #endif - %include %include %include @@ -37,12 +39,32 @@ %include %include %include +%include +%include +%include +%include + +/* the IO_ERROR exception handler, not working yet... */ +%exception +{ + try { + $function + } + catch (IO_ERROR e) { + PyErr_SetString(PyExc_IOError,"IO error"); + return NULL; + } +} + +%include #ifdef BUILD_WITH_PLUGIN -%include -%include + %include + %include #endif +/* this is to help python with the * accessor of DLIST templates */ + %rename(Get) operator BOARD_ITEM*; %rename(Get) operator TRACK*; %rename(Get) operator D_PAD*; @@ -51,11 +73,16 @@ BOARD *GetBoard(); -// se must translate C++ templates to scripting languages +// we must translate C++ templates to scripting languages %template(BOARD_ITEM_List) DLIST; -%template(MODULE_List) DLIST; -%template(TRACK_List) DLIST; -%template(PAD_List) DLIST; +%template(MODULE_List) DLIST; +%template(TRACK_List) DLIST; +%template(PAD_List) DLIST; +/* TODO: -the std::* compilatio is broken with some swig + gcc combinations + * see kicad.i for more information. + * %template(MARKER_Vector) std::vector; + * %template(ZONE_CONTAINER_Vector) std::vector; + */ diff --git a/pcbnew/scripting/pcbnew_scripting_helpers.cpp b/pcbnew/scripting/pcbnew_scripting_helpers.cpp new file mode 100644 index 0000000000..ee2400903a --- /dev/null +++ b/pcbnew/scripting/pcbnew_scripting_helpers.cpp @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include + +static PCB_EDIT_FRAME *PcbEditFrame=NULL; + +BOARD *GetBoard() +{ + if (PcbEditFrame) return PcbEditFrame->GetBoard(); + else return NULL; +} + +void ScriptingSetPcbEditFrame(PCB_EDIT_FRAME *aPCBEdaFrame) +{ + PcbEditFrame = aPCBEdaFrame; +} + + +BOARD* LoadBoard(wxString aFileName) +{ +#ifdef USE_NEW_PCBNEW_LOAD + try{ + return IO_MGR::Load(IO_MGR::KICAD,aFileName); + } catch (IO_ERROR) + { + return NULL; + } +#else + fprintf(stderr,"Warning, LoadBoard not implemented without USE_NEW_PCBNEW_LOAD\n"); + return NULL; +#endif +} + +bool SaveBoard(wxString aFileName, BOARD* aBoard) +{ + +#ifdef USE_NEW_PCBNEW_LOAD + aBoard->m_Status_Pcb &= ~CONNEXION_OK; + aBoard->SynchronizeNetsAndNetClasses(); + aBoard->SetCurrentNetClass( aBoard->m_NetClasses.GetDefault()->GetName() ); + + wxString header = wxString::Format( + wxT( "PCBNEW-BOARD Version %d date %s\n\n# Created by Pcbnew%s\n\n" ), + BOARD_FILE_VERSION, DateAndTime().GetData(), + GetBuildVersion().GetData() ); + + PROPERTIES props; + + props["header"] = header; + + try + { + IO_MGR::Save( IO_MGR::KICAD, aFileName, aBoard, &props ); + return true; + } + catch (IO_ERROR) + { + return false; + } + +#else + fprintf(stderr,"Warning, SaveBoard not implemented without USE_NEW_PCBNEW_LOAD\n"); + return false; +#endif + +} + + diff --git a/pcbnew/scripting/pcbnew_scripting_helpers.h b/pcbnew/scripting/pcbnew_scripting_helpers.h new file mode 100644 index 0000000000..4750f56f46 --- /dev/null +++ b/pcbnew/scripting/pcbnew_scripting_helpers.h @@ -0,0 +1,16 @@ +#ifndef __PCBNEW_SCRIPTING_HELPERS_H +#define __PCBNEW_SCRIPTING_HELPERS_H + +#include + +/* we could be including all these methods as static in a class, but + * we want plain pcbnew. access from python */ + +#ifndef SWIG +void ScriptingSetPcbEditFrame(PCB_EDIT_FRAME *aPCBEdaFrame); +#endif + +BOARD* LoadBoard(wxString aFileName); +bool SaveBoard(wxString aFileName, BOARD* aBoard); + +#endif \ No newline at end of file diff --git a/pcbnew/scripting/python_scripting.cpp b/pcbnew/scripting/python_scripting.cpp index 46135151cb..1a5bf7bc21 100644 --- a/pcbnew/scripting/python_scripting.cpp +++ b/pcbnew/scripting/python_scripting.cpp @@ -18,7 +18,8 @@ static int SwigNumModules = 0; /* Add a name + initfuction to our SwigImportInittab */ -static void swigAddModule(const char *name, void (*initfunc)()) { +static void swigAddModule(const char *name, void (*initfunc)()) +{ SwigImportInittab[SwigNumModules].name = (char *)name; SwigImportInittab[SwigNumModules].initfunc = initfunc; SwigNumModules++; @@ -28,7 +29,8 @@ static void swigAddModule(const char *name, void (*initfunc)()) { /* Add the builting python modules */ -static void swigAddBuiltin() { +static void swigAddBuiltin() +{ int i = 0; while (PyImport_Inittab[i].name) { swigAddModule(PyImport_Inittab[i].name, PyImport_Inittab[i].initfunc); @@ -38,26 +40,18 @@ static void swigAddBuiltin() { } static void swigAddModules() { - //swigAddModule("_kicad",init_kicad); swigAddModule("_pcbnew",init_pcbnew); + + // finally it seems better to include all in just one module + // but in case we needed to include any other modules, + // it must be done like this: + // swigAddModule("_kicad",init_kicad); + } static void swigSwitchPythonBuiltin() { - PyImport_Inittab = SwigImportInittab; -} - -static PCB_EDIT_FRAME *PcbEditFrame=NULL; - -BOARD *GetBoard() -{ - if (PcbEditFrame) return PcbEditFrame->GetBoard(); - else return NULL; -} - -void pythonSetPcbEditFrame(PCB_EDIT_FRAME *aPCBEdaFrame) -{ - PcbEditFrame = aPCBEdaFrame; + PyImport_Inittab = SwigImportInittab; } @@ -83,8 +77,9 @@ void pcbnewInitPythonScripting() of kicad here */ PyRun_SimpleString("import sys\n" - "sys.path.append(\".\")\n" + "sys.path.append(\".\")\n" "import pcbnew\n"); } + \ No newline at end of file diff --git a/pcbnew/scripting/python_scripting.h b/pcbnew/scripting/python_scripting.h index 03b0de8b63..32dfd2278d 100644 --- a/pcbnew/scripting/python_scripting.h +++ b/pcbnew/scripting/python_scripting.h @@ -1,11 +1,8 @@ #ifndef __PYTHON_SCRIPTING_H #define __PYTHON_SCRIPTING_H -#include #include -void pythonSetPcbEditFrame(PCB_EDIT_FRAME *aPCBEdaFrame); void pcbnewInitPythonScripting(void); - #endif