Complex builds in Visual Studio - c++

I have a few things that I cannot find a good way to perform in Visual Studio:
Pre-build step invokes a code generator that generates some source files which are later compiled. This can be solved to a limited extent by adding blank files to the project (which are later replaced with real generated files), but it does not work if I don't know names and/or the number of auto-generated source files. I can easily solve it in GNU make using $(wildcard generated/*.c). How can I do something similar with Visual Studio?
Can I prevent pre-build/post-build event running if the files do not need to be modified ("make" behaviour)? The current workaround is to write a wrapper script that will check timestamps for me, which works, but is a bit clunky.
What is a good way to locate external libraries and headers installed outside of VS? In *nix case, they would normally be installed in the system paths, or located with autoconf. I suppose I can specify paths with user-defined macros in project settings, but where is a good place to put these macros so they can be easily found and adjusted?
Just to be clear, I am aware that better Windows build systems exist (CMake, SCons), but they usually generate VS project files themselves, and I need to integrate this project into existing VS build system, so it is desirable that I have just plain VS project files, not generated ones.

If you need make behavior and are used to it, you can create visual studio makefile projects and include them in your project.
If you want less clunky, you can write visual studio macros and custom build events and tie them to specific build callbacks / hooks.
You can try something like workspacewhiz which will let you setup environment variables for your project, in a file format that can be checked in. Then users can alter them locally.

I've gone through this exact problem and I did get it working using Custom Build Rules.
But it was always a pain and worked poorly. I abandoned visual studio and went with a Makefile system using cygwin. Much better now.
cl.exe is the name of the VS compiler.
Update: I recently switched to using cmake, which comes with its own problems, and cmake can generate a visual studio solution. This seems to work well.

Specifically for #3, I use property pages to designate 3rd party library location settings (include paths, link paths, etc.). You can use User Macros from a parent or higher level property sheet to designate the starting point for the libraries themselves (if they are in a common root location), and then define individual sheets for each library using the base path macro. It's not automatic, but it is easy to maintain, and every developer can have a different root directory if necessary (it is in our environment).
One downside of this approach is that the include paths constructed this way are not included in the search paths for Visual Studio (unless you duplicate the definitions in the Projects and Directories settings for VS). I spoke to some MS people at PDC08 about getting this fixed for VS2010, and improving the interface in general, but no solid promises from them.

(1). I don't know a simple answer to this, but there are workarounds:
1a. If content of generated files does not clash (i.e. there is no common static identifiers etc.), you can add to the project a single file, such as AllGeneratedFiles.c, and modify your generator to append a #include "generated/file.c" to this file when it produces generated/file.c.
1b. Or you can create a separate makefile-based project for generated files and build them using nmake.
(2). Use a custom build rule instead of post-build event. You can add a custom build rule by right-clicking on the project name in the Solution Explorer and selecting Custom Build Rules.
(3). There is no standard way of doing this; it has to be defined on a per-project basis. One approach is to use environment variables to locate external dependencies. You can then use those environment variables in project properties. Add a readme.txt describing required tools and libraries and corresponding environment variables which the user has to set, and it should be easy enough for anyone to set up.

Depending on exactly what you are trying to do, you can sometimes have some luck with using a custom build step and setting your dependencies properly. It may be helpful to put all the generated code into its own project and then have your main project depend on it.

Related

How to make Visual Studio 2017 C++ project more portable between computers?

