Merge branch 'add-orcad-importer' into 'master'

Draft: Add OrCAD Library (OLB) Importer

See merge request kicad/code/kicad!1963
This commit is contained in:
Werni 2024-07-01 18:35:34 +00:00
commit a9d40aa34c
15 changed files with 1203 additions and 3 deletions

View File

@ -46,6 +46,10 @@ endif()
project( kicad )
if( NOT DEFINED OPENORCADPARSER_PATH )
set(OPENORCADPARSER_PATH "/YOUR/PATH/TO/OpenOrcadParser")
endif()
# Create a default build type for our QA that doesn't include `NDEBUG`
set(CMAKE_CXX_FLAGS_QABUILD "-Os -g1 -ggdb1")

View File

@ -468,6 +468,8 @@ set( COMMON_IO_SRCS
io/cadstar/cadstar_archive_parser.cpp
io/cadstar/cadstar_parts_lib_parser.cpp
# OrCAD
# Eagle
io/eagle/eagle_parser.cpp

View File

@ -140,6 +140,10 @@ const std::string FILEEXT::ProjectLocalSettingsFileExtension( "kicad_prl" );
const std::string FILEEXT::LegacySchematicFileExtension( "sch" );
const std::string FILEEXT::CadstarSchematicFileExtension( "csa" );
const std::string FILEEXT::CadstarPartsLibraryFileExtension( "lib" );
const std::string FILEEXT::OrCadDesignFileExtension( "DSN" );
const std::string FILEEXT::OrCadDesignBackupFileExtension( "DBK" );
const std::string FILEEXT::OrCadLibraryFileExtension( "OLB" );
const std::string FILEEXT::OrCadLibraryBackupFileExtension( "OBK" );
const std::string FILEEXT::KiCadSchematicFileExtension( "kicad_sch" );
const std::string FILEEXT::SpiceFileExtension( "cir" );
const std::string FILEEXT::CadstarNetlistFileExtension( "frp" );

View File

@ -1,3 +1,5 @@
include(FetchContent)
# Add all the warnings to the files
if( COMPILER_SUPPORTS_WARNINGS )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARN_FLAGS_CXX}")
@ -26,6 +28,24 @@ set_property( SOURCE sim/ngspice.cpp
NGSPICE_DLL_FILE="${NGSPICE_DLL_FILE}"
)
set(SPDLOG_FMT_EXTERNAL OFF CACHE BOOL "Use external fmt library" FORCE)
set(SPDLOG_FMT_EXTERNAL_HO OFF CACHE BOOL "Use external fmt library" FORCE)
FetchContent_Declare(
spdlog
GIT_REPOSITORY https://github.com/gabime/spdlog
GIT_TAG v1.14.1
)
FetchContent_MakeAvailable(spdlog)
FetchContent_Declare(
nameof
GIT_REPOSITORY https://github.com/Neargye/nameof
GIT_TAG v0.10.4
)
FetchContent_MakeAvailable(nameof)
include_directories( BEFORE ${INC_BEFORE} )
include_directories(
${CMAKE_SOURCE_DIR}/common
@ -37,6 +57,9 @@ include_directories(
./symbol_editor
./tools
./widgets
${CMAKE_BINARY_DIR}/_deps/spdlog-src/include
${CMAKE_BINARY_DIR}/_deps/nameof-src/include
${OPENORCADPARSER_PATH}/src
)
set( EESCHEMA_SCH_IO
@ -74,6 +97,10 @@ set( EESCHEMA_SCH_IO
sch_io/cadstar/cadstar_sch_archive_parser.cpp
sch_io/cadstar/sch_io_cadstar_archive.cpp
# OrCAD IO plugin
sch_io/orcad/orcad2kicad.cpp
sch_io/orcad/sch_io_orcad.cpp
# LTSpice IO plugin
sch_io/ltspice/ltspice_schematic.cpp
sch_io/ltspice/sch_io_ltspice.cpp
@ -550,6 +577,8 @@ set_source_files_properties( ${CMAKE_SOURCE_DIR}/common/single_top.cpp PROPERTIE
target_link_libraries( eeschema
kicommon
${wxWidgets_LIBRARIES}
spdlog::spdlog
${OPENORCADPARSER_PATH}/build/lib/libOpenOrCadParser.so
)
# the main Eeschema program, in DSO form.
@ -567,7 +596,9 @@ target_include_directories( eeschema_kiface_objects
target_link_libraries( eeschema_kiface_objects
PUBLIC
common )
common
${OPENORCADPARSER_PATH}/build/lib/libOpenOrCadParser.so
)
# Since we're not using target_link_libraries, we need to explicitly
# declare the dependency

View File

@ -0,0 +1,544 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 Dominik Wernberger <dominik.wernberger@gmx.de>
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <cmath>
#include <vector>
#include <deque>
#include "orcad2kicad.h"
#include <core/typeinfo.h>
#include <sch_shape.h>
#include <sch_text.h>
// OpenOrcadParser Headers
#include "Container.hpp"
#include "GetStreamHelper.hpp"
#include "PinShape.hpp"
#include "Primitives/PrimArc.hpp"
#include "Primitives/PrimBezier.hpp"
#include "Primitives/PrimLine.hpp"
#include "Primitives/PrimPolygon.hpp"
#include "Primitives/PrimPolyline.hpp"
#include "Primitives/PrimRect.hpp"
#include "Streams/StreamPackage.hpp"
SCH_SHAPE* convPrimArc2ARC(const PrimArc* aOrcadObj)
{
// Kicad does not support elliptical arcs, we approximate
// it by straight lines, however arcs are actually not yet
// supported!
const auto p1 = VECTOR2I( convDimIU( aOrcadObj->x1 ), convDimIU( aOrcadObj->y1 ) );
const auto p2 = VECTOR2I( convDimIU( aOrcadObj->x2 ), convDimIU( aOrcadObj->y2 ) );
const auto start = VECTOR2I( convDimIU( aOrcadObj->startX ), convDimIU( aOrcadObj->startY ) );
const auto end = VECTOR2I( convDimIU( aOrcadObj->endX ), convDimIU( aOrcadObj->endY ) );
// if( isCircle( p1, p2 ) )
// {
// std::unique_ptr<SCH_SHAPE> kicadObj = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC, LAYER_DEVICE );
// // Circle radius
// double r = std::abs( p1.x - p2.x ) / 2.0;
// // Point between end and start point
// VECTOR2D m1 = start + (end - start) / 2.0;
// // Center Point
// VECTOR2D c = VECTOR2D( p1.x + r, p1.y + r );
// // Vector from center to m1
// VECTOR2D m2 = m1 - c;
// double len_m2 = m2.EuclideanNorm();
// VECTOR2D mid_d = m2 / len_m2 * r;
// VECTOR2I mid = VECTOR2I( static_cast<int32_t>( std::round( mid_d.x ) ), static_cast<int32_t>( std::round( mid_d.y ) ));
// kicadObj->SetArcGeometry( end, mid, start );
// ksymbol->AddDrawItem( kicadObj.release() );
// }
auto segment = createEllipsoide( p1, p2, start, end );
auto stroke = STROKE_PARAMS{};
stroke.SetLineStyle( LineStyle2LINE_STYLE.at( aOrcadObj->getLineStyle() ) );
stroke.SetWidth( LineWidth2Width.at( aOrcadObj->getLineWidth() ) );
// stroke.SetColor( KIGFX::COLOR4D{0.0, 0.0, 0.0, 1.0} );
// for( auto& segment : segments )
{
segment->SetStroke( stroke );
}
return segment;
}
std::vector<SCH_SHAPE*> convPrimBezier2BEZIER(const PrimBezier* aOrcadObj)
{
const int segments = static_cast<int>( ( aOrcadObj->points.size() - 1 ) / 3 );
auto stroke = STROKE_PARAMS{};
stroke.SetLineStyle( LineStyle2LINE_STYLE.at( aOrcadObj->getLineStyle() ) );
stroke.SetWidth( LineWidth2Width.at( aOrcadObj->getLineWidth() ) );
// stroke.SetColor( KIGFX::COLOR4D{0.0, 0.0, 0.0, 1.0} );
std::vector<SCH_SHAPE*> segmentsVec;
for( int i = 0; i < segments; ++i )
{
const auto start = VECTOR2I( convDimIU( aOrcadObj->points.at(i + 0).x ), convDimIU( aOrcadObj->points.at(i + 0).y ) );
const auto c1 = VECTOR2I( convDimIU( aOrcadObj->points.at(i + 1).x ), convDimIU( aOrcadObj->points.at(i + 1).y ) );
const auto c2 = VECTOR2I( convDimIU( aOrcadObj->points.at(i + 2).x ), convDimIU( aOrcadObj->points.at(i + 2).y ) );
const auto end = VECTOR2I( convDimIU( aOrcadObj->points.at(i + 3).x ), convDimIU( aOrcadObj->points.at(i + 3).y ) );
SCH_SHAPE* kicadObj = new SCH_SHAPE( SHAPE_T::BEZIER, LAYER_DEVICE );
kicadObj->SetStroke( stroke );
kicadObj->SetStart( start );
kicadObj->SetBezierC1( c1 );
kicadObj->SetBezierC2( c2 );
kicadObj->SetEnd( end );
segmentsVec.push_back( kicadObj );
}
return segmentsVec;
}
SCH_TEXT* convPrimCommentText2SCH_TEXT(const PrimCommentText* aOrcadObj)
{
int32_t width = aOrcadObj->x2 - aOrcadObj->x1;
int32_t height = aOrcadObj->y2 - aOrcadObj->y1;
VECTOR2I pos = VECTOR2I( convDimIU( aOrcadObj->locX + width / 2 ), convDimIU( aOrcadObj->locY + height / 2 ) );
wxString text = {aOrcadObj->name.c_str(), wxConvUTF8};
SCH_TEXT* kicadObj = new SCH_TEXT( pos, text, LAYER_NOTES, SCH_TEXT_T );
return kicadObj;
}
SCH_SHAPE* convPrimEllipse2POLY(const PrimEllipse* aOrcadObj)
{
FILL_T fill;
switch( aOrcadObj->getFillStyle() )
{
case FillStyle::Solid:
fill = FILL_T::FILLED_SHAPE;
break;
case FillStyle::None:
fill = FILL_T::NO_FILL;
break;
default: // Hatching is not supported in Kicad
fill = FILL_T::NO_FILL;
break;
}
const auto p1 = VECTOR2I( convDimIU( aOrcadObj->x1 ), convDimIU( aOrcadObj->y1 ) );
const auto p2 = VECTOR2I( convDimIU( aOrcadObj->x2 ), convDimIU( aOrcadObj->y2 ) );
auto kicadObj = createEllipsoide( p1, p2, fill );
auto stroke = STROKE_PARAMS{};
stroke.SetLineStyle( LineStyle2LINE_STYLE.at( aOrcadObj->getLineStyle() ) );
stroke.SetWidth( LineWidth2Width.at( aOrcadObj->getLineWidth() ) );
// stroke.SetColor( KIGFX::COLOR4D{0.0, 0.0, 0.0, 1.0} );
kicadObj->SetStroke( stroke );
return kicadObj;
}
SCH_SHAPE* convPrimLine2POLY(const PrimLine* aOrcadObj)
{
SCH_SHAPE* kicadObj = new SCH_SHAPE( SHAPE_T::POLY, LAYER_DEVICE );
auto stroke = STROKE_PARAMS{};
stroke.SetLineStyle( LineStyle2LINE_STYLE.at( aOrcadObj->getLineStyle() ) );
stroke.SetWidth( LineWidth2Width.at( aOrcadObj->getLineWidth() ) );
// stroke.SetColor( KIGFX::COLOR4D{0.0, 0.0, 0.0, 1.0} );
kicadObj->SetStroke( stroke );
kicadObj->AddPoint( VECTOR2I( convDimIU( aOrcadObj->x1 ), convDimIU( aOrcadObj->y1 ) ) );
kicadObj->AddPoint( VECTOR2I( convDimIU( aOrcadObj->x2 ), convDimIU( aOrcadObj->y2 ) ) );
return kicadObj;
}
SCH_SHAPE* convPrimPolygon2POLY(const PrimPolygon* aOrcadObj)
{
FILL_T fill;
switch( aOrcadObj->fillStyle )
{
case FillStyle::Solid:
fill = FILL_T::FILLED_SHAPE;
break;
case FillStyle::None:
fill = FILL_T::NO_FILL;
break;
default: // Hatching is not supported in Kicad
fill = FILL_T::NO_FILL;
break;
}
SCH_SHAPE* kicadObj = new SCH_SHAPE( SHAPE_T::POLY, LAYER_DEVICE, 0, fill );
auto stroke = STROKE_PARAMS{};
stroke.SetLineStyle( LineStyle2LINE_STYLE.at( aOrcadObj->getLineStyle() ) );
stroke.SetWidth( LineWidth2Width.at( aOrcadObj->getLineWidth() ) );
// stroke.SetColor( KIGFX::COLOR4D{0.0, 0.0, 0.0, 1.0} );
kicadObj->SetStroke( stroke );
for( const auto& point : aOrcadObj->points )
{
kicadObj->AddPoint( VECTOR2I( convDimIU( point.x ), convDimIU( point.y ) ) );
}
return kicadObj;
}
SCH_SHAPE* convPrimPolyline2POLY(const PrimPolyline* aOrcadObj)
{
SCH_SHAPE* kicadObj = new SCH_SHAPE( SHAPE_T::POLY, LAYER_DEVICE );
auto stroke = STROKE_PARAMS{};
stroke.SetLineStyle( LineStyle2LINE_STYLE.at( aOrcadObj->getLineStyle() ) );
stroke.SetWidth( LineWidth2Width.at( aOrcadObj->getLineWidth() ) );
// stroke.SetColor( KIGFX::COLOR4D{0.0, 0.0, 0.0, 1.0} );
kicadObj->SetStroke( stroke );
for( const auto& point : aOrcadObj->points )
{
kicadObj->AddPoint( VECTOR2I( convDimIU( point.x ), convDimIU( point.y ) ) );
}
return kicadObj;
}
SCH_SHAPE* convPrimRect2RECTANGLE(const PrimRect* aOrcadObj)
{
SCH_SHAPE* kicadObj = new SCH_SHAPE( SHAPE_T::RECTANGLE, LAYER_DEVICE );
auto stroke = STROKE_PARAMS{};
stroke.SetLineStyle( LineStyle2LINE_STYLE.at( aOrcadObj->getLineStyle() ) );
stroke.SetWidth( LineWidth2Width.at( aOrcadObj->getLineWidth() ) );
// stroke.SetColor( KIGFX::COLOR4D{0.0, 0.0, 0.0, 1.0} );
kicadObj->SetStroke( stroke );
kicadObj->SetPosition( VECTOR2I( 0, 0 ) );
kicadObj->SetStart( VECTOR2I( convDimIU( aOrcadObj->x1 ), convDimIU( aOrcadObj->y1 ) ) );
kicadObj->SetEnd( VECTOR2I( convDimIU( aOrcadObj->x2 ), convDimIU( aOrcadObj->y2 ) ) );
return kicadObj;
}
int32_t convDimIU(int32_t aOrcadIU)
{
return aOrcadIU * 2540;
}
PIN_ORIENTATION getPinOrientation(const StructSymbolPin* aPin)
{
if( aPin->startX == aPin->hotptX )
{
if( aPin->startY > aPin->hotptY)
{
return PIN_ORIENTATION::PIN_DOWN;
}
else
{
return PIN_ORIENTATION::PIN_UP;
}
}
if( aPin->startY == aPin->hotptY )
{
if( aPin->startX > aPin->hotptX)
{
return PIN_ORIENTATION::PIN_RIGHT;
}
else
{
return PIN_ORIENTATION::PIN_LEFT;
}
}
// Pin orientation is kind of diagonal,
// return some dummy value.
return PIN_ORIENTATION::PIN_LEFT;
}
// aP1, aP2 are the points spanning the bounding rectangle of the ellipsoid
// A circle is a special ellipsoid where the bounding rectangle is square
bool isCircle(const VECTOR2I& aP1, const VECTOR2I& aP2)
{
int32_t width = std::abs( aP1.x - aP2.x );
int32_t height = std::abs( aP1.y - aP2.y );
if( width == height )
{
return true;
}
return false;
}
SCH_SHAPE* createEllipsoide(const VECTOR2I& aP1, const VECTOR2I& aP2, FILL_T aFill )
{
auto rect = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE, LAYER_DEVICE );
rect->SetPosition( aP1 );
rect->SetStart( aP1 );
rect->SetEnd( aP2 );
// Draw bounding rectangle
// return rect.release();
const double r1 = rect->GetRectangleWidth() / 2.0; //!< Radius 1
const double r2 = rect->GetRectangleHeight() / 2.0; //!< Radius 2
// Ellipsoid midpoint
const VECTOR2D mid = VECTOR2D( aP1.x + r1, aP1.y + r2 );
// Number of linear segments we approximate the ellipsoid with
const int numberSegments = 100;
SCH_SHAPE* s = new SCH_SHAPE( SHAPE_T::POLY, LAYER_DEVICE, 0, aFill );
for(int i = 0; i < numberSegments; ++i)
{
const double da = 2.0 * std::numbers::pi / (numberSegments - 1);
const double x = mid.x + r1 * std::cos(i * da);
const double y = mid.y + r2 * std::sin(i * da);
const auto p = VECTOR2I( static_cast<int32_t>(std::round(x)), static_cast<int32_t>(std::round(y)) );
s->AddPoint( p );
}
return s;
}
SCH_SHAPE* createEllipsoide(const VECTOR2I& aP1, const VECTOR2I& aP2, const VECTOR2I& aStart, const VECTOR2I& aEnd )
{
auto rect = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE, LAYER_DEVICE );
rect->SetPosition( aP1 );
rect->SetStart( aP1 );
rect->SetEnd( aP2 );
const double r1 = rect->GetRectangleWidth() / 2.0; //!< Radius 1
const double r2 = rect->GetRectangleHeight() / 2.0; //!< Radius 2
// Ellipsoid midpoint
const VECTOR2D mid = VECTOR2D( aP1.x + r1, aP1.y + r2 );
const VECTOR2D startVec = aStart - mid;
const VECTOR2D endVec = aEnd - mid;
const VECTOR2D normX = VECTOR2D( 1.0, 0.0 );
const double phi_start = std::acos( (startVec.x * normX.x + startVec.y * normX.y ) / ( startVec.EuclideanNorm() * normX.EuclideanNorm() ) );
const double phi_end = std::acos( (endVec.x * normX.x + endVec.y * normX.y ) / ( endVec.EuclideanNorm() * normX.EuclideanNorm() ) );
double delta_phi = ( endVec.x * startVec.x + endVec.y * startVec.y ) / ( endVec.EuclideanNorm() * startVec.EuclideanNorm() );
delta_phi = std::acos( delta_phi );
// Number of linear segments we approximate the ellipsoid with
const int numberSegments = 100;
SCH_SHAPE* s = new SCH_SHAPE( SHAPE_T::POLY, LAYER_DEVICE );
double phi = phi_end;
// double delta_phi = (phi_end - phi_start) - 360;
for(int i = 0; i < numberSegments; ++i)
{
const double da = delta_phi / (numberSegments - 1);
const double x = mid.x + r1 * std::cos(i * da + phi);
const double y = mid.y + r2 * std::sin(i * da + phi);
const auto p = VECTOR2I( static_cast<int32_t>(std::round(x)), static_cast<int32_t>(std::round(y)) );
s->AddPoint( p );
}
return s;
}
// OrCAD uses trailing backslashes after each character to
// indicate a overbar over that character.
// E.g. OrCAD `R\E\S\E\T\` becomes KiCAD `~{RESET}`
wxString convPinName( const std::string& aOrCadPinName )
{
struct CharProp
{
CharProp() : str{}, hasOverbar{false} { }
CharProp(const std::string& aStr, bool aHasOverbar) : str{aStr}, hasOverbar{aHasOverbar} { }
std::string str;
bool hasOverbar;
};
std::deque<CharProp> charProps;
for( const auto& c : aOrCadPinName )
{
if( c == '\\' )
{
if( !charProps.empty() )
{
charProps.back().hasOverbar = true;
}
}
else
{
charProps.push_back( {std::string{c}, false} );
}
}
std::deque<CharProp> strProps;
// Combine multiple successive short overbars to one large
for( const auto& charProp : charProps )
{
if( strProps.empty() )
{
strProps.push_back( charProp );
continue;
}
if( (charProp.hasOverbar && strProps.back().hasOverbar) ||
(!charProp.hasOverbar && !strProps.back().hasOverbar ) )
{
strProps.back().str += charProp.str;
}
else
{
strProps.push_back( charProp );
}
}
std::string kicadPinName{};
for( const auto& strProp : strProps )
{
if( strProp.hasOverbar )
{
kicadPinName += std::string{"~{"} + strProp.str + std::string{"}"};
}
else
{
kicadPinName += strProp.str;
}
}
return wxString{kicadPinName.c_str(), wxConvUTF8};
}
SCH_PIN* StreamPackage2SCH_PIN( const StreamPackage* aOrcadStream, LIB_SYMBOL* aSymbol, uint32_t aIdx )
{
if( !aOrcadStream )
{
return nullptr;
}
if( aOrcadStream->libraryParts.empty() )
{
return nullptr;
}
StructSymbolPin* pkgPin = nullptr;
if( aIdx < aOrcadStream->libraryParts.at( 0 )->symbolPins.size() )
{
pkgPin = aOrcadStream->libraryParts.at( 0 )->symbolPins.at( aIdx ).get();
}
if( !pkgPin )
{
return nullptr;
}
SCH_PIN* pin = new SCH_PIN( aSymbol );
pin->SetName( convPinName( pkgPin->name ) );
const GRAPHIC_PINSHAPE shape = OrCad2Kicad_PinShape.at( ToShapeType( pkgPin->pinShape ) );
pin->SetShape( shape );
wxString pinNumber = wxString{"", wxConvUTF8};
do
{
if( !aOrcadStream->package )
{
break;
}
if( aOrcadStream->package->devices.empty() )
{
break;
}
if( !aOrcadStream->package->devices.at( 0 ) )
{
break;
}
if( aIdx < aOrcadStream->package->devices.at( 0 )->pinMap.size() )
{
pinNumber = wxString{aOrcadStream->package->devices.at( 0 )->pinMap.at( aIdx ).c_str(), wxConvUTF8};
}
}
while( false );
pin->SetNumber( pinNumber );
const auto pinOrientation = getPinOrientation( pkgPin );
pin->SetOrientation( pinOrientation );
pin->SetType( OrCad2Kicad_PinType.at( pkgPin->portType ) );
pin->SetLength( convDimIU( pkgPin->getPinLength() ) );
pin->SetPosition( VECTOR2I( convDimIU ( pkgPin->hotptX ), convDimIU( pkgPin->hotptY ) ) );
return pin;
}

View File

@ -0,0 +1,104 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 Dominik Wernberger <dominik.wernberger@gmx.de>
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <map>
#include <pin_type.h>
#include <sch_pin.h>
#include <sch_shape.h>
#include <sch_text.h>
// OpenOrcadParser Headers
#include "Enums/LineStyle.hpp"
#include "Enums/LineWidth.hpp"
#include "PinShape.hpp"
#include "Primitives/PrimArc.hpp"
#include "Primitives/PrimBezier.hpp"
#include "Primitives/PrimCommentText.hpp"
#include "Primitives/PrimEllipse.hpp"
#include "Primitives/PrimLine.hpp"
#include "Primitives/PrimPolygon.hpp"
#include "Primitives/PrimPolyline.hpp"
#include "Primitives/PrimRect.hpp"
#include "Streams/StreamPackage.hpp"
#include "Structures/StructSymbolPin.hpp"
SCH_SHAPE* convPrimArc2ARC(const PrimArc* aObj);
std::vector<SCH_SHAPE*> convPrimBezier2BEZIER(const PrimBezier* aOrcadObj);
SCH_TEXT* convPrimCommentText2SCH_TEXT(const PrimCommentText* aOrcadObj);
SCH_SHAPE* convPrimEllipse2POLY(const PrimEllipse* aOrcadObj);
SCH_SHAPE* convPrimLine2POLY(const PrimLine* aOrcadObj);
SCH_SHAPE* convPrimPolyline2POLY(const PrimPolyline* aOrcadObj);
SCH_SHAPE* convPrimPolygon2POLY(const PrimPolygon* aOrcadObj);
SCH_SHAPE* convPrimRect2RECTANGLE(const PrimRect* aOrcadObj);
int32_t convDimIU(int32_t aOrcadIU);
PIN_ORIENTATION getPinOrientation(int32_t aStartX, int32_t aStartY, int32_t aHotptX, int32_t aHotptY);
bool isCircle(const VECTOR2I& aP1, const VECTOR2I& aP2);
SCH_SHAPE* createEllipsoide(const VECTOR2I& aP1, const VECTOR2I& aP2, FILL_T aFill = FILL_T::NO_FILL);
SCH_SHAPE* createEllipsoide(const VECTOR2I& aP1, const VECTOR2I& aP2, const VECTOR2I& aStart, const VECTOR2I& aEnd );
SCH_PIN* StreamPackage2SCH_PIN( const StreamPackage* aOrcadStream, LIB_SYMBOL* aSymbol, uint32_t aIdx );
const std::map<ShapeType, GRAPHIC_PINSHAPE> OrCad2Kicad_PinShape = {
{ShapeType::Clock, GRAPHIC_PINSHAPE::CLOCK},
{ShapeType::Dot, GRAPHIC_PINSHAPE::INVERTED},
{ShapeType::DotClock, GRAPHIC_PINSHAPE::INVERTED_CLOCK},
{ShapeType::Line, GRAPHIC_PINSHAPE::LINE},
{ShapeType::Short, GRAPHIC_PINSHAPE::LINE},
{ShapeType::ShortClock, GRAPHIC_PINSHAPE::CLOCK},
{ShapeType::ShortDot, GRAPHIC_PINSHAPE::INVERTED},
{ShapeType::ShortDotClock, GRAPHIC_PINSHAPE::INVERTED_CLOCK},
{ShapeType::ZeroLength, GRAPHIC_PINSHAPE::LINE}
};
const std::map<PortType, ELECTRICAL_PINTYPE> OrCad2Kicad_PinType = {
{PortType::Input, ELECTRICAL_PINTYPE::PT_INPUT},
{PortType::Bidirectional, ELECTRICAL_PINTYPE::PT_BIDI},
{PortType::Output, ELECTRICAL_PINTYPE::PT_OUTPUT},
{PortType::OpenCollector, ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR},
{PortType::Passive, ELECTRICAL_PINTYPE::PT_PASSIVE},
{PortType::ThreeState, ELECTRICAL_PINTYPE::PT_TRISTATE},
{PortType::OpenEmitter, ELECTRICAL_PINTYPE::PT_OPENEMITTER},
{PortType::Power, ELECTRICAL_PINTYPE::PT_UNSPECIFIED} // We can't know whether to use PT_POWER_IN or PT_POWER_OUT
};
const std::map<LineWidth, int> LineWidth2Width = {
{LineWidth::Thin, 3 * 254},
{LineWidth::Medium, 9 * 254},
{LineWidth::Wide, 12 * 254},
{LineWidth::Default, 0} // Defaults to 6 * 254
};
const std::map<LineStyle, LINE_STYLE> LineStyle2LINE_STYLE = {
{LineStyle::Solid, LINE_STYLE::SOLID},
{LineStyle::Dash, LINE_STYLE::DASH},
{LineStyle::Dot, LINE_STYLE::DOT},
{LineStyle::DashDot, LINE_STYLE::DASHDOT},
{LineStyle::DashDotDot, LINE_STYLE::DASHDOTDOT},
{LineStyle::Default, LINE_STYLE::DEFAULT}
};

View File

@ -0,0 +1,397 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 Dominik Wernberger <dominik.wernberger@gmx.de>
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <cmath>
#include <filesystem>
#include <memory>
#include "sch_io_orcad.h"
#include "orcad2kicad.h"
#include <kiplatform/environment.h>
#include <project_sch.h>
#include <sch_screen.h>
#include <sch_shape.h>
#include <sch_sheet.h>
#include <sch_text.h>
#include <schematic.h>
#include <string_utils.h>
#include <wildcards_and_files_ext.h>
#include <wx/log.h>
#include <wx/stdstream.h>
#include <wx/zipstrm.h>
#include <nlohmann/json.hpp>
#include <core/map_helpers.h>
#include <wx/wfstream.h>
// OpenOrcadParser Headers
#include "Container.hpp"
#include "Enums/DirectoryType.hpp"
#include "GetStreamHelper.hpp"
#include "PinShape.hpp"
#include "Primitives/PrimArc.hpp"
#include "Primitives/PrimBezier.hpp"
#include "Primitives/PrimCommentText.hpp"
#include "Primitives/PrimLine.hpp"
#include "Primitives/PrimPolygon.hpp"
#include "Primitives/PrimPolyline.hpp"
#include "Primitives/PrimRect.hpp"
#include "Streams/StreamPackage.hpp"
namespace fs = std::filesystem;
Database parseDatabase(const wxString& aLibraryPath)
{
const fs::path dbPath{std::string{aLibraryPath.mb_str()}};
Container parser{dbPath, ParserConfig{}};
// ContainerContext& ctx = parser.getContext();
parser.parseDatabaseFile();
Database db = parser.getDb();
return db;
}
void dummy_create_in_schematic(SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet)
{
std::unique_ptr<LIB_SYMBOL> ksymbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
LIB_ID libId;
libId.Parse( "foo", true );
ksymbol->SetPower();
ksymbol->SetLibId( libId );
ksymbol->SetName( "Name" );
ksymbol->GetReferenceField().SetText( wxS( "#PWR" ) );
ksymbol->GetReferenceField().SetVisible( false );
ksymbol->GetValueField().SetText( "Name" );
ksymbol->GetValueField().SetVisible( true );
ksymbol->SetDescription( wxString::Format( _( "Power symbol creates a global "
"label with name '%s'" ),
"Name" ) );
ksymbol->SetKeyWords( wxS( "power-flag" ) );
ksymbol->SetShowPinNames( false );
ksymbol->SetShowPinNumbers( false );
std::unique_ptr<SCH_PIN> pin = std::make_unique<SCH_PIN>( ksymbol.get() );
pin->SetName( "Name" );
pin->SetNumber( wxS( "1" ) );
pin->SetOrientation( PIN_ORIENTATION::PIN_DOWN );
pin->SetType( ELECTRICAL_PINTYPE::PT_POWER_IN );
pin->SetLength( 0 );
ksymbol->AddDrawItem( pin.release() );
LIB_SYMBOL* pwrLibSym = ksymbol.release();
std::unique_ptr<SCH_SYMBOL> schSym = std::make_unique<SCH_SYMBOL>(
*pwrLibSym, libId, &aSchematic->CurrentSheet(), 0 );
VECTOR2D pos( 0, 0 );
schSym->SetPosition( pos );
schSym->SetRef( &aSchematic->CurrentSheet(), "asdf" );
SCH_SCREEN* screen = aRootSheet->GetScreen();
screen->Append( schSym.release() );
}
bool SCH_IO_ORCAD::CanReadSchematicFile( const wxString& aFileName ) const
{
// Not yet supported
return false;
}
bool SCH_IO_ORCAD::CanReadLibrary( const wxString& aFileName ) const
{
return true;
}
int SCH_IO_ORCAD::GetModifyHash() const
{
return 0;
}
void SCH_IO_ORCAD::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
const wxString& aLibraryPath,
const STRING_UTF8_MAP* aProperties )
{
if( !m_db.has_value() )
{
m_db = parseDatabase( aLibraryPath );
}
const auto dir = getDirectoryStreamFromDb<StreamPackagesDirectory>(
m_db.value(), DirectoryType::PackagesDirectory );
if( dir )
{
for( const auto& item : dir->items )
{
std::cout << "Enumerate package " << item.name << std::endl;
aSymbolNameList.Add( wxString{item.name.c_str(), wxConvUTF8} );
}
}
std::cout << "Enumerated " << aSymbolNameList.size() << " packages" << std::endl;
}
void SCH_IO_ORCAD::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
const wxString& aLibraryPath,
const STRING_UTF8_MAP* aProperties )
{
wxArrayString aSymbolNameList{};
EnumerateSymbolLib( aSymbolNameList, aLibraryPath, aProperties );
for(const auto& name : aSymbolNameList )
{
std::cout << "Loading package " << name << std::endl;
const auto symbol = LoadSymbol( aLibraryPath, name, aProperties );
aSymbolList.push_back( symbol );
}
std::cout << "Loaded " << aSymbolNameList.size() << " packages" << std::endl;
}
LIB_SYMBOL* SCH_IO_ORCAD::LoadSymbol( const wxString& aLibraryPath,
const wxString& aAliasName,
const STRING_UTF8_MAP* aProperties )
{
std::cout << "Loading " << aAliasName << std::endl;
if( !m_db.has_value() )
{
m_db = parseDatabase( aLibraryPath );
}
std::shared_ptr<StreamPackage> package{};
for( auto& stream : m_db.value().mStreams )
{
if( stream->mCtx.mCfbfStreamLocation.matches_pattern({{"Packages"}, {std::string{aAliasName.mb_str()}}}) )
{
package = std::dynamic_pointer_cast<StreamPackage>( stream );
break;
}
}
LIB_SYMBOL* ksymbol = new LIB_SYMBOL( wxEmptyString );
if(package)
{
wxString name{"Dummy", wxConvUTF8};
wxString refDes{"X", wxConvUTF8};
wxString pcbFootprint{"", wxConvUTF8};
if( package->package )
{
name = wxString{package->package->name.c_str(), wxConvUTF8};
refDes = wxString{package->package->refDes.c_str(), wxConvUTF8};
pcbFootprint = wxString{package->package->pcbFootprint.c_str(), wxConvUTF8};
}
for( const auto& libraryPart : package->libraryParts )
{
if( !libraryPart )
{
continue;
}
for( const auto& primitive : libraryPart->primitives )
{
switch( primitive->getObjectType() )
{
case Primitive::Arc:
{
const auto orcadObj = dynamic_cast<const PrimArc*>( primitive.get() );
auto kicadObj = convPrimArc2ARC( orcadObj );
ksymbol->AddDrawItem( kicadObj );
break;
}
case Primitive::Bezier:
{
const auto orcadObj = dynamic_cast<const PrimBezier*>( primitive.get() );
auto segments = convPrimBezier2BEZIER( orcadObj );
for( auto& segment : segments )
{
ksymbol->AddDrawItem( segment );
}
break;
}
case Primitive::CommentText:
{
const auto orcadObj = dynamic_cast<const PrimCommentText*>( primitive.get() );
auto kicadObj = convPrimCommentText2SCH_TEXT( orcadObj );
ksymbol->AddDrawItem( kicadObj );
break;
}
case Primitive::Ellipse:
{
const auto orcadObj = dynamic_cast<const PrimEllipse*>( primitive.get() );
auto kicadObj = convPrimEllipse2POLY( orcadObj );
ksymbol->AddDrawItem( kicadObj );
break;
}
case Primitive::Line:
{
const auto orcadObj = dynamic_cast<const PrimLine*>( primitive.get() );
auto kicadObj = convPrimLine2POLY( orcadObj );
ksymbol->AddDrawItem( kicadObj );
break;
}
case Primitive::Polygon:
{
const auto orcadObj = dynamic_cast<const PrimPolygon*>( primitive.get() );
auto kicadObj = convPrimPolygon2POLY( orcadObj );
ksymbol->AddDrawItem( kicadObj );
break;
}
case Primitive::Polyline:
{
const auto orcadObj = dynamic_cast<const PrimPolyline*>( primitive.get() );
auto kicadObj = convPrimPolyline2POLY( orcadObj );
ksymbol->AddDrawItem( kicadObj );
break;
}
case Primitive::Rect:
{
const auto orcadObj = dynamic_cast<const PrimRect*>( primitive.get() );
auto kicadObj = convPrimRect2RECTANGLE( orcadObj );
ksymbol->AddDrawItem( kicadObj );
break;
}
default:
std::cout << "Unimplemented Primitive detected" << std::endl;
break;
}
}
for( size_t i = 0U; i < libraryPart->symbolPins.size(); ++i )
{
auto pin = StreamPackage2SCH_PIN( package.get(), ksymbol, i );
if( pin )
{
ksymbol->AddDrawItem( pin );
}
}
}
LIB_ID libId{ wxS( "Library" ), name };
ksymbol->SetLibId( libId );
ksymbol->SetName( name );
ksymbol->GetReferenceField().SetText( refDes );
ksymbol->GetReferenceField().SetVisible( true );
ksymbol->GetFootprintField().SetText( pcbFootprint );
ksymbol->GetFootprintField().SetVisible( false );
ksymbol->GetValueField().SetText( wxS( "" ) );
ksymbol->GetValueField().SetVisible( true );
bool pinNameVisible = true;
bool pinNumberVisible = true;
if( package && !package->libraryParts.empty() )
{
const auto& generalProperties = package->libraryParts.at(0)->generalProperties;
pinNameVisible = generalProperties.pinNameVisible;
pinNumberVisible = generalProperties.pinNumberVisible;
}
ksymbol->SetShowPinNames( pinNameVisible );
ksymbol->SetShowPinNumbers( pinNumberVisible );
}
return ksymbol;
}
SCH_SHEET* SCH_IO_ORCAD::LoadSchematicFile( const wxString& aFileName, SCHEMATIC* aSchematic,
SCH_SHEET* aAppendToMe,
const STRING_UTF8_MAP* aProperties )
{
std::cout << "Loading schematic " << std::endl;
wxCHECK( !aFileName.IsEmpty() && aSchematic, nullptr );
SCH_SHEET* rootSheet = nullptr;
if( aAppendToMe )
{
wxCHECK_MSG( aSchematic->IsValid(), nullptr,
wxS( "Can't append to a schematic with no root!" ) );
rootSheet = &aSchematic->Root();
}
else
{
rootSheet = new SCH_SHEET( aSchematic );
rootSheet->SetFileName( aFileName );
aSchematic->SetRoot( rootSheet );
}
if( !rootSheet->GetScreen() )
{
SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
screen->SetFileName( aFileName );
rootSheet->SetScreen( screen );
}
SYMBOL_LIB_TABLE* libTable = PROJECT_SCH::SchSymbolLibTable( &aSchematic->Prj() );
wxCHECK_MSG( libTable, nullptr, wxS( "Could not load symbol lib table." ) );
// @todo
// LoadSchematic( aSchematic, rootSheet, aFileName );
dummy_create_in_schematic(aSchematic, rootSheet);
aSchematic->CurrentSheet().UpdateAllScreenReferences();
return rootSheet;
}

