Externalizing parameters for VS2008 C++ project compilation - c++

Is there some way to externalize the paths of libraries that are used in the compilation process on Visual Studio 2008? Like, *.properties files?
My goal is to define "variables" referencing locations to headers files and libraries, like *.properties files are used in the Ant build system for Java.

I think you're looking for .vsprops files. They're comparable to the *.properties files.

Environment Variables?
All the $(xyz) replacements allowed in the propertier are, and you are allowed to "bring your own".
They are normally inherited from the parent process, so you can set them
for the machine / user in the system settings (usually inherited via explorer)
in a batch file that sets them before running devenv.exe
in an addin like SolutionBuildEnvironment to read them from a project file

I don't know how Ant works, but for your static libraries and headers you can edit the .vcproj file. These are XML files in fact. Libraries go in the VCLinkerTool tool tag, in AdditionalDependencies
<Tool
Name="VCLinkerTool"
AdditionalOptions=" /subsystem:windowsce,5.01"
AdditionalDependencies="iphlpapi.lib commctrl.lib coredll.lib"
/>
Additional header paths are defined in the VCCLCompilerTool tool tag, in AdditionalIncludeDirectories
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="dev\mydir"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
/>
Be careful, there is one such section for each build configuration.
Is this what you are looking for?
Edit : the .vsprops suggested by MSalters are more powerful; you can define additional dependencies and libraries in them an make your projects inherit these properties. Well I learned something useful today!

If you're referring to influencing the location of #includes, Project properties|Configuration Properties|C/C++/Additional Include Directories is the ticket. There is also project properties|Common Properties|Additional reference search paths.
If your question is how do I parameterize stuff in a VCProj file like I would in Ant, the answer is that in VS2010 VC projects are[/can?] be MSBuild-based whereas VS2008 vcproj files are a proprietary XML based format [but as the other answers say, they have an analogous properties capability].
In the absence of more info, I'm pretty sure the standard approach for what you're doing is to add your search paths a la the first or second paragraph.

