Static build of GMP for MSVC (Windows) - c

Is it possible to build GMP for MSVC on Windows?
I need fully static solution (static library), without any DLL dependencies. So that my final EXE doesn't depend on any external (non-system) DLLs.
I'm alright if building GMP will need Cygwin or MSYS, as far as it can be used later in MSVC without any problems. But as far as I know at least Cygwin builds always depend on extra DLLs like cygwin1.dll which is not affordable for me, fully static-library solution is needed.
I'm aware there exists MPIR library that is more Windows friendly. But right now I need specifically GMP solution if possible.
Of course would be great if all optimizations and assembly is used when building for Windows. But if assembly is not possible then at least non-assembly (generic) variant of GMP is needed.
Of course I need 64-bit version.
If someone can post all steps needed to produce such static library for MSVC usage? Or maybe link some web-site that has such instructions?

I successfully managed to compile a working fully statically linked program with GMP using MSVC under Windows.
For that I used installation of MSYS, which is located in c:/bin/msys/ on my machine.
Then inside MSYS shell installed GMP packages mingw-w64-clang-x86_64-gmp and gmp-devel (pacman -S gmp-devel to install and pacman -Ss gmp to search).
In MSVC compiler I added include directory c:/bin/msys/clang64/include/.
Wrote an example of GMP usage program in C++, that implements Trial Division / Pollard's Rho / Pollard's P-1 factoring algorithms using long arithmetics. This program uses both mpz_...() C routines and mpz_class C++ wrapper class. For example this program is located in main.cpp.
To linker command line I added following libraries:
c:/bin/msys/clang64/lib/libgmp.a
c:/bin/msys/clang64/lib/libgmpxx.a
c:/bin/msys/mingw64/lib/gcc/x86_64-w64-mingw32/10.3.0/libgcc.a
c:/bin/msys/clang64/x86_64-w64-mingw32/lib/libmingwex.a
Also I had to add /FORCE flag (read about it here) to linker command, because libmingwex.a has some symbols overlapping with default MSVC's libraries, precisely without /FORCE I had following errors:
libucrt.lib(strnlen.obj) : error LNK2005: wcsnlen already defined in libmingwex.a(lib64_libmingwex_a-wcsnlen.o)
libucrt.lib(strnlen.obj) : error LNK2005: strnlen already defined in libmingwex.a(lib64_libmingwex_a-strnlen.o)
bin\win-msvc-m-64-release\drafts\gmp_int_msvc.exe : fatal error LNK1169: one or more multiply defined symbols found
All steps produced working (tested) final statically-linked program without any external DLL dependencies (of course except for default system DLLs of Windows).
It means MSYS's libraries .a are fully compatible with MSVC and link successfully in MSVC compilation.
Not to have /FORCE linker flag I also did extra following steps. Made a copy of c:/bin/msys/clang64/x86_64-w64-mingw32/lib/libmingwex.a library. Used c:/bin/msys/clang64/bin/objcopy.exe util, which probably was installed together with Clang. With objcopy renamed overlapping symbols:
objcopy --redefine-sym wcsnlen=msys_wcsnlen libmingwex.a
objcopy --redefine-sym strnlen=msys_strnlen libmingwex.a
which allowed me to successfully use this modified libmingwex.a library to link in MSVC without using /FORCE.

Related

Integrating .lib files with C code written on Linux

