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 { randomUUID } from 'crypto';
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")
.option("src", {
describe: "Source directory to llvm-project",
@@ -21,20 +23,31 @@ const args = await yargs(hideBin(process.argv))
describe: "Install prefix",
type: "string",
})
.option("msimd-math", {
.option("math-simd", {
describe: "Add -msimd for libpgmath",
type: "boolean",
demandOption: true,
})
.option('mcpu', {
type: 'string',
description: '-mcpu option for compilers',
choices: ['8a', '6b', 'host'],
default: 'host',
})
.help()
.parse();
const src = path.resolve(args.src);
const build = args.build ?? path.resolve(src, "build");
const prefix = args.prefix ?? path.resolve(src, "install", randomUUID());
const src = path.resolve(argv.src);
const build = argv.build ?? path.resolve(src, "build");
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({
src: args.src,
src: argv.src,
buildDir(packageName) {
return path.join(build, packageName);
},
@@ -44,7 +57,8 @@ const packages = llvmPackages({
buildPlatform: { arch: arch() },
hostPlatform: { arch: arch() },
},
enableLibpgmathSIMD: args['msimd-math']
mathSIMD: argv['math-simd'],
cpuVariant,
});
for (const pkg of packages) {

View File

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

View File

@@ -130,3 +130,27 @@ export function command(o: CMakeGenerateOptions): string[] {
...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(' ');
}