diff --git a/README.md b/README.md index b63555f..11c2b2e 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,33 @@ Install pymaketool: $ pip3 install pymaketool ``` +Create new basic C project. +```bash +$ pynewproject CLinuxGCC + (author) Your name: Ericson + (project_name) Your project name: hello + +$ cd hello + +hello$ make clean + +hello$ make + +hello$ ./Release/hello +``` +Note: this example use **EclipseAddon** by default, pymaketool generate files *.setting/language.settings.xml* and *.cproject*. + +## Quick start in Docker + +Pull imagen and run container: +```bash +$ docker pull ericsonjoseph/pymaketool + +$ docker run -it ericsonjoseph/pymaketool + +ubuntu@$ pynewproject CLinuxGCC +``` + ## Quick Info **pymaketool** process modules of code like objects. These objects ware define by files **_mk.py*. With Python you can code how to discover and get source files and include paths, e.g.: diff --git a/docs/source/conf.py b/docs/source/conf.py index 13c15ee..2cd8689 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ author = 'Ericson Joseph' # The full version, including alpha/beta/rc tags -release = '2.0.2' +release = '2.0.3' version = release diff --git a/pymakelib/__init__.py b/pymakelib/__init__.py index 1d07892..c32c90b 100644 --- a/pymakelib/__init__.py +++ b/pymakelib/__init__.py @@ -31,6 +31,7 @@ from abc import ABC,abstractmethod import logging from logging import Logger as SysLogger +from typing import List FORMATTER = logging.Formatter("%(levelname)-8s%(filename)s:%(lineno)d %(message)s") @@ -77,7 +78,7 @@ class MKVARS(): SIZE = '$(SIZE)' TARGET = '$(TARGET)' PROJECT = '$(PROJECT)' - STATIC_LIBS = '$(addprefix -L,$(dir $(SLIBS_OBJECTS))) $(addprefix -l,$(SLIBS_NAMES))' + STATIC_LIBS = '$(SLIBS_NAMES)' def MOD_PATH(wk): return wk['modPath'] @@ -144,6 +145,7 @@ def getProjectInstance() -> AbstractMake: from pathlib import Path import copy from . import prelib as plib +from . import module import sys class Pymaketool(): @@ -163,4 +165,11 @@ def readModules(self, modulesPaths) -> list: for filename in modulesPaths: mod = plib.readModule(filename, copy.deepcopy(self.compilerOpts), None) self.modules.extend(mod) + return self.modules + + def read_modules(self, modulesPaths) -> List[module.AbstractModule]: + self.modules = [] + for filename in modulesPaths: + mod = plib.read_module(filename, copy.deepcopy(self.compilerOpts), None) + self.modules.extend(mod) return self.modules \ No newline at end of file diff --git a/pymakelib/generator.py b/pymakelib/generator.py new file mode 100644 index 0000000..743e864 --- /dev/null +++ b/pymakelib/generator.py @@ -0,0 +1,185 @@ +from os import write +from pathlib import Path +from . import Define as D +from . import preconts as K +from . import Pymaketool +from .module import AbstractModule, StaticLibraryModule +from . import Logger +from abc import ABC, abstractmethod + +from pymakelib import module + +log = Logger.getLogger() + +def getLineSeparator(key: str, num: int): + header = '' + for _ in range(num): + header += key + return header + +def macrosDictToString(macros): + mstr = [] + if isinstance(macros, dict): + for key in macros: + if macros[key] != None and macros[key] != '': + if isinstance(macros[key], str): + mstr.append('-D{}=\\\"{}\\\"'.format(key, macros[key])) + elif isinstance(macros[key], bool): + mstr.append( + '-D{}={}'.format(key, '1' if macros[key] else '0')) + elif isinstance(macros[key], D): + mstr.append( + '-D{}={}'.format(key, macros[key].getDefine())) + else: + mstr.append('-D{}={}'.format(key, macros[key])) + else: + mstr.append('-D{}'.format(key)) + + return ' '.join(mstr) + + +class Generator(ABC): + + def __init__(self, module: AbstractModule, project: Pymaketool): + self.module = module + self.project = project + self.output = [] + + @abstractmethod + def process(self) -> str: + pass + +class MakeGenerator(Generator): + + def __init__(self, module, project: Pymaketool): + super().__init__(module, project) + self.isstaticlib = isinstance(module, StaticLibraryModule) + if self.isstaticlib: + mod:StaticLibraryModule = module + mod.decorate_module() + + def write(self, value): + self.output.append(value) + + def get_srcs_dirs(self, srcs) -> list: + dirs = [] + for src in srcs: + dirs.append(Path(str(src)).parent) + dirs = list(set(dirs)) + return dirs + + def compiler_opts2str(self, compiler_opts): + mstr = [] + def proc(moduleCompileOps): + if isinstance(moduleCompileOps, dict): + for key in moduleCompileOps: + if key == 'TARGETS': + continue + if (key == K.COMPOPTS_MACROS_KEY and isinstance(moduleCompileOps[key], dict)): + macros = macrosDictToString(moduleCompileOps[key]) + mstr.append(macros) + else: + mstr.append(' '.join(moduleCompileOps[key])) + + elif isinstance(moduleCompileOps, list): + for item in moduleCompileOps: + mstr.append(item) + + if isinstance(compiler_opts, dict): + proc(compiler_opts) + elif isinstance(compiler_opts, list): + for moduleCompileOps in compiler_opts: + proc(moduleCompileOps) + + rmstr = list(filter(lambda item: item, mstr)) + rmstr = ' '.join(rmstr) + rmstr = ' '.join(rmstr.split()) + log.debug(f"compiler options: {rmstr}") + return rmstr + + def write_header(self): + mod_path = f"{self.module.path}" + self.write("{}\n".format(getLineSeparator('#', 52))) + self.write("#{0:^50}#\n".format(mod_path)) + self.write("{}\n".format(getLineSeparator('#', 52))) + self.write("\n") + + def write_srcs(self): + prefixSrcs = "" + if self.isstaticlib: + prefixSrcs = self.module.name.upper() + "_" + srcs = self.module.getSrcs() + for src in srcs: + if str(src).endswith('.c'): + self.write("{}CSRC += {}\n".format(prefixSrcs, src)) + elif str(src).endswith('.cpp'): + self.write("{}CXXSRC += {}\n".format(prefixSrcs, src)) + elif str(src).endswith('.s'): + self.write("{}ASSRC += {}\n".format(prefixSrcs, src)) + self.write('\n') if srcs else None + + def write_incs(self): + incs = self.module.getIncs() + for inc in incs: + if inc: + self.write("INCS += -I{}\n".format(inc)) + self.write('\n') if incs else None + + def write_compiler_opts(self): + proj_settings = self.project.projSettings; + comp_opts = self.module.getCompilerOpts() + if comp_opts: + srcs = self.module.getSrcs() + isstatic = self.isstaticlib + for src in srcs: + if isstatic: + objs = str(src).replace('.c', '.o').replace('.s', '.o') + outputObj = '$({}_OUTPUT)/'.format(self.module.key) + str(objs) + self.write("{} : CFLAGS = {}\n".format(str(outputObj), self.compiler_opts2str(comp_opts))) + else: + objs = str(src).replace('.cpp', '.o') + objs = objs.replace('.c', '.o') + objs = objs.replace('.s', '.o') + ouputobj = Path(str(proj_settings['FOLDER_OUT']) + '/' + str(objs)) + log.debug(ouputobj) + self.write("{} : CFLAGS = {}\n".format(str(ouputobj), self.compiler_opts2str(comp_opts))) + + + def write_staticlib_def(self): + mod: StaticLibraryModule = self.module + log.debug(f"module \'{mod.path}\' static library name {mod.name}") + log.debug(f"module \'{mod.path}\' static output directory {mod.output_dir}") + self.write('{}_NAME = {}\n'.format(mod.key, mod.name)) + self.write('{}_OUTPUT = {}\n'.format(mod.key, str(mod.output_dir))) + library = mod.output_dir / Path('lib'+mod.name+'.a') + self.write('{}_AR = {}\n'.format(mod.key, str(library))) + self.write('\n') + + def write_staticlib_rules(self): + mod: StaticLibraryModule = self.module + self.write('{0}'.format(mod.objects)) + self.write('\n\n' if mod.objects else '') + self.write('{}'.format(mod.rule)) + self.write('\n\n' if mod.rule else '') + self.write('{}\n'.format(mod.command)) + self.write('\n\n') + self.write('SLIBS_NAMES += {}\n'.format(mod.linker)) + self.write('SLIBS_OBJECTS += {}\n'.format(mod.library)) + if mod.rebuild: + self.write('\n') + for src in mod.getSrcs(): + obj = str(src).replace('.c', '.o').replace('.s', '.o') + outputObj = '$({}_OUTPUT)/'.format(mod.key) + str(obj) + self.write("{} : .FORCE\n".format(outputObj)) + self.write('\n') + + def process(self) -> str: + self.write_header() + if self.isstaticlib: + self.write_staticlib_def() + self.write_srcs() + self.write_incs() + self.write_compiler_opts() + if self.isstaticlib: + self.write_staticlib_rules() + return ''.join(self.output) diff --git a/pymakelib/module.py b/pymakelib/module.py index d7ea607..5ed8076 100644 --- a/pymakelib/module.py +++ b/pymakelib/module.py @@ -33,7 +33,7 @@ from pathlib import Path from . import preconts as K from . import git -from abc import ABC,abstractmethod +from abc import ABC,abstractmethod, ABCMeta from . import Logger log = Logger.getLogger() @@ -50,10 +50,27 @@ class IncType: class StaticLibrary: - def __init__(self, name: str, outputDir: str, rebuild=False): + def __init__(self, name: str, outputDir: str, rebuild=False, lib_linked_opts=None, orden=1): self.name = name + self.orden = orden self.outputDir = Path(outputDir) self.rebuild = rebuild + self.mkkey = self.name.upper() + self.lib_name = 'lib' + self.name + '.a' + self.library = self.outputDir / Path(self.lib_name) + self.lib_objs = f"{self.mkkey}_OBJECTS = $({self.mkkey}_CSRC:%.c=$({self.mkkey}_OUTPUT)/%.o) $({self.mkkey}_CSRC:%.s=$({self.mkkey}_OUTPUT)/%.o)" + self.lib_objs_compile = f"$({self.mkkey}_OUTPUT)/%.o: %.c\n\t$(call logger-compile-lib,\"CC\",\"{self.library}\",$<)\n\t@mkdir -p $(dir $@)\n\t$(CC) $(CFLAGS) $(INCS) -o $@ -c $<" + self.lib_compile = f"$({self.mkkey}_AR): $({self.mkkey}_OBJECTS)\n\t$(call logger-compile,\"AR\",$@)\n\t$(AR) -rc $@ $(filter %.o,$({self.mkkey}_OBJECTS))" + self.lib_linked_opts = lib_linked_opts + self.lib_linked = "-L{0} -l{1} {2}".format(self.outputDir, self.name, self._get_str_linked_opts(self.lib_linked_opts)) + + def _get_str_linked_opts(self, opts): + if isinstance(opts, str): + return opts + elif isinstance(opts, list): + return ' '.join(opts) + else: + return "" def setRebuild(self, rebuild: bool): self.rebuild = rebuild @@ -84,7 +101,9 @@ def __init__(self, srcs, incs, flags, filename, staticLib: StaticLibrary = None) self.incs = incs self.flags = flags self.filename = filename + self.module_name = "" self.staticLib = staticLib + self.orden = 0 if staticLib == None else staticLib.orden def isEmpty(self): if not self.srcs and not self.incs and not self.staticLib: @@ -247,9 +266,27 @@ class AbstractModule(ABC): Attributes: path (str): path of module """ - def __init__(self, path) -> None: + def __init__(self) -> None: super().__init__() - self.path = path + self.module_name = self.get_module_name() + self.path = self.get_path() + self.dir = Path(self.path).parent + + def get_module_name(self) -> str: + """Module name + + Returns: + str: name of module (default: class name) + """ + return self.__class__.__name__ + + def get_path(self): + """Get path of module in filesystem + + Returns: + str: path (default: self.__module__.module_name) + """ + return f"{self.__module__}.{self.module_name}" def init(self): """Initialization of module @@ -283,10 +320,10 @@ def findSrcs(self, src_type: SrcType) -> list: Returns: list: list of sources paths realtive to project """ - log.debug(f"find srcs in {self.path}") + log.debug(f"find srcs in {self.dir}") srcs = [] for ext in src_type: - srcs += list(Path(self.path).rglob('*' + ext)) + srcs += list(Path(self.dir).rglob('*' + ext)) return srcs def findIncs(self, inc_type: IncType) -> list: @@ -300,7 +337,7 @@ def findIncs(self, inc_type: IncType) -> list: """ incsfiles = [] for ext in inc_type: - incsfiles += list(Path(self.path).rglob('*' + ext)) + incsfiles += list(Path(self.dir).rglob('*' + ext)) incs = [] for i in incsfiles: @@ -330,6 +367,85 @@ def getCompilerOpts(self): """ pass +class StaticLibraryModule(metaclass=ABCMeta): + + @classmethod + def __subclasshook__(cls, subclass): + return (hasattr(subclass, 'get_lib_name') and + callable(subclass.get_lib_name) and + hasattr(subclass, 'get_lib_outputdir') and + callable(subclass.get_lib_outputdir)) + + def decorate_module(self): + self.name = self.get_lib_name() + self.lib_name = 'lib' + self.name + '.a' + self.output_dir = Path(self.get_lib_outputdir()) + self.orden = self.get_order() + self.rebuild = self.get_rebuild() + self.key = self.name.upper() + self.library = self.output_dir / Path(self.lib_name) + self.objects = self.get_objects(self.key) + self.rule = self.get_rule(self.key) + self.command = self.get_command(self.key) + self.linker = self.get_linker(self.key) + + def _get_str_linked_opts(self, opts): + if isinstance(opts, str): + return opts + elif isinstance(opts, list): + return ' '.join(opts) + else: + return "" + + @abstractmethod + def get_lib_name(self) -> str: + raise NotImplementedError + + @abstractmethod + def get_lib_outputdir(self) -> str: + raise NotImplementedError + + def get_linker_opts(self) -> str: + return None + + def get_objects(self, key) -> str: + return f"{key}_OBJECTS = $({key}_CSRC:%.c=$({key}_OUTPUT)/%.o) $({key}_CSRC:%.s=$({key}_OUTPUT)/%.o)" + + def get_rule(self, key) -> str: + return f"$({key}_OUTPUT)/%.o: %.c\n\t$(call logger-compile-lib,\"CC\",\"{key}\",$<)\n\t@mkdir -p $(dir $@)\n\t$(CC) $(CFLAGS) $(INCS) -o $@ -c $<" + + def get_command(self, key) -> str: + return f"$({key}_AR): $({key}_OBJECTS)\n\t$(call logger-compile,\"AR\",$@)\n\t$(AR) -rc $@ $(filter %.o,$({key}_OBJECTS))" + + def get_linker(self, key) -> str: + return "-L{0} -l{1}".format(self.output_dir, self.name, self._get_str_linked_opts(self.get_linker_opts())) + + def get_order(self): + return 1 + + def get_rebuild(self): + return False + + +class POJOModule(AbstractModule): + def __init__(self, path): + super().__init__(path) + self.includes = [] + self.sources = [] + self.compiler_opts = None + self.init_resp = None + + def init(self): + return self.init_resp + + def getSrcs(self) -> list: + return self.includes + + def getIncs(self) -> list: + return self.sources + + def getCompilerOpts(self): + return self.compiler_opts class BasicCModule(AbstractModule): """Basic C module, find all sources and includes in module path @@ -337,8 +453,8 @@ class BasicCModule(AbstractModule): Args: path (str): path to module, _mk.py file. """ - def __init__(self, path): - super().__init__(path) + def __init__(self): + super().__init__() def getSrcs(self) -> list: """Return list with all sources in module path @@ -368,8 +484,8 @@ class ExternalModule(AbstractModule): Raises: AttributeError: path is not valid """ - def __init__(self, path): - super().__init__(path) + def __init__(self): + super().__init__() try: modPath = self.getModulePath() if not modPath.endswith("_mk.py"): @@ -450,15 +566,16 @@ def ModuleClass(clazz): else: log.warning(f"class \'{clazz.__name__}\' in \'{__name__}\' not inheritance of Module.AbstractModule") - classdir = str(clazz) - log.debug(f"class dir {classdir}") - m = re.search(r"[a-zA-Z\./_-]+)\'>", classdir) - modulePath = None - if m: - p = Path(m.group('dir')) - modulePath = p.parent + # classdir = str(clazz) + # log.debug(f"class dir {classdir}") + # m = re.search(r"[a-zA-Z\./_-]+)\'>", classdir) + # modulePath = None + # if m: + # p = Path(m.group('dir')) + # modulePath = p + # modulePath = f"{clazz.__module__}.{clazz.__name__}" - obj = clazz(modulePath) + obj = clazz() global ModulesInstances try: _ = ModulesInstances @@ -467,7 +584,7 @@ def ModuleClass(clazz): ModulesInstances = [] - log.debug(f"add new instance of ModuleClass \'{clazz.__name__}\' with path {modulePath}") + log.debug(f"add new instance of ModuleClass \'{clazz.__name__}\' with path {clazz.__module__}") ModulesInstances.append(obj) diff --git a/pymakelib/prelib.py b/pymakelib/prelib.py index 0dd629e..e1a7e68 100644 --- a/pymakelib/prelib.py +++ b/pymakelib/prelib.py @@ -26,6 +26,9 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +from typing import List import sys from pathlib import Path import importlib.util @@ -33,7 +36,7 @@ from . import Define as D from .module import ModuleHandle from .module import CompilerOptions -from .module import Module, getModuleInstance, cleanModuleInstance +from .module import Module, getModuleInstance, cleanModuleInstance, AbstractModule, POJOModule from .module import StaticLibrary from . import getProjectInstance from . import Logger @@ -116,6 +119,31 @@ def reafGenHeader(headerpath): sys.stdout = stdout_ +def read_module(module_path: Path, compiler_opts, goals=None) -> List[AbstractModule]: + lib = importlib.util.spec_from_file_location(str(module_path), str(module_path)) + mod = importlib.util.module_from_spec(lib) + log.debug(f"exec module {mod.__name__}") + lib.loader.exec_module(mod) + + moduleInstances = getModuleInstance() + modules = [] + + if not moduleInstances: + modHandle = ModuleHandle(module_path.parent, compiler_opts, goals) + m = POJOModule(module_path) + m.init_resp = wprInit(mod, modHandle) + m.includes = wprGetIncs(mod, modHandle) + m.sources = wprGetSrcs(mod, modHandle) + m.compiler_opts = wprGetCompilerOpts(mod, modHandle) + modules.append(m) + else: + modules.extend(getModuleInstance()) + + cleanModuleInstance() + + return modules + + def readModule(modPath, compilerOpts, goals=None): lib = importlib.util.spec_from_file_location(str(modPath), str(modPath)) mod = importlib.util.module_from_spec(lib) @@ -200,7 +228,10 @@ def readModule(modPath, compilerOpts, goals=None): log.debug( f"\'{type(moduleInstance).__name__}\' return empty compiler options") - modules.append(Module(srcs, incs, flags, modPath, staticLib=staticLib)) + m = Module(srcs, incs, flags, modPath, staticLib=staticLib) + if moduleInstance.module_name: + m.module_name = moduleInstance.module_name + modules.append(m) cleanModuleInstance() @@ -422,6 +453,7 @@ def wprGetTargetScript(): else: logkeys.append('>>') + # print labels for i in range(len(targetval)): targetsmk.write("{0:<15} = {1}\n".format( labels[i], targetval[i])) @@ -431,11 +463,11 @@ def wprGetTargetScript(): for i in range(len(labels)): if labels[i] == 'TARGET': - targetsmk.write("\n$({}): {}\n".format( - labels[i], '$(OBJECTS) $(SLIBS_OBJECTS)')) + targetsmk.write("\n$({}): {} {}\n".format( + labels[i], '$(OBJECTS) $(SLIBS_OBJECTS)', '' if i == 0 else "$("+ labels[i-1] + ")")) else: - targetsmk.write("\n$({}): $({})\n".format( - labels[i], labels[i-1])) + targetsmk.write("\n$({}): {}\n".format( + labels[i], '' if i == 0 else "$("+ labels[i-1] + ")")) targetsmk.write( '\t$(call logger-compile,"{}",$@)\n'.format(logkeys[i])) diff --git a/pymakelib/pym.py b/pymakelib/pym.py new file mode 100644 index 0000000..961c6fa --- /dev/null +++ b/pymakelib/pym.py @@ -0,0 +1,45 @@ +from pymakelib import module +import inspect +import logging +import sys + +def __getmodule_caller(func): + def stack_(frame): + framelist = [] + while frame: + framelist.append(frame) + frame = frame.f_back + return framelist + + stack_list = stack_(sys._getframe(1)) + idx = 0 + for stack in stack_list: + idx += 1 + if stack.f_code.co_name == func: + break + parentframe = stack_list[idx] + return parentframe.f_code.co_filename + + +def add_library(name, outputdir, srcs=[], incs=[]): + + @module.ModuleClass + class _(module.BasicCModule, module.StaticLibraryModule): + + def get_module_name(self): # + return str(name).capitalize() # + # Not need in class mode + def get_path(self): # + return __getmodule_caller('add_library') # + + def get_lib_name(self) -> str: + return name + + def get_lib_outputdir(self) -> str: + return outputdir + + def getSrcs(self): + return super().getSrcs() if not srcs else srcs + + def getIncs(self): + return super().getIncs() if not incs else incs \ No newline at end of file diff --git a/pymakelib/toolchain.py b/pymakelib/toolchain.py index 5ef848e..090a4be 100644 --- a/pymakelib/toolchain.py +++ b/pymakelib/toolchain.py @@ -35,6 +35,10 @@ def confARMeabiGCC(binLocation='', prefix='arm-none-eabi-', extIncludes=[]): return confGCC(binLocation, prefix, extIncludes) +def get_c_linux(bin_location='', ext_incs=[]) -> dict: + return get_gcc_linux(bin_location, ext_incs) + + def get_gcc_linux(bin_location='', ext_incs=[]) -> dict: """Get dictionary with gcc compiler set for linux @@ -48,15 +52,32 @@ def get_gcc_linux(bin_location='', ext_incs=[]) -> dict: return confLinuxGCC(binLocation=bin_location, extIncludes=ext_incs) +def get_cpp_linux(bin_location='', ext_incs=[]) -> dict: + return get_gpp_linux(bin_location, ext_incs) + + +def get_gpp_linux(bin_location='', ext_incs=[]) -> dict: + """Get dictionary with g++ compiler set for linux + + Args: + bin_location (str, optional): location of toolchain. Defaults to ''. + ext_incs (list, optional): list of external includes. Defaults to []. + + Returns: + dict: set of gcc compiler e.g. {'CC': 'g++' ... } + """ + return confGCC(binLocation=bin_location, extIncludes=ext_incs, iscpp=True) + + def confLinuxGCC(binLocation='', extIncludes=[]): return confGCC(binLocation, '', extIncludes) -def confGCC(binLocation='', prefix='', extIncludes=[]): +def confGCC(binLocation='', prefix='', extIncludes=[], iscpp=False): binpath = Path(binLocation) cmd_gcc = str(binpath / (prefix + 'gcc')) cmd_gxx = str(binpath / (prefix + 'g++')) - cmd_ld = str(binpath / (prefix + 'gcc')) + cmd_ld = str(binpath / (prefix + ('g++' if iscpp else 'gcc'))) cmd_ar = str(binpath / (prefix + 'ar')) cmd_as = str(binpath / (prefix + 'as')) cmd_objcopy = str(binpath / (prefix + 'objcopy')) diff --git a/scripts/pybuildanalyzer2 b/scripts/pybuildanalyzer2 index 7d585da..fd910e3 100755 --- a/scripts/pybuildanalyzer2 +++ b/scripts/pybuildanalyzer2 @@ -324,7 +324,7 @@ class GtkRegionsWin: class MemRegionView: - PRINT_FORMAT = '| {0:<12}| {1:<15}| {2:<15}| {3:>12}| {4:>12}| {5:>12} {6:<11} {7:>7} |' + PRINT_FORMAT = '| {0:<15}| {1:<15}| {2:<15}| {3:>12}| {4:>12}| {5:>12} {6:<11} {7:>7} |' def __init__(self, regions): self.regions = regions diff --git a/scripts/pymake b/scripts/pymake new file mode 100755 index 0000000..2b3eaf1 --- /dev/null +++ b/scripts/pymake @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +from pymakelib import Pymaketool +from pymakelib import generator + +p = Pymaketool() + +modules_paths = p.getModulesPaths() +print(modules_paths) +modules = p.read_modules(modules_paths) +for m in modules: + g = generator.MakeGenerator(m, p) + print(g.process()) \ No newline at end of file diff --git a/scripts/pymaketool b/scripts/pymaketool index fd80aa9..809fdcc 100755 --- a/scripts/pymaketool +++ b/scripts/pymaketool @@ -49,7 +49,7 @@ log = Logger.getLogger() parser = argparse.ArgumentParser() parser.add_argument('goal', type=str, help='Makefile command goal', default=None, nargs='?') parser.add_argument('--init', type=str, help='initialize project', const=os.path.basename(os.getcwd()), dest='project_name', nargs='?') -parser.add_argument('-v', '--version', action='version', version='%(prog)s 2.0.2') +parser.add_argument('-v', '--version', action='version', version='%(prog)s 2.0.3') args = parser.parse_args() goal = args.goal @@ -153,20 +153,22 @@ def getLineSeparator(key: str, num: int): return header log.debug('**load modules**') +modules = sorted(modules, key=lambda mod: mod.orden) for mod in modules: if mod.isEmpty(): log.debug(f"module \'{mod.filename}\' is empty, module skiped*") continue - - print('Module: {}'.format(mod.filename)) - log.info('read module \'{}\''.format(mod.filename)) + + mod_filename = f"{mod.filename}:{mod.module_name}" + print('Module: {}'.format(mod_filename)) + log.info('read module \'{}\''.format(mod_filename)) srcsfile.write("{}\n".format(getLineSeparator('#', 52))) - srcsfile.write("#{0:^50}#\n".format(str(mod.filename))) + srcsfile.write("#{0:^50}#\n".format(str(mod_filename))) srcsfile.write("{}\n".format(getLineSeparator('#', 52))) if mod.staticLib: - log.debug(f"module \'{mod.filename}\' static library name {mod.staticLib.name}") - log.debug(f"module \'{mod.filename}\' static output directory {mod.staticLib.outputDir}") + log.debug(f"module \'{mod_filename}\' static library name {mod.staticLib.name}") + log.debug(f"module \'{mod_filename}\' static output directory {mod.staticLib.outputDir}") mkkey = mod.staticLib.name.upper() srcsfile.write('{}_NAME = {}\n'.format(mkkey, mod.staticLib.name)) srcsfile.write('{}_OUTPUT = {}\n'.format(mkkey, str(mod.staticLib.outputDir))) @@ -214,21 +216,22 @@ for mod in modules: objs = str(src).replace('.cpp', '.o') objs = objs.replace('.c', '.o') objs = objs.replace('.s', '.o') - srcsfile.write("{} : CFLAGS = {}\n".format( - projSettings['FOLDER_OUT'] / str(objs), plib.compilerOptsByModuleToLine(mod.flags))) + ouputobj = Path(str(projSettings['FOLDER_OUT']) + '/' + str(objs)) + log.debug(ouputobj) + srcsfile.write("{} : CFLAGS = {}\n".format(str(ouputobj), plib.compilerOptsByModuleToLine(mod.flags))) srcsfile.write('\n') if mod.staticLib: mkkey = mod.staticLib.name.upper() - srcsfile.write('{0}_OBJECTS = $({0}_CSRC:%.c=$({0}_OUTPUT)/%.o) $({0}_CSRC:%.s=$({0}_OUTPUT)/%.o)\n'.format(mkkey)) - srcsfile.write('\n') - srcsfile.write('$({0}_OUTPUT)/%.o: %.c\n\t$(call logger-compile-lib,"CC",\"{1}\",$<)\n\t@mkdir -p $(dir $@)\n\t$(CC) $(CFLAGS) $(INCS) -o $@ -c $<\n'.format(mkkey, library)) - srcsfile.write('\n') - srcsfile.write('$({0}_AR): $({0}_OBJECTS)\n\t$(call logger-compile,"AR",$@)\n\t$(AR) -rc $@ $(filter %.o,$({0}_OBJECTS))'.format(mkkey)) + srcsfile.write('{0}'.format(mod.staticLib.lib_objs)) + srcsfile.write('\n\n' if mod.staticLib.lib_objs else '') + srcsfile.write('{}'.format(mod.staticLib.lib_objs_compile)) + srcsfile.write('\n\n' if mod.staticLib.lib_objs_compile else '') + srcsfile.write('{}\n'.format(mod.staticLib.lib_compile)) srcsfile.write('\n\n') - srcsfile.write('SLIBS_NAMES += {}\n'.format(mod.staticLib.name)) - srcsfile.write('SLIBS_OBJECTS += {}\n'.format(library)) + srcsfile.write('SLIBS_NAMES += {}\n'.format(mod.staticLib.lib_linked)) + srcsfile.write('SLIBS_OBJECTS += {}\n'.format(mod.staticLib.library)) if mod.staticLib.rebuild: srcsfile.write('\n') for src in mod.srcs: @@ -284,7 +287,7 @@ if (USE_EXCLUDE_FOLDERS): for allinc in allIncFoldes: aux = allinc + '/' if not any(aux.startswith(a + "/") for a in includes): - if not str(allinc).startswith('Test/ceedling') and not allinc == '.': + if not str(allinc).startswith('Test/ceedling') and not allinc == '.' and not str(allinc).startswith(str(projSettings['FOLDER_OUT'])): auxpath = Path(allinc) if p.match(auxpath.name): listToExclude.append(str(auxpath.parent)) @@ -313,4 +316,4 @@ try: p.init() except Exception as ex: log.exception(ex) - exit(-1) \ No newline at end of file + exit(-1) diff --git a/setup.py b/setup.py index 8d9cab4..86facdf 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="pymaketool", - version="2.0.2", + version="2.0.3", author="Ericson Joseph", author_email="ericsonjoseph@gmail.com", description="Python Makefile Tool", diff --git a/tests/unit/test_module.py b/tests/unit/test_module.py index 4d7ab24..a310eac 100644 --- a/tests/unit/test_module.py +++ b/tests/unit/test_module.py @@ -19,8 +19,8 @@ def test_basic_c_module(self): class ModTest(module.BasicCModule): pass - mod = ModTest('mod') - self.assertEqual('mod', mod.path) + mod = ModTest() + self.assertEqual('ModTest', mod.module_name) self.assertIsInstance(mod.getSrcs(), list) self.assertIsInstance(mod.getIncs(), list) @@ -38,8 +38,8 @@ def getIncs(self) -> list: 'mod/inc/main.h' ] - mod = ModTest('mod') - self.assertEqual('mod', mod.path) + mod = ModTest() + self.assertEqual('ModTest', mod.module_name) self.assertIsInstance(mod.getSrcs(), list) self.assertIsInstance(mod.getIncs(), list)