How to get object file to link first? - visual-c++

I'm trying to compile a Windows DLL for code originally intended for a Unix platform. One problem I have is that Windows fopen() defaults to O_TEXT, but Unix defaults to O_BINARY.
Windows recommends two ways to solve this:
Use _set_fmode() function, didn't work for me probably because I could not call it from correct context.
Link with binmode.obj object file. This file is included with the compiler, and the compiler knows where to look for it.
The latter worked for my own code, but it does not seem to work for third party static libraries. Looking at the linker output, I can see that static libraries are included before binmode.obj, but binmode.obj was included before my own object files.
The real solution should be to persuade all external libraries to include binmode.obj, but this is somewhat non-trivial and might incur significant maintenance overhead in the future.
So I'd like to try to move the binmode.obj to the beginning of the linker command line, but this proved to be surprisingly difficult. I've tried:
target_link_libraries( mylib PRIVATE binmode.obj ) - Got correct position, but got renamed to binmode.obj.lib casuing linker error.
Tried making a static library with binmode.obj as a pre-compiled object, but got an error that the file has a relative path. I have no idea how to make it a full path.
Tried adding it as a linker flag in different ways, even including using toolchain file, but it all ended up with binmode.obj being placed after libraries.
I'm now out of ideas and feel I need help with this. Any suggestions how to fix this?

#fabian's comment made me read the right part of CMake documentation, which made me realize that UNKNOWN library type could be used. Using the following code in CMake I could make binmode.obj appear before all libraries:
add_library( binmode_obj UNKNOWN IMPORTED GLOBAL )
set_target_properties( binmode_obj PROPERTIES IMPORTED_LOCATION binmode.obj )
target_link_libraries( mylib PUBLIC binmode_obj )
This solved my problem of trying out if link binmode.obj before libraries might fix my original problem. It didn't, unfortunately. But that is another problem...

Related

Why would a linker try to link to a file I never told it to link to?

I'm getting a linker error indicating that the linker was unable to open a file (a static library) and therefore it fails. I am having a very difficult time troubleshooting this error because I never told the linker to link to the file which it is failing to open.
I am telling the linker to link to several static libraries. Many of the libraries I am linking to are wxWidgets static libraries. I don't need ALL of the modules from wxWidgets, so there are some which I am linking to and many which I am not. The file which the linker can't open is 'wxbase31ud_net.lib'. Like I said, that file is not among the libraries I am linking to. My immediate thought was that this dependency was being introduced implicitly somehow, perhaps by one of the wxwidgets libraries I WAS linking to. I didn't think static linkage worked this way but I didn't have any other ideas. I have been investigating that possibility and I've found nothing which indicates that is the case.
I set the build output verbosity to maximum, and the 'wxbase31ud_net.lib' is never mentioned anywhere until the error is reported.
I confirmed in my cmake project that the file in question was never passed back to me from the FindWxWidgets module, and was never referenced in any of the lists of files I associate with the target.
I grepped through the entire project directory and found no reference to the file anywhere, including the cmake-generated project files (visual studio project files).
What could be causing the linker to try and open this file?
Edit: Also, to be clear, the error I'm seeing is LNK1104
it's probably from a #pragma comment(lib,"???") except in the case of wx the argument to the pragma may be complex macros and it will be difficult to grep. This particular one may be from setup.h with #pragma comment(lib, wxWX_LIB_NAME("base", "")). You should be solving this by adding the directory with the wx libs to the linker's search directories.
The answer by zeromus is correct, this is almost certainly indeed due to including msvc/wx/setup.h which contains #pragma comment(lib)s. Possible solutions:
Simplest: build all the libraries, this will solve the errors and it's not a problem to link with a library you don't use.
Also simple but slightly less obvious: predefine wxNO_NET_LIB when building your project, this will prevent the file above from autolinking this particular library. You may/will need to define more wxNO_XXX_LIB symbols if you're missing other libraries, of course.
Less simple but arguably the least magic too: stop using $(WXWIN)/include/msvc in your include path, then wx/setup.h under it won't be included and nothing will be linked in automatically. The drawback is that you will have to specify all the libraries you do need to link with manually.

Executable exporting symbols BUT not getting exported as they are unreferenced by the executable itself

I have a particular use case where executable needs to export certain symbols, which are imported and used by the dynamically loaded DLLs the executable loads on runtime.
The executable links with some static libraries, which actually have symbols that are exported while the DLLs use these static libraries headers to import those symbols.
If these symbols are not used or un-referenced in the executable, then the linker removes them and hence they do not get exported and hence not available for DLLs at load time.
This i solved on GCC / clang using --whole-archive and -force_load option respectively.
What about MSVC on windows? I use __declspec(dllexport) and __declspec(dllimport) for exporting and importing symbols on windows.
EDIT:
For code reference, you can find the code here: https://github.com/hunkabhicupid/exeexport
The issue is something similar to these posts 1, 2 BUT the answers to these posts did not help me find a solution or i did not find them useful.
Problem: On windows, STATIC LIB which contains an OBJ file that has a function marked __decl-spec(dll¬export) but if the same is not used in the EXE, function does not get exported from the EXE. On other platforms also we have the same problem BUT there we have compiler options like --whole-archive / -force_load, do make it work.
Links:
Link1
Link2
Only solution that come to my mind is to not create STATIC libs, rather include all code (static LIBS) in the executable then:
1. It works on Windows
2. It works on Linux without --whole-archive
3. It works on Mac OS X without -force_load
4. We also need not worry about if 2 & 3 include the dead code, exe bloat etc.
This is the only solution till the linkers become smart and throw out every unused symbol, except those marked specifically for external consumption i.e. marked to be exported.
Does dumpbin /exports {dll} show you the exports properly? Perhaps you should try dumpbin /exports {import lib}?
Based on the info so far I'm guessing the problem is not that the symbols are not exported but rather one of build order. If you get 'unresolved externals' when linking the dll, it seems you expect the exe-exported symbols to be resolved by the linker when linking the dll, but the exe is not built yet. (you probably wired it to reference the dll, so it builds only after the dll is linked).
One way to go about it is to have the dll LoadLibrary the exe and GetProcAddress the functions you want - but that really is a contrived way to achieve what you're after. If these symbols are defined in a static library, why not have both the exe and the dll link against it?

