AdaCore / gprbuild

GPRbuild is an advanced build system designed to help automate the construction of multi-language systems.
Other
65 stars 21 forks source link

Dynamic vs Static linking #51

Closed Alex-Gamper closed 5 years ago

Alex-Gamper commented 5 years ago

Hi AdaCore

I have recently built XMLADA, GPRBUILD and LIBADALANG projects from your git repo, with little or no issues , great work ! However using these projects in combination is a bit problematic. As an example if my GPR file (being a shared lib , ie windows DLL which it MUST be when developing a COM component) then the default LIBRARY_TYPE used in XMLADA conflicts with the default used in GPR. (as an example)

The result of the above is that GPRBUILD complains with the following error message shared library project "gpr" cannot import static library project "xmlada_dom" etc...

In my mind having extensive experience in the windows C/C++ dev environment, I see no reason why a DLL cannot import/link to a static library. I appreciate the issues around initializing the Ada/Gnat runtime, but could you explain the rational in doing this ?

Maybe at a minimum make/standardize set the GPRBUILD parameters (ie -X[abcdef] to DEFAULT values across ALL your projects! (in other words don't set LIBRARY_TYPE to "static" by default when an upstream library has a default of "relocatable")

Thanks Alex

pmderodat commented 5 years ago

Hello @Alex-Gamper,

Thank you for your feedback!

Linking a library statically into a shared one makes it possible to link the same static library several times in the same program. This will duplicate code, but most importantly data (i.e. state), which violates Ada semantics, hence the restriction.

All of the projects you quote (XML/Ada, GPRbuild and Libadalang) support the same LIBRARY_TYPE scenario variable, so you should be able to make all of them use shared libraries when you pass -XLIBRARY_TYPE=relocatable to your gprbuild command-line. Is this what you tried?

Alex-Gamper commented 5 years ago

Hi AdaCore

With respect to point 1) I understand , And for point 2) Yes this is a solution, However the "default" scenario variable for LIBRARY_TYPE do not appear to be consistent across your GitHub projects, and if I don't specify a -XLIBRARY_TYPE then I get the original error mentioned above. As an example libadalang expects either "relocatable" or "default", But other gpr projects expect "relocatable" or "static" for the LIBRARY_TYPE scenario variable.

A nice feature would by for GPRBUILD to pass down to dependent gpr projects the invoked LIBRARY_TYPE ?? But this would mean standardization of both the name of the scenario variable and its values

food for thought !

In summary I can work around these issues, not ideal but I, as a very small developer can live with it

Alex

pmderodat commented 5 years ago

Good to know that this does not prevent you from working with these technologies. :-)

I’m concerned about the behavior you get by default. Libadalang’s project file, like all all other project files (XML/Ada, GNATCOLL, Libgpr, …) is supposed to use the LIBRARY_TYPE scenario variable, with two possible values (static, relocatable), with static being the default. This project file is generated from there: https://github.com/AdaCore/langkit/blob/master/langkit/templates/project_file.mako#L17

Not having static as the default for LIBRARY_TYPE for Libadalang can happen if you install Libadalang (ada/manage.py install) as a shared library only, which is the default in Libadalang. In order to install both flavors (static and shared), you need to do:

ada/manage.py --enable-static make
ada/manage.py --enable-static install $INSTALL_DIR

(side note: we planned to update Libadalang’s build procedures to mention this)

However, I don’t understand how default can be the default value. If anything needs to be done, I think it would be to investigate how this happens. At least I cannot reproduce. How do you know that Libadalang expects either relocatable or default, by the way? Have you looked at libadalang.gpr?

Your suggestion for GPRbuild to pass down the library type makes sense, and this is what is actually supposed to happen with with the current LIBRARY_TYPE setup: it’s a scenario variable, so it is shared by all projects files that GPRbuild loads. GPRbuild also checks that the value (passed or used by default) is valid in all contexts where it is used.

Alex-Gamper commented 5 years ago

Hi AdaCore

