Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare two PyInstaller generated Linux executables in Python

The problem is quite simple, but I don't see any sample.

I need to compare two executables generated by PyInstaller and determine which one is newer (but not by simple timestamp). Timestamp might be newer, but the content stays the same. I need to replace the old file only if both timestamp is newer and the content is different.

Any example solution? For example simple version tag in PyInstaller (strange but can't find much info on it, in manual it says only about using Windows version files)

update:

  • Linux executables
  • Have access to files generation process.
  • it is cli app and best is not to use vcs, some simple solution.
  • actual comparison process will take place in a Python script
  • tried filecmp as suggested - it returns False even for the same build generated 2 times (with shallow=False flag).

Best option as to my point of view is to compare content & timestamp. if timestamp is newer and the content is different => means new version.

like image 707
user1935987 Avatar asked Oct 16 '22 13:10

user1935987


1 Answers

When you run pyinstaller, you have to ensure that you perform a reproducible build. i.e one that can be used to perform a bit for bit comparison between executables. According to the docs:

Python uses a random hash to make dicts and other hashed types, and this affects compiled byte-code as well as PyInstaller internal data structures. As a result, two builds may not produce bit-for-bit identical results even when all the components of the application bundle are the same and the two applications execute in identical ways.

To do this, just set the PYTHONHASHSEED environment variable to a constant number before running pyinstaller:

PYTHONHASHSEED=1
export PYTHONHASHSEED
pyinstaller --onefile test.py

unset PYTHONHASHSEED

Then you can use whatever tools/modules you want to compare the executables, such as filecmp, BeyondCompare etc., or even just a simple checksum in linux:

cksum dist/test

EDIT: With regards to timestamping or tagging a binary - you could do the following to add additional notes to a linux binary after its built:

# Create a file with the notes or comments to add to the binary. 
# I am adding the current date for versioning info
date > version

# Add notes to the binary
objcopy --add-section .pyversion=version --set-section-flags .pyversion=noload,readonly dist/test dist/test-with-version

# Check the version/notes on the new binary
objdump -sj .pyversion dist/test-with-version

You should get something like:

dist/test-with-version:     file format elf64-x86-64
Contents of section .pyversion:
0000 46726920 53657020 31342031 343a3339  Fri Sep 14 14:39
0010 3a333620 41455354 20323031 380a      :36 AEST 2018.
like image 189
moebius Avatar answered Oct 21 '22 00:10

moebius