-
Notifications
You must be signed in to change notification settings - Fork 161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add GAP kernel API (aka libgap) #2702
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2702 +/- ##
==========================================
+ Coverage 75.79% 75.79% +<.01%
==========================================
Files 479 480 +1
Lines 241471 241483 +12
==========================================
+ Hits 183022 183044 +22
+ Misses 58449 58439 -10
|
src/libgap-api.c
Outdated
/*** Integer *************************************************************/ | ||
/*************************************************************************/ | ||
|
||
Obj GAP_IntObj_Int( Int value ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang-format all new files?
src/libgap-api.c
Outdated
|
||
void GAP_SetElmPList( Obj list, Int pos, Obj elem ){ | ||
SET_ELM_PLIST( list, pos, elem ); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honest open question: I wonder whether there is an actual reason (e.g. extreme performance needs?) for why this "API" exposes potentially dangerous low-level functions like SET_ELM_PLIST
, or even AssPlist
-- wouldn't it be more useful and safer to expose ASS_LIST
, ELM0_LIST
, LEN_LIST
, etc.?
I just had a look at the sage code, and also at https://hackmd.io/emNi76svSWCh1fBeLKqPdA# (which @nthiery and me created together). Some notes:
LEN_PLIST
is used once in SageMath -- incorrectly, though, as it is also called on ranges, blists, strings -> should really useLEN_LIST
instead- as far as I can tell, no other GAP function with the string
plist
(upper or lower case) is used by SageMath, although a few more are imported (but then not used)
Perhaps @sebasguts "needs" some of them? Is there perhaps a code repository somewhere to look at?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finding what the correct API is is, in my opinon, the name of the game for the immediate future of "LibGAP".
Fort that its important to know use-cases. I wasnt aware of https://hackmd.io/emNi76svSWCh1fBeLKqPdA#, and as a non-user of this library of course completely oblivious to what people want to do.
src/libgap-api.c
Outdated
|
||
void GAP_Finalize(void) | ||
{ | ||
FinishBags(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the intention behind GAP_Finalize
? It makes GAP impossible to use afterwards, but is far from deinitializing it completely; e.g. it does not close file descriptors, nor does it call finalizers ("free functions") for any bags, hence it won't free external data allocated by external modules like NormalizInterface
. It doesn't terminate child processes, etc.
So, all in all, this function is currently of rather limited use. Hence I would suggest to either remove it; or else at least add a comment explaining its incomplete state.
Oh, and it won't work with Julia GC or Boehm, but that holds for other things in this PR, too (though most other stuff should be easy to adjust).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intention is to finish the GAP "session", and be able to GAP_Initialize
again, having a fresh GAP session.
Of course better yet, in future, if we have all state encapsulated, we'd be able to run multiple GAPs in one process.
That said, if noone sees a use for this, we can just leave it out for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not think we would need this in OSCAR for now, so I think it could be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd quite like to be able to finalize GAP for my racket bindings, otherwise using libgap in drracket is a bit of a pain, as it crashes on reload. I might be able to address this issue by unloading the .so file, but have to check whether that's possible.
Either way, its for me to implement if noone else wants it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I wrote, I am neutral on whether to keep it or drop it; but if kept, I still recommend to add a warning comment, like // TODO: this function does not yet free all state held by GAP, e.g. it does not close any open file handles or kill child processes
. But in the end ... shrug
src/gasman.h
Outdated
* If not 0 this function will be called in | ||
* CollectBags to allow users of libgap to mark bags | ||
*/ | ||
extern TNumExtraMarkFuncBags ExtraMarkFuncBags; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd strongly prefer if we did not expose a global variable like this, but instead provided a SetExtraMarkFuncBags(TNumExtraMarkFuncBags func)
setter function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #2706
src/libgap-api.c
Outdated
#include "plist.h" | ||
#include "stringobj.h" | ||
|
||
Obj FuncREAD_ALL_COMMANDS(Obj self, Obj instream, Obj echo, Obj capture, Obj resultCallback); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This must go into a header file which is included in both this file here, and the file which declares FuncREAD_ALL_COMMANDS
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #2707
tst/testlibgap/0001.c
Outdated
printf("Input:\n%s", cmd); | ||
res = GAP_EvalString(cmd); | ||
rc = GAP_LenPList(res); | ||
for(i=1;i<=rc;i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang-format?
tst/testlibgap/0001.c
Outdated
ires = GAP_ElmPList(res, i); | ||
if( GAP_ElmPList(ires, 1) == True ) | ||
printf("Output:\n%s\n", CSTR_STRING(GAP_ElmPList(ires, 5))); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it perhaps be helpful to print the output in the same format as a .tst
file?
(Fine by me to leave it as is, just wondering)
Makefile.rules
Outdated
@@ -995,6 +1002,14 @@ testbugfix: all | |||
ReadGapRoot( "tst/testbugfix.g" );' | $(TESTGAP) | \ | |||
tee `date -u +dev/log/testbugfix2_%Y-%m-%d-%H-%M` ) | |||
|
|||
obj/libgap-test-0001.lo: $(top_srcdir)/tst/testlibgap/0001.c | |||
$(QUIET_CC)$(COMPILE) $(DEPFLAGS) $(GAP_CFLAGS) $(CC_EXTRA_FLAGS) $(GAP_CPPFLAGS) -c $< -o $@ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is CC_EXTRA_FLAGS
? Is this an accidental left-over, or meant to introduce C flags just for testlibgap
?
Other than that, with PR #2704 this build rule could go, and the general *.c build rule would take of compiling this C file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is, I believe, an accidental leftover from the history of trying to get libgap into master
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With PR #2704 merged, I think this rule can just be removed (after a rebase, I mean)
Makefile.rules
Outdated
obj/libgap-test-0001.lo: $(top_srcdir)/tst/testlibgap/0001.c | ||
$(QUIET_CC)$(COMPILE) $(DEPFLAGS) $(GAP_CFLAGS) $(CC_EXTRA_FLAGS) $(GAP_CPPFLAGS) -c $< -o $@ | ||
|
||
testlibgap: libgap.la obj/libgap-test-0001.lo |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
Makefile.rules
Outdated
$(QUIET_CC)$(COMPILE) $(DEPFLAGS) $(GAP_CFLAGS) $(CC_EXTRA_FLAGS) $(GAP_CPPFLAGS) -c $< -o $@ | ||
|
||
testlibgap: libgap.la obj/libgap-test-0001.lo | ||
$(QUIET_LINK)$(LINK) obj/libgap-test-0001.lo libgap.la -o test-libgap |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would recommend to always use $<
, $@
etc. instead of duplicating the names of inputs and outputs, for the usual reasons why one should avoid code duplication. So here that could become:
testlibgap: libgap.la obj/libgap-test-0001.lo
$(QUIET_LINK)$(LINK) $+ -o test-libgap
...
Additional thought: all other files related to this test are named 0001.FOO
, would you mind if the executable then was named 0001
(or 0001.exe
or 0001.prog
or whatever)? That would then suggest a clear why how to generalize this to more tests (i.e. just provide a list of stem names for tests; then for each such name "FOO", compile FOO.c
into FOO
(or FOO.prog
or whatever), run it with input file FOO.in
(if present), send output to FOO.out
and diff it against FOO.expect
.
And most importantly, it would enable us to resolve issue #1917, i.e., start providing kernel based tests for some features which are otherwise difficult to test (such as ObjInt_Int
and its various siblings).
I can make these changes later, of course, simply want to hear what others think of the general idea.
Should we get rid of the "--enable-libgap" configure switch? It currently (as far as I can tell) serves no useful purpose other than to confuse people (me); a dynamically linkable object could be created either way; we could just link the |
To add some more detail: the (I am not sure about the usefulness of the |
I'd be fine with removing the |
{ | ||
InitializeGap(&argc, argv, env); | ||
SetExtraMarkFuncBags(markBagsCallback); | ||
STATE(JumpToCatchCallback) = errorCallback; |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
Only marginally related: Where the heck does the spurious |
src/libgap-api.c
Outdated
|
||
void GAP_SetElmPList(Obj list, Int pos, Obj elem) | ||
{ | ||
SET_ELM_PLIST(list, pos, elem); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wrote the following before, but due to updates to this PR, it is now hidden; but I still would like a reply by @sebasguts on this:
Honest open question: I wonder whether there is an actual reason (e.g. extreme performance needs?) for why this "API" exposes potentially dangerous low-level functions like SET_ELM_PLIST
, or even AssPlist
-- wouldn't it be more useful and safer to expose ASS_LIST
, ELM0_LIST
, LEN_LIST
, etc.?
I just had a look at the sage code, and also at https://hackmd.io/emNi76svSWCh1fBeLKqPdA# (which @nthiery and me created together). Some notes:
LEN_PLIST
is used once in SageMath -- incorrectly, though, as it is also called on ranges, blists, strings -> should really useLEN_LIST
instead- as far as I can tell, no other GAP function with the string
plist
(upper or lower case) is used by SageMath, although a few more are imported (but then not used)
Perhaps @sebasguts "needs" some of them? Is there perhaps a code repository somewhere to look at?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, @markuspf replied:
Finding what the correct API is is, in my opinon, the name of the game for the immediate future of "LibGAP".
I have a clear opinion on this: such an API should overall aim to provide high-level APIs at first; and only add lower-level APIs if there is a strong justification that make the higher level APIs unsuitable (and even then, I'd first investigate making the higher level APIs better). In this case, I think it's a mistake to export all those plist accessors, when we already have generic list accessors. The only reason to use the plist ones is raw performance, but a sizeable portion of that is sacrificed by these non-inlined wrappers anyway. There may be other reasons to export plist-only APIs, but these then should be conscious decisions (and ideally explained in comments).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That said, if you guys really, really want to expose these plist APIs (even though e.g. GAP_SetElmPList
is impossible to use correctly via the provided API GAP_SetElmPList, since CHANGED_BAG
is not exposed), fine, go ahead -- but I think it runs totally against the idea of creating a long-term stable API, as naturally lower level interfaces are much more likely to change than higher level ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more note regarding the symbols used by SageMath: a lot of the low level ones come from the function gap_eval
. My suggestion here would be to try and replace most of it by using READ_ALL_COMMANDS
, or a similar new function. To get somewhere quickly, I'd not worry about making the ideal generic function we all want in the long run, but just something that does precisely what SageMath needs; we then may have to touch this again later down the road, but I think that'll be much easier once we on the GAP side have clear insights on what you need. Perhaps @nthiery has thoughts on this, too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is precisely what GAP_EvalString
does (or, well, is supposed to do!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fingolfin said
Also, @markuspf replied:
Finding what the correct API is is, in my opinon, the name of the game for the immediate future of "LibGAP".
I have a clear opinion on this: such an API should overall aim to provide high-level APIs at first; and only add lower-level APIs if there is a strong justification that make the higher level APIs unsuitable (and even then, I'd first investigate making the higher level APIs better). In this case, I think it's a mistake to export all those plist accessors, when we already have generic list accessors. The only reason to use the plist ones is raw performance, but a sizeable portion of that is sacrificed by these non-inlined wrappers anyway. There may be other reasons to export plist-only APIs, but these then should be conscious decisions (and ideally explained in comments).
I completely agree. The API that is in libgap-api.c
right now is what I stole from @sebasguts' code, the only "high level" function I added is GAP_EvalString
.
I will update this PR with a basic API which I think is useful (informed by the hackmd document you hinted at, and an effort of mine of tying GAP into racket and idris. Needless to say that feedback from serious users of the API (i.e. SageMath and Oscar) would be incredibly useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for being late to the show. I would be perfectly happy with the lowercase-functions, actually. I am not very picky here, we would need to do the input checks done by the lowercase versions for OSCAR anyway. I doubt there is a speed difference when doing it from julia or from GAP. Code to look at can be found here: https://github.com/oscar-system/LibGAP.jl/blob/master/src/libgap.jl
Furthermore, I also think the way @markuspf did the new version is also good!
src/libgap-api.c
Outdated
|
||
Obj GAP_CallFuncList(Obj func, Obj arg_list) | ||
{ | ||
return CallFuncList(func, arg_list); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
arg_list
-> argList
? (to follow our general naming conventions)
src/libgap-api.h
Outdated
/*************************************************************************/ | ||
|
||
// CallFuncList | ||
Obj GAP_CallFuncList(Obj, Obj); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Repeating more now-hidden comments:
Personally, I don't like that all argument names are omitted, esp. as there is virtually no documentation; so one has to look at the implementation to figure out what the various functions here do -- also, curiously, in some cases (GAP_AssPList
, GAP_ValGVar
, ....) the argument name was left in.
That's not a blocker, but since you announced that I may not complain about anything that I don't mention upfront, I'll point out every little detail.
tst/testlibgap/basic.c
Outdated
printf("gap> %s\n", cmd); | ||
res = GAP_EvalString(cmd); | ||
rc = GAP_LenPList(res); | ||
for(i=1;i<=rc;i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang-format?
tst/testlibgap/basic.c
Outdated
{ | ||
printf("Initializing GAP...\n"); | ||
GAP_Initialize(argc, argv, environ, 0L, 0L); | ||
printf("done\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: Maybe change to
printf("# Initializing GAP...\n");
GAP_Initialize(argc, argv, environ, 0L, 0L);
printf("# done\n");
so that the output file becomes a valid .tst file?
The spurious ^M comes from the Browse package, see issue #430 |
(So you can avoid it if you e.g. start gap with the |
Just to note: I did not intend to hide the comments (I even copied them into a textfile on my machine to not forget about the points raised), but I am fiddling on this PR to move it closer to mergeability (or being obsoleted by smaller PRs, whichever comes first) |
Generally this looks good to me. On the "plist" question. I agree with the general sentiment of not exposing In this context, the use case would be a libGAP client that needed to put some objects in a list to pass to some GAP function. In that context it is natural and safe to use
I don't know what the performance penalty fro going through I wonder if it might be appropriate to add an API function that simply does this whole job -- takes a C array (or C++ vector) of GAP objects and makes them into a GAP list. Less critically, one could do something similar for records. |
While I agree that a conversion function that takes a C array of GAP refs and turns it into a plist, I would suggest to only add APIs they are explicitly requested. |
I also would want to think about a function that made a plist from an array, because I would worry about people mallocing that array, which would be bad (as the GC wouldn't see it while it was in malloced memory). |
With regards list functions, I would prefer to only share this like AssList, and maybe wrap new plist to not require the last option which requires a tnum. My preferred design would be to have some way of marking functions which can cause crashes with UNSAFE, or some similar marker, and encourage people to mostly use functions which check their arguments. However some external users might think that wouldn't be fast enough (I think the they would be wrong) |
Not that this is not a requirement. Also we could "officially" mark the API as subject to change (by putting a if comment on the file /release notes), which would give us the chance to make changes with our first couple of users of the gap API. |
What would be that "first half" to be committed? Something like this?
Also, while I am not overly fussed with names, I have in the back of my head some opposition to calling this baby My (current) preferred name is GAP (or just API), and calling the includes either |
@fingolfin you might notice that I indeed put "WIP" in the title to signify that this is work in progress, i.e. experimentation, but visible to interested parties so they can, if they want to, comment. I also don't believe that this code, as is, compiles at all. I am aware of the problems wrt |
Sorry, I missed the title change |
f7cae72
to
4eb1b46
Compare
Updated to only contain the "first half" of the original PR; To make even I'd like to move towards merging this PR now, which means: please comment about things that need to be changed now to get this merged, and I'll open a new PR with a proposed API for more advanced work. |
054c98e
to
5b21da2
Compare
Note that we need #2723 for this now to stop GAP from starting an invisible shell which blocks the process that calls |
7a5e877
to
b084bea
Compare
.travis.yml
Outdated
@@ -108,6 +108,9 @@ matrix: | |||
# test error reporting and compiling (quickest job in this test suite) | |||
- env: TEST_SUITES="testspecial test-compile" | |||
|
|||
# test libgap | |||
- env: TEST_SUITES="testlibgap" CONFIGFLAGS="--enable-debug --enable-Werror" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those CONFIGFLAGS can be dropped now, they are the default ones.
Makefile.rules
Outdated
@@ -395,6 +397,8 @@ gap$(EXEEXT): $(OBJS) cnf/GAP-LDFLAGS cnf/GAP-LIBS cnf/GAP-OBJS | |||
|
|||
endif | |||
|
|||
libgap.so: $(OBJS) | |||
$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) -shared $(OBJS) $(GAP_LIBS) -o $@ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm... I just realized that the libgap
target does not depend on libgap.so
; and we already have a libgap.la
; something does not quite add up here?!
src/libgap-api.c
Outdated
UInt len; | ||
|
||
if (IS_STRING(string)) { | ||
copy = CopyToStringRep(string); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This creates a copy, even if the original string was already in string rep. Perhaps instead do this:
if (!IS_STRING_REP(string) string = CopyToStringRep(string);
and then use string
instead of copy
below?
src/libgap-api.h
Outdated
// Users of GAP as a library currently call directly into | ||
// GAP kernel functions. In the future we would like to hide | ||
// all GAP internal functions (in the .so/.dll file) and only | ||
// allow access to GAP via functions defined in this file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do "we"? This is a goal some of us might have; but it would also force all kernel extensions to be rewritten, for no clear gain, so even among us I am not sure this is universally supported; and there are several folks who have not chimed in on this at all yet.
Personally, I am not yet convinced this approach with a brand new API created for external consumption is viable. I remember similar approaches taken e.g. by OS vendors in the past; almost always people search for (and found) ways to work around this, because the "official" APIs just were missing too many useful or even crucial things.
Another problem with such external API is that it means GAP kernel developers won't "dogfood" them: I'll probably never use these APIs, thus won't be aware of issues with them, won't be in a good position to maintain them.
All in all, I really prefer what the Julia folks did, where they simply mark select functions as "official", by adding something like "GAP_EXPORT" for such symbols. The main (only?) issue people seem to have with that in GAP is namespacing, and the risk of name clashes, which Julia mostly avoids by adding the jl_
prefix to all identifiers. But there are ways around that, too; e.g. using #define's to rename all APIs in GAP transparently; or even just simply adding a GAP specific prefix.
Anyway, don't get me wrong: I am not opposed to merging this as-is for now, as long as people keep an open mind to revise and revisit this as needed; I'd hope that developing more actual "clients" for the API wil make it much clearer what works and what doesn't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I have to admit that I am losing patience with this as well. I am not (productively) using this API, and none of the "stakeholders" have chimed in either; yet "we" (mainly you and me) have sunk quite a bit of time dancing around this tree.
So unless we get feedback from @nthiery or @sebasguts I'll remove the custom API functions, I suggest we merge just the building of the dynamic object file and the GAP_EvaluateString
, and leave it at that unless a demand shows up (together with a person who implements that).
The only additional thing I can suggest is emailing the GAP developers mailing list and see whether any feedback transpires there.
Well, I have to admit that I am losing patience with this as well. I am
not (productively) using this API, and none of the "stakeholders" have
chimed in either; yet "we" (mainly you and me) have sunk quite a bit of
time dancing around this tree.
Yeah, I know; I am sorry the timing does not work right. It's
frustrating for me as well not to be able to jump in the discussion at
a time where you are available and investing a lot of efforts. I'd
rather be playing with the new GAP API than taking care of reports as
I have been doing in the last two weeks. Gosh, one more week to go;
and then teaching starts ...
Overall my impression is that, on Sage's side, we could adapt quite
easily whatever the API is. From the discussions we had you know the
kind of feature we need. So proceed to wherever feels best from GAP's
perspective.
|
@@ -389,13 +388,16 @@ gap$(EXEEXT): libgap.la cnf/GAP-LDFLAGS cnf/GAP-LIBS cnf/GAP-OBJS | |||
|
|||
else | |||
|
|||
all: libgap.so | |||
libgap.so: symlinks libgap.la | |||
$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) -shared $(OBJS) $(GAP_LIBS) -o $@ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Disclaimer: the following is not meant to block this PR as such, just tries to clarify some background.
When I just looked at the above lines, I wondered again about the relation between libgap.so and libgap.la. There is now a dependency here -- but there seems no strict technical reason.
Moreover, on Mac OS X, the suffix .so is wrong, it should be .dylib. And of course on Windows one would expect gap.dll or so. But on Windows, we technically already build GAP into a DLL, as we need that, in order to be able to support kernel extensions at all.
However, all this has an "easy" solution: libgap.la already builds a shared library. That's what libtool .la files are for: they abstract over static/shared libraries in a portable way. Building libgap.la
creates .libs/libgap.dylib
for me on Mac OS X. Specifically:
$ ls .libs/
libgap.0.dylib libgap.dylib libgap.la libgap.lai
So it already takes care of things like file extensions.
We abuse this for the Cygwin builds:
bin/$(GAPARCH)/gap.dll: symlinks libgap.la
cp .libs/cyggap-0.dll $@ # FIXME: HACK to support kernel extensions
But that' a bad HACK, which I only added to make things work quickly. In reality, one should not directly access files in .libs
, but rather use the libtool
script to use these files, e.g. to link against them, or to install them.
Indeed, installing a .la
may cause libtool to relink it (because the rpaths and other settings that one needs to use the library may differ between when using it inside a build directory during development; and when using it as a system wide installed library).
This all means that this libgap.so
target should be temporary at best. What we should do instead, though, depends a bit on how libgap.so
is supposed to be used: are people right now linking against it by specifying -L/path/to/GAPROOT -lgap
? If so, and if they are using GNU libtool as well, they are better of specifying /path/to/GAPROOT/libgap.la
. If so, but they are not using GNU libtool, it becomes a bit tricky.
Of course, if instead one requires people to do a make install
from within GAP (which is not fully implemented, in particular the libgap part...), then all that goes away...
All in all, the best long term solution probably is to finally implement make install
, or at least enough of it to make libgap usable by clients. I always planned to work on that eventually (but demand wasn't exactly high), and would be happy to collaborate on it, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way I use libgap
at the moment is by
(define-ffi-definer define-gap
(ffi-lib "/home/makx/git/gap/master/.libs/libgap.so"))
in Racket (well knowing that this is of course at best a hack, too). If libgap.so were installed, I'd probably be able to just use `ffi-lib "gap".
I do not require header files, but I have to give GAP_Initialize
the path to the GAP library. I believe this is mostly how SageMath uses libgap as well.
The reason the .so
target is there is because I apparently still did not understand libtool. I did remember that the .la
file is all we need, and that the .so
file just appeared for me in .libs
.
Happy to learn how to do the make install
so that enough people are happy (but for that we need people to use it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be OK with merging this as it currently is (not much is left... ;-). The issue with libgap.la vs. libgap.so can be resolved later and separately.
What we should do instead, though, depends a bit on how libgap.so is
supposed to be used: are people right now linking against it by
specifying -L/path/to/GAPROOT -lgap? If so, and if they are using GNU
libtool as well, they are better of specifying
/path/to/GAPROOT/libgap.la. If so, but they are not using GNU libtool,
it becomes a bit tricky.
...
All in all, the best long term solution probably is to finally
implement make install, or at least enough of it to make libgap usable
by clients. I always planned to work on that eventually (but demand
wasn't exactly high), and would be happy to collaborate on it, too.
From Sage's (and packagers I assume) perspective: make install would
be great. But in the meantime, since we are using autotools in many
other places anyway, it should be fine to use libtool. I would just
need to double check our build rule since Cython is involved too, and
I don't remember whether Cython does the linking too.
|
Squashed and rebased on master. If tests pass I'll merge this. |
This pull request is the next logical step in providing GAP as a dynamically loadable library (known by some as LibGAP).
I squashed a whole history of commits developed by @sebasguts, @fingolfin, and me into a single commit because it's not that big anymore. If there's certain bits you'd like committed separately, speak now or forever hold your peace.
It would be good if @sebasguts (for @oscar-system) and @nthiery (for SageMath) as the main "clients" could have a look to see whether this is going towards what they are hoping for.
For the future there needs to be more documentation, and more thorough testing, and a more comprehensive API.
For a future pull-request I am thinking about making a command-line-switch
--disable-shell
which disables the repl (basically removing the need forIsLIBGAP
, at least right now, and I can't think of another usecase for this particular constant.