Okay so i am trying to convert some projects into DLL's. These are all visual studio 2008 projects, and are all written in C++.
We have 9 different projects(all under 1 solution in Visual Studio 2008). E.g.:
RasterTools\
RasterDataset.h
RasterDataset.cpp
Point.h
Point.cpp
<... insert like 50 more cpp files ...>
CoreTools\
Image.h
Image.cpp
CoreUtilities.h
CoreUtilities.cpp
<... insert more ...>
<... insert 7 or more projects ...>
Now the thing is certain projects use other project's classes. For example Image.h uses Point.h, and CoreUtilities.h has some functions for dealing with Points. What is the proper way to build a DLL when you have multiple projects that are all intertwined.
Basically we want to have the following:
CoreTools.dll
RasterTools.dll
<other projects.dll>
I understand how to handle the __declspec(dllexport) and dllimport fine, through macros. But when i attempt to build for example the CoreTools.dll i get linker errors where ever i use a class or functionality not contained within that project. For example when building coreTools.dll i get linker errors for any of the Point Class functions.
How can i deal with this?
EDIT
I tried this, and basically i noticed that almost all of the checkboxes were grayed out since its results in circular dependencies. :(
If you right-click on the project which throw ups the linker errors and choose 'Project Dependencies...' you'll see a list of all other projects in your solution.
Check the boxes next to the (DLL) projects you need to link with and Visual Studio will automatically link to it (and ensure the dependencies are built before the clients).
For each DLL you build you should also build a LIB. If Project B (B.DLL) references entries in Project A (A.DLL), then Project A is built first, it creates A.DLL and A.LIB, then Project B can add A.LIB to optional link libraries to resolve its references. Then C.DLL that depends on B.DLL can include in the link step B.LIB and so on and so forth.
At least this is what happens at the very low, build/make level. The dev environemnt may do all these under the covers for you if you choose the project dependencies right, as leegent suggests.
If you have circular dependencies between your DLLs, you'll have to resolve them by moving stuff around so that you get layered DLLs, with each DLL at a given level only using code from levels below.
Related
I use MSVC2019 for two C++ projects:
APP is a dynamic link library.
TEST is the automated test project.
TEST does not only perform tests on the API part of the DLL, but also on some non-published methods of APP ("unit tests"). Those methods are made visible to the TEST project by linking against the .obj files of the APP project.
Keeping this list of .obj files up-to-date becomes tedious lately. I wondered if there's a way to provide the list of files as input text file to the MSVC linker (see "Configuration Properties" -> "Linker" -> "Command line" -> "Additional options"). A script could generate the list of files easily and just pass it to the linker by piping from stdin.
My first attempt failed, simply adding "< myLinkerArguments.txt".
Example:
PATH_TO_LINKER\link.exe /ERRORREPORT:PROMPT /OUT:"G:\testproject\test_d.exe" < myLinkerArguments.txt
Any ideas if and how that's possible?
Thank you for reading,
Paul
According to the Microsoft documentation, you could try the following but different approaches:
The unit tests call non-member functions that aren't exported from the DLL, and the DLL can be built as a static library: Change the DLL project so that it's compiled to a .lib file. Add a separate test project that references the project under test.
This approach has the benefit of allowing your tests to use non-exported members, but still keep the tests in a separate project.
or
The unit tests must call non-member functions that aren't exported, and the code must be built as a dynamic link library (DLL): Add unit tests in the same project as the product code.
See https://learn.microsoft.com/en-us/visualstudio/test/how-to-write-unit-tests-for-cpp-dlls?view=vs-2022 for more information.
I would build a version of the DLL that is identical in every respect but which (also) exports the additional functions you want to test. Linking these in as separate object files sounds dangerous since then you have two copies - one in the .OBJ file and one in the DLL - and that might very well lead to trouble.
A practical way to achieve this is via a macro, let's call it EXPORT_FOR_TESTING, which can be #defined appropriately in the project file that builds the DLL.
So create yourself additional configuration(s) in there, one of which #defines EXPORT_FOR_TESTING as __declspec( dllexport ) and the other one can then define it as empty. After that, just link your test app with the test DLL and you're done.
Firstly, this is old code that I inherited and I would love to clean it up and make it perfect someday, but I cannot do that today. Therefore, I ask that answers like "rewrite the whole thing so that there are no circular dependencies" not be given.
I have a solution with 44 projects. Most of the projects build DLLs and a few build executables. There are multiple projects that depend on another project that, in one way or another, requires the first. Some are as simple as A requires B.lib and B requires A.lib and others are longer chains that loop back around.
When I inherited the code, it was not clean and there were old build files still amongst the source, namely .LIB files. Without removing those .LIB files all 44 projects are able to build and all of the old .LIB files are replaced with newly built files. This tells me that if I build a second time, none of the old .LIBs are being used and that all of my deliverables are now entirely generated from current source.
This leaves me with a problem: I wanted to clean out all none source files from version control, but if I do so, then I can no longer build the projects.
To further clearify, the projects that build DLLs create a .LIB file as an intermidiate step and these files are copied into a common folder that is listed in the "Additional Library Directories" property of each project and the individual .LIB files that are needed for a give project are in the "Additional Dependencies" property for that project.
Edit: I am not looking to do a major overhaul of the code. I know that all of the object files that all of the projects need are created. I also know that this structure is not optimal. I do, however, believe that if the linker knew where to look, it could find everything that is needed.
Extract just the parts from A that B requires into a new DLL 'C'. Then make both A depend on both B & C, whereas B just depends on C.
It's not going to be easy, but just keep extracting little bits at a time.
In C# it's pretty simple to add a project reference that will build the dependency, put the resulting assembly in the original's Debug/ directory and properly compile against that assembly.
So at the moment, I have a project with the Main() and a static library project in one solution. However, when I compile the Main() project and I look in the bin/Debug/ directory I don't find either the Static.lib file or the .obj files, which I think would need to be there, or something... I'm getting linker errors.
I think maybe I have to Configure the project to find the .obj and the .lib file produced by the static library project (which compiles fine, and actually produces those files.)
I'm missing something, and I'm not very well versed in Visual Studio with C++.
How do I add the reference in the Main project to use the library produced by the static library project?
The first thing you'll have to unterstand is, that static libraries are nothing like .NET assemblies. They are linked into the .exe and are not distributed as separate entity.
Your linker errors are most likely a result of you not linking to the library.
There are several ways to define libraries that have to be linked.
One is int the project settings under linker -> input -> additional dependencies,
the other would be the cheap route via #pragma comment(lib, "path to library")
You can add the name of the .lib files you need by going in project property->Linker->Input->Additional Dependencies
Then you will have to give the folder where your library is in VC++ Directories->Library Directerories.
Here is a very comprehensive answer: visual c++: #include files from other projects in the same solution
It describes the settings for the linker but also other essentials when referencing another C++ project. (especially when coming from C# but not being too versed in C++)
In .NET, one of design goals was due make this process a lot easier and automatic. Mission accomplished there.
In the native C++ world, the process is much more manual. Here is roughly my process for hooking up different modules together.
Include all relevant modules in the solution.
Set the output
directory of each project to the same directory. Either Right click
on each project, choose properties and in general, set the output
directory to: $(SolutionDir)\Bin\$(Configuration)\$(PlatformTarget).
For reduced headaches, Set this for all configurations and platforms.
Then all the files will be placed in somewhere like
\your-solution\bin\Debug\x64.
Set the project dependencies - Right click on each project that will be linking to another -> Choose Build Dependencies and select the referenced projects.
Set up the linking process, by Right clicking on the calling project and choosing
properties. Go to linker -> Input and add: $(SolutionDir)\Bin\$(Configuration)\$(PlatformTarget)\MyLibrary.lib
For the actual functions that are going to linked to, I set the
function declarations to something like (There are a lot of variations on the function declaration, a bit outside of the scope here):
#define DllExport __declspec( dllexport )
extern "C" void DllExport WINAPI` Testing();
In actual cpp file of the calling function, I add something like the following:
#include "..\MyLibrary\mylibrary.h"
Then in the actual calling function. simply add called function:
Testing();
If you are building multiple projects in the same solution, use a project reference to automatically link your libraries and executables together:
https://learn.microsoft.com/en-us/visualstudio/msbuild/common-msbuild-project-items?view=vs-2019#projectreference
which is explained pretty well here:
https://milania.de/blog/Project_references_in_Visual_Studio_and_C%2B%2B
The advantage to this approach, is that the build order will be correct. Using Additional Dependencies, as suggested in the other answers, will not maintain the proper build order.
I'm writing a program (in C++), which requires several VS projects, that I would like to put in the same VS solution. I'm using Visual Studio 2010.
Here is simply the wanted architecture : I'm using a 3rd party library (A) for my project, I have all the headers and .lib files, that I compiled with the source code.
With this library, I'm writing my own classes and function. That is my project (B).
Then I would like to develop two interfaces for the users: A command line interface (C1) and a GUI interface (C2), that are using the classes and functions defined in (B).
A <-- B <-- C1
<-- C2
I'm new to Visual Studio, and I don't know how to handle these dependencies properly.
Shall I use project dependencies (in the solution properties) or references (in the project properties) ? In fact, I'm not sure what dependencies and references are doing exactly.
Shall I compile B into some .lib library, or do something else ? If I do so, have to link only B.lib to my C1 and C2 projects, or should I also link A.lib (in other words, is the content of A.lib included somehow in B.lib ?).
And of course I would want the dependencies to be handle well, in order to always work with the up-to-date version of each project.
Is there a good way of doing it ?
Thank's in advance, and have a nice week-end :)
Yes. Use Project References.
Here is the official answer from Microsoft. While the page talks about .NET, its almost the same for native projects too.
TL;DR version:
Advantages of Project References:
They work on all development workstations where the solution and project set are loaded. This is because a project Globally Unique Identifier (GUID) is placed in the project file, which uniquely identifies the referenced project in the context of the current solution.
They enable the Visual Studio .NET build system to track project dependencies and determine the correct project build orders.
They avoid the potential for referenced assemblies to be missing on a particular computer.
They automatically track project configuration changes. For example, when you build using a debug configuration, any project references refer to debug assemblies generated by the referenced projects, while they refer to release assemblies in a release configuration. This means that you can automatically switch from debug to release builds across projects without having to reset references.
They enable Visual Studio .NET to detect and prevent circular dependencies.
Here is another nice article on Project Settings Changes in VS 2010 that also states that references are to be preferred over Project Dependencies. In fact, the article also says that the VS2010 solution converter automatically detects Project dependencies and changes them to Project references.
The policy at the company I work for is to use project references.
The project references are more useful since they keep the information of what projects a given project depends on with the project. If you then have to add the project to a new solution you do not have to go back to the old solution file to find out what projects a given project depends on.
I haven't worked much with Visual Studio before. I've started a personal project in my spare time and I would like to use test-driven development since it has been a huge benefit to me in my Java development. I started this project quite a while ago, and I used CppUnit. I know there are probably other frameworks that are better, but this is what's already in place.
My Visual Stuido 2005 solution has 2 projects in it. It worked fine when the unit tests resided right alongside the application code. As the project grew in size, this became quite cumbersome and inelegant. I created a new project under my solution to house the unit tests (so it now has 3 projects). Everything went fine until I tried to build the solution. Everything compiled, but the unit test project failed to link. The output gives me 51 "unresolved external symbol" errors (LNK2019) for what seems like every function that my tests call.
As far as I can deduce, the problem is the directory structure that Visual Studio creates. Each project gets its own directory, and then below that are the object files and executables that get created. I think the problem is that, while the header files are properly included in each unit test, the linker can't find the cpp files because they are in a different directory. When it fails to find the implementation of a called function, it gives me the 2019 error.
Am I right in my evaluation of the problem? How can I fix it? Do I need to completely reorganize my projects or is it a simple configuration of the linker?
Thanks
Yes, your evaluation sounds pretty good. Try this: In the solution explorer, right click the name of the project that contains your tests and choose "Project Dependencies". Put a check by every project that it is dependent on. That should set up the linker settings so it automatically can find the correct files.
It sounds like the functions/classes that your test project is using from your main projects aren't exported. If code isn't exported, then nothing outside of the DLL/exe that the code lives in can reference it.
A common way that we handle this is to add a define to the project (in the project settings, go to Configuration Properties -> C/C++ -> Preprocessor, the first line has the defines) called something like PROJECTNAME_IMPL (make sure you do this for both Debug and Release configurations!). Then there is a header file (called ProjectNameExport.h) that anything exported includes, which contains something like the following:
#ifdef PROJECTNAME_IMPL
#define PROJECTNAME_API __declspec(dllexport)
#else
#define PROJECTNAME_API __declspec(dllimport)
#endif
Then, when defining a class (for example):
#include "ProjectNameExport.h"
class PROJECTNAME_API Foo
{
};
This has the result of exporting the class when the header file is included in a file within the project, and importing the class when the header file is included in a file in another project (that links to the first project, of course).
I always add the code to be tested to a separate static .lib file, and have the main application EXE and unit tests EXE depend on this. New code is added the .lib project, and the dependency support ensure the EXEs link with no errors. You need to make sure the EXE projects can find the .lib headers, but this will depend on your directory structure. You also have to watch that that the .lib and the EXEs are using the same CRT/MFC library (for example, when using the CRT you can statically link with it or use a DLL).
I find using libs in this way easier to maintain than adding files/headers to multiple projects.
I am using the Boost test framework but I would structure this the same no matter the TDD framework.
A good article on a similar setup can be found here:
http://www.codeproject.com/KB/architecture/Designing_Robust_Objects.aspx