TLDR; devenv appears to build dependencies with whatever config/platform was last selected in the GUI, rather than what /projectconfig says. Ideas?
I have a Visual Studio 2012 solution that builds debug & release, win32 & x64. It has two projects
"common" produces a static library
"foo" produces a dll, and links with common.lib
Both projects output to $(SolutionDir)$(Configuration)_$(Platform), e.g. myTest/Release_Win32 so I can easily swap between configs.
The project foo depends on common, and when I explicitly build foo in the full GUI it properly builds common first, for whichever configuration/platform I'm currently targetting.
However, If I run the command line
devenv.exe myTest/myTest.sln /project foo /projectconfig "Release|x64" /build
Then it will fail because it can't find common.lib when linking. Indeed, there's no myTest/Release_x64/common.lib, but there IS myTest/Debug_Win32/common.lib. I can verify this is caused by that devenv command, it re-appears after removing all the directories.
It appears devenv is trying to build common as a dependency, but failing to specify the projectconfig and falling back to the default Debug & Win32.
I can work around this by manually building common before attempting to build foo, but I'd prefer it to happen automagically. Has anyone else encountered this, or have a workaround/solution?
Here's a solution that demonstrates the problem, and how I created it:
http://beanalby.net/stackExchange/vsDepends.zip
created "common" as Static Lib with new solution
created "foo" as Console App in that solution
added $(OutDir)common.lib as Additional Dependency under Linker/Input for all configurations on foo
marked "foo" depends on "common"
exited visual studio, saving projects & solution
running devenv myTest/myTest.sln /project foo /projectconfig "Release|x64" /build produces:
C:\Users\jason\Desktop>devenv myTest/myTest.sln /project foo /projectconfig "Release|x64" /build
Microsoft (R) Microsoft Visual Studio 2012 Version 11.0.60610.1.
Copyright (C) Microsoft Corp. All rights reserved.
1>------ Build started: Project: common, Configuration: Debug Win32 ------
1>Build started 11/15/2013 13:15:22.
1>PrepareForBuild:
1> Creating directory "C:\Users\jason\Desktop\myTest\Debug\".
1>InitializeBuildStatus:
1> Creating "Debug\common.unsuccessfulbuild" because "AlwaysCreate" was specified.
1>ClCompile:
1> stdafx.cpp
1>Lib:
1> common.vcxproj -> C:\Users\jason\Desktop\myTest\Debug\common.lib
1>FinalizeBuildStatus:
1> Deleting file "Debug\common.unsuccessfulbuild".
1> Touching "Debug\common.lastbuildstate".
1>
1>Build succeeded.
1>
1>Time Elapsed 00:00:00.52
2>------ Build started: Project: foo, Configuration: Release x64 ------
2>Build started 11/15/2013 13:15:22.
2>PrepareForBuild:
2> Creating directory "C:\Users\jason\Desktop\myTest\x64\Release\".
2>InitializeBuildStatus:
2> Creating "x64\Release\foo.unsuccessfulbuild" because "AlwaysCreate" was specified.
2>ClCompile:
2> stdafx.cpp
2> foo.cpp
2>LINK : fatal error LNK1181: cannot open input file 'C:\Users\jason\Desktop\myTest\x64\Release\comm
on.lib'
2>
2>Build FAILED.
2>
2>Time Elapsed 00:00:00.56
========== Build: 1 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
If you open Visual Studio, change the platform/config to anything else, and exit (it won't ask to save), then common will build as THAT platform/config.
This happens with both the VS2012 x64 Cross Tools Command Prompt and VS2012 x86 Native Tools Command Prompt.
Confirming Hans Passant's comment, The docs for devenv say:
Note
For build-related tasks, it is now recommended that you use MSBuild
instead of devenv. For more information, see MSBuild Command-Line Reference.
Using MSBuild instead as
MSBuild.exe myTest/myTest.sln /t:foo /p:Configuration=Release;Platform=x64
lets it get the platform & config properly. This Q/A shall serve as a warning to those still using devenv on the command line. Repent & switch!
Related
I'd like to use a script to build translations (convert from .ts to .qm, using Qt's lrelease.exe) before compiling the resource file (QRC) where they are included. In this way I know they are always updated, not to mention to avoid including binary files in the repository.
I use Visual Studio and have installed the Qt Visual Studio Tools. Normally, I'd do this through a pre-build step in the project, but it is not being executed and the compilation of the QRC file always fails.
1>------ Build started: Project: MyApp, Configuration: Release Win32 ------
1>Rcc'ing MyApp.qrc...
1> RCC: Error in 'C:\src\MyApp\MyApp\MyApp.qrc': Cannot find file 'translations/myapp_en.qm'
1>MyApp.qrc : error 1: rcc (c:\Qt\qt_5_12_3\v141\Win32\bin\rcc.exe)
1>Done building project "MyApp.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 12 up-to-date, 1 skipped ==========
The script works correctly and it is called successfully either if placed as a post-build event or from command line.
#echo off
pushd "%1"
for %%F in (*.ts) do (
c:\Qt\qt_5_12_3\v141\Win32\bin\lrelease -compress %%F -qm %%~nF.qm
)
popd
exit /b 0
What I'm I doing wrong?
It happened that I was using the new Qt/MSBuild mode of Qt VS Tools. Internally it generates several hidden targets in the MSBuild workflow, which are executed before the pre-build events.
The solution was to use a custom build step instead, with some specific settings:
Execute before the QtRcc target (the one that actually compiles the resource file)
The Qt VS Tools parses QRC files to check if the resources have been modified, so it can skip compiling them. It is necessary to add the .qm translation files as output of the custom build step.
Similarly, to guarantee translations are always compiled, set dependencies of the custom build step to the .ts source files.
I am using devenv command line switches to build and deploy a project. Build is getting started and the project is never deployed. I am using the following line of code
devenv "%pathtosolution%" /deploy Debug /project "%relativepathtoprojectfile%" /projectconfig "Debug|x64"
This is what I am seeing after that
1>------ Build started: Project: %projectname%, Configuration: Debug x64 ------
C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE>
Am I missing any switch/argument?
Try %pathtosolution% in place of %pathtosolution and %relativepathtoprojectfile% in place of %relativepathtoprojectfile
in Winbatch, variables are accessed using %var%, not %var
Since VS2010, Microsoft Visual Studio introduces the Platform Toolset concept that encapsulate the traditional global INCLUDE, LIB, PATH settings inside various Toolsets. I admit that's an improvement for flexibility, but it should not be a blackbox that makes us foolish.
Now my question is, how do I know what the resulting INCLUDE, LIB, PATH are when I apply a Toolset to my project. I think it is not realistic to analyze those hundreds of .targets and .props files(in C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120) manually to get the result. Most of the time, we just need the result. Is there any concise way to achieve that?
==== UPDATE ====
Stijn provides the right answer for me. Now I can see PATH= , LIB= , INCLUDE= ... from the build log. But, a minor question, what is the difference of LIB and LIBPATH?
1>Using "SetEnv" task from assembly "C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.Build.CppTasks.Common.dll".
1>Task "SetEnv"
1> PATH=C:\VS2013\VC\bin;;C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools;C:\VS2013\Common7\Tools\bin;C:\VS2013\Common7\tools;C:\VS2013\Common7\ide;C:\Program Files (x86)\HTML Help Workshop;;C:\Program Files (x86)\MSBuild\12.0\bin\;C:\Windows\Microsoft.NET\Framework\v4.0.30319\;C:\Windows\SysWow64;;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.0\;;C:\Windows-Kits\8.1\bin\x86;C:\Windows-Kits\8.1\tools\tracing\x86
1>Done executing task "SetEnv".
1>Task "SetEnv"
1> LIB=C:\VS2013\VC\lib;C:\VS2013\VC\atlmfc\lib;;
1>Done executing task "SetEnv".
1>Task "SetEnv"
1> LIBPATH=C:\VS2013\VC\atlmfc\lib;C:\VS2013\VC\lib;
1>Done executing task "SetEnv".
1>Task "SetEnv"
1> INCLUDE=D:\u8vc\USBview\C++\;C:\VS2013\VC\include;C:\VS2013\VC\atlmfc\include;;
The easisest way is probably to adjust the msbuild log settings so the INCLUDE/LIB/PATH environment variables are printed to the output window. In Visual Studio's options you can either:
set Projects and Solutions->VC++ Project Settings->Show Envirohnment In Log to Yes
set Projects and Solutions->Build and Run->MSBuild project build output verbosity to Detailed or Diagnostic
Then in the build log grep for INCLUDE etc
For command line builds use the /v:d switch with MSBuild.
I've expirienced the promlem using CMake. I need to use VS solution (.sln) in one target, so I have something like that:
set(SLN "${SOME_PATH}/src/exemple.sln")
get_filename_component(
VS_DIR "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0\\Setup\\VS;ProductDir]"
REALPATH CACHE)
set(BUILD_TOOL "${VS_DIR}/Common7/IDE/devenv.exe")
set(BUILD_COMMAND
"${BUILD_TOOL}" "${SLN}" "/build" "Debug"
)
add_custom_target(
${Project_OUTPUT}
COMMAND ${BUILD_COMMAND}
VERBATIM
)
And sometimes this target (when it is being compiled) hangs. Does someone know what it might be? Maybe it doesn't depend on CMake? According to logs, build system starts few projects (from this solution) and does nothing after that:
26>------ Build started: Project: project26, Configuration: Debug Win32 ------
27>------ Build started: Project: project27, Configuration: Debug Win32 ------
28>------ Build started: Project: project28, Configuration: Debug Win32 ------
29>------ Build started: Project: project29, Configuration: Debug Win32 ------
It seems that you need to specify devenv.com instead of devenv.exe. See the output of the following commands:
E:\folder>devenv.exe "E:\folder\solution.sln" /build Debug
E:\folder>devenv.com "E:\folder\solution.sln" /build Debug
Microsoft (R) Visual Studio Version 10.0.40219.1.
Copyright (C) Microsoft Corp. All rights reserved.
========== Build: 0 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========
E:\folder>
I have to enabled diagnostic mode of MSBuild project build output verbosity to see this:
1>Done executing task "EnableExtension" -- FAILED. (TaskId:81)
1>Done building target "DeployVsixExtensionFiles" in project "myextension.csproj" -- FAILED.: (TargetId:93)
...
1>Build FAILED.
1>
1>Time Elapsed 00:00:01.27
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
My problem is I cannot debug the Visual Studio extension package I'm working on, as the build output says something has failed. What's wired, the obj and bin folders with all content inside (including vsix package), has been created. I don't really know what special I've changed, because few hours ago everything was fine.
How can I investigate what has gone wrong ?
Btw: I'm using VS 2012 Premium Update 1
EDIT:
I remembered what I've done. While being in debug mode, I entered Tools -> Extensions and Updates, and uninstalled my currently debugged extension (without restarting VS after that operation). Further attempt of debugging (F5 after CLOSING Experimental Instance of VS) results in this mysterious build behavior.
My current workaround I've come up with after some time is to change the display name of the extension package in the source.extension.vsixmanifest file:
<Metadata>
...
<DisplayName>Change this name to sth else and press F5</DisplayName>
...
</Metadata>
Nothing else needs to be changed (unfortunately reversion to old name still fires this error, but at least developing and debugging can be continued).
UPDATE:
I've checked the windows registry for such problematic name, and found following PendingDeletions key:
HKEY_USERS\S-1-5-21-1832937852-2116575123-337272265-599953\Software\Microsoft\VisualStudio\11.0Exp\ExtensionManager\PendingDeletions
Under this key there is value pointing at my extension I've previously uninstalled (while being in the debug mode):
C:\USERS\G_159\APPDATA\LOCAL\MICROSOFT\VISUALSTUDIO\11.0EXP\EXTENSIONS\JAROSLAW WALISZKO\MYEXTENSION\1.0\
Removal of this entry fixes that case.
Davide Icardi commented:
Another solution is to manually open the Visual Studio experimental instance. Starting it caused all the pending extensions to be deleted automatically.
To start the experimental instance, run this command in a developer command prompt:
devenv.exe /RootSuffix Exp
Update: I'm dumb - after installing the VS 2013 SDK, there's a shortcut to start the experimental instance in the Visual Studio 2013 folder of the Start menu.