0

I have a Visual studio 2015 C++ project that has references to a few 3rd-party free library.

Just to reduce compile time (currently 5 - 90 seconds),
I want to split the project into many smaller projects.

In preparation, I have already created filters in the solution explorer.
The filters show a top-level structure of my project - divided into tier :-

Tier 1  - my core library, no reference to outside, rarely change
Tier 2a - my custom encapsulator for external library "A"
Tier 2b - my custom encapsulator for external library "B"
...
    note: all Tier2 #include Tier1 , rarely change
Tier 3  - business logic that rarely change, #include Tier1&2
Tier 4  - business logic that often change , #include Tier1&2&3

Question : How to split this project into many projects easily?
e.g. almost easy as click a filter then select "extracted to a new project"

I have read some sources - their explanation suitable for how to create from scratch, not for an existing project.

It also seems that I have to add some lines for some individual files.

#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif

I have >100 files, so it is not very practical.
I googled "split visual studio c++ project", but did not find many results.

Relate question : not explain "how"
How do you split a Visual Studio Solution?

External link : all has the line #define DECLDIR __declspec(dllexport)
http://www.codeguru.com/cpp/cpp/cpp_mfc/tutorials/article.php/c9855/DLL-Tutorial-For-Beginners.htm
https://manski.net/2011/11/creating-a-dll-project/

Community
  • 1
  • 1
javaLover
  • 6,347
  • 2
  • 22
  • 67
  • 1
    There's no easy way I'm aware of. I normally make a copy of the whole project folder, rename the vcxproj file, rename all refs to the project name in the vcxproj file (using notepad++), then add the new project to the solution and delete all the files I didn't want in there. Takes about 3 mins once you get used to it... Not ideal, but still... – Baldrick Jun 23 '16 at 06:39
  • @Baldrick Thanks! 3 minutes at the best is very little! .... May you explain "rename all refs to the project name in the vcxproj file" please? If I have pj1.vcxproj and want to create library pj2, roughly speaking, I will have to edit all words "pj1" in the pj1.vcxproj, right? I found only 1 place pj1, is that what you mean? ...... Do I still have to DECLDIR declspec(dllexport) each file manually? – javaLover Jun 23 '16 at 07:33
  • 1
    Yep, basically. How many refs there are really depends on what's in the project, but rename all the ones you find, and try to add it back to the solution. It'll fail to load if you screwed it up. This won't help with the 'DECLDIR' part - for that you'd probably need a macro or script of some kind to process your files and add it in. – Baldrick Jun 23 '16 at 08:14

1 Answers1

1

I would like to note first that if your lower tiers rarely change, whole compilation would rarely occur too. Also note that there is no one click to rule them all solution.

You're almost there. If you've already grouped your project into separate library, the next step would be to actually turn them into dynamic library. This would speed up compilation greatly as long as no symbol are changed (implementation modification is fine). For example for Tier 1 project:

First, create a dynamic library project (DLL Project). Erase all source code which generated by VS. Group all Tier 1's source code (header and cpp/implementation file) to the project's directory. Add them to the project.

We can have multiple dynamic libraries for each header file, but Visual Studio is not the best IDE for such task (use technology like CMake or QBS). To be safe, consolidate declarations into single header file (or at least some manageable number, don't forget to change the #include in implementation files). Add dynamic library macro to the header, e.g. tier1lib.h

#ifdef DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif

This macro would tell whether we're importing or exporting a symbol based on our build commands.

Now in tier1lib.h, mark which symbol that will be visible to other project. In each function, add DECLDIR macro such as

DECLDIR void foo();
// or, if you want to export/import whole class' public symbols
class DECLDIR Foo{};

Build it.

Now in the main project, tell VS about where to find the dynamic library. Add include path (where to find headers), library path (where to find *.lib file) and library filename (e.g. tier1lib.lib). Copy the resulting *.dll to the main project's output folder and Tier 1 compilation is now completely separated to the main project.

Leben Asa
  • 307
  • 1
  • 6
  • Thank. Tier 1 has 30 .h files, I should not consolidate all declarations into single header file, should I? IMHO, just forward declaration of 30 files can be tedious and reduce maintainability. .... or is it "the way" to go in real business world? – javaLover Jun 23 '16 at 07:24
  • 1
    Nah. Just do what fits your need. Consolidating declarations simply means less dynamic library macro, doesn't affect anything. – Leben Asa Jun 23 '16 at 08:09
  • 1
    I would like to suggest to invest your time into scriptable build tools such as `CMake` or `QBS`, they have ways to optimize build. In my experience (building OpenCV), even using `MSBuild` is considerably faster than building in VS. You can clearly see VS often build things more than once in Output panel, I have no idea why it does that. – Leben Asa Jun 23 '16 at 08:19
  • 1
    `CMake` won't build anything. It's actually a generator, so you would get a VS solution. But you can make fancy multi-dependency project easily with it. `Qbs` on the other hand can find most compiler in your system and actually build your project. – Leben Asa Jun 23 '16 at 08:26