Qt5 - static libraries with static CRT - qt5

I'm trying to build Qt5.0.2 (MSVC10, Win7) statically, with static CRT.
I've modified Qt5.0.2\5.0.2\Src\qtbase\mkspecs\win32-msvc2010\qmake.conf replacing every occurrence of MD and MDd compiler flags with MT and MTd respectively. Then I configure Qt: configure -debug-and-release -static -opensource -nomake examples -nomake tests.
Configure detects the platform correctly: QMAKESPEC...win32-msvc2010 (detected)
However, it seems that the above modifications have no effect: when I run nmake, cl gets invoked with -MD flag.
How can I trace/debug this issue?
UPDATE: I've noticed, that the library makefiles (qtbase/src/corelib/Makefile.Release, etc) do not get updated, so they keep containing MD option. How to make them updated?

Related

cmake - linking static library pytorch cannot find its internal functions during build

I'm trying to build a program using cmake. For several reasons, the program must be built using static libraries rather than dynamic libraries, and I need to use PyTorch so this is what I've done:
Downloaded and installed PyTorch static library (I've found libtorch.a in the proper path, in /home/me/pytorch/torch/lib)
Made CMakeLists.txt with the following contents:
cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR)
project(example-app LANGUAGES CXX)
find_package(Torch REQUIRED)
add_executable(example-app example-app.cpp argparse/argparse.cpp)
target_link_libraries(example-app "${TORCH_LIBRARIES}" -static -fopenmp)
set_property(TARGET example-app PROPERTY CXX_STANDARD 14)
FYI, example-app.cpp is the file with the main function, and argparse/ is a directory with some source code for functions called in example-app.cpp
It works until cmake -DCMAKE_PREFIX_PATH=/home/me/pytorch/torch .., but the following build incurs some errors, saying it could not find the reference to some functions, namely functions starting with fbgemm::. fbgemm is (as long as I know) some sort of GEMM library used in implementing PyTorch.
It seems to me that while linking the static PyTorch library, its internal libraries like fbgemm stuff have not been linked properly, but I'm not an expert on cmake and honestly not entirely sure.
Am I doing something wrong, or is there a workaround for this problem? Any help or push in the right direction would be greatly appreciated.
P.S.
The exact error has not been posted because it is way too long, but it consists of mostly undefined reference to ~ errors. If looking at the error message might be helpful for some people, I'd be happy to edit the question and post it.
building and running the file works fine if I remove the parts that require the library's functions from the code without commenting out #include <torch/torch.h> from example-app.cpp.
Lately went through similar process with static linking of PyTorch and to be honest it wasn't too pretty.
I will outline the steps I have undertaken (you can find exact source code in torchlambda, here is CMakeLists.txt (it also includes AWS SDK and AWS Lambda static builds), here is a script building pytorch from source ( cloning and building via /scripts/build_mobile.sh with only CPU support)),
though it's only with CPU support (though similar steps should be fine if you need CUDA, it will get you started at least).
Pytorch static library
Pre-built static PyTorch
First of all, you need pre-built static library files (all of them need to be static, hence no .so, only those with .a extension are suitable).
Tbh I've been looking for those provided by PyTorch on installation page, yet there is only shared version.
In one GitHub issue I've found a way to download them as follows:
Instead of downloading (here via wget) shared libraries:
$ wget https://download.pytorch.org/libtorch/cu101/libtorch-shared-with-deps-1.4.0.zip
you rename shared to static (as described in this issue), so it would become:
$ wget https://download.pytorch.org/libtorch/cu101/libtorch-static-with-deps-1.4.0.zip
Yet, when you download it there is no libtorch.a under lib folder (didn't find libcaffe2.a either as indicated by this issue), so what I was left with was building explicitly from source.
If you have those files somehow (if so, please provide where you got them from please), you can skip the next step.
Building from source
For CPU version I have used /pytorch/scripts/build_mobile.sh file, you can base your version off of this if GPU support is needed (maybe you only have to pass -DUSE_CUDA=ON to this script, not sure though).
Most important is cmake's -DBUILD_SHARED_LIBS=OFF in order to build everything as static library. You can also check script from my tool which passes arguments to build_mobile.sh as well.
Running above will give you static files in /pytorch/build_mobile/install by default where there is everything you need.
CMake
Now you can copy above build files to /usr/local (better not to unless you are using Docker as torchlambda) or set path to it from within your CMakeLists.txt like this:
set(LIBTORCH "/path/to/pytorch/build_mobile/install")
# Below will append libtorch to path so CMake can see files
set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${LIBTORCH}")
Now the rest is fine except target_link_libraries, which should be (as indicated by this issue, see related issues listed there for additional reference) used with -Wl,--whole-archive linker flag, which brought me to this:
target_link_libraries(example-app PRIVATE -lm
-Wl,--whole-archive "${TORCH_LIBRARIES}"
-Wl,--no-whole-archive
-lpthread
${CMAKE_DL_LIBS})
You may not need either of -lm, -lpthread or ${CMAKE_DL_LIBS}, though I needed it when building on Amazon Linux AMI.
Building
Now you are off to building your application. Standard libtorch way should be fine but here is another command I used:
mkdir build && \
cd build && \
cmake .. && \
cmake --build . --config Release
Above will create build folder where example-app binary should be now safely located.
Finally use ld build/example-app to verify everything from PyTorch was statically linked, see aforementioned issue point 5., your output should look similar.

How to static linking to glibc in cmake

I'm trying to build a package from Fedora that can run on a RedHat 6 machine. So I need to build and static linking with some library that does not exist in RedHat machine.
I found that I can you -static-libgcc or -static-libstdc++ to link with static version of standard library but I don't know how to do with glibc.
How can I link to static library of glibc with CMake?
I know the question mentions glibc but for C++, since -static-libgcc and -static-libstdc++ are linker options, the correct way to set them in CMake is with target_link_libraries().
So you would set it like this, where MyLibrary is the name of your project:
target_link_libraries(MyLibrary -static-libgcc -static-libstdc++)
Given this, if you want complete static linking of glibc you would likewise pass the -static flag.
target_link_libraries(MyLibrary -static)
If you want more of a global setting:
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_EXE_LINKER_FLAGS "-static")
However, bear in mind that glibc is not designed to be statically linked, and without a great amount of additional work, you won't wind up with a truly static package. Your use case of building "a package from Fedora that can run on a RedHat 6 machine" will not readily work by statically linking glibc.

