ENH: Generate remaining installed headers Basically openblas_config f77blas and cblaspull/4832/head
| @@ -0,0 +1,103 @@ | |||
| #!/usr/bin/env python3 | |||
| import argparse | |||
| from pathlib import Path | |||
| def write_openblas_config_header(dest_dir, version, config_last_path, template_path): | |||
| config_h_path = dest_dir / "openblas_config.h" | |||
| with config_h_path.open('w') as f: | |||
| f.write("#ifndef OPENBLAS_CONFIG_H\n") | |||
| f.write("#define OPENBLAS_CONFIG_H\n") | |||
| with config_last_path.open('r') as config_last: | |||
| for line in config_last: | |||
| if line.strip(): | |||
| defines = line.split('#define ') | |||
| for define in defines: | |||
| if define.strip(): | |||
| parts = define.split(maxsplit=1) | |||
| if len(parts) > 0: | |||
| macro_name = parts[0] | |||
| rest_of_line = " ".join(parts[1:]) if len(parts) > 1 else "" | |||
| line_to_write = f"#define OPENBLAS_{macro_name} {rest_of_line}" | |||
| f.write(f"{line_to_write.strip()}\n") | |||
| f.write(f'#define OPENBLAS_VERSION " OpenBLAS {version} "\n') | |||
| with template_path.open('r') as template: | |||
| f.write(template.read()) | |||
| f.write("#endif /* OPENBLAS_CONFIG_H */\n") | |||
| print(f"Generated openblas_config.h in {dest_dir}") | |||
| def write_f77blas_header(dest_dir, common_interface_path): | |||
| f77blas_h_path = dest_dir / "f77blas.h" | |||
| with f77blas_h_path.open('w') as f: | |||
| f.write("#ifndef OPENBLAS_F77BLAS_H\n") | |||
| f.write("#define OPENBLAS_F77BLAS_H\n") | |||
| f.write('#include "openblas_config.h"\n') | |||
| with common_interface_path.open('r') as common_interface: | |||
| f.write(common_interface.read()) | |||
| f.write("#endif\n") | |||
| print(f"Generated f77blas.h in {dest_dir}") | |||
| def write_cblas_header(dest_dir, cblas_path, symbol_prefix, symbol_suffix): | |||
| cblas_h_path = dest_dir / "cblas.h" | |||
| with cblas_path.open('r') as cblas_file: | |||
| content = cblas_file.read() | |||
| if symbol_prefix: | |||
| content = re.sub(r'\bcblas', f'{symbol_prefix}cblas', content) | |||
| content = re.sub(r'\bopenblas', f'{symbol_prefix}openblas', content) | |||
| content = re.sub(f'{symbol_prefix}openblas_complex', 'openblas_complex', content) | |||
| content = re.sub(r'\bgoto', f'{symbol_prefix}goto', content) | |||
| if symbol_suffix: | |||
| content = re.sub(r'\bcblas(\w*)', r'cblas\1' + symbol_suffix, content) | |||
| content = re.sub(r'\bopenblas(\w*)', r'openblas\1' + symbol_suffix, content) | |||
| content = re.sub(r'\bgoto(\w*)', r'goto\1' + symbol_suffix, content) | |||
| content = re.sub(r'openblas_complex_(\w*)' + symbol_suffix, r'openblas_complex_\1', content) | |||
| content = content.replace('common', 'openblas_config') | |||
| with cblas_h_path.open('w') as f: | |||
| f.write(content) | |||
| print(f"Generated cblas.h in {dest_dir}") | |||
| def main(): | |||
| parser = argparse.ArgumentParser(description="Generate OpenBLAS headers") | |||
| parser.add_argument('--dest-dir', required=True, help="Destination directory for headers") | |||
| parser.add_argument('--version', required=True, help="OpenBLAS version") | |||
| parser.add_argument('--config-last', required=True, help="Path to config_last.h") | |||
| parser.add_argument('--template', required=True, help="Path to openblas_config_template.h") | |||
| parser.add_argument('--common-interface', required=True, help="Path to common_interface.h") | |||
| parser.add_argument('--cblas', required=True, help="Path to cblas.h") | |||
| parser.add_argument('--symbol-prefix', default="", help="Symbol prefix for cblas.h") | |||
| parser.add_argument('--symbol-suffix', default="", help="Symbol suffix for cblas.h") | |||
| parser.add_argument('--generate-f77blas', action='store_true', help="Generate f77blas.h") | |||
| parser.add_argument('--generate-cblas', action='store_true', help="Generate cblas.h") | |||
| args = parser.parse_args() | |||
| dest_dir = Path(args.dest_dir) | |||
| dest_dir.mkdir(parents=True, exist_ok=True) | |||
| config_last_path = Path(args.config_last) | |||
| template_path = Path(args.template) | |||
| common_interface_path = Path(args.common_interface) | |||
| cblas_path = Path(args.cblas) | |||
| write_openblas_config_header(dest_dir, args.version, config_last_path, template_path) | |||
| if args.generate_f77blas: | |||
| write_f77blas_header(dest_dir, common_interface_path) | |||
| if args.generate_cblas: | |||
| write_cblas_header(dest_dir, cblas_path, args.symbol_prefix, args.symbol_suffix) | |||
| if __name__ == "__main__": | |||
| main() | |||
| @@ -61,6 +61,8 @@ build_cpp_thread_safety_test = get_option('build_cpp_thread_safety_test') | |||
| build_cpp_thread_safety_gemv = get_option('build_cpp_thread_safety_gemv') | |||
| build_static_libs = get_option('build_static_libs') | |||
| max_stack_alloc = get_option('max_stack_alloc') | |||
| quad_prec = get_option('quad_precision') | |||
| exprecision = get_option('exprecision') | |||
| if host_machine.system() == 'linux' | |||
| no_affinity = true | |||
| @@ -502,9 +504,43 @@ if not get_option('build_without_lapack') | |||
| endif | |||
| # TODO(rg) Generate these | |||
| # 'cblas.h', 'f77blas.h', 'openblas_config.h', | |||
| # install_headers(lapacke_headers) | |||
| # Paths to necessary files for header generation | |||
| fconfig_h = meson.build_root() / 'config.h' | |||
| fconfig_last = meson.build_root() / 'config_last.h' | |||
| template = meson.source_root() / 'openblas_config_template.h' | |||
| common_interface = meson.source_root() / 'common_interface.h' | |||
| cblas = meson.source_root() / 'cblas.h' | |||
| # Prepare config_last.h from config.h | |||
| pcl = custom_target('prepare_config_last', | |||
| output : 'config_last.h', | |||
| command : [py3, meson.source_root() / 'prepare_config_last.py', | |||
| '--config', fconfig_h, | |||
| '--output', fconfig_last, | |||
| quad_prec ? '--quad-precision' : [], | |||
| exprecision ? '--exprecision' : [], | |||
| ], | |||
| build_by_default : true, | |||
| depends: config_h, | |||
| ) | |||
| # Generate the headers | |||
| custom_target('gen_install_headers', | |||
| output : ['openblas_config.h', 'f77blas.h', 'cblas.h'], | |||
| command : [py3, meson.source_root() / 'gen_install_headers.py', | |||
| '--dest-dir', meson.build_root(), | |||
| '--version', meson.project_version(), | |||
| '--config-last', fconfig_last, | |||
| '--template', template, | |||
| '--common-interface', common_interface, | |||
| '--cblas', cblas, | |||
| not get_option('no_fortran') ? '--generate-f77blas' : [], | |||
| not get_option('build_without_cblas') ? '--generate-cblas' : [], | |||
| ], | |||
| install : true, | |||
| install_dir : 'include', | |||
| depends : pcl, | |||
| ) | |||
| pkg = import ('pkgconfig') | |||
| pkg_ver = meson.project_version() | |||
| @@ -43,11 +43,14 @@ option('use_xblas', type : 'boolean', value : false, | |||
| # From / for interface/Makefile | |||
| option('build_bfloat16', type: 'boolean', value: false, description: 'Build bfloat16') | |||
| option('exprecision', type: 'boolean', value: false, description: 'Build the q suffixes') | |||
| # option('exprecision', type: 'boolean', value: false, description: 'Build the q suffixes') | |||
| # Meson only | |||
| # This is the equivalent of producing all precisions via make all inside lapack-netlib/blas/src | |||
| option('build_all_prec', type: 'boolean', value: true, description: 'Build all precisions') | |||
| # For installation, maps to | |||
| option('quad_precision', type: 'boolean', value: false, description: 'Build quad precision') | |||
| option('exprecision', type: 'boolean', value: false, description: 'Build extended precision') | |||
| # For naming netlib libraries | |||
| option('netlib_blas_name', type: 'string', value: 'refblas', description: 'Name for the Netlib BLAS library') | |||
| @@ -0,0 +1,37 @@ | |||
| #!/usr/bin/env python3 | |||
| import argparse | |||
| from pathlib import Path | |||
| def prepare_config_last(config_path, output_path, quad_precision, exprecision): | |||
| config_path = Path(config_path) | |||
| output_path = Path(output_path) | |||
| with config_path.open("r") as config_file: | |||
| config_lines = config_file.readlines() | |||
| with output_path.open("w") as output_file: | |||
| output_file.writelines(config_lines) | |||
| if quad_precision: | |||
| output_file.write("#define QUAD_PRECISION\n") | |||
| if exprecision: | |||
| output_file.write("#define EXPRECISION\n") | |||
| def main(): | |||
| parser = argparse.ArgumentParser(description="Prepare config_last.h from config.h") | |||
| parser.add_argument("--config", required=True, help="Path to config.h") | |||
| parser.add_argument("--output", required=True, help="Path to output config_last.h") | |||
| parser.add_argument( | |||
| "--quad-precision", action="store_true", help="Enable QUAD_PRECISION" | |||
| ) | |||
| parser.add_argument("--exprecision", action="store_true", help="Enable EXPRECISION") | |||
| args = parser.parse_args() | |||
| prepare_config_last(args.config, args.output, args.quad_precision, args.exprecision) | |||
| if __name__ == "__main__": | |||
| main() | |||