#!/usr/bin/python # -*- coding: utf-8 -*- ## ## @author Edouard DUPIN ## ## @copyright 2012, Edouard DUPIN, all right reserved ## ## @license MPL v2.0 (see license file) ## ## ## Executable/binary builder ## from lutin import multiprocess from lutin import tools from lutin import debug from lutin import depend from lutin import env import os ## ## Initialize the builder, if needed ... to get dependency between builder (for example) ## def init(): pass ## ## Get the current builder type. ## Return the type of builder ## def get_type(): return "linker" ## ## @brief Get builder input file type ## @return List of extention supported ## def get_input_type(): return ["o"] ## ## @brief Get builder output file type ## @return List of extention supported ## def get_output_type(): return ["", "exe", "bin"] ## ## @brief Get builder support multi-threading or not ## @return True Multithreading supported ## @return False Multithreading NOT supported ## def get_support_multithreading(): return False ## ## @brief Commands for running gcc to link an executable. ## def link(file, binary, target, depancy, flags, name, basic_path, static = False): file_src = file file_dst = target.get_build_file_bin(name, static) file_depend = file_dst + target.suffix_dependence file_cmd = file_dst + target.suffix_cmd_line file_warning = file_dst + target.suffix_warning debug.extreme_verbose("list files = " + str(depancy.src)) list_static = [] list_dynamic = [] if static == True: #get all parent static libs list_static = depancy.src['static'] # get only parent shared that is not static for elem in depancy.src['dynamic']: lib_name = elem[:-len(target.suffix_lib_dynamic)] + target.suffix_lib_static if lib_name not in depancy.src['static']: list_dynamic.append(elem) else: #get all parent dynamic libs list_dynamic = depancy.src['dynamic'] # get only parent shared that is not static for elem in depancy.src['static']: lib_name = elem[:-len(target.suffix_lib_static)] + target.suffix_lib_dynamic if lib_name not in depancy.src['dynamic']: list_static.append(elem) # set ccache interface: compilator_ccache = "" if env.get_ccache() == True: compilator_ccache = "ccache" #create comand line: cmd = [compilator_ccache] # a specific case to not depend on the libstdc++ automaticly added by the G++ or clang++ compilator ==> then need to compile with GCC or CLANG if use libcxx from llvm or other ... if "need-libstdc++" in depancy.flags \ and depancy.flags["need-libstdc++"] == True: cmd.append(target.xx) else: cmd.append(target.cc) try: cmd.append(target.arch) except: pass try: cmd.append(target.sysroot) except: pass try: cmd.append(["-o", file_dst]) except: pass try: cmd.append(file_src) except: pass try: cmd.append(depancy.src['src']) except: pass try: cmd.append(list_static) except: pass try: for elem in list_dynamic: lib_path = os.path.dirname(elem) lib_name = elem[len(lib_path)+len(target.prefix_lib)+1:-len(target.suffix_lib_dynamic)] cmd.append("-L" + lib_path) cmd.append("-l" + lib_name) if target.name != "MacOs" \ and target.name != "Android": if len(list_dynamic) > 0: cmd.append("-Wl,-R$ORIGIN/../lib/") except: pass cmd.append("-Wl,-rpath,\"$ORIGIN/../lib\"") try: cmd.append(flags["local"]["link"]) except: pass try: cmd.append(depancy.flags["link"]) except: pass try: cmd.append(target.global_flags["link"]) except: pass for view in ["local", "export"]: if view not in flags: continue for type in ["link-lib"]: if type in flags[view]: cmd.append([("-l" + sss).replace("-l/", "/") for sss in flags[view][type] ]) for type in ["link-bin"]: if type in flags[view]: cmd.append(flags[view][type]) for type in ["link-lib"]: if type in depancy.flags: cmd.append([("-l" + sss).replace("-l/", "/") for sss in depancy.flags[type] ]) for type in ["link-lib"]: if type in target.global_flags: cmd.append([("-l" + sss).replace("-l/", "/") for sss in target.global_flags[type] ]) for type in ["link-bin"]: if type in target.global_flags: cmd.append(target.global_flags[type]) if type in depancy.flags: cmd.append(depancy.flags[type]) cmd_line = tools.list_to_str(cmd) # check the dependency for this file : if depend.need_re_package(file_dst, file_src, True, file_cmd=file_cmd, cmd_line=cmd_line) == False \ and depend.need_re_package(file_dst, depancy.src, False, file_cmd=file_cmd, cmd_line=cmd_line) == False: return file_dst tools.create_directory_of_file(file_dst) debug.print_element("Executable", name, "==>", os.path.relpath(file_dst)) multiprocess.run_command(cmd_line, store_output_file=file_warning) if target.config["mode"] == "release"\ or env.get_force_strip_mode() == True: # get the file size of the non strip file originSize = tools.file_size(file_dst); debug.print_element("Executable(strip)", name, "", "") cmd_lineStrip=tools.list_to_str([ target.strip, file_dst]) multiprocess.run_command(cmd_lineStrip, store_output_file=file_warning) # get the stip size of the binary strip_size = tools.file_size(file_dst) debug.debug("file reduce size : " + str(originSize/1024) + "ko ==> " + str(strip_size/1024) + "ko") # write cmd line only after to prevent errors ... tools.store_command(cmd_line, file_cmd)