about summary refs log tree commit diff
path: root/nixpkgs/pkgs/tools/security/jadx/default.nix
blob: a1fbd44b02320ccd6395d2de5e9c3a0e672d4eed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
{ lib
, stdenv
, fetchFromGitHub
, gradle
, jdk
, quark-engine
, makeWrapper
, perl
, imagemagick
, makeDesktopItem
, copyDesktopItems
, desktopToDarwinBundle
}:

let
  pname = "jadx";
  version = "1.4.7";

  src = fetchFromGitHub {
    owner = "skylot";
    repo = pname;
    rev = "v${version}";
    hash = "sha256-3t2e3WfH/ohkdGWlfV3t9oHJ1Q6YM6nSLOgmzgJEkls=";
  };

  deps = stdenv.mkDerivation {
    name = "${pname}-deps";
    inherit src;

    nativeBuildInputs = [ gradle jdk perl ];

    buildPhase = ''
      export GRADLE_USER_HOME=$(mktemp -d)
      export JADX_VERSION=${version}
      gradle --no-daemon jar

      # Apparently, Gradle won't cache the `compileOnlyApi` dependency
      # `org.jetbrains:annotations:22.0.0` which is defined in
      # `io.github.skylot:raung-common`. To make it available in the
      # output, we patch `build.gradle` and run Gradle again.
      substituteInPlace build.gradle \
        --replace 'org.jetbrains:annotations:23.0.0' 'org.jetbrains:annotations:22.0.0'
      gradle --no-daemon jar
    '';

    # Mavenize dependency paths
    # e.g. org.codehaus.groovy/groovy/2.4.0/{hash}/groovy-2.4.0.jar -> org/codehaus/groovy/groovy/2.4.0/groovy-2.4.0.jar
    installPhase = ''
      find $GRADLE_USER_HOME/caches/modules-2 -type f -regex '.*\.\(jar\|pom\)' \
        | perl -pe 's#(.*/([^/]+)/([^/]+)/([^/]+)/[0-9a-f]{30,40}/([^/\s]+))$# ($x = $2) =~ tr|\.|/|; "install -Dm444 $1 \$out/$x/$3/$4/$5" #e' \
        | sh

      # Work around okio-2.10.0 bug, fixed in 3.0. Remove "-jvm" from filename.
      # https://github.com/square/okio/issues/954
      mv $out/com/squareup/okio/okio/2.10.0/okio{-jvm,}-2.10.0.jar
    '';

    outputHashMode = "recursive";
    outputHash = "sha256-QebPRmfLtXy4ZlyKeGC5XNzhMTsYI0X36My+nTFvQpM=";
  };
in stdenv.mkDerivation (finalAttrs: {
  inherit pname version src;

  nativeBuildInputs = [ gradle jdk imagemagick makeWrapper copyDesktopItems ]
    ++ lib.optionals stdenv.hostPlatform.isDarwin [ desktopToDarwinBundle ];

  # Otherwise, Gradle fails with `java.net.SocketException: Operation not permitted`
  __darwinAllowLocalNetworking = true;

  buildPhase = ''
    # The installDist Gradle build phase tries to copy some dependency .jar
    # files multiple times into the build directory. This ends up failing when
    # the dependencies are read directly from the Nix store since they are not
    # marked as chmod +w. To work around this, get a local copy of the
    # dependency store, and give write permissions.
    depsDir=$(mktemp -d)
    cp -R ${deps}/* $depsDir
    chmod -R u+w $depsDir

    gradleInit=$(mktemp)
    cat >$gradleInit <<EOF
      gradle.projectsLoaded {
        rootProject.allprojects {
          buildscript {
            repositories {
              clear()
              maven { url '$depsDir' }
            }
          }
          repositories {
            clear()
            maven { url '$depsDir' }
          }
        }
      }

      settingsEvaluated { settings ->
        settings.pluginManagement {
          repositories {
            maven { url '$depsDir' }
          }
        }
      }
    EOF

    export GRADLE_USER_HOME=$(mktemp -d)
    export JADX_VERSION=${version}
    gradle --offline --no-daemon --info --init-script $gradleInit pack
  '';

  installPhase = ''
    runHook preInstall

    mkdir $out $out/bin
    cp -R build/jadx/lib $out
    for prog in jadx jadx-gui; do
      cp build/jadx/bin/$prog $out/bin
      wrapProgram $out/bin/$prog \
        --set JAVA_HOME ${jdk.home} \
        --prefix PATH : "${lib.makeBinPath [ quark-engine ]}"
    done

    for size in 16 32 48; do
      install -Dm444 \
        jadx-gui/src/main/resources/logos/jadx-logo-"$size"px.png \
        $out/share/icons/hicolor/"$size"x"$size"/apps/jadx.png
    done
    for size in 64 128 256; do
      mkdir -p $out/share/icons/hicolor/"$size"x"$size"/apps
      convert -resize "$size"x"$size" jadx-gui/src/main/resources/logos/jadx-logo.png $out/share/icons/hicolor/"$size"x"$size"/apps/jadx.png
    done

    runHook postInstall
  '';

  desktopItems = [
    (makeDesktopItem {
      name = "jadx";
      desktopName = "JADX";
      exec = "jadx-gui";
      icon = "jadx";
      comment = finalAttrs.meta.description;
      categories = [ "Development" "Utility" ];
    })
  ];

  meta = with lib; {
    description = "Dex to Java decompiler";
    longDescription = ''
      Command line and GUI tools for produce Java source code from Android Dex
      and Apk files.
    '';
    sourceProvenance = with sourceTypes; [
      fromSource
      binaryBytecode  # deps
    ];
    license = licenses.asl20;
    platforms = platforms.unix;
    maintainers = with maintainers; [ delroth emilytrau ];
  };
})