This document provides detailed instructions for developing the SparseIR.jl Julia package.
- Language: Julia
- Build System: Julia Package Manager (Pkg)
- Test Framework: Julia Test.jl
- Documentation: Documenter.jl
- Main Files:
src/
# Run in Julia REPL
using Pkg
Pkg.activate(".")
Pkg.instantiate()
# Run tests
using Pkg
Pkg.test()
# Build documentation
using Documenter
include("docs/make.jl")If Pkg.instantiate() fails because a local Manifest.toml has fallen out of sync
with Project.toml, run Pkg.resolve() and then retry Pkg.instantiate():
using Pkg
Pkg.activate(".")
Pkg.resolve()
Pkg.instantiate()During development, you may want to use a locally built version of libsparseir instead of the pre-built JLL package. This allows you to test changes to the C API immediately.
Directory Structure:
projects/
├── sparse-ir/
│ ├── sparse-ir-rs/ # Rust implementation with C API
│ └── SparseIR.jl/ # Julia bindings
Steps:
-
Place repositories side by side: Ensure
sparse-ir-rsandSparseIR.jlare in the same parent directory. -
Rebuild SparseIR.jl: The build script automatically detects
sparse-ir-rsand builds it:using Pkg Pkg.build("SparseIR")
This will:
- Detect
../sparse-ir-rsdirectory - Build
sparse-ir-rswithcargo build --release --features system-blas - Copy
libsparse_ir_capi.dylib(or.so/.dll) todeps/ - Regenerate C API bindings in
src/C_API.jl
- Detect
-
Verify the build: Check that the local library was built:
ls -lh deps/libsparse_ir_capi.dylib
-
Test with local library:
using SparseIR basis = FiniteTempBasis{Fermionic}(10.0, 1.0, 1e-6) println("Basis size: ", length(basis))
Note: If sparse-ir-rs is not found in the expected location, SparseIR.jl will fall back to using the pre-built libsparseir_jll package from Julia's package registry.
Using Local libsparseir (for development):
When deps/libsparse_ir_capi.dylib (or .so/.dll) exists, SparseIR.jl will use it automatically. You'll see:
[ Info: Using local libsparseir: /path/to/SparseIR.jl/deps/libsparse_ir_capi.dylib
Switching to Remote libsparseir (JLL version):
To use the pre-built JLL package instead of the local library:
# Remove local library
rm -rf deps/libsparse_ir_capi.*
# Clear precompilation cache
rm -rf ~/.julia/compiled/v1.*/SparseIR/
# Restart Julia and verify
julia --project=. -e "using SparseIR"
# You should NOT see the "Using local libsparseir" messageSwitching back to Local libsparseir:
# Rebuild local library
julia --project=. -e "using Pkg; Pkg.build(\"SparseIR\")"
# Clear precompilation cache
rm -rf ~/.julia/compiled/v1.*/SparseIR/
# Restart Julia and verify
julia --project=. -e "using SparseIR"
# You should see "Using local libsparseir: ..." messageIf you need to force a clean rebuild (e.g., after updating sparse-ir-rs):
# Remove the built library and cached files
rm -rf deps/libsparse_ir_capi.*
rm -rf deps/build.log
# Then rebuild
julia --project=. -e "using Pkg; Pkg.build(\"SparseIR\")"For a complete clean rebuild:
# 1. Clean local build artifacts
rm -rf deps/
# 2. Clear precompilation cache
rm -rf ~/.julia/compiled/v1.*/SparseIR/
# 3. Rebuild and precompile
julia --project=. -e "using Pkg; Pkg.build(\"SparseIR\"); using SparseIR"src/
├── SparseIR.jl # Main file
├── abstract.jl # Abstract type definitions
├── basis.jl # Basis classes
├── basis_set.jl # Basis sets
├── C_API.jl # C API bindings
├── dlr.jl # DLR implementation
├── freq.jl # Frequency-related functions
├── kernel.jl # Kernel functions
├── poly.jl # Polynomial classes
├── sampling.jl # Sampling
└── sve.jl # SVE implementation
- Design considering type immutability
- Type stability for performance
- Leverage generic programming
- Proper resource management using
finalizer - Prevent memory leaks in C API integration
- Design considering garbage collection
- Ensure type stability
- Avoid unnecessary allocations
- Leverage vectorized operations
- Unit tests for each function
- Integration tests
- Performance tests
# Load the package
using SparseIR
# Run tests
using Pkg
Pkg.test()
# Run specific test file
include("test/runtests.jl")
# Build documentation
using Documenter
include("docs/make.jl")
# Performance testing
using BenchmarkTools
@benchmark some_function()
# Check memory usage
using Profile
@profile some_function()# Clear precompilation cache (if code changes aren't reflected)
rm -rf ~/.julia/compiled/v1.*/SparseIR/
# Rebuild local library
julia --project=. -e "using Pkg; Pkg.build(\"SparseIR\")"# Run in debug mode
julia --project=. -e "
using SparseIR
# Debug code
"
# Profiling
using Profile
@profile some_function()
Profile.print()
# Memory leak check
using Profile
@profile some_function()
Profile.print()- C API functions are defined in
C_API.jl - Implement error handling properly
- Perform type conversions explicitly
- Automate memory management with
finalizer
- Update version number in
Project.toml - Update CHANGELOG
- Ensure all tests pass
- Build documentation
- Create and push a tag