I have put libncurses.so.5 from /usr/pkg/lib to /usr/lib. It works now. It seems to me that your bindings don`t need adaption. I will check the library search path for gcc. It`s weird that the binary don`t find the right library, even when the -lncurses path is given.
Thanks a lot.
By the way. Why don`t you upload the bindings to the gnu-pascal site? Some little webspace for gpc bindings/stuff would be great. That`s also what fpc is doing.
Greerings Karim
Karim Forsthofer wrote:
The -L option only refers to link-time searching. For runtime searching, one often needs an additional option. Under Linux this would be -Wl,-R/usr/pkg/lib (sic!, one single option, without spaces), perhaps the same works under *BSD as well.
Yes, we have plenty of web space for contributions. If you (Willett) would like to get an account (ssh/scp/sftp), please mail me privately. Alternative, you can upload the package through the upload form (under "Downloads" ;-) on the web site.
Frank
On 8 Sep 2005, at 06:56, Frank Heckenbach wrote:
Frank:
Thanks for the invitation. I will. First, I am working on a more significant example program that makes intensive use of the ncurses library.... both as a more thorough test and as an example. Also odds and ends such as the cWordBool type that I'm hoping will be included in your next compiler release, and hoping to hear from some non-MacOSX people as to whether or not they need to adjust types, this would make my docs more generic. I'd do it as a "download".
Karim:
Could you do the following greps, which should yield something like the "typedef" on the following line. You may need to adjust for your directory, possibly not /usr/include :
iceland:~ willett$ grep chtype; /usr/include/curses.h typedef unsigned long chtype;
Same for: grep define\ NCURSES_ATTR_SHIFT grep NCURSES_BOOL;
or better (but more bother for you), run "configure" on the ncurses source, and send me the file "config.cache"
Adriaan or Frank:
My documentation is oversimplified in linking. It now says only:
"To insure the ncurses.pas interface is available, compile it with: gp ncurses.pas (the code contains {$L ncurses }, otherwise the compile line would require -lncurses)"
But the problem Karim encountered shows my doc is not enough on some non-OSX systems. I'm afraid I don't understand the diversity of library arrangments (nor even the linking mechanism) well enough to offer generic advice across gpc systems. I've made an ill-informed stab in the dark, below. Could I ask one of you to edit it? Then I'll copy it into the ncurses docs.
PROPOSED ADDITION TO GPC NCURSES DOCS, PLEASE EDIT:
To insure the ncurses.pas interface is available, compile it with: gp ncurses.pas (the code contains {$L ncurses }, otherwise the compile line would require -lncurses)"
When you compile your own programs, you must also EITHER include {$L ncurses } in the source code, or include -lncurses on the "gp" command line. Try just the above, if it works, skip the rest of this section. If the above does not work on your system, additional steps are needed to find the ncurses library at link and/ or load time.
For example, on one NetBSD system, the above {$L ncurses} alone produces an error like: 'Shared object "libncurses.so.5" not found'
You may need to locate the file "libncurses.so.5" and PLEASE ADD HERE A GENERIC DESCRIPTION OF WHAT IS BEING DONE.
For example, you might copy libncurses.so.5 from /usr/pkg/lib to / usr/lib.
Also, the -L option only refers to link-time searching. For runtime searching, one often needs an additional option. Under Linux this is the following, added to the "gp" command line each time you compile a program using ncurses: (OR/AND WHEN COMPILING NCURSES.PAS??) -Wl,-R/usr/pkg/lib (one single option, without spaces)
PLEASE FIX MY IGNORANCE IN THE ABOVE, THEN I'LL CLIP IT INTO DOC
Thanks to all,
Willett Kempton
willett wrote:
Note that gp is a separate download from http://fjf.gnu.de/. It is not included yet in the standard gpc distribution, although I am including (and recommending) it with the OS X distribution.
Anyway,
gp program.pas = gpc --automake -o program program.pas gp unit.pas = gpc --automake -c unit.pas
Regards,
Adriaan van Os
willett wrote:
gp scans all source files for {$L} directives, so you can put it in the unit and users won't have to put it in their programs. The same, BTW, also holds for gpc --automake, modulo the known automake problems.
You may need to locate the file "libncurses.so.5" and
This file name may be too specific and subject to change. "libncurses.so* or libncurses.a" might be more general. (Most linkers used by gpc can deal with dynamic or static libraries transparently. With the option -static, they will use static libraries, otherwise whatever they can find.)
Tell the linker where to find the libraries ...
For example, you might copy libncurses.so.5 from /usr/pkg/lib to / usr/lib.
Not really recommended. These directories should be managed by the system distribution only, also to avoid trouble with future system upgrades.
No, both -L and -Wl options are only needed for linking, i.e. when an executable is being produced. In other compilations they won't hurt, though, (except possibly for a harmless warning about them being unused -- at least with gpc, while gp filters out such options automatically when not needed), so it can be reasonable to put them in a global alias/wrapper script ...
Generally, if a library is in directory /foo/bar, you need the option -L/foo/bar and for dynamic libraries also -Wl,-R/foo/bar (again, please note, I've only used the latter on Linux, someone might report if it works elsewhere, or if another option is required).
For a few standard directories this is not necessary as they are predefined, but even /usr/local/lib is not among them in several Linux distributions I've seen (which I do not really understand), so it has become a rather common issue to me ...
Sorry for the chaotic writeup, you probably can't directly copy&paste it ...
Adriaan van Os wrote:
or gpc --automake --executable-file-name program.pas
(i.e., the capability of choosing the output file name based on the input file is also there in gpc, but with gp it's the default).
Frank
gp program.pas = gpc --automake -o program program.pas gp unit.pas = gpc --automake -c unit.pas
The latter brings me to the following for gp (see gp --help)
As far as I know, the opposite switch is not available, namely to compile *and link* a unit. This is useful when compiling a unit into a shared library, while still using the specs file instead of a separate ld run (which could be less compatible).
Of course, I can write a patch for gp to add this feature. Any suggestions for the switch to use ?
Regards,
Adriaan van Os
Adriaan van Os wrote:
Compiling to shared libraries requires more options. A simple compilation without `-c' won't do. So it's more involved than adding a switch.
For one thing, it requires all files to be compiled with `-fPIC' (position independent code). This might not be necessary on all targets, and the option may even be called differently on some, but in general this means compiling everything twice, so that static libraries don't incur the (slight) performance penalty of PIC.
Then, on Linux, I need options such as
-fPIC -shared -Wl,-soname=foo.so.1.2.3
The latter is required so if the library is linked to foo.so (as usual), and this is used for later linking in a program, the linker knows that the real name is foo.so.1.2.3, so it will use the correct version even if later another version was installed and linked to foo.so. (That's an important point of shared library version management.)
AFAIK, the libtool authors have spent quite some time (and not really all too successfully, IMHO) trying to automate this across platforms. Perhaps it will actually be somewhat easier to do in gp (which does the compiler invocations anyway) than in libtool (which needs to wrap all compiler invocations in a script, with its own set of problems). But still expect quite a bit of work and testing ...
Of course, I can write a patch for gp to add this feature. Any suggestions for the switch to use ?
Certainly a long name as there are already so many short names, and we should allow for future additions in the backend (as far as they'll make sense with gp). Perhaps something like `--create-shared-library=foo.so.1.2.3'. But that's really the least problem.
Frank
Frank Heckenbach wrote:
An option --create-shared-library would be nice, of course, but I understand that it can be a problem, at least across platforms. So, I were really only thinking of sending in a patch that implements a --compile-and-link option that overrules the automatic -c option for units, that's all (a five minute hack).
Given that option, It is no problem to create a dynamic library on Mac OS X with Darwin specific compiler options, like -dynamiclib (see <http://gcc.gnu.org/onlinedocs/gcc-4.0.1/gcc/Darwin- Options.html#Darwin-Options>). I checked this morning that gpc can actually create a dynamic library with one call (!). Through the specs, gpc invokes libtool and it creates the dynamic library (there was indeed a problem left but that's another issue that I still have to look at).
With gp, this is currently impossible, because of the automatic -c for units (which I agree is a good thing to have as default).
Regards,
Adriaan van Os
Of course, I can write a patch for gp to add this feature. Any suggestions for the switch to use ?
Could you make -c a toggle switch? So
no -c is compile only for main program, compile and link for program -c is compile only -c -c is compile and link
It's not without president for switches to toggle...?
Otherwise, perhaps --compile=auto/only/link or --compile-and-link
Just a thought.
For gp you'll also need to be careful that you can do:
gp subunit.p gp --compile-and-link mainunit.p
and not have gp decide that the options have changed and so it needs to recompile subunit.p.
Enjoy, Peter.
Peter N Lewis wrote:
It's without precedent and against the conventions I know of.
Still, with the current patch --compile-and-link doesn't overrule -c, so
gp ... -c ... --compile-and-link ...
doesn't link. If that's important, I have to rewrite the patch.
gp seems to recompile subunit.p in this situation anyway, independent of the --compile-and-link switch. I tried it with an unpatched gp-0.60. Can you confirm that this happens when you test it yourself ?
Regards,
Adriaan van Os
There are many uses of such toggling switches in unix programs. Lets see, curl:
--tcp-nodelay Turn on the TCP_NODELAY option. See the curl_easy_setopt(3) man page for details about this option. (Added in 7.11.2)
If this option is used several times, each occurrence toggles this on/off.
(and many other curl options)
That was the only one I could easily find by searching man pages for "toggle", but I'm sure there are others with different words in their man pages. As I said, toggling options are not without precedence - whether it is a good idea or not, I leave to someone else to decide.
Actually, you're right, there is something a bit funky going on for the explicitly specified file in the gp command line. I'll try to remember to take a look at some point. Interestingly, it only affects the directly specified unit, ie, if you have a tree like:
lowunit, medunit, highunit, then the sequence:
gp -c lowunit.p will compile lowunit.p
gp -c medunit.p will compile lowunit and medunit.
gp -c highunit.p will compile medunit and highunit, but will not recompile lowunit (it having been compiled as a secondary unit from the second command).
The affects my highly patched version of gp, so I expect it also behaves this way in the unpathced version, though I did not try that. I presume something in the way the primary file gpd is saved is subtely different to what is expected.
Ahh, I see, at least for me,
gp -c lowunit.p results in the gpd including the line:
g /Users/peter/Interarchy/Project/Build/IAObjects/.gpi
when it should have the line
g /Users/peter/Interarchy/Project/Build/IAObjects/lowunit.gpi
I haven't looked in to why.
The issue I raised is still valid either way though. Peter.
Ok, the problem is that there is no interface name determined for the "MainSrc" unit. This patch:
--- gp.pas (revision 373) +++ gp.pas (working copy) @@ -1330,7 +1330,7 @@ DoApplyAutoUses := True; pp := @Deps; while pp^ <> nil do pp := @pp^^.Next; - pp^ := NewDep (MainSrc, '', fk_Program, True); + pp^ := NewDep (MainSrc, LoCaseStr (NameFromPath (MainSrc)), fk_Program, True); DepToDo := pp^ end else
Should resolve it. It just uses the interface name as the lowercase of the basename of the MainSrc. The InterfaceName is not needed for compiling the main program, which is why this has gone unnoticed. I'm not sure if this InterfaceName determination is correct for modules.
Enjoy, Peter.
Peter N Lewis wrote:
I don't think so. Did you test it with a module that has a different interface name than its file name?
Frank
At 3:08 +0200 11/9/05, Frank Heckenbach wrote:
No, I would assume it wont work in that case. I'm afraid I have no idea even what the structure of a module is.
The patch should still be an improvement, it would at least work in the normal case, and should have no negative affect on any case (except perhaps a pathological case where you had two modules, each with an interface using the name of the other file).
A complete solution would presumably require parsing the file and determining its interface name. Perhaps GetDep needs to note that InterfaceName is '' and figure it out in the normal way? Or perhaps the way of kick starting the loop in CollectDeps needs to be adjusted so that MainSrc is simply a dependency of something non-existant, or CollectDeps could figure out the InterfaceName itself. It looks like the InterfaceName is not actually stored in the gdp, so that would seem to imply determining it requires reparsing the file, which obviously is not desirable, so perhaps the gpd needs to store the InterfaceName for this to work fully.
Can modules have multiple interface names? Peter.
Adriaan van Os wrote:
It's not without precedent, but IMHO too confusing in this case. And more confusion is just what we need WRT gcc/gpc/gp options. ;-)
And your second suggestion (which is not exactly toggling) is also quite nonobvious IMHO.
If it's not very much effort, this might be useful. Or a warning about nonsensical options.
gp has a mechanism to decide which options are relavant for recompiling or only relinking (see RecompileRelevant). Adriaan's patch doesn't make the option recompile-relevant, so it *should* work. But of course, there may be bugs in gp (outside of the patch). I haven't tested this situation very much, since I usually only compile complete programs with gp.
Frank
At 18:57 +0200 10/9/05, Frank Heckenbach wrote:
It's not without precedent, but IMHO too confusing in this case. And more confusion is just what we need WRT gcc/gpc/gp options. ;-)
I can't argue with that ;-)
I use gp on individual files to implement command-K, compile, which just compiles the unit I'm working on (and anything it depends on) and then displays any errors in an error browser window. It works very nicely. I'm glad Adriaan noticed the little glitch, as that explains a few times I wondered why it was compiling something I thought should be up to date. I'll try to track down the glitch on Monday if no one else has found it. Peter.
The included patch adds --compile-and-link to gp. I hope it's acceptable. It nicely creates a dynamic library on Mac OS X from a unit (while passing some extra needed options of course). Even better, the problem that I encountered this morning while trying this with gpc (.o files of compiled units weren't linked in) doesn't occur with gp !
Waldek Hebisch wrote:
At first sight, that looks somewhat strange (conceptually), because a library is a collection of routines, like a unit, not a program. Still, I will experiment with it, thanks for the hint.
Regards,
Adriaan van Os
Adriaan van Os wrote:
Looks alright. Though you might want to add a note in the documentation that linking will usually fail, unless the module/unit or something it uses provides a `main' function, or you're creating a dynamic library which requires additional options.
I also wonder if you (Waldek) misunderstood this option. It does not tell gp to compile and link. Instead it changes the linker name of the main program. I don't think it's applicable here.
Frank
Frank Heckenbach
--gpc-main option does not affect linking. But it allows to put pascal program (not a unit) in a library, by eliminating link error due to duplicate main. IIUC gp will link main program, even if other options tell it to make shared library.
It solves less problems that I thougt: my idea was to call fake main function to initialize the shared library. But there are two problems here: 1) main calls _p_finalize. So gpc runtime is unusable after main returns (could be solved by running _p_finalize via atexit) 2) main initializes arguments and environment, which should be done only by a program. Probably we should access environment via libc and initilaze arguments only when present.
Anyway, my attempt at shared libraries (I probably should call `_p_finalize' from ini.c):
gcc -c -fPIC -g ini.c /pom/kompi/gcc/tst44/gpc2-3.4.3/gcc/xgpc \ -B/pom/kompi/gcc/tst44/gpc2-3.4.3/gcc/ \ -shared -fPIC -fautomake -fgpc-main=mylib_main -g mylib.p ini.o -o libmylib.so gcc -g trr.c -L. -lmylib -Wl,-rpath=/pom/kompi/gcc/tst44/gpc2-3.4.3/gcc/ \ -Wl,-rpath=/tmp
Note: to make shared library one needs shared libgpc. My system gpc has only static libgpc, so I used another gpc copy (hence the long paths). Also, since the shared libraries are in non-system directories I need extra magic (`-Wl,-rpath=...' options) to say to the dynamic linker where to find them.
Note2: My goal was to have a dynamic library which is usable from non-Pascal main program. Except for `_p_finalize' problem the library can also be used from Pascal main program (and in principle one should be able to use multiple shared libraries).
-----------------<ini.c>----------------------------
extern void _p__rts_Init_init(void); extern void mylib_init(void);
void ini(void) __attribute__((constructor)) /* __attribute__((section (".init"))) */ ;
void ini(void) { _p__rts_Init_init(); mylib_init(); } -------------------------------------------------------
-------------------------<mylib.p>--------------------- program mylib; attribute (name = 'mylib'); uses u1; begin end . -------------------------------------------------------
-------------------------<u1.p>------------------------ unit u1; interface procedure p; attribute(name = 'mylib_p'); implementation procedure p; begin end; initialization begin writeln('u1 init') end; end . -------------------------------------------
Adriaan van Os wrote:
If you intend to use at most one shared library in a program then it is enough to use -fPIC (and for example i386 does not even require -fPIC). However, if you use multiple shared libraries and static libgpc, then each shared library will bring its own copy of libgpc. In particular there will be two copies of libgpc data. Depending on dynamic linker you will get dynamic link errors or subtle errors at runtime.
Waldek Hebisch wrote:
And -fPIC is the default on some platforms.
Unless global symbols from libgpc are marked as non-global in the shared library, e.g.
[G5:~] adriaan% gp --compile-and-link MainUnit.pas -dynamiclib -Wl,-init,_MyDylibInit -Wl,-install_name,@executable_path/MyDylib -o MyDylib -Wl,-exported_symbols_list,Symbols.txt
where Symbols.txt is the list of symbols that we want export from the shared library
[G5:~] adriaan% cat Symbols.txt _MyDylibInit _MyDylibTest
Regards,
Adriaan van Os
Adriaan van Os wrote:
That is the case of subtle errors: consider things like signal handlers or file buffers. You do not want handler from library A to clean up only library A when library B caused an error. You do not want to have two file buffers for a single file. While I have _not_ checked that any of the above may happen in gpc runtime, just by Murphy something will get broken.
Waldek Hebisch wrote:
I haven't strictly checked either, but I'm quite sure it would happen if you have two copies of RTS routines. There really should be a single copy of the RTS in a program. Whether this is a shared library of its own, or a static library included in one other shared library (only one and nohere else, including the main program), both could work, but the former is probably less error-prone ...
Frank
Waldek Hebisch wrote:
I see the point, but what is the difference between this situation (two shared libraries, each with a copy of libgpc) and e.g. one library written in Pascal and the other in a language xxx ?
_p__rts_Init_init(); mylib_init();
Is it better to call _p__rts_Init_init rather than _p_initialize ? Does everything get initialized correctly then ?
Regards,
Adriaan van Os
Adriaan van Os wrote:
What is better depends on goals. AFAICS if we only do the above then arguments and environment effectively will be empty. If a a Pascal main program dynamically loads the library, then call to _p_initialize will wipe out main program environment and arguments (IIUC normally dynamic linker loads libraries _before_ the main program, but it is possible to load libraries _after_ the main program has started).
Adriaan van Os wrote:
You mean the difference between one and two copies of libgpc? (Whether there are other libraries is irrelevant here.) As Waldek said, two copies means two copies of all the global variables such as Input and Output and several internal RTS variables. This will most likely lead to inconsistent results. E.g., imagine, two `Input's, each with its own buffer, and reading from `Input' will read from different buffers, depending from where it's called.
_p__rts_Init_init is an name used internally by the RTS. It should never be called from outside and could be changed anytime. _p_initialize is the function to be called from outside.
Waldek Hebisch wrote:
If that's a problem, IMHO we should find a proper solution instead of accessing RTS internals. One way would be to skip setting arguments if NULL (AFAIK, this can never happen in the main program).
For the environment, it's a bit more difficult, as there are two ways to get it -- the 3rd parameter to `main' and the `[__]environ' variable. The latter is POSIX, AFAIK, but not all systems really support it, so GPC supports both ways, to make it more likely to get the environment. But here, AFAICS, for the first way, we can do the same as for the arguments, and for the second one, we could use an internal flag, so the environment variable, if present, is only used once.
This require some changes in the RTS, but not too bad AFAICS. So if we decide that's what we need, I think I could do it quickly ...
An alternative would be a new flag (in the `Options' parameter), but AFAICS we don't actually need it.
Frank
Frank Heckenbach wrote:
I will be pleased with the change. Another idea is to create a separate routine for this (without parameters (or maybe only with the `Options' parameter))
procedure GPC_Lib_Initialize; attribute( name = '_p_lib_initialize');
GPC_Lib_Initialize can call into GPC_Intitialize with the right parameters. The advantage is that code doesn't break if the parameter list of GPC_Intitialize changes (as it did when the `Options' parameter was added). Then, GPC_Lib_Initialize is the routine to call when creating shared libraries or (e.g.) when linking Pascal code to a C program.
Regards,
Adriaan van Os
Waldek Hebisch wrote:
<snip>
Anyway, my attempt at shared libraries (I probably should call `_p_finalize' from ini.c):
I added my attempt for a dynamic library (of type MH_DYLIB) on Mac OS X. It is simply created with a call to gp:
[G5:~] adriaan% gp --compile-and-link MainUnit.pas -dynamiclib -Wl,-init,_MyDylibInit -Wl,-install_name,@executable_path/MyDylib -o MyDylib
Regards,
Adriaan van Os
----------
UNIT MyDylib; attribute( name = 'MyDylib'); {to set the external name of init routine}
INTERFACE
uses GPC;
procedure MyDylibInit; attribute( name = 'MyDylibInit'); {this routine is specified as the library's init entry point, with the -init ld switch}
{ Unlike bundle files and loadable bundle packages, dynamic libraries and frameworks on Mac OS X * are loaded automatically, rather than manually by application software * can not be unloaded (where bundles can) * can have linked-in version numbers * can have an initialization routine that is called automatically at load-time}
function MyDylibTest ( theInt1: CInteger; theInt2: CInteger): CInteger; attribute( name = 'MyDylibTest'); {just an example routine}
IMPLEMENTATION
type PCStringsPtr = ^PCStrings;
function NSGetEnviron: PCStringsPtr; external name '_NSGetEnviron'; {see the declaration in /usr/include/crt_externs.h on Mac OS X}
procedure GPC_Initialize ( theArgumentCount : CInteger; theArguments : PCStrings; theStartEnvironment : PCStrings; Options : CInteger); external name '_p_initialize'; {exported by gpc's runtime library}
procedure MyDylibUnitInit; external name 'MyDylib_init'; {re-import the compiler glue code that initializes this unit}
var gDummyArguments: array[ 0..1] of CString = ( 'MyDylib', nil);
procedure MyDylibMyInitStuff; begin {whatever} end;
procedure MyDylibInit; begin GPC_Initialize ( 1, PCStrings( @gDummyArguments), NSGetEnviron^, 0); MyDylibUnitInit; {$local W-} MyDylibMyInitStuff {$endlocal} end;
function MyDylibTest ( theInt1: CInteger; theInt2: CInteger): CInteger; begin MyDylibTest:= theInt1 + theInt2 end;
END.