diff --git a/gen_install_headers.py b/gen_install_headers.py new file mode 100644 index 000000000..6e9607879 --- /dev/null +++ b/gen_install_headers.py @@ -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() diff --git a/meson.build b/meson.build index 0f1cb44ec..36e69771f 100644 --- a/meson.build +++ b/meson.build @@ -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() diff --git a/meson_options.txt b/meson_options.txt index 0f6fc9c67..b95394015 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -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') diff --git a/prepare_config_last.py b/prepare_config_last.py new file mode 100644 index 000000000..80602db88 --- /dev/null +++ b/prepare_config_last.py @@ -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()