I am developing a project on C++ which relies on many of third-party libraries (*.lib files and *.h files). I store these libraries in a folder which is not dependant to project, like C:/thirdpartylib. Relative paths is not an option, since it becomes way too long. I have defined connections to libraries in linker setting and in general C++ settings.
But when I pass the project to supervisor he has to reset all paths to libraries to match his environment. We use git, and the project file is being tracked. He stores thirdparty libraries in another way than me.
Is there any way to make a project more portable? Maybe it is possible to store paths in some sort of config files?
As #gaurav says, the way to deal with this in Visual Studio is with property sheets. It's unfortunate that this term is used for two different things in VS, but I guess they just ran out of names (spoiler alert).
These are very powerful, once you learn how they work, and they're just what you need here because they let you define macros, and these macros can in turn be used in the rest of your project to refer to the (volatile) location of your various libraries. This is a trick that everyone who uses VS should know, but it seems that a lot of people don't.
I don't think it's worth me trying to walk you through the mechanics of setting one up here because Microsoft already document it in the Visual Studio help file. Suffice to say, you do it in the Property Manager, that should help you track down the relevant information.
There is also an excellent blog post here which I recommend you read before you do anything else:
http://www.dorodnic.com/blog/2014/03/20/visual-studio-macros/
It's also on Wayback Machine here:
https://web.archive.org/web/20171203113027/http://www.dorodnic.com/blog/2014/03/20/visual-studio-macros/
OK, so now we know how to define a macro, what can we do with it?
Well, that's actually the easy part. If we have a macro called, say, FOO, then wherever we want to expand that macro in some project setting or other we can just use $(FOO). There's also a bunch of macros built into the IDE as listed here:
https://msdn.microsoft.com/en-us/library/c02as0cs.aspx
So, you, I imagine, will want to define macros for the include and lib directories for each of your external libraries and you can then use these to replace the hard-coded paths you are currently using in your project.
And that, I reckon, should sort you out, because the definitions of the macros themselves are stored in a separate file, external to your project file, and different users / build machines can use different files. IIRC, these have extension .props.
Also, you can define a macro in terms of another macro or macros, and that makes the job easier still.
So, who still thinks that Microsoft don't know how to create a build system? Visual Studio is a fantastic piece of software once you get used to it, there's just a bit of a learning curve.
The way to go for large project is to use a package manager. There are some good options out there. Perhaps in windows and visual studio you can use vcpkg or NuGet unmanaged.
If you cannot use a package manager for some reason, the next thing to do is to commit all the dependencies to the GIT repo. If you only target windows platforms like windows 8 or 10 and want to support only VS2017 then committing the compiled dependencies is not a problem. The downside is that the repo will become huge.
For a tiny school project the latter option is viable.

What is the correct way to import a type library in Visual Studio?

