176 lines
5.7 KiB
JavaScript
176 lines
5.7 KiB
JavaScript
|
|
|
|
const fs = require("fs");
|
|
const os = require("os");
|
|
const path = require("path");
|
|
const { spawnSync } = require("child_process");
|
|
const args = process.argv.slice(2);
|
|
const THIRDPARTY_DIR = __dirname;
|
|
|
|
function findArg(argname, isBoolean) {
|
|
let prefix = `--${argname}`;
|
|
let idx = args.findIndex(arg => arg == prefix);
|
|
if (idx >= 0) {
|
|
if (isBoolean) return true;
|
|
else return args[idx + 1];
|
|
}
|
|
idx = args.findIndex(arg => arg.startsWith(prefix))
|
|
if (idx >= 0) return args[idx].substring(prefix.length + 1);
|
|
return null;
|
|
}
|
|
|
|
function assert(cond, message) {
|
|
if (!cond) {
|
|
console.error(message);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
const buildOptions = {
|
|
withOpenCV: findArg("with-opencv", true) ?? false,
|
|
buildType: findArg("build-type", false) ?? "Release",
|
|
proxy: findArg("proxy"),
|
|
generator: findArg("generator"),
|
|
}
|
|
|
|
const spawnOption = {
|
|
stdio: "inherit", env: {
|
|
...process.env, ...buildOptions.proxy ? {
|
|
"http_proxy": buildOptions.proxy,
|
|
"https_proxy": buildOptions.proxy,
|
|
} : {}
|
|
}
|
|
};
|
|
|
|
function P(path) { return path.replace(/\\/g, "/"); }
|
|
|
|
function checkFile(...items) {
|
|
return fs.existsSync(path.resolve(...items));
|
|
}
|
|
|
|
function downloadSource(name, repo, branch, recursive, checkedFile) {
|
|
const sourceRootDir = path.join(THIRDPARTY_DIR, "_source");
|
|
fs.mkdirSync(sourceRootDir, { recursive: true });
|
|
const sourceDir = path.join(sourceRootDir, name);
|
|
if (checkFile(sourceDir, checkedFile)) return sourceDir;
|
|
|
|
console.log(`${name}源代码不存在,正在下载...`);
|
|
assert(spawnSync("git", [
|
|
"clone",
|
|
...recursive ? ["--recursive"] : [],
|
|
repo, "-b", branch,
|
|
sourceDir
|
|
], { ...spawnOption }).status == 0, `下载${name}源代码失败`);
|
|
|
|
return sourceDir;
|
|
}
|
|
|
|
function cmakeBuildFromSource(name, repo, branch, downloader, buildArgs, cmakeCreator) {
|
|
const sourceDir = downloader ? downloader(name, repo, branch) : downloadSource(name, repo, branch, false, "CMakeLists.txt");
|
|
const buildDir = path.join(sourceDir, "build", buildOptions.buildType);
|
|
const installDir = path.join(THIRDPARTY_DIR, name, buildOptions.buildType);
|
|
const configFile = path.join(installDir, "config.cmake");
|
|
|
|
if (typeof buildArgs == "function") buildArgs = buildArgs(sourceDir, buildDir, installDir);
|
|
|
|
//编译源代码
|
|
if (checkFile(configFile)) return
|
|
console.log(`${name}目标不存在,正在编译...`);
|
|
fs.rmSync(buildDir, { recursive: true, force: true });
|
|
fs.mkdirSync(buildDir, { recursive: true });
|
|
|
|
assert(spawnSync("cmake", [
|
|
"-G", buildOptions.generator ?? "Ninja", sourceDir,
|
|
"-DCMAKE_BUILD_TYPE=" + buildOptions.buildType,
|
|
"-DCMAKE_INSTALL_PREFIX=" + installDir,
|
|
...(buildArgs ?? []).map(arg => arg.startsWith("-D") ? arg : `-D${arg}`),
|
|
], { ...spawnOption, cwd: buildDir }).status == 0, `配置${name}失败`);
|
|
|
|
assert(spawnSync("cmake", [
|
|
"--build", ".",
|
|
"--parallel", os.cpus().length.toString(),
|
|
"--config", buildOptions.buildType,
|
|
"--target", "install",
|
|
], { ...spawnOption, cwd: buildDir }).status == 0, `编译${name}失败`);
|
|
|
|
fs.writeFileSync(configFile, cmakeCreator(installDir));
|
|
}
|
|
|
|
async function downloadFromURL(name, url, resolver) {
|
|
const cacheDir = path.join(THIRDPARTY_DIR, "_cache");
|
|
fs.mkdirSync(cacheDir, { recursive: true });
|
|
const saveName = path.join(cacheDir, path.basename(url));
|
|
const outputDir = path.join(cacheDir, name);
|
|
fs.rmSync(outputDir, { force: true, recursive: true });
|
|
|
|
if (!checkFile(saveName)) {
|
|
console.log(`开始下载${name}, 地址:${url}`);
|
|
const result = spawnSync("curl", ["-o", saveName + ".cache", "-L", url, "-s", "-w", "%{http_code}"], { ...spawnOption, stdio: "pipe" });
|
|
assert(result.status == 0 && result.stdout.toString() == "200", `下载${name}失败`);
|
|
fs.renameSync(saveName + ".cache", saveName);
|
|
}
|
|
let currentName = saveName;
|
|
|
|
if (saveName.endsWith(".bz2")) {
|
|
currentName = saveName.substring(0, saveName.length - 4);
|
|
const input = fs.createReadStream(saveName);
|
|
const out = fs.createWriteStream(currentName);
|
|
const bz2 = require("unbzip2-stream")();
|
|
await new Promise((resolve, reject) => {
|
|
input.pipe(bz2).pipe(out);
|
|
out.on("close", resolve);
|
|
input.on("error", reject);
|
|
bz2.on("error", reject);
|
|
out.on("error", reject);
|
|
});
|
|
}
|
|
|
|
const format = path.extname(currentName);
|
|
assert([".tar", ".gz", ".tgz", ".zip"].includes(format), "仅支持.tar, .gz, .tgz, .zip格式的压缩文件");
|
|
const method = {
|
|
".tar": require("compressing").tar,
|
|
".gz": require("compressing").gzip,
|
|
".tgz": require("compressing").tgz,
|
|
".zip": require("compressing").zip,
|
|
}[format];
|
|
await method.uncompress(currentName, outputDir);
|
|
|
|
await resolver(outputDir);
|
|
|
|
fs.rmSync(outputDir, { recursive: true, force: true });
|
|
}
|
|
|
|
async function main() {
|
|
//OpenCV
|
|
if (buildOptions.withOpenCV) cmakeBuildFromSource("OpenCV", "https://github.com/opencv/opencv.git", "4.11.0", null, [
|
|
"-DBUILD_SHARED_LIBS=OFF",
|
|
"-DBUILD_opencv_apps=OFF",
|
|
"-DBUILD_opencv_js=OFF",
|
|
"-DBUILD_opencv_python2=OFF",
|
|
"-DBUILD_opencv_python3=OFF",
|
|
"-DBUILD_ANDROID_PROJECTS=OFF",
|
|
"-DBUILD_ANDROID_EXAMPLES=OFF",
|
|
"-DBUILD_TESTS=OFF",
|
|
"-DBUILD_FAT_JAVA_LIB=OFF",
|
|
"-DBUILD_ANDROID_SERVICE=OFF",
|
|
"-DBUILD_JAVA=OFF",
|
|
"-DBUILD_PERF_TESTS=OFF",
|
|
"-DBUILD_TIFF=ON",
|
|
"-DBUILD_OPENJPEG=ON",
|
|
"-DBUILD_JPEG=ON",
|
|
"-DBUILD_PNG=ON",
|
|
"-DBUILD_WEBP=ON",
|
|
], (root) => [
|
|
`set(OpenCV_STATIC ON)`,
|
|
os.platform() == "win32" ?
|
|
`include(${JSON.stringify(P(path.join(root, "OpenCVConfig.cmake")))})` :
|
|
`include(${JSON.stringify(P(path.join(root, "lib/cmake/opencv4/OpenCVConfig.cmake")))})`,
|
|
`set(OpenCV_INCLUDE_DIR \${OpenCV_INCLUDE_DIRS})`,
|
|
os.platform() == "win32" ?
|
|
"set(OpenCV_LIB_DIR ${OpenCV_LIB_PATH})" :
|
|
`set(OpenCV_LIB_DIR ${JSON.stringify(P(path.join(root, "lib")))})`,
|
|
// `set(OpenCV_LIBS OpenCV_LIBS)`,
|
|
].join("\n"));
|
|
}
|
|
|
|
main(); |