You can use a build system like CMake. You give CMake a high-level description of your project, and it spits out the necessary files to get your project to build correctly via another tool (e.g. Visual Studio's IDE, or a Unix-style makefile).
Paths: You can use CMake's INCLUDE_DIRECTORIES() and LINK_DIRECTORIES() commands in the CMakeList.txt configuration file to specify these paths. CMake has variables which describe both aspects of your environment (many of which can be autodiscovered, e.g. CMAKE_C_COMPILER which is the command to run your C compiler) plus any options you wish to allow the user to specify directly. All variables are stored in a separate plain text configuration file, CMakeCache.txt, that can be edited in a text editor or using a special GUI configuration tool.
CMake has many other features, like the ability to autodiscover the locations of many useful libraries, and to produce customised source/header files from "template" files containing CMake directives using the CONFIGURE_FILE() command.
Advantages:
Highly portable across common environments (e.g. it can produce solution files for several versions of MS Visual C++, as well as makefiles for Unix (e.g. Linux) systems).
Used by several large multiplatform projects (e.g. KDE)
Very simple to set up simple projects
I've found the dependency checking system to be rock-solid -- e.g. it knows to rebuild if you change compiler options (unlike naive use of make for example)
Disadvantages:
Ugly, primitive syntax
Documentation quality varies (e.g. it's sometimes hard to tell exactly what properties affect any given object)
Some time investment involved

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.

How to create dynamic defines for Visual Studio?

I have a C++ project that builds on several platforms.
On Mac OSX and Linux, I use SConstruct, which allows me to have some "smartness" regarding the different compilation steps. Namely, I could put the program version in a file named VERSION at the root of the repository, whose content is simply:
2.0
In the build SConscript, I just have to open, read and parse that file and I can create dynamic defines based on it. For instance:
env.Append(CXXFLAGS=['-DVERSION_MAJOR=%s' % open('VERSION').read().split('.')[0]])
This is, for obvious reasons, very convenient. It also allows me to put today's date in an environment variable for instance.
Now for Windows, I have a .sln file with different .vcxproj files into which I'd like to do something similar, except I have no idea how.
To summarize, my question is: how can I have "smart" defines like that (reading, parsing a file and putting its content into several environment variables) without having to change the .sln/.vcxproj files manually on every version shift ?
I know I could use SCons on Windows too, but I'd like not to (mainly because it seems less popular on the platform, and I don't want to scare potential contributors that only know Windows-specific tools).
A common way to do this is to define your constants in an include file:
e.g.
// Version.h - Autogenerated, don't edit
#define VERSION_MAJOR 1
Next you write a script or a program (in your favourite language) to obtain version from somewhere and dynamically write Version.h. Possibly parse the old Version.h and increment or get it from some external source.
In visual studio, create a custom build step for Version.h and make it dependent on something that forces it to update on every build.
You could maintain the current solution, and for Windows, integrate it with Visual Studio solution and project files generated by SCons using the MSVSProject() builder or the MSVSSolution() builder.
You can find more info about these SCons builders here.

Directory structure for a C++ library

I am working on a C++ library. Ultimately, I would like to make it publicly available for multiple platforms (Linux and Windows at least), along with some examples and Python bindings. Work is progressing nicely, but at the moment the project is quite messy, built solely in and for Visual C++ and not multi-platform at all.
Therefore, I feel a cleanup is in order. The first thing I'd like to improve is the project's directory structure. I'd like to create a structure that is suitable for the Automake tools to allow easy compilation on multiple platforms, but I've never used these before. Since I'll still be doing (most of the) coding in Visual Studio, I'll need somewhere to keep my Visual Studio project and solution files as well.
I tried to google for terms like "C++ library directory structure", but nothing useful seems to come up. I found some very basic guidelines, but no crystal clear solutions.
While looking at some open source libraries, I came up with the following:
\mylib
\mylib <source files, read somewhere to avoid 'src' directory>
\include? or just mix .cpp and .h
\bin <compiled examples, where to put the sources?>
\python <Python bindings stuff>
\lib <compiled library>
\projects <VC++ project files, .sln goes in project root?>
\include?
README
AUTHORS
...
I have no/little previous experience with multi-platform development/open source projects and am quite amazed that I cannot find any good guidelines on how to structure such a project.
How should one generally structure such a library project? What ca be recommended to read? Are there some good examples?
One thing that's very common among Unix libraries is that they are organized such that:
./ Makefile and configure scripts.
./src General sources
./include Header files that expose the public interface and are to be installed
./lib Library build directory
./bin Tools build directory
./tools Tools sources
./test Test suites that should be run during a `make test`
It somewhat reflects the traditional Unix filesystem under /usr where:
/usr/src Sometimes contains sources for installed programs
/usr/include Default include directory
/usr/lib Standard library install path
/usr/share/projectname Contains files specific to the project.
Of course, these may end up in /usr/local (which is the default install prefix for GNU autoconf), and they may not adhere to this structure at all.
There's no hard-and-fast rule. I personally don't organize things this way. (I avoid using a ./src/ directory at all except for the largest projects, for example. I also don't use autotools, preferring instead CMake.)
My suggestion to you is that you should choose a directory layout that makes sense for you (and your team). Do whatever is most sensible for your chosen development environment, build tools, and source control.
There is this awesome convention that I recently came across that might be helpful: The Pitchfork Layout (also on GitHub).
To sum up, subsection 1.3 states that:
PFL prescribes several directories that should appear at the root of the project tree. Not all of the directories are required, but they have an assigned purpose, and no other directory in the filesystem may assume the role of one of these directories. That is, these directories must be the ones used if their purpose is required.
Other directories should not appear at the root.
build/: A special directory that should not be considered part of the source of the project. Used for storing ephemeral build results. must not be checked into source control. If using source control, must be ignored using source control ignore-lists.
src/: Main compilable source location. Must be present for projects with compiled components that do not use submodules.
In the presence of include/, also contains private headers.
include/: Directory for public headers. May be present. May be omitted for projects that do not distinguish between private/public headers. May be omitted for projects that use submodules.
tests/: Directory for tests.
examples/: Directory for samples and examples.
external/: Directory for packages/projects to be used by the project, but not edited as part of the project.
extras/: Directory containing extra/optional submodules for the project.
data/: Directory containing non-source code aspects of the project. This might include graphics and markup files.
tools/: Directory containing development utilities, such as build and refactoring scripts
docs/: Directory for project documentation.
libs/: Directory for main project submodules.
Additionally, I think the extras/ directory is where your Python bindings should go.
I don't think there's actually any good guidelines for this. Most of it is just personal preference. Certain IDE's will determine a basic structure for you, though. Visual Studio, for example, will create a separate bin folder which is divided in a Debug and Release subfolders. In VS, this makes sense when you're compiling your code using different targets. (Debug mode, Release mode.)
As greyfade says, use a layout that makes sense to you. If someone else doesn't like it, they will just have to restructure it themselves. Fortunately, most users will be happy with the structure you've chosen. (Unless it's real messy.)
I find wxWidgets library (open source) to be a good example. They support many different platforms (Win32, Mac OS X, Linux, FreeBSD, Solaris, WinCE...) and compilers (MSVC, GCC, CodeWarrior, Watcom, etc.). You can see the tree layout here:
https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk/
I can realy recommend you using CMake... it's for cross platform development and it's much more flexible that automake, use CMake and you will be able to write cross platform code with your own direcory structure on all systems.

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.

Complex builds in Visual Studio

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.