From 33e26b278d616e5f50ca98fcd40c305af1a5fd42 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Mon, 3 Feb 2014 13:26:18 -0600 Subject: [PATCH] KIWAY in progress... --- CMakeLists.txt | 46 +++++++++++++------ CMakeModules/config.h.cmake | 7 ++- common/kiway.cpp | 6 ++- common/single_top.cpp | 60 +++++++++++++------------ eeschema/CMakeLists.txt | 26 ++++++----- eeschema/eeschema.cpp | 18 ++++---- include/kiway.h | 25 ++++++----- tools/CMakeLists.txt | 49 ++++++++++---------- tools/{mac_test.cpp => kiface_test.cpp} | 0 9 files changed, 135 insertions(+), 102 deletions(-) rename tools/{mac_test.cpp => kiface_test.cpp} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18c2638636..012a06fff4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ set( CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules ) # option( USE_KIWAY_DLLS - "Build the major modules as DLLs or DSOs, will soon be the norm." OFF ) + "Build the major modules as KIFACE DLLs or DSOs, will soon be the norm." OFF ) # The desire is to migrate designs *away from* case independence, and to create designs which use # literally (case specific) interpreted component names. But for backwards compatibility, @@ -240,6 +240,8 @@ if( USE_WX_GRAPHICS_CONTEXT ) add_definitions( -DUSE_WX_GRAPHICS_CONTEXT ) endif() + + # Allow user to override the default settings for adding images to menu items. By default # images in menu items are enabled on all platforms except OSX. This can be over ridden by # defining -DUSE_IMAGES_IN_MENUS=ON/OFF to force the preferred behavior. @@ -253,6 +255,25 @@ else() endif() endif() + +# KIFACE_SUFFIX is the file extension used for top level program modules which +# implement the KIFACE interface. A valid suffix starts with a period '.'. + +if( false ) + # This is the eventual situation near milestone C) of modular-kicad blueprint. + # Until then we use .kiface extension so we don't collide with python DSO. + set( KIFACE_SUFFIX ${CMAKE_SHARED_MODULE_SUFFIX} ) +else() + # Temporary situation until we can dovetail the python DSO into the kiface DSO. + set( KIFACE_SUFFIX ".kiface" ) +endif() + +# KIFACE_PREFIX is a basename prefix used for top level program modules which +# implement the KIFACE. +set( KIFACE_PREFIX "_" ) +#message( STATUS "KIFACE_SUFFIX:${KIFACE_SUFFIX} KIFACE_PREFIX:${KIFACE_PREFIX}" ) + + #================================================ # Locations for install targets. set( KICAD_BIN bin @@ -313,7 +334,7 @@ add_definitions(-DWX_COMPATIBILITY) find_package( OpenGL QUIET ) check_find_package_result( OPENGL_FOUND "OpenGL" ) -if ( KICAD_BUILD_STATIC OR KICAD_BUILD_DYNAMIC ) +if( KICAD_BUILD_STATIC OR KICAD_BUILD_DYNAMIC ) #set(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.so;.dylib;.dll") @@ -331,35 +352,34 @@ if ( KICAD_BUILD_STATIC OR KICAD_BUILD_DYNAMIC ) endif() add_custom_target( lib-dependencies - DEPENDS boost cairo glew libpng pixman pkgconfig - ) + DEPENDS boost cairo glew libpng pixman pkgconfig + ) include( download_libpng ) if( KICAD_SCRIPTING_WXPYTHON ) - message(FATAL_ERROR "KICAD_BUILD_* and SCRIPTING Not Implemented Yet!") + message( FATAL_ERROR "KICAD_BUILD_* and SCRIPTING Not Implemented Yet!" ) else() include( download_wxwidgets ) add_dependencies( lib-dependencies libwx ) - endif( KICAD_SCRIPTING_WXPYTHON ) + endif() include( download_pkgconfig ) - set( PKG_CONFIG_EXECUTABLE "${PKGCONFIG_ROOT}/bin/pkg-config") + set( PKG_CONFIG_EXECUTABLE "${PKGCONFIG_ROOT}/bin/pkg-config" ) include( download_glew ) - set( GLEW_GLEW_LIBRARY "${GLEW_ROOT}/lib/libGLEW.a") - set( GLEW_INCLUDE_DIR "${GLEW_ROOT}/include") + set( GLEW_GLEW_LIBRARY "${GLEW_ROOT}/lib/libGLEW.a" ) + set( GLEW_INCLUDE_DIR "${GLEW_ROOT}/include" ) include( download_pixman ) - set( PIXMAN_LIBRARY "${PIXMAN_ROOT}/lib/libpixman-1.a") + set( PIXMAN_LIBRARY "${PIXMAN_ROOT}/lib/libpixman-1.a" ) include( download_cairo ) - set( CAIRO_INCLUDE_DIR "${CAIRO_ROOT}/include/cairo") - set( CAIRO_LIBRARY "${CAIRO_ROOT}/lib/libcairo.a") + set( CAIRO_INCLUDE_DIR "${CAIRO_ROOT}/include/cairo" ) + set( CAIRO_LIBRARY "${CAIRO_ROOT}/lib/libcairo.a" ) if( KICAD_BUILD_DYNAMIC AND APPLE ) add_custom_target( osx_fix_bundles ALL DEPENDS cvpcb eeschema gerbview kicad pcbnew bitmap2component pcb_calculator pl_editor) add_custom_command(TARGET osx_fix_bundles POST_BUILD COMMAND scripts/osx_fixbundle.sh COMMENT "Migrating dylibs to bundles") endif() - endif( KICAD_BUILD_STATIC OR KICAD_BUILD_DYNAMIC) ##################### diff --git a/CMakeModules/config.h.cmake b/CMakeModules/config.h.cmake index fe255e07da..ca228b70ea 100644 --- a/CMakeModules/config.h.cmake +++ b/CMakeModules/config.h.cmake @@ -67,9 +67,14 @@ /// When defined, build the GITHUB_PLUGIN for pcbnew. #cmakedefine BUILD_GITHUB_PLUGIN -/// When defined, use KIWAY and DSOs +/// When defined, use KIWAY and KIFACE DSOs #cmakedefine USE_KIWAY_DLLS +/// A file extension with a leading '.' is a suffix, and this one is used on +/// top level program modules which implement the KIFACE. +#define KIFACE_SUFFIX wxT( "@KIFACE_SUFFIX@" ) +#define KIFACE_PREFIX wxT( "@KIFACE_PREFIX@" ) + /// Name of repo from which this build came. #define KICAD_REPO_NAME "@KICAD_REPO_NAME@" diff --git a/common/kiway.cpp b/common/kiway.cpp index 895f4db2a9..92086838ca 100644 --- a/common/kiway.cpp +++ b/common/kiway.cpp @@ -23,9 +23,11 @@ */ #include +#include #include #include + // one for each FACE_T wxDynamicLibrary KIWAY::s_sch_dso; wxDynamicLibrary KIWAY::s_pcb_dso; @@ -41,8 +43,8 @@ const wxString KIWAY::dso_name( FACE_T aFaceId ) { switch( aFaceId ) { - case FACE_SCH: return wxT( "_eeschema." ) DSO_EXT; - case FACE_PCB: return wxT( "_pcbnew." ) DSO_EXT; + case FACE_SCH: return KIFACE_PREFIX wxT( "eeschema" ) KIFACE_SUFFIX; + case FACE_PCB: return KIFACE_PREFIX wxT( "pcbnew" ) KIFACE_SUFFIX; default: wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFaceId" ) ); diff --git a/common/single_top.cpp b/common/single_top.cpp index 8620e0f861..fa2dad482e 100644 --- a/common/single_top.cpp +++ b/common/single_top.cpp @@ -25,9 +25,9 @@ /* - This is a program launcher for a single DSO. Initially it will only mimic a - KIWAY not actually implement one, since only a single DSO is supported by - it. + This is a program launcher for a single KIFACE DSO. Initially it will only + mimic a KIWAY, not actually implement one, since only a single DSO is + supported by it. */ @@ -107,8 +107,8 @@ static wxString wxJoin(const wxArrayString& arr, const wxChar sep, #endif -// POLICY CHOICE: return the name of the DSO to load as single_top. -static const wxString dso_name( const wxString& aAbsoluteArgv0 ) +// POLICY CHOICE: return the full path of the DSO to load from single_top. +static const wxString dso_full_path( const wxString& aAbsoluteArgv0 ) { // Prefix basename with '_' and change extension to DSO_EXT. @@ -129,11 +129,14 @@ static const wxString dso_name( const wxString& aAbsoluteArgv0 ) // too many masters here: python, windows, linux, OSX, multiple versions of wx... wxFileName fn( aAbsoluteArgv0 ); - wxString basename( wxT( '_' ) ); + wxString basename( KIFACE_PREFIX ); // start with special prefix - basename += fn.GetName(); + basename += fn.GetName(); // add argv[0]'s basename fn.SetName( basename ); - fn.SetExt( DSO_EXT ); + + // here a suffix == an extension with a preceding '.', + // so skip the preceding '.' to get an extension + fn.SetExt( KIFACE_SUFFIX + 1 ); // special extension, + 1 => &KIFACE_SUFFIX[1] return fn.GetFullPath(); } @@ -157,10 +160,11 @@ void SetLibEnvVar( const wxString& aAbsoluteArgv0 ) // POLICY CHOICE: Keep same path, so that installer MAY put the // "subsidiary shared libraries" in the same directory as the top process module. // A subsidiary shared library is one that is not a top level DSO, but rather - // some shared library that a top level DSO needs to even be loaded. + // some shared library that a top level DSO needs to even be loaded. It is + // a static link to a shared object from a top level DSO. // This directory POLICY CHOICE is not the only dir in play, since LIB_ENV_VAR - // has numerous path options in it, as does DSO searching on linux. + // has numerous path options in it, as does DSO searching on linux, windows, and OSX. // See "man ldconfig" on linux. What's being done here is for quick installs // into a non-standard place, and especially for Windows users who may not // know what the PATH environment variable is or how to set it. @@ -183,7 +187,7 @@ void SetLibEnvVar( const wxString& aAbsoluteArgv0 ) } -// Only a single KIWAY is supported in this single_top to level component, +// Only a single KIWAY is supported in this single_top top level component, // which is dedicated to loading only a single DSO. static KIWAY standalone; @@ -199,7 +203,8 @@ static wxDynamicLibrary dso; * @param aDSOName is an absolute full path to the DSO to load and find KIFACE_GETTER_FUNC within. * * @return KIFACE_GETTER_FUNC* - a pointer to a function which can be called to get the KIFACE - * or NULL if not found or not version compatible. + * or NULL if the getter func was not found. If not found, it is possibly not version compatible + * since the lookup is done by name and the name contains the API version. */ static KIFACE_GETTER_FUNC* get_kiface_getter( const wxString& aDSOName ) { @@ -234,16 +239,18 @@ bool PROCESS::OnInit() wxStandardPathsBase& paths = wxStandardPaths::Get(); +#if defined(DEBUG) wxString dir = paths.GetLocalizedResourcesDir( wxT( "de" ), wxStandardPaths::ResourceCat_None ); printf( "LocalizeResourcesDir:'%s'\n", TO_UTF8( dir ) ); wxString dummy( _( "translate this" ) ); +#endif wxString absoluteArgv0 = paths.GetExecutablePath(); -#if 0 || defined(DEBUG) +#if 0 && defined(DEBUG) printf( "argv[0]:'%s' absoluteArgv0:'%s'\n", TO_UTF8( wxString( argv[0] ) ), TO_UTF8( absoluteArgv0 ) @@ -256,36 +263,31 @@ bool PROCESS::OnInit() return false; } - // Set LIB_ENV_VAR *before* loading the DSO, in case the module holding the - // KIFACE has hard dependencies on subsidiary DSOs below it, *before* loading - // the KIFACE. + // Set LIB_ENV_VAR *before* loading the DSO, in case the top-level DSO holding the + // KIFACE has hard dependencies on subsidiary DSOs below it. SetLibEnvVar( absoluteArgv0 ); - wxString dname = dso_name( absoluteArgv0 ); + wxString dname = dso_full_path( absoluteArgv0 ); // Get the getter. KIFACE_GETTER_FUNC* getter = get_kiface_getter( dname ); - // get_kiface_getter() returned NULL? If so it handled the UI message, so - // we can fail without any further UI. if( !getter ) + { + // get_kiface_getter() failed & already showed the UI message. + // Return failure without any further UI. return false; + } // Get the KIFACE, and give the DSO a single chance to do its // "process level" initialization. kiface = getter( &kiface_version, KIFACE_VERSION, &wxGetApp() ); - if( !kiface ) - { - // get_kiface_getter() did its own UI error window, because it called - // functions in wxDynamicLibrary which did so using wxLogSysError(). - // Therefore say nothing on failure, it's already been said. - // Return false telling startup code to fail the program immediately. - return false; - } + // KIFACE_GETTER_FUNC function comment (API) says the non-NULL is uconditional. + wxASSERT_MSG( kiface, wxT( "attempted DSO has a bug, failed to return a KIFACE*" ) ); - // Using the KIFACE, create a window that the KIFACE knows about, - // pass classId=0 for now. This uses a virtual function KIFACE::CreateWindow() + // Use KIFACE to create a window that the KIFACE knows about, + // pass classId=0 for now. KIFACE::CreateWindow() is a virtual // so we don't need to link to it. wxFrame* frame = (wxFrame*) kiface->CreateWindow( 0, &standalone ); diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 0776a9ff13..05dd30bf82 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -236,7 +236,7 @@ set_source_files_properties( dialogs/dialog_bom.cpp # not ready for even building yet: -if( false AND USE_KIWAY_DLLS ) +if( USE_KIWAY_DLLS ) add_executable( eeschema WIN32 MACOSX_BUNDLE ../common/single_top.cpp @@ -246,33 +246,33 @@ if( false AND USE_KIWAY_DLLS ) ${wxWidgets_LIBRARIES} ) - add_library( eeschema_dso MODULE + add_library( eeschema_kiface MODULE ${EESCHEMA_SRCS} ${EESCHEMA_COMMON_SRCS} ${EESCHEMA_RESOURCES} ) - - set_target_properties( eeschema_dso PROPERTIES - # keep whatever file extension is supplied by SUFFIX, do not use the PREFIX, - # and set the basename. The result is eeschema.so or eeschema.dll. + set_target_properties( eeschema_kiface PROPERTIES + # Decorate OUTPUT_NAME with PREFIX and SUFFIX, creating something like + # _eeschema.so, _eeschema.dll, or _eeschema.kiface OUTPUT_NAME eeschema - PREFIX "" + PREFIX ${KIFACE_PREFIX} + SUFFIX ${KIFACE_SUFFIX} ) if( APPLE ) - set_target_properties( eeschema_dso PROPERTIES + set_target_properties( eeschema_kiface PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist ) endif() if( MAKE_LINK_MAPS ) # generate a link map with cross reference - set_target_properties( eeschema_dso PROPERTIES - LINK_FLAGS "-Wl,-cref -Wl,-Map=eeschema_dso.map" + set_target_properties( eeschema_kiface PROPERTIES + LINK_FLAGS "-Wl,-cref -Wl,-Map=${KIFACE_PRE}eeschema.${KIFACE_EXT}.map" ) endif() - target_link_libraries( eeschema_dso + target_link_libraries( eeschema_kiface common bitmaps polygon @@ -280,7 +280,9 @@ if( false AND USE_KIWAY_DLLS ) ${GDI_PLUS_LIBRARIES} ) - install( TARGETS eeschema_dso + # Note that this filename is subject to change at milestone C) of + # modular-kicad blueprint. + install( TARGETS eeschema_kiface DESTINATION ${KICAD_BIN} COMPONENT binary ) diff --git a/eeschema/eeschema.cpp b/eeschema/eeschema.cpp index bb530ddd2e..5efa3e62c8 100644 --- a/eeschema/eeschema.cpp +++ b/eeschema/eeschema.cpp @@ -53,7 +53,7 @@ #include #include -struct SCH_FACE : public KIFACE +static struct SCH_FACE : public KIFACE { wxWindow* CreateWindow( int aClassId, KIWAY* aKIWAY, int aCtlBits = 0 ) { @@ -76,27 +76,28 @@ struct SCH_FACE : public KIFACE * * @return void* - and must be cast into the know type. */ - VTBL_ENTRY void* IfaceOrAddress( int aDataId ) + void* IfaceOrAddress( int aDataId ) { return NULL; } - } kiface; -static EDA_APP* app; - -extern "C" KIFACE* KIFACE_GETTER( int* aKIFACEversion, int aKIWAYversion, wxApp* aProcess ); +static EDA_APP* process; +// KIFACE_GETTER's actual spelling is a substitution macro found in kiway.h. +// KIFACE_GETTER will not have name mangling due to declaration in kiway.h. MY_API( KIFACE* ) KIFACE_GETTER( int* aKIFACEversion, int aKIWAYversion, wxApp* aProcess ) { - app = (EDA_APP*) aProcess; + process = (EDA_APP*) aProcess; return &kiface; } + EDA_APP& wxGetApp() { - return *app; + wxASSERT( process ); // KIFACE_GETTER has already been called. + return *process; } #else @@ -111,7 +112,6 @@ IMPLEMENT_APP( EDA_APP ) #endif - // Global variables wxSize g_RepeatStep; int g_RepeatDeltaLabel; diff --git a/include/kiway.h b/include/kiway.h index d5013b09ad..632ac308a4 100644 --- a/include/kiway.h +++ b/include/kiway.h @@ -115,15 +115,12 @@ as such! As such, it is OK to use UTF8 characters: #if defined(__linux__) #define LIB_ENV_VAR wxT( "LD_LIBRARY_PATH" ) - #define DSO_EXT wxT( "so" ) + #elif defined(__WXMAC__) #define LIB_ENV_VAR wxT( "DYLD_LIBRARY_PATH" ) - // This should be set to whatever CMake builds when using: - // add_library( target MODULE ) - #define DSO_EXT wxT( "so" ) + #elif defined(__MINGW32__) #define LIB_ENV_VAR wxT( "PATH" ) - #define DSO_EXT wxT( "dll" ) #endif @@ -139,7 +136,7 @@ class PROJECT public: #if 0 - /// Derive PROCESS elements from this, it has a virtual destructor, and + /// Derive PROJECT elements from this, it has a virtual destructor, and /// Elem*() functions can work with it. class ELEM_BASE { @@ -220,13 +217,15 @@ struct KIFACE *

