parent
bcaa07b0ac
commit
d9a0a8ff3e
@ -172,6 +172,7 @@ def _ng_package_impl(ctx):
|
|||||||
|
|
||||||
packager_inputs = (
|
packager_inputs = (
|
||||||
ctx.files.srcs +
|
ctx.files.srcs +
|
||||||
|
ctx.files.data +
|
||||||
esm5_sources.to_list() +
|
esm5_sources.to_list() +
|
||||||
depset(transitive = [d.typescript.transitive_declarations
|
depset(transitive = [d.typescript.transitive_declarations
|
||||||
for d in ctx.attr.deps
|
for d in ctx.attr.deps
|
||||||
@ -186,6 +187,7 @@ def _ng_package_impl(ctx):
|
|||||||
packager_args.add(npm_package_directory.path)
|
packager_args.add(npm_package_directory.path)
|
||||||
packager_args.add(ctx.label.package)
|
packager_args.add(ctx.label.package)
|
||||||
packager_args.add([ctx.bin_dir.path, ctx.label.package], join_with="/")
|
packager_args.add([ctx.bin_dir.path, ctx.label.package], join_with="/")
|
||||||
|
packager_args.add([ctx.genfiles_dir.path, ctx.label.package], join_with="/")
|
||||||
|
|
||||||
# Marshal the metadata into a JSON string so we can parse the data structure
|
# Marshal the metadata into a JSON string so we can parse the data structure
|
||||||
# in the TypeScript program easily.
|
# in the TypeScript program easily.
|
||||||
@ -213,6 +215,9 @@ def _ng_package_impl(ctx):
|
|||||||
packager_args.add(_flatten_paths(bundles), join_with=",")
|
packager_args.add(_flatten_paths(bundles), join_with=",")
|
||||||
packager_args.add([s.path for s in ctx.files.srcs], join_with=",")
|
packager_args.add([s.path for s in ctx.files.srcs], join_with=",")
|
||||||
|
|
||||||
|
# TODO: figure out a better way to gather runfiles providers from the transitive closure.
|
||||||
|
packager_args.add([d.path for d in ctx.files.data], join_with=",")
|
||||||
|
|
||||||
if ctx.file.license_banner:
|
if ctx.file.license_banner:
|
||||||
packager_inputs.append(ctx.file.license_banner)
|
packager_inputs.append(ctx.file.license_banner)
|
||||||
packager_args.add(ctx.file.license_banner.path)
|
packager_args.add(ctx.file.license_banner.path)
|
||||||
@ -246,6 +251,10 @@ NG_PACKAGE_ATTRS = dict(NPM_PACKAGE_ATTRS, **dict(ROLLUP_ATTRS, **{
|
|||||||
esm5_outputs_aspect,
|
esm5_outputs_aspect,
|
||||||
sources_aspect,
|
sources_aspect,
|
||||||
]),
|
]),
|
||||||
|
"data": attr.label_list(
|
||||||
|
doc = "Additional, non-Angular files to be added to the package, e.g. global CSS assets.",
|
||||||
|
allow_files = True,
|
||||||
|
),
|
||||||
"include_devmode_srcs": attr.bool(default = False),
|
"include_devmode_srcs": attr.bool(default = False),
|
||||||
"readme_md": attr.label(allow_single_file = FileType([".md"])),
|
"readme_md": attr.label(allow_single_file = FileType([".md"])),
|
||||||
"globals": attr.string_dict(default={}),
|
"globals": attr.string_dict(default={}),
|
||||||
|
@ -14,6 +14,9 @@ function main(args: string[]): number {
|
|||||||
// Exit immediately when encountering an error.
|
// Exit immediately when encountering an error.
|
||||||
shx.set('-e');
|
shx.set('-e');
|
||||||
|
|
||||||
|
// Keep track of whether an error has occured so that we can return an appropriate exit code.
|
||||||
|
let errorHasOccured = false;
|
||||||
|
|
||||||
// This utility expects all of its arguments to be specified in a params file generated by
|
// This utility expects all of its arguments to be specified in a params file generated by
|
||||||
// bazel (see https://docs.bazel.build/versions/master/skylark/lib/Args.html#use_param_file).
|
// bazel (see https://docs.bazel.build/versions/master/skylark/lib/Args.html#use_param_file).
|
||||||
const paramFilePath = args[0];
|
const paramFilePath = args[0];
|
||||||
@ -35,6 +38,9 @@ function main(args: string[]): number {
|
|||||||
// This is the intended output location for package artifacts.
|
// This is the intended output location for package artifacts.
|
||||||
binDir,
|
binDir,
|
||||||
|
|
||||||
|
// The bazel-genfiles dir joined with the srcDir (e.g. 'bazel-bin/package.common').
|
||||||
|
genfilesDir,
|
||||||
|
|
||||||
// JSON data mapping each entry point to the generated bundle index and
|
// JSON data mapping each entry point to the generated bundle index and
|
||||||
// flat module metadata, for example
|
// flat module metadata, for example
|
||||||
// {"@angular/core": {
|
// {"@angular/core": {
|
||||||
@ -67,6 +73,9 @@ function main(args: string[]): number {
|
|||||||
// List of all files in the ng_package rule's srcs.
|
// List of all files in the ng_package rule's srcs.
|
||||||
srcsArg,
|
srcsArg,
|
||||||
|
|
||||||
|
// List of all files in the ng_package rule's data.
|
||||||
|
dataArg,
|
||||||
|
|
||||||
// Path to the package's LICENSE.
|
// Path to the package's LICENSE.
|
||||||
licenseFile,
|
licenseFile,
|
||||||
] = params;
|
] = params;
|
||||||
@ -77,6 +86,7 @@ function main(args: string[]): number {
|
|||||||
const esm5 = esm5Arg.split(',').filter(s => !!s);
|
const esm5 = esm5Arg.split(',').filter(s => !!s);
|
||||||
const bundles = bundlesArg.split(',').filter(s => !!s);
|
const bundles = bundlesArg.split(',').filter(s => !!s);
|
||||||
const srcs = srcsArg.split(',').filter(s => !!s);
|
const srcs = srcsArg.split(',').filter(s => !!s);
|
||||||
|
const dataFiles: string[] = dataArg.split(',').filter(s => !!s);
|
||||||
const modulesManifest = JSON.parse(modulesManifestArg);
|
const modulesManifest = JSON.parse(modulesManifestArg);
|
||||||
|
|
||||||
if (readmeMd) {
|
if (readmeMd) {
|
||||||
@ -84,31 +94,39 @@ function main(args: string[]): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Relativize the path where the file is written.
|
* Writes a file into the package based on its input path, relativizing to the package path.
|
||||||
* @param f a path relative to the srcDir, typically from a file in the srcs[]
|
* @param inputPath Path to the file in the input tree.
|
||||||
* @param c content of the file
|
* @param fileContent Content of the file.
|
||||||
*/
|
*/
|
||||||
function writeSrcFile(f: string, c: string) {
|
function writeFileFromInputPath(inputPath: string, fileContent: string) {
|
||||||
mkDirWriteFile(path.join(out, path.relative(srcDir, f)), c);
|
// We want the relative path from the given file to its ancestor "root" directory.
|
||||||
|
// This root depends on whether the file lives in the source tree (srcDir) as a basic file
|
||||||
|
// input to ng_package, the bin output tree (binDir) as the output of another rule, or
|
||||||
|
// the genfiles output tree (genfilesDir) as the output of a genrule.
|
||||||
|
let rootDir: string;
|
||||||
|
if (inputPath.includes(binDir)) {
|
||||||
|
rootDir = binDir;
|
||||||
|
} else if (inputPath.includes(genfilesDir)) {
|
||||||
|
rootDir = genfilesDir;
|
||||||
|
} else {
|
||||||
|
rootDir = srcDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
const outputPath = path.join(out, path.relative(rootDir, inputPath));
|
||||||
|
|
||||||
|
// Always ensure that the target directory exists.
|
||||||
|
shx.mkdir('-p', path.dirname(outputPath));
|
||||||
|
fs.writeFileSync(outputPath, fileContent, 'utf-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Relativize the path where the file is written.
|
* Copies a file into the package based on its input path, relativizing to the package path.
|
||||||
* @param f a path relative to the binDir, typically from a file in the deps[]
|
* @param inputPath a path relative to the binDir, typically from a file in the deps[]
|
||||||
* @param c content of the file
|
|
||||||
*/
|
*/
|
||||||
function writeBinFile(f: string, c: string) {
|
function copyFileFromInputPath(inputPath: string) {
|
||||||
const outputPath = path.join(out, path.relative(binDir, f));
|
writeFileFromInputPath(inputPath, fs.readFileSync(inputPath, 'utf-8'));
|
||||||
mkDirWriteFile(outputPath, c);
|
|
||||||
return outputPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy the file, relativizing the path.
|
|
||||||
* @param f a path relative to the binDir, typically from a file in the deps[]
|
|
||||||
*/
|
|
||||||
function copyBinFile(f: string) { writeBinFile(f, fs.readFileSync(f, 'utf-8')); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Relativize the path where a file is written.
|
* Relativize the path where a file is written.
|
||||||
* @param file a path containing a re-rooted segment like .esm5 or .es6
|
* @param file a path containing a re-rooted segment like .esm5 or .es6
|
||||||
@ -135,9 +153,13 @@ function main(args: string[]): number {
|
|||||||
const content = fs.readFileSync(f, 'utf-8')
|
const content = fs.readFileSync(f, 'utf-8')
|
||||||
// Strip the named AMD module for compatibility with non-bazel users
|
// Strip the named AMD module for compatibility with non-bazel users
|
||||||
.replace(/^\/\/\/ <amd-module name=.*\/>\n/, '');
|
.replace(/^\/\/\/ <amd-module name=.*\/>\n/, '');
|
||||||
const outputPath = writeBinFile(f, content);
|
writeFileFromInputPath(f, content);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Copy all `data` files into the package. These are files that aren't built by the ng_package
|
||||||
|
// rule, but instead are just straight copied into the package, e.g. global CSS assets.
|
||||||
|
dataFiles.forEach(f => copyFileFromInputPath(f));
|
||||||
|
|
||||||
// Iterate through the entry point modules
|
// Iterate through the entry point modules
|
||||||
// We do this first because we also record new paths for the esm5 and esm2015 copies
|
// We do this first because we also record new paths for the esm5 and esm2015 copies
|
||||||
// of the index JS file, which we need to amend the package.json.
|
// of the index JS file, which we need to amend the package.json.
|
||||||
@ -149,11 +171,11 @@ function main(args: string[]): number {
|
|||||||
moduleFiles['esm5_index'] = path.join(binDir, 'esm5', relative);
|
moduleFiles['esm5_index'] = path.join(binDir, 'esm5', relative);
|
||||||
moduleFiles['esm2015_index'] = path.join(binDir, 'esm2015', relative);
|
moduleFiles['esm2015_index'] = path.join(binDir, 'esm2015', relative);
|
||||||
|
|
||||||
writeBinFile(moduleFiles['esm5_index'], indexContent);
|
writeFileFromInputPath(moduleFiles['esm5_index'], indexContent);
|
||||||
writeBinFile(moduleFiles['esm2015_index'], indexContent);
|
writeFileFromInputPath(moduleFiles['esm2015_index'], indexContent);
|
||||||
|
|
||||||
copyBinFile(moduleFiles['typings']);
|
copyFileFromInputPath(moduleFiles['typings']);
|
||||||
copyBinFile(moduleFiles['metadata']);
|
copyFileFromInputPath(moduleFiles['metadata']);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Root package name (e.g. '@angular/common'), captures as we iterate through sources below.
|
// Root package name (e.g. '@angular/common'), captures as we iterate through sources below.
|
||||||
@ -161,6 +183,13 @@ function main(args: string[]): number {
|
|||||||
const packagesWithExistingPackageJson = new Set<string>();
|
const packagesWithExistingPackageJson = new Set<string>();
|
||||||
|
|
||||||
for (const src of srcs) {
|
for (const src of srcs) {
|
||||||
|
if (src.includes(binDir) || src.includes(genfilesDir)) {
|
||||||
|
errorHasOccured = true;
|
||||||
|
console.error(
|
||||||
|
'The "srcs" for ng_package should not include output of other rules. Found:\n' +
|
||||||
|
` ${src}`);
|
||||||
|
}
|
||||||
|
|
||||||
let content = fs.readFileSync(src, 'utf-8');
|
let content = fs.readFileSync(src, 'utf-8');
|
||||||
// Modify package.json files as necessary for publishing
|
// Modify package.json files as necessary for publishing
|
||||||
if (path.basename(src) === 'package.json') {
|
if (path.basename(src) === 'package.json') {
|
||||||
@ -177,7 +206,7 @@ function main(args: string[]): number {
|
|||||||
rootPackageName = packageJson['name'];
|
rootPackageName = packageJson['name'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeSrcFile(src, content);
|
writeFileFromInputPath(src, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
const licenseBanner = licenseFile ? fs.readFileSync(licenseFile, 'utf-8') : '';
|
const licenseBanner = licenseFile ? fs.readFileSync(licenseFile, 'utf-8') : '';
|
||||||
@ -196,7 +225,7 @@ function main(args: string[]): number {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return 0;
|
return errorHasOccured ? 1 : 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a binDir-relative path to srcDir-relative
|
* Convert a binDir-relative path to srcDir-relative
|
||||||
@ -216,11 +245,6 @@ function main(args: string[]): number {
|
|||||||
!f.endsWith(`.ngsummary${ext}`);
|
!f.endsWith(`.ngsummary${ext}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mkDirWriteFile(p: string, content: string) {
|
|
||||||
shx.mkdir('-p', path.dirname(p));
|
|
||||||
fs.writeFileSync(p, content, 'utf-8');
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyFile(file: string, baseDir: string, relative = '.') {
|
function copyFile(file: string, baseDir: string, relative = '.') {
|
||||||
const dir = path.join(baseDir, relative);
|
const dir = path.join(baseDir, relative);
|
||||||
shx.mkdir('-p', dir);
|
shx.mkdir('-p', dir);
|
||||||
@ -240,6 +264,7 @@ function main(args: string[]): number {
|
|||||||
* Inserts or edits properties into the package.json file(s) in the package so that
|
* Inserts or edits properties into the package.json file(s) in the package so that
|
||||||
* they point to all the right generated artifacts.
|
* they point to all the right generated artifacts.
|
||||||
*
|
*
|
||||||
|
* @param packageJson The path to the package.json file.
|
||||||
* @param parsedPackage Parsed package.json content
|
* @param parsedPackage Parsed package.json content
|
||||||
*/
|
*/
|
||||||
function amendPackageJson(packageJson: string, parsedPackage: {[key: string]: string}) {
|
function amendPackageJson(packageJson: string, parsedPackage: {[key: string]: string}) {
|
||||||
@ -298,13 +323,13 @@ function main(args: string[]): number {
|
|||||||
/** Creates metadata re-export file for a secondary entry-point. */
|
/** Creates metadata re-export file for a secondary entry-point. */
|
||||||
function createMetadataReexportFile(entryPointName: string, metadataFile: string) {
|
function createMetadataReexportFile(entryPointName: string, metadataFile: string) {
|
||||||
const inputPath = path.join(srcDir, `${entryPointName}.metadata.json`);
|
const inputPath = path.join(srcDir, `${entryPointName}.metadata.json`);
|
||||||
writeSrcFile(inputPath, JSON.stringify({
|
writeFileFromInputPath(inputPath, JSON.stringify({
|
||||||
'__symbolic': 'module',
|
'__symbolic': 'module',
|
||||||
'version': 3,
|
'version': 3,
|
||||||
'metadata': {},
|
'metadata': {},
|
||||||
'exports':
|
'exports':
|
||||||
[{'from': `${srcDirRelative(inputPath, metadataFile.replace(/.metadata.json$/, ''))}`}],
|
[{'from': `${srcDirRelative(inputPath, metadataFile.replace(/.metadata.json$/, ''))}`}],
|
||||||
'flatModuleIndexRedirect': true
|
'flatModuleIndexRedirect': true,
|
||||||
}) + '\n');
|
}) + '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,18 +342,19 @@ function main(args: string[]): number {
|
|||||||
const content = `${license}
|
const content = `${license}
|
||||||
export * from '${srcDirRelative(inputPath, typingsFile.replace(/\.d\.tsx?$/, ''))}';
|
export * from '${srcDirRelative(inputPath, typingsFile.replace(/\.d\.tsx?$/, ''))}';
|
||||||
`;
|
`;
|
||||||
writeSrcFile(inputPath, content);
|
writeFileFromInputPath(inputPath, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a package.json for a secondary entry-point.
|
* Creates a package.json for a secondary entry-point.
|
||||||
|
* @param dir The directory under which the package.json should be written.
|
||||||
* @param entryPointPackageName The full package name for the entry point,
|
* @param entryPointPackageName The full package name for the entry point,
|
||||||
* e.g. '@angular/common/http'.
|
* e.g. '@angular/common/http'.
|
||||||
*/
|
*/
|
||||||
function createEntryPointPackageJson(dir: string, entryPointPackageName: string) {
|
function createEntryPointPackageJson(dir: string, entryPointPackageName: string) {
|
||||||
const pkgJson = path.join(srcDir, dir, 'package.json');
|
const pkgJson = path.join(srcDir, dir, 'package.json');
|
||||||
const content = amendPackageJson(pkgJson, {name: entryPointPackageName});
|
const content = amendPackageJson(pkgJson, {name: entryPointPackageName});
|
||||||
writeSrcFile(pkgJson, content);
|
writeFileFromInputPath(pkgJson, content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,9 +15,31 @@ ng_package(
|
|||||||
"package.json",
|
"package.json",
|
||||||
"some-file.txt",
|
"some-file.txt",
|
||||||
],
|
],
|
||||||
|
data = [
|
||||||
|
":arbitrary_bin_file",
|
||||||
|
":arbitrary_genfiles_file",
|
||||||
|
":extra-styles.css",
|
||||||
|
],
|
||||||
entry_point = "packages/bazel/test/ng_package/example/index.js",
|
entry_point = "packages/bazel/test/ng_package/example/index.js",
|
||||||
deps = [
|
deps = [
|
||||||
":example",
|
":example",
|
||||||
"//packages/bazel/test/ng_package/example/secondary",
|
"//packages/bazel/test/ng_package/example/secondary",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Use a genrule to create a file in bazel-genfiles to ensure that the genfiles output of
|
||||||
|
# a rule can be passed through to the `data` of ng_package.
|
||||||
|
genrule(
|
||||||
|
name = "arbitrary_genfiles_file",
|
||||||
|
outs = ["arbitrary_genfiles.txt"],
|
||||||
|
cmd = "echo Hello > $@",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Use a genrule to create a file in bazel-bin to ensure that the bin output of
|
||||||
|
# a rule can be passed through to the `data` of ng_package.
|
||||||
|
genrule(
|
||||||
|
name = "arbitrary_bin_file",
|
||||||
|
outs = ["arbitrary_bin.txt"],
|
||||||
|
cmd = "echo World > $@",
|
||||||
|
output_to_bindir = True,
|
||||||
|
)
|
||||||
|
3
packages/bazel/test/ng_package/example/extra-styles.css
Normal file
3
packages/bazel/test/ng_package/example/extra-styles.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.special {
|
||||||
|
color: goldenrod;
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
arbitrary_bin.txt
|
||||||
|
arbitrary_genfiles.txt
|
||||||
bundles
|
bundles
|
||||||
bundles/example-secondary.umd.js
|
bundles/example-secondary.umd.js
|
||||||
bundles/example-secondary.umd.js.map
|
bundles/example-secondary.umd.js.map
|
||||||
@ -43,6 +45,7 @@ esm5
|
|||||||
esm5/secondary/secondarymodule.ngsummary.js
|
esm5/secondary/secondarymodule.ngsummary.js
|
||||||
example_public_index.d.ts
|
example_public_index.d.ts
|
||||||
example_public_index.metadata.json
|
example_public_index.metadata.json
|
||||||
|
extra-styles.css
|
||||||
fesm2015
|
fesm2015
|
||||||
fesm2015/example.js
|
fesm2015/example.js
|
||||||
fesm2015/example.js.map
|
fesm2015/example.js.map
|
||||||
@ -65,6 +68,16 @@ secondary
|
|||||||
secondary.d.ts
|
secondary.d.ts
|
||||||
secondary.metadata.json
|
secondary.metadata.json
|
||||||
some-file.txt
|
some-file.txt
|
||||||
|
--- arbitrary_bin.txt ---
|
||||||
|
|
||||||
|
World
|
||||||
|
|
||||||
|
|
||||||
|
--- arbitrary_genfiles.txt ---
|
||||||
|
|
||||||
|
Hello
|
||||||
|
|
||||||
|
|
||||||
--- bundles/example-secondary.umd.js ---
|
--- bundles/example-secondary.umd.js ---
|
||||||
|
|
||||||
(function (global, factory) {
|
(function (global, factory) {
|
||||||
@ -661,6 +674,13 @@ export * from './index';
|
|||||||
|
|
||||||
{"__symbolic":"module","version":4,"metadata":{"MyModule":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"NgModule","line":11,"character":1},"arguments":[{}]}],"members":{}}},"origins":{"MyModule":"./mymodule"},"importAs":"example"}
|
{"__symbolic":"module","version":4,"metadata":{"MyModule":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"NgModule","line":11,"character":1},"arguments":[{}]}],"members":{}}},"origins":{"MyModule":"./mymodule"},"importAs":"example"}
|
||||||
|
|
||||||
|
--- extra-styles.css ---
|
||||||
|
|
||||||
|
.special {
|
||||||
|
color: goldenrod;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
--- fesm2015/example.js ---
|
--- fesm2015/example.js ---
|
||||||
|
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user