Skip to content

Added API to manually run CMake - #1483

Open
DangMinhTam382 wants to merge 4 commits into
eclipse-cdt:mainfrom
DangMinhTam382:CMakeConfigurationWork
Open

Added API to manually run CMake#1483
DangMinhTam382 wants to merge 4 commits into
eclipse-cdt:mainfrom
DangMinhTam382:CMakeConfigurationWork

Conversation

@DangMinhTam382

Copy link
Copy Markdown
Contributor

Allows ISV to manually run CMake without having to build the project.
Moved code to separate method and make a convenience protected for the derived to call.

@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown

Test Results

4 719 tests  ±0   4 710 ✅ ±0   2m 42s ⏱️ +9s
  183 suites ±0       9 💤 ±0 
  183 files   ±0       0 ❌ ±0 

Results for commit 6314dbd. ± Comparison against base commit 90d1dd3.

♻️ This comment has been updated with latest results.

@DangMinhTam382

Copy link
Copy Markdown
Contributor Author

Hi Mr. @betamaxbandit ,
CC: Mr. @Kummallinen ,

Before making this PR official, could you take a quick look and let me know what you think?

FYI, it built failed due to the removal of IMG_DLCL_COPY_VIEW_TO_CLIPBOARD in IInternalDebugUIConstants.class.
Fix for this build should be included in #1485

Thanks.

@DangMinhTam382
DangMinhTam382 force-pushed the CMakeConfigurationWork branch from db124ca to 6b81f27 Compare June 25, 2026 10:56
@betamaxbandit

Copy link
Copy Markdown
Contributor

Hi Mr. @betamaxbandit , CC: Mr. @Kummallinen ,

Before making this PR official, could you take a quick look and let me know what you think?

Hi @DangMinhTam382 ,
Thanks for this. I've started reviewing this, but need some more time. I'll probably finish the review tomorrow (Fr).
Cheers John

Allows ISV to manually run CMake without having to build the project.
Moved code to separate method and make a convenience protected for the
derived to call.
@DangMinhTam382
DangMinhTam382 force-pushed the CMakeConfigurationWork branch from 6b81f27 to f70ef1b Compare July 20, 2026 10:14
@DangMinhTam382

Copy link
Copy Markdown
Contributor Author

Hi Mr. @betamaxbandit ,

I have made some modification to allow manual testing for this PR.
This is now ready to be review now!

Many thanks,
Tam.

@betamaxbandit betamaxbandit left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just a few minor grammar issues.


### 9) CMake configuration

Verifies that API for configuring CMake could work individually.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verifies that the API for configuring CMake can be invoked independently.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion! I updated the README.md file

### 9) CMake configuration

Verifies that API for configuring CMake could work individually.
Note, API could only be test in Developer environment with plug-in **org.eclipse.cdt.cmake.example** included.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this API can only be tested in a CDT development environment that includes the org.eclipse.cdt.cmake.example plug-in.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion! I updated the README.md file

Comment on lines +49 to +52
1. Remove existing "**/build/**" folder.
2. Right click project > select "Configure CMake Project".

