How to compile WebRTC properly with Visual Studio in debug? - c++

I'm trying to compile WebRTC, but because we use a number of libraries, some of which are closed source and beyond our control, how it gets compiled is rather sensitive to match. I've already had to edit the build/config/win/BUILD.gn script to use /MDd and /MD build flags instead of /MTd and /MT respectively, as we use the multi-threaded DLL runtime. To build, we run
gn gen out/Debug --args="is_debug=true is_clang=false use_lld=false visual_studio_version=2019"
ninja -C out/Debug
However, when linking against webrtc.lib, it fails with multiple errors citing a mismatch between _ITERATOR_DEBUG_LEVEL. I've seen this error plenty, it happens when linking a release-built library (_ITERATOR_DEBUG_LEVEL=2) with a debug executable (_ITERATOR_DEBUG_LEVEL=0). However that's clearly not how I've compiled it. I've tried adding /DEBUG (which should be implied by /MDd as far as I know) but it produces an identical library with the same issue. I've confirmed checking the generated .ninja scripts that these arguments are in the cflags.
Is there a way to get ninja to properly observe the debug flags?

I had the same issue. Although, WebRTC is a powerful library, it looks terrible for native development. Neither good documentation nor examples, especially for using outside Google sources.
Please, try this one argument, that helped me:
enable_iterator_debugging=true

I don't deal with libwebrtc myself, but I have heard that long term you might have a better experience pulling out all the files and using your own build system. Orchid did this, but I haven't looked at it myself.
There are other C/C++ WebRTC implementations if you are doing DataChannels only that might be helpful also!

Related

the meaning of visual studio /Z7 [duplicate]

Background
There are several different debug flags you can use with the Visual Studio C++ compiler. They are:
(none)
Create no debugging information
Faster compilation times
/Z7
Produce full-symbolic debugging information in the .obj files using CodeView format
/Zi
Produce full-symbolic debugging information in a .pdb file for the target using Program Database format.
Enables support for minimal rebuilds (/Gm) which can reduce the time needed for recompilation.
/ZI
Produce debugging information like /Zi except with support for Edit-and-Continue
Issues
The /Gm flag is incompatible with the /MP flag for Multiple Process builds (Visual Studio 2005/2008)
If you want to enable minimal rebuilds, then the /Zi flag is necessary over the /Z7 flag.
If you are going to use the /MP flag, there is seemingly no difference between /Z7 and /Zi looking at MSDN. However, the SCons documentation states that you must use /Z7 to support parallel builds.
Questions
What are the implications of using /Zi vs /Z7 in a Visual Studio C++ project?
Are there other pros or cons for either of these options that I have missed?
Specifically, what is the benefit of a single Program Database format (PDB) file for the target vs multiple CodeView format (.obj) files for each source?
References
MDSN /Z7, /Zi, /ZI (Debug Information Format)
MSDN /MP (Build with Multiple Processes)
SCons Construction Variables CCPDBFLAG
Debug Info
Codeview is a much older debugging format that was introduced with Microsoft's old standalone debugger back in the "Microsoft C Compiler" days of the mid-1980s. It takes up more space on disk and it takes longer for the debugger to parse, and it's a major pain to process during linking. We generated it from our compiler back when I was working on the CodeWarrior for Windows in 1998-2000.
The one advantage is that Codeview is a documented format, and other tools can often process it when they couldn't deal with PDB-format debug databases. Also, if you're building multiple files at a time, there's no contention to write into the debug database for the project. However, for most uses these days, using the PDB format is a big win, both in build time and especially in debugger startup time.
One advantage of the old C7 format is that it's all-in-one, stored in the EXE, instead of a separate PDB and EXE. This means you can never have a mismatch. The VS dev tools will make sure that a PDB matches its EXE before it will use it, but it's definitely simpler to have a single EXE with everything you need.
This adds new problems of needing to be able to strip debug info when you release, and the giant EXE file, not to mention the ancient format and lack of support for other modern features like minrebuild, but it can still be helpful when you're trying to keep things as simple as possible. One file is easier than two.
Not that I ever use C7 format, I'm just putting this out there as a possible advantage, since you're asking.
Incidentally, this is how GCC does things on a couple platforms I'm using. DWARF2 format buried in the output ELF's. Unix people think they're so hilarious. :)
BTW the PDB format can be parsed using the DIA SDK.
/Z7 keeps the debug info in the .obj files in CodeView format and lets the linker extract them into a .pdb while /Zi consolidates it into a common .pdb file during compilation already by sync'ing with mspdbsrv.exe.
So /Z7 means more file IO, disc space being used and more work for the linker (unless /DEBUG:FASTLINK is used) as there is lots of duplicate debug info in these obj files. But it also means every compilation is independent and thus can actually still be faster than /Zi with enough parallelization.
By now they've improved the /Zi situation though by reducing the inter-process communication with mspdbsrv.exe: https://learn.microsoft.com/en-us/cpp/build/reference/zf
Another use-case of /Z7 is for "standalone" (though larger) static libraries that don't require shipping a separate .pdb if you want that. That also prevents the annoying issues arising from the awful default vcxxx.pdb name cl uses as long as you don't fix it with a proper https://learn.microsoft.com/en-us/cpp/build/reference/fd-program-database-file-name, which most people forget.
/ZI is like /Zi but adds additional data etc. to make the Edit and Continue feature work.
There is one more disadvantage for /Z7:
It's not compatible with incremental linking, which may alone be a reason to avoid it.
Link: http://msdn.microsoft.com/en-us/library/4khtbfyf%28v=vs.100%29.aspx
By the way: even though Microsoft says a full link (instead of an incremental) is performed when "An object that was compiled with the /Yu /Z7 option is changed.", it seems this is only true for static libraries build with /Z7, not for object files.
Another disadvantage of /Z7 is the big size of the object files. This has already been mentioned here, however this may escalate up to the point where the linker is unable to link the executable because it breaks the size limit of the linker or the PE format (it gives you linker error LNK1248). It seems Visual Studio or the PE format has a hard limit of 2GB (also on x64 machines). When building a debug version you may run into this limit. It appears this does not only affect the size of the final compiled executable, but also temporary data. Only Microsoft knows about the linker internals, but we ran into this problem here (though the executable was of course not 2gigs large, even in debug). The problem miraculously went away and never came back when we switched the project to /ZI.

