Notes |
|
(0023868)
|
David Cole
|
2010-12-10 10:47
|
|
Quick update on this issue. We've tried a few things as work-arounds, but have not come up with anything that works reliably yet. I'm working on submitting a bug report to the Microsoft Visual Studio team to see what they have to say.
Keep your eye on these bug notes for updates. As info comes in, I'll post it here. |
|
|
(0024377)
|
David Cole
|
2011-01-03 18:58
|
|
|
|
(0024541)
|
David Cole
|
2011-01-10 14:02
|
|
We have a new idea for how to solve this problem. Bill, Brad and I discussed it this morning, and came up with this:
When an input to CMake changes, and the user clicks build in Visual Studio, the first thing to build is the ZERO_CHECK project. When cmake re-runs from the ZERO_CHECK project within Visual Studio, we will pass an additional command line flag indicating that the call came from a VS ZERO_CHECK instigated re-build.
Rather than calling the VS macro *after* we generate, when we know how many *.sln/*.vcproj/*.vcxproj files have changed, and after having changed those files on disk, and calling the "reload macro" over in VS, which tries to prompt the user, stop the build, close and re-load.... Rather than all of that, we propose the following new approach:
When called from ZERO_CHECK to re-run CMake, we will:
- decide to close/configure+generate/reload
- or -
- "cancel" and avoid configure+generate
If deciding to close/configure+generate/reload, we will:
- call Visual Studio's "Build.Cancel"
- call Visual Studio's Solution.Close
- configure+generate
- call Visual Studio's Solution.Open
If cancel, we will:
- simply return
- leave sln/vcproj/vcxproj files stale w.r.t. CMake input
- allow the VS build to continue
- user may still cancel the build at this point, if he wants to
We could, in fact, achieve this feature without doing any user prompting by default.
I propose that we invent a new variable or global property to control this behavior named CMAKE_VS_RELOAD. It's values would be:
ON - always do the auto-reload behavior for this project
OFF - always do the cancel behavior
PROMPT_DEFAULT_ON - prompt the user, default choice is ON
PROMPT_DEFAULT_OFF - prompt the user, default choice is OFF
By default, if you don't set this variable or property, and it's not defined, then you get the "ON" behavior.
We think this approach will yield a more robust and less confusing implementation of the "auto-reload feature".
Does anybody monitoring this bug have any thoughts or suggestions w.r.t. this new approach? Thanks in advance. |
|
|
(0024544)
|
David Cole
|
2011-01-10 14:10
|
|
One thing to think about when considering the solution to this problem described in 0011258:0024541 : cmake may be called from other contexts to re-configure/re-generate *NOT from VS* BUT *while the solution is open in an instance of VS* -- (i.e. cmake-gui, cmake command line tool in a cmd prompt, an automated build script is running on that build tree, ...)
We need to be careful about the implications of these interactions, and to make sure that the reload behavior is triggered from the scenarios where we want it to be triggered, and avoided in the scenarios where we want it avoided. |
|
|
(0024559)
|
James Bigler
|
2011-01-10 16:14
|
|
One of the things I like about this approach is the ability to ask *before* CMake reconfigures and changes all of your build files whether you want this to happen. Often, once CMake reconfigures, the CMake plugin must run or the user gets prompted with too many reload dialogs.
I would also argue for not allowing CMake to configure as a default build rule as part of any project except for ZERO_CHECK. This would mean removing the default build rule on CMakeLists.txt files in individual projects. Unfortunately there's no good way to force ZERO_CHECK to run when doing a "Build only this project" unlike a makefile. I would be willing to live with this, because the number of times that I would call "Build only this project" and expect it to reconfigure are rather small. |
|
|
(0024565)
|
Fraser Hutchison
|
2011-01-10 18:57
|
|
I also like the idea of configure+generate happening while the solution is unloaded. Although I guess occasionally it may be slightly less efficient than what happens currently (e.g. if none of the projects are affected by the config+generate step)?
I don't see a good solution to the scenario you describe where cmake is run from outside VS. Does this not really need Microsoft to resolve the bug you filed? |
|
|
(0024623)
|
Bill Hoffman
|
2011-01-12 11:14
|
|
Running from outside VS should work as well.
when running a VS generator from the outside you do this:
- Look for running VS instances, and find out what solutions they have loaded.
- If one of them is in the binary folder for the build, or one of its sub-directories
- do an unload for those projects
- run cmake
- reload the project |
|
|
(0024680)
|
Ben Medina
|
2011-01-14 12:26
|
|
Sounds like a great solution. |
|
|
(0025241)
|
James Bigler
|
2011-02-03 11:54
(edited on: 2011-02-03 12:24) |
|
Were there any checkins relating to this? I see that it is targetted for 2.8.4, but no checkins were reported on the bug.
|
|
|
(0025242)
|
David Cole
|
2011-02-03 11:57
|
|
No commits yet. I'm still working on a fix. If we have an rc3, and I can get it working reasonably by then, it will be in there... Otherwise it will get pushed off until 2.8.5. |
|
|
(0025251)
|
David Cole
|
2011-02-03 15:39
|
|
Adding this code:
// Tell VS to stop the build before we go configure/generate:
//
if(!this->VSSolutionFile.empty())
{
cmCallVisualStudioMacro::CallMacro(this->VSSolutionFile.c_str(),
"Macros.CMakeVSMacros2.Macros.StopBuild", "", true);
}
Right after this chunk:
// now run the global generate
// Check the state of the build system to see if we need to regenerate.
if(!this->CheckBuildSystem())
{
return 0;
}
(currently line 2300 of cmake.cxx)
Seems to work pretty well with Visual Studio 2010. We call the macro to stop
the build, it cancels the build (but still allows cmake to finish), cmake
regenerates vcxproj/sln files, and then Visual Studio prompts with a single
dialog asking if you want to reload the solution.
But... with Visual Studio 2008 (have not yet tried 2005), VS also stops the
build, but does not allow CMake to finish. Therefore, you end up in an infinite
"run cmake because the build system is out of date" loop because CMake never
finishes...
I really don't want to end up with divergent different ways of "solving" this
"problem" based on Visual Studio version. But based on the above evidence
(which goes a ways toward explaining how we ended up with what we have now) I
do not see any other way than to do this differently for different Visual
Studio versions.
Would anybody like to volunteer to try any other tactics or do some
experimentation toward solving this? This issue drives me crazy... |
|
|
(0025277)
|
Robert Lenhardt
|
2011-02-04 06:10
|
|
I just checked this article:
http://visualstudiohacks.com/general/customize-your-project-build-process/ [^]
There are some events which are triggered on project build start and completion.
So why not try to:
- Register a callback on VS project completion
- callback checks for project ZERO_CHECK and build failure (if ZERO_CHECK fails, solution needs to be reloaded?)
- callback triggers Build.Cancel, Solution.Close, Solution.Open
Does this sound reasonable? |
|
|
(0025280)
|
David Cole
|
2011-02-04 08:44
|
|
Robert, your suggestion in 0011258:0025277 sounds reasonable. (But I say that every time we have a new idea here, and then I get frustrated by the devils in the details...)
Does anybody monitoring this issue have time to try out such a strategy today? If so, add a note here, letting us know you're working on it. Otherwise, I'll give this one a try, but maybe not till Monday. Thanks... |
|
|
(0025281)
|
Robert Lenhardt
|
2011-02-04 09:00
|
|
Ok, i just wanted to check if this idea was weighed before and found wanting.
I will try to get into the devilish details during the weekend and report back if it works. |
|
|
(0025300)
|
Robert Lenhardt
|
2011-02-05 10:52
|
|
Here is an update to my suggestion. I tried to:
- add a ReloadFlag to the Macros module, and set it to True when ReloadProject is called by Cmake
- add a Event Callback on Project Build End too check if ReloadFlag is set, if yes do Build.Cancel
- add a Event Callback on Build End (get triggered by Build.Cancel above), and Close and Reopen Solution there
You can try it out by unloading the CMake macros and loading the attached version, as there is no change in CMake itself, only to the macros.
Outcome: VS 2008 and 2010 pop up a 'File Modification Detected' dialog (for the solution only, not for all projects) while solution is reloading. You can press Ignore because the Solution has reloaded already. But it seems that you can not get around a file changed popup when you have already changed the Solution and want to Cancel the build.
I think you have to do the stamp check and the solution regeneration in separate cmake runs, so you can
- check the stamps while building
- if stamp check fails, cancel the build, close the solution
- call cmake from the macro to regenerate the solution
- open the regenerated solution
But relying on VS macros for cmake invocation seems fragile to me. What do the others think? |
|
|
(0026853)
|
Bill Hoffman
|
2011-06-14 10:16
|
|
I don't think we have another choice. We have the makefiles and vs projects call cmake. So calling it from the macros should not be that much of a stretch. The tricky part will be getting the right arguments to it. Since the macros are not project specific. Would you be able to give this a try and create a patch? |
|
|
(0026870)
|
Robert Lenhardt
|
2011-06-15 08:35
|
|
I can give it a try. But the problem is that the stamp check and regeneration is not separated in cmake. As far as i know ZERO_CHECK does
cmake --check-stamp-list ...
and this triggers regeneration if one stamp is older.
Is there a way (command line option) to only do the check without immediate regeneration? |
|
|
(0027429)
|
Jonathan S. Shapiro
|
2011-09-15 16:53
|
|
I'm going to ask Rico Mariani if he has any ideas on this, but in the meantime, a "turn this on its ear" sort of approach occurred to me.
Since the build can be performed externally by cmake and nmake/msbuild, it might be worth asking why we want the solution file in the first place. The answer, I suspect, is that various bits of Visual Studio make use of the project file as a core database describing the "shape" of the project/solution.
This has me wondering if it is possible to gain that benefit of the solution file *without* using it to direct the build? For example, what happens if we generate a solution file that has all of the necessary dependency information but is somehow marked "do not build" on every step **other than** ZERO_CHECK?
In effect, I think I'm suggesting a hybrid style of external build, where each build re-generates the solution file as an *output* to be consumed by the debugger and/or browser.
From my perspective, I'd actually prefer this over relying on the solution file for the build. I'm rather concerned about what happens when somebody adds a file to the solution from within VS and forgets to update the underlying CMake file. If we don't rely on the solution file for build purposes, that becomes less of a issue.
Like I said, it's a naive question, and there is probably a perfectly obvious reason why it is a bad idea. But it seemed worth throwing out there... |
|
|
(0027439)
|
Bill Hoffman
|
2011-09-16 15:23
|
|
One of the big selling points of CMake, is that it produces native IDE files especially VS ones. People that like VS, like to see the native files. Often times, I go in via the IDE and look at compile flags for a specific file. I also generate preprocessed .i files. Both of those tasks would not be possible with a system like you describe. If you prefer to do that, you can do it with CMake today. Just use the external_project command to create an external project that builds with nmake/jom and have the outer project be the VS IDE. Which brings up another point, the IDE or now msbuild does parallel builds differently and sometimes better than nmake/jom. Also, some folks use integrated cluster building tools that would not work if you used makefiles. Other add on projects to VS would also not work. So, I think we will be doing IDE files for some time to come.
Seems like we actually have a good fix, and need to try it. We just have to do something different for VS 2010 vs 2008. I will try to take a look at this... |
|
|
(0027452)
|
Bill Hoffman
|
2011-09-19 14:25
|
|
"Seems to work pretty well with Visual Studio 2010. We call the macro to stop
the build, it cancels the build (but still allows cmake to finish), cmake
regenerates vcxproj/sln files, and then Visual Studio prompts with a single
dialog asking if you want to reload the solution."
I tried the above, but it does not work. VS will pop up two dialogs for each .vcxproj file that has changed. Here is the problem:
1. when doing a build you can not reload the project
2. If you stop the build, the current process continues to run.
- you can not reload during a build
- once cmake stops running it can not reload the project
Seems to be that we need to spawn a process that can not be killed by VS. Then that process needs to kill the build and do the reload. Might still have trouble because as soon as you kill the build VS will notice the .sln and .vcxproj file changes, and start the dialog per target reload... |
|
|
(0027491)
|
David Cole
|
2011-09-29 14:29
|
|
Observations:
- if we call "Build.Cancel" during a macro invocation, the remainder of the macro does not run
- if we call Solution.Close/Solution.Open from the OnBuildDone event, it is too late, because VS notices the filters files have changed and prompts about them before the OnBuildDone event fires
Conclusion:
- the only thing we can think to solve this is to defer generation of the new sln/vcproj files until later, and then just call Build.Cancel, *then* call this sequence at OnBuildDone time: Solution.Close, rename generated files, Solution.Open.
We tried the following code to come to this conclusion:
Private Sub BuildEvents_OnBuildDone(ByVal Scope As EnvDTE.vsBuildScope, ByVal Action As EnvDTE.vsBuildAction) Handles BuildEvents.OnBuildDone
MsgBox("OnBuildDone event - before")
CloseThenOpenIfCancelled()
MsgBox("OnBuildDone event - after")
End Sub
Imports EnvDTE
Imports System.Diagnostics
Public Module Macros
Dim cancelled As Boolean
' DO NOT EDIT THIS MACRO
' This macro is automatically configured here by CMake
Public Sub ReloadProjects(Optional ByVal projects As String = "")
cancelled = False
Dim solution As String
solution = DTE.Solution.FullName
If (Not solution Is Nothing) Then
If (Not solution = "") Then
Dim files As String()
files = projects.Split(";")
Dim msg As String
msg = "CMake has regenerated " & files.Length & " .sln and/or .vcproj files."
msg = msg & vbCrLf & vbCrLf & "Click:"
msg = msg & vbCrLf & " -- Yes to reload the whole"
msg = msg & " solution and issue a new Build Solution command."
msg = msg & vbCrLf & " -- No to reload the whole solution"
msg = msg & " and stop the build."
msg = msg & vbCrLf & " -- Cancel to do nothing."
msg = msg & vbCrLf & vbCrLf & "(After clicking Cancel, Visual Studio will"
msg = msg & " likely prompt to reload each .vcproj file individually,"
msg = msg & " resulting in " & files.Length & " more dialogs...)"
Dim result As MsgBoxResult
result = MsgBox(msg, MsgBoxStyle.YesNoCancel + MsgBoxStyle.MsgBoxSetForeground, _
"CMake - Automatically reload and build?")
If ((result = MsgBoxResult.Yes) Or (result = MsgBoxResult.No)) Then
cancelled = True
DTE.ExecuteCommand("Build.Cancel", "")
'DTE.Solution.Close(True)
'DTE.Solution.Open(solution)
If (result = MsgBoxResult.Yes) Then
DTE.ExecuteCommand("Build.BuildSolution", "")
End If
End If
End If
End If
End Sub
' DO NOT EDIT THIS MACRO
' This macro is automatically configured here by CMake
Public Sub StopBuild(Optional ByVal projects As String = "")
DTE.ExecuteCommand("Build.Cancel", "")
End Sub
Public Sub CloseThenOpenIfCancelled()
If (cancelled) Then
MsgBox("close then open")
Dim solution As String
solution = DTE.Solution.FullName
DTE.Solution.Close(True)
DTE.Solution.Open(solution)
End If
End Sub
End Module |
|
|
(0027492)
|
David Cole
|
2011-09-29 14:46
|
|
One approach that should work, based on our observations:
We could modify cmGeneratedFileStreamBase to defer the call to RenameFile until later...
In the VB macros, we could iterate the list of file names passed in to the Reload macro and do the file renames right in VBA code itself, in between calls to Solution.Close and Solution.Open.
It will take a bit of time to implement this, but it looks like it should be possible with this approach. |
|
|
(0027652)
|
Jean-Christophe Fillion-Robin
|
2011-10-26 04:03
|
|
From Bill Hoffman - 9:43 PM - 2011/10/26:
There is an out of cmake solution for this.
http://vscommands.com/ [^]
If you install the VSCommands plugin free version, it will fix the reload dialog to only ask once. |
|
|
(0027970)
|
David Cole
|
2011-12-13 19:27
|
|
Unset target version field; too late for a fix to go into 2.8.7; deferred until a future version.
(Although, see other notes for other ways to deal with this problem...)
|
|
|
(0029683)
|
Robert Carnecky
|
2012-06-13 13:23
|
|
I don't really know the internals of ZERO_CHECK and the CMake macros, so this might not work at all.
But have you tried using an add-in instead of the ZERO_CHECK/macro solution? Since an add-in is native code, I don't think Visual Studio can abort it once Build.Cancel is called (not tried it out though).
The add-in could:
- Register for the OnBuildBegin event (fires before any project is built)
- During OnBuildBegin, decide whether the project is managed by CMake, ask CMake if anything changed, and use the dialog described by David to ask the user what to do
- If the user decides to regenerate the project, cancel the build, close the solution, regenerate using CMake, reload the solution
As for using external generators while Visual Studio is running, I could live with "Cannot generate project while it is being used. Please close the solution in Visual Studio". Currently, it takes less time than confirming the reloading of all changed project files anyway. |
|
|
(0029838)
|
Tom Reijnders
|
2012-06-26 11:24
|
|
As far as I can tell, a solution didn't end up in 2.8.8 either. Is that correct? |
|
|
(0029839)
|
David Cole
|
2012-06-26 11:30
|
|
Tom Reijnders, you are correct in note 0011258:0029838. As far as we know there is no satisfactory solution to this issue, so it is still not solved in 2.8.8, and it won't be in the shortly forthcoming 2.8.9 either. |
|
|
(0031355)
|
David Cole
|
2012-10-31 05:50
|
|
Some feedback on the http://vscommands.com [^] plugin:
"The plugin seems to work as described: it pops up a "reload all" dialog. Now, it turns out that the reloads don't always work, and I have to close the solution and open again, but at least I can do that without hitting "reload" 25 times." |
|
|
(0032205)
|
Ryan H. Kawicki
|
2013-02-06 10:41
|
|
I'm just curious to know if this is still actively being looked into.
I see that Microsoft really has not been very helpful, and I am not very familiar with the IDE macro system to be useful.
VS Commands seems to be a workaround, and trying to augment our development environment with this is like pulling teeth so management and security will allow it to be approved for classified systems.
Thanks |
|
|
(0032789)
|
void.pointer
|
2013-04-09 12:44
|
|
I thought of an interesting solution to this problem under discussion. I think this will work for all versions of Visual Studio.
Instead of relying on macros to determine when the solution needs to be reloaded, just modify the .SLN files. You can either do this through some XML tag with a version number in it (incremented each time CMake determines the solution and/or project(s) should be reloaded), or you can use a "dummy" project, called something like "reload###", where ### is some counter/version, starting from 001. When you generate with CMake, and changes are detected, then increment to 002.
In my experience, Visual Studio will always prompt for a solution reload (if the SLN file changed) before prompting to reload projects that have changed. When you reload the solution, you automatically reload every project, so there is no need to click through possibly hundreds of reload confirmation dialogs.
Thoughts? |
|
|
(0032790)
|
Bill Hoffman
|
2013-04-09 13:45
|
|
That sounds interesting. Would just a touch on the file work? Although, I think I have seen it reload project files first and then reload the solution. The other problem is will this interrupt the build? If you do a build and cmake re-runs will the build stop and the solution reload? |
|
|
(0032791)
|
void.pointer
|
2013-04-09 15:27
(edited on: 2013-04-09 15:29) |
|
I am not sure a touch would work. It seems that Visual Studio doesn't use the modification/access dates to determine whether to reload a solution. It's easy to see this: Just regenerate your visual studio targets without making any changes to the scripts. The file contents are exactly the same, but modification date is changed. Visual Studio won't ask you to reload anything.
I've been using Visual Studio since version 6 and I have never seen it ask to reload projects if solution is out of date. So, I can't really say if you have in fact seen it do any different.
Also I don't believe this will force builds to be interrupted. In my experience, the user has to manually stop an in-progress build. After stopping, the prompt to reload solution appears immediately. However, your macro can still be useful here. The macro can detect if the solution needs to be reloaded and provide a way to stop the build for the user, however, it should not attempt to reload the solution: Ideally, stop the build, and Visual Studio will reload for you after that.
|
|
|
(0032792)
|
Bill Hoffman
|
2013-04-09 15:34
|
|
It is certainly worth a try. It might work. Do you have some time to try it? I can help point in the right direction. |
|
|
(0032815)
|
Brad King
|
2013-04-12 11:04
|
|
Re 0011258:0032791: This is a good idea. It looks like one could add content like a
# CMake-Force-Reload: 1
comment as the *third* line of the .sln file and increment the number when necessary. VS seems to ignore it.
In cmGlobalVisualStudioGenerator::CallVisualStudioMacro's MacroReload code path it calls GetFilesReplacedDuringGenerate to decide whether anything has really changed. If so, it tries to do the reload. This code is only called by cmGlobalVisualStudio7Generator::Generate which does
// Now write out the DSW
this->OutputSLNFile();
// If any solution or project files changed during the generation,
// tell Visual Studio to reload them...
if(!cmSystemTools::GetErrorOccuredFlag())
{
this->CallVisualStudioMacro(MacroReload);
}
This is where some refactoring will be needed. Before writing a new .sln file, CMake should read the *existing* .sln to extract the current CMake-Force-Reload number (and assume "0" if none is found). If any *other* files have been replaced by this point (GetFilesReplacedDuringGenerate returns a non-empty list) then increment the number (leave it alone otherwise). Finally, include the (possibly incremented) CMake-Force-Reload number in generation of the new .sln so it will be updated if and only if something has changed. |
|
|
(0032816)
|
Ryan H. Kawicki
|
2013-04-12 11:11
|
|
Just a quick mention, I've been using CMake 2.8.7 with VS11 and have noticed the following:
1) Build does not prompt to stop the build when CMake regenerates projects / solution. Haven't looked to validate VS11 registered the macros. Not that big of a deal, as a manual stop can be done.
2) It appears VS11 now detects multiple projects out of date and will now prompt the user to just reload the whole solution once instead of each individual project. |
|
|
(0032912)
|
voidpointer
|
2013-04-19 12:57
|
|
Sorry for the late response. Unfortunately I don't think I'll have the time to be able to implement this feature. I've been wanting to get my hands dirty with the CMake code base for a number of reasons, but it's just not feasible with the little amount of free time I have, in addition to the fact that there isn't someone actively sitting next to me or available for questions (and there would be many of them). |
|
|
(0036102)
|
David Cole
|
2014-06-03 06:10
|
|
I think the "right solution" to this problem is to remove the feature moving forward.
The more recent versions of Visual Studio do better with reloading and prompting less in general anyhow, and this feature in CMake is at this point more problems than it's worth.
Perhaps it could be left "as is" for legacy versions of VS (say back to VS 10 or 11), and simply omitted with more recent versions...? |
|
|
(0036108)
|
Ryan H. Kawicki
|
2014-06-03 10:02
|
|
I think that leaving it for legacy is find and omitting for future versions is fine. As volatile as the IDE is, this may become an issue in the future, but for now, allow the newer IDEs (VS11 and VS12) handle the update. |
|
|
(0038517)
|
Brad King
|
2015-04-15 10:09
|
|
|
|
(0039772)
|
Robert Maynard
|
2015-11-02 09:13
|
|
Closing resolved issues that have not been updated in more than 4 months. |
|