Change include paths - c++

I have a C++ solution that uses several external libraries. For that to work, the compiler needs to be able to find all the header files. Currently this works by hard-coding the header locations into the various project files. But since the headers are installed in a different location on each computer, that means the project will only build on one machine.
What is the "correct" way to deal with this problem?
I feel like there should be a way to define which libraries each project needs, and then a separate file somewhere that says where those libraries are on this particular machine. But I don't know if MSBuild has anything remotely like that.
(Obviously, as well as the header files, we have exactly the same problem with the linker needing to find the object code to link in.)

It seems you can in fact fix this using environment variables. Either through the Visual Studio user interface itself, or just by editing the *.vcxproj file in a text editor, edit the include path from
D:\Libraries\Boost\32bit\include;D:\Libraries\GTest\32bit\include
to instead be something like
$(BOOST_ROOT)\include;$(GTEST_ROOT)\include
Now the project builds on any machine where the environment variable %BOOST_ROOT% is set to the right folder path. (And likewise for %GTEST_ROOT%.)

Related

Why fatal error “LNK1104: cannot open file 'cryptlib.lib' occur when I compile a C++ project in Visual Studio?

I am getting the error mentioned above when compiling a project on Visual Studio. What is strange and different about my situation is that this works on my personal laptop, but not at work.
I have the entire project saved in Dropbox, because I sometimes work on my projects from work and I like this automatic sync that way I don't worry about loosing anything. Having said that, I use relative paths for my libraries, that way the folder is the same for both computers, i.e. "..\cryptopp\x64\Output\Debug\cryptlib.lib"
My question is, why does it work at home, but not at work? I made sure the property sheet has the correct path as well. The linker and VC++ directories are both relative paths.
This cryptlib.lib has some namespaces like CryptoPP and variable types such as byte, it won't give me an error on this. It knows it exists (I get the correct font color)
Is there something that I am missing?
P.S. Added screenshots per request. Can't add more than 2 links, so I merged 2 screenshots into 1. That ECE427Projects is where the solution file is located. I don't want to go any further back than that.
Screenshot 1
Screenshot 2
You've put the directory for the library in the wrong field.
There's two places you could use to specify the directory where your libraries are supposed to be. I prefer to use the Library Directories section in Configuration Properties→VC++ Directories, but the alternate is Additional Library Directories in Configuration Properties→Linker→General. There's no need to specify it in both locations, though I doubt anything bad will happen if you do. Bear in mind that this is supposed to be a directory, not a file, so delete the trailing cryptlib.lib file name from this directory string.
If you haven't, in Configuration Properties→Linker→Input, for Additional Dependencies, you should be putting the name of the library object (cryptlib.lib), in your case.
For all of these, make sure the default values inherited by the project property pages are still there, after the stuff you add.
Let me know if this doesn't resolve the issue.

visual c++ include folders, libraries, etc

I'm an engineer, not a strong programmer. I'm writing some simulations using openGL and freeglut. I develop on my computer at home or at school or work so I need to keep everything contained. Typically I've gotten things to work by placing needed libraries in my solution folder and linking to them in the project properties. Any header files I've also put in the solution folder (or subfolder if already defined e.g. GL/freeglut.h). Then in my source files I use a command like #include "GL/freeglut.h" with quotes. In my most recent project I'm having problems with another set of headers that deal with hardware that have classes with the same name. It is my understanding that if you keep your headers in separate folders and be careful with namespaces there shouldn't be a problem. I can also configure additional include folders for the project then I use a command like #include <GL/freeglut.h>. What is the best way to set all of this up?

Precompiled headers question

