OCaml default include directory and default ocamlrun location - macos

I have compiled OCaml from source on my mac (the host), and I have no problem. I have also cross-compiled OCaml on my mac for some target (different from the host) and in this case I have the following issues :
1) I can use directly (on the target) ocamlrun and ocamlyacc as they are "pure" binaries, without problem, as on the host. If I want to use other binaries from $INSTALL/bin ($INSTALL is the install directory of ocaml on the target) like ocamlopt, I have errors telling my that the path of ocamlrun is wrong. Indeed, if I open the ocamlopt binary with and hexadecimal editor, I see that it begins with a #!/not/target/but/host/path/to/ocamlrun where the path is the path to ocamlrun on the host (my mac) on which I configured the cross-build, not the path to its target version... Of course, if I replace this path by the one on the target, no need anymore to do ocamlrun ocamlopt, everything is ok. Same for all others binaries from $INSTALL/bin, ocamlrun and ocamlyacc put aside. (The last two do work directly, as I wrote above.) Is there a way to configure (on host) the ocaml cross-build so that the right path for ocamlrun on the target appears directly at beginning of binaries from $INSTALL/bin ?
2) I cannot compile code without needing to specify the $INSTALL/lib/ocaml dir through the -I flag. Is there a way to force this standard libraries path at the configure ? Or any ocaml "internal" environment variable dealing with it that I could edit to be sure that ocaml will look for libs in $INSTALL/lib/ocaml ? (I am quite pessimistic for an environment variable solution as on the host I only have two environment variables (at printenv) concerning ocaml and no one seems to deal with this kind of stuff, so that I don't see why it would go differently/better on the target...)

Related

Cmake implicit link directory paths and how to set/override to enable building a common sandbox on different OS versions w.r.t lib dependencies

I work with a large source tree that builds with cmake (rev 3.9.6). I often check the tree
out into a common NFS mounted path, and then build the sandbox on different machines (mounted
thru a common NFS path).
I would ideally like to be able to first build the tree on a CentOS7 system, and
then log into a CentOS8 system, type make from the top of the tree, and see
there is no need to reconfigure anything (cmake) or rebuild anything (all
make dependencies satisfied).
All the binaries built on the CentOS7 system run on the CentOS8 system and it looks
like all tests pass on both CentOS7 and CentOS8. It also works to build the source tree
from scratch on a CentOS8 system as well (after dealing with how compiler warnings changed for
the newer compilers on CentOS8).
In practice I've found that building first on CentOS7 causes cmake generated files
(build.make) to end up with a CentOS7 gcc compiler specific path in them as a make dependency.
Or it looks to me like these generated cmake files from the CentOS7 build,
<top of tree>/CMakeFiles/3.9.6/{CMakeCCompiler.cmake,CMakeCXXCompiler.cmake}
set the serarch paths for the compiler and system libraries via,
set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-redhat-linux/4.8.5;/usr/lib64;/lib64;/usr/lib")
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-redhat-linux/4.8.5;/usr/lib64;/lib64;/usr/lib")
The first path, /usr/lib/gcc/x86_64-redhat-linux/4.8.5, is unique to the compiler
version on CentOS7 and so does not exist on CentOS8. A cmake generated dependency using this path (in build.make files)stops
make dead in its tracks when typing make at the top of the sandbox in NFS on a CentOS8 machine
because it can't resolve the non-existant path:
foo: /usr/lib/gcc/x86_64-redhat-linux/4.8.2/libgomp.so
However, that pathname to libgomp.so thru the CentOS7 gcc path is a soft link,
/usr/lib/gcc/x86_64-redhat-linux/4.8.2/libgomp.so -> ../../../../lib64/libgomp.so.1.0.0
Or the same version of libgomp.so (libgomp.so.1.0.0) will be referenced on CentOS7 by:
/usr/lib/gcc/x86_64-redhat-linux/4.8.2/libgomp.so
/usr/lib64/libgomp.so.1
Alternately, on CentOS8 libgomp.so.1.0.0 is found via the paths:
/usr/lib/gcc/x86_64-redhat-linux/8/libgomp.so
/usr/lib64/libgomp.so.1
I've experimented with removing the gcc specific path from the implicit link cmake
variables to instead have,
set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib64;/lib64;/usr/lib")
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib64;/lib64;/usr/lib")
But the CentOS7 compiler specific path will still be found via the /usr/lib entry and I cannot exclude
/usr/lib as a search path altogether. I would really just like to exclude /usr/lib/gcc (?) as an implicit search path
and even then I would have to specify linking against libgomp.so.1 or libgomp.so.1.0.0 instead of libgomp.so.
(BTW - I'm not sure setting those cmake variables explicitly before the project statement in the top level
CMakeLists.txt file worked, but I did not see any way to modify/change how the CMakeC[XX]Compiler.cmake files
are generated in the first place).
Now I could add a custom command to trigger PRE_BUILD on every cmake target to edit any cmake generated build.make
with that the dependency such that,
foo: /usr/lib/gcc/x86_64-redhat-linux/4.8.2/libgomp.so
... edited thru custom command becomes...
foo: /lib64/libgomp.so.1.0.0
This does in fact work and allows make to finish checking (and find) all dependencies when I run it from the top
of the tree on CentOS7 or CentOS8 (after first building on CentOS7). But I would prefer not to retroactively edit
cmake generated files.
So happy to hear any suggestions or if it's just unreasonable to expect to achieve this kind
of parity when building the same NFS mounted sandbox on two revs of the OS with different compiler (revisions and paths), i.e.,
the "right" thing to do is to always re-run cmake on CentOS8 and then rebuild everything on CentOS8.

How to run a C program in android-x86 terminal?

I have to C program which is compiled using gcc in ubuntu. I want to run that executable in android terminal. When i run it is showing either "file or directory is not found" or "not executable:ELF32".
I want to run the code in android terminal. Is there any way or flags in gcc or using any other compiler so that i can run my code in the android terminal.?
Android does not use the same system libraries as Ubuntu, so they will not be found.
There are two solutions:
Copy the libraries you need.
If you can place them in the same filesystem locations they have in Ubuntu then great, otherwise you'll need to run the ld-linux.so manually and tell it where to find the libraries. Or, you could relink the program such that it expects to find the dynamic linker and libraries in a non-standard place. You might also use a chroot, but that requires root, and you'd need to find a chroot binary that works.
Use a static link.
This usually just means passing -static to GCC. You get a much larger binary that should be entirely self-contained, with no dependencies. It requires that static versions of all your libraries are available on your build system. Also, some features (such as DNS lookup) always expect a shared library, so they won't work this way.
Even then, you should expect some Linux features to not work. Basically, anything that requires hardware features or configuration files in /etc are going to need a lot of effort. There are various projects that have done this already (search "linux chroot android").
I'm not sure what the "not executable:ELF32" message means, but you should check whether you're building 32 or 64-bit executables, and which the Android binaries are using (file <whatever> should tell you).

clozure cl: cl-freetype2 on windows 7

I'm working on windows 7 64bit system using clozure cl (version 1.8-r15286m) with quicklisp installed.
I need some freetype2 bindings for common lisp. (map characters to glyphs + kerning info)
I've tried to install "cl-freetype2" using
(ql:quickload "cl-freetype")
from 32bit clozure cl, and I've run into several problems.
"grovel.lisp" (located in quicklisp/software/cffi_0.11.1/grovel/grovel.lisp) assumes that I have gcc installed at "c:/msys/1.0/bin/gcc.exe" (I have mingw-gcc in path, but not there). Fixed by replacing "c:/msys/1.0/bin/gcc.exe" with "gcc" in "grovel.lisp".
When trying to compile cffi bindings for freetype2, same file does not include drive letters when passing include directories to compiler (i.e. instead of -i"d:/somedir" it passes -i"/somedir" to gcc`).
"grovel.lisp" tries to include unix include directories.
I cannot fix #2 myself.
I found this discussions, tried both listed patches, and neither of them worked. (first one breaks cffi, because ccl can't find neither "namestring-prefix" function nor "pathname-prefix" function), second one does not fix the problem.
What can I do in this situation?
I'd prefer to avoid fixing "groveller" myself, I simply need some bindings for freetype2.
Basically, I need to be able to
Load truetype font.
Map unicode char to glyph.
Get kerning information for pair of glyphs.
Load glyph bitmap.
Any ideas?
Figured it out.
Installing cl-freetype2 via quicklisp requires fully functional installation of MinGW.
Ensure that mingw-gmp is installed. (mingw-get install gmp)
Ensure that mingw/bin directory is within system path (right click on "My Computer"->Properties->Advanced->Environment Variables). Is Set. Should be something like "D:/development/MinGW/bin " (assuming MinGW is installed in "d:/development").
Locate "grovel.lisp" within your ccl installation, and replace ""c:/msys/1.0/bin/gcc.exe" with "gcc". You don't have to do that if gcc is installed at this location.
Launch mingw shell.
download unpack and install latest Freetype2 tarball using ".configure && make && make install", similarly to unix enviornment.
Locate freetype-6.dll copy it into freetype.dll and move freetype.dll into location within system path.
(Assuming that MinGW is installed in "d:/development/MinGW"), create CPATH user environment variable with following context: D:\development\MinGW\msys\1.0\local\include\freetype2;D:\development\MinGW\msys\1.0\local\include. That is - if you didn't specify "/usr" prefix during freetype2 compilation.
From within mingw shell, launch wx86cl and try (ql:quickload "cl-freetype2"). It should work properly.
If it still doesn't work, in all your root drives create directory junctions to directory in which mingw is installed. (i.e. "c:/development" linking to "d:/development", etc).
I must admit that this was much hassle, so I still think that it'll be a better idea to make a small dll that provides minimal set of functions I need while using freetype internally, then load this dll using cffi. This should be much easier.

cross-gcc doesn't search for target as and ld in path?

I've successfully built a couple of cross-gcc compilers, hosted on OSX Lion and targeting both i386-pc-solaris2.10 and x86_64-linux-gnu.
I have 2.22 binutils for those target installed under $BINUTILSROOT and $BINUTILSROOT/bin in my PATH. Reading http://gcc.gnu.org/install/configure.html, in particular
--with-as=pathname
Specify that the compiler should use the assembler pointed to by pathname, rather than the one found by the standard rules to find an assembler, which are:
Unless GCC is being built with a cross compiler, check the libexec/gcc/target/version directory. libexec defaults to exec-prefix/libexec; exec-prefix defaults to prefix, which defaults to /usr/local unless overridden by the --prefix=pathname switch described above. target is the target system triple, such as `sparc-sun-solaris2.7', and version denotes the GCC version, such as 3.0.
If the target system is the same that you are building on, check operating system specific directories (e.g. /usr/ccs/bin on Sun Solaris 2).
Check in the PATH for a tool whose name is prefixed by the target system triple.
Check in the PATH for a tool whose name is not prefixed by the target system triple, if the host and target system triple are the same (in other words, we use a host tool if it can be used for the target as well).
I thought my -gcc (configured with --with-gnu-as --with-gnu-ld) would have picked up respectively i386-pc-solaris2.10-as and x86_64-linux-gnu-as (and corresponding -ld) because they are in $BINUTILSROOT/bin which is in the PATH and so the 3rd bullet from the above list should apply.
But this doesn't seem to work, and I've confirmed with dtrace that -gcc doesn't search for -as and -ld in the PATH.
The only solution I've found to be working is to also fully specify as and ld adding
--with-as=$BINUTILSROOT/bin/-as --with-ld=$BINUTILSROOT/bin/-ld
when configuring gcc.
Am I misinterpreting gcc docs, or this is the only way to have cross-compilation working?
Ordinarily you'd install a cross-compiler in the same directory as your cross-binutils. If you do that it'll Just Work.
If you're not installing the compiler into the same directory because you want to "stage" it for building a package, then you should configure with the --prefix of the final installed location (in which the binutils should already be present), and then install with
make DESTDIR=/path/to/staging/dir install
to override the prefix setting. You'd then copy those files into the true prefix (presumably as part of a package install) before you use them.
If you don't want to install in the same directory for another reason then you have to specify the path as you've discovered. There are other ways to make it work, but --with-as is the intended solution. If you really don't like that solution, then you can do
make configure-gcc
ln -s $BINUTILSROOT/bin/as gcc/as
ln -s $BINUTILSROOT/bin/ld gcc/ld
That will make the build work (IIRC), but the final installed compiler will still look in the standard places. In fact, this works because, during build only, the gcc directory is one of the standard places.
The reason for all this is that it doesn't use "x86_64-linux-gnu-as": it actually uses "prefix/x86_64-linux-gnu/bin/as" and if that doesn't exist it looks in the other standard places for "as", and typically finds the host "/usr/bin/as" which doesn't work well (and leads to very confusing error messages).

USB GCC Development Environment with Libraries

I'm trying to get something of an environment on a usb stick to develop C++ code in. I plan to use other computers, most of the time linux, to work on this from a command line using g++ and make.
The problem is I need to use some libraries, like Lua and OpenGL, which the computers don't have. I cannot add them to the normal directories, I do not have root on these computers. Most of the solutions I've found involve putting things in /usr/lib/ and the like, but I cannot do that. I've also attempted adding options like '-L/media//lib', which is where they are kept, and it didn't work. When compiling, I get the same errors I got when first switching to an OS with the libraries not installed.
Is there somewhere on the computer outside of /usr/ I can put them, or a way to make gcc 'see' them?
You need more than the libraries to be able to compile code utilizing those libraries. (I'm assuming Linux here, things might be slightly different on e.g. OSX,BSDs,Cygwin,Mingw..)
Libraries
For development you need these 3 things when your code uses a library:
The library header files, .h files
The library development files, libXXX.so or libXXX.a typically
The library runtime files , libXXX.so.Y where Y is a version number. These are not needed if you statically link in the library.
You seem to be missing the header files (?) Add them to your usb stick, say under /media/include
Development
Use (e.g.) the compiler flag -I/media/include when compiling source code to refer to a non-standard location of header files.
Use the compiler/linker flag -L/media/lib to refer to non-standard location of libraries.
You might be missing the first step.
Running
For dynamically linked libraries, the system will load those only from default locations, typically /lib/ , /usr/lib/
Learn the ldd tool to help debug this step.
You need to tell the system where to load additional libraries when you're running a program, here's 3 alternatives:
Systemwide: Edit /etc/ld.so.conf and add /media/libs there. Run ldconfig -a afterwards.
Local, to the current shell only. set the LD_LIBRARY_PATH environment variable to refer to /media/lib, run export LD_LIBRARY_PATH=/media/lib
Executable: Hardcode the non-standard library path in the executable. You add this to the linking step when creating your executable: -Wl,-rpath,/media/lib
Etc.
There could be other reasons things are not working out, if so,
show us the output of ls -l /media/libs , and where you put the library header files, the command line you use to compile/link, and the exact errors you get.
Missing the headers and/or development libraries (for dynamic libraries there is usually a symlink from a libXXX.so to a libXXX.so.Y , the linker needs the libXXX.so , it will not look directly at libXXX.so.Y)
using libraries not compatible with your current OS/architecture. (libraries compiled on one linux distro is often not compatible with another distro, or even another minor version of the same distro)
using an usb stick with a FAT32 filesystem, you'll get in trouble with symlinks..

Resources