flintlib / arb

Arb has been merged into FLINT -- use https://github.com/flintlib/flint/ instead
http://arblib.org/
GNU Lesser General Public License v2.1
457 stars 137 forks source link

Arb fails to link under vcpkg. #410

Closed kaba2 closed 2 years ago

kaba2 commented 2 years ago

The following example fails to link. Arb version is 2.21.1. Windows.

src/main.cpp:

#include <malloc.h>
#include <arb.h>

int main()
{
    arb_t x;
    arb_init(x);
    arb_const_pi(x, 50 * 3.33);
    arb_printn(x, 50, 0); flint_printf("\n");
    flint_printf("Computed with arb-%s\n", arb_version);
    arb_clear(x);
}

vcpkg.json:

{
  "name": "testarb",
  "version-string": "0.1.0",
  "dependencies": [
    "arb"
  ]
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.15)

project(testarb CXX)

include_directories("./vcpkg/packages/arb_x64-windows/include")
include_directories("./vcpkg/packages/flint_x64-windows/include")
include_directories("./vcpkg/packages/gmp_x64-windows/include")
include_directories("./vcpkg/packages/mpfr_x64-windows/include")
include_directories("./vcpkg/packages/pthreads_x64-windows/include")

link_directories("./vcpkg/packages/arb_x64-windows/lib")
link_directories("./vcpkg/packages/flint_x64-windows/lib")
link_directories("./vcpkg/packages/gmp_x64-windows/lib")
link_directories("./vcpkg/packages/mpfr_x64-windows/lib")
link_directories("./vcpkg/packages/pthreads_x64-windows/lib")

add_executable(testarb src/main.cpp)
target_compile_features(testarb PRIVATE cxx_std_20)

target_link_libraries(testarb PRIVATE gmp flint mpfr arb)

Command line:

git clone https://github.com/Microsoft/vcpkg.git
.\vcpkg\bootstrap-vcpkg.bat
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=./vcpkg/scripts/buildsystems/vcpkg.cmake
cmake --build build

Output:

main.obj : error LNK2019: unresolved external symbol __imp_arb_version referenced in function main [C:\work\testarb\bui
ld\testarb.vcxproj]
arb.lib(div.c.obj) : error LNK2019: unresolved external symbol __gmpn_div_q referenced in function arf_div [C:\work\tes
tarb\build\testarb.vcxproj]

If I open gmp.lib in 7-zip, I can find __gmpn_div_qr_1 and __gmpn_div_qr_2, but not __gmpn_div_q. How can I make this example link?

albinahlback commented 2 years ago

mpn_div_q is indeed not documented and not linked in gmp.h. However, it can be found under mpn/generic/div_q.c, and thus Fredrik simply created a link for it at line 17 in arf/div.c.

albinahlback commented 2 years ago

So you have two error messages during compilation. Is the first error message dependent upon the second one (or vice versa), or are they independent?

kaba2 commented 2 years ago

The errors seem to be independent. Here's a minimal example for arb_version:

src/main.cpp:

#include <arb.h>

int main()
{
    flint_printf("Computed with arb-%s\n", arb_version);
}

It gives the error:

main.obj : error LNK2019: unresolved external symbol __imp_arb_version referenced in function main [C:\code\testarb\bui
ld\testarb.vcxproj]

Example for the other error:

src/main.cpp:

#include <malloc.h>
#include <arb.h>

int main()
{
    arb_t x;
    arb_init(x);
    arb_const_pi(x, 50 * 3.33);
    arb_printn(x, 50, 0); flint_printf("\n");
    arb_clear(x);
}

It gives the error:

arb.lib(div.c.obj) : error LNK2019: unresolved external symbol __gmpn_div_q referenced in function arf_div [C:\code\tes
tarb\build\testarb.vcxproj]

Aside 1: for some reason malloc.h is needed to provide _alloca.

Aside 2: there's something wrong with the vcpkg debug config for arb. It copies gmpd.dll into to the output directory, but at runtime the program expects gmp.dll. To sidestep this issue, build Release config instead:

git clone https://github.com/Microsoft/vcpkg.git
.\vcpkg\bootstrap-vcpkg.bat
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=./vcpkg/scripts/buildsystems/vcpkg.cmake
cmake --build build --config Release

I wonder who maintains the vcpkg arb package? Should its problems be reported here, or should it be reported to vcpkg repository?

Aside 3: This works:

src/main.cpp:

#include <malloc.h>
#include <arb.h>

int main()
{
    flint_printf("Hello");
}
albinahlback commented 2 years ago

As I understand it, vcpkg is a package manager for C libraries? Can you at least compile the binary from scratch using CMake?

albinahlback commented 2 years ago

You can see who has contributed to vcpkg's Arb here: https://github.com/microsoft/vcpkg/tree/master/ports/arb. Bring this issue up with them, as we do not support vcpkg.

