Waf PDB output in Windows (MSVC toolset)? - windows

I used to use GDB + Clang, and I'm realizing how much I took stack traces for granted.
How does one have Waf generate PDB output in the directory of a built executable?
My configuration passes /Zi and /debug flags to the compiler/linker, but the only pdb file I'm seeing (for any of my several binary outputs located in subdirectories of my build directory) is a vc110.pdb file in the root of the build directory (and no, there's no executable binary of any kind in the root of my build directory).
Extra information available on request - even after some Googling and other info-finding tasks I'm just not sure what would be useful for me to put down at the moment (as in, I'd probably need to dive into the Waf code to know what the heck to put down...).

The debugging database is only generated my Visual Studio if you request it. Run the build again with python waf.py -v -v build to see what switches Waf sends to VS.
link.exe should be given /DEBUG and to cl.exe /Zi and /FS. You set them in your wscript using:
def configure(ctx):
...
ctx.env.CXXFLAGS += ['/Zi', '/FS']
ctx.env.LINKFLAGS += ['/DEBUG']

Related

How to build Qt5 as static libraries under Windows

To distribute a Qt appication to Windows users as a simple .exe file, one would need to link statically with a static version of Qt libraries. Assume we distribute our license under an open license so that static linking of Qt is allowed. So we just need static library binaries of Qt5Core, Qt5Gui, Qt5Widgets. How to get them?
The binary distribution of Qt5 comes with dynamic libraries only. It contains some .lib files as well - but beware, these are not the static libraries, but some auxiliary files. They can be distinguished from true static libraries by their size: true static libraries are much bigger (many MB in the case of Qt5 components). So we need to statically compile Qt5 ourselves. This turns out to be surprisingly difficult.
The official instructions (http://doc.qt.io/qt-5/windows-building.html) are almost useless: Way too short, they do not even convey an idea of the difficulty of the task. A precise, up-to-date, step-by-step guide how to compile Qt5 into static libraries is currently missing. We should have it here.
The short answer: Don't waste your time on this. Link dynamically, and let an installer distribute your application. This is the only mode that is seriously supported by Qt5 and by CMake. Working without their support and against their advise is close to hopeless. Setting up an installer is far easier (though no fun either - we currenly use black magic from https://hk.saowen.com/a/d1cf90fcfea6d511629fd5a6c8113808721a7f19656677e8a5fab370a8d35cd4).
The long (yet incomplete) answer, in case you want to outsmart me:
The following steps brought me deceptively close to a solution. I succeeded in building static libraries, but I failed to link my application: Upon getting hundreds of LNK2001 and LNK2019 errors caused by cryptic unresolved external symbols, I had to give up.
So here comes a step-by-step description of what worked for me in October 2018 on a Windows10 virtual desktop. For each installation step, a check is indicated. If a check fails then fix the problem before proceeding further.
To start, install some tools that are needed later on:
Perl, needed for zlib and openssl configuration:
Skip if "perl -v" works.
Get installer from https://www.activestate.com/activeperl
Run installer -> will install to C:\Perl64.
Check: Restart terminal and try "perl -v".
An editor that can handle Unix end-of-line. Notepad won't do. Install vim, emacs, or whatsoever.
chocolatey package manager, needed to install flex and bison:
Run admin shell (Circle Menu > search for "Command" > right-click on "Command Prompt" > run as Admin)
Copy download command from https://chocolatey.org/install#install-with-cmdexe
Paste command to admin shell, and watch installation
Check: in terminal, try command "choco"
flex and bison, needed by qtbase compilation:
It's not obvious to get the right version of flex. From gnuwin32.sourceforge.net I got an outdated flex that missed a command-line argument required during Qt compilation. Compiling flex from source introduces a tail of further dependences. The simplest solution I found uses the Chocolatey package manager.
In admin shell, run: "choco install winflexbison3". This creates a directory X that contains the binaries win_flex.exe and win_bison.exe and a supporting "data" folder. Find out the location of X. In my case, X=C:\ProgramData\chocolatey\lib\winflexbison3\tools
Check: cd X, and run "win_flex --version", "win_bison --version".
During Qt compilation, these tools will be needed under their standard names "flex" and "bison". Therefore we need symbolic links flex->win_flex, bison->win_bison.
mlink X\flex.exe X\win_flex.exe
mlink X\bison.exe X\win_bison.exe
note: mklink needs absolute paths to work reliably
note: the symlink must not go to another directory lest bison won't find the "data" folder
Add X to the %PATH%
Check: in any shell, try "flex --version" and "bison --version"
So far for the tools. Now we need two libraries that must be statically linked to Qt (magic learned from https://stackoverflow.com/a/41815812/1017348):
Build static zlib:
Download https://zlib.net/zlib1211.zip
Unpack to C:\Development\zlib-1.2.11
Edit the file win32\Makefile.msc with an editor that can handle Unix EOLs:
Find the line starting with CFLAGS
Replace -MD with -GL -MT -Zc:wchar_t-
Find the line starting with LDFLAGS
Replace -debug with -opt:icf -dynamicbase -nxcompat -ltcg /nodefaultlib:msvcrt
Build zlib using the following command (should take less than a minute):
nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF -DNDEBUG -I." OBJA="inffasx64.obj gvmat64.obj inffas8664.obj"
Check: as a result, the source directory must contain zlib.lib (856kB), inter alia.
Build static openssl library:
Download https://www.openssl.org/source/openssl-1.1.1.tar.gz
Unpack to C:\Development\openssl-1.1.1
Copy files from zlib: cd zlib-1.2.11; xcopy zconf.h ..\openssl-1.1.1\ ; same for zlib.h zlib.lib zlib.pdb
cd ..\openssl-1.1.1
perl Configure VC-WIN64A no-asm no-shared zlib no-zlib-dynamic threads --prefix=C:\opt\local_x64
note: I added "no-asm" to avoid installation of NASM (Netwide Assembler)
note: I changed prefix, since only admins can install to C:\Windows
Edits the file ''makefile'':
Find the line that starts with: CFLAG
Append: /Zc:wchar_t- /GL /Zi
Find the line that starts with: LDFLAGS
Replace /debug with /incremental:no /opt:icf /dynamicbase /nxcompat /ltcg /nodefaultlib:msvcrt
Find the line that starts with: CNF_EX_LIBS
Replace ZLIB1 with zlib.lib
Build: "nmake"
Check: directory must contain openssl.lib (size?)
Now we are ready to build qtbase from source, using the command-line version of the Visual Studio C++ compiler:
Download (update location for latest Qt): https://download.qt.io/archive/qt/5.11/5.11.2/submodules/qtbase-everywhere-src-5.11.2.zip
Unpacking takes ca 20'
Move the source directory to the Local Disk (C:\Development)
To work with Visual Studio, use a specially configured terminal. Use Taskbar>Circle>Search to launch "x64 Native Tools Command Prompt for VS 2017"
cd qtbase...
Check: configure --help
configure -platform win32-msvc2017 -opensource -confirm-license -release -static -openssl-linked no-dbus -no-libpng -no-libjpeg -nomake examples -nomake tests -prefix C:\opt\local_x64 -I C:\Development\openssl-1.1.1\include -L C:\Development\openssl-1.1.1 -D OPENSSL_LIBS=C:\Development\openssl-1.1.1\libssl.lib
while debugging "configure", it may be necessary to delete config.cache.
option -I does not work with relative paths
the label "win32" may look wrong if we want to use Qt in a 64bit application, but we are advised not to worry: building Qt under Windows: really with "-platform win32-msvc2017"?
I don't know how to get rid of Sql: https://bugreports.qt.io/browse/QTBUG-71253
libpng and libjpeg are needed by optional code. They are provided in src/3rdparty, which tends to provoke clashes with system provided library versions. Therefore, we build without PNG and JPG support.
nmake
Check: static libraries (big .lib and small .prl) land in directory lib/
54.7 MB Qt5Core.lib
23.4 MB Qt5Widgets.lib
18.2 MB Qt5Gui.lib
07.4 MB Qt5Network.lib
...
That's it, we have static Qt libraries. Only, as said above, this did not help me when I tried to link my application with these libraries.

check what run-time static library or dll uses

is there a tool in windows SDK to ckeck what CRT a library uses?
for example I have a *.lib file, how do check if it's compiled with /MDd flag or /MT?
also how to check the same for dll or exe?
can this be done with dumpbin?
If it is a .lib file, a static link library, then you don't know anything about the CRT yet. It wasn't linked yet. You can find out about the original programmer's intention, use a hex viewer to look the .lib file, Notepad will do fine as well. You'll see the original command line that was used to compile the .obj files that were embedded in the .lib file. Simply search for "cl.exe", you'll have a good idea what compiler version was used from the path to cl.exe. And you can see the command line options so you'll know if /MD or /MT was in effect. And the /O option, important to have an idea whether you've got a Debug or Release build.
If it is a .dll file then dumpbin.exe /imports is your best choice. The dependency on the msvcrxxx.dll file will be visible, with xxx the version number like "120". If you see it then the name tells you if /MD or /MDd was used, "d" is appended for the Debug version of the CRT If it is missing then you know that /MT or /MTd was used, no hint about the build flavor available.
Following the recommendations from the library owner is always best, you can get into a lot of trouble when the CRT version or build settings of the library doesn't match yours. With non-zero odds that you have to ask him for an update, YMMV.

Building Clang on Windows

I'm trying to build LLVM/Clang on Windows 7 with Microsoft C++ 2013. Building LLVM spat out a few error messages along the way but mostly seemed to be succeeding and did end up creating a folder full of exe's so that part seems to have worked. When I try to build Clang:
C:\clang>\CMake\bin\cmake.exe ..\clang-3.4 -DCLANG_PATH_TO_LLVM_BUILD=/llvm
CMake Error at CMakeLists.txt:29 (message):
Please set CLANG_PATH_TO_LLVM_BUILD to a directory containing a LLVM build.
And I get the same error message whether I omit CLANG_PATH_TO_LLVM_BUILD, define it in CMakeLists.txt or an environment variable instead of the command line, set it to possibly relevant subdirectories of /llvm etc.
What am I missing?
You're not following the instructions on this page correctly, under "Using Visual Studio". You will end up with
/
/llvm
/llvm/CMakeLists.txt
/llvm/tools/clang
/llvm/tools/clang/CMakeLists.txt
Step 4, repeated here for clarity:
Run CMake to generate the Visual Studio solution and project files:
cd ..\.. (back to where you started)
mkdir build (for building without polluting the source dir)
cd build
If you are using Visual Studio 2012: cmake -G "Visual Studio 11" ..\llvm
That last bit needs to be run from inside the VS Command Prompt, but you seem to have that sorted out. You can also generate "NMake makefiles" if you don't use the IDE to build. Anyways, the point is that you should call cmake on the toplevel CMakeLists.txt file, not on the clang one directly. Clang will be built as part of the build process. You can even add libc++ and compiler-rt to the llvm/projects directory to have these built automatically on platforms that support them.
What you are doing is building clang "out of tree". Which is possible and even supported, but only really useful in certain circumstances. You'll need a previously built build of LLVM in some directory. You then set CLANG_PATH_TO_LLVM_BUILD to the directory containing the built LLVM files (this is not the source directory). But as I said, that's making things needlessly difficult.

How to check if dll generated is statically or dynamically linked?

Following is my linking command:
Running Mkbootstrap for XML::SAX::ExpatXS ()
C:\Perl\bin\perl.exe -MExtUtils::Command -e chmod -- 644 ExpatXS.bs
link -out:blib\arch\auto\XML\SAX\ExpatXS\ExpatXS.dll -dll -nologo -nodefaultlib -debug -opt:ref,icf -libpath:"C:\Perl\lib\CORE" -machine:x86 ExpatXS.obj -def:ExpatXS.def
Creating library blib\arch\auto\XML\SAX\ExpatXS\ExpatXS.lib and object blib\arch\auto\XML\SAX\ExpatXS\ExpatXS.exp
The compilation flags used are /Zi /GF /MD -c
I want to know if this dll is getting statically or dynamically linked. I referred http://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx but the compiler ignores these options when I specify them in my makefile.
Thanks
Your snippet only shows the DLL getting built, it doesn't say anything about the program that uses the DLL. Which has the choice to use the DLL either way.
If you have no idea then a simple way to find out is to run Dumpbin.exe /imports on the EXE. You'll see the exports from the DLL that are actually used listed in the output. If you don't see anything then the DLL could only be dynamically loaded. Or not at all. The debugger shows notifications for DLLs that get loaded into a process, you'll see them in the Output window.
Download a copy of the windows Dependency Walker, fire it up and load your freshly minted dll.
It will show all the DLLs that your dll imports. If one of the imports has a name like msvcr<blah>.dll (e.g., msvcrt.dll, or msvcr90.dll — you get the picture), then it is using the c-runtime in a dll (which incidentally, is the recommended thing for a dll to do).

Linking FFTW into Matlab Mex file

I am trying to run FFTW code in a mex file. This is strictly for the purpose of development and testing. After some googling, I see that others have tried to do something similar and have had related problems, but I have not found any solutions. When attempting to run the mex file, Matlab tells me:
??? Error using ==>
chirpTransform.mxCta Invalid MEX-file
'\removed\my\directory\+chirpTransform\mxCta.mexw32':
The specified procedure could not be
found.
.
I am using gnumex with MinGW to build the mex file because LCC seems to have some issues. I have tried using the 32 bit DLL from the FFTW site (http://www.fftw.org/install/windows.html). I have tried using the fftwf3.dll in the Matlab 2009b bin directory. I built the dll from source using Msys/MinGW. In all cases, the results are the same. In all cases I did the following to generate the lib file.
c:\gnumex\mexdlltool.exe -d
libfftw3f-3.def -D libfftw3f-3.dll -l
libfftw3f.lib --as C:\MinGW\bin\as.exe
I also tried using the visual studio lib.exe tool and experimented with various mexdlltool flags.
It appears that I can directly call functions in the fftwf3-3.dll using Matlab's loadlibrary functionality. Since the DLL appears not to be the problem, I tried building a static version of fftwf3 and linking it directly into the mex file. I got the same results! If I remove the FFTW code, the mex file runs fine. I have just about given up at this point, and I am tyring to come up with alternative methods of testing.
I've run into this issue with other mex functions. In my experience, it typically means that there is a dependency issue. Some dependency is not located.
Here is a link to TMW's documentation on this issue:
Invalid MEX-File Error
Give it a read, and then try using dependency walker to diagnose the problem.
It's been a long time, and my setup has changed, but this works for me now. I suspect hoogamaphone was right. I probably didn't have the fftw dll in the same directory as the mex dll (and it wasn't in my path). In fact, 64 bit Matlab 2016a still gives you a warning about not being able to find the mex file when, in fact, it's a dependency that's missing.
My current setup is using the Visual Studio 2013 C++ compiler by default. As mentioned on the fftw web site, you need to generate a lib file for linking. You can run the Visual Studio command prompt from a regular command prompt like so:
"%VS120COMNTOOLS%VsDevCmd.bat"
Then run the following in the directory with the def file.
lib /machine:x64 /def:libfftw3f-3.def
And compile.
mex mxCta.c cta.c -I../fftw -L../fftw -llibfftw3f-3.lib
Perhaps another possibility is that gnumex introduced some dependency into the mex dll. I no longer recall whether I had used gnumex successfully testing other code. When using cygwin, if you don't use the mingw compiler (x86_64-w64-mingw32-gcc), you'll end up with a dependency on the cygwin1.dll.
Finally, if you use more than one compiler, make sure all the compiler flags are the same (same function calling conventions, ABI, etc). Also, Mathworks has changed the mex build procedure. In a recent project, I copied mexconfig.xml to my local directory from
C:\Users\myuser\AppData\Roaming\MathWorks\MATLAB\R2016a\mex_C_win64.xml
and edited the compiler flags like so:
COMPFLAGS="/Zp8 /GR /W3 /EHs /nologo /MD /Gz /TC"
If you use a custom build file, use the -f option.
mex mxCustom.c custom.lib -f mexconfig.xml

Resources