Background
Our build uses ant and a custom task to build Visual Studio projects/solutions as well as some Java projects. There structure is basically a large tree and artifacts from the projects are typically copied upwards to a common build directory.
This was previously a complete mess and I've greatly simplified the ant scripts and now I'm most of the way through the Visual Studio projects/solutions. These projects are extremely old and have been upgraded through every version of Visual Studio up to 2013. Part the changes I have done was to use as many of the default project properties and macros as possible. Most of these used to be hard coded.
Although I have modified the projects to use the $(Configuration) macro to separate the artifacts from different configurations these still get copied to a common location for other dependent projects in other solutions. So to avoid confusion and actually make sure our debug builds link to all the debug libraries (which wasn't happening previously) I have been adding suffixes to the Target Name. E.g. The Target Name of a Debug Unicode build will be $(ProjectName)DU.
Problem
This has been great so far but now I'm not sure how to complete these changes for one of our COM libraries. This library has an IDL file and the MIDL compiler generates a TLB file. Maybe this isn't a good way to do it but for now I wanted the TLB file to also have a different suffix depending on the build. The problem is, when I change the Type Library property for the MIDL configuration then this breaks the Compile-time directives in the RC file. I figured it might be possible to use #ifdefs in the TEXTINCLUDE block depending on whether _UNICODE or _DEBUG are set (provided I do it via the Resource Includes dialog so I don't break the RC file). It also means that there are other importlib attributes that will also need #ifdef checks.
At the moment it kinda works without renaming the TLB files but that's only because they are currently only being used within this solution.
Has anyone ever done anything like this or know a better solution?
Update
I guess what I really need to know here is what is the best way to use types from one COM DLL in another one? Should I even be using importlib? The MSDN documentation says that in most cases you should be using the import instead. I tried this but broke a whole bunch of stuff.

Allowing developer-specific settings in VS2008 Native C++ projects

Is it possible to combine the following properties, and if so, how?
Store in our version control system some Visual Studio 2008 native C++ (VCPROJ) project files for the developers in our team that use this IDE.
Allow some of those developers to tweak their projects (e.g. using debug version of third-party libraries instead of the usual ones).
Make sure these modifications are done in files that are not versioned.
In other words, I would like to allow developers to tweak some settings in their projects without risking that these changes are committed.
An 'optional VSPROP' file approach seems doomed to fail, as VS2008 refuses to load projects that refer to non-existent VSPROP files...
Any other suggestion? Is this possible with VS2010?
You may not be able to do this but using a solution that generates the vcproj like CMake for example would let you do this. Scripts all your project with CMake and literally conditionally include a config file(if present for example) that developers can change on their setup.
Branches could solve this problem: you create a branch, play with different versions of third-party, merge changes to trunk if results are good.
Well, as a preliminary solution you could put the project file into something like .hgignore or .gitignore after its initial commit.
This way changes to it can't be done accidentally.
At least that's how I handle .hgignore itself.
We use a versionned "common_configuration" folder, and a script which copies project files from this "common_configuration" folder towards the "project" folder.
We have another script to copy the configuration backwards, so the developpers need to make a conscious action to commit their local changes to the global version control system.
It answers partly your needs :
The upside : we have a way to keep a common configuration for everyone, and no accidental committing of local configuration
The downside : blindly copying the files actually crushes local changes. We live with it. We could write some more clever merger tool (using diff, or xml specific manipulations), but don't want to spend to much time on supporting the deployment tools.

Use domain-specific-language files inside C++ project

I am developping a DSL with its own graphical editor. Such files have a .own extension. I also have a small tool that compiles .own files into .h files.
X.own --> X.h and X/*.h
I have written a simple .rules file to launch the generation.
My problem is the following :
Most of my source files include X.h, but a change in X.own does not mean the generated X.h (or any other generated file) will be different. This is dealt with by the generator through the use of temporary files and file comparison. But Visual Studio does not seem to know how to deal with all this. If i set the "output file(s)" property to the right file(s), it always assumes they will be changed. If i don't, it generates its build process assuming they won't be !
How can i make things right ?
1) Launch custom build tool
2) Compute build process based on dependencies
Don't use the custom build tool options but instead set it up as a pre-build event for the solution (this can take a general command line, just like the custom build tool). This way MSVS will not examine the generated files. As long as they are #included or listed in the solution explorer they should be compiled fine as the generation of the .h files will happen before any other compilation.
I find the custom build tool is not so useful as the pre- and post- build events in general, because of the way it expects files to be generated or modified. You might find this tool useful for other things in the future (e.g. to compress the .exe after build, to generate other dependencies correctly, to ensure files are in place etc...)
There is a nice diagram showing where to find these options in the solution properties here
jheriko's answer is interesting, because it provides a way to launch custom tool, then generate build dependencies. But it's not very usable, because you then lose all possibilities to use "custom build tools" toolkit, in which you can
choose to always compile files with some precise extension
manually skip custom build for a particular file in a particular project configuration (and visualize this decision)
There is no way (or at least i have found none) to "have it all". The only way i have found is to have the custom build tool return a non-zero number when files have been updated, with a message to the user explaining that it is not an error and inviting him to launch build again. The next time, custom build tool is launched again (not optimal, but the tool i use is pretty fast) but modifies no new file, and build process goes on, using valid dependencies.
Note : the approach described above does not work with Incredibuild, which seems to ignore project build order.

Building both DLL and static libs from the same project

I have a number of native C++ libraries (Win32, without MFC) compiling under Visual Studio 2005, and used in a number of solutions.
I'd like to be able to choose to compile and link them as either static libraries or DLLs, depending on the needs of the particular solution in which I'm using them.
What's the best way to do this? I've considered these approaches:
1. Multiple project files
Example: "foo_static.vcproj" vs "foo_dll.vcproj"
Pro: easy to generate for new libraries, not too much manual vcproj munging.
Con: settings, file lists, etc. in two places get out of sync too easily.
2. Single project file, multiple configurations
Example: "Debug | Win32" vs "Debug DLL | Win32", etc.
Pro: file lists are easier to keep in sync; compilation options are somewhat easier to keep in sync
Con: I build for both Win32 and Smart Device targets, so I already have multiple configurations; I don't want to make my combinatorial explosion worse ("Static library for FooPhone | WinMobile 6", "Dynamic library for FooPhone | WinMobile 6", "Static library for BarPda | WinMobile 6", etc.
Worse Con: VS 2005 has a bad habit of assuming that if you have a configuration defined for platform "Foo", then you really need it for all other platforms in your solution, and haphazardly inserts all permutations of configuration/platform configurations all over the affected vcproj files, whether valid or not. (Bug filed with MS; closed as WONTFIX.)
3. Single project file, selecting static or dynamic via vsprops files
Example: store the appropriate vcproj fragments in property sheet files, then apply the "FooApp Static Library" property sheet to config/platform combinations when you want static libs, and apply the "FooApp DLL" property sheet when you want DLLs.
Pros: This is what I really want to do!
Cons: It doesn't seem possible. It seems that the .vcproj attribute that switches between static and dynamic libraries (the ConfigurationType attribute of the Configuration element) isn't overrideable by the .vsprops file. Microsoft's published schema for these files lists only <Tool> and <UserMacro> elements.
EDIT: In case someone suggests it, I've also tried a more "clever" version of #3, in which I define a .vsprops containing a UserMacro called "ModuleConfigurationType" with a value of either "2" (DLL) or "4" (static library), and changed the configuration in the .vcproj to have ConfigurationType="$(ModuleConfigurationType)". Visual Studio silently and without warning removes the attribute and replaces it with ConfigurationType="1". So helpful!
Am I missing a better solution?
I may have missed something, but why can't you define the DLL project with no files, and just have it link the lib created by the other project?
And, with respect to settings, you can factor them out in vsprop files...
There is an easy way to create both static and dll lib versions in one project.
Create your dll project. Then do the following to it:
Simply create an nmake makefile or .bat file that runs the lib tool.
Basically, this is just this:
lib /NOLOGO /OUT:<your_lib_pathname> #<<
<list_all_of_your_obj_paths_here>
<<
Then, in your project, add a Post Build Event where the command just runs the .bat file (or nmake or perl). Then, you will always get both a dll and a static lib.
I'll refrain from denigrating visual studio for not allowing the tool for this to exist in a project just before Linker (in the tool flow).
I think the typical way this is done is choice 2 above. It is what I use and what I have seen done by a number of libraries and companies.
If you find it does not work for you then by all means use something else.
Good luck.
I prefer 2 configurations way.
Setup all common settings via 'All configurations' item in a project properties windows. After it separated settings. And it's done. Let's go coding.
Also there is very good feature named 'Batch build', which builds specified configurations by turn.
Multiple projects are the best way to go - this is the configuration i have most widely seen in umpteen no of projects that i have come across.
That said, it might be also possible to implement the third option by modifying your vcproj files on the fly from external tools(like a custom vbscript), that you could invoke from a make file. You can use shell variables to control the behavior of the tool.
Note that you should still use use visual studio to make the build, the makefile should only launch your external tool if required to make the mods and then follow that by the actual build command
I use Visual Studio 6.0 (Still) due to issues that are preventing us from Migrating to VS2005 or newer. Rebuilding causes severe issues (everything breaks)... so many of us are considering lobbying a migration to GnuC++ moving forward in a structured way to eventually get us off of licensed Visual Studio products and onto Eclipse and Linux.
In Unix/Linux it is easy to build for all configurations.. so I can't believe what a time and productivity sink it is to try and accomplish the same task in Visual Studio. For VS6.0 I have so far found that only having two separate projects seems to be workable. I haven't yet tried the multiple configuration technique, but will see if it works in the older VS6.0.
Why not go for version 1 and generate the second set of project files from the first using a script or something. That way you know that the differences are JUST the pieces required to build a dll or static lib.