build/llvmPackages: support mathlib configuration / mcpuVariant

This commit is contained in:
2025-02-21 11:02:18 +08:00
parent f4c8deda6b
commit 00d57ff13b
3 changed files with 75 additions and 17 deletions

View File

@@ -5,8 +5,10 @@ import path from 'path';
import { buildPackage } from '../build/build.js'; import { buildPackage } from '../build/build.js';
import { randomUUID } from 'crypto'; import { randomUUID } from 'crypto';
import { arch } from 'os'; import { arch } from 'os';
import * as sunway from '../sunway.js';
import chalk from 'chalk';
const args = await yargs(hideBin(process.argv)) const argv = await yargs(hideBin(process.argv))
.version("0.0.0") .version("0.0.0")
.option("src", { .option("src", {
describe: "Source directory to llvm-project", describe: "Source directory to llvm-project",
@@ -21,20 +23,31 @@ const args = await yargs(hideBin(process.argv))
describe: "Install prefix", describe: "Install prefix",
type: "string", type: "string",
}) })
.option("msimd-math", { .option("math-simd", {
describe: "Add -msimd for libpgmath", describe: "Add -msimd for libpgmath",
type: "boolean", type: "boolean",
demandOption: true, demandOption: true,
}) })
.option('mcpu', {
type: 'string',
description: '-mcpu option for compilers',
choices: ['8a', '6b', 'host'],
default: 'host',
})
.help() .help()
.parse(); .parse();
const src = path.resolve(args.src); const src = path.resolve(argv.src);
const build = args.build ?? path.resolve(src, "build"); const build = argv.build ?? path.resolve(src, "build");
const prefix = args.prefix ?? path.resolve(src, "install", randomUUID()); const prefix = argv.prefix ?? path.resolve(src, "install", randomUUID());
const cpuVariant = argv.mcpu === "host" ? sunway.getHostGeneration() : argv.platform as sunway.SunwayGeneration;
console.log(`prefix: ${chalk.red(prefix)}`);
console.log(`mcpu: ${cpuVariant}`);
const packages = llvmPackages({ const packages = llvmPackages({
src: args.src, src: argv.src,
buildDir(packageName) { buildDir(packageName) {
return path.join(build, packageName); return path.join(build, packageName);
}, },
@@ -44,7 +57,8 @@ const packages = llvmPackages({
buildPlatform: { arch: arch() }, buildPlatform: { arch: arch() },
hostPlatform: { arch: arch() }, hostPlatform: { arch: arch() },
}, },
enableLibpgmathSIMD: args['msimd-math'] mathSIMD: argv['math-simd'],
cpuVariant,
}); });
for (const pkg of packages) { for (const pkg of packages) {

View File

@@ -1,9 +1,10 @@
import path from "path"; import path from "path";
import { GeneralVariable, LLVMVariable, command, variable } from "../commands/cmake.js"; import { GeneralVariable, LLVMVariable, buildCompilerFlags, command, variable } from "../commands/cmake.js";
import { PackagePlatform, PackageTask } from "./build.js"; import { PackagePlatform, PackageTask } from "./build.js";
import { promisifySpawn } from "../cli.js"; import { promisifySpawn } from "../cli.js";
import os from "os"; import os from "os";
import { SpawnOptions, spawn } from "child_process"; import { SpawnOptions, spawn } from "child_process";
import * as sunway from '../sunway.js';
export interface LLVMPackageOverrides { export interface LLVMPackageOverrides {
cmakeDefinitionOverrides?: { cmakeDefinitionOverrides?: {
@@ -60,7 +61,9 @@ export interface LLVMPackageOptions {
platform: PackagePlatform; platform: PackagePlatform;
enableLibpgmathSIMD: boolean; mathSIMD: boolean;
cpuVariant: sunway.SunwayGeneration;
}; };
export function llvmPackages({ export function llvmPackages({
@@ -70,7 +73,8 @@ export function llvmPackages({
buildDir, buildDir,
cmakeDefinitionOverrides, cmakeDefinitionOverrides,
spawnOverrides, spawnOverrides,
enableLibpgmathSIMD = false, mathSIMD,
cpuVariant,
}: LLVMPackageOptions & LLVMPackageOverrides): PackageTask[] { }: LLVMPackageOptions & LLVMPackageOverrides): PackageTask[] {
const rm = "rm"; const rm = "rm";
const cmake = "cmake"; const cmake = "cmake";
@@ -107,6 +111,16 @@ export function llvmPackages({
await promisifySpawn(spawn(cmake, ["--build", build, "--target", "install"], spawnOptions)); await promisifySpawn(spawn(cmake, ["--build", build, "--target", "install"], spawnOptions));
}); });
const mcpuFlag = sunway.mcpu(cpuVariant);
// Shared flags for compiling libpgmath & cflang.
// The toolchain of these targets are clang.
const clangCXFlags = [
"-Wno-sign-compare",
mcpuFlag,
];
function mkLLVMPackage(): PackageTask { function mkLLVMPackage(): PackageTask {
const build = buildDir('llvm'); const build = buildDir('llvm');
return { return {
@@ -139,18 +153,19 @@ export function llvmPackages({
await promisifySpawn(spawn(rm, ["-rf", build], spawnOptions)); await promisifySpawn(spawn(rm, ["-rf", build], spawnOptions));
// Flags shared between C and C++ compiler. // Flags shared between C and C++ compiler.
const cxFlags = ["-mlong-double-64"]; const cxFlags = [
if (enableLibpgmathSIMD) { ...clangCXFlags,
cxFlags.push("-msimd"); "-mlong-double-64",
} ...mathSIMD ? ["-msimd"] : [],
];
// Configure libpgmath. // Configure libpgmath.
await promisifySpawn(spawn(cmake, command({ await promisifySpawn(spawn(cmake, command({
definitions: variable({ definitions: variable({
...general, ...general,
...{ ...{
CMAKE_C_FLAGS: cxFlags.join(" "), CMAKE_C_FLAGS: buildCompilerFlags(cxFlags),
CMAKE_CXX_FLAGS: cxFlags.join(" "), CMAKE_CXX_FLAGS: buildCompilerFlags(cxFlags),
CMAKE_C_COMPILER: path.join(installPrefix, "bin", "clang"), CMAKE_C_COMPILER: path.join(installPrefix, "bin", "clang"),
CMAKE_CXX_COMPILER: path.join(installPrefix, "bin", "clang++"), CMAKE_CXX_COMPILER: path.join(installPrefix, "bin", "clang++"),
} as GeneralVariable, } as GeneralVariable,
@@ -172,12 +187,17 @@ export function llvmPackages({
name: "cflang", name: "cflang",
configurePhase: async () => { configurePhase: async () => {
await promisifySpawn(spawn(rm, ["-rf", build], spawnOptions)); await promisifySpawn(spawn(rm, ["-rf", build], spawnOptions));
const cxFlags = [
...clangCXFlags,
];
// Configure cflang. // Configure cflang.
await promisifySpawn(spawn(cmake, command({ await promisifySpawn(spawn(cmake, command({
definitions: variable({ definitions: variable({
...general, ...general,
...{ ...{
CMAKE_C_FLAGS: buildCompilerFlags(cxFlags),
CMAKE_CXX_FLAGS: buildCompilerFlags(cxFlags),
CMAKE_Fortran_FLAGS: buildCompilerFlags([mcpuFlag]),
CMAKE_C_COMPILER: path.join(installPrefix, "bin", "clang"), CMAKE_C_COMPILER: path.join(installPrefix, "bin", "clang"),
CMAKE_CXX_COMPILER: path.join(installPrefix, "bin", "clang++"), CMAKE_CXX_COMPILER: path.join(installPrefix, "bin", "clang++"),
CMAKE_Fortran_COMPILER: path.join(installPrefix, "bin", "flang"), CMAKE_Fortran_COMPILER: path.join(installPrefix, "bin", "flang"),

View File

@@ -130,3 +130,27 @@ export function command(o: CMakeGenerateOptions): string[] {
...optFlag('-C', o.preloadCache), ...optFlag('-C', o.preloadCache),
]; ];
} }
/**
* Escapes a single C compiler flag argument to ensure CMake can parse it correctly.
* Handles spaces and double quotes by wrapping the argument in double quotes and escaping internal double quotes.
*/
function escapeCmakeFlag(arg: string): string {
// Escape internal double quotes as \"
let escaped = arg.replace(/"/g, '\\"');
// If the argument contains spaces or originally has double quotes, wrap it in double quotes
if (escaped.includes(' ') || arg.includes('"')) {
escaped = `"${escaped}"`;
}
return escaped;
}
/**
* Converts an array of strings into a single string suitable for CMAKE_C_FLAGS.
* @param flags The original array of compiler flags, e.g., ["-O2", "-DNAME=Hello World"]
* @returns The escaped string that can be directly passed to CMake
*/
export function buildCompilerFlags(flags: string[]): string {
return flags.map(escapeCmakeFlag).join(' ');
}