Skip to content

Commit fe62f42

Browse files
Teo Koon PengMinggang Wang
authored andcommitted
find ros packages from ament index (#746)
When in a path that has ament executed, use the ament index to obtain a list of ros definition files instead of recursively scanning the directory. This improves the message generation speed, on my pc, i get old find packages ``` real 0m6.069s user 0m13.387s sys 0m3.757s ``` using ament index ``` real 0m2.189s user 0m13.449s sys 0m3.722s ``` Fix #747
1 parent cc4289c commit fe62f42

File tree

1 file changed

+97
-1
lines changed

1 file changed

+97
-1
lines changed

rosidl_gen/packages.js

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@
1616

1717
const debug = require('debug')('rosidl_gen:packages');
1818
const fs = require('fs');
19+
const readline = require('readline');
1920
const path = require('path');
2021
const walk = require('walk');
2122
const os = require('os');
2223

24+
const fsp = fs.promises;
25+
2326
const generatedRoot = path.join(__dirname, '../generated/');
2427

2528
function getPackageName(filePath, amentExecuted) {
@@ -70,6 +73,96 @@ function addInterfaceInfo(info, type, pkgMap) {
7073
pkg[type].push(info);
7174
}
7275

76+
/**
77+
* Gets all ament packages with ros messages in an ament index.
78+
* @param {string} rootDir Path to the ament root directory
79+
* @returns {string[]} array of package names
80+
*/
81+
async function getAmentPackages(rootDir) {
82+
try {
83+
const files = await fsp.readdir(
84+
path.join(
85+
rootDir,
86+
'share',
87+
'ament_index',
88+
'resource_index',
89+
'rosidl_interfaces'
90+
)
91+
);
92+
return files;
93+
} catch (e) {
94+
if (!e.code === 'ENOENT') {
95+
throw e;
96+
}
97+
return [];
98+
}
99+
}
100+
101+
/**
102+
* Get paths to all rosidl resources in an ament package
103+
* @param {string} packageName name of the package
104+
* @param {string} amentRoot ament root directory
105+
* @returns {string[]} array of rosidl ament resources in a package
106+
*/
107+
async function getPackageDefinitionsFiles(packageName, amentRoot) {
108+
const rosFiles = [];
109+
const rl = readline.createInterface(
110+
fs.createReadStream(
111+
path.join(
112+
amentRoot,
113+
'share',
114+
'ament_index',
115+
'resource_index',
116+
'rosidl_interfaces',
117+
packageName
118+
),
119+
{ emitClose: true }
120+
)
121+
);
122+
rl.on('line', (line) => {
123+
rosFiles.push(path.join(amentRoot, 'share', packageName, line));
124+
});
125+
await new Promise((res) => {
126+
rl.on('close', res);
127+
});
128+
return rosFiles;
129+
}
130+
131+
/**
132+
* Collects all packages in a directory by using the ament index.
133+
* @param {string} dir - the directory to search in
134+
* @return {Promise<Map<string, object>>} A mapping from the package name to some info about it.
135+
*/
136+
async function findAmentPackagesInDirectory(dir) {
137+
const pkgs = await getAmentPackages(dir);
138+
const rosFiles = (
139+
await Promise.all(pkgs.map((pkg) => getPackageDefinitionsFiles(pkg, dir)))
140+
).flat();
141+
const pkgMap = new Map();
142+
return new Promise((resolve, reject) => {
143+
rosFiles.forEach((filePath) => {
144+
if (path.extname(filePath) === '.msg') {
145+
// Some .msg files were generated prior to 0.3.2 for .action files,
146+
// which has been disabled. So these files should be ignored here.
147+
if (path.dirname(dir).split(path.sep).pop() !== 'action') {
148+
addInterfaceInfo(
149+
grabInterfaceInfo(filePath, true),
150+
'messages',
151+
pkgMap
152+
);
153+
}
154+
} else if (path.extname(filePath) === '.srv') {
155+
addInterfaceInfo(grabInterfaceInfo(filePath, true), 'services', pkgMap);
156+
} else if (path.extname(filePath) === '.action') {
157+
addInterfaceInfo(grabInterfaceInfo(filePath, true), 'actions', pkgMap);
158+
} else {
159+
// we ignore all other files
160+
}
161+
});
162+
resolve(pkgMap);
163+
});
164+
}
165+
73166
/**
74167
* Collects all packages in a directory.
75168
* @param {string} dir - the directory to search in
@@ -85,7 +178,10 @@ async function findPackagesInDirectory(dir) {
85178
if (err) {
86179
amentExecuted = false;
87180
}
88-
dir = amentExecuted ? path.join(dir, 'share') : dir;
181+
182+
if (amentExecuted) {
183+
return resolve(findAmentPackagesInDirectory(dir));
184+
}
89185

90186
let walker = walk.walk(dir, { followLinks: true });
91187
let pkgMap = new Map();

0 commit comments

Comments
 (0)