Path: blob/develop/src/sage_setup/autogen/flint/writer.py
4086 views
r"""1Write flint header files.2"""3#*****************************************************************************4# Copyright (C) 2023 Vincent Delecroix <[email protected]>5#6# This program is free software: you can redistribute it and/or modify7# it under the terms of the GNU General Public License as published by8# the Free Software Foundation, either version 2 of the License, or9# (at your option) any later version.10# http://www.gnu.org/licenses/11#*****************************************************************************1213import os14import shutil15from .env import AUTOGEN_DIR, FLINT_GIT_DIR, FLINT_DOC_DIR, FLINT_INCLUDE_DIR16from .reader import extract_functions171819def write_flint_cython_headers(output_dir, documentation=False):20r"""21Write cython header files.2223Arguments24output_dir -- (string) path where to write the .pxd files2526Requires gitpython to be installed.27"""28if not os.path.isdir(os.path.join(FLINT_GIT_DIR, ".git")):29raise ValueError(f"FLINT_GIT_DIR(={FLINT_GIT_DIR}) is not a Git repository")3031import git32repo = git.Repo(FLINT_GIT_DIR)33commit = repo.head.commit34print(f"Generating cython headers from {commit}")3536header_list = []37pxd_list = []38for filename in os.listdir(FLINT_DOC_DIR):39if not filename.endswith('.rst'):40continue41prefix = filename[:-4]4243absolute_filename = os.path.join(FLINT_DOC_DIR, filename)44content = extract_functions(absolute_filename)45if not content:46# NOTE: skip files with no function declaration47continue4849# try to match header50header = prefix + '.h'51if prefix == 'flint':52header = header + '.in'53absolute_header = os.path.join(FLINT_INCLUDE_DIR, header)5455if not os.path.isfile(absolute_header):56print('Warning: skipping {} because no associated .h found'.format(filename))57continue5859# TODO: below are some exceptions for which we do not create .pxd file60if prefix == 'machine_vectors' or prefix == 'fft_small':61print('Warning: ignoring machine_vectors and fft_small because architecture dependent')62continue63if prefix == 'acb_theta':64print('Warning: ignoring acb_theta because not in stable release')65continue6667header_list.append(prefix + '.h')68pxd_list.append(prefix + '.pxd')6970output = open(os.path.join(output_dir, prefix + '.pxd'), 'w')7172print('# distutils: libraries = flint', file=output)73print('# distutils: depends = flint/{}'.format(prefix + '.h'), file=output)74print(file=output)75print('#' * 80, file=output)76print('# This file is auto-generated by the script', file=output)77print('# SAGE_ROOT/src/sage_setup/autogen/flint_autogen.py.', file=output)78print('# From the commit {}'.format(commit), file=output)79print('# Do not modify by hand! Fix and rerun the script instead.', file=output)80print('#' * 80, file=output)81print(file=output)8283print('from libc.stdio cimport FILE', file=output)84print('from sage.libs.gmp.types cimport *', file=output)85print('from sage.libs.mpfr.types cimport *', file=output)86print('from sage.libs.flint.types cimport *', file=output)87print(file=output)8889print('cdef extern from "flint_wrap.h":', file=output)9091for section in content:92if section is not None:93print(' ## {}'.format(section), file=output)94for func_signatures, doc in content[section]:95if documentation:96print(file=output)97for line in doc:98print(' # {}'.format(line), file=output)99for line in func_signatures:100print(' {} noexcept'.format(line), file=output)101102if os.path.isfile(os.path.join(AUTOGEN_DIR, 'macros', prefix + '_macros.pxd')):103print('\nfrom .{} cimport *'.format(prefix + '_macros'), file=output)104105output.close()106107for extra_header in ['nmod_types.h']:108if extra_header in header_list:109print('Warning: {} already in HEADER_LIST'.format(extra_header))110header_list.append(extra_header)111112header_list.sort()113pxd_list.sort()114115with open(os.path.join(AUTOGEN_DIR, 'templates', 'flint_wrap.h.template')) as f:116text = f.read()117with open(os.path.join(output_dir, 'flint_wrap.h'), 'w') as output:118output.write(text.format(HEADER_LIST='\n'.join('#include <flint/{}>'.format(header) for header in header_list)))119120with open(os.path.join(AUTOGEN_DIR, 'templates', 'types.pxd.template')) as f:121text = f.read()122with open(os.path.join(output_dir, 'types.pxd'), 'w') as output:123output.write(text.format(HEADER_LIST=' '.join('flint/{}'.format(header) for header in header_list)))124125for filename in os.listdir(os.path.join(AUTOGEN_DIR, 'macros')):126prefix = filename[:-4]127shutil.copy(os.path.join(AUTOGEN_DIR, 'macros', filename), os.path.join(output_dir, filename))128129with open(os.path.join(AUTOGEN_DIR, 'templates', 'flint_sage.pyx.template')) as f:130text = f.read()131with open(os.path.join(output_dir, 'flint_sage.pyx'), 'w') as output:132output.write(text.format(CYTHON_IMPORTS='\n'.join('from .{} cimport *'.format(header[:-4]) for header in pxd_list)))133134135