📜 ⬆️ ⬇️

Nuget ++ for the poor

If you regularly write in C ++ using third-party libraries (okromya boost) and you are tired of constantly setting the paths to folders with headers and libs, then under the cat you will find one way to automate this somewhat.

Every time starting a small ConsoleApplication project in VisualStudio, in order to try out the idea that came to mind, I feel pain. The pain of constant settings in the sections Properties-> C / C ++ -> General-> Additional Include Directories and Properties-> Linker-> General-> Additional Library Directories .

If there are 1-3 projects and a couple of third-party libraries in the Solution-e, then it is still tolerable, but for> 10 projects and> 5 libraries everything looks different. And when one day my patience broke, I decided to automate this business somehow. Taking the system for boost, I began to cut out my bike. What I wanted to get from the solution:
')
  1. Connecting third-party libraries by prescribing a 2-level include-a, including the name of the library, for example
    #include <gtest/gtest.h> #include <vsqlite/connection.hpp> 

  2. Automatic linking of the corresponding * .lib files when connecting a * .hpp file
  3. X86 / x64, Debug / Release, Static / Dynamic Runtime support
  4. The ability to quickly transfer to another machine

First of all, you should decide on the folder in which our repository will be stored. I have C: / nuget ++. Inside, folders include , lib / x86 , lib / x64 , projects . With the first 3, everything is clear, and in the third folder I store projects for building these same libraries.

For example, take the gtest library, unzip it in the projects folder and open gtest-md.sln from the msvc folder.

Next, we copy all the headers from projects / gtest / include / gtest to include / gtest / . To execute the first item, simply add a reference to nuget ++ / include to the global settings of c ++ projects. In Visual Studio 2015 (and, as I recall, in 2013 too) it does this by opening the Property Manager window ( View-> Property Manager ), and editing the Microsoft.Cpp.Win32.user and Microsoft.Cpp.x64.user files in any from configurations of any C ++ project. Namely, we are interested in the section Common Properties-> C / C ++ -> General-> Additional Include Directories — we simply add a stupid path to the include folder of our nuget, for example C: \ nuget ++ \ include;% (AdditionalIncludeDirectories) .

To perform the 2nd and 3rd paragraph will have a little tricky. To begin with we will create for our library 4 configurations for x86 / x64 and Static / Dynamic Runtime. In the project properties, we change the name of the output file and the linking variant of the runtime library for each of the configurations in the sections Properties-> Configuration Properties-> General-> Target Name and Properties-> Configuration Properties-> C / C ++ -> Code Generation, respectively.
ConfigurationOutput file nameRuntime library
Release Static Runtime$ (ProjectName) -vc $ (PlatformToolsetVersion) -mt-sMulti-threaded (/ MT)
Release Dynamic Runtime$ (ProjectName) -vc $ (PlatformToolsetVersion) -mtMulti-threaded DLL (/ MD)
Debug Static Runtime$ (ProjectName) -vc $ (PlatformToolsetVersion) -mt-sgdMulti-threaded Debug (/ MTd)
Debug Dynamic Runtime$ (ProjectName) -vc $ (PlatformToolsetVersion) -mt-gdMulti-threaded Debug DLL (/ MDd)

Having done batch-build, we will get 2 groups (x86 and x64) with 4 lib-files that need to be transferred to the lib / x86 and lib / x64 folders.
For automatic linking of the specified files, you will have to shuffle a little over the library itself. First of all, add the auto_link.hpp file to the project and, for them, include it from all other headers. By digging into MSDN on the topic of / MT, / MD, / MTd, / MDd keys, you can create a table with a unique set of macros for each configuration. A bit of magic with macros and auto_link.hpp ready:

auto_link.hpp
 #pragma once #if _MSC_VER == 1500 #define GTEST_LIB_TOOLSET "vc90" #elif _MSC_VER == 1600 #define GTEST_LIB_TOOLSET "vc100" #elif _MSC_VER == 1700 #define GTEST_LIB_TOOLSET "vc110" #elif _MSC_VER == 1800 #define GTEST_LIB_TOOLSET "vc120" #elif _MSC_VER == 1900 #define GTEST_LIB_TOOLSET "vc140" #endif #if defined(_MT) || defined(__MT__) # define GTEST_LIB_THREAD_OPT "mt" #else # define GTEST_LIB_THREAD_OPT #endif #if defined(_DEBUG) #if defined(_DLL) # define GTEST_LIB_RT_OPT "-gd" #else # define GTEST_LIB_RT_OPT "-sgd" #endif #else #if defined(_DLL) # define GTEST_LIB_RT_OPT "" #else # define GTEST_LIB_RT_OPT "-s" #endif #endif #ifndef GTEST_LIB #define GTEST_LIB_FULL_NAME "gtest-" GTEST_LIB_TOOLSET "-" GTEST_LIB_THREAD_OPT GTEST_LIB_RT_OPT ".lib" #pragma comment(lib, GTEST_LIB_FULL_NAME) #pragma message("linking to gtest:" GTEST_LIB_FULL_NAME) #endif 


Create a test project, a few lines of code:

 #include <gtest/gtest.h> int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } TEST(autolink_tests, can_autolink_gtests){} 

Build and voila:



To transfer the resulting repository (4 point), just copy it to another machine and set the paths to the include, lib / x86 and lib / x64 folders.

As a bonus, we get compatibility with the boost; simply copy the hpp, lib and dll files to the appropriate directories. As a result, having spent 1 working day on organizing my own nuget ++ for the poor , I got rid of a headache when using running third-party libraries. Now in my arsenal of boost, cryptopp, gmock, gtest, jsoncpp, pugixml, vsqlite and this list is constantly expanding. Plans to create a single Solution and set up Build events for automatically copying the necessary files to target directories.

Source: https://habr.com/ru/post/276883/


All Articles