def create_boards_tree(board_file_path, new_board_path): """Create a json version of boards file from cosa""" with open(helper.linux_path(board_file_path)) as f: board_str = f.readlines() tree = {} curr_board = '' for line in board_str: if 'name=' in line: curr_board = line[:line.find('.')] tree[curr_board] = {} tree[curr_board]['name'] = line[line.find('='):].strip('=').strip( '\n').strip(' ') elif 'mcu=' in line: tree[curr_board]['mcu'] = line[line.find('='):].strip('=').strip( '\n').strip(' ') elif 'f_cpu=' in line: tree[curr_board]['f_cpu'] = line[line.find('='):].strip('=').strip( '\n').strip(' ') elif 'board=' in line: tree[curr_board]['id'] = line[line.find('='):].strip('=').strip( '\n').strip(' ') with open(helper.linux_path(new_board_path), 'w') as f: json.dump(tree, f, indent=4)
def clean_wcosa(path): """cleans the bin folder, deleting all the build files""" path = str(path) # confirm if bin folder/path exists if os.path.exists(helper.linux_path(path + '/wcosa/bin')): os.chdir(helper.linux_path(path + '/wcosa/bin')) else: output.writeln('\nNot a valid WCosa project', Fore.RED) quit(2) # check if the current build files are for the current board # clean and build if boards are different try: output.write('Cleaning build files - ', Fore.GREEN) for folder in helper.get_dirs(helper.get_working_directory()): shutil.rmtree(folder) for file in helper.get_files(helper.get_working_directory()): os.unlink(file) except IOError: output.writeln('Error while cleaning build files', Fore.RED) output.writeln('done')
def get_board_properties(board, board_path): """parses the board file returns the properties of the board specified""" with open(helper.linux_path(board_path)) as f: board_data = json.load(f, object_pairs_hook=OrderedDict) return board_data[board]
def fill_internal_config(path, curr_path, user_config_data): """fills the internal config file that will be used for internal build""" with open(helper.linux_path(path)) as f: internal_config_data = json.load(f, object_pairs_hook=OrderedDict) internal_config_data['project-name'] = os.path.basename(curr_path) internal_config_data['ide'] = user_config_data['ide'] internal_config_data['board'] = user_config_data['board'] internal_config_data['port'] = user_config_data['port'] internal_config_data['wcosa-path'] = helper.get_wcosa_path() internal_config_data['current-path'] = helper.linux_path(curr_path) internal_config_data['cmake-version'] = settings.get_settings_value( 'cmake-version') # get c and cxx flags board_properties = board_parser.get_board_properties( user_config_data['board'], internal_config_data['wcosa-path'] + '/wcosa/boards.json') internal_config_data[ 'cmake-c-flags'] = platform_parser.get_c_compiler_flags( board_properties, internal_config_data['wcosa-path'] + '/toolchain/cosa/platform.txt', settings.get_settings_value('include-extra-flags')) internal_config_data[ 'cmake-cxx-flags'] = platform_parser.get_cxx_compiler_flags( board_properties, internal_config_data['wcosa-path'] + '/toolchain/cosa/platform.txt', settings.get_settings_value('include-extra-flags')) internal_config_data['cmake-cxx-standard'] = settings.get_settings_value( 'cmake-cxx-standard') internal_config_data['custom-definitions'] = user_config_data[ 'build-flags'] internal_config_data['module-definitions'] = user_config_data[ 'module-flags'] internal_config_data['cosa-libraries'] = user_config_data['cosa-libraries'] with open(helper.linux_path(path), 'w') as f: json.dump(internal_config_data, f, indent=settings.get_settings_value('json-indent')) return internal_config_data
def update_wcosa(path, board, ide): """Updates existing WCosa project""" path = str(path) write('Updating work environment - ', color=Fore.CYAN) verify_path(path) templates_path = helper.linux_path(helper.get_wcosa_path() + '/templates') user_config_path = path + '/config.json' internal_config_path = path + '/wcosa/internal-config.json' general_cmake_path = path + '/wcosa/CMakeLists.txt' # create src, lib, and wcosa folders create_folders(path) # copy all then CMakeLists templates and configuration templates copyfile(templates_path + '/cmake/CMakeLists.txt.tpl', general_cmake_path) copyfile(templates_path + '/config/internal-config.json.tpl', internal_config_path) # recopy any missing files if not os.path.exists(path + '/config.json'): copyfile(templates_path + '/config/config.json.tpl', user_config_path) writeln('done') write('Updating configurations with new changes - ', color=Fore.CYAN) user_data = config.fill_user_config(user_config_path, board, Port(None), ide) project_data = config.fill_internal_config(internal_config_path, path, user_data) cmake.parse_update(general_cmake_path, project_data) if user_data['ide'] == 'clion': copyfile(templates_path + '/ide/clion/CMakeListsPrivate.txt.tpl', path + '/CMakeListsPrivate.txt') # recopy any missing files if not os.path.exists(path + '/CMakeLists.txt'): copyfile(templates_path + '/ide/clion/CMakeLists.txt.tpl', path + '/CMakeLists.txt') if not os.path.exists(path + '/.gitignore-files'): copyfile(templates_path + '/gitignore-files/.gitignore-clion', path + '/.gitignore') cmake.parse_update(path + '/CMakeLists.txt', project_data) cmake.parse_update(path + '/CMakeListsPrivate.txt', project_data) elif not os.path.exists(path + '/.gitignore'): copyfile(templates_path + '/gitignore-files/.gitignore-general', path + '/.gitignore') writeln('done')
def get_all_board(board_path): """parses the board file returns the properties of the board specified""" with open(helper.linux_path(board_path)) as f: board_data = json.load(f, object_pairs_hook=OrderedDict) keys = [] for key in board_data: keys.append(key) return keys
def fill_user_config(path, board, port, ide): """fills the user config file that will be used for internal build""" with open(helper.linux_path(path)) as f: user_config_data = json.load(f, object_pairs_hook=OrderedDict) if not board.use_same(): user_config_data['board'] = str(board) if not ide.use_same(): user_config_data['ide'] = str(ide) if not port.use_same(): user_config_data['port'] = str(port) user_config_data['framework'] = settings.get_settings_value('framework') with open(helper.linux_path(path), 'w') as f: json.dump(user_config_data, f, indent=settings.get_settings_value('json-indent')) return user_config_data
def get_c_compiler_flags(board_properties, platform_path, include_extra=True): """Get template filled c compiler flags""" with open(helper.linux_path(platform_path)) as f: raw_flags = get_raw_flags(f.readlines(), 'c', include_extra) processed_flags = '' for flag in raw_flags.split(' '): data = { 'build.mcu': board_properties['mcu'], 'build.f_cpu': board_properties['f_cpu'], 'runtime.ide.version': settings.get_settings_value('arduino-version') } processed_flags += helper.fill_template(flag, data) + ' ' return processed_flags.strip(' ')
def parse_update(tpl_path, project_data): """reads the cmake template file and completes it using project data""" tpl_path = helper.linux_path(tpl_path) tpl_file = open(tpl_path) tpl_str = tpl_file.readlines() tpl_file.close() new_str = '' index = 0 while index < len(tpl_str): curr_line = tpl_str[index] compare_tag = curr_line.strip('\n').strip(' ') # handle loop statements if compare_tag == LIB_SEARCH_TAG: result = get_elements(tpl_str, index) new_str += lib_search(result[0], project_data) index = result[1] elif compare_tag == COSA_SEARCH_TAG: result = get_elements(tpl_str, index) new_str += cosa_search(result[0], project_data) index = result[1] elif compare_tag == FIRMWARE_GEN_TAG: result = get_elements(tpl_str, index) new_str += firmware_gen(result[0], project_data) index = result[1] elif compare_tag == DEF_SEARCH_TAG: result = get_elements(tpl_str, index) new_str += def_search(result[0], project_data) index = result[1] else: new_str += helper.fill_template(curr_line, project_data) index += 1 tpl_file = open(tpl_path, 'w') tpl_file.write(new_str) tpl_file.close()
def build_wcosa(path, generator=None, make=None, cmake=None, needs_cmake=True): """build wcosa project, cmake and make""" path = str(path) output.writeln('Wcosa project build started', Fore.GREEN) output.write('Verifying the project structure - ', Fore.GREEN) # check if path is valid if not os.path.exists(path): output.write('Project path is invalid: ' + path, Fore.RED) quit(2) # confirm if bin folder/path exists if os.path.exists(helper.linux_path(path + '/wcosa/bin')): os.chdir(helper.linux_path(path + '/wcosa/bin')) else: output.writeln('\nNot a valid WCosa project', Fore.RED) quit(2) output.writeln('done') cmake_program = cmake or get_cmake_program() make_program = make or get_make_program() output.write('Verifying cmake and make installs - ', Fore.GREEN) # check if cmake is in environment paths (unix/linux based systems) if not cmake_program: output.writeln( '\ncmake does not exist, please install it or make sure it is in your environment PATH', Fore.RED) quit(2) # check if make is in environment paths (unix/linux based systems) if not make_program: output.writeln( '\nmake does not exist, please install it or make sure it is in your environment PATH', Fore.RED) quit(2) output.writeln('done') if not generator or not str(generator): generator = Generator(get_generator_for(make_program)) # check if path is valid and get build information from the user config if not os.path.exists(path + '/config.json'): output.write( 'Project user configuration file does not exist, recreate or update the project', Fore.RED) quit(2) else: with open(path + '/config.json') as f: data = json.load(f, object_pairs_hook=OrderedDict) board = data['board'] # check if the current build files are for the current board # clean and build if boards are different if os.path.exists(helper.get_working_directory() + '/Makefile'): with open(helper.get_working_directory() + '/Makefile') as f: makefile_str = ''.join(f.readlines()) if '\n' + board not in makefile_str: output.writeln( 'Since a new board is detected, full build will be triggered', Fore.GREEN) clean_wcosa(path) if needs_cmake: output.writeln('Running the build using cmake and ' + str(generator), Fore.GREEN) cmake_code = subprocess.call(['cmake', '-G', str(generator), '..']) if cmake_code != 0: output.writeln( 'Project build unsuccessful, cmake exited with error code ' + str(cmake_code), Fore.RED) quit(2) make_code = subprocess.call([make_program]) # make returns 2 if the project has not been configured if make_code == 2 or make_code == '2': output.writeln('No Makefiles present, run wcosa build', Fore.RED) quit(2) if make_code != 0: output.writeln( 'Project build unsuccessful, make exited with error code ' + str(make_code), Fore.RED) quit(2) output.writeln('Project successfully built', Fore.GREEN)
def upload_wcosa(path, port): """upload wcosa project to the port specified or an automatically selected one""" path = str(path) output.writeln('Wcosa project upload started', Fore.GREEN) output.write('Verifying build files - ', Fore.GREEN) # confirm if bin folder/path exists if os.path.exists(helper.linux_path(path + '/wcosa/bin')): os.chdir(helper.linux_path(path + '/wcosa/bin')) else: output.writeln('\nNot a valid WCosa project', Fore.RED) # if project has not been built right if not os.path.exists(helper.get_working_directory() + '/Makefile'): output.writeln('\nNo Makefile, build the project first ', Fore.RED) quit(2) output.writeln('done') # check if path is valid and get the user config if not os.path.exists(path + '/config.json'): output.write( 'Project user configuration file does not exist, recreate or update the project', Fore.RED) quit(2) user_port = None data = None else: with open(path + '/config.json') as f: data = json.load(f, object_pairs_hook=OrderedDict) user_port = data['port'].strip(' ') if not port.use_same(): output.write('Using the port provided - ' + str(port), Fore.GREEN) else: # if port is defined in the config file, then use that port if user_port.lower() != 'None'.lower() and user_port != '': port = user_port output.writeln('Using the port from the config file: ' + user_port, Fore.GREEN) # check if the port is valid if port not in get_serial_devices(): output.writeln( '\nPort provided does not have a valid device connected to it', Fore.RED) quit(2) else: output.writeln('Automatically selecting a port', Fore.GREEN) port = serial_ports() output.writeln('Port chosen: ' + port, Fore.GREEN) # save the port in the config file so that update can update the project based on that temp_data = copy.copy(data) temp_data['port'] = str(port) with open(path + '/config.json', 'w') as f: json.dump(temp_data, f, indent=settings.get_settings_value('json-indent')) # do not print the updating logs output.output_status(False) # reset the port in the user config to the port that was there with open(path + '/config.json', 'w') as f: json.dump(data, f, indent=settings.get_settings_value('json-indent')) output.writeln('Upload triggered on ' + str(port), Fore.GREEN) upload_code = subprocess.call([get_make_program(), 'upload']) if upload_code != 0: output.writeln( 'Project upload unsuccessful, make exited with error code ' + str(upload_code), Fore.RED) quit(2) output.writeln('Project upload successful', Fore.GREEN)
def create_wcosa(path, board, ide): """Creates WCosa project from scratch""" path = str(path) write('Creating work environment - ', color=Fore.CYAN) verify_path(path) templates_path = helper.linux_path(helper.get_wcosa_path() + '/templates') user_config_path = helper.linux_path(path + '/config.json') internal_config_path = helper.linux_path(path + '/wcosa/internal-config.json') general_cmake_path = helper.linux_path(path + '/wcosa/CMakeLists.txt') src_path = helper.linux_path(path + '/src/main.cpp') # check if there are already src and lib folders. We do not want to delete those folders if len(helper.get_dirs(path)) > 0 and (os.path.exists(path + '/src') or os.path.exists(path + '/lib')): writeln( '\nThere is already a src and/or lib folder in this directory. Use wcosa update instead', color=Fore.RED) quit(2) # create src, lib, and wcosa folders create_folders(path, True) # copy all then CMakeLists templates and configuration templates copyfile(templates_path + '/cmake/CMakeLists.txt.tpl', general_cmake_path) copyfile(templates_path + '/config/internal-config.json.tpl', internal_config_path) copyfile(templates_path + '/config/config.json.tpl', user_config_path) copyfile(templates_path + '/examples/main.cpp', src_path) writeln('done') write('Updating configurations based on the system - ', color=Fore.CYAN) user_data = config.fill_user_config(user_config_path, board, Port(None), ide) project_data = config.fill_internal_config(internal_config_path, path, user_data) cmake.parse_update(general_cmake_path, project_data) if user_data['ide'] == 'clion': copyfile(templates_path + '/ide/clion/CMakeLists.txt.tpl', path + '/CMakeLists.txt') copyfile(templates_path + '/ide/clion/CMakeListsPrivate.txt.tpl', path + '/CMakeListsPrivate.txt') copyfile(templates_path + '/gitignore-files/.gitignore-clion', path + '/.gitignore') cmake.parse_update(path + '/CMakeLists.txt', project_data) cmake.parse_update(path + '/CMakeListsPrivate.txt', project_data) else: copyfile(templates_path + '/gitignore-files/.gitignore-general', path + '/.gitignore') writeln('done') writeln('Project Created and structure:', color=Fore.YELLOW) writeln('src -> All source files go here:', color=Fore.YELLOW) writeln('lib -> All custom libraries go here', color=Fore.YELLOW) writeln('wcosa -> All the build files are here (do no modify)', color=Fore.YELLOW)