Recompile with -fPIC Gentoo

I'm new to Gentoo and trying to install a 3D modelling program called TexGen (http://texgen.sourceforge.net/index.php/Main_Page) using CMake, and I keep getting the error:
relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
This occurs during the step:
[ 80%] Linking CXX shared module ../_Renderer.so
I've looked all over and tried setting the -fPIC flag in the cmake options file, but there's no change in the result. As I said I'm quite new (in the order of a few weeks) to Linux and Gentoo and any help would be greatly appreciated.
Actually Gentoo has a eclass(es) to build CMake based projects (see /usr/portage/cmake*.eclass). And AFAIK, it replace package options with yours (to be precise, it adds a new configuration type), configured in /etc/portage/make.conf (or /etc/paludis/bashrc if you use paludis). So, I not wondered that "hacking" CMakeLists.txt in the package ebuild do not help.
So, easiest way is to add that option to your Gentoo settings instead. Personaly I use this way to build boost library in my system (yep, I need boost's static libraries to be linked into dynamic one in some of my projects). And yes, I'm using paludis, but emerge probably has similar feature (a way to set per package compiler options).
The other way, instead of "hacking" compiler options directly (via CMAKE_<LANG>_FLAGS), take a look to CMAKE_POSITION_INDEPENDENT_CODE -- it'll add a proper compiler option for you, and probably eclass' manipulations with cache wouldn't affect this setting.
I got it to work (for installing ffmpeg) by simply reinstalling the whole thing from the beginning with all instances of $ ./configure replaced by $ ./configure --enable-shared (first make sure to delete all the folders and files including the .so files from the previous attempt).
Apparently this works because https://stackoverflow.com/a/13812368/10593190.

How to static link ncurses on AIX using xlc

I'm trying to use the ncurses library on AIX 7.1 to make use of panels which aren't included in the curses library that is standard on AIX. I have the ncurses library installed. The compile,link, and execute work fine with:
xlc ngoodbye.c -lncurses
The actual ncurses library is libncurses.a, which I understand is a static library. However, when I move the executable to another AIX host and execute I get:
Dependent module libncurses.a(libncurses.so.5) could not be loaded. Could not load module libncurses.a(libncurses.so.5). System error: No such file or directory.
How can I link the ncurses library so that the program will execute on other hosts where the ncurses library isn't installed? Note I'm using xlc on AIX, not gcc.
I've tried -bstatic but get link errors at compile time. Note that I'm not a developer so my experience in this area is limited. Thanks.
Both static and shared libraries in AIX are built as position independent (PIC). So even a "shared" library can be statically bound to an executable. You were on the right track with -bstatic, you just need to switch back to dynamic binding for the rest of the libraries you're linking to.
So try this for your final link:
xlc -o myexe myexe.o <other objects as needed> -bstatic -lncurses -bdynamic -lm <and other other libraries as needed>
I do this all the time to make sure that my production environment matches my development one.
Normally ".a" does mean a static library. However, in adapting the initial report (in 2008) describing the AIX 5 shared library configuration there was some miscommunication and ".a" was used for both static and shared libraries. That was finally corrected last year (see changelog).
AIX 4, by the way, used a much more complicated scheme, so shared libraries for ncurses were first implemented on AIX 5.
Packagers prefer shared libraries. So what you have is a shared library named libncurses.a (legal, but not conventional). This is not created with the archiver ar, but using the loader ld. To see that they are different, you can try
ar tv libncurses.a
(with the appropriate directory). Likely ar will say something like
ar: 0707-108 File libncurses.a is not an archive file.
while file may give a more informative message:
libncurses.a: executable (RISC System/6000) or object module not stripped
You can however build ncurses from source. In that case (no matter what version), the default builds static libraries. You need not install those into the system area, but can configure ncurses using the --prefix option to install into a different directory.
As suggested in another answer, there is a workaround using the -bdynamic and -bstatic options of AIX's ld (loader), e.g., changing
xlc -o foo foo.c -lncurses
to
xlc -o foo foo.c -bstatic -lncurses -ldynamic
However, this is partly dependent upon the loader's search path and the name of the archive. If the archive is named libncurses.a, the command works as given. If it is named libncurses.so (as in current sources), then this command is needed to link against the shared library:
xlc -o foo foo.c -brtl -lncurses
But this command (which one might suppose to provide the static linkage using the libncurses.so file) does not succeed:
xlc -o foo foo.c -brtl -bstatic -lncurses -bdynamic

Building SDL2_image as a CMake external project

I've been trying to create a CMake-based build-system for a project that is supposed to use SDL2_image library. I do not want to force user to install any libraries to the system to be able to build the project, so I took advantage of the CMake's ability to download and build dependencies (freetype, SDL2 and SDL2_image) from source code as External Projects.
Everything is fine with freetype and SDL2 (which both include CMakeLists.txt files out of the box), but I've ran out of ideas how to make it work for SDL2_image. CMake's external projects support custom configuration and building settings which I used in different variants with no success.
The CMake file itself can be found here, but the problematic part is this:
# SDL_image library
ExternalProject_Add(sdl2_image_project
URL https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.0.tar.gz
DEPENDS sdl2_project
PREFIX ${LIBS_DIR}/SDL2_image
CONFIGURE_COMMAND LDFLAGS=-L${SDL2_BIN} CFLAGS=-I${SDL2_SRC}/include SDL2_CONFIG=${SDL2_BIN}/sdl2-config <SOURCE_DIR>/configure --prefix=<INSTALL_DIR> --enable-shared=no
BUILD_COMMAND make
INSTALL_COMMAND ""
)
An error occurs while building sdl2_image_project. Some trivial research discovered that the error is generated by the undefined references to parts of libdl. Here is a tiny part of the hole error:
libtool: link: gcc -I/home/snikitin/_src/img_glypher/libs/SDL2/src/sdl2_project/include -I/usr/local/include/SDL2 -D_REENTRANT -o showimage showimage.o -Wl,-rpath -Wl,/usr/local/lib -pthread -L/home/snikitin/_src/img_glypher/libs/SDL2/src/sdl2_project-build ./.libs/libSDL2_image.a -L/usr/local/lib -lSDL2 -pthread
/home/snikitin/_src/img_glypher/libs/SDL2/src/sdl2_project-build/libSDL2.a(SDL_dynapi.c.o): In function `get_sdlapi_entry':
/home/snikitin/_src/img_glypher/libs/SDL2/src/sdl2_project/src/dynapi/SDL_dynapi.c:227: undefined reference to `dlopen'
I think the problem takes place due to the fact that linker tries to create a shared version of SDL2_image library while linking it to a static libSDL2.a. The thing is - if this is right - SDL2 building step creates both static and shared versions of itself so one would assume that linker would use libSDL2-2.0.so instead (I do not actually need a shared library - just the static one, but I do not know how to prevent the build system from trying to create it apart from passing --enable-shared=no to SDL2_image configure script, which does not help in this case).
After a lot of googling I've discovered that the possible source of the problem is that sdl2-config (which is called to get some flags for compiler during SDL_image building) may be called with wrong arguments and produces wrong cflags which confuse everything else. But I'm not sure that is the case and also I do not know how to influence sdl2_config call from CMake (configure --help does not seem to unveil any useful options for this situation).
I am running Ubuntu 14.04 x64 if it matters in any way. Would appreciate any advice!
Looks like you need to link some libraries like m and dl. It can be fixed by providing
custom sdl2-config file. Copy sdl2-config from extracted archive and substitute --libs result:
--libs)
echo -L${exec_prefix}/lib -Wl,-rpath,${libdir} -pthread -lSDL2 -lm -ldl
;;
Note that order is important (that's why just modifying LIBS not works for me).
Now this file can be used in your ExternalProject_Add command instead of SDL2_CONFIG=${SDL2_BIN}/sdl2-config:
...
... CFLAGS=-I${SDL2_SRC}/include SDL2_CONFIG=${CMAKE_CURRENT_LIST_DIR}/sdl2-config <SOURCE_DIR>/configure
...