You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
436 lines
15 KiB
436 lines
15 KiB
cmake_minimum_required(VERSION 3.18)
|
|
project(pyngspice VERSION 43.0.0 LANGUAGES C CXX)
|
|
|
|
# ============================================================================
|
|
# Options
|
|
# ============================================================================
|
|
option(BUILD_PYTHON_BINDINGS "Build Python bindings" ON)
|
|
option(ENABLE_XSPICE "Enable XSPICE code models" ON)
|
|
option(ENABLE_OSDI "Enable OSDI (Verilog-A) support" ON)
|
|
option(ENABLE_CIDER "Enable CIDER numerical device models" OFF) # Disabled - needs special KLU setup
|
|
option(ENABLE_KLU "Enable KLU sparse matrix solver" OFF) # Disabled - needs complex build setup
|
|
|
|
# ============================================================================
|
|
# Compiler settings
|
|
# ============================================================================
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_C_STANDARD 11)
|
|
set(CMAKE_C_EXTENSIONS ON) # Use gnu11 instead of c11 for better complex support
|
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
|
|
# Suppress warnings
|
|
if(MSVC)
|
|
add_compile_options(/W3 /wd4996 /wd4267 /wd4244 /wd4018 /wd4090 /wd4101 /wd4146)
|
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS)
|
|
add_definitions(-DWIN32 -D_WINDOWS)
|
|
else()
|
|
add_compile_options(-Wall -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -Wno-format)
|
|
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
|
add_compile_options(-Wno-maybe-uninitialized -Wno-unused-but-set-variable)
|
|
endif()
|
|
endif()
|
|
|
|
# ============================================================================
|
|
# Platform detection
|
|
# ============================================================================
|
|
if(WIN32)
|
|
set(PLATFORM_WINDOWS TRUE)
|
|
elseif(APPLE)
|
|
set(PLATFORM_MACOS TRUE)
|
|
elseif(UNIX)
|
|
set(PLATFORM_LINUX TRUE)
|
|
endif()
|
|
|
|
# ============================================================================
|
|
# Find dependencies
|
|
# ============================================================================
|
|
find_package(Python3 REQUIRED COMPONENTS Interpreter Development.Module NumPy)
|
|
|
|
# Find pybind11 — try system install first, then fall back to pip-installed
|
|
find_package(pybind11 CONFIG QUIET)
|
|
if(NOT pybind11_FOUND)
|
|
# pybind11 is a build dependency in pyproject.toml, so pip has already
|
|
# installed it into the build environment. Find it via the Python package.
|
|
execute_process(
|
|
COMMAND ${Python3_EXECUTABLE} -c
|
|
"import pybind11; print(pybind11.get_cmake_dir())"
|
|
OUTPUT_VARIABLE PYBIND11_CMAKE_DIR
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
RESULT_VARIABLE PYBIND11_RESULT
|
|
)
|
|
if(PYBIND11_RESULT EQUAL 0)
|
|
list(APPEND CMAKE_PREFIX_PATH ${PYBIND11_CMAKE_DIR})
|
|
find_package(pybind11 CONFIG REQUIRED)
|
|
else()
|
|
message(FATAL_ERROR
|
|
"pybind11 not found. Install it with: pip install pybind11>=2.11")
|
|
endif()
|
|
endif()
|
|
|
|
# Math library on Unix
|
|
if(UNIX AND NOT APPLE)
|
|
find_library(M_LIBRARY m REQUIRED)
|
|
endif()
|
|
|
|
find_package(Threads REQUIRED)
|
|
|
|
# ============================================================================
|
|
# Source directories
|
|
# ============================================================================
|
|
set(NGSPICE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
|
|
|
# ============================================================================
|
|
# Include directories
|
|
# ============================================================================
|
|
set(NGSPICE_INCLUDE_DIRS
|
|
${CMAKE_CURRENT_SOURCE_DIR}/visualc/src/include # Windows config.h
|
|
${NGSPICE_SRC}
|
|
${NGSPICE_SRC}/include
|
|
${NGSPICE_SRC}/include/cppduals # For HICUM2 duals library
|
|
${NGSPICE_SRC}/include/ngspice
|
|
${NGSPICE_SRC}/spicelib/devices
|
|
${NGSPICE_SRC}/spicelib/analysis
|
|
${NGSPICE_SRC}/spicelib/parser
|
|
${NGSPICE_SRC}/maths/dense
|
|
${NGSPICE_SRC}/maths/sparse
|
|
${NGSPICE_SRC}/maths/ni
|
|
${NGSPICE_SRC}/maths/deriv
|
|
${NGSPICE_SRC}/maths/cmaths
|
|
${NGSPICE_SRC}/maths/misc
|
|
${NGSPICE_SRC}/maths/poly
|
|
${NGSPICE_SRC}/maths/fft
|
|
${NGSPICE_SRC}/frontend
|
|
${NGSPICE_SRC}/frontend/plotting
|
|
${NGSPICE_SRC}/frontend/parser
|
|
${NGSPICE_SRC}/frontend/help
|
|
${NGSPICE_SRC}/frontend/numparam
|
|
${NGSPICE_SRC}/frontend/trannoise
|
|
${NGSPICE_SRC}/misc
|
|
${NGSPICE_SRC}/ciderlib/input
|
|
${NGSPICE_SRC}/ciderlib/support
|
|
${NGSPICE_SRC}/ciderlib/oned
|
|
${NGSPICE_SRC}/ciderlib/twod
|
|
${NGSPICE_SRC}/xspice/cm
|
|
${NGSPICE_SRC}/xspice/cmpp
|
|
${NGSPICE_SRC}/xspice/evt
|
|
${NGSPICE_SRC}/xspice/enh
|
|
${NGSPICE_SRC}/xspice/ipc
|
|
${NGSPICE_SRC}/xspice/idn
|
|
${NGSPICE_SRC}/xspice/mif
|
|
${NGSPICE_SRC}/xspice/icm
|
|
${NGSPICE_SRC}/osdi
|
|
)
|
|
|
|
# ============================================================================
|
|
# Build date/version info
|
|
# ============================================================================
|
|
string(TIMESTAMP NGSPICE_BUILD_DATE "%Y-%m-%d")
|
|
|
|
# ============================================================================
|
|
# Compile definitions
|
|
# ============================================================================
|
|
set(NGSPICE_DEFINITIONS
|
|
-DNGSPICEDLL
|
|
-DSHARED_MODULE
|
|
-DSIMULATOR
|
|
-DHAS_PROGREP
|
|
-DNG_SHARED_BUILD
|
|
-DNGSPICEBUILDDATE="${NGSPICE_BUILD_DATE}"
|
|
)
|
|
|
|
# MinGW-specific: nothing special needed now since we patched cmath1.c
|
|
|
|
if(ENABLE_XSPICE)
|
|
list(APPEND NGSPICE_DEFINITIONS -DXSPICE)
|
|
endif()
|
|
|
|
if(ENABLE_OSDI)
|
|
list(APPEND NGSPICE_DEFINITIONS -DOSDI)
|
|
endif()
|
|
|
|
if(ENABLE_CIDER)
|
|
list(APPEND NGSPICE_DEFINITIONS -DCIDER)
|
|
endif()
|
|
|
|
if(ENABLE_KLU)
|
|
list(APPEND NGSPICE_DEFINITIONS -DKLU)
|
|
endif()
|
|
|
|
# ============================================================================
|
|
# Collect ngspice source files
|
|
# ============================================================================
|
|
|
|
# Frontend sources
|
|
file(GLOB FRONTEND_SOURCES
|
|
${NGSPICE_SRC}/frontend/*.c
|
|
)
|
|
|
|
# Frontend subdirectories
|
|
file(GLOB FRONTEND_PARSER_SOURCES ${NGSPICE_SRC}/frontend/parser/*.c)
|
|
file(GLOB FRONTEND_NUMPARAM_SOURCES ${NGSPICE_SRC}/frontend/numparam/*.c)
|
|
file(GLOB FRONTEND_TRANNOISE_SOURCES ${NGSPICE_SRC}/frontend/trannoise/*.c)
|
|
file(GLOB FRONTEND_HELP_SOURCES ${NGSPICE_SRC}/frontend/help/*.c)
|
|
file(GLOB FRONTEND_PLOTTING_SOURCES ${NGSPICE_SRC}/frontend/plotting/*.c)
|
|
|
|
# Math sources
|
|
file(GLOB MATHS_SPARSE_SOURCES ${NGSPICE_SRC}/maths/sparse/*.c)
|
|
file(GLOB MATHS_DENSE_SOURCES ${NGSPICE_SRC}/maths/dense/*.c)
|
|
file(GLOB MATHS_NI_SOURCES ${NGSPICE_SRC}/maths/ni/*.c)
|
|
file(GLOB MATHS_DERIV_SOURCES ${NGSPICE_SRC}/maths/deriv/*.c)
|
|
file(GLOB MATHS_CMATHS_SOURCES ${NGSPICE_SRC}/maths/cmaths/*.c)
|
|
file(GLOB MATHS_MISC_SOURCES ${NGSPICE_SRC}/maths/misc/*.c)
|
|
file(GLOB MATHS_POLY_SOURCES ${NGSPICE_SRC}/maths/poly/*.c)
|
|
file(GLOB MATHS_FFT_SOURCES ${NGSPICE_SRC}/maths/fft/*.c)
|
|
|
|
# Spicelib sources
|
|
file(GLOB SPICELIB_ANALYSIS_SOURCES ${NGSPICE_SRC}/spicelib/analysis/*.c)
|
|
file(GLOB SPICELIB_PARSER_SOURCES ${NGSPICE_SRC}/spicelib/parser/*.c)
|
|
|
|
# Device sources - collect all device model subdirectories
|
|
file(GLOB_RECURSE SPICELIB_DEVICES_C_SOURCES ${NGSPICE_SRC}/spicelib/devices/*.c)
|
|
# HICUM2 .cpp files use the "duals" library for automatic differentiation (header-only, included in ngspice)
|
|
file(GLOB_RECURSE SPICELIB_DEVICES_CPP_SOURCES ${NGSPICE_SRC}/spicelib/devices/*.cpp)
|
|
set(SPICELIB_DEVICES_SOURCES ${SPICELIB_DEVICES_C_SOURCES} ${SPICELIB_DEVICES_CPP_SOURCES})
|
|
# Exclude KLU-specific binding files when KLU is disabled
|
|
if(NOT ENABLE_KLU)
|
|
list(FILTER SPICELIB_DEVICES_SOURCES EXCLUDE REGEX "bindCSC\\.c$")
|
|
endif()
|
|
|
|
# Misc sources
|
|
file(GLOB MISC_SOURCES ${NGSPICE_SRC}/misc/*.c)
|
|
|
|
# CIDER sources (if enabled)
|
|
if(ENABLE_CIDER)
|
|
file(GLOB CIDER_INPUT_SOURCES ${NGSPICE_SRC}/ciderlib/input/*.c)
|
|
file(GLOB CIDER_SUPPORT_SOURCES ${NGSPICE_SRC}/ciderlib/support/*.c)
|
|
file(GLOB CIDER_ONED_SOURCES ${NGSPICE_SRC}/ciderlib/oned/*.c)
|
|
file(GLOB CIDER_TWOD_SOURCES ${NGSPICE_SRC}/ciderlib/twod/*.c)
|
|
set(CIDER_SOURCES
|
|
${CIDER_INPUT_SOURCES}
|
|
${CIDER_SUPPORT_SOURCES}
|
|
${CIDER_ONED_SOURCES}
|
|
${CIDER_TWOD_SOURCES}
|
|
)
|
|
endif()
|
|
|
|
# XSPICE sources (if enabled)
|
|
if(ENABLE_XSPICE)
|
|
file(GLOB XSPICE_CM_SOURCES ${NGSPICE_SRC}/xspice/cm/*.c)
|
|
file(GLOB XSPICE_EVT_SOURCES ${NGSPICE_SRC}/xspice/evt/*.c)
|
|
file(GLOB XSPICE_ENH_SOURCES ${NGSPICE_SRC}/xspice/enh/*.c)
|
|
file(GLOB XSPICE_IPC_SOURCES ${NGSPICE_SRC}/xspice/ipc/*.c)
|
|
file(GLOB XSPICE_IDN_SOURCES ${NGSPICE_SRC}/xspice/idn/*.c)
|
|
file(GLOB XSPICE_MIF_SOURCES ${NGSPICE_SRC}/xspice/mif/*.c)
|
|
# ICM (code models) built separately
|
|
set(XSPICE_SOURCES
|
|
${XSPICE_CM_SOURCES}
|
|
${XSPICE_EVT_SOURCES}
|
|
${XSPICE_ENH_SOURCES}
|
|
${XSPICE_IPC_SOURCES}
|
|
${XSPICE_IDN_SOURCES}
|
|
${XSPICE_MIF_SOURCES}
|
|
)
|
|
# Exclude KLU-specific binding files when KLU is disabled
|
|
if(NOT ENABLE_KLU)
|
|
list(FILTER XSPICE_SOURCES EXCLUDE REGEX "bindCSC\\.c$")
|
|
endif()
|
|
endif()
|
|
|
|
# OSDI sources (if enabled)
|
|
if(ENABLE_OSDI)
|
|
file(GLOB OSDI_SOURCES ${NGSPICE_SRC}/osdi/*.c)
|
|
endif()
|
|
|
|
# KLU sources (if enabled)
|
|
if(ENABLE_KLU)
|
|
# KLU sources are in src/maths/KLU directory
|
|
file(GLOB KLU_SOURCES ${NGSPICE_SRC}/maths/KLU/*.c)
|
|
list(APPEND NGSPICE_INCLUDE_DIRS ${NGSPICE_SRC}/maths/KLU)
|
|
endif()
|
|
|
|
# Main ngspice files
|
|
set(NGSPICE_MAIN_SOURCES
|
|
${NGSPICE_SRC}/sharedspice.c
|
|
${NGSPICE_SRC}/conf.c
|
|
${NGSPICE_SRC}/ngspice.c # Contains SIMinfo definition
|
|
)
|
|
|
|
# MSVC compatibility
|
|
if(MSVC AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/visualc/src/msvc-compat.c)
|
|
list(APPEND NGSPICE_MAIN_SOURCES
|
|
${CMAKE_CURRENT_SOURCE_DIR}/visualc/src/msvc-compat.c
|
|
)
|
|
endif()
|
|
|
|
# ============================================================================
|
|
# Combine all ngspice sources
|
|
# ============================================================================
|
|
set(ALL_NGSPICE_SOURCES
|
|
${NGSPICE_MAIN_SOURCES}
|
|
${FRONTEND_SOURCES}
|
|
${FRONTEND_PARSER_SOURCES}
|
|
${FRONTEND_NUMPARAM_SOURCES}
|
|
${FRONTEND_TRANNOISE_SOURCES}
|
|
${FRONTEND_HELP_SOURCES}
|
|
${FRONTEND_PLOTTING_SOURCES}
|
|
${MATHS_SPARSE_SOURCES}
|
|
${MATHS_DENSE_SOURCES}
|
|
${MATHS_NI_SOURCES}
|
|
${MATHS_DERIV_SOURCES}
|
|
${MATHS_CMATHS_SOURCES}
|
|
${MATHS_MISC_SOURCES}
|
|
${MATHS_POLY_SOURCES}
|
|
${MATHS_FFT_SOURCES}
|
|
${SPICELIB_ANALYSIS_SOURCES}
|
|
${SPICELIB_PARSER_SOURCES}
|
|
${SPICELIB_DEVICES_SOURCES}
|
|
${MISC_SOURCES}
|
|
)
|
|
|
|
if(ENABLE_CIDER)
|
|
list(APPEND ALL_NGSPICE_SOURCES ${CIDER_SOURCES})
|
|
endif()
|
|
|
|
if(ENABLE_XSPICE)
|
|
list(APPEND ALL_NGSPICE_SOURCES ${XSPICE_SOURCES})
|
|
endif()
|
|
|
|
if(ENABLE_OSDI)
|
|
list(APPEND ALL_NGSPICE_SOURCES ${OSDI_SOURCES})
|
|
endif()
|
|
|
|
if(ENABLE_KLU AND DEFINED KLU_SOURCES)
|
|
list(APPEND ALL_NGSPICE_SOURCES ${KLU_SOURCES})
|
|
endif()
|
|
|
|
# Remove files that cause conflicts or aren't needed for shared library
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "main\\.c$")
|
|
# Note: ngspice.c is INCLUDED - it contains SIMinfo but no main()
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "winmain\\.c$")
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "tclspice\\.c$")
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "ngnutmeg\\.c$")
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "nghelp\\.c$")
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "ngsconvert\\.c$")
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "ngmultidec\\.c$")
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "ngproc2mod\\.c$")
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "makeidx\\.c$")
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "hist_info\\.c$")
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "testcommands\\.c$")
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "test_accuracy\\.c$")
|
|
# Exclude ndev (network device) - uses Unix socket headers
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "/ndev/")
|
|
# Exclude CIDER-dependent numerical device models when CIDER is disabled
|
|
if(NOT ENABLE_CIDER)
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "/nbjt/")
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "/nbjt2/")
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "/numd/")
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "/numd2/")
|
|
list(FILTER ALL_NGSPICE_SOURCES EXCLUDE REGEX "/numos/")
|
|
endif()
|
|
|
|
# ============================================================================
|
|
# Create ngspice static library
|
|
# ============================================================================
|
|
add_library(ngspice_core STATIC ${ALL_NGSPICE_SOURCES})
|
|
|
|
target_include_directories(ngspice_core PUBLIC ${NGSPICE_INCLUDE_DIRS})
|
|
target_compile_definitions(ngspice_core PUBLIC ${NGSPICE_DEFINITIONS})
|
|
|
|
if(UNIX AND NOT APPLE)
|
|
target_link_libraries(ngspice_core PUBLIC ${M_LIBRARY})
|
|
endif()
|
|
|
|
target_link_libraries(ngspice_core PUBLIC Threads::Threads)
|
|
|
|
# Windows-specific libraries
|
|
if(WIN32)
|
|
target_link_libraries(ngspice_core PUBLIC shlwapi)
|
|
endif()
|
|
|
|
# ============================================================================
|
|
# Python extension sources
|
|
# ============================================================================
|
|
set(PYTHON_EXT_SOURCES
|
|
${NGSPICE_SRC}/bindings/module.cpp
|
|
${NGSPICE_SRC}/cpp/simulator.cpp
|
|
${NGSPICE_SRC}/cpp/callbacks.cpp
|
|
${NGSPICE_SRC}/cpp/sim_runner.cpp
|
|
${NGSPICE_SRC}/cpp/raw_read.cpp
|
|
${NGSPICE_SRC}/cpp/trace.cpp
|
|
)
|
|
|
|
# ============================================================================
|
|
# Create Python module
|
|
# ============================================================================
|
|
pybind11_add_module(_pyngspice MODULE ${PYTHON_EXT_SOURCES})
|
|
|
|
target_include_directories(_pyngspice PRIVATE
|
|
${NGSPICE_INCLUDE_DIRS}
|
|
${NGSPICE_SRC}/cpp
|
|
${Python3_INCLUDE_DIRS}
|
|
${Python3_NumPy_INCLUDE_DIRS}
|
|
)
|
|
|
|
target_compile_definitions(_pyngspice PRIVATE
|
|
NGSPICE_PYTHON_MODULE
|
|
VERSION_STR="${PROJECT_VERSION}"
|
|
${NGSPICE_DEFINITIONS}
|
|
)
|
|
|
|
# Link against ngspice core and Python
|
|
target_link_libraries(_pyngspice PRIVATE
|
|
ngspice_core
|
|
Python3::NumPy
|
|
)
|
|
|
|
if(APPLE)
|
|
target_link_libraries(_pyngspice PRIVATE "-framework Accelerate")
|
|
endif()
|
|
|
|
# Output .pyd directly into pyngspice/ for inplace editable install
|
|
set_target_properties(_pyngspice PROPERTIES
|
|
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/pyngspice
|
|
)
|
|
|
|
# MinGW: statically link all runtime DLLs (ship zero DLLs)
|
|
if(MINGW)
|
|
target_link_options(_pyngspice PRIVATE -static-libgcc -static-libstdc++)
|
|
target_link_libraries(_pyngspice PRIVATE
|
|
-Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic
|
|
)
|
|
endif()
|
|
|
|
# ============================================================================
|
|
# Install (for wheel builds)
|
|
# ============================================================================
|
|
install(TARGETS _pyngspice
|
|
LIBRARY DESTINATION pyngspice
|
|
RUNTIME DESTINATION pyngspice
|
|
)
|
|
|
|
install(FILES
|
|
${CMAKE_CURRENT_SOURCE_DIR}/pyngspice/__init__.py
|
|
${CMAKE_CURRENT_SOURCE_DIR}/pyngspice/runner.py
|
|
${CMAKE_CURRENT_SOURCE_DIR}/pyngspice/netlist.py
|
|
DESTINATION pyngspice
|
|
)
|
|
|
|
# ============================================================================
|
|
# Summary
|
|
# ============================================================================
|
|
message(STATUS "")
|
|
message(STATUS "========================================")
|
|
message(STATUS "pyngspice Configuration")
|
|
message(STATUS "========================================")
|
|
message(STATUS " Version: ${PROJECT_VERSION}")
|
|
message(STATUS " Python: ${Python3_EXECUTABLE}")
|
|
message(STATUS " NumPy: ${Python3_NumPy_VERSION}")
|
|
message(STATUS " pybind11: ${pybind11_VERSION}")
|
|
message(STATUS " XSPICE: ${ENABLE_XSPICE}")
|
|
message(STATUS " OSDI: ${ENABLE_OSDI}")
|
|
message(STATUS " CIDER: ${ENABLE_CIDER}")
|
|
message(STATUS " KLU: ${ENABLE_KLU}")
|
|
message(STATUS " Source files: ${CMAKE_CURRENT_LIST_DIR}")
|
|
message(STATUS "========================================")
|
|
message(STATUS "")
|