Expected: CMake Configuration process start with active launch settings.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Remove any existing **/build/** folder.
  2. Right-click the project and select Configure CMake Project.

Expected: The CMake configuration process starts using the active launch settings.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion! I updated the README.md file

@jld01
jld01 marked this pull request as ready for review July 21, 2026 13:43
/**
* @since 2.1
*/
protected IStatus configureCMakeBuildFiles(IProgressMonitor monitor) throws CoreException, IOException {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This helper now refreshes and processes compile_commands.json, but build() continues to do the existing compile_commands.json refresh/processing immediately afterwards. So a normal build that needs to run CMake appears to parse compile_commands.json twice.

Could we split this into two helpers, e.g. one method that only runs the CMake configure command and another that refreshes/processes compile_commands.json? Then build() can keep its existing single compile_commands.json processing step, while the public configure-only API can call both helpers.
Something like ...

private IStatus runCMakeConfigure(CommandDescriptorBuilder cmdBuilder, IConsole console,
		ConsoleOutputStream infoStream, IProgressMonitor monitor)
		throws CoreException, IOException {
	// run CMake only
}

private void refreshAndProcessCompileCommandsFile(IConsole console, IProgressMonitor monitor)
		throws CoreException {
	getCompileCommandsFile().refreshLocal(IResource.DEPTH_ZERO, monitor);
	processCompileCommandsFile(console, monitor);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, you're right there!
It does parse compile_commands.json file twice.

Code updated as your suggestion!

*/
protected IStatus configureCMakeBuildFiles(IProgressMonitor monitor) throws CoreException, IOException {
IProject project = getProject();
project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think the configure-only API should delete all CDT problem markers. A manual CMake configure does not run the compiler, so clearing previous compiler diagnostics could hide real errors even though no build has replaced them.

The private helper already clears CMake execution markers via deleteCMakeErrorMarkers(getProject()), which seems appropriate. I suggest removing this broader ICModelMarker.C_MODEL_PROBLEM_MARKER deletion from the configure-only API and leaving broad marker cleanup to the full build path only.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed!
Code updated, no longer remove ICModelMarker.C_MODEL_PROBLEM_MARKER when only configure CMake

String arg0 = command.getArguments().get(0);
if (p == null) {
// process start failed
String msg = String.format(Messages.CMakeBuildConfiguration_Failure, ""); //$NON-NLS-1$

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this message is now returned to callers as an IStatus, it would be useful to include the command that failed to start. Could this use arg0 instead of the empty string?
something like ...

String msg = String.format(Messages.CMakeBuildConfiguration_Failure, arg0);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had some thought on this one.

Since the condition is checking for process starting error, instead of using arg0, the message is updated to
Failure running cmake: Process failed to start

Error related to arg0 with be check/log in the next condition

			if (exitValue != 0) {
				// cmake had errors...
				String msg = String.format(Messages.CMakeBuildConfiguration_ExitFailure, arg0, exitValue);
				addMarker(srcFolder.getProject(), -1, msg, IMarkerGenerator.SEVERITY_ERROR_BUILD, null);
				return Status.error(msg);
			}

WDT?


/**
* @since 2.1
*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a good comment seeing as this is going to be API.
Something like ...

/**
 * Runs the CMake configure step for this build configuration without invoking
 * the build target. On success, refreshes and processes compile_commands.json
 * so scanner information is updated.
 * <p>
 * This method writes to the CDT build console, deletes stale CMake execution
 * markers, may create new CMake execution markers, and updates scanner
 * information for this build configuration. Callers should run this from a
 * background workspace operation, not directly from the UI thread.
 *
 * @param monitor progress monitor, or {@code null}
 * @return {@link Status#OK_STATUS} if CMake completed successfully; otherwise
 *         an error status if the CMake process could not be started or exited
 *         non-zero
 * @throws CoreException if workspace refresh, marker handling, or scanner-info
 *         processing fails
 * @throws IOException if console/process I/O fails
 * @since 2.1
 */
public IStatus configureCMakeBuildFiles(IProgressMonitor monitor)
		throws CoreException, IOException {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhh, thanks your suggestion.
That's a big help for me.

addMarker(srcFolder.getProject(), -1, msg, IMarkerGenerator.SEVERITY_ERROR_BUILD, null);
return null;
}
IStatus result = configureCMakeBuildFiles(cmdBuilder, console, infoStream, monitor);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This helper now refreshes and processes compile_commands.json, but build() continues to do the existing compile_commands.json refresh/processing immediately afterwards. So a normal build that needs to run CMake appears to parse compile_commands.json twice.

Could we split this into two helpers, e.g. one method that only runs the CMake configure command and another that refreshes/processes compile_commands.json? Then build() can keep its existing single compile_commands.json processing step, while the public configure-only API can call both helpers.

Something like ...

private IStatus runCMakeConfigure(CommandDescriptorBuilder cmdBuilder, IConsole console,
		ConsoleOutputStream infoStream, IProgressMonitor monitor)
		throws CoreException, IOException {
	// run CMake only
}

private void refreshAndProcessCompileCommandsFile(IConsole console, IProgressMonitor monitor)
		throws CoreException {
	getCompileCommandsFile().refreshLocal(IResource.DEPTH_ZERO, monitor);
	processCompileCommandsFile(console, monitor);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, you're right there!
It does parse compile_commands.json file twice.

Code updated as your suggestion!

ILog.of(ConfigureExtendedCMakeProjectHandler.class)
.error("Failed to configure for extended CMake Project", e); //$NON-NLS-1$
}
return null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runInWorkspace should return an IStatus. Returning null after logging the exception is risky and means the Jobs framework does not receive a proper failure status.

Could this return the CoreException status, or an error status for IOException?

Something like ...

} catch (CoreException e) {
	return e.getStatus();
} catch (IOException e) {
	ILog.of(ConfigureExtendedCMakeProjectHandler.class)
			.error("Failed to configure for extended CMake Project", e); //$NON-NLS-1$
	return Status.error("Failed to configure for extended CMake Project", e); //$NON-NLS-1$
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, thanks for pointing this out and the suggestion as well.

I believe the WorkspaceJob does log the error if an error status is return.
So, I grouped them together and return a simple
Status.error(message, exception)

WDT?

return null;
}
};
job.schedule();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This job modifies project state: markers, resource refresh, and scanner information. Should it set a scheduling rule before scheduling, probably the project, to avoid running concurrently with other workspace operations on the same project?
Suggestion ...

job.setRule(project);
job.schedule();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm with you on this one.

I'm not quite sure if there's another WS job running during CMake configuration process, so I'll play it safe here and set rule to it as suggested.

point="org.eclipse.ui.commands">
<command
id="org.eclipse.cdt.cmake.example.configureCMakeProject"
name="Configure Extended CMake Project">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The menu label says "Configure CMake Project" but the command name says "Configure Extended CMake Project". Could these be made consistent? Unless "Extended" has a specific meaning here, I suggest using "Configure CMake Project" in both places.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes, the initial intent was to allow CMake configuration only for Extended CMake projects.
Later, this was changed to support all CMake projects, and these spots were somehow missed.

Updated the UI and class names to align with the current behavior.

@betamaxbandit betamaxbandit left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,
this is looking really good.
There's a few minor issues that should be resolved please.

@DangMinhTam382
DangMinhTam382 force-pushed the CMakeConfigurationWork branch from a8aa06f to 6314dbd Compare July 22, 2026 09:00

@DangMinhTam382 DangMinhTam382 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Mr. @betamaxbandit ,

I fixed your comments and this should be ready to be reviewed again

Many thanks,
Tam


/**
* @since 2.1
*/

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhh, thanks your suggestion.
That's a big help for me.

addMarker(srcFolder.getProject(), -1, msg, IMarkerGenerator.SEVERITY_ERROR_BUILD, null);
return null;
}
IStatus result = configureCMakeBuildFiles(cmdBuilder, console, infoStream, monitor);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, you're right there!
It does parse compile_commands.json file twice.

Code updated as your suggestion!

return null;
}
};
job.schedule();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm with you on this one.

