Let's imagine this situation:
Project Foo compiles to Foo.dll and Foo.lib.
Project Bar compiles to Bar.dll and references Foo as a dependency in VS project.
Now the problem: Almost every time I change internal details (Not API, not set of exported functions) of Foo.dll - Foo.lib gets updated, and Bar.dll gets relinked with new Foo.lib. If I turn on detailed output in VS I see:
Source compilation required: input C:\PROJECTS\FOO\RELEASEUNICODE\FOO.LIB is newer than output C:\PROJECTS\BAR\RELEASEUNICODE\BAR.DLL.
And next command starts link.exe to link new Bar.dll
The question: Why does this happen? I'm not really familiar with idea of lib file for dll (I haven't seen .a file for .so dynamic lib in linux), but isn't the main idea of dll file is to avoid any compile-time linking? Why does the lib file change every time I change internals of foo.dll ? Is there a way to avoid relinking of dependant library? In my project I have dozens of dlls depending on foo.dll, and every time I change 10 lines of code in foo.dll - all these dependencies endup relinked, and this takes a lot of time.
MSBuild simply looks time stamps for when a file was modified. It isn't smart enough to know that no public API changed.
So the rule that msbuild operates by is, if an input is newer, the dependent (in your case bar) will have to be rebuilt (in your case simply relinked).
I supposed if msbuild knew about api changes, it would have to parse all the code and keep some sort of database of the entire code, something that for a build is mostly unnecessary and very costly.
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.
I need to build a DLL that can then be loaded with JNI from a java program. I was able to do this last year and it worked fine. I'm trying to recompile my same .cpp file now though that I make the dll with and it is failing because of an included dll dependency that gets brought in.
I have a c++ program that calls about 5 functions from some existing C++ code here. These functions are part of a huge codebase that are normally all linked together to build a set of 5 dlls.
I use dependency walker to view my dll and last year it compiled with just 2 dependent system dlls being put in my dll. Today I'm trying to recompile the same dll, but it brings in a 3rd dll file if I link with the .lib file from our existing codebase that contains the functions I use.
Basically I know my dll will work fine with JNI if I can avoid that 3rd dll showing up in my program. The problem is I don't know how to reference the functions I need in my code from our existing code base without linking to the lib file.
I can get this to work with standard c++ files and methods. This problem only happens when I reference this preexisting code from our huge codebase.
If I do not link my .obj file with a .lib file from our code I get unresolved reference messages from my Borland 5.5 compiler I have to use.
The overall issue is that my dll file works fine when I call it from a c++ exe file, but Java cannot handle something in it. Also, if I compile my code into a .so file in unix instead of a windows dll, Java JNI works fine and can load it. I know the problem is related to how Windows uses dlls, and I know if this 3rd dll doesn't load as part of my dll it will also work. I just have no idea what I did last year to build my dll without this 3rd one showing as a dependency.
If I comment out the functions from our existing code it compiles fine and loads because the 3rd dll dependency doesn't get put in my dll.
More Details
I had a message about missing _strcopy, so I linked in the cw32mti.lib file and that went away, but then that cw32mti.dll shows up in my dll file. How do I prevent the missing reference message for something like that and prevent it from putting the dll in my dll?
My link command looks like this.
ilink32 mydll.obj, mydll.dll,,cw32mti
The only way I get the other missing references to work is adding the other dll to my link command like:
ilink32 mydll.obj, mydll.dll,,cw32mti.lib other.lib
Where other.dll contains functions I call from mydll.dll such as calculate(int a, int b), so my code has a link it in like calculate(num1, num2); The problem is when I use the lib that contains the calculate method, it also brings in other dlls linked to the other.dll that I do not want to load. I need to be able to call calculate(num1, num2) without adding other.dll to mydll.dll. This worked before without dynamically calling calculate and using the getprocaddress type of coding.
Update - I eventually had to give up on getting the windows dll to work with the smartheap memory manager. Since this code was deployed in unix, I was able to just build the .so files and get those to work with JNI. For the Windows dll compile, I put some conditional compiler statements around the JNI code that was causing the smartheap dll to be loaded, so then when it compiles in windows it does not use that code. Instead I just had it print out a statement saying it was not executing in windows.
We also ran into issues later with getting our 64 bit JBoss server to run and load these 32 bit .so files. I ended up running a parallel JBoss server next to the 64bit one and called the methods that referenced the 32 bit library on the 32 bit instance of JBoss.
It may evolve into more later, but for now this task is working for us after months of trying many different things. I appreciate all of the help and input here.
If you can get your hands on the application DLL built from last year, use TDUMP to see what the module dependencies are. (You might have to analyze all the DLLs to get a good picture.) Then endeavor to reproduce that in the new DLL, probably by adjusting the linker's configuration .DEF file.
Without any code or .DEF file shown in your question, it is very difficult to be more specific.
Recently I discovered a problem on the midas and I fixed it, the problem now is that I want to use MidasLib not the midas.dll and with the source code I'm only able to build the DLL.
The source is C++ and I have very few knowledge with it. I know the MidasLib.pas uses internally midas.obj, so I need to create it to statically link the midas to my application. How to do it on C++ Builder? (XE)
When you compile C++ code, the compiler creates an .OBJ file for each .CPP/.C file you have and saves them somewhere on your computer. What happens in most cases is that one would run a linker on all of those .OBJ files to join them into a single EXE or DLL, but in your case you don't need those results. Your C++ Builder is, like most programming IDEs, automatically doing both the compilation and linking.
If you just want the .OBJ, you need to find where in your project folder C++ Builder is placing its .OBJ files (called its "intermediate output", typically, as it is the intermediate step between compilation and linking). So you must have a source file called midas.cpp or midas.c that produces a corresponding output file called midas.obj.
I have a project that uses a DLL that I have created. Everything works wonderfully, but I am now extending the library in the DLL to optimize some older functions.
What I was wondering is if I just modify the library to where only the main function body changes and nothing else can I just rebuild the DLL and replace it with the old one or is it because the function body changed I need to rebuild any projects that used this DLL.
The main reason I asked is because all of these projects have me referencing the .lib file and to be honest I am not sure what is exactly in a .lib file of a DLL project.
Any advice would be greatly appreciated.
Thanks
If you're just changing the functions to optimize them, without changing the function signatures, then you can just build your library and deploy it (replacing the old library).
However, if you need to change the function signatures then you can do one of (at least) two things:
Modify the code that's using your library to use the new function signatures.
If #1 is not an option, then consider leaving the old function and deprecating it. Applications with make use of your latest version will have to avoid using the deprecated methods.
You can read more about .lib/.dll here: http://www.screenio.com/tips/dll.htm
If you only change function bodies, and those functions are not template functions, and you compile the dll with the same compile options, as you did back then, you should be fine.
You might have to take care that both the dll and your executable use the same version of the Microsoft C++ Runtime Library. The version of it, that will be loaded, can be overriden by manifest files.
The .lib file lets you write code that uses your DLL as though it was a static library. Essentially it contains the declarations of all the functions in your DLL. It is generated whenever you build the DLL, but if you don't add (or remove, but you should never remove once you've deployed) a function, or change the signature of a function, then it won't change. You will also have a header file to tell the compiler what functions are in your DLL and this you will change by hand when you add a function or change the signature of a function.
If your only change is a bugfix (or perf improvement or whatever) to the actual code inside a function, you can get away with deploying only the updated DLL. For other changes you must deploy the lib and the DLL. If you've changed the signature of a function you'll have to deploy the new .h, change the calling code to call with the revised parameters, and then get the calling code recompiled. If you just added something you can get away with not rebuilding the calling code.
I have a (native C++) visual studio solution with several projects in it, some of them being DLLs. The dependencies of the projects on each other is fed into "Project dependencies". Whenever a DLL is being changed and re-built, regardless of wether this change affects other projects or not (that is, only the implementation and not the declarations are changed), The entire dependency tree from that DLL and up is being re-linked (not recompiled, however) whenever a dependent project is being built or tested as a build candidate, while this is completely unnecessary. If I would run the dependent project from outside VS prior to the whole re-linking proccess, it would run just fine as is.
Since the project is large this whole unnecesarry process takes a significant amount of time. Any way to fix this behavior?
If I understand what you are saying then you've rebuilt a DLL and are complaining that it is relinking anything that uses that DLL?
This sounds correct to me, if you've changed a DLL then you have to relink anything that uses it as it depends on it. I'm aware that you can change the implementation inside a DLL and if you are careful to keep the interface identical then you won't have to relink it, but VC++ like most build tools only goes on change times and the time of the LIB file for it surely has changed so the only safe thing to do is relink.
If you don't want this to happen then you probably need project A to link to fixed copy of the library for the DLL and not the one from the project
Well this is a typical VS behavior, when you "re-build a solution"... to overcome this "Build" the changed component rather than "Rebuilding" it and u should be fine. Or you can unload the projects/DLLs that you know they wont get changed and when rebuilding VS will only build the loaded projs and ignores the unloaded ones.
I'm not sure what you mean when you say "VS re-link and not re-compile", when you rebuild a solution, all projects are compiled and linked according to the dependency tree...