How to change working directory in Visual Studio

When developing a C++ program using Visual Studio, you typically compile and run it from the Visual Studio IDE. By default, when you do this, the executable is run with the working directory being the directory containing the Visual C++ project (.vcxproj). That is, this is the directory which acts as the current directory for your executable, when it run from within Visual Studio. Note that if you ran the executable from a commandline, then the working directory would be the current directory of your command prompt.

This behavior can be irritating if you have some files that your program needs to read or write. It would be nice if the executable considered the directory it resides in as the working directory. Changing this is easy:

  1. Open Project > Properties > Configuration Properties > Debugging.

  2. The Working Directory entry would be $(ProjectDir) by default. Change it to whatever you wish. If you want it to be the same directory as the place where the executable resides in, then change it to $(SolutionDir)$(Configuration)\

Tried with: Visual Studio 2012 and Windows 7 x64

Advertisements

How to use Armadillo on Windows

Armadillo is a C++ template library for linear algebra. It is built upon LAPACK and BLAS. It offers a simple API that is similar to that of Matlab.

1. Download the source code of Armadillo from here. Unzip the source code of Armadillo to a directory.

2. Create an environment variable named ARMADILLO_ROOT with a value of the Armadillo directory.

3. Armadillo requires LAPACK and BLAS libraries for any non-trivial matrix operation. To enable it to use these libraries, open $(ARMADILLO_ROOT)/include/armadillo_bits/config.hpp and uncomment the defines of ARMA_USE_LAPACK and ARMA_USE_BLAS.

4. To use Armadillo in your Visual C++ project, add $(ARMADILLO_ROOT)/include as an Include directory.

5. Since Armadillo source code uses LAPACK and BLAS, your project needs to link with these libraries. Armadillo ships with pre-built 32-bit .lib and .dll files for LAPACK and BLAS. Add $(ARMADILLO_ROOT)/examples/lib_win32 as Library directory to your project. Add blas_win32_MT.lib and lapack_win32_MT.lib as additional dependencies to your project.

6. Include the armadillo header file in your source code. Use the Armadillo classes and methods in your code. Remember to use the namespace arma:: Your code should compile to an EXE file without any further problems.

7. Copy the blas_win32_MT.dll and lapack_win32_MT.dll files from $(ARMADILLO_ROOT)/examples/lib_win32 to the directory that contains your EXE file. Your program should execute successfully now.

Tried with: Armadillo 3.920.2 and Visual Studio 2010

How to build RDKit on Windows

RDKit is a cheminformatics library with a C++ and Python API. You typically need to build it only if you need to use the C++ API on Windows. Here are the steps that worked for me:

1. Install Python and Numpy.

2. Install Boost.

3. Install CMake.

4. Download the latest RDKit source code from Github here. I have found that their Sourceforge releases do not include the C++ libraries.

5. Create a build directory in RDKit directory and open a command-prompt there and type cmake-gui ..

6. In the CMake GUI, pick the version of Visual Studio. Click Configure, click Configure again and then click Generate. CMake generates the Visual Studio solution for RDKit.

7. Open the generated RDKit.sln solution file. Choose a build type (Release or Debug) that matches that of the cheminformatics project you are working on. Choose Build > Build Solution. RDKit should build successfully.

8. Add an environment variable named RDBASE with a value of the RDKit base directory.

9. Open the cheminformatics C++ project you are working on. Add $(RDBASE)/Code as an Include directory. Add $(RDBASE)/Build/lib/Debug or $(RDBASE)/Build/lib/Release as a Library directory. Add all the .lib files in the library directory for linking.

10. To use a RDKit class in your C++ source file, find the header file that contains it. You can do this by looking at C++ documentation of RDKit. You may need to add the header file path relative to $(RDBASE)/Code

Tried with: Visual Studio 2010, Boost 1.51 and Windows 7 x64

LNK2038 Linker Error in Visual C++

Problem

I got this error at the linking stage of compiling a Visual C++ project:

Error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.obj

This project was being linked with other libraries and the error referred to the _ITERATOR_DEBUG_LEVEL was defined with different values in my application and the external library.

Solution

The difference in the _ITERATOR_DEBUG_LEVEL typically happens if a Release version of a library is linked against a Debug version of another library or application. Make the two have the same build type and this error should go away.

If you cannot do that, then set the _ITERATOR_DEBUG_LEVEL in your project to match the value used in the other library.

Tried with: Visual Studio 2010 and Windows 7 x64

C++: pragma once

