Source code for pyccel.commands.build

# -*- coding: utf-8 -*-
"""
    Quickly setup a Pyccel source to work with pyccel.
"""

# TODO this file has not been refactored yet


import sys
import os
import argparse

from os import path

from pyccel import __version__ as __display_version__
from pyccel.codegen.utilities_old import build_file
from pyccel.codegen.utilities_old import build_cmakelists
from pyccel.codegen.utilities_old import build_cmakelists_dir
from pyccel.codegen.utilities_old import generate_project_main


EXTENSIONS = {
    'math': True,
    'blas': False
}

DEFAULT_VALUE = {
    'author': '__AUTHOR__',
    'sep': True,
    'language': 'fortran',
    'suffix': '.f90',
    'master': 'main',
}


[docs]def mkdir_p(dir): # type: (unicode) -> None if path.isdir(dir): return os.makedirs(dir)
[docs]def get_parser(): # type: () -> argparse.ArgumentParser parser = argparse.ArgumentParser( usage='usage: %(prog)s [OPTIONS] SOURCEDIR [FILENAMES...]', epilog='For more information, visit <http://http://pyccel.readthedocs.io/>.', description=""" Generate low-level code from python source files. pyccel-build generates low-level code from the files in SOURCEDIR and places it in OUTPUT_DIR. It looks for 'conf.py' in SOURCEDIR for the configuration settings. The 'pyccel-quickstart' tool may be used to generate template files, including 'conf.py' pyccel-build can create low-level code in different languages. A language is selected by specifying the builder name on the command line; it defaults to FORTRAN. By default, everything that is outdated is built. Output only for selected files can be built by specifying individual filenames. """) parser.add_argument('--version', action='version', dest='show_version', version='%%(prog)s %s' % __display_version__) parser.add_argument('sourcedir', help='path to pyccel source files') parser.add_argument('filenames', nargs='*', help='a list of specific files to rebuild. Ignored ' 'if -a is specified') group = parser.add_argument_group('general options') group.add_argument('--output-dir', type=str, \ help='Output directory.') group.add_argument('--convert-only', action='store_true', help='Converts pyccel files only without build') group.add_argument('-b', metavar='BUILDER', dest='builder', default='fortran', help='builder to use (default: fortran)') group.add_argument('-a', action='store_true', dest='force_all', help='write all files (default: only write new and ' 'changed files)') group.add_argument('-E', action='store_true', dest='freshenv', help='don\'t use a saved environment, always read ' 'all files') group.add_argument('-j', metavar='N', default=1, type=int, dest='jobs', help='build in parallel with N processes where ' 'possible') group = parser.add_argument_group('build configuration options') group.add_argument('-c', metavar='PATH', dest='confdir', help='path where configuration file (conf.py) is ' 'located (default: same as SOURCEDIR)') group.add_argument('-D', metavar='setting=value', action='append', dest='define', default=[], help='override a setting in configuration file') group = parser.add_argument_group('console output options') group.add_argument('-v', action='count', dest='verbosity', default=0, help='increase verbosity (can be repeated)') group.add_argument('-q', action='store_true', dest='quiet', help='no output on stdout, just warnings on stderr') group.add_argument('-Q', action='store_true', dest='really_quiet', help='no output at all, not even warnings') group.add_argument('-W', action='store_true', dest='warningiserror', help='turn warnings into errors') return parser
# TODO default debug should be True for the moment
[docs]def build(d, silent=False, force=True, dep_libs=[], dep_extensions=['math'], clean=True, debug=True): """Generates the project from a dictionary.""" if not debug: sys.tracebacklimit = 0 conf_filename = os.path.join(os.getcwd(), 'conf.py') if not os.path.exists(conf_filename): raise ValueError('Could not find conf.py file.' ' Make sure you run pyccel-build from the right directory.') language = d['language'] sourcedir = d['sourcedir'] output_dir = d['output_dir'] mkdir_p(output_dir) py_file = lambda f: (f.split('.')[-1] == 'py') ignore_file = lambda f: (os.path.basename(f) in ['__init__.py']) files = [f for f in os.listdir(sourcedir) if py_file(f) and not ignore_file(f)] programs = [] for f_name in files: if not silent: print ('> converting {0}/{1}'.format(sourcedir, f_name)) filename = os.path.join(sourcedir, f_name) info = build_file(filename, language=language, compiler=None, output_dir=output_dir) if not info['is_module']: programs.append(f_name.split('.')[0]) # remove .pyccel temporary files if clean: os.system('rm {0}/*.pyccel'.format(output_dir)) # ... is_program = lambda f: (f.split('.')[0] in programs) valid_file = lambda f: (f.split('.')[-1] in ['f90']) files = [f for f in os.listdir(output_dir) if valid_file(f) if not(is_program(f))] programs = [f for f in os.listdir(output_dir) if valid_file(f) if is_program(f)] # print('>>>> files = {0}'.format(files)) # print('>>>> programs = {0}'.format(programs)) libname = os.path.basename(sourcedir) dep_libs += ['pyccelext_{0}'.format(i) for i in dep_extensions] build_cmakelists(output_dir, libname, files, force=force, dep_libs=dep_libs, programs=programs) build_cmakelists_dir('src') # ... # ... if not('convert_only' in d): from pyccel.codegen.cmake import CMake cmake = CMake('.') cmake.make()
# ...
[docs]def main(argv=sys.argv[1:]): """Creates a new pyccel project.""" # ... parser = get_parser() try: args = parser.parse_args(argv) except SystemExit as err: return err.code # ... d = vars(args) # delete None or False value d = dict((k, v) for k, v in d.items() if not (v is None or v is False)) # ... settings = DEFAULT_VALUE.copy() for k,v in d.items(): settings[k] = v # ... # ... settings['extensions'] = [k[4:] for k,v in d.items() if v and (k[:4] == 'ext_')] # ... # ... default value is ./src/SRCDIR if not 'output_dir' in settings: srcdir = settings['sourcedir'] settings['output_dir'] = 'src/{0}'.format(srcdir) # ... # ... build(settings)
# ...