* Most all calls are via virtual functions which means C++ vtables * are used to hold function pointers and eliminate the need to link to specific - * object code libraries, speeding development and encourage clearly defined + * object code libraries, speeding development and encouraging clearly defined * interface design. There is one KIWAY in the launching portion of the process * for each open KiCad project. Each project has its own KIWAY. Within a KIWAY - * is an actual PROJECT data structure. In summary, a KIWAY facilitates - * communicating between DSOs, where the topic of the communication is - * project specific. Here a "project" means a BOARD and a SCHEMATIC and a NETLIST, - * (anything relating to production of a single BOARD and added to class PROJECT.) + * is an actual PROJECT data structure. + *

+ * In summary, a KIWAY facilitates communicating between DSOs, where the topic + * of the communication is project specific. Here a "project" means a BOARD + * and a SCHEMATIC and a NETLIST, (anything relating to production of a single BOARD + * and added to class PROJECT.) */ class KIWAY : public wxEvtHandler { @@ -279,7 +278,11 @@ private: * @param aKIFACEversion is where to put the API version implemented by the KIFACE. * @param aKIWAYversion tells the KIFACE what KIWAY version will be available. * @param aProcess is a pointer to the basic wxApp for this process. + * @return KIFACE* - unconditionally. */ typedef KIFACE* KIFACE_GETTER_FUNC( int* aKIFACEversion, int aKIWAYversion, wxApp* aProcess ); +/// No name mangling. Each TOPMOD will implement this once. +extern "C" KIFACE* KIFACE_GETTER( int* aKIFACEversion, int aKIWAYversion, wxApp* aProcess ); + #endif // KIWAY_H_ diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index bd9668017c..eaa8a7f4d5 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -78,13 +78,12 @@ target_link_libraries( property_tree ) -#----------------------------------------------------------- +#-------------------------------------------------- # The small launcher, it sets up wxWidgets library and loads a MODULE by the same name -# but with extension *.dylib. The two files: mac_test and mac_test.dylib must be in -# same directory for the launcher to find the *.dylib. +# but with extension ${KIFACE_SUFFIX}. -set( PAIR_BASE dso ) +set( PAIR_BASE kiway_test ) add_executable( ${PAIR_BASE} WIN32 MACOSX_BUNDLE EXCLUDE_FROM_ALL @@ -94,37 +93,37 @@ target_link_libraries( ${PAIR_BASE} common ${wxWidgets_LIBRARIES} ) - -# make a DLL/DSO/DYLIB, but *_dso is not its real name, see OUTPUT_NAME below. -add_library( ${PAIR_BASE}_dso MODULE - EXCLUDE_FROM_ALL - mac_test.cpp - ) -target_link_libraries( ${PAIR_BASE}_dso - common - ${wxWidgets_LIBRARIES} - ) - -set_target_properties( ${PAIR_BASE}_dso PROPERTIES - # keep whatever file extension is supplied by SUFFIX, do not use the PREFIX, - # and set the basename. The result is ${PAIR_BASE}.so or ${PAIR_BASE}.dll, - # or ${PAIR_BASE}.dylib - OUTPUT_NAME ${PAIR_BASE} - PREFIX "_" - ) - if( APPLE ) set_target_properties( ${PAIR_BASE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist ) endif() + +# make a KIFACE top level DLL/DSO +add_library( ${PAIR_BASE}_kiface MODULE + EXCLUDE_FROM_ALL + kiface_test.cpp + ) +target_link_libraries( ${PAIR_BASE}_kiface + common + ${wxWidgets_LIBRARIES} + ) +set_target_properties( ${PAIR_BASE}_kiface PROPERTIES + OUTPUT_NAME ${PAIR_BASE} + PREFIX ${KIFACE_PREFIX} + SUFFIX ${KIFACE_SUFFIX} + ) + +# if you build ${PAIR_BASE}, then also build ${PAIR_BASE}_kiface if out of date. +add_dependencies( ${PAIR_BASE} ${PAIR_BASE}_kiface ) + if( MAKE_LINK_MAPS ) # generate a link maps with cross reference - set_target_properties( ${PAIR_BASE}_dso PROPERTIES - LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=${PAIR_BASE}_dso.map" + set_target_properties( ${PAIR_BASE}_kiface PROPERTIES + LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=${KIFACE_PREFIX}${PAIR_BASE}${KIFACE_SUFFIX}.map" ) set_target_properties( ${PAIR_BASE} PROPERTIES diff --git a/tools/mac_test.cpp b/tools/kiface_test.cpp similarity index 100% rename from tools/mac_test.cpp rename to tools/kiface_test.cpp