Including libraries inside libraries

I've looked around (including StackOverflow), but the only question close to mine, as far as I can tell, is specific to Windows distributables, which doesn't apply to me.
I want to release a library: MyLibrary.lib
It uses some third-party libraries, for instance, ZMQ
I've included the third-party library into MyLibrary both with either #pragma or actually adding it to the project.
Either way, MyLibrary.lib compiles fine and creates a .lib file
HOWEVER.
An executable that is linked to MyLibrary complains at link time that it can't find the referenced ZMQ functions, as if ZMQ is not incorporated into MyLibrary.
Looking at MyLibrary with a hex editor it doesn't seem like ZMQ.LIB was incorporated. There are references to it but it seems "weak linked". I don't see the ZMQ code in there.
Alternatively, if I can get the application/executable to build and run it, it'll complain at runtime that it can't find zmq.dll.
Either way, it's obviously not in "MyLibrary".
How can I get a library to include other third-party libraries, so I don't have to distribute a bunch individually? What step am I missing?
Using MSVC2013
Thanks
Although I had the .lib I needed, it turns out it was an import lib, and the .dll was distributed elsewhere. I found the .dll and now it works. Thanks to all who responded.
What about the flags described in this article:
https://msdn.microsoft.com/en-US/library/2kzt1wy3%28v=vs.120%29.aspx
Can they help you?

How to know when to use the .a or .so when linking to Boost?

I wanted to try out the Boost::Serialization library for a project I'm working on. I'm also trying to get used to programming in Linux as well. I set up boost in its default locations. I tried compiling the test file they provide here with the command line arguments they provide and it worked fine. In this example they use the .a file.
Then I went to the Serialization page and tried running one of the serialization demos. I ran basically the same commands, except I swapped out the file names and linked against libboost_serialization.a instead of libboost_regex.a, but I got a bunch of errors. After playing with different options and double checking the directories I finally got it to work by replacing the .a with the .so file.
Just for reference, what finally worked for me was this:
g++ /usr/local/lib/libboost_serialization.so sertest.cpp -o sertest
How come for one example I linked against the .a file, and in the other I had to link against the .so?
Because when linking statically, the order in which you specify the libraries and object files does matter. Specifically, a library must be mentioned after object files that use symbols from it.

How can I force MSVC++ to ignore CRT dependencies of a static library?

I don't know if it's possible to do this, but I would like the /NODEFAULTLIB to be applied to a static library project.
I have many application projects (A.exe, B.dll, C.dll) that use a common static library D.lib.
This library has a lot of code and also has other .lib dependencies as well. One of them is the openssl library, which seems to have been built for win32 against the Release version of the CRT (i don't have the original project/sources).
So far, to avoid the mixing of the Release/Debug versions of CRT, I have to put the /NODEFAULTLIB:msvcrt.lib linker directive in all leaf projects (A.exe, B.dll). This works but I think it's not the ideal way of dealing with that issue.
I tried to put this property in D.lib project, but it has no effect.
Is there a way to force msvc++ to ignore the msvcrt.lib dependency from the 3rd party library?
A .lib does not have any linker settings because you don't link it, you link to it. A .lib is just an archive of .obj files, sort of like an uncompressed .zip file - that's why you have to put the setting on all projects that link to it.
If you're using VS2005+ you could use property sheets so that you only have to put the setting in one place and then use that property sheet in all projects.
However, OpenSSL is just that - Open Source, so you should be able to get the source for the version you are using and build it again (and add it to your version control system of course). I thought OpenSSL could be built as a DLL or LIB, which would solve your problem as the DLL would not interfere with the linking of your code.
Failing that, you always have the option of slitting your functionality out into a separate DLL so that you only have issues with one project.
To prevent your distributed static link library from depending on a specific MSVC runtime library you need to set this compiler option (in Visual Studio 2010 it looks like):
Configuration Properties -> C/C++ -> Advanced -> Omit Default Library Name = Yes (/ZI)
Now your users can link to your release built static lib from their debug build and not try to link to the incorrect runtime library causing problems, as well as linkers warnings.
Note that may cause link errors if your library actually depends on a specific runtime library or its behavior, and compatible components are not provided in some other way.
My understanding is that if library LIB in linked statically into a DLL, the DLL contains already all relevant code from LIB. Therefore, this coupling cannot be removed. This is just based on my understanding of statical linking, not on experiments.

Resources