I'm not quite sure if there's another WS job running during CMake configuration process, so I'll play it safe here and set rule to it as suggested.


### 9) CMake configuration

Verifies that API for configuring CMake could work individually.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion! I updated the README.md file

Comment on lines +49 to +52
1. Remove existing "**/build/**" folder.
2. Right click project > select "Configure CMake Project".

Expected: CMake Configuration process start with active launch settings.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion! I updated the README.md file

*/
protected IStatus configureCMakeBuildFiles(IProgressMonitor monitor) throws CoreException, IOException {
IProject project = getProject();
project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed!
Code updated, no longer remove ICModelMarker.C_MODEL_PROBLEM_MARKER when only configure CMake

String arg0 = command.getArguments().get(0);
if (p == null) {
// process start failed
String msg = String.format(Messages.CMakeBuildConfiguration_Failure, ""); //$NON-NLS-1$

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had some thought on this one.

Since the condition is checking for process starting error, instead of using arg0, the message is updated to
Failure running cmake: Process failed to start

Error related to arg0 with be check/log in the next condition

			if (exitValue != 0) {
				// cmake had errors...
				String msg = String.format(Messages.CMakeBuildConfiguration_ExitFailure, arg0, exitValue);
				addMarker(srcFolder.getProject(), -1, msg, IMarkerGenerator.SEVERITY_ERROR_BUILD, null);
				return Status.error(msg);
			}

WDT?

ILog.of(ConfigureExtendedCMakeProjectHandler.class)
.error("Failed to configure for extended CMake Project", e); //$NON-NLS-1$
}
return null;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, thanks for pointing this out and the suggestion as well.

I believe the WorkspaceJob does log the error if an error status is return.
So, I grouped them together and return a simple
Status.error(message, exception)

WDT?

point="org.eclipse.ui.commands">
<command
id="org.eclipse.cdt.cmake.example.configureCMakeProject"
name="Configure Extended CMake Project">

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes, the initial intent was to allow CMake configuration only for Extended CMake projects.
Later, this was changed to support all CMake projects, and these spots were somehow missed.

Updated the UI and class names to align with the current behavior.

/**
* @since 2.1
*/
protected IStatus configureCMakeBuildFiles(IProgressMonitor monitor) throws CoreException, IOException {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, you're right there!
It does parse compile_commands.json file twice.

Code updated as your suggestion!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants