@specs-feup/clava
Version:
A C/C++ source-to-source compiler written in Typescript
183 lines (150 loc) • 4.61 kB
text/typescript
import Io from "@specs-feup/lara/api/lara/Io.js";
import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.js";
import { JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.js";
import Clava from "../Clava.js";
import CMakerUtils from "./CMakerUtils.js";
/**
* Contains CMaker sources
*/
export default class CMakerSources {
untaggedSources = [];
taggedSources: Record<string, string[]> = {};
tags: Set<string> = new Set();
disableWeaving: boolean;
constructor(disableWeaving: boolean = false) {
this.disableWeaving = disableWeaving;
}
private static VARIABLE_UNTAGGED_SOURCES = "CMAKER_SOURCES";
private static VARIABLE_EXTERNAL_SOURCES = "EXTERNAL_SOURCES";
/**
*
*/
copy() {
const newCMakerSources = new CMakerSources();
newCMakerSources.untaggedSources = this.untaggedSources.slice();
newCMakerSources.taggedSources = structuredClone(this.taggedSources);
newCMakerSources.tags = structuredClone(this.tags);
newCMakerSources.disableWeaving = this.disableWeaving;
return newCMakerSources;
}
/**
* Adds the given sources.
*
* @param paths - Array with paths to sources
*/
addSources(paths: string[]) {
for (const path of paths) {
this.addSourcePrivate(this.untaggedSources, path);
}
}
/**
* Add the given sources.
*/
addSource(path: string) {
this.addSourcePrivate(this.untaggedSources, path);
}
/**
* Adds the given sources associated to a tag.
*/
addTaggedSources(tag: string, paths: string[]) {
// Get current tagged sources
let sources = this.taggedSources[tag];
// If not defined, initialize it
if (sources === undefined) {
sources = [];
this.taggedSources[tag] = sources;
this.tags.add(tag);
}
for (const path of paths) {
this.addSourcePrivate(sources, path);
}
}
private addSourcePrivate(sources: string[], path: string | JavaClasses.File) {
const parsedPath = CMakerUtils.parsePath(path);
sources.push(`"${parsedPath}"`);
}
/**
* @returns An array with the CMake variables that have source files
*/
getSourceVariables() {
const sources = [];
if (this.untaggedSources.length > 0) {
sources.push(CMakerSources.VARIABLE_UNTAGGED_SOURCES);
}
if (!this.disableWeaving) {
if (Clava.getProgram().extraSources.length > 0) {
sources.push(CMakerSources.VARIABLE_EXTERNAL_SOURCES);
}
}
for (const tag of this.tags.values()) {
sources.push(tag);
}
return sources;
}
private parseSourcePath(path: string | JavaClasses.File) {
return `"${CMakerUtils.parsePath(path)}"`;
}
/**
* @returns String with the CMake code that declares the current sources
*/
getCode() {
let code = "";
// Add untagged sources
if (this.untaggedSources.length > 0) {
code += this.getCodeSource(
CMakerSources.VARIABLE_UNTAGGED_SOURCES,
this.untaggedSources
);
}
// Add external sources if weaving is not disabled
if (!this.disableWeaving) {
code = this.addExternalSources(code);
}
for (const tag of this.tags.values()) {
const tagCode = this.getCodeSource(tag, this.taggedSources[tag]);
if (code.length !== 0) {
code += "\n";
}
code += tagCode;
}
return code;
}
private addExternalSources(code: string) {
const extraSources = Clava.getProgram().extraSources;
const extraSourcesArray = [];
for (const extraSource of extraSources) {
debug(`Adding external source '${extraSource}'`);
if (Io.isFile(extraSource)) {
extraSourcesArray.push(this.parseSourcePath(extraSource));
} else if (Io.isFolder(extraSource)) {
for (const sourcePath of Io.getPaths(extraSource)) {
extraSourcesArray.push(this.parseSourcePath(sourcePath));
}
} else {
console.log(`[CMAKER] Extra source ' ${extraSource} ' does not exist`);
}
}
if (extraSourcesArray.length > 0) {
if (code.length !== 0) {
code += "\n";
}
code += this.getCodeSource(
CMakerSources.VARIABLE_EXTERNAL_SOURCES,
extraSourcesArray
);
}
return code;
}
/**
* @returns String with the CMake code for a given source name and values
*/
private getCodeSource(sourceName: string, values: string[]) {
const prefix = `set (${sourceName} `;
// Build space
let space = "";
for (let i = 0; i < prefix.length; i++) {
space += " ";
}
return prefix + values.join("\n" + space) + "\n)";
}
}