kaba2 commented 2 years ago

Thanks. I have reported the issue at the vcpkg repository. I haven't yet managed to build Arb from stratch. I just got the dependencies built. The build is somewhat complicated under Windows, since the libraries do not all support Windows builds out of the box. Fortunately Brian Gladman has been active at providing build support for the dependencies under Windows.

JackBoosY commented 2 years ago

Hi, I'm vcpkg maintainer. It's indeed a bug in vcpkg side, but I need to confirm one thing: https://github.com/fredrik-johansson/arb/blob/076249eaeebb159a9e0b68090fec83ebb495605e/arf/div.c#L15-L20 __gmpn_div_q is expected to be defined in the gmp side, but in gmp 6.2.1, there only contains the following function defines:

So is the expected gmp version outdated here?

kaba2 commented 2 years ago

Looking at the gmp 6.2.1 source code at file mpn/generic/div_q.c line 99, I find a function named mpn_div_q:

void
mpn_div_q (mp_ptr qp,
       mp_srcptr np, mp_size_t nn,
       mp_srcptr dp, mp_size_t dn, mp_ptr scratch)

So looking at this it seems the function names start with mpn rather than gmpn. The types of the parameters seem to match with what is expected in the forward declaration in Arb source code at file arb/arf/div.c line 17:

void __gmpn_div_q(mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr);

I checked gmp 5.0.0 source code from 2010-01-08 which shows the same name mpn_div_q. The previous release gmp 4.3.2 from 2010-01-07 does not contain that function, so it was introduced in gmp 5.0.0.

albinahlback commented 2 years ago

GMP ships the macro __MPN(x) which expands to __gmpn_x. In gmp-impl.h you find mpn_div_q declared, where they have set

#define mpn_div_q __MPN(div_q)

So GMP actually never declares any function named mpn_div_q, it declares a function called __gmpn_div_q. This is still shipped with GMP, it's just not visible.

To restate my question: do you have any problems with compiling Arb with any of the supported methods?

kaba2 commented 2 years ago

Aah, macros, good catch.

I interpreted that the question by @JackBoosY above was more directed to arb developers, in the hope that you could shine some light on the problem.

Building Arb on Windows is painful, because I have to build transitive dependencies on various build systems. And many of those build systems do not work directly under Windows, which makes it much worse. I'd just hope that developers of gmp, flint, fmpr, and arb came together and made their build systems cross platform (practically: change to use CMake solely) so that we can have a simple unified build on any platform.

vcpkg is trying to make builds less painful, by building you the transitive dependencies automatically. Without developer support I can imagine it is a bit like wandering in the dark when errors such as in this thread do happen.

I have managed to manually build the transitive dependencies for arb, but have not attempted to build arb itself yet.

albinahlback commented 2 years ago

(What I'm stating here is my opinion only)

I don't think that anyone will ever change it to only using CMake. I don't like CMake. I just find it more complex compared to plain and simple Make. Furthermore, as GMP uses Make, I think we will continue to use it as our main building tool.

I just want Arb to work on Windows. Windows is not a good platform. Microsoft had to create Windows Subsystem for Linux in order to stay relevant. Most scientific computations are done on Unix-type systems anyway, so focusing on Windows would be a waste in my opinion.

kaba2 commented 2 years ago

I don't think anyone particularly loves CMake (syntax). But it works for cross-platform builds, so right now it is the goto-tool for that. Some of us poor developers who want to write cross-platform programs are suffering from Unix-only build systems :( Even when you use CMake, you just use it to generate makefiles (say), and then use make as usual. That is a pre-step comparable to how (as far as I know) you now use configure before make.

JackBoosY commented 2 years ago

@kaba2 @albinahlback Thanks for clarify! One thing remains: Although I found the defination of mpn_div_q, but the export symbols are only have suffixes r_1 and r_2, is that correct?

Are there any macros that will expand this symbol to these two suffixes?

albinahlback commented 2 years ago

@kaba2 @albinahlback Thanks for clarify! One thing remains: Although I found the defination of mpn_div_q, but the export symbols are only have suffixes r_1 and r_2, is that correct?

That is correct.

Are there any macros that will expand this symbol to these two suffixes?

That is not correct. GMP never declares mpn_div_q for external uses (i.e. to users). However, one can still call the function (assuming you have declared it) since GMP will compile the function.

JackBoosY commented 2 years ago

That is not correct. GMP never declares mpn_div_q for external uses (i.e. to users). However, one can still call the function (assuming you have declared it) since GMP will compile the function.

I can only find the declaration of the original function, not the implement. And I can't find this symbol in the generated library. There may have something wrong with gmp build, right?

albinahlback commented 2 years ago

It is implemented under mpn/generic/div_q.c, I believe.

kaba2 commented 2 years ago

The bug with vcpkg was fixed by @JackBoosY. Thanks to @albinahlback for providing details!