I am writing my own C++ project library in visual studio (couple of projects that consist of *cpp, *.h files, NOT an actual .lib file). Each of these projects is located in single Visual Studio "solution".
When I needed to use a code from one project in another, I just copied it. But that was short term solution. Now my library has grown both in size and functionality, and because of code duplication I ended up with dozens of different versions of the same file.
That single solution serve me as a playground // test ground for new ideas. I am developing projects not libs. Currently it holds about 50 projects.
I am working on visual studio 2015.
Lets say I have setup like this:
DataIO project located in */Solution/#DataInputAndOutput/DataIO/DataIO.h
consist both of DataIO.h and DataIO.cpp
Foo project located in */Solution/#Foo/Foo/Foo.h
consist both of Foo.h and Foo.cpp
DataIO.h:
#pragma once
#ifndef __DATA_IO_H__
#define __DATA_IO_H__
// ...
extern FILE * const logFile;
// Bunch of function declarations
#endif // !__DATA_IO_H__
I know that this is not a "Minimal, Complete, and Verifiable example" but my problem lies in logistic of things, not things themselves. And I believe that my description is sufficient.
Problem #1: In Foo.cpp I #include "DataIO.h" (with is possible because i added additional include directories in Foo project setup) But whenever I try to compile Foo I am given following error: unresolved external symbol for every function declaration inside DataIO.h and that one external variable. How Can I Fix this problem? Do I need to create a DataIO.lib to keep things straight?
I tried to add DataIO.h and DataIO.cpp into Foo project directly (NOT copy it, just add it into project) but that seems like a bad idea...
I recommend trying out the new "Shared Items Project" in VS2015+. A Shared Items Project is literally just a set of files. The project itself doesn't build anything. In fact, there are no (or almost no) compilation or linkage settings in a Shared Items Project -- those settings come the the project that references the Shared Items Project. When you reference a Shared Items Project from some other project FOO, the build of FOO happens as if the files of the Shared Items Project are items of the referencing project.
Short of that, you can set up your shared projects to build .libs and then use Project References within Visual Studio to automatically set up the linkage. I think you have to manually set up the include paths when doing this, though.
The best way to do this is to factor out common code into a library so the common code resides in one place. And then have your projects use the library - via an include file and linking with said library.
Related
We have a solution with projects that is generate by cmake.
There is src folder that has all the source code. Proj_Service1, Proj_Service2 and Proj_Service3 reference same Main.cpp and Base_Service.cpp files. In addition, each project has reference to its own ServiceX.cpp file. All projects are console projects (exe). See solution structure below:
-Solution
----Proj_Service1
-------Main.cpp
-------Base_Service.cpp
-------Service1.cpp
----Proj_Service2
-------Main.cpp
-------Base_Service.cpp
-------Service2.cpp
----Proj_Service3
-------Main.cpp
-------Base_Service.cpp
-------Service3.cpp
The reason the structure above in that way is becuase it was decided in the company that each project should include only files that relevant to the project.
I want to add Test_Proj project that will test one of the services or/and all of them using googletest.
When I try to instantiate ServiceX.cpp in Test_Proj, I obviously get linker errors since Proj_ServiceX is not lib and therefore I cannot link to it.
What I thought to do is to create an additional project of type "lib", move Service1.cpp, Service2.cpp and Service3.cpp files to it and make all projects reference it. Basically:
-Solution
----Service_Proj
-------Base_Service.cpp
-------Service1.cpp
-------Service2.cpp
-------Service3.cpp
----Proj_Service1
-------[Reference to Service_Proj]
----Proj_Service2
-------[Reference to Service_Proj]
----Proj_Service3
-------[Reference to Service_Proj]
----Test_Proj
-------[Reference to Service_Proj]
Questions:
Is the solution I suggested above is the only way?
If there is a different, better approach, even the one that requires using other tools, I'll be glad to hear.
Scenario 1
A solution SolA contains only 1 project named PrjA.
PrjA is a Win32 console application, the compilation result is PrjA.exe.
How shall I split the source code files in PrjA into PrjA1 and PrjB, so that the management of the source code is easier, while the compilation result, PrjA1.exe, will be almost the same as PrjA.exe?
For example, I have PrjA :-
PrjA has 300 .cpp files.
PrjA.exe sizes 400KB.
I hope to split PrjA into 2 projects :-
PrjA1 has 200 .cpp files
PrjB has 100 .cpp files.
PrjA1.exe is also around 400KB.
I'm not sure how to setup PrjB or what will be its compilation result.
Assume PrjB compiles to PrjB.DLL, sized 100KB, I hope PrjA1.exe will somehow embed PrjB.dll inside itself. Thus the size would be 400KB.
I don't want a 300KB PrjA1.exe, which will dynamically link to 100KB PrjB.dll in runtime.
Question: How shall I set PrjB, and how shall I set the link between PrjA1 and PrjB?
Scenario 2
Same as Scenario 1, just this round PrjA's compilation result is a windows DLL, named PrjA.dll, how shall I split PrjA into PrjA1 and PrjB?
The development environment is Visual Studio 2013 under windows 7 64-bits, but the compilation results are 32-bit.
This is how you move existing code into static library. I use VS2015, it should be the same with VS2013, but I can't check that. I start with the following solution structure:
First thing to do is to add new project to the solution.
File -> Add -> New project -> Win32 Project
Check Static library and uncheck precompiled header
Then click Show all files icon in the solution explorer for both projects. This turn filters off and shows project folder as it is. It should look like this:
Drag and drop all needed files from one project to another:
Now reference your library. Uncheck Show all files icon to show References. Right click -> Add reference and check your static library project:
Last thing to do is to add include directory to the project that uses the library. This is done in project properties. Be sure to check All configurations and All platforms:
That's it. Now when you build your solution, VS builds your static library, builds your main project and links them together. The result should be identical as if everything is in the same project.
I wanted to have one project which would contain common header files that could be used by other projects in the same solution (Unfortunately I cannot accomplish this task). In order to accomplish this task here is what I tried
1-Created a new C++ console application called common.
2-From the properties of this project I changed the configuration type to static Library.
3-I added a simple header file commonheader.h to the project having a class person and built it as a result I got
C:\Users\Raj\Documents\Visual Studio 2010\Projects\Ctest\Debug\Common.lib
4-Now in order to use that header file from a different project I created another project
called Test. And in the properties of test I added Common as a reference
5-I then tried to access the person class however the VS2010 still complains that it cannot find the person class.
Any suggestions on what I might be doing wrong ? . I added the path
C:\Users\Raj\Documents\Visual Studio 2010\Projects\Ctest\Debug\ in addition include addition files of the Test project. Any ideas how I can access the person class
AFAIK the .lib files only contains the compiled source of your implementations, you still need to include the header files themselves to get access to the interface
I'm using Visual Studio 2010, with a lot of project and solution files. But now I find myself in a bit of dependency hell with ProjectReferences:
Project Simple produces a static lib.
Projects Foo and Bar depend on Simple, and also produce static libs.
Project Module depends on Foo and produces a DLL.
Project Module2 depends on Bar and produces a DLL.
So the dependency tree looks like this:
Simple
|
____________/ \__________
| |
Foo Bar
| |
Module Module2
With ProjectReferences, I can make Module depend on Foo and automatically link Foo.lib. This works fine.
But, is there a way for Module to automatically link in Simple.lib?
It seems like that should be possible. Module depends on Foo, which depends on Simple, so it seems like it should be able to have an option for "link in the output of my references and my references' references". But I can't find anything that lets me do that.
The "Link Library Dependencies" option doesn't do it. It only links in Foo.lib, and then I get a linking error about unresolved external symbols (symbols which are defined in Simple.lib).
Setting "Link Library Dependencies" to true for the Foo->Simple and Bar->Simple references seems to work at first, until you have a project that uses both Foo and Bar. That setting actually embeds Simple.lib inside of Foo.lib and Bar.lib, and then you get "symbol is already defined" errors if you try to use both Foo.lib and Bar.lib. And that's the correct error - I don't actually want to put Simple.lib inside of any other lib.
I can add a ProjectReferece from Module to Simple, but that's tedious to set in every project that uses Foo, and it's violating the encapsulation of Foo. Module should not need to know about Simple. Obviously the linker needs to know about Simple, but it should be able to figure that out by following ProjectReferences.
Here's why this matters: Suppose, during maintenance, a new project is created: Basic, which creates a static lib, and Simple depends on Basic. Now we have to update every single project that has a ProjectReference to Simple directly or through another ProjectReference (in this example it's only two projects, Module and Module2, but in reality it's dozens). That's tedious.
tl;dr Is there a way to automatically link in the static libs of my dependencies?
Apparently, this is a bug in Visual Studio 2010:
https://connect.microsoft.com/VisualStudio/feedback/details/638534/unresolved-externals-when-build-a-vc-project-with-chained-static-lib-dependencies#details
Unfortunately, Microsoft closed the bug as "fixed" -- which isn't quite true. It's more of a workaround, but it's not what I would consider a real fix. (A real fix would be a patch or a service pack, not something that needs to be manually tweaked on every machine).
The "fix" is to do the following:
Modify %ProgramFiles(x86)%\MSBuild\Microsoft.cpp\v4.0\Microsoft.CPPBuild.Targets
And change the line:
<Target Name="GetResolvedLinkLibs" Returns="#(LibFullPath)"
DependsOnTargets="$(CommonBuildOnlyTargets)">
To
<Target Name="GetResolvedLinkLibs" Returns="#(LibFullPath)"
DependsOnTargets="$(CommonBuildOnlyTargets);ResolvedLinkLib">
So, just add the ;ResolvedLinkLib part to that file. Then VS will link in dependencies of dependencies.
In my place we have a big C++ code base and I think there's a problem how header files are used.
There're many Visual Studio project, but the problem is in concept and is not related to VS. Each project is a module, performing particular functionality. Each project/module is compiled to library or binary. Each project has a directory containing all source files - *.cpp and *.h. Some header files are API of the module (I mean the to the subset of header files declaring API of the created library), some are internal to it.
Now to the problem - when module A needs to work with module B, than A adds B's source directory to include search path. Therefore all B's module internal headers are seen by A at compilation time.
As a side effect, developer is not forced to concentrate what is the exact API of each module, which I consider a bad habit anyway.
I consider an options how it should be on the first place. I thought about creating in
each project a dedicated directory containing interface header files only. A client module wishing to use the module is permitted to include the interface directory only.
Is this approach ok? How the problem is solved in your place?
UPD On my previous place, the development was done on Linux with g++/gmake and we indeed used to install API header files to a common directory is some of answers propose. Now we have Windows (Visual Studio)/Linux (g++) project using cmake to generate project files. How I force the prebuild install of API header files in Visual Studio?
Thanks
Dmitry
It sounds like your on the right track. Many third party libraries do this same sort of thing. For example:
3rdParty/myLib/src/ -contains the headers and source files needed to compile the library
3rdParty/myLib/include/myLib/ - contains the headers needed for external applications to include
Some people/projects just put the headers to be included by external apps in /3rdParty/myLib/include, but adding the additional myLib directory can help to avoid name collisions.
Assuming your using the structure: 3rdParty/myLib/include/myLib/
In Makefile of external app:
---------------
INCLUDE =-I$(3RD_PARTY_PATH)/myLib/include
INCLUDE+=-I$(3RD_PARTY_PATH)/myLib2/include
...
...
In Source/Headers of the external app
#include "myLib/base.h"
#include "myLib/object.h"
#include "myLib2/base.h"
Wouldn't it be more intuitive to put the interface headers in the root of the project, and make a subfolder (call it 'internal' or 'helper' or something like that) for the non-API headers?
Where I work we have a delivery folder structure created at build time. Header files that define libraries are copied out to a include folder. We use custom build scripts that let the developer denote which header files should be exported.
Our build is then rooted at a substed drive this allows us to use absolute paths for include directories.
We also have a network based reference build that allows us to use a mapped drive for include and lib references.
UPDATE: Our reference build is a network share on our build server. We use a reference build script that sets up the build environment and maps(using net use) the named share on the build server(i.e. \BLD_SRV\REFERENCE_BUILD_SHARE). Then during a weekly build(or manually) we set the share(using net share) to point to the new build.
Our projects then a list of absolute paths for include and lib references.
For example:
subst'ed local build drive j:\
mapped drive to reference build: p:\
path to headers: root:\build\headers
path to libs: root:\build\release\lib
include path in project settings j:\build\headers; p:\build\headers
lib path in project settings j:\build\release\lib;p:\build\release\lib
This will take you local changes first, then if you have not made any local changes(or at least you haven't built them) it will use the headers and libs from you last build on the build server.
I've seen problems like this addressed by having a set of headers in module B that get copied over to the release directory along with the lib as part of the build process. Module A then only sees those headers and never has access to the internals of B. Usually I've only seen this in a large project that was released publicly.
For internal projects it just doesn't happen. What usually happens is that when they are small it doesn't matter. And when they grow up it's so messy to separate it out no one wants to do it.
Typically I just see an include directory that all the interface headers get piled into. It certainly makes it easy to include headers. People still have to think about which modules they're taking dependencies on when they specify the modules for the linker.
That said, I kinda like your approach better. You could even avoid adding these directories to the include path, so that people can tell what modules a source file depends on just by the relative paths in the #includes at the top.
Depending on how your project is laid out, this can be problematic when including them from headers, though, since the relative path to a header is from the .cpp file, not from the .h file, so the .h file doesn't necessarily know where its .cpp files are.
If your projects have a flat hierarchy, however, this will work. Say you have
base\foo\foo.cpp
base\bar\bar.cpp
base\baz\baz.cpp
base\baz\inc\baz.h
Now any header file can include
#include "..\baz\inc\baz.h
and it will work since all the cpp files are one level deeper than base.
In a group I had been working, everything public was kept in a module-specific folder, while private stuff (private header, cpp file etc.) were kept in an _imp folder within this:
base\foo\foo.h
base\foo\_imp\foo_private.h
base\foo\_imp\foo.cpp
This way you could just grab around within your projects folder structure and get the header you want. You could grep for #include directives containing _imp and have a good look at them. You could also grab the whole folder, copy it somewhere, and delete all _imp sub folders, knowing you'd have everything ready to release an API.
Within projects headers where usually included as
#include "foo/foo.h"
However, if the project had to use some API, then API headers would be copied/installed by the API's build wherever they were supposed to go on that platform by the build system and then be installed as system headers:
#include <foo/foo.h>