Thanks for the quick response, I was not expecting that! (given my time zone difference's) and yes I was NOT aware of the --enable-static flag to libadalang.gpr this should be documented in libadalang build procedures, Thanks !

I did look at the libadalang.gpr in {root}/share/gpr and the gpr file did originally contain the following (which I had to change for my purposes) Since I did NOT pass thru a value to the source GPR file for the scenario variable LIBRARY_TYPE. In future I MUST remember to set this up in my GPR file and pass this in on invocation (Please note that I am NOT actually using GPS as my IDE, by rather "VisualAda" So the issue is probably in my side in NOT specifying the LIBRARY_TYPE in the first place ??

If I have any more concerns, I'll raise a separate issue !

Thanks

Alex

library project Libadalang is type BUILD_KIND is ("relocatable"); BUILD : BUILD_KIND := external("LIBADALANG_LIBRARY_TYPE", external("LIBRARY_TYPE", "default"));

pmderodat commented 5 years ago

On the Internet, you never really know the timezone of others. ;-)

I have really no idea how this default could appear, and I definitely cannot reproduce. Just in case: what version of GPRbuild/GNAT do you use? (run gprbuild --version and gnatls -v to know). Are you using the current master branches of Libadalang/Langkit? What is you build/install procedure exactly?

In future I MUST remember to set this up in my GPR file and pass this in on invocation

What do you mean? You can’t change scenario variables directly in GPR files.

Also, what is VisualAda?

So, just in case there is still some ambiguity: unless there is a bug (and clearly here something is wrong), leaving the default should work just fine (defaulting to static libraries).

Alex-Gamper commented 5 years ago

Hi AdaCore

Version information for my toolchain is detailed below, and yes I am using the current master branch for libadalang (Note so is Gprbuild and Xmlada) The build procedures for Libadalang are as per the Readme on GitHub. (Note also that I am running under Windows 10 x64)

Maybe the issue is because I am using the master branch of gprbuild/gprinstall as the gpr file in the build directory looks fine wrt LIBRARY_TYPE, But the gpr file installed into {root}/share/gpr does not have the "static" option for LIBRARY_TYPE, I checked a second separate PC/Build and it has the same issue, Is the generation of the installed gpr file done via a mako template, or from within gprbuild ?

With respect to the GPR file, what I meant was, is that I need to set the BUILD_KIND, LIBRARY_TYPE in MY upstream application GPR file and then remember to invoke gprbuild with the appropriate value for the scenario variable (if different from the defaults)

Note that VisualAda is a "Visual Studio 2017" extension that allows editing, build and debug facilities for Ada based projects. It also has a number of templates (for example console, dll, lib and native services) to kick start development. It uses the visual studio project format, but generates a gpr file under the covers, which is invoked by Gprbuild. Apps can be debugged either via GDB or the native windows debugger, both from within the VS2017 IDE, Intellisense is currently limited, But I am hoping to extend this via libadalang ? :-)

VisualAda can be freely downloaded from the following URL

https://marketplace.visualstudio.com/items?itemName=AlexGamper.VisualAda

Alex

alexg@DESKTOP-Alex MINGW64 ~ $ gprbuild --version GPRBUILD Pro 18.0w (19940713) (x86_64-w64-mingw32) Copyright (C) 2004-2016, AdaCore This is free software; see the source for copying conditions. See your AdaCore support agreement for details of warranty and support. If you do not have a current support agreement, then there is absolutely no warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

alexg@DESKTOP-Alex MINGW64 ~ $ gnatls -v

GNATLS 8.2.0 Copyright (C) 1997-2018, Free Software Foundation, Inc.

Source Search Path:

C:\msys64\mingw64\lib\gcc\x86_64-w64-mingw32\8.2.0\adainclude Object Search Path: C:\msys64\mingw64\lib\gcc\x86_64-w64-mingw32\8.2.0\adalib Project Search Path: C:\msys64\mingw64\x86_64-w64-mingw32\lib\gnat C:\msys64\mingw64\x86_64-w64-mingw32\share\gpr C:\msys64\mingw64\share\gpr C:\msys64\mingw64\lib\gnat alexg@DESKTOP-Alex MINGW64 ~ $ gcc -v Using built-in specs. COLLECT_GCC=C:\msys64\mingw64\bin\gcc.exe COLLECT_LTO_WRAPPER=C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.2.0/lto-wrapper.exe Target: x86_64-w64-mingw32 Configured with: ../gcc-8.2.0/configure --prefix=/mingw64 --with-local-prefix=/mingw64/local --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --with-native-system-header-dir=/mingw64/x86_64-w64-mingw32/include --libexecdir=/mingw64/lib --enable-bootstrap --with-arch=x86-64 --with-tune=generic --enable-languages=ada,c,lto,c++,objc,obj-c++,fortran --enable-shared --enable-static --enable-libatomic --enable-threads=posix --enable-graphite --enable-fully-dynamic-string --enable-libstdcxx-filesystem-ts=yes --enable-libstdcxx-time=yes --disable-libstdcxx-pch --disable-libstdcxx-debug --disable-isl-version-check --enable-lto --enable-libgomp --disable-multilib --enable-checking=release --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-libiconv --with-system-zlib --with-gmp=/mingw64 --with-mpfr=/mingw64 --with-mpc=/mingw64 --with-isl=/mingw64 --with-pkgversion='Rev3, Built by MSYS2 project' --with-bugurl=https://sourceforge.net/projects/msys2 --with-gnu-as --with-gnu-ld Thread model: posix gcc version 8.2.0 (Rev3, Built by MSYS2 project)
Alex-Gamper commented 5 years ago