With both Visual C++ and GCC supporting pragma once completely, I do not see any reason to still use the include guards. Include guards were always a messy solution and I am glad that their death certificate has been written. For example, I would typically use a ALL_CAPS version of the header filename as the defined name. But then, one had to remember to change this whenever the file was renamed. Also, an include guard involved two pieces of code (the #ifndef-#define and the #endif) between which the header code was placed, again too messy and problematic.

In comparison, using #pragma once is straightforward. As a bonus, the horrendous C++ compilation time might be reduced a bit due to optimizations for pragma once by both these compilers.

Visual C++: Assert in Release Mode

Problem

In Visual C++, assertions are disabled in Release mode and enabled in Debug mode of the solution. I find assertions to be cheap and effective means of capturing programmer errors and would like assertions to be invoked during Release mode too.

Solution

assert is a macro and its existence during compilation is controlled by the definition of the NDEBUG identifier. If NDEBUG is defined, assertions are disabled. As you can guess, by default, NDEBUG is defined in Release mode.

So, to enable assertions in Release mode, go to the project properties → C/C++ → Preprocessor → Preprocessor Definitions and remove NDEBUG.

Tried with: Visual C++ 2008

CGAL: GMP and MPFR Linker Errors

Problem

Compiling any Visual C++ solution that uses CGAL produces either or both of these errors:

1>LINK : fatal error LNK1104: cannot open file 'gmp-vc90-mt.lib'
1>LINK : fatal error LNK1104: cannot open file 'mpfr-vc90-mt.lib'

Solution

CGAL seems to look for GMP and MPFR libraries, whose names are suffixed with the Visual C++ version (vc90) and the build type (mt). However, CGAL stopped shipping pre-built GMP and MPFR libraries in such a format a while ago. Instead it ships a single library file for each. For example, in CGAL 3.8, these files are libgmp-10.lib and libmpfr-4.lib.

With this knowledge, this error can be fixed and the solution can be compiled like this:

  1. Ignore the library dependencies that are indicated by CGAL. This can be done by going to Properties → Linker → Input → Ignore Specific Library and adding gmp-vc90-mt.lib,mpfr-vc90-mt.lib
  2. Link with the available libraries instead. This can be done by going to Properties → Linker → Input → Additional Dependencies and adding libgmp-10.lib libmpfr-4.lib

The Visual C++ solution using CGAL should be able to build and execute without errors now.

Tried with: Visual C++ 2008 and CGAL 3.8

CUDA: LNK2005 Linker Errors

The Problem

When building a Visual Studio solution which has CUDA source files (*.cu), LNK2005 linker errors of the following kind might be seen:

LIBCMT.lib(hooks.obj) : error LNK2005: "void __cdecl terminate(void)" (?terminate@@YAXXZ) already defined in MSVCRT.lib(MSVCR90.dll)

What does it mean?

This indicates a mismatch between the kind of C runtime library used by the CUDA Build Rule and that used for the rest of the Visual C++ project.

How to fix it?

This problem can be fixed by making both of these use the same kind of C runtime library. For example, if the Visual C++ project is compiled using Multi Threaded DLL (/MD) and the CUDA build rule has Multi Threaded (/MT), then change the CUDA build rule to use /MD too.

 

Tried with: CUDA 3.2 and Visual Studio 2008

Visual C++: Creating a New Configuration

Creating a new configuration for compilation in Visual C++ is easy!

For example, say I want to create a new configuration that is same as Release mode, except I want assert() to be compiled. To do this:

  • Choose Project → Properties and in the Properties dialog, choose Configuration Manager.
  • In the Active Solution Configuration dropdown, choose New.
  • In the New Solution Configuration dialog that pops up, give the new configuration a name (ReleaseWithAssert for example) and choose an existing configuration whose settings to copy from. For our example, I would choose to copy from Release. This creates a new configuration named ReleaseWithAssert with all the settings from the Release configuration.
  • Go into the new configuration settings and make the changes you want. For example, I typically enable assertions in Release mode by removing the definition of the NDEBUG preprocessor directive.

Visual C++: Windows and Console Subsystems

Subsystem

The Subsystem option can be found in any Visual C++ project here: Project → Properties → Linker → System → Subsystem. The choice of Subsystem decides the execution environment for the executable that is compiled from the project. For a Console application, choose /SUBSYSTEM:CONSOLE. For a Windows (GUI) application, choose /SUBSYSTEM:WINDOWS. There are other Subsystems, but these two are the most common.

Entry Point Function

The entry point function of the executable is decided based on the Subsystem. A Console executable begins from a main() function, so this should be present somewhere in the project code. A Windows executable begins from a WinMain() function, so this should be defined. If a windowing library (like wxWidgets for example) is being used, that library code would typically have the WinMain call defined inside.

Preprocessor Definitions

In older Visual C++ environments, the preprocessor definitions _CONSOLE and _WINDOWS corresponded to the above 2 subsystems. They are still defined by Visual C++ when it creates a project. These definitions are not really needed now. But, there might be header files of external libraries that you use, which might look out for these definitions. So, it might be a good idea to not delete them if you face errors.

Switching Subsystems

To switch a Visual C++ project from Console to Windows or vice versa, both the Subsystem and the Preprocessor Definitions need to be changed.

Errors

A project has a mismatched Subsystem when its code is written for Console and its Subsystem is set to Windows or vice versa. This manifests itself in errors like:

MSVCRTD.lib(crtexew.obj) : error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup

To fix this, make sure the Subsystem matches the code, else switch it.