I have a C++ program that links Google's WebRTC library that compiles and runs successfully when I target 32-bit but doesn't work at all when I target 64-bit. After some trial and error I created the following program:
#include <media/base/adapted_video_track_source.h>
class AdaptedVideoTrackSource : rtc::AdaptedVideoTrackSource
{
public:
void AddRef() const {}
rtc::RefCountReleaseStatus Release() const { return rtc::RefCountReleaseStatus::kDroppedLastRef; }
bool is_screencast() const {return false;}
absl::optional<bool> needs_denoising() const {return false;}
bool GetStats(webrtc::VideoTrackSourceInterface::Stats* stats) {return false;}
webrtc::MediaSourceInterface::SourceState state() const {return webrtc::MediaSourceInterface::kLive;}
bool remote() const {return false;}
};
int main() {
AdaptedVideoTrackSource source;
}
This program fails with this error:
If I remove the super class the program runs fine.
How exactly do I debug a problem like this? I'm at a loss since I can't exactly debug the program. dumpbin appears to think my webrtc library is fine but says warning LNK4048: Invalid format file; ignored for my executable.
There's a lot of steps in the build process and I don't think I can put all of them here. I use CMake with ExternalProject_Add to download and build webrtc. I generate Ninja makefiles to build my code. Here are the ninja rules used to link the exe.
rule CXX_EXECUTABLE_LINKER__Test
command = cmd.exe /C "$PRE_LINK && "C:\Program Files\CMake\bin\cmake.exe" -E vs_link_exe --intdir=$OBJECT_DIR --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100183~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100183~1.0\x64\mt.exe --manifests $MANIFESTS -- C:\PROGRA~2\MIB055~1\2017\COMMUN~1\VC\Tools\MSVC\1416~1.270\bin\Hostx64\x64\link.exe /nologo $in /out:$TARGET_FILE /implib:$TARGET_IMPLIB /pdb:$TARGET_PDB /version:0.0 $LINK_FLAGS $LINK_PATH $LINK_LIBRARIES && $POST_BUILD"
description = Linking CXX executable $TARGET_FILE
restat = $RESTAT
build utest\Test.exe: CXX_EXECUTABLE_LINKER__Test utest\CMakeFiles\Test.dir\main.cpp.obj | <OTHER LIBARIES> || <OTHER LIBARIES>
FLAGS = /DWIN32 /D_WINDOWS /GR /EHsc /bigobj /Zi /Ob0 /Od /RTC1 -MTd
LINK_FLAGS = /machine:x64 /debug /INCREMENTAL /subsystem:console
LINK_LIBRARIES = <OTHER LIBARIES> webrtc_bundle.lib <OTHER LIBRARIES>
LINK_PATH = -LIBPATH:D:\Folder\install64\lib
OBJECT_DIR = utest\CMakeFiles\Test.dir
POST_BUILD = cd .
PRE_LINK = cd .
TARGET_COMPILE_PDB = utest\CMakeFiles\Test.dir\
TARGET_FILE = utest\Test.exe
TARGET_IMPLIB = utest\Test.lib
TARGET_PDB = utest\Test.pdb
It's private code so I renamed the executable I build and replaced the non webrtc libraries with <OTHER LIBARIES>.
This is the args.gn I use to build webrtc:
target_cpu="x64"
rtc_enable_protobuf=true
is_official_build=false
rtc_build_examples=false
rtc_include_tests=false
enable_iterator_debugging=true
is_clang=false
Also, I wrote my own BUILD.gn file to bundle webrtc with other libraries that Google's build system can build.
UPDATE
I found that I can manually link my obj files and make a perfectly good exe. Then I started going into the Ninja Makefiles generated by CMake and playing around with the linker rules. I found that if I remove /debug from the linker flags then everything works great. Of course, I want to be able to debug my debug builds.
I moved on and tried to start building my project with clang-cl and lld-link which provided a little more diagnostic output. I started getting warnings about linking different versions of the run time library. MSVC_RUNTIME_LIBRARY was correctly set and I had the /MTd flag in CMAKE_CXX_FLAGS and CMAKE_LINKER_FLAGS but by running ninja with the verbose setting I could see that my flags were being followed by /MDd which overwrote the previous runtime setting. Eventually I appended /MTd to CMAKE_CXX_FLAGS_DEBUG and CMAKE_CXX_FLAGS_RELEASE and now it's the last runtime flag in the compiler and link commands and I haven't had this problem since.
Related
I am trying to write a code using Google's OR-Tools library on Microsoft Visual Studio 2019. I followed the following steps:
Installed OR-Tools from Binary on Windows on their website.
Extracted the .zip file in C:\Libraries
Wrote my code on VS (I wrote #include <ortools/linear_solver/linear_solver.h> and using namespace operations_research; rest is usual C++ Code)
In Visual Studio, went to Project > Properties > C/C++ > Additional Include Directories
Added "C:\Libraries\or-tools\include" (which contains the folder "ortools" that I included)
Clicked Apply then OK then compiled my code.
I am getting a bunch of linking errors "error LINK2019". Is there anything else I should do so I can use this library freely on my machine?
From the supplied makefile:
Compile flags:
DEBUG = /O2 -DNDEBUG
CXXFLAGS = /std:c++17 /EHsc /MD /nologo /D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS -nologo $(DEBUG) \
/DPSAPI_VERSION=1 /D__WIN32__ /DNOMINMAX /DWIN32_LEAN_AND_MEAN=1 /D_CRT_SECURE_NO_WARNINGS \
/DGFLAGS_DLL_DECL= /DGFLAGS_DLL_DECLARE_FLAG= /DGFLAGS_DLL_DEFINE_FLAG= /DGOOGLE_GLOG_DLL_DECL= \
/I$(INC_DIR)\\src\\windows /I$(INC_DIR) /I. \
/DUSE_BOP /DUSE_GLOP \
/DUSE_CBC /DUSE_CLP \
/DUSE_SCIP
Link flags:
LDFLAGS = psapi.lib ws2_32.lib
OR_TOOLS_LNK = lib\\ortools.lib
The suggested way of building 7Zip is on the command line via the nmake command line utility. 7zip doesn't seem to come with a working visual studio solution.
I have seen invocations such as nmake NEW_COMPILER=1 MY_STATIC_LINK=1 suggested for initiating a build using the various nested .MAK files.
Using this command line interface how might I force a build with debug symbols?
If there is no standard way to accomplish this via nmake, I'd be glad to receive help with regards to 7Zip in particular. I am much less familiar with .MAK than GNU make, and have thus far been unable to find something akin to a "debug target" in the GNU make sense in 7ZIP.
To make a project that uses visual studio nmake build a debug output you need to edit the makefile and make 2 changes.
First you need to add /Zi to the list of flags used when compiling
CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -W4 -WX -EHsc -Gy -GR- -GF /Zi
Second you need to add /debug to list of options for the linker e.g.
LFLAGS = $(LFLAGS) -nologo -OPT:REF -OPT:ICF /DEBUG
I tested this on a different library, I assume there will be similarities here.
7zip archiver gives great compression and performance results, but unfortunately have lack of documentation nor for building process nor at the entire code.
I know that the question asked 1.5 yrs ago but I hope to save someone time for digging around in the 7z.
To build 7z from sources you need the Microsoft Visual Studio and do following steps:
Start Tools Command Prompt for VS 2019
Navigate to sources folder cd c:\sources\7z
Invoke nmake /f makefile
Otherwise you can convert MSVC 6.0 dsw/dsp files to modern .vcxproj format. Just open dsw file in the MSVC 2019 and it will do the conversion automatically.
The trick is that you need to navigate into project directory to do that. The 7z build system hard tied to relative directory structure and gets build parameters from top level main Build.mak file.
So, if you need to modify build parameters for all projects it is enough to modify that file.
For 7z version 19.00 you need to edit these lines in CPP/Build.mak file:
Add /Zi fag to line CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -W4 -WX -EHsc -Gy -GR- -GF /Zi
Add /DEBUG LFLAGS = $(LFLAGS) -nologo -OPT:REF -OPT:ICF /DEBUG
Change -O1 and -O2 for flags CFLAGS_O1 CFLAGS_O2
!IF "$(PLATFORM)" == "x64"
CFLAGS_O1 = $(CFLAGS) -Od
!ELSE
CFLAGS_O1 = $(CFLAGS) -Od
!ENDIF
CFLAGS_O2 = $(CFLAGS) -Od
I try to build static Boost library that will not depend on project runtime version (MT or MD). The only thing required to build such library is to add /Zl option to command line.
I edited tools/build/src/user-config.jam and specify compiler flags here:
using msvc : : : <cxxflags>/Zl ;
When I open rsp files generates by boost build system, I see /Zl flag here, for example, in regex.obj.rsp:
"libs\regex\build\..\src\regex.cpp" -Fo"bin.v2\libs\regex\build\msvc-14.1\release\address-model-64\link-static\runtime-link-static\threading-multi\regex.obj" -TP /O2 /Ob2 /W4 /GR /MT /Zc:forScope /Zc:wchar_t /favor:blend /wd4675 /EHs /Zl -c
-DBOOST_ALL_NO_LIB=1
-DNDEBUG
"-I."
So, for me it looks like the resulted library can link both /MD and /MT. However, it is not true:
libboost_regex.lib(regex.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MD_DynamicRelease'
This trick (with /Zl) works for me with zlib, openssl, libcurl, libsqlite3 and many other libraries; can anyone explain why does it not work with boost? Does boost somehow override /Zl option even it exists in rsp file and in user-config.jam, or why boost libraries require the same version of runtime even /Zl option is supposed to make it runtime-independent?
I am trying to compile this libevent2 package to Windows, but currently I can't because the configure script is a shell script (/bin/sh; can't be run in Windows).
Is there any way I can compile it or obtain a pre-compiled package? I currently have MinGW, CMake and MS C++ installed.
EDIT: I have managed to compile libevent2 using nmake Makefile.nmake but it hasn't produced any Windows binaries/libraries. Only .lib.
The makefile is as follows -
# WATCH OUT! This makefile is a work in progress. It is probably missing
# tons of important things. DO NOT RELY ON IT TO BUILD A GOOD LIBEVENT.
# Needed for correctness
CFLAGS=/IWIN32-Code /Iinclude /Icompat /DWIN32 /DHAVE_CONFIG_H /I.
# For optimization and warnings
CFLAGS=$(CFLAGS) /Ox /W3 /wd4996 /nologo
# XXXX have a debug mode
LIBFLAGS=/nologo
CORE_OBJS=event.obj buffer.obj bufferevent.obj bufferevent_sock.obj \
bufferevent_pair.obj listener.obj evmap.obj log.obj evutil.obj \
strlcpy.obj signal.obj bufferevent_filter.obj evthread.obj \
bufferevent_ratelim.obj evutil_rand.obj
WIN_OBJS=win32select.obj evthread_win32.obj buffer_iocp.obj \
event_iocp.obj bufferevent_async.obj
EXTRA_OBJS=event_tagging.obj http.obj evdns.obj evrpc.obj
ALL_OBJS=$(CORE_OBJS) $(WIN_OBJS) $(EXTRA_OBJS)
STATIC_LIBS=libevent_core.lib libevent_extras.lib libevent.lib
all: static_libs tests
static_libs: $(STATIC_LIBS)
libevent_core.lib: $(CORE_OBJS) $(WIN_OBJS)
lib $(LIBFLAGS) $(CORE_OBJS) $(WIN_OBJS) /out:libevent_core.lib
libevent_extras.lib: $(EXTRA_OBJS)
lib $(LIBFLAGS) $(EXTRA_OBJS) /out:libevent_extras.lib
libevent.lib: $(CORE_OBJS) $(WIN_OBJS) $(EXTRA_OBJS)
lib $(LIBFLAGS) $(CORE_OBJS) $(EXTRA_OBJS) $(WIN_OBJS) /out:libevent.lib
clean:
del $(ALL_OBJS)
del $(STATIC_LIBS)
cd test
$(MAKE) /F Makefile.nmake clean
tests:
cd test
$(MAKE) /F Makefile.nmake
A .lib file is a Windows binary file. It's a static library file, and is used by the linker in your application to statically link against (i.e. "use" in layman terms) the library.
Since libevent2 is not a program, you won't get a .exe output - it'll be either a big .dll + small .lib (for dynamic linking) or a big .lib (for static linking).
Use Cygwin to compile. It's a Linux emulation like.
I have a program which I would like compile using cl.exe on the command-line. This program depends on some boost libraries which I fail to link to.
The error I'm getting is:
cl /Fosamples\proxy\proxy.obj /c samples\proxy\proxy.cpp /TP /O2 /EHsc
/DBOOST_ALL_NO_LIB /DBOOST_THREAD_USE_LIB /DBOOST_SYSTEM_USE_LIB
/DBOOST_USE_WINDOWS_H /DTAP_ID=\"tap0901\" /D_WIN32_WINNT=0x0501 /MD /nologo
/Isamples\proxy /Iinclude proxy.cpp
link /nologo /MD /OUT:samples\proxy\proxy.exe /LIBPATH:samples\proxy
/LIBPATH:lib asiotap.lib libboost_system-vc100-mt-1_47.lib
libboost_thread-vc100-mt-1_47.lib ws2_32.lib gdi32.lib iphlpapi.lib
advapi32.lib samples\proxy\proxy.obj
LINK : warning LNK4044: unrecognized option '/MD'; ignored
asiotap.lib(bootp_builder.obj) : error LNK2001: unresolved external
symbol "class boost::system::error_category const & __cdecl
boost::system::system_category(void)"
(?system_category#system#boost##YAAEBVerror_category#12#XZ)
I compiled Boost, using the following command-line, from the x64 MSVC command prompt:
.\b2.exe install toolset=msvc --prefix=C:\Boost-VC-x64
If I look inside libboost_system-vc100-mt-1_47.lib I can see that:
?system_category#system#boost##YAABVerror_category#12#XZ
Is exported. But If you look closely it differs a bit from the one in my compilation errors:
?system_category#system#boost##YAAEBVerror_category#12#XZ // The symbol I miss
?system_category#system#boost##YAABVerror_category#12#XZ // The exported symbol
I guess I should either change Boost or my compilation options but fail to figure what to change exactly. Any clue ?
Thank you very much.
After some investigations, I realized that I compiled Boost for a x86 platform where I was linking with a x64 binary.
I thought that compiling Boost inside a Visual Studio x64 command prompt was enough but you actually have to specify:
.\b2.exe install toolset=msvc address-model=64 --prefix=C:\Boost-VC-x64
To make it work.