diff --git a/binaryc/__pycache__/functions.cpython-36.pyc b/binaryc/__pycache__/functions.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d94edfad50de7db8a96e18cb3cb9c54647929fad Binary files /dev/null and b/binaryc/__pycache__/functions.cpython-36.pyc differ diff --git a/binaryc/custom_logging.c b/binaryc/custom_logging.c new file mode 100644 index 0000000000000000000000000000000000000000..22c19e939fd0fe56509d91802c583b724cd40b20 --- /dev/null +++ b/binaryc/custom_logging.c @@ -0,0 +1,20 @@ +#pragma push_macro("MAX") +#pragma push_macro("MIN") +#undef MAX +#undef MIN +#include "binary_c.h" + +void custom_output_function(struct stardata_t * stardata); +void custom_output_function(struct stardata_t * stardata) +{ + // struct stardata_t * stardata = (struct stardata_t *)x; + PRINTF("MY_STELLAR_DATA %g %g +",((double)stardata->model.time),((double)stardata->star[0].mass)); +PRINTF("my_sss2 %g %g +",((double)stardata->model.time),((double)stardata->star[1].mass));; +} + +#undef MAX +#undef MIN +#pragma pop_macro("MIN") +#pragma pop_macro("MAX") \ No newline at end of file diff --git a/binaryc/functions.py b/binaryc/functions.py new file mode 100644 index 0000000000000000000000000000000000000000..b9d635e071213b9a8d47eaedb5291477721d2115 --- /dev/null +++ b/binaryc/functions.py @@ -0,0 +1,238 @@ +import os +import textwrap +import subprocess +import socket + +# Functions for the automatic logging of stuff + +def autogen_C_logging_code(logging_dict): + # See example_perl.pm autologging + """ + Function that autogenerates PRINTF statements for binaryc + + Input: + dictionary where the key is the header of that logging line and items which are lists of parameters that will be put in that logging line + + example: {'MY_STELLAR_DATA': + [ + 'model.time', + 'star[0].mass', + 'model.probability', + 'model.dt' + ']} + """ + + # Check if the input is of the correct form + if not type(logging_dict)==dict: + print("Error: please use a dictionary as input") + return None + + code = '' + # Loop over dict keys + for key in logging_dict: + logging_dict_entry = logging_dict[key] + + # Check if item is of correct type: + if type(logging_dict_entry)==list: + + # Construct print statement + code += 'PRINTF("{}'.format(key) + code += ' {}'.format('%g '*len(logging_dict_entry)) + code = code.strip() + code += '\n"' + + # Add format keys + for param in logging_dict_entry: + code += ',((double)stardata->{})'.format(param) + code += ');\n' + + else: + print('Error: please use a list for the list of parameters that you want to have logged') + code = code.strip() + # print("MADE AUTO CODE\n\n{}\n\n{}\n\n{}\n".format('*'*60, repr(code), '*'*60)) + + return code + +#################################################################################### +def binary_c_log_code(code): + """ + Function to construct the code to construct the custom logging function + # see example_perl.pm binary_c_log_code in perl + """ + custom_logging_function_string = """\ +#pragma push_macro(\"MAX\") +#pragma push_macro(\"MIN\") +#undef MAX +#undef MIN +#include \"binary_c.h\" + +void custom_output_function(struct stardata_t * stardata); +void custom_output_function(struct stardata_t * stardata) +{{ + // struct stardata_t * stardata = (struct stardata_t *)x; + {}; +}} + +#undef MAX +#undef MIN +#pragma pop_macro(\"MIN\") +#pragma pop_macro(\"MAX\")\ + """.format(code) + + # print(repr(textwrap.dedent(custom_logging_function_string))) + return textwrap.dedent(custom_logging_function_string) + +def binary_c_write_log_code(code, filename): + """ + Function to write the generated logging code to a file + """ + + cwd = os.getcwd() + + filePath = os.path.join(cwd, filename) + if os.path.exists(filePath): + try: + os.remove(filePath) + except: + print("Error while deleting file {}".format(filePath)) + + with open(filePath, 'w') as f: + f.write(code) + +def from_binary_c_config(config_file, flag): + """ + Function to run the binaryc_config command with flags + """ + + res = subprocess.check_output('{config_file} {flag}'.format(config_file=config_file, flag=flag), + shell=True, stderr=subprocess.STDOUT) + + # convert and chop off newline + res = res.decode('utf').rstrip() + return res + +def return_compilation_dict(): + """ + Function to build the compile command for the shared library + + inspired by binary_c_inline_config command in perl + + TODO: this function still has some cleaning up to do wrt default values for the compile command + + returns: + - string containing the command to build the shared library + """ + + # use binary_c-config to get necessary flags + BINARY_C_DIR = os.getenv('BINARY_C') + if BINARY_C_DIR: + BINARY_C_CONFIG = os.path.join(BINARY_C_DIR, 'binary_c-config') + BINARY_C_SRC_DIR = os.path.join(BINARY_C_DIR, 'src') + # TODO: build in check to see whether the file exists + else: + raise NameError('Envvar BINARY_C doesnt exist') + return None + + # TODO: make more options for the compiling + cc = from_binary_c_config(BINARY_C_CONFIG, 'cc') + + # Check for binary_c + BINARY_C_EXE = os.path.join(BINARY_C_DIR, 'binary_c') + if not os.path.isfile(BINARY_C_EXE): + print("We require binary_c executable; have you built binary_c?") + raise NameError('BINARY_C executable doesnt exist') + + # TODO: debug + binclibs = from_binary_c_config(BINARY_C_CONFIG, 'libs') + libdirs = "{} -L{}".format(from_binary_c_config(BINARY_C_CONFIG, 'libdirs'), BINARY_C_SRC_DIR) + bincflags = from_binary_c_config(BINARY_C_CONFIG, 'cflags') + bincincdirs = from_binary_c_config(BINARY_C_CONFIG, 'incdirs') + + # combine + binclibs = ' {} {}'.format(libdirs, binclibs) + + # setup defaults: + defaults = { + 'cc': 'gcc', # default compiler + 'ccflags': bincflags, + 'ld': 'ld', # 'ld': $Config{ld}, # default linker + 'debug': 0, + 'inc': '{} -I{}'.format(bincincdirs, BINARY_C_SRC_DIR), + # inc => ' '.($Config{inc}//' ').' '.$bincincdirs." -I$srcdir ", # include the defaults plus # GSL and binary_c + # 'libname': libname, # libname is usually just binary_c corresponding to libbinary_c.so + 'libs': binclibs, + } + + # set values with defaults. TODO: make other input possile. + ld = defaults['ld'] + debug = defaults['debug'] + inc = defaults['inc'] # = ($ENV{BINARY_GRID2_INC} // $defaults{inc}).' '.($ENV{BINARY_GRID2_EXTRAINC} // ''); + libs = defaults['libs'] # = ($ENV{BINARY_GRID2_LIBS} // $defaults{libs}).' '.($ENV{BINARY_GRID2_EXTRALIBS}//''); + ccflags = defaults['ccflags'] # = $ENV{BINARY_GRID2_CCFLAGS} // ($defaults{ccflags}) . ($ENV{BINARY_GRID2_EXTRACCFLAGS} // ''); + + # you must define _SEARCH_H to prevent it being loaded twice + ccflags += ' -D_SEARCH_H' + + # ensure library paths to the front of the libs: + libs_content = libs.split(' ') + library_paths = [el for el in libs_content if el.startswith('-L')] + non_library_paths = [el for el in libs_content if (not el.startswith('-L') and not el=='')] + libs = "{} {}".format(' '.join(library_paths), ' '.join(non_library_paths)) + + print("Building shared library for custom logging with (binary_c.h) at {} on {}\n".format(BINARY_C_SRC_DIR, socket.gethostname())) + print("With options:\n\tcc = {cc}\n\tccflags = {ccflags}\n\tld = {ld}\n\tlibs = {libs}\n\tinc = {inc}\n\n".format( + cc=cc, ccflags=ccflags, ld=ld, libs=libs, inc=inc) + ) + + return { + 'cc': cc, + 'ld': ld, + 'ccflags': ccflags, + 'libs': libs, + 'inc': inc + } + +# compilation_dict = return_compilation_dict('libcustomlogging') +def compile_shared_lib(code, sourcefile_name, outfile_name): + """ + Function to write the custom logging code to a file and then compile it. + """ + + # Write code to file + binary_c_write_log_code(code, sourcefile_name) + + # create compilation command + compilation_dict = return_compilation_dict() + + command = "{cc} {ccflags} {libs} -o {outfile_name} {sourcefile_name} {inc}".format( + cc=compilation_dict['cc'], + ccflags=compilation_dict['ccflags'], + libs=compilation_dict['libs'], + outfile_name=outfile_name, + sourcefile_name=sourcefile_name, + inc=compilation_dict['inc']) + + # remove extra whitespaces: + command = ' '.join(command.split()) + + # Execute compilation + res = subprocess.check_output('{command}'.format(command=command), + shell=True, stderr=subprocess.STDOUT) + print(res) + + + + # return command + +# generate logging lines +logging_line = autogen_C_logging_code( + { + 'MY_STELLAR_DATA': ['model.time', 'star[0].mass'], + 'my_sss2': ['model.time', 'star[1].mass'] + } +) + +# Generate code around logging lines +created_code = binary_c_log_code(logging_line) + +compile_shared_lib(created_code, sourcefile_name='custom_logging.c', outfile_name='lib_custom_logging.so') \ No newline at end of file diff --git a/binaryc/main.py b/binaryc/main.py new file mode 100644 index 0000000000000000000000000000000000000000..ccc28fa4357eb3e7a9e30250f03a2a2b0d9cca34 --- /dev/null +++ b/binaryc/main.py @@ -0,0 +1,35 @@ +from functions import autogen_C_logging_code, binary_c_log_code, binary_c_write_log_code + +import textwrap + +# generate logging lines +logging_line = autogen_C_logging_code( + { + 'MY_STELLAR_DATA': ['model.time', 'star[0].mass'], + 'my_sss2': ['model.time', 'star[1].mass'] + } +) + +# Generate code around logging lines +created_code = binary_c_log_code(logging_line) + +binary_c_write_log_code(created_code) + + + + + + + + + + + + + + + + + + + diff --git a/binaryc/readme.md b/binaryc/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..9c5fd5f79752aff29607c408cf671949b23c1fcb --- /dev/null +++ b/binaryc/readme.md @@ -0,0 +1,2 @@ +# function for binaryc to work +