View File

@ -0,0 +1,92 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 Dominik Wernberger <dominik.wernberger@gmx.de>
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef SCH_IO_ORCAD_H_
#define SCH_IO_ORCAD_H_
#include <optional>
#include <sch_io/sch_io.h>
#include <sch_io/sch_io_mgr.h>
#include <reporter.h>
#include <wildcards_and_files_ext.h>
#include <wx/arrstr.h>
// OpenOrcadParser headers
#include "Database.hpp"
class SCH_SHEET;
class SCH_SCREEN;
class SCH_IO_ORCAD : public SCH_IO
{
public:
SCH_IO_ORCAD() : SCH_IO( wxS( "OrCAD Database" ) ), m_db{}
{
m_reporter = &WXLOG_REPORTER::GetInstance();
}
~SCH_IO_ORCAD() {}
const IO_BASE::IO_FILE_DESC GetSchematicFileDesc() const override
{
return IO_BASE::IO_FILE_DESC( _HKI( "OrCAD Design files" ),
{ FILEEXT::OrCadDesignFileExtension, FILEEXT::OrCadDesignBackupFileExtension } );
}
const IO_BASE::IO_FILE_DESC GetLibraryDesc() const override
{
return IO_BASE::IO_FILE_DESC( _HKI( "OrCAD Library files" ),
{ FILEEXT::OrCadLibraryFileExtension, FILEEXT::OrCadLibraryBackupFileExtension } );
}
bool CanReadSchematicFile( const wxString& aFileName ) const override;
bool CanReadLibrary( const wxString& aFileName ) const override;
int GetModifyHash() const override;
SCH_SHEET* LoadSchematicFile( const wxString& aFileName, SCHEMATIC* aSchematic,
SCH_SHEET* aAppendToMe = nullptr,
const STRING_UTF8_MAP* aProperties = nullptr ) override;
void EnumerateSymbolLib( wxArrayString& aSymbolNameList, const wxString& aLibraryPath,
const STRING_UTF8_MAP* aProperties = nullptr ) override;
void EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList, const wxString& aLibraryPath,
const STRING_UTF8_MAP* aProperties = nullptr ) override;
LIB_SYMBOL* LoadSymbol( const wxString& aLibraryPath, const wxString& aAliasName,
const STRING_UTF8_MAP* aProperties = nullptr ) override;
bool IsLibraryWritable( const wxString& aLibraryPath ) override { return false; }
private:
std::optional<Database> m_db;
};
#endif // SCH_IO_ORCAD_H_

