Skip to content

Commit c9b0d09

Browse files
authored
Added RosPackageFilters & blocklist.json (#891)
On windows workflow use node 18.12.0 inplace of 18.13.0. There is a repeatable issue with node-gyp configuration on node 18.13. It seems to be related to the node cache. Switching to 18.12 avoids using a cached version of node 18 and the issue no longer occurs. Fix #890
1 parent 7fd0ea0 commit c9b0d09

File tree

7 files changed

+162
-42
lines changed

7 files changed

+162
-42
lines changed

.github/workflows/windows-build-and-test-compatibility.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
strategy:
1111
fail-fast: false
1212
matrix:
13-
node-version: [10.X, 12.X, 14.X, 16.11.X, 17.X, 18.X, 19.X]
13+
node-version: [10.X, 12.X, 14.X, 16.11.X, 17.X, 18.12.X, 19.X]
1414
ros_distribution:
1515
# - foxy
1616
- galactic

.github/workflows/windows-build-and-test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
strategy:
2727
fail-fast: false
2828
matrix:
29-
node-version: [10.X, 12.X, 14.X, 16.11.X, 17.X, 18.X, 19.X]
29+
node-version: [10.X, 12.X, 14.X, 16.11.X, 17.X, 18.12.0, 19.X]
3030
steps:
3131
- name: Setup Node.js ${{ matrix.node-version }}
3232
uses: actions/setup-node@v2

rosidl_gen/blocklist.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[
2+
{
3+
"pkgName": "rosbag2_storage_mcap_testdata"
4+
}
5+
]

rosidl_gen/filter.js

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
const os = require('os');
4+
5+
// blocklist.json format
6+
// [
7+
// {
8+
// pkgName: RegExString,
9+
// interfaceName: RegExString,
10+
// os: RegExString
11+
// },
12+
// ...
13+
// ]
14+
//
15+
// examples
16+
// [
17+
// {
18+
// "pkgName": "action*"
19+
// },
20+
// {
21+
// "pkgName": "std_msgs",
22+
// },
23+
// {
24+
// "pkgName": "std_msgs",
25+
// "interfaceName": "String"
26+
// },
27+
// {
28+
// "os": "Linux"
29+
// },
30+
// ]
31+
32+
const RosPackageFilters = {
33+
filters: [],
34+
_loaded: false,
35+
36+
addFilter: function (pkgName, interfaceName, os) {
37+
this.filters.push({
38+
pkgName: pkgName,
39+
interfaceName: interfaceName,
40+
os: os,
41+
});
42+
},
43+
44+
_matches: function (filter, pkgInfo) {
45+
if (filter.os && filter.os.test(os.type())) {
46+
return true;
47+
}
48+
49+
if (filter.pkgName) {
50+
if (filter.pkgName.test(pkgInfo.pkgName)) {
51+
if (!filter.interfaceName) {
52+
return true;
53+
}
54+
} else {
55+
return false;
56+
}
57+
}
58+
59+
if (
60+
filter.interfaceName &&
61+
filter.interfaceName.test(pkgInfo.interfaceName)
62+
) {
63+
return true;
64+
}
65+
66+
return false;
67+
},
68+
69+
load: function (
70+
blocklistPath = path.join(__dirname, '../rosidl_gen/blocklist.json')
71+
) {
72+
this._loaded = true;
73+
74+
if (!fs.existsSync(blocklistPath)) return;
75+
76+
// eslint-disable-next-line
77+
let blocklistData = JSON.parse(fs.readFileSync(blocklistPath, 'utf8'));
78+
79+
let filters = blocklistData.map((pkgFilterData) => {
80+
let filter = {};
81+
if (pkgFilterData['pkgName']) {
82+
filter.pkgName = new RegExp(pkgFilterData.pkgName);
83+
}
84+
if (pkgFilterData['interfaceName']) {
85+
filter.interfaceName = new RegExp(pkgFilterData.interfaceName);
86+
}
87+
if (pkgFilterData['os']) {
88+
filter.os = new RegExp(pkgFilterData.os);
89+
}
90+
return filter;
91+
});
92+
93+
this.filters = filters.filter(
94+
(filter) => !filter.os || filter.os.test(os.type())
95+
);
96+
},
97+
98+
matchesAny: function (pkgInfo) {
99+
if (!this._loaded) this.load();
100+
return this.filters.some((filter) => this._matches(filter, pkgInfo));
101+
},
102+
};
103+
104+
module.exports = RosPackageFilters;

rosidl_gen/index.js

+3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ const installedPackagePaths = process.env.AMENT_PREFIX_PATH.split(
2626

2727
async function generateInPath(path) {
2828
const pkgs = await packages.findPackagesInDirectory(path);
29+
2930
const pkgsInfo = Array.from(pkgs.values());
31+
3032
await Promise.all(
3133
pkgsInfo.map((pkgInfo) => generateJSStructFromIDL(pkgInfo, generatedRoot))
3234
);
@@ -42,6 +44,7 @@ async function generateAll(forcedGenerating) {
4244
path.join(__dirname, 'generator.json'),
4345
path.join(generatedRoot, 'generator.json')
4446
);
47+
4548
await Promise.all(
4649
installedPackagePaths.map((path) => generateInPath(path))
4750
);

rosidl_gen/packages.js

+39-39
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const path = require('path');
2121
const walk = require('walk');
2222
const os = require('os');
2323
const flat = require('array.prototype.flat');
24+
const pkgFilters = require('../rosidl_gen/filter.js');
2425

2526
const fsp = fs.promises;
2627

@@ -140,28 +141,30 @@ async function findAmentPackagesInDirectory(dir) {
140141
pkgs.map((pkg) => getPackageDefinitionsFiles(pkg, dir))
141142
);
142143

143-
// Support flat() methond for nodejs < 11.
144+
// Support flat() method for nodejs < 11.
144145
const rosFiles = Array.prototype.flat ? files.flat() : flat(files);
145146

146147
const pkgMap = new Map();
147148
return new Promise((resolve, reject) => {
148149
rosFiles.forEach((filePath) => {
149-
if (path.extname(filePath) === '.msg') {
150-
// Some .msg files were generated prior to 0.3.2 for .action files,
151-
// which has been disabled. So these files should be ignored here.
152-
if (path.dirname(dir).split(path.sep).pop() !== 'action') {
153-
addInterfaceInfo(
154-
grabInterfaceInfo(filePath, true),
155-
'messages',
156-
pkgMap
157-
);
158-
}
159-
} else if (path.extname(filePath) === '.srv') {
160-
addInterfaceInfo(grabInterfaceInfo(filePath, true), 'services', pkgMap);
161-
} else if (path.extname(filePath) === '.action') {
162-
addInterfaceInfo(grabInterfaceInfo(filePath, true), 'actions', pkgMap);
150+
const interfaceInfo = grabInterfaceInfo(filePath, true);
151+
const ignore = pkgFilters.matchesAny(interfaceInfo);
152+
if (ignore) {
153+
console.log('Omitting filtered interface: ', interfaceInfo);
163154
} else {
164-
// we ignore all other files
155+
if (path.extname(filePath) === '.msg') {
156+
// Some .msg files were generated prior to 0.3.2 for .action files,
157+
// which has been disabled. So these files should be ignored here.
158+
if (path.dirname(dir).split(path.sep).pop() !== 'action') {
159+
addInterfaceInfo(interfaceInfo, 'messages', pkgMap);
160+
}
161+
} else if (path.extname(filePath) === '.srv') {
162+
addInterfaceInfo(interfaceInfo, 'services', pkgMap);
163+
} else if (path.extname(filePath) === '.action') {
164+
addInterfaceInfo(interfaceInfo, 'actions', pkgMap);
165+
} else {
166+
// we ignore all other files
167+
}
165168
}
166169
});
167170
resolve(pkgMap);
@@ -191,30 +194,27 @@ async function findPackagesInDirectory(dir) {
191194
let walker = walk.walk(dir, { followLinks: true });
192195
let pkgMap = new Map();
193196
walker.on('file', (root, file, next) => {
194-
if (path.extname(file.name) === '.msg') {
195-
// Some .msg files were generated prior to 0.3.2 for .action files,
196-
// which has been disabled. So these files should be ignored here.
197-
if (path.dirname(root).split(path.sep).pop() !== 'action') {
198-
addInterfaceInfo(
199-
grabInterfaceInfo(path.join(root, file.name), amentExecuted),
200-
'messages',
201-
pkgMap
202-
);
203-
}
204-
} else if (path.extname(file.name) === '.srv') {
205-
addInterfaceInfo(
206-
grabInterfaceInfo(path.join(root, file.name), amentExecuted),
207-
'services',
208-
pkgMap
209-
);
210-
} else if (path.extname(file.name) === '.action') {
211-
addInterfaceInfo(
212-
grabInterfaceInfo(path.join(root, file.name), amentExecuted),
213-
'actions',
214-
pkgMap
215-
);
197+
const interfaceInfo = grabInterfaceInfo(
198+
path.join(root, file.name),
199+
amentExecuted
200+
);
201+
const ignore = pkgFilters.matchesAny(interfaceInfo);
202+
if (ignore) {
203+
console.log('Omitting filtered interface: ', interfaceInfo);
216204
} else {
217-
// we ignore all other files
205+
if (path.extname(file.name) === '.msg') {
206+
// Some .msg files were generated prior to 0.3.2 for .action files,
207+
// which has been disabled. So these files should be ignored here.
208+
if (path.dirname(root).split(path.sep).pop() !== 'action') {
209+
addInterfaceInfo(interfaceInfo, 'messages', pkgMap);
210+
}
211+
} else if (path.extname(file.name) === '.srv') {
212+
addInterfaceInfo(interfaceInfo, 'services', pkgMap);
213+
} else if (path.extname(file.name) === '.action') {
214+
addInterfaceInfo(interfaceInfo, 'actions', pkgMap);
215+
} else {
216+
// we ignore all other files
217+
}
218218
}
219219
next();
220220
});

rostsd_gen/index.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ declare module "rclnodejs" {
3131
const path = require('path');
3232
const fs = require('fs');
3333
const loader = require('../lib/interface_loader.js');
34+
const pkgFilters = require('../rosidl_gen/filter.js');
3435

3536
async function generateAll() {
3637
// load pkg and interface info (msgs and srvs)
@@ -63,7 +64,14 @@ function getPkgInfos(rootDir) {
6364

6465
for (let filename of files) {
6566
const typeClass = fileName2Typeclass(filename);
66-
if (!typeClass.type) continue;
67+
if (
68+
!typeClass.type ||
69+
pkgFilters.matchesAny({
70+
pkgName: typeClass.package,
71+
interfaceName: typeClass.name,
72+
})
73+
)
74+
continue;
6775

6876
const rosInterface = loader.loadInterface(typeClass);
6977

0 commit comments

Comments
 (0)