I have pre-existing code that was written and is running on a Linux machine. I need to add to this code, this new code which depends on a library using VS. I have decided to develop on Visual Studio using WSL (Windows Subsystem for Linux) then taking the executable/out file to my Linux machine and running it there.
The code I am adding myProg.c uses a function Func(double arg) which comes from the library Reallib.lib
I have included the header file
#include "Support_Files/Reallib.h"
In my project property pages, the .lib file is in the Additional Dependencies
Support_Files/Reallib.lib
The declaration in the Reallib.h file:
long Func(double arg)
At build-time, these are the errors I get:
/mnt/c/Users/mitch/Projects/myproject/myproject/myproject/obj/x64/Debug/myProg.c: in function `main':
undefined reference to Func
ld returned 1 exit status
If I'm including my library already, why am I getting this error? Is it because Linux systems don't use .lib files? How can I combine the code written on Windows with code written on Linux?
Researching online doesn't seem to match my similar problem.
I have already tried using GCC for Remote Linux, but a similar error was produced. But neither (WSL or Remote Linux) seem to play nice with combining .lib files with source code written on Linux.
Now, I could add RealFunc.c and that would clear the error up, but I would just get another undefined reference error, and so on and so forth (RealFunc.c has plenty of other dependencies that are taken care of in Reallib.lib)
Configuration properties > General > Platform Toolset
I've also tried developing only on Linux, bringing the .lib file over and updating my makefile to link that, but it wasn't working (I believe because Linux doesn't use .lib)
What should be my route of action? I NEED the code that is in Reallib.lib. Do I need to bite the bullet and essentially recompile all the source code in Reallib.lib? Do I need to just move over to Linux 100% and use VS Code? I like using VS because it makes the compiling and linking options much easier. I am still new to C and Linux.
I am using Visual Studio 2022 17.4.3
WSL Ubuntu (v20.04)
$ gcc --version
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
There is no proper/native way to use a Windows library .lib in Linux, your only solution is by re-compiling the library for the targeted platform, in this case, is Linux.
Option A
Simply re-compile the library source code in Linux using GCC or Clang to generate the proper .a static library or .so shared library.
Option B
Install a cross compiler in Windows for Linux, you can use Cygwin if you are familiar with it.

How can I make a binary that uses openmp and compiled with intel's C compiler portable?

Normally I compile code (all in a single file main.c) with the intel oneapi command prompt like so
icl.exe main.c -o binary_name
I can then run binary_name.exe without issue from a regular command prompt. However, when I recently exploited openmp multithreading and compiled like so.
icl.exe main.c -o binary_name /Qopenmp /MD /link libiomp5md.lib
Then, when I try to run it through an ordinary command prompt, I get this message:
I'd ultimately like to move this simple code around (say, to another computer with the same OS). Is there some procedure through a command prompt or batch file for packaging and linking a dynamic library? It is also looking like statically linking for openmp is not supported on windows
Either make a statically linked version, or distribute the dependency DLL file(s) along with the EXE file.
You can check the dependencies of your EXE with Dependency Walker.
As you correctly statedk statically linking for OpenMP is not supported on Windows. Depending on your use case you have a couple of options. The simplest one for simple testing is to just ship the Dynamic-Link Library with you executable and place it in the same directory in the target system. Having built a lot of systems using DLLs, this is typically what most developers do to ensure capability with their code in a production environment even.
If you are looking to do something more complex on the target system you can place the Dynamic-Link library in a shared location and follow the search order suggestions from the Microsoft Build site:
https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order

Trouble linking a mex file to static mpfr library

I am trying to compile a mex file that requires the mpfr C library, using MATLAB R2013a on Mac OS 10.8.5. I would like it to run on systems that don't have a separate installation of MPFR, so I am trying to include the static library:
mex my_program.c libmpfr.a
I copied the libmpfr.a library into the folder with my source code to simplify things. When I run this command I get the following error message:
ld: targeted OS version does not support use of thread local variables in _mpfr_add for architecture x86_64
A little research suggested that this issue could be due to a problem with the llvm-gcc-4.2 compiler that comes with Xcode and is used in MATLAB by default. So, I tried to set up a different compiler. I got GCC 4.7.4 (the latest version supported by MATLAB) from MacPorts, as described here: http://www.ficksworkshop.com/blog/14-coding/65-installing-gcc-on-mac. Next, I edited the mexopts.sh file to point MATLAB to the correct compiler, by entering the following settings:
CC='/opt/local/bin/gcc-mp-4.7'
CXX='/opt/local/bin/g++-mp-4.7'
Now when I try to compile, I get a different error message:
In file included from /Applications/MATLAB_R2013a.app/extern/include/matrix.h:294:0,
from /Applications/MATLAB_R2013a.app/extern/include/mex.h:58,
from include/main.h:5,
from include/poisson.h:7,
from src/main.c:22:
/Applications/MATLAB_R2013a.app/extern/include/tmwtypes.h:61:21: fatal error: float.h: No such file or directory
If, in mexopts.sh, I additionally set
SDKROOT='/opt/local/'
or a number of other choices (based on the locations of different copies of float.h that I can find on my system), I instead see
my_program.c:10:20: fatal error: stdlib.h: No such file or directory
So it seems that GCC-MP-4.7 is having trouble locating all of the standard C libraries.
I'd be grateful for a solution to either of these issues (linking to static mpfr useing the default compiler, or configuring GCC 4.7 to find the standard C libraries).
I found that the "thread local variables" error was caused by the compiler trying to include backwards-compatibility to OSX 10.5. Since I don't need it to do this, I edited the mexopts.sh file, replacing this line
MACOSX_DEPLOYMENT_TARGET='10.5'
with this:
MACOSX_DEPLOYMENT_TARGET='10.8'
This resulted in the mex file compiling successfully using the built-in Xcode compiler.

unable to compile C files (MEX) in matlab (Windows) using GNU GCC

I am trying to compile native linux c files on windows using GNU GCC compilers. For the installation purpose, I have followed the steps mentioned by Faheem in the following link :
Using GCC(minGW) as Matlab's MEX compiler
the example given there compiled successfully. but when i am trying to compile a file using thread functions, the following error is being thrown:
fatal error: pthread.h: No such file or directory
#include
^
compilation terminated.
I have installed all the components from MinGW installer related to GNU C compiler bu still the error persists. Can any one suggest a way to solve this problem. Thanks in advance.
According to the TDM-GCC "Quircks" page, TDM-GCC includes a pthreads emulation layer for Microsoft Windows systems, called "winpthreads", and a recent toolchain you should have x86_64-w64-mingw32\include\pthread.h in the TDM install path. So, I don't know what is wrong with Faheem's instructions, but you should have no trouble including pthread.h if MATLAB is configured correctly.
What is not stated on the TDM Quircks page is that TDM uses Winpthreads from the MinGW-w64 project. From the current README installed with TDM:
"Winpthreads" is one of the libraries distributed by the MinGW-w64 project, and
it allows GCC to be compiled with full pthreads compatibility, which is
necessary to enable std::thread and other threading related functions in the
C++ runtime.
As it states, Pthreads is part of the MinGW-w64 project and you can also get it with MinGW-w64 if you pick a pthreads enabled toolchain. For MinGW-w64, I do the following to set it up (see here for more details):
Grab the latest revision for w64 from Sourceforge (or use the installer to choose the toolchain you want, picking a pthread version).
Extract it so that you have a path to the compiler like C:\mingw-w64\x86_64-4.9.2-release-posix-seh-rt_v3-rev1\bin\x86_64-w64-mingw32-g++.exe. There is no need for MSYS, cygwin, or any other environment if you plan on compiling in MATLAB with mex.
Set it up with a custom mexopts.bat or using the new xml configuration system. On my GitHub repo, I have C++ configurations for MinGW-w64 in both file types: mingw_mexopts.bat and mex_C++_mingw-w64.xml. For example, using the xml file to set up C++ MEX file compilation:
mex -setup:C:\Users\Jon\Documents\MATLAB\mex_C++_mingw-w64.xml C++
If needed, set up the C compiler in a similar manner by modifying the config files.
I posted a more detailed version of the above instructions in my answer to the canonical question on the MinGW-with-MATLAB topic.

How do I install C packages on windows

I have to use LU decompostion to fit a simple model to some data (simulated) in C. An example of what I need to do is here:
However, I'm stuck with a more basic problem: how do I install packages in C and call them in my code?
I'm new in C and I'm used to R. But I have this assingment to do some tests about Matrix inversion, LU decomposision and the professor suggested using Lapack to easy things (thus, I don't need to code myself the LU decomposition etc.). But I don't know how to install the package and call it in my code, in order to use the functions of LAPACK.
I have a windows 7 64 bits and I'm using compiler Code Blocks 8.02
Thanks for any help.
Normally you don't "install" C libraries in that sense. Normally, in Windows you have three types of files. The header files, typically ending in .h, the dynamic library, .dll, and most likely some linker files (typically, .lib, .a or something). The linker and compiler will need to be able to find these files somewhere. Normally you set the include directory paths, and library directory paths.
E.g. Let's say you downloaded a library called foo, and you extract it to C:\foo.
In that folder, libfoo.a, foo.dll and foo.h reside. In Code::Blocks you will have to point include directory path to C:\foo and library path to C:\foo so that the linker and compiler know where to look for these files. Since you're linking against the foo library, you will also have to set -lfoo or something similiar in linker command line. This is GCC syntax, but I think Code::Blocks uses GCC compiler behind the scenes anyways.
In the C code you can just #include <foo.h> and the compiler will find it for you.
You need to install that library and it might actually supply a tool for that. Check their documentation (e.g. a file INSTALL or README in their distributed sources). If the library uses only headers you might only need to copy it's headers to some directory on your system, but their buildsystem might be able to do that for you.
Once that is done you would tell your IDE on where to look for the sources and if the library uses not just headers to link against the actual library file. See the documentation in the Code::Blocks Wiki on how this is done for some example cases and adapt for your library.
The simplest thing to do in your situation is to install Cygwin. You can use the setup.exe installer to install the GCC and the LAPACK libraries. When you want to use the LAPACK library, you will add the -llapack option to your GCC command line.

Resources