I am right now reorganizing my project and what recently was a simple application now became a pair of C++ projects - static library and real application.
I would like to share one precompiled header between two projects, but face some troubles with setting up the .pdb file paths.
Assume my first project is called Library and builds it's .lib file with a corresponding Library.pdb file. Now, the second project is called Application and builds everything into the same folder (.exe and another Application.pdb file).
Right now my both projects create their own precompiled headers file (Library.pch and Application.pch) based on one actual header file. It works, but I think it's a waste of time and I also think there should be a way to share one precompiled header between two projects.
If in my Application project I try to set the Use Precompiled Header (/Yu) option and set it to Library.pch, it wouldn't work, because of the following error:
error C2858: command-line option 'program database name "Application.pdb" inconsistent with precompiled header, which used "Library.pdb".
So, does anyone know some trick or way to share one precompiled header between two projects preserving proper debug information?
The question is, why do you want to share the precompiled header (PCH) files. Generally I woul d say, that does not make sense. PCH are used to speed up compiling not to share any information between different projects.
Since you also write about the PDB file, you probably want to debug the library code with your applications. This can be achieved by setting the /Fd parameter when compiling the library. When you link the library in your application and the linker finds the corresponding PDB file, you get full debug support.
This sounds complicated and cumbersome to set up. More than that, it may not be possible at all.
Instead, you can include the precompiled header from one application into the second. It will still be compiled once for the second project, but maintenance becomes easy and you do not have to redefine the dependencies in the second project (just include them).

Source file organisation

I am having a bit of trouble organising my source files.
I have my own small, but growing collection of code that I would like to use in various projects. The file and folder layout is something like this:
library\sub1\source.h
library\sub1\source.cpp
library\sub2\source.h
library\sub2\source.cpp
One of my problems is that I want to include this code, as needed, in my other projects. To date I have used absolute paths to point to the libary code, but there must be a better way.
Futhermore, I need to add every library file I use to a project's files Visual Studio in order for it to compile correctly.
So my question in short is how do I fix this? What is the proper/best way to handle the above situation.
You shouldn't, in general, add source files from libraries directly to other projects. Compile them separatly as a library and use those.
For organising the library's directory structure itself, right now I settled on something like the following structure
library1/widget.h
library1/private/onlyinlib.h
library1/private/widget.cpp
(and if applicable)
library1/private/resources/widget.jpg
library1/private/project/widget.xcode
I put all headers directly in the library path, and have a subfolder private which will contain everything that's only used by the library, but should never be shared / exposed.
The greatest advantage is that every project I start only needs a include path pointing at the directory containing my libraries, then every (public) include is done like
#include "library1/widget.h"
private includes are simply
#include "onlyinlib.h"
This has a number of advantages:
If new libraries are introduced, there's no messing with project /compiler settings to get the headers 'visible'.
Moving to other compilers / platforms is also very little hassle.
The headers are automatically 'namespaced', i.e. by including part of the path too, it's next to impossible to get a nameclash with the includes
It's immediatly obvious where a header comes from, and if a header is part of the public interface or not
I don't think that there's a proper way to do this - it's going to depend on exactly what you are trying to achieve.
Here's some things you might not be aware of:
You can use relative paths in your projects.
You can use environment variables in paths.
You can add directories to Visual Studio's search rules.
This gives you a little more control over where you put the include files and if you add your folders to Visual Studio's search rules you don't have to include any paths at all.
If you must include third-party code instead of just linking with a pre-compiled version (e.g., perhaps you need to make modifications or tweaks to it), consider branching it in whatever you use for source-control:
/trunk/... --- your code goes here
/thirdparty --- pristine copies of third-party libraries go here
/thirdparty/lib1
/thirdparty/lib2
etc.
/trunk/lib1 --- branched from: /thirdparty/lib1, perhaps with local changes
this is the version that you build/link with.
Assuming you use a decent source-control system, this scheme will allow you to easily upgrade to newer versions of third-party libraries and then merge those changes with the changes you've made locally.
For example, suppose "lib1" releases a new version:
Commit the change to /thirdparty/lib1.
Merge from /thirdparty/lib1 to /trunk/lib1
Fix any merge conflicts.
This is, IMO, the only sane way to handle upgrading third-party libraries to which you've made local modifications.
First: Add all used directorys to your project include paths. Add them as relative paths if possible.
Second: You must add all used librarys/source files to your project. This can be either done in the project explorer, or in the Project->Linker tab. In the latter case, you'll have to add the used directories to the projects library paths as well.
Usually its not a good idea to use paths in #include directives.

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.