HBehrens / puncover

Analyses C/C++ build output for code size, static variables, and stack usage

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Windows compatibility (.exe ARM tools)

nono313 opened this issue · comments

I managed to build and install puncover on my Windows 10 machine.
When I try to run it, I get the following error :

parsing ELF at firmware.elf Traceback (most recent call last): File "C:\Python\Python37-32\Scripts\puncover-script.py", line 11, in <module> load_entry_point('puncover==0.0.1', 'console_scripts', 'puncover')() File "C:\Python\Python37-32\lib\site-packages\puncover-0.0.1-py3.7.egg\puncover\puncover.py", line 58, in main builder.build_if_needed() File "C:\Python\Python37-32\lib\site-packages\puncover-0.0.1-py3.7.egg\puncover\builders.py", line 32, in build_if_needed self.build() File "C:\Python\Python37-32\lib\site-packages\puncover-0.0.1-py3.7.egg\puncover\builders.py", line 22, in build self.collector.parse_elf(self.get_elf_path()) File "C:\Python\Python37-32\lib\site-packages\puncover-0.0.1-py3.7.egg\puncover\collector.py", line 306, in parse_elf self.parse_assembly_text("".join(self.gcc_tools.get_assembly_lines(elf_file))) File "C:\Python\Python37-32\lib\site-packages\puncover-0.0.1-py3.7.egg\puncover\gcc_tools.py", line 27, in get_assembly_lines return self.gcc_tool_lines('objdump', ['-dslw', os.path.basename(elf_file)], os.path.dirname(elf_file)) File "C:\Python\Python37-32\lib\site-packages\puncover-0.0.1-py3.7.egg\puncover\gcc_tools.py", line 23, in gcc_tool_lines proc = subprocess.Popen([self.gcc_tool_path(name)] + args, stdout=subprocess.PIPE, cwd=cwd) File "C:\Python\Python37-32\lib\site-packages\puncover-0.0.1-py3.7.egg\puncover\gcc_tools.py", line 18, in gcc_tool_path raise Exception("Could not find %s" % path) Exception: Could not find C:\Program Files\...\gcc\arm-none-eabi\bin\objdump

As this is Windows, the objdump tool do exist but as a 'objdump.exe' file, not as 'objdump'.

Would it be possible to check for .exe file and use them for Windows users ?

I am not sure puncover will word on Windows at all as this hasn't been tested. Adding .exe to the various executable paths sounds easy enough but traditionally there are more issues with Windows vs. non-Windows systems that are in the details.

Before going down that rabbit whole and backing Windows support via CI: Did you try running its unit-tests from source? That would give some early signal about the general feasibility of using puncover on Windows.

I have run the command python -m unittest which I assume is what should be used to execute the unit tests (tell me if I'm wrong), and I do get a lot of errors but all related to the same thing it seems.

unit-test-error.log

It seems that it's mostly the program looking for a root / and an assert checking paths with / and not .

I am also trying to run pancover on windows, a fast change of some files made it run and the unit test returned 3 errors, which are a mismatch of paths and looks okay.

Running it i only see a partly a overview, gcc was setup to create the stack usage files. It seems for me somewhere else is matching problem between file names and symbol names.

Perhaps it helps to get an idea, where to search for more os dependencies, or you have an idea what i could check to make it work additionally on windows.

gcc_tool_path(self, name):
        if os.name == 'nt':
          path = self.gcc_base_filename + name + ".exe"
        else:
          path = self.gcc_base_filename + name`

normalize_files_paths
And modifying the normalize_files_paths

   def normalize_files_paths(self, base_dir):
        base_dir = os.path.abspath(base_dir) if base_dir else os.path.sep
        for s in self.all_symbols():
            path = s.get(PATH, None)
            if path:
                if path.startswith(base_dir):
                    path = os.path.relpath(path, base_dir)
                elif path.startswith(os.path.sep):
                    path = path[1:]
                s[PATH] = path

and file_element_

def file_element_for_path(self, path, type, default_values):
        if not path:
            return None

        result = self.file_elements.get(path, None)
        if not result:
            parent_dir = os.path.dirname(path)
            parent_folder = self.folder_for_path(parent_dir) if parent_dir and parent_dir != os.path.sep else None
            result = {
                TYPE: type,
                PATH: path,
                FOLDER: parent_folder,
                NAME: os.path.basename(path),
            }
            for k, v in default_values.items():
                result[k] = v
            self.file_elements[path] = result

        return result if result[TYPE] == type else None

edit
so it seems to be the different regex in the collector.py don't like the windows path c:/
changing that also make it more usable. Still seem to be a few things missing

    if os.name == 'nt':
      parse_size_line_re = re.compile(r"^([\da-f]{8})\s+([\da-f]{8})\s+(.)\s+(\w+)(\s+([\w]:)([^:]+):(\d+))?")
    else:
      parse_size_line_re = re.compile(r"^([\da-f]{8})\s+([\da-f]{8})\s+(.)\s+(\w+)(\s+([^:]+):(\d+))?")

unit_tests.txt
grafik

grafik

Hello,

before I saw this post i fixed the problem in my own way. You can see the results of my changes in the attached patch-file. If you have any questions about my changes then feel free to concat me.

fixWindowsPaths.patch.txt

Thank you @ckak07. I managed to run puncover on Windows thanks to your patch.

Maybe this could be included in a PR for integration ?

@ckak07 Thanks for the patch, this works perfectly 👍

Just a side note, I think the regex pattern suggested by @tobiwan88 is wrong.

This is the regex output you get with his suggestion

https://regex101.com/r/elYiD0/1

As you see match group for file is number 7 and for the line it is match group 8. However, in the code the match groups should be 6 and 7 respectively

file = match.group(6)
line = int(match.group(7))

My suggestion is to change the pattern for windows to be

parse_size_line_re = re.compile(r"^([\da-f]{8})\s+([\da-f]{8})\s+(.)\s+(\w+)(\s+([a-zA-Z]:.+)):(\d+)?")

See example

https://regex101.com/r/uoL5Xb/1

Just an FYI. I fixed the OS path dependency issue. Feel free to test my changes

#64

This is fixed thanks to @vChavezB in #70 , and released as version 0.3.0 to pypi.