Added a new script to scan standalone plugin dependencies at archive

time to make sure they aren't referencing anything external.
This commit is contained in:
Casey Langen 2022-02-17 21:39:45 -08:00
parent 433283a6fa
commit 1b2a4627c3
3 changed files with 140 additions and 0 deletions

5
script/.prettierrc Normal file
View File

@ -0,0 +1,5 @@
{
"tabWidth": 2,
"useTabs": false,
"singleQuote": true
}

View File

@ -90,6 +90,15 @@ cp bin/locales/*.json $OUTDIR/locales
cp bin/themes/*.json $OUTDIR/themes cp bin/themes/*.json $OUTDIR/themes
cp -rfp bin/share/terminfo/* $OUTDIR/share/terminfo/ cp -rfp bin/share/terminfo/* $OUTDIR/share/terminfo/
if [[ $CROSSCOMPILE == "rpi" ]]; then
printf "\n\n\n ***** CROSSCOMPILE DETECTED, **NOT** SCANNING DEPENDENCIES! *****\n\n\n"
sleep 1
else
printf "\n\n\n ***** SCANNING DEPENDENCIES *****\n\n\n"
sleep 1
node ./script/scan-standalone dist/$VERSION/$OUTNAME || exit $?
fi
strip $OUTDIR/musikcube strip $OUTDIR/musikcube
strip $OUTDIR/musikcubed strip $OUTDIR/musikcubed
strip $OUTDIR/libmusikcore.${DLL_EXT} strip $OUTDIR/libmusikcore.${DLL_EXT}

126
script/scan-standalone.js Normal file
View File

@ -0,0 +1,126 @@
const { promisify } = require('util');
const exec = promisify(require('child_process').exec);
const readdir = promisify(require('fs').readdir);
const mac = process.platform === 'darwin';
const filetype = mac ? '.dylib' : '.so';
/* these libraries will always have dynamic dependencies, so ignore */
const ignoredLibraries = mac ? new Set([]) : new Set([]);
/* we assume these dependencies will always be available on the user's
target machine. */
const validLibraries = mac
? new Set([
'/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit',
'/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices',
'/System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox',
'/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon',
'/System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio',
'/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation',
'/System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics',
'/System/Library/Frameworks/CoreMedia.framework/Versions/A/CoreMedia',
'/System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo',
'/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation',
'/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration',
'/usr/lib/libc++.1.dylib',
'/usr/lib/libobjc.A.dylib',
'/usr/lib/libSystem.B.dylib',
'/usr/lib/libz.1.dylib',
])
: new Set([
'/lib64/ld-linux-x86-64.so.2',
'libc.so.6',
'libdl.so.2',
'libgcc_s.so.1',
'libm.so.6',
'libstdc++.so.6',
'libz.so.1',
'linux-vdso.so.1',
]);
let errors = 0;
const path = process.argv[2];
if (!path) {
console.log('\n\nusage: node scan-standalone.js <path>\n\n');
process.exit(1);
}
const ls = async (leaf) => {
const output = await readdir(`${path}/${leaf}`);
const files = output
.filter((fn) => fn.indexOf(filetype) !== -1)
.filter((fn) => !ignoredLibraries.has(fn));
return files;
};
const lddLinux = async (fn) => {
const output = await exec(`ldd ${path}/${fn}`);
const problems = output.stdout
.split('\n')
.map((line) => line.trim())
/* libraries resolved properly will exist in the current path; exclude */
.filter((line) => !!line && line.indexOf(path) === -1)
.filter((line) => line !== 'statically linked')
/* libraries are formatted as "<name> [=> <path>] <(offset)>". if there's
a fat arrow, just grab everything to the left of it. then, if there's
still an offset, strip that as well */
.map((line) => line.split(' => ')[0].split(' ')[0].trim())
.filter((line) => !validLibraries.has(line));
return problems;
};
const lddMac = async (fn) => {
const output = await exec(`otool -L ${path}/${fn}`);
const problems = output.stdout
.split('\n')
.map((line) => line.trim())
/* we want all of the libraries we compile ourself to be prefixed
with the value `@rpath/`. */
.filter((line) => !!line && line.indexOf('@rpath/') === -1)
/* the first line of output is the path to the library, exclude it */
.slice(1)
/* libraries are formatted as "<name> (compatibility ...)", so split
and take the name */
.map((line) => line.split(' (compatibility')[0].trim())
.filter((line) => !validLibraries.has(line));
return problems;
};
const ldd = async (fn) => {
const problems = mac ? await lddMac(fn) : await lddLinux(fn);
if (!problems.length) {
console.log(`${fn}: ok`);
} else {
console.error(`${fn}: potential problems found`);
problems.forEach((line) => console.error(` * ${line}`));
++errors;
}
};
const lddDir = async (leaf) => {
const files = await ls(leaf);
await Promise.allSettled(files.map((fn) => ldd(`${leaf}/${fn}`)));
};
const main = async () => {
await ldd('musikcube');
await ldd('musikcubed');
await ldd(`libmusikcore${filetype}`);
await lddDir('plugins');
await lddDir('lib');
if (errors) {
console.log(
`\n\n\n ***** ${errors} problematic files detected! ***** \n\n\n`
);
process.exit(1);
}
console.log('\neverything looks good!\n');
};
main();