coriolis/bootstrap/crlenv.py

276 lines
11 KiB
Python
Executable File

#!/usr/bin/env python3
import sys
import os
import os.path
from pathlib import Path
import socket
import subprocess
import re
import argparse
reCoriolisPattern = re.compile( r".*coriolis.*" )
reReleaseSharedPattern = re.compile( r".*Release\.Shared.*" )
reReleaseStaticPattern = re.compile( r".*Release\.Static.*" )
reDebugSharedPattern = re.compile( r".*Debug\.Shared.*" )
reDebugStaticPattern = re.compile( r".*Debug\.Static.*" )
def scrubPath ( pathName ):
"""
Remove from the PATH like environment variable ``pathName`` any
previous path item referring to a Coriolis location.
"""
if not pathName in os.environ: return ''
value = os.environ[ pathName ]
elements = value.split( ':' )
scrubbed = []
for element in elements:
if element == '': continue
if reCoriolisPattern .match(element) \
or reReleaseSharedPattern.match(element) \
or reReleaseStaticPattern.match(element) \
or reDebugSharedPattern .match(element) \
or reDebugStaticPattern .match(element):
continue
scrubbed.append( element )
if len(scrubbed) == 0: return ''
return ':'.join( scrubbed )
def envWriteBack ( pathName, pathValue ):
"""
Add to the environment PATH like variable ``pathName`` the components
given in ``pathValue`` and export it back. To avoid having multiple
Coriolis in the path, it is scrubbed beforehand.
"""
if pathName in os.environ:
scrubbed = scrubPath( pathName )
if scrubbed != '':
pathValue += ':' + scrubbed
os.environ[ pathName ] = pathValue
return pathValue
def setupPaths ( verbose, debug=False ):
"""
Guess and setup the main variables to use Coriolis:
* ``PATH``, to find the binaries.
* ``LD_LIBRARY_PATH``, to access the dynamic libraries.
* ``DYLD_LIBRARY_PATH``, same as above under MacOS.
* ``PYTHONPATH``, to access the various Python modules provided
by Coriolis.
:param verbose: Self explanatory.
:param debug: Use the version compiled with debugging support.
Be aware that it is roughly 4 times slower...
It's the tree rooted at ``Debug.Shared/install``
instead of ``Release.Shared/install``.
"""
# Setup CORIOLIS_TOP.
osEL9 = re.compile (".*Linux.*el9.*x86_64.*")
osSlsoc7x_64 = re.compile (".*Linux.*el7.*x86_64.*")
osSlsoc6x_64 = re.compile (".*Linux.*el6.*x86_64.*")
osSlsoc6x = re.compile (".*Linux.*(el|slsoc)6.*")
osSLSoC5x_64 = re.compile (".*Linux.*el5.*x86_64.*")
osSLSoC5x = re.compile (".*Linux.*(el5|2.6.23.13.*SoC).*")
osFedora_64 = re.compile (".*Linux.*fc.*x86_64.*")
osFedora = re.compile (".*Linux.*fc.*")
osLinux_64 = re.compile (".*Linux.*x86_64.*")
osLinux = re.compile (".*Linux.*")
osDarwin = re.compile (".*Darwin.*")
osUbuntu1004 = re.compile (".*Linux.*ubuntu.*")
osUbuntu1004_64 = re.compile (".*Linux.*ubuntu.*x86_64.*")
osFreeBSD8x_amd64 = re.compile (".*FreeBSD 8.*amd64.*")
osFreeBSD8x_64 = re.compile (".*FreeBSD 8.*x86_64.*")
osFreeBSD8x = re.compile (".*FreeBSD 8.*")
osCygwinW7_64 = re.compile (".*CYGWIN_NT-6\.1.*x86_64.*")
osCygwinW7 = re.compile (".*CYGWIN_NT-6\.1.*i686.*")
osCygwinW8_64 = re.compile (".*CYGWIN_NT-6\.[2-3].*x86_64.*")
osCygwinW8 = re.compile (".*CYGWIN_NT-6\.[2-3].*i686.*")
osCygwinW10_64 = re.compile (".*CYGWIN_NT-10\.[0-3].*x86_64.*")
osCygwinW10 = re.compile (".*CYGWIN_NT-10\.[0-3].*i686.*")
uname = subprocess.Popen( ["uname", "-srm"], stdout=subprocess.PIPE )
lines = uname.stdout.readlines()
line = lines[0].decode( 'ascii' )
if osSlsoc7x_64 .match(line): osDir = "Linux.el7_64"
elif osEL9 .match(line): osDir = "Linux.el9"
elif osSlsoc6x_64 .match(line): osDir = "Linux.slsoc6x_64"
elif osSlsoc6x .match(line): osDir = "Linux.slsoc6x"
elif osSLSoC5x_64 .match(line): osDir = "Linux.SLSoC5x_64"
elif osSLSoC5x .match(line): osDir = "Linux.SLSoC5x"
elif osFedora_64 .match(line): osDir = "Linux.fc_64"
elif osFedora .match(line): osDir = "Linux.fc"
elif osUbuntu1004 .match(line): osDir = "Linux.Ubuntu1004"
elif osUbuntu1004_64 .match(line): osDir = "Linux.Ubuntu1004_64"
elif osLinux_64 .match(line): osDir = "Linux.x86_64"
elif osLinux .match(line): osDir = "Linux.i386"
elif osFreeBSD8x_64 .match(line): osDir = "FreeBSD.8x.x86_64"
elif osFreeBSD8x_amd64.match(line): osDir = "FreeBSD.8x.amd64"
elif osFreeBSD8x .match(line): osDir = "FreeBSD.8x.i386"
elif osDarwin .match(line): osDir = "Darwin"
elif osCygwinW7_64 .match(line): osDir = "Cygwin.W7_64"
elif osCygwinW7 .match(line): osDir = "Cygwin.W7"
elif osCygwinW8_64 .match(line): osDir = "Cygwin.W8_64"
elif osCygwinW8 .match(line): osDir = "Cygwin.W8"
elif osCygwinW10_64 .match(line): osDir = "Cygwin.W10_64"
elif osCygwinW10 .match(line): osDir = "Cygwin.W10"
else:
uname = subprocess.Popen( ["uname", "-sr"], stdout=subprocess.PIPE )
osDir = uname.stdout.readlines()[0][:-1]
print( '[WARNING] environment.setupPaths(): Unrecognized OS: "{}".'.format( line[:-1] ))
print( ' (using: "{}")'.format( osDir ))
osDir = Path( osDir )
homeDir = Path( os.environ['HOME'] )
buildType = Path( 'Debug.Shared' if debug else 'Release.Shared' )
scriptPath = Path( __file__ ).resolve()
topDirs = []
if debug:
topDirs.append( homeDir / 'coriolis-2.x' / osDir / buildType / 'install' )
if 'CORIOLIS_TOP' in os.environ:
topDirs.append( Path( os.environ['CORIOLIS_TOP'] ))
if not debug:
topDirs.append( homeDir / 'coriolis-2.x' / osDir / buildType / 'install' )
topDirs += [ Path( '/soc/coriolis2' )
, Path( '/usr' )
]
for part in scriptPath.parts:
if part == 'nightly':
topDirs.append( homeDir / 'nightly' / 'coriolis-2.x' / osDir / buildType / 'install' )
break
if verbose:
print( ' o Self locating Coriolis:' )
coriolisTop = None
for topDir in topDirs:
if coriolisTop or not (topDir / 'bin' / 'cgt').is_file():
if verbose: print( ' - {}'.format(topDir) )
continue
if verbose: print( ' - {} *'.format(topDir) )
coriolisTop = topDir
if not coriolisTop:
print( '[ERROR] environment.setupPaths(): Unable to locate Coriolis.' )
return False
os.environ[ 'CORIOLIS_TOP' ] = coriolisTop.as_posix()
if coriolisTop == '/usr': sysconfDir = Path( 'etc', 'coriolis2' )
else: sysconfDir = coriolisTop / 'etc' / 'coriolis2'
# Setup PATH.
binPath = envWriteBack( 'PATH', (coriolisTop/'bin').as_posix() )
# Setup LD_LIBRARY_PATH.
libDirs = []
for lib in [ Path('lib'), Path('lib64') ]:
libDir = lib
absLibDir = coriolisTop / lib
if absLibDir.is_dir():
libDirs.append( absLibDir )
libDir = None
if not len(libDirs):
print( '[ERROR] environment.setupPaths(): Library directory not found.' )
return False
libraryPath = ''
ldPathName = 'LD_LIBRARY_PATH'
if osDir.as_posix().startswith( 'Darwin' ):
ldPathName = 'DYLD_LIBRARY_PATH'
for libDir in libDirs:
if len(libraryPath): libraryPath = libraryPath + ':'
libraryPath = libraryPath + libDir.as_posix()
libraryPath = envWriteBack( ldPathName, libraryPath )
# Setup PYTHONPATH.
v = sys.version_info
sitePackagesDir = None
for pyPackageDir in [ Path('python{}.{}'.format(v.major,v.minor)) / 'site-packages'
, Path('python{}.{}'.format(v.major,v.minor)) / 'dist-packages'
, Path('{}.{}'.format(v.major,v.minor)) / 'site-packages'
, Path('python{}'.format(v.major)) / 'site-packages'
, Path('python{}'.format(v.major)) / 'dist-packages'
, Path('{}'.format(v.major)) / 'site-packages'
]:
sitePackagesDir = libDirs[-1] / pyPackageDir
if sitePackagesDir.is_dir():
if verbose:
print( ' - {} *'.format(sitePackagesDir) )
break
if verbose:
print( ' - {}'.format(sitePackagesDir) )
sitePackagesDir = None
if sitePackagesDir is None:
print( '[ERROR] environment.setupPaths(): Python {site,dist}-packages directory not found.' )
return False
pythonPath = ''
for packageDir in [ sitePackagesDir
, sitePackagesDir / 'crlcore'
, sitePackagesDir / 'cumulus'
, sitePackagesDir / 'cumulus/plugins'
, sitePackagesDir / 'status'
, sysconfDir
]:
sys.path.append( str(packageDir) )
if len(pythonPath): pythonPath += ':'
pythonPath += str(packageDir)
pythonPath = envWriteBack( 'PYTHONPATH', pythonPath )
return True
def printVariable ( name ):
if not name in os.environ:
print( '{:<16}:'.format( name ))
print( '- variable_not_set' )
return
values = os.environ[ name ].split( ':' )
print( '{}:'.format( name ))
for value in values:
print( '- {}'.format( value ))
def printEnvironment ():
"""
Display the environment setup, using YAML formatting.
"""
print( '# crlenv.py: Alliance/Coriolis finder, guessed values.' )
print( '---' )
for name in ('CORIOLIS_TOP', 'PATH', 'DYLD_LIBRARY_PATH'
, 'LD_LIBRARY_PATH', 'PYTHONPATH'):
printVariable( name )
if __name__ == '__main__':
"""
Run any script in a environmnent set for Coriolis.
Example:
.. code:: bash
ego@home:~> crlenv.py -- doit clean_flow
b2v Run <blif2vst arlet6502 depends=[Arlet6502.blif]>.
cgt Run plain CGT (no loaded design)
clean_flow Clean all generated (targets) files.
gds Run <Alias "gds" for "pnr">.
pnr Run <pnr arlet6502_cts_r.gds depends=[arlet6502.vst,Arlet6502.spi]>.
yosys Run <yosys Arlet6502.v top=Arlet6502 blackboxes=[] flattens=[]>.
ego@home:~> crlenv.py -- bash
[ego@home]$ echo $CORIOLIS_TOP
/home/ego/coriolis-2.x/Linux.el9/Release.Shared/install
[ego@home]$ exit
ego@home:~>
"""
parser = argparse.ArgumentParser()
parser.add_argument( '-v', '--verbose', action='store_true', dest='verbose' )
parser.add_argument( '-d', '--debug' , action='store_true', dest='debug' )
parser.add_argument( 'command', nargs='*' )
args = parser.parse_args()
setupPaths( args.verbose, args.debug )
if not len(args.command):
printEnvironment()
sys.exit( 0 )
state = subprocess.run( args.command )
sys.exit( state.returncode )