Debugging C++ Library

I've been working on adding functionality to a C++ library. The library is compiled by using CMake. It has a complex set of dependencies. I have a C++ test file that runs code relating to the library. Let the compiled file be test.cpp, its executable test.
So far, I've been debugging by adding "cout" statements to the library files. I frequently get segmentation faults, but can usually figure it out by inspection. Obviously, this is inefficient. I want to see where the code fails, by using gdb. Via this stackoverflow post, I tried adding debug flags to my cmake, but when I run gdb on test and do bt, I don't get comprehensive info. I simply get the name of the function in the library where the code fails, not the exact line.
Anyone know how to get the gdb information?
While adding the respective compiler flags manually will work, it is not the most convenient way of doing so. As suggested by #ruslo, you should use the following command line instead for getting debug support:
cmake -DCMAKE_BUILD_TYPE=Debug <path_to_source>
There are several reasons for this:
Compiler flags are not portable. -g -O0 will work on gcc, but what about other compilers? One of CMake's main strengths is to make portability easy, so you should not throw it out of the window easily.
Multi-configuration generators (like most IDE generators) allow to use multiple profiles at once. You would not want to force users of those IDEs to compile without optimizations even though they selected a Release profile, would you?
Changes to CMAKE_CXX_FLAGS are global. This becomes especially nasty once you have to compose multiple projects together. If you absolutely need to manually give compiler flags, use target_compile_options for this purpose.
Last but not least: Setting CMAKE_BUILD_TYPE is the idiomatic solution to this problem. It is the one right tool for solving it and people familiar with CMake (granted, there are not too many around of those...) will be surprised if you solve it using a non-idiomatic workaround.
I've figured it out. They key is to add the "-g" flag to
SET (CMAKE_C_FLAGS ...
and
SET(CMAKE_CXX_FLAGS ...
to the CMakeLists.txt file.

SDL2, error LNK2005 objects already defined in libcmt

So this is a common error but all the posts say I need to pay more attention to which versions of libraries I'm including. I'm using SDL2, OpenGL, and SDL_Mixer... I don't have any options in what I include except to stick with 32-bit libs.
Debug compiles fine but release gives me the LNK2005 error unless I set runtime libraries to /MD. I'd like to avoid that extra dependency. The resulting executable stops responding on SDL initializations or some OpenGL calls unless Visual Studio launches the release build. So I've got some kind of multi-threading issue but I'm not close to understanding it. Little help?
UPDATE: /FORCE:MULTIPLE allows the project to be compiled with /MT. But just like with /MD, the resulting executable crashes unless visual studio launches the release build. What does that mean?
UPDATE2: Use /MD in SDL projects. Crash was just a memory error the debugger wasn't catching. Linking was unrelated.
Ok, so your only other options I see are
(1) ignoring the other library that is causing the LNK2005 error (since you are defining something in two places, it doesn't know which one to use. Since ignoring libcmt.lib caused a lot of issues, maybe try the other place that defines the method).
2) Use /FORCE:MULTIPLE in your linker command line options, which will have it allow multiple definitions of a symbol.
Is rebuilding SDL an option? If so
get the source from libsdl.org
go to the VisualC directory
select the relevant solution
from there, for each of the projects, change the build type from /MD to /MT
rebuild: you should now just get a lib and DLL which are built as /MT and should link with your program compiled as /MT. You should no longer have to resort to /ignorelibs and /forcemultiple

How to build and link LuaJIT statically (VS 2013)

Premise : I'd like my C++ application not to depend on whatever Microsoft Visual C++ redistributable, so I can ship my executable file that will work out of the box.
What I've done first : switching the runtime library to Multithread (/MT) from DLL Multithread (/MD) in order to avoid the need for msvcr110.dll (and shouldn't VS 2013 require the 120 version, as it's the compiler version ?). To do that I also had to recompile another library I'm using with the same runtime library, and that worked. I had my .exe which could be ran anywhere without problems (or I wasn't aware of, haha).
Then I added some functionalities that make use of LuaJIT. I've built LuaJIT by the msvcbuild.bat provided with the package and it worked like a charm, but now my executable requires the msvcr110.dll to run. I guess that's because LuaJIT was compiled with the /MD flag, but I'd like to know if there is a proper way to do what I want.
You should run msvcbuild.bat with static command line parameter.
I didn't test this, but you most likely need to use the /MT flag on each piece of the compilation you do. In this case, both your main program, and LuaJIT. In that msvcbuild.bat file (https://github.com/luvit/luajit-2.0/blob/master/src/msvcbuild.bat) you can see that they are explicitly specifying /MD (line 17). Methinks that is your problem. Change it to /MT and see.

CMake link stage question

I am currently building a rather large application, using cmake to generate cross platform build scripts. During this process of putting together the cmake build scripts, I have discovered the pain of gcc link line ordering.
The basic issues is that including static libraries in the wrong order leads to unused library symbols being thrown away that then cannot be found by subsequent dependent libraries.
Thus, I am in the situation where cmake generates a visual studios build system that compiles just fine, but the unix makefiles throw all kinds of "undefined symbol" errors. I have figured out a work around for this - in the add_executable command, I am including the static libraries twice.
My hope is that there is a more standard/better way to deal with this issue. Being that I am not the only developer, and that the majority of regular development is done in windows, I really want a link-order agnostic CMake script. The windows developers just don't deal with this link order issue. On top of that, figuring out the correct order would be very difficult - I do not have that information readily available and there are a lot of static libraries (70 or so).
After searching the internet, I did learn about the -static and -dynamic flags, but getting CMake to include them is non-obvious and gcc complains about not being able to find the dynamic libraries.
Anyway, I welcome suggestions on how to do the right thing.
Did you try disabling the strip? Maybe with something like cmake -DCMAKE_STRIP=/bin/true ..? Maybe that will stop the symbols being thrown out.
I think this is less of a CMake issue, and more of a GCC behavior. This question/answer should help out a bit:
Linker order in GCC
You will have to bite the bullet and modify your CMakeLists.txt files to link properly on Linux. Since the Windows developers don't care, you shouldn't disturb them.
Best,
-dan