View File

@ -34,6 +34,7 @@
#include <sch_io/easyedapro/sch_io_easyedapro.h>
#include <sch_io/database/sch_io_database.h>
#include <sch_io/ltspice/sch_io_ltspice.h>
#include <sch_io/orcad/sch_io_orcad.h>
#include <sch_io/http_lib/sch_io_http_lib.h>
#include <common.h> // for ExpandEnvVarSubstitutions
@ -74,6 +75,7 @@ SCH_IO* SCH_IO_MGR::FindPlugin( SCH_FILE_T aFileType )
case SCH_EASYEDA: return new SCH_IO_EASYEDA();
case SCH_EASYEDAPRO: return new SCH_IO_EASYEDAPRO();
case SCH_LTSPICE: return new SCH_IO_LTSPICE();
case SCH_ORCAD: return new SCH_IO_ORCAD();
case SCH_HTTP: return new SCH_IO_HTTP_LIB();
default: return nullptr;
}
@ -97,6 +99,7 @@ const wxString SCH_IO_MGR::ShowType( SCH_FILE_T aType )
case SCH_EASYEDA: return wxString( wxT( "EasyEDA (JLCEDA) Std" ) );
case SCH_EASYEDAPRO: return wxString( wxT( "EasyEDA (JLCEDA) Pro" ) );
case SCH_LTSPICE: return wxString( wxT( "LTspice" ) );
case SCH_ORCAD: return wxString( wxT( "OrCAD" ) );
case SCH_HTTP: return wxString( wxT( "HTTP" ) );
default: return wxString::Format( _( "Unknown SCH_FILE_T value: %d" ),
aType );
@ -128,6 +131,8 @@ SCH_IO_MGR::SCH_FILE_T SCH_IO_MGR::EnumFromStr( const wxString& aType )
return SCH_EASYEDAPRO;
else if( aType == wxT( "LTspice" ) )
return SCH_LTSPICE;
else if( aType == wxT( "OrCAD" ) )
return SCH_ORCAD;
else if( aType == wxT( "HTTP" ) )
return SCH_HTTP;

