chore: don't hard-code cdk build order (#6207)

* chore: don't hard-code cdk build order

* Use BuildPackage

* packagename grep

* fix rollup globals conflict
This commit is contained in:
Jeremy Elbourn
2017-08-04 14:05:07 -07:00
committed by tinayuangao
parent c6c7908c29
commit f913cc992a
6 changed files with 98 additions and 53 deletions
-13
View File
@@ -1,13 +0,0 @@
{
"extends": "../tsconfig-build",
"files": [
"public_api.ts"
],
"angularCompilerOptions": {
"annotateForClosureCompiler": true,
"strictMetadataEmit": true,
"flatModuleOutFile": "index.js",
"flatModuleId": "@angular/cdk/testing",
"skipTemplateCodegen": true
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
"compilerOptions": {
"experimentalDecorators": true,
"noUnusedParameters": true,
"lib": ["es2015", "dom"],
"lib": ["es2015", "dom", "es2016.array.include"],
"module": "commonjs",
"moduleResolution": "node",
"outDir": "../../dist/tools/gulp",
+13 -9
View File
@@ -2,10 +2,8 @@ import {join} from 'path';
import {main as tsc} from '@angular/tsc-wrapped';
import {buildConfig} from './build-config';
import {getSecondaryEntryPointsForPackage} from './secondary-entry-points';
import {
buildPrimaryEntryPointBundles,
buildSecondaryEntryPointBundles
} from 'material2-build-tools';
import {buildPrimaryEntryPointBundles, buildSecondaryEntryPointBundles} from './build-bundles';
const {packagesDir, outputDir} = buildConfig;
@@ -23,9 +21,6 @@ export class BuildPackage {
/** Path to the package output. */
packageOut: string;
/** Secondary entry points for the package. */
secondaryEntryPoints: string[];
/** Path to the entry file of the package in the output directory. */
private entryFilePath: string;
@@ -35,6 +30,17 @@ export class BuildPackage {
/** Path to the tsconfig file, which will be used to build the tests. */
private tsconfigTests: string;
/** Secondary entry points for the package. */
get secondaryEntryPoints(): string[] {
if (!this._secondaryEntryPoints) {
this._secondaryEntryPoints = getSecondaryEntryPointsForPackage(this);
}
return this._secondaryEntryPoints;
}
private _secondaryEntryPoints: string[];
constructor(public packageName: string, public dependencies: BuildPackage[] = []) {
this.packageRoot = join(packagesDir, packageName);
this.packageOut = join(outputDir, 'packages', packageName);
@@ -43,8 +49,6 @@ export class BuildPackage {
this.tsconfigTests = join(this.packageRoot, testsTsconfigName);
this.entryFilePath = join(this.packageOut, 'index.js');
this.secondaryEntryPoints = getSecondaryEntryPointsForPackage(packageName);
}
/** Compiles the package sources with all secondary entry points. */
+1 -1
View File
@@ -47,7 +47,7 @@ export function composeRelease(buildPackage: BuildPackage) {
function createFilesForSecondaryEntryPoint(buildPackage: BuildPackage, releasePath: string) {
const {packageName, packageOut} = buildPackage;
getSecondaryEntryPointsForPackage(packageName).forEach(entryPointName => {
getSecondaryEntryPointsForPackage(buildPackage).forEach(entryPointName => {
// Create a directory in the root of the package for this entry point that contains
// * A package.json that lists the different bundle locations
// * An index.d.ts file that re-exports the index.d.ts from the typings/ directory
+5 -3
View File
@@ -1,10 +1,12 @@
import {getSecondaryEntryPointsForPackage} from './secondary-entry-points';
import {join} from 'path';
import {getSubdirectoryNames} from './secondary-entry-points';
import {buildConfig} from './build-config';
/** Method that converts dash-case strings to a camel-based string. */
const dashCaseToCamelCase = (str: string) => str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
/** List of available secondary entry-points for the CDK package. */
const cdkSecondaryEntryPoints = getSecondaryEntryPointsForPackage('cdk');
/** List of potential secondary entry-points for the CDK package. */
const cdkSecondaryEntryPoints = getSubdirectoryNames(join(buildConfig.packagesDir, 'cdk'));
/** Object with all CDK entry points in the format of Rollup globals. */
const rollupCdkEntryPoints = cdkSecondaryEntryPoints.reduce((globals: any, entryPoint: string) => {
+78 -26
View File
@@ -1,35 +1,87 @@
/**
* List of cdk entry-points in the order that they must be built. This is necessary because
* some of the entry-points depend on each other. This is temporary until we switch to bazel.
*/
const CDK_ENTRY_POINTS = [
'coercion',
'rxjs',
'keyboard',
'platform',
'bidi',
'table',
'portal',
'observe-content',
'a11y',
];
import {join} from 'path';
import {readdirSync, lstatSync, existsSync} from 'fs';
import {spawnSync} from 'child_process';
import {BuildPackage} from './build-package';
/**
* Gets secondary entry-points for a given package.
* Gets secondary entry-points for a given package in the order they should be built.
*
* This currently assumes that every directory under a package should be an entry-point. This may
* not always be desired, in which case we can add an extra build configuration for specifying the
* entry-points.
* This currently assumes that every directory under a package should be an entry-point except for
* specifically black-listed directories.
*
* @param packageName The package name for which to get entry points, e.g., 'cdk'.
* @param pkg The package for which to get entry points, e.g., 'cdk'.
* @returns An array of secondary entry-points names, e.g., ['a11y', 'bidi', ...]
*/
export function getSecondaryEntryPointsForPackage(packageName: string) {
// For now, we hard-code the fact that only the CDK has secondary entry-points until we switch
// to bazel.
if (packageName === 'cdk') {
return CDK_ENTRY_POINTS;
export function getSecondaryEntryPointsForPackage(pkg: BuildPackage) {
const packageName = pkg.packageName;
const packageDir = pkg.packageRoot;
// Get the list of all entry-points as the list of directories in the package that have a
// tsconfig-build.json
const entryPoints = getSubdirectoryNames(packageDir)
.filter(d => existsSync(join(packageDir, d, 'tsconfig-build.json')));
// Create nodes that comprise the build graph.
const buildNodes: BuildNode[] = entryPoints.map(p => ({name: p, deps: []}));
// Create a lookup for name -> build graph node.
const nodeLookup = buildNodes.reduce((lookup, node) => {
return lookup.set(node.name, node);
}, new Map<string, BuildNode>());
// Regex used to extract entry-point name from an import statement referencing that entry-point.
// E.g., extract "portal" from "from '@angular/cdk/portal';".
const importRegex = new RegExp(`${packageName}/(.+)';`);
// Update the deps for each node to point to the appropriate BuildNodes.
buildNodes.forEach(node => {
// Look for any imports that reference this same umbrella package and get the corresponding
// BuildNode for each by looking at the import statements with grep.
node.deps = spawnSync('egrep', [
'-roh',
'--include', '*.ts',
`from.'@angular/${packageName}/.+';`,
`${packageDir}/${node.name}/`
])
.stdout
.toString()
.split('\n')
.filter(String)
.map(importStatement => importStatement.match(importRegex)![1])
.map(depName => nodeLookup.get(depName)!) || [];
});
// Concatenate the build order for each node into one global build order.
// Duplicates are automatically omitted by getBuildOrder.
return buildNodes.reduce((order: string[], node) => {
return [...order, ...getBuildOrder(node)];
}, []);
}
/** Gets the build order for a given node with DFS. */
function getBuildOrder(node: BuildNode): string[] {
if (node.visited) {
return [];
}
return [];
let buildOrder: string[] = [];
for (const dep of node.deps) {
buildOrder = [...buildOrder, ...getBuildOrder(dep)];
}
node.visited = true;
return [...buildOrder, node.name];
}
/** Gets the names of all subdirectories for a given path. */
export function getSubdirectoryNames(dir: string): string[] {
return readdirSync(dir).filter(f => lstatSync(join(dir, f)).isDirectory());
}
/** A node in the build graph of a package's entry-points. */
interface BuildNode {
name: string;
deps: BuildNode[];
visited?: boolean;
}