Hi AdaCore

On a separate but related issue/question, Is their a AdaCore document that defines common/standard scenario variables and their range of values ? This would be helpful for ISV's like myself that publish opensource libraries, which have a dependency on AdaCores's own opensource libraries

Things that spring to mind are

  1. BUILD_TYPE (ie prod/dev)
  2. LIBRARY_TYPE (relocatable/static)
  3. OS (ie operating system) (Linux/MacOs/Windows)
  4. RTS ??

I am happy to raise this as a separate issue (question) on GitHub and obviously contribute :-)

Thanks Alex

t-14 commented 5 years ago

The only one that merits a mention is LIBRARY_TYPE since this variable is used in installed projects. All others are transient build-time variables that we make no special effort to enforce.

pmderodat commented 5 years ago

Version information for my toolchain is detailed below, and yes I am using the current master branch for libadalang (Note so is Gprbuild and Xmlada) The build procedures for Libadalang are as per the Readme on GitHub. (Note also that I am running under Windows 10 x64)

Ok, then this is weird. I cannot reproduce: after running:

ada/manage.py make
ada/manage.py install path_to_install

After that, the only possible build kind in path_to_install\share\gpr\libadalang.gpr is relocatable, so no default. I’ve tried on x86-windows and I only have access to that, but I don’t think this should make any difference. You have a recent compiler and rebuilt all dependencies yourself, so everything should be fine in that regard.

Maybe the issue is because I am using the master branch of gprbuild/gprinstall as the gpr file in the build directory looks fine wrt LIBRARY_TYPE, But the gpr file installed into {root}/share/gpr does not have the "static" option for LIBRARY_TYPE, I checked a second separate PC/Build and it has the same issue, Is the generation of the installed gpr file done via a mako template, or from within gprbuild ?

If you don’t pass --enable-static to the manage.py script (all invocations) as I suggested in my previous messages, then it’s expected that LIBRARY_TYPE does not the static alternative (but just relocatable instead). The installed gpr file is created running gprinstall on build/lib/gnat/libadalang.gpr (likewise for langkit_support.gpr, by the way).

One one hand, AdaCore’s convention for project files is to assign static as the default for LIBRARY_TYPE; on the other hand, Libadalang is very useful to use from a Python interpreter, which needs a shared library, hence the default behavior of manage.py.

Note that VisualAda is a "Visual Studio 2017" extension that allows editing, build and debug facilities for Ada based projects. It also has a number of templates (for example console, dll, lib and native services) to kick start development. It uses the visual studio project format, but generates a gpr file under the covers, which is invoked by Gprbuild. Apps can be debugged either via GDB or the native windows debugger, both from within the VS2017 IDE, Intellisense is currently limited,But I am hoping to extend this via libadalang ? :-)

Cool! Adding support for Ada to Intellisense is one option, but given that Visual Studio will support the Language Server Protocol, leveraging https://github.com/AdaCore/ada_language_server seems to be the easiest way. :-)

Alex-Gamper commented 5 years ago

Hi AdaCore

Thanks for your detailed analysis, When I get time I'll try and rebuild using both --enable-static and --enable-shared and see what happens

With respect to intellisense support, I have 2 options

  1. Use ada_language_server, this uses redirected stdin, stdout to pass the Jason RPC messages between Visual Studio and Ada_language_server.exe. This can be easily hooked up via the sample instructions provided at https://docs.microsoft.com/en-us/visualstudio/extensibility/adding-an-lsp-extension?view=vs-2017

This can be made to work, and I have a done a proof of concept implementation which works, sort of :-) The problem/issue is that the MS LSP client wants to do statement completion on anything that's NOT a trigger character for the LSP server as a default, and it uses all the current document's tokens as possible matches. So for example if I type in " I " it matches all tokens that contain "I" and totally pollutes the completion list !

  1. Develop a native Visual studio "statement completion" as outlined in the VS SDK documentation. This however would entail using the libadalang C/C++ bindings via a C++/CLI wrapper library, this should be doable, and I hope to have a reference implementation in the next few weeks ?

Alex

pmderodat commented 5 years ago

Ok! In the meantime, I’ll close this (because we can’t reproduce). Nonetheless, if you have news, please send a note here, we can always re-open this issue. Thanks!