View File

@ -68,6 +68,7 @@ public:
SCH_EASYEDA, ///< EasyEDA Std schematic file
SCH_EASYEDAPRO, ///< EasyEDA Pro archive
SCH_LTSPICE, ///< LtSpice Schematic format
SCH_ORCAD, ///< OrCAD file format
SCH_HTTP, ///< KiCad HTTP library
// Add your schematic type here.

View File

@ -133,6 +133,10 @@ public:
static const std::string KiCadSchematicFileExtension;
static const std::string SpiceFileExtension;
static const std::string CadstarNetlistFileExtension;
static const std::string OrCadDesignFileExtension;
static const std::string OrCadDesignBackupFileExtension;
static const std::string OrCadLibraryFileExtension;
static const std::string OrCadLibraryBackupFileExtension;
static const std::string OrCadPcb2NetlistFileExtension;
static const std::string NetlistFileExtension;
static const std::string AllegroNetlistFileExtension;

View File

@ -109,6 +109,7 @@ PRIVATE
${GDI_PLUS_LIBRARIES}
Boost::headers
Boost::unit_test_framework
${OPENORCADPARSER_PATH}/build/lib/libOpenOrCadParser.so
)
# Eeschema tests, so pretend to be eeschema (for units, etc)

View File

@ -93,6 +93,7 @@ PRIVATE
${GDI_PLUS_LIBRARIES}
Boost::headers
Boost::unit_test_framework
${OPENORCADPARSER_PATH}/build/lib/libOpenOrCadParser.so
)
if( KICAD_SPICE_QA AND MSVC )

