1 module gccbuild.cleanup; 2 3 import scriptlike, gccbuild, painlessjson, std.json; 4 5 void cleanupToolchain(Duration totalTime) 6 { 7 startSection("Finalizing toolchain"); 8 9 removeFolders(); 10 stripTargetLibraries(); 11 stripHostBinaries(); 12 13 if (build.cleanup.matchesBuildType && !build.cleanup.commands.empty) 14 { 15 writeBulletPoint("Executing custom cleanup commands"); 16 auto oldCWD = pushCWD(toolchainDir); 17 runBuildCommands(build.cleanup.commands); 18 endBulletPoint(); 19 } 20 21 writeBulletPoint("Writing GCC information"); 22 auto info = GCCInfo(build.target, build.host, build.multilibs); 23 auto json = info.toJSON(); 24 writeFile(toolchainDir ~ "gcc_info.json", toJSON(&json, true)); 25 endBulletPoint(); 26 27 endSectionLog(); 28 writelnLog(); 29 writelnLog("Total execution time: ", totalTime); 30 closeLog(); 31 32 writeBulletPoint("Compressing log file"); 33 runCollectLog("xz -9 " ~ logFilePath.toString()); 34 runCollectLog( 35 "mv " ~ (logFilePath.toString() ~ ".xz") ~ " " ~ (toolchainDir ~ "build.log.xz").toString()); 36 endBulletPoint(); 37 38 endSection(false); 39 } 40 41 struct GCCInfo 42 { 43 string target, host; 44 MultilibEntry[] multilibs; 45 } 46 47 void removeFolders() 48 { 49 writeBulletPoint("Removing unnecessary folders"); 50 if ((build.cleanup.matchesBuildType && !build.cleanup.remove.empty) 51 || (build.variantCleanup && !build.variantCleanup.remove.empty)) 52 { 53 if (build.cleanup.matchesBuildType) 54 { 55 foreach (entry; build.cleanup.remove) 56 { 57 tryRmdirRecurse(toolchainDir ~ entry.substituteVars); 58 } 59 } 60 if (build.variantCleanup) 61 { 62 foreach (entry; build.variantCleanup.remove) 63 { 64 tryRmdirRecurse(toolchainDir ~ entry.substituteVars); 65 } 66 } 67 } 68 else 69 { 70 tryRmdirRecurse(sysrootDirWithPrefix ~ "bin"); 71 tryRmdirRecurse(sysrootDirWithPrefix ~ "libexec"); 72 tryRmdirRecurse(sysrootDirWithPrefix ~ "sbin"); 73 tryRmdirRecurse(sysrootDirWithPrefix ~ "etc"); 74 tryRmdirRecurse(sysrootDirWithPrefix ~ "var"); 75 tryRmdirRecurse(sysrootDirWithPrefix ~ "share"); 76 tryRmdirRecurse(sysrootDir ~ "bin"); 77 tryRmdirRecurse(sysrootDir ~ "libexec"); 78 tryRmdirRecurse(sysrootDir ~ "sbin"); 79 tryRmdirRecurse(sysrootDir ~ "etc"); 80 tryRmdirRecurse(sysrootDir ~ "var"); 81 tryRmdirRecurse(sysrootDir ~ "share"); 82 tryRmdirRecurse(toolchainDir ~ "etc"); 83 tryRmdirRecurse(toolchainDir ~ "var"); 84 tryRmdirRecurse(toolchainDir ~ "share"); 85 } 86 endBulletPoint(); 87 } 88 89 void stripTargetLibraries() 90 { 91 if (skipStripLibraries) 92 { 93 writeBulletPoint("Stripping target libraries... (skipped)"); 94 return; 95 } 96 writeBulletPoint("Stripping target libraries..."); 97 98 auto oldPath = updatePathVar(binDir); 99 100 if ((build.cleanup.matchesBuildType && !build.cleanup.stripTarget.empty) 101 || (build.variantCleanup && !build.variantCleanup.stripTarget.empty)) 102 { 103 if (build.cleanup.matchesBuildType) 104 { 105 foreach (entry; build.cleanup.stripTarget) 106 { 107 stripPath(toolchainDir ~ entry.substituteVars, targetStrip); 108 } 109 } 110 if (build.variantCleanup) 111 { 112 foreach (entry; build.variantCleanup.stripTarget) 113 { 114 stripPath(toolchainDir ~ entry.substituteVars, targetStrip); 115 } 116 } 117 } 118 else 119 { 120 foreach (multilib; build.multilibs) 121 { 122 auto path = sysrootDirWithPrefix ~ Path("lib") ~ Path(multilib.osFolder); 123 auto path2 = toolchainDir ~ Path(build.target) ~ Path("lib") ~ Path(multilib.osFolder); 124 auto path3 = toolchainDir ~ Path("lib") ~ Path(multilib.osFolder); 125 auto path4 = toolchainDir ~ Path("lib"); 126 stripPath(path, targetStrip); 127 stripPath(path2, targetStrip); 128 stripPath(path3, targetStrip); 129 stripPath(path4, targetStrip); 130 } 131 } 132 restorePathVar(oldPath); 133 endBulletPoint(); 134 } 135 136 void stripHostBinaries() 137 { 138 if (skipStripBinaries) 139 { 140 writeBulletPoint("Stripping host binaries... (skipped)"); 141 return; 142 } 143 writeBulletPoint("Stripping host binaries..."); 144 145 if ((build.cleanup.matchesBuildType && !build.cleanup.stripHost.empty) 146 || (build.variantCleanup && !build.variantCleanup.stripHost.empty)) 147 { 148 if (build.cleanup.matchesBuildType) 149 { 150 foreach (entry; build.cleanup.stripHost) 151 { 152 stripPath(toolchainDir ~ entry.substituteVars, hostStrip, true, false); 153 } 154 } 155 if (build.variantCleanup) 156 { 157 foreach (entry; build.variantCleanup.stripHost) 158 { 159 stripPath(toolchainDir ~ entry.substituteVars, hostStrip, true, false); 160 } 161 } 162 } 163 else 164 { 165 auto path = toolchainDir ~ "bin"; 166 auto path2 = toolchainDir ~ Path(build.target) ~ "bin"; 167 auto path3 = toolchainDir ~ "libexec"; 168 auto path4 = toolchainDir ~ Path(build.target) ~ "libexec"; 169 stripPath(path, hostStrip, true, false); 170 stripPath(path2, hostStrip, true, false); 171 stripPath(path3, hostStrip, true, true); 172 stripPath(path4, hostStrip, true, true); 173 } 174 endBulletPoint(); 175 } 176 177 void stripPath(Path path, string stripProgram, bool stripExes = false, bool stripLibs = true) 178 { 179 yapFunc(stripProgram, " ", path); 180 if (!path.exists || !path.isDir) 181 return; 182 183 foreach (entry; path.dirEntries(SpanMode.depth)) 184 { 185 if (!entry.isFile) 186 continue; 187 if (stripLibs && (entry.extension == ".so" || entry.extension == ".dll" 188 || entry.extension == ".a" || entry.extension == ".lib")) 189 { 190 // Skip linker script files (libc.so) 191 if (!runCollectLog("file -b " ~ entry).canFind("ASCII")) 192 { 193 tryRunCollectLog(stripProgram ~ " --strip-debug " ~ entry); 194 } 195 } 196 else if (stripExes && (entry.extension == ".exe" 197 || runCollectLog("file -b " ~ entry).canFind("executable"))) 198 { 199 tryRunCollectLog(stripProgram ~ " --strip-debug " ~ entry); 200 } 201 } 202 }