I have always used the Visual Studio Dependencies option to ensure that, for example, when building my C++ projects, any dependent LIB or DLL projects are also built. However, I keep hearing people mention 'references' and wondered, with VS 2010 on the horizon, I should be changing how I do this.
Are there any benefits to using references to dependencies or is the former a .NET feature only? I am currently using VS2008.
I prefer using references since these were introduced for unmanaged C++ in VS 2005. The difference (in unmanaged C++ developer's perspective) is that reference is stored in .vcproj file, while project dependencies are stored in .sln file.
This difference means that when you reuse your project in different solutions (and I often do) you don't need to redefine the inter-project relationships again.
Visual Studio is smart enough not to depend gravely on the paths of the projects when it establishes the reference relationship.
It used to be in VS2008 that a project dependency on a static library would automatically result in the right configuration (Debug|Release) would be linked in. It looks like VS2010 lost that ability with the move to msbuild. Sigh.
'References' are a .NET thing and don't apply to native C++; they are different than dependent projects. A dependent project in a solution is a project that must be built before (or after depending on which way the dependency goes) another project.
A reference is an assembly that contains types used in the project. The analogous thing in a native C++ project might be the include files used by a project and the .lib files that get linked in (the native C++ project 'consumes' those items even if they aren't built in another step of the solution).
Related
there is a possibility to add an existing project as a "reference" to a solution in VS(talking about C++ now). As far as I understand it means that all the project files will be added to a solution and I can modify any properties and source code, and it will affect the original solution to which this project belongs. Do I have a correct understanding of it? Or is it something else?
I don't really get why we need it, if I need another project I can use it as a lib or DLL file, this reference thing seems to make things more complicated - if I do any changes to project properties I need to think how it will affect building another solution this project belongs to.
In Visual C++ "project-to-project" references within a solution really does two things:
If the referenced project is a static or DLL library, it's implicitly included in your referencing project's link statement.
The referenced project is considered a build-dependency for the referencing project so it will be built first.
That's pretty much it. If you want to include headers in the referenced project, you need to add it your AdditionalIncludes property for the referencing project.
For a DLL project, you can set a property on it to get it's DLL copied to your referencing project's build directory.
See Visual C++ Team Blog which was back in VS 2010 when it was first introduced.
There's a different model of code sharing called Shared Projects where the shared code is built in each referencing project--i.e. there's no shared binaries.
0. Disclaimer
This question is only about Visual Studio C++ project/solution configuration and may involve subjectivity.
However, the idea behind this post is to share our approaches to configure a large Visual Studio solution.
I'm not considering any tool like CMake/Premake here.
1. Problem
How do you handle a large scaled C++ application architecture and configuration using Visual Studio?
What is, for you, the best way to setup a new Visual Studio solution composed of multiple projects?
What Visual Studio project/solution configuration feature are you trying to avoid? (Ex: Filters instead of folders)
2. Personnal approach
2.1. Context
I'm a software developer for a video game company, so I will take a very simplified game engine architecture to illustrate my words:
2.2. File Structure
My Visual Studio solution would probably look something like this:
Where Application is an executable and every other projects are libraries (Dynamically linked).
My approach would be to separate each project into two folders: include, src
And the inner structure would be separated into folders following my namespaces:
2.3. Project Configuration
The following lines will assume there is only one $(Configuration) and $(Platform) available (Ex: Release-x64) and that referencing .lib files into Linker/Input/Additional Dependencies is done for each project.
I would here define a Bin (Output), Bin-Int (Intermediate output) and Build (Organized output) folder, let's say they are located in $(SolutionDir):
$(SolutionDir)Bin\
$(SolutionDir)Bin-Int\
$(SolutionDir)Build\
The Bin and Bin-Int folders are playgrounds for the compiler, while the Build folder is populated by each project post-build event:
$(SolutionDir)Build\$(ProjectName)\include\ (Project includes)
$(SolutionDir)Build\$(ProjectName)\lib\ (.lib files)
$(SolutionDir)Build\$(ProjectName)\bin\ (.dll files)
This way, each $(SolutionDir)Build\$(ProjectName)\ can be shared as an independent library.
Note: Following explainations may skip $(SolutionDir) from the Build folder path to simplify reading.
If B is dependent of A, Build\B\include\ will contain B and A includes. The same way, Build\B\bin\ will contain B and A binaries and Build\B\lib\ will contain B and A .lib files (If and only if B is ok to expose A to its user, otherwise, only B .lib files will be added to Build\B\lib\).
Projects reference themselves relatively to Build\ folders. Thus, if B is dependent of A, B include path will reference $(SolutionDir)Build\A\include\ (And not $(SolutionDir)A\include\), so any include used by A will be available for B without specifying it explicitly. (But result to sections 2.6.2., 2.6.3. and 2.6.4. technical limitations).
After that, I make sure that my solution has a proper Project Dependencies configuration so the Build Order, when building the whole solution, will consider and respect my project dependencies.
2.4. User Project Configuration
Our EngineSDK user (Working onto Application) will only have to setup Application such as:
Include Directories: $(SolutionDir)Build\Engine\include\
Library Directory: $(SolutionDir)Build\Engine\lib\
Post-build: Copy $(SolutionDir)Build\Engine\bin\* to $(OutDir)
Additional Dependencies: Any .lib file upstream in the dependency hierarchy is listed here
This is the typical Visual Studio configuration flow of a lot of C++ library.
Common library folder architecture that I try to preserve:
lib\
include\
bin\
Here are some example of libraries using this folder architecture model (Do note that bin is exclusively for dynamically linked libraries as statically linked libraries don't bother with DLLs):
SFML: https://www.sfml-dev.org/
SDL: https://www.libsdl.org/
2.5. Advantages
Clear folder architecture
Ability to export a library directly by copy-pasting or zipping a sub-folder of $(SolutionDir)Build\
2.6. Technical limitations
The approach I wrote here has some drawbacks. These limitations are the reason of this post as I want to improve myself:
2.6.1. Tedious configuration
Dealing with 10 or less projects is fine, however, with bigger solutions (15+ projects), it can quickly become a mess. Project configurations are very rigid, and a small change in project architecture can result into hours of project configuration and debugging.
2.6.2. Post-build limitation
Let's consider a simple dependency case:
C is dependent of B and B is dependent of A.
C is an executable, and B and A are libraries
B and A post-build events update their Build\$(ProjectName)\ directory
When changing the source code of A, then compiling it, Build\A\ will get updated. However, as B has been previously compiled (Before A changes), its Build\B\ folder contains a copy of previous A binaries and includes. Thus, executing C (Which is only aware of B as a dependency), will use old A binaries/includes. A workaround I found for this problem is to manually trigger B post-build event before executing C. However, forgetting to trigger an intermediate project post-build can result into headaches during debugging (Not loaded symbols, wrong behaviour...).
2.6.3. Multiple times single header reference
Another limitation for this approach is "Multiple times single header reference".
This problem can be explained by considering the project dependency image at section 2.1..
Considering that Graphics and Physics are both including Maths headers, and that Engine is including Build\Graphics\include\ and Build\Physics\include\, typing a header name will show multiple identical results:
2.6.4. De-synchronized symbol referencing
If B is dependent of A and any header changes in A (for instance, we add a new function), Rescan File/Rescan Solution will be needed to access the new symbol from B.
Also, navigating to files or symbol can make us move to the wrong header (Copied header instead of the original one).
3. Interrogations and learning perspectives
3.1. Project Reference
During my Visual Studio software developer journey, I came through the project Reference concept, but I can't find how it can solve the technical limitations of my current approach, nor how it can helps me to re-think it.
3.2. Property sheets
As every project configuration of my solution is following the same principle but the content (Include dirs, library dirs...) for each one is different, I'm not sure how to make a great usage of property sheets.
3.3. Exploring GitHub
Currently I'm struggling finding some good project architecture references. I would be pleased finding some Visual Studio configured solution on GitHub or any code sharing platform. (I know that CMake and Premake are prefered in most case when sharing code, however, learning more about Visual Studio project configuration is my actual goal).
Thanks for reading my words, I hope that you are also interested into discussing about this subject and maybe we can share our approaches.
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.
I'm writing a program (in C++), which requires several VS projects, that I would like to put in the same VS solution. I'm using Visual Studio 2010.
Here is simply the wanted architecture : I'm using a 3rd party library (A) for my project, I have all the headers and .lib files, that I compiled with the source code.
With this library, I'm writing my own classes and function. That is my project (B).
Then I would like to develop two interfaces for the users: A command line interface (C1) and a GUI interface (C2), that are using the classes and functions defined in (B).
A <-- B <-- C1
<-- C2
I'm new to Visual Studio, and I don't know how to handle these dependencies properly.
Shall I use project dependencies (in the solution properties) or references (in the project properties) ? In fact, I'm not sure what dependencies and references are doing exactly.
Shall I compile B into some .lib library, or do something else ? If I do so, have to link only B.lib to my C1 and C2 projects, or should I also link A.lib (in other words, is the content of A.lib included somehow in B.lib ?).
And of course I would want the dependencies to be handle well, in order to always work with the up-to-date version of each project.
Is there a good way of doing it ?
Thank's in advance, and have a nice week-end :)
Yes. Use Project References.
Here is the official answer from Microsoft. While the page talks about .NET, its almost the same for native projects too.
TL;DR version:
Advantages of Project References:
They work on all development workstations where the solution and project set are loaded. This is because a project Globally Unique Identifier (GUID) is placed in the project file, which uniquely identifies the referenced project in the context of the current solution.
They enable the Visual Studio .NET build system to track project dependencies and determine the correct project build orders.
They avoid the potential for referenced assemblies to be missing on a particular computer.
They automatically track project configuration changes. For example, when you build using a debug configuration, any project references refer to debug assemblies generated by the referenced projects, while they refer to release assemblies in a release configuration. This means that you can automatically switch from debug to release builds across projects without having to reset references.
They enable Visual Studio .NET to detect and prevent circular dependencies.
Here is another nice article on Project Settings Changes in VS 2010 that also states that references are to be preferred over Project Dependencies. In fact, the article also says that the VS2010 solution converter automatically detects Project dependencies and changes them to Project references.
The policy at the company I work for is to use project references.
The project references are more useful since they keep the information of what projects a given project depends on with the project. If you then have to add the project to a new solution you do not have to go back to the old solution file to find out what projects a given project depends on.
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.