post-install-nix.pl 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use 5.30.0;
  5. use File::Copy;
  6. use File::Basename;
  7. my ($original_bin, $tuned_bin) = ($ARGV[0], $ARGV[1]);
  8. die("usage: $0 path/to/original/executable path/to/modified/executable")
  9. if (!$original_bin || !$tuned_bin);
  10. # returns hash of ALL (recursively) resolved dependecies,
  11. # i.e. {lib_1.so => /path/to/lib_1.so, ... }
  12. my $resolve = sub {
  13. my $binary = shift;
  14. my $list = `ldd $binary 2>&1`;
  15. my %mapping =
  16. map { m/(.*) => (.*)/; ($1, $2) }
  17. map { s/\s*(lib.*) \(.*/$1/r }
  18. grep { /\s*lib.* => / }
  19. split /\n/, $list;
  20. return \%mapping;
  21. };
  22. # returns true if library should be skipped (i.e. it is a SYSTEM dependency)
  23. my $skip = sub {
  24. my $path = shift;
  25. return scalar($path =~ m{^(/usr/|/lib/)});
  26. };
  27. my $dest_dir = dirname($tuned_bin);
  28. my $copied = 0;
  29. my $resolved = $resolve->($original_bin);
  30. for my $lib (keys $resolved->%*) {
  31. my $path = $resolved->{$lib};
  32. next if $skip->($path);
  33. my $target = "$dest_dir/$lib";
  34. next if (-e $target);
  35. if (File::Copy::syscopy($path, $target)) {
  36. say "[copied] $lib";
  37. ++$copied;
  38. } else {
  39. say "[error] cannot copy $lib ($path -> $target): $!";
  40. }
  41. say $lib;
  42. }
  43. say "totally copied $copied libs";
  44. =x
  45. my $info = $read_elf->($tuned_bin);
  46. my $all_libs = $get_dynamic->($info);
  47. my $dest_dir = $get_rpath->($info);
  48. my $resolved = $resolve->($original_bin);
  49. my $processed = {};
  50. my $copied = 0;
  51. say "dest_lib_dir = $dest_dir";
  52. mkdir($dest_dir);
  53. # try to copy each found dependecy
  54. while (my $lib = shift($all_libs->@*)) {
  55. # skip already processed and not resolved dependency
  56. next if exists $processed->{$lib};
  57. say "zzz $lib";
  58. #if (exists $resolved->{$lib}) {
  59. # my $r = $resolved->{$lib};
  60. # next unless $r =~ m|/home/|;
  61. #}
  62. my $source_lib = $resolved->{$lib};
  63. my $dest_lib = "$dest_dir/$lib";
  64. # skip already existing (copied) dependency
  65. if (-e $dest_lib) {
  66. $processed->{$lib} = 1;
  67. next;
  68. }
  69. if ($skip->($source_lib)) {
  70. #say "[skip] $lib";
  71. next;
  72. }
  73. if (File::Copy::syscopy($source_lib, $dest_lib)) {
  74. say "[copy] $lib ($source_lib)";
  75. # $DB::single = 1 if ($lib eq 'libwx_gtk3u_richtext-3.2.so.0');
  76. ++$copied;
  77. # gather dependencies of the depndency
  78. my $lib_info = $read_elf->($source_lib);
  79. my $lib_libs = $get_dynamic->($lib_info);
  80. my $libs_resolved = $resolve->($source_lib);
  81. # append gathered dependencies if needed
  82. for my $l (@$lib_libs) {
  83. # $DB::single = 1 if ($l eq 'libwx_baseu_xml-3.2.so.0');
  84. next if exists $processed->{$l};
  85. next if not exists $libs_resolved->{$l};
  86. my $dep_path = $libs_resolved->{$l};
  87. next if $skip->($dep_path) =~ m{/usr/|/lib/};
  88. $resolved->{$l} = $dep_path;
  89. push $all_libs->@*, $l;
  90. }
  91. } else {
  92. say "[error] $lib (from $source_lib): $!";
  93. }
  94. $processed->{$lib} = 1;
  95. }
  96. say "totally copied $copied libs";
  97. =cut