View File

@ -21,6 +21,8 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
include(FetchContent)
# Disable shared library building for all thirdparty libraries
set( BUILD_SHARED_LIBS OFF )
@ -32,6 +34,13 @@ set( BUILD_SHARED_LIBS OFF )
# instead of with cmake_policy will apply the change to the third-party CMakeLists files.
set( CMAKE_POLICY_DEFAULT_CMP0077 NEW )
FetchContent_Declare(
fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt
GIT_TAG 10.2.1
)
FetchContent_MakeAvailable(fmt)
set( ARGPARSE_INSTALL OFF )
add_subdirectory( argparse )
add_subdirectory( clipper )
@ -40,8 +49,8 @@ add_subdirectory( compoundfilereader )
add_subdirectory( delaunator )
add_subdirectory( dxflib_qcad )
add_subdirectory( expected )
set( FMT_INSTALL OFF )
add_subdirectory( fmt )
# set( FMT_INSTALL OFF )
# add_subdirectory( fmt )
add_subdirectory( gzip-hpp )
add_subdirectory( lemon )
add_subdirectory( libcontext )

View File

@ -30,6 +30,7 @@ message(STATUS "nanodbc compile: C++${CMAKE_CXX_STANDARD}")
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_COMPILER_IS_GNUCXX)
include(CheckCXXCompilerFlag)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
string(REGEX REPLACE "[/-]W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
if (NOT (CMAKE_VERSION VERSION_LESS 3.6.0)) # Compiler features for Intel in CMake 3.6+