Visual Studio run custom build tool when dependencies change - visual-studio-2013

I have a solution with two C++ projects in Visual Studio 2013.
Project A creates a static library. Project B produces a SWIG-generated DLL wrapper for A, linking the lib generated by A. The complicating factor is that B generates code using a "Custom Build Step", set to execute before ClCompile. The custom build step calls out to an external tool to generate wrapper code based on classes defined in header files in project A. If the generation completes successfully, project B builds a DLL from the generated code, linking against the .lib generated in project A.
The problem I have is that the custom step in B is occurring on every build (as one would expect), but I'd like to make it happen when there are changes to header files in A. I can't see a way of defining a rule that enforces this condition. If I add "..\project A*.h" to the Additional Dependencies field of the Custom Build Step, the missing link would be a macro that evaluates to true when any file in Additional Dependencies is newer than any file in the Outputs field.
Does Visual Studio provide a macro that tells me when the Custom Build Step's Additional Dependencies are newer than Outputs, or am I in scripting territory here?

I use a custom build similar to this:
<CustomBuild>
<Command>swig -c++ -python -I..\include -outdir $(OutDir) %(Identity)</Command>
<Message>Creating SWIG-generated files...</Message>
<Outputs>$(ProjectName)_wrap.cxx;$(Outdir)$(ProjectName).py</Outputs>
<AdditionalInputs>header1.h;header2.h;header3.h</AdditionalInputs>
</CustomBuild>
I don't use anything additional, so Visual Studio seems to have a default rule to run the custom build step if files in AdditionalInputs are newer than Outputs.

Related

Visual Studio project types Makefile and Utility

I am creating a vcxproj project to build C code (UEFI) which builds with custom build steps. I need the source C and H files to display with full IntelliSense support, then when I hit F5, I want the project to build if any source file changed, then start Debug. If nothing changed, just start the Debugger. The Build just needs to run my command line commands, I do not need Visual Studio to use its C compiler and Linker. It seems the only way to build with custom steps is to set Configuration Type to either Makefile or Utility.
One problem with Makefile project is that it always builds the NMake command line even if I did not touch any files. Is there a way to configure build so that it only builds if any of the source files changed, like with Application or Dynamic Library project types?
Another problem (only with Makefile project) is that it forces IntelliSense to some C++ mode that marks all my CHAR16* L"Strings" as errors: a value type of const wchar_t* cannot be used to initialize an entry of type "CHAR16*". There are Additional Options under NMake IntelliSense menu, but no matter what I put there makes no difference. There is no documentation about what the available switches are and their effect. Is it possible to configure a Makefile project to C mode? BTW, VS2013 does not have this problem, it is only VS2019 and VS2022.
Utility project type does not have the above-mentioned problem with IntelliSense, but it always returns "build up-to-date" even when I change source files, which should set a dirty flag and cause a build. The build only starts when I select Rebuild. Is it possible to configure a Utility project to build when a source file changed?

TypeScript compilation outside of project created with Visual Studio

I have inherited a large LOB application that is built using TypeScript. The project has no reference paths in any of the files due to the fact it has been setup and created using Visual Studio 2013 - Visual Studio seems to have some magic where it will pick up the global TypeMaps itself. scoff.
The current build process has been to use Grunt to copy the compiled .js files (which are generated on save in Visual Studio) to a build directory - not actually compile them.
(to further reinforce this point, Grunt is NOT compiling any TypeScript).
This build process is now no longer acceptable as I am moving the application to a build through a Continuous Integration process, using Team City and Command Line tsc.exe/Grunt - so when the repository is checked out there are obviously no generated .js files in the project.
In its current state there is a host of compilation errors when trying to use Command Line tsc.exe/Grunt to compile the TypeScript files, I think due to the fact that the application is not using reference paths?
Does this mean I'm going to need to add all of the relevant reference paths to each file in the project?
Has anyone got any experience regarding this kind of setup and could point me in the right direction to manage these reference paths and build process?
Thanks
In its current state there is a host of compilation errors when trying to use Command Line tsc.exe/Grunt to compile the TypeScript files, I think due to the fact that the application is not using reference paths
No. You should use a tsconfig.json which will create the compilation context.
More
https://basarat.gitbooks.io/typescript/content/docs/project/project.html
A solution has been found.
Using the Visual Studio configuration options in the grunt-ts task I have setup the task to specifically use the projects .csprog and TypeScript 1.4 compiler (we are locked into this compiler).
My configuration for the grunt-ts task:
ts: {
default: {
vs: "Consortium.Client.Web.csproj",
options: {
compiler: "1.4/tsc"
}
}
}
I hope on the off chance, this helps someone else.

VS2010/MSBuild 4.0 building external projects

It seems that since VS2010 and MSBuild 4.0, VisualStudio and MSBuild are able to resolve and build project references that are not located within the solution.
Let us create an example to be more concrete. Create a solution called Solution1 with a C# project named A and another project called B. In project B, add a reference to project A. Now create a new solution called Solution2 and click "Add Existing project" and select Project B. There is a warning that can be seen in Solution Explorer and the Warning List.
The trick is that even with "warning as error" we are able to build Solution2.sln. Actually, project A is found
and built by Visual Studio or MSBuild. Let us verify this by opening a VS2010/VS2012 command line and execute the following commands:
msbuild <dirPathToSolution1> Solution1.sln /t:clean **cleaning up solution1 with project A"
msbuild <dirPathToSolution1> Solution2.sln /t:build
ProjectA is effectively built and worse: the warning mentioned above is not even raised there. With previous versions of Visual Studio such situation could not happen (I have tested it with msbuild 3.5 and VS2008).
However, in our situation we would like to prevent such things. Indeed, we have a large source repository with several solutions and many committers. We are reorganizing our dependencies aiming finally to the extraction of smaller repositories. Meanwhile, we do not want developers to add hidden project dependencies without seeing it. We would like to allow only project references "inside" a solution, leaving other dependencies to assembly references.
So the question is "Is there a way, to prevent such solution such as Solution2 to build ?". Ideally, it should not compile with both VS2012 and MSBuild. However a solution involving only the MSBuild command line would do thanks to our Continous Integration.
edit I checked Microsoft.Common.Targets and there does not seem any way to achieve what you want. Either project references are built, or they are not (this is for instance influenced by the BuildProjectReferences flag of my original answer). There is no way to build them selectively depending on which solution they are in unless I'm missing something - which is mainly because project references are set on the project level, not on the solution level: in your project file there is an MsBuild ItemGroup named ProjectReferences and that is used. (Actually this makes some sense: if you ask MsBuild to build projectB.csproj, and B says it references A, then no solution comes into play and you could expect it to build A, after all you are referencing it).
Now as I understand it, you want to prohibit referencing across directories whose structure happens to be represented by solutions. If that is the case, and you really need this, you could probably get away with a tool that parses the MsBuild log and looks for lines like
Project "somedir\projectB.csproj" (2) is building "someOtherDir\projectA.csproj" (3) ...
then extract the directory info from it and make the tool raise an error when they do not match. Then incorporate the tool in your CI server and feed it with the msbuild log files.
original answer
Try with /p:BuildProjectReferences=false on the command line. As the name suggests it will disable building of referenced projects. When building solution1, this should not be a problem since projectA will be built anyway as it is in the solution. However when building solution2, it won't build projectA and you'll get a build error.

How to compile all CPP file without building the whole project in VS2010

Is it possible that I can just compile all CPP files under a project and without linking etc. the project?
The only way I know to do this is by specify the /c switch when you compile the code. Unfortunately, this option is not available from within the Visual Studio development environment, so you'll need to build your code on the command line by calling cl.exe directly. To make things easy on yourself, use the Visual Studio Command Prompt to do so.
Not sure if it's possible to get MSBuild to do this, the documentation is unclear whether the limitation is Visual Studio itself or if it's a limitation of MSBuild. I haven't actually tried for myself.
Alternatively, you can build individual source files from within the IDE by pressing Ctrl+F7 (at least, assuming the default C++ development settings). If that fails, it's also available as the "Compile" option located in the "Build" menu.
I'm not sure whether this will do what you need, but may be worth a try: create a project for an executable (rather than a library) and include all cpp files in it. Add a main() function that just returns zero. Set the C++ optimisation option to 'optimise references' (/OPT:REF). This may just compile all the cpp files but effectively ignore them during the link stage since none of them are referenced by the application.
You don't say why you need to do this - is it because linking takes a huge amount of time?

Where can I see the build script used by Visual Studio?

Where can I find the build script -all the list of tools used to build and link the assemlies like al.exe etc.-that BUILDS, REBUILDS the visual-Studio solutions?
MSBuild (the build engine for Visual Studio) uses a model where the tool(s) used for an action are dictated by the project file being built. Thus your list of tools will vary based on the types of projects you are building. The easiest way to find out the list of tools being used for a build of any given solution would be to turn on a more detailed logging level (detailed or diag) for MSBuild via Tools->Options->Projects & Solutions->Build & Run in Visual Studio and then parse/investigate the build output for an indication of the tools currently invoked by the Build Targets.
As Nick Nieslanik has said in his answer, the actual toolset will vary based on the project type (and target programming language), maybe even the selected .NET framework version.
To have single view on all definitions, properties, targets, etc. used by MSBuild, you could generate and review a fully preprocessed project file (only available with MSBuild 4.0 or newer).
From msbuild.exe /? output:
/preprocess[:file]
Creates a single, aggregated project file by
inlining all the files that would be imported during a
build, with their boundaries marked. This can be
useful for figuring out what files are being imported
and from where, and what they will contribute to
the build. By default the output is written to
the console window. If the path to an output file
is provided that will be used instead.
(Short form: /pp)
Example:
/pp:out.txt
Example:
msbuild.exe myproj.csproj /pp:out.xml
In this case out.xml is basically a self-contained file that has all the Import-ed project files inline so you can easily search and browse them.
In each project (in this case a c# csproj) file is a link to the msbuild used by msbuild/visual studio to build.
e.g. <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
This target links to the internal files used.

Resources