Skip to content
This repository was archived by the owner on Mar 26, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"cwd": "${workspaceFolder:cli}",
"program": "${workspaceFolder:cli}/dist/index.js",
"sourceMaps": true,
"args": ["-d", "/Users/barry/Repos/ibmi-company_system", "--verbose", "-bf", "make"],
"args": ["-d", "/Users/barry/Repos/ibmi-company_system", "--verbose", "-bf", "make", "-f", "qrpglesrc/employees.pgm.sqlrpgle"],
"preLaunchTask": {
"type": "npm",
"script": "webpack:dev"
Expand Down
93 changes: 76 additions & 17 deletions cli/src/builders/make/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'path';
import { ILEObject, ILEObjectTarget, ImpactedObject, ObjectType, Targets } from '../../targets';
import { asPosix, fromCl, getFiles, toCl } from '../../utils';
import { warningOut } from '../../cli';
import { name } from '../../../webpack.config';
import { name, target } from '../../../webpack.config';
import { FolderOptions, getFolderOptions } from './folderSettings';
import { readAllRules } from './customRules';
import { CompileData, CommandParameters, getTrueBasename } from '../environment';
Expand All @@ -20,8 +20,19 @@ interface Step {
command: string;
}

/**
* parents: this property controls the all target. It will include all the parents of partial build objects.
* partial: if this property is true, the makefile will only include targets for the partial build objects (and optionally their parents)
*/
type PartialOptions = { partial: boolean, parents: boolean };

interface PartialTargets {
partial: ILEObject[];
children?: ILEObject[];
}

export class MakeProject {
private noChildren: boolean = false;
private partialOptions: PartialOptions = { partial: false, parents: false };
private settings: iProject = new iProject();
private projectActions: ProjectActions;
private actionsEnabled: boolean = false;
Expand All @@ -32,8 +43,8 @@ export class MakeProject {
this.projectActions = new ProjectActions(this.targets, this.rfs);
}

public setNoChildrenInBuild(noChildren: boolean) {
this.noChildren = noChildren;
public setPartialOptions(options: PartialOptions) {
this.partialOptions = options;
}

public useActions() {
Expand Down Expand Up @@ -188,7 +199,7 @@ export class MakeProject {
``,
...this.generateTargets(specificObjects),
``,
...this.generateGenericRules()
...this.generateGenericRules(specificObjects)
];
}

Expand All @@ -214,30 +225,56 @@ export class MakeProject {
];
}

public generateTargets(partialBuild?: ILEObject[]): string[] {
let lines = [];
/**
* Used to return the objects required to do a partial build.
* If `partial` is true, it will return the object and all objects depending on it recursively.
* If `parents` is true, it will return all parent objects of the partial build objects, and their children/
*/
private getPartialTargets(partialBuild?: ILEObject[]): PartialTargets|undefined {
if (partialBuild === undefined) {
return;
}

// A 'partial build' means we only want to build specific objects
// and we also want to build their parents too. We update `partialBuild`
let allParents: ILEObject[]|undefined;

// we also want to build their parents too. We update `partialBuild`
// to include all the parents of the specific objects.
if (partialBuild) {
if (this.partialOptions.parents) {
allParents = [];
const impacts = partialBuild.map(o => this.targets.getImpactFor(o));

let allAffected: ILEObject[] = [];

const addImpact = (impactedObj: ImpactedObject) => {
if (!allAffected.some(o => o.systemName === impactedObj.ileObject.systemName && o.type === impactedObj.ileObject.type)) {
allAffected.push(impactedObj.ileObject);
if (!allParents.some(o => o.systemName === impactedObj.ileObject.systemName && o.type === impactedObj.ileObject.type)) {
allParents.push(impactedObj.ileObject);
}

impactedObj.children.forEach(child => addImpact(child));
}

impacts.forEach(impact => addImpact(impact));

partialBuild = allAffected;
partialBuild = allParents;
}

let allChildren: ILEObject[]|undefined = this.partialOptions.partial ? this.targets.getRequiredObjects(partialBuild) : undefined;

return {
partial: partialBuild,
children: allChildren
}
}

public generateTargets(partialBuild?: ILEObject[]): string[] {
let lines = [];

// A 'partial build' means we only want to build specific objects
const buildObjects = this.getPartialTargets(partialBuild);

if (buildObjects) {
partialBuild = buildObjects.partial;
}

// If we are in partial mode, we only want to generate targets for the specific objects
const all = partialBuild || [
...(this.targets.binderRequired() ? [this.targets.getBinderTarget()] : []),
...this.targets.getTargetsOfType(`PGM`),
Expand All @@ -251,7 +288,19 @@ export class MakeProject {
)
}

if (!this.noChildren) {
if (buildObjects && buildObjects.children) {
// If we don't want the children to get built, we only generate the targets for the specific objects
for (const obj of buildObjects.children) {
if (obj.reference) continue; // Skip references

const target = this.targets.getTarget(obj);
if (target && target.deps && target.deps.length > 0) {
lines.push(
`$(PREPATH)/${target.systemName}.${target.type}: ${target.deps.filter(d => d.reference !== true).map(dep => `$(PREPATH)/${dep.systemName}.${dep.type}`).join(` `)}`
)
}
}
} else {
// If we don't want the children to get built, we don't generate the dependency targets
for (const target of this.targets.getTargets()) {
if (target && target.deps.length > 0) {
Expand All @@ -275,9 +324,15 @@ export class MakeProject {
return lines;
}

public generateGenericRules(): string[] {
public generateGenericRules(partialBuild?: ILEObject[]): string[] {
let lines = [];

const buildObjects = this.getPartialTargets(partialBuild);

if (buildObjects) {
partialBuild = buildObjects.partial;
}

for (const entry of Object.entries(this.settings.compiles)) {
let [type, data] = entry;

Expand Down Expand Up @@ -320,6 +375,10 @@ export class MakeProject {
if (objects.length > 0) {
for (const ileObject of objects) {
if (ileObject.reference) continue;

if (buildObjects && buildObjects.children && !buildObjects.children.some(o => o.systemName === ileObject.systemName && o.type === ileObject.type)) {
continue; // Skip this object
}

// This is used when your object really has source

Expand Down
6 changes: 3 additions & 3 deletions cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ export let cliSettings = {
withActions: false,
fixIncludes: false,
autoRename: false,
fileList: false,
lookupFiles: [] as string[],
lookupFiles: undefined as string[]|undefined,
userBranch: ``,
makeFileNoChildren: false,
makefileIsPartial: false,
makefileWithParents: false,
assumeSourcesArePrograms: false,
};

Expand Down
33 changes: 25 additions & 8 deletions cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,17 @@ async function main() {

case '-nc':
case '--no-children':
cliSettings.makeFileNoChildren = true;
warningOut(`--no-children is deprecated and is default when doing partial builds.`);
break;

case `-ip`:
case `--is-partial`:
cliSettings.makefileIsPartial = true;
break;

case `-wp`:
case `--with-parents`:
cliSettings.makefileWithParents = true;
break;

case '-ap':
Expand All @@ -79,7 +89,7 @@ async function main() {
case `-f`:
case `--files`:
case `-l`:
cliSettings.fileList = true;
cliSettings.lookupFiles = [];
break;

case `-h`:
Expand Down Expand Up @@ -127,15 +137,19 @@ async function main() {
console.log(``);
console.log(`Options specific to '-bf make':`);
console.log(``);
console.log(`\t-nc`);
console.log(`\t--no-children\tUsed with '-bf make' and won't include children of`);
console.log(`\t\t\tobjects in the makefile. Useful in conjuction with '-f'.`);
console.log(`\t-ip`);
console.log(`\t--is-partial\tWill only generate targets that are needed for`);
console.log(`\t\t\tthe objects that are being built.`);
console.log(``);
console.log(`\t-wp`);
console.log(`\t--with-parents\tUsed with '-bf make' and will add parents of`);
console.log(`\t\t\tobjects being partially built to the makefile.`);
console.log(``);
process.exit(0);
break;

default:
if (cliSettings.fileList) {
if (cliSettings.lookupFiles !== undefined) {
cliSettings.lookupFiles.push(parms[i]);
}
break;
Expand Down Expand Up @@ -232,9 +246,12 @@ async function main() {

await makeProj.setupSettings();

makeProj.setNoChildrenInBuild(cliSettings.makeFileNoChildren);
makeProj.setPartialOptions({
partial: cliSettings.makefileIsPartial,
parents: cliSettings.makefileWithParents
})

let specificObjects: ILEObject[] | undefined = cliSettings.fileList ? cliSettings.lookupFiles.map(f => targets.getResolvedObject(path.join(cwd, f))).filter(o => o) : undefined;
let specificObjects: ILEObject[] | undefined = cliSettings.lookupFiles ? cliSettings.lookupFiles.map(f => targets.getResolvedObject(path.join(cwd, f))).filter(o => o) : undefined;
writeFileSync(path.join(cwd, `makefile`), makeProj.getMakefile(specificObjects).join(`\n`));

break;
Expand Down
Loading
Loading