After some fiddling I finally found out how to invoke cmake.build properly from within launch.json.
Steps:
#!/bin/bash
if [ $1 == 0 ]
then
printf "Build is OK :-)\n"
exit 0
fi
if [ $1 == 1 ]
then
printf "**** Please build project first. ****\n\n"
exit 1
else
printf "**** Please fix build errors. ****\n\n"
fi
exit 2
{
"label": "Check build",
"type": "shell",
"options": { "statusbar": { "hide" : true } },
"presentation": {
"echo": false,
"focus": false,
"reveal": "never",
"revealProblems": "always" // Use "always" to default to the "problems" window or "never" to default to the "output" window after build.
},
"command" : "someFolder/prelaunch.bash ${command:cmake.build}"
}
add the preLaunchTask to launch.json: "preLaunchTask": "Check build"
change the source code of the extension (main.js in the VS code extensions folder):
/**
* Implementation of `cmake.build`
*/
async build(target_) {
this.m_promise_build = await this.runBuild(target_); // add await to the build function
//return this.m_promise_build; // comment this and add the following line
return JSON.stringify(this.m_promise_build);
}
Is there any chance this modification gets into the releases? Or add an implementation (eg. cmake.prebuild)?
Thank you for the idea. We may not be able to implement it immediately, but we will track the community reactions to determine where this might fit into our backlog.
Can you clarify whether you want to use preLaunchTask, or whether you're using that because you didn't know how to get your program to build otherwise?
There is an example launch.json in our documentation that shows how to do this without a preLaunchTask. https://github.com/microsoft/vscode-cmake-tools/blob/develop/docs/debug-launch.md#debug-using-a-launchjson-file
The cmake.launchTargetPath and cmake.getLaunchTargetPath variable substitutions and their side effects (or lack thereof) are documented here: https://github.com/microsoft/vscode-cmake-tools/blob/develop/docs/cmake-settings.md#command-substitution.
cmake.build wasn't really designed to be used in a task but the way you're using it works. Alternatively, cmake.tasksBuildCommand should give you the cmake command required to build your binary, so if you want a preLaunchTask you could create a shell task that runs ${command:cmake.tasksBuildCommand} as the command (I see this is missing from the substitution documentation).
I updated the documentation with information about cmake.tasksBuildCommand.
@bobbrow is there a way to programmatically (instead of using the GUI as shown here) select CMake's launch target?
@bobbrow,
The reason I want to have preLaunchTask to build the output is to prevent the user from starting a debug-session when the code doesn't compile well (it often leads to confusion when you're debugging different code from the one you're running).
Besides that, the users are using a debugger extension (Cortex-Debug) so starting a built-in debug session is not what they're looking after.
I tried running the ${command:cmake.tasksBuildCommand}, which works well besides one drawback. The command is executed on the Terminal window and missing from the Cmake output window. The Cmake output window has a big advantage as you can < CTRL> click the links of the error definitions to navigate to the problems.
Is there a way to have the taskBuildCommand run in the Cmake output window? An if not, what would be the issue of returning a string on the cmake.build function (or make a separate function for that)?
I finally got it working by creating a .js 'wrapper' which is called from the preLaunchTask directly.
This issue may be closed.
Evaluating ${command:cmake.launchTargetPath} in your launch.json will return null in the event of a build failure which should prevent debugging from starting. I verified this yesterday and it worked as I expected. It does require cmake.buildBeforeRun to be true though (that's the default setting value FWIW).
If you prefer to use ${command:cmake.tasksBuildCommand} in a preLaunchTask you should be able to also add a "problemMatcher" to your task definition which will parse the results out of the terminal output stream and convert errors into problems. VS Code has a number of pre-defined ones. cpptools also adds a $gcc matcher.
Also, I seem to be able to CTL+click on links in the terminal window. It goes to the build errors for me.
@abelfodil, yes there is a way to programmatically invoke a build from another extension.
vscode.commands.executeCommand('cmake.build'); // Build the currently selected target
cmake.build accepts additional parameters if you want to be more specific about which target to build. I'm not sure what your requirements are though, so let me know if you need more detail. You can also take a look at extension.ts line 834 for the command signature.
This is exactly what I did. I noticed it was possible to Ctrl+click the links in the terminal window indeed, however creating a dedicated .js (using the Powertools extension) provided the most flexible solution.
I created a .js file with the following command implementation:
exports.execute = async (args) => {
const vscode = args.require('vscode');
var ret = await vscode.commands.executeCommand('cmake.build');
if (ret == 0) return '';
vscode.commands.executeCommand('workbench.action.problems.focus', 'CMake/Build');
vscode.window.showErrorMessage("Your code didn't built well...\n\nTry some more :-)", { modal: true });
return null;
};
Next, I called this command directly from the preBuildTask.
Sounds good. I'm glad you have a solution that works for you. I'll close this issue now.
Actually @bobbrow I was talking about target selection (and not build)
Oops! Yes you did. 馃槄 Try this instead:
vscode.commands.executeCommand('cmake.selectLaunchTarget', undefined, "targetName");
The first parameter is a vscode.WorkspaceFolder (can be undefined if you want to use the currently "active" folder as context)
The second parameter is the target name