Linking against static Lua libraries on macOS - macos

I'm trying to compile and link a program (using CMake) that uses Lua 5.3's C interface on Mac OS X 10.15.7. However I have these problems:
brew install lua#5.3 only installs dynamic libraries
I cannot copy static libraries built from source to /usr/local due to System Integrity Protection (?)
I don't know how to make CMake find the libraries if I put them anywhere else (using find_package(Lua 5.3 REQUIRED)
What's the easiest way to solve this?

If I correctly understand your question, you are trying to use Lua's C API, which means that you need access to the principal header files lua.h, lualib.h, and lauxlib.h, as well the static library liblua.a that is created when the interpreter is built.
I would recommend downloading lua-5.3.5.tar.gz from lua.org and then building from source.
This can be done easily from the Terminal:
$ wget http://www.lua.org/ftp/lua-5.3.5.tar.gz
$ tar xzf lua-5.3.5.tar.gz
$ cd lua-5.3.5
$ make macosx
After that you should be able to do make install as well, which copies the Lua interpreter to /usr/local/bin, I believe.
If you do not want the key Lua header files put into your include path, build your program with -I and -L flags. Also, don't forget the -llua -ldl -lm flags when linking your program.

Related

How to dynamically link your nim-application against musl?

I've written a web-server in nim using the prologue framework. I would like to deploy that application using an alpine-docker-container.
As far as I'm aware, compiling means you dynamically link against your system libraries for whatever you need, that system library on any normal distro being glibc.
On alpine however you do not use glibc, you use musl, so dynamically linking against glibc means my application will expect glibc functions with glibc names that do not exist since there are only musl functions.
The big question that arises out of this for me as a python developer that jumped onto nim and knows very little about compilers:
How do I compile, so that I link dynamically against musl?
The folks from nim discord's brought me to the answer. It consists of passing flags to the nim-compiler to swap out the compiler nim normally uses for its generated C-code, in order to use musl-gcc. This can be done by using the --gcc.exe:"musl-gcc" and --gcc.linkerexe:"musl-gcc" flags.
Here an example for Linux:
1. install musl to get access to musl-gcc
download the tar file from the official musl page
Unpack the tar file somewhere
Run bash configure in the unpacked directory. WARNING: Make sure that you do NOT install musl with --prefix being /usr/local, as that may adversely affect your system. Use somewhere else where it is unlikely to override files, e.g. /usr/local/musl. This path will further be referred to as <MUSL_INSTALL_PATH>
Run make && make install in the unpacked directory
Add <MUSL_INSTALL_PATH> to your PATH environment variable
Validate whether you set everything up correctly by opening a new terminal and seeing whether you have access to the musl-gcc command
2. Compile with musl
Create a compile command with --gcc.exe:"musl-gcc" to swap out gcc with musl-gcc and --gcc.linkerexe:"musl-gcc" to swap out the default linker with musl-gcc as well. An example can look like this:
nim c \
--gcc.exe:"musl-gcc" \
--gcc.linkerexe:"musl-gcc" \
--define:release \
--threads:on \
--mm:orc \
--deepcopy:on \
--define:lto \
--outdir:"." \
<PATH_TO_YOUR_MAIN_PROJECT_FILE>.nim
run the command
This should generate a binary that is dynamically linked against musl and thus can run within an alpine docker container.

How to link and compile using specific library version installed at custom location?

I am trying to compile a program which uses GSL, in fact I am already able to compile it successfully on my local machine using
g++ -o program program.c prog0.o -L/usr/local/lib -lgsl -lgslcblas -lm
My problem is that I need to compile this program on a work machine in a shared system, but I know the program will not compile with an up to date version of GSL, so I need to install and use an older version.
I did this on my own system using the default installation, so the relevant files are located in /usr/local/lib on my local machine, and the compilation works for me with the above command.
But since the work machine is in a shared system, I cannot mess with the default directories, so I installed the correct GSL version on the work machine in my directory under /home/myname/gsl/.
So on the work machine the folder /home/myname/gsl/lib contains the same relevant files as the folder /usr/local/lib on my machine.
Now I did various attempts to try and tell g++ to use this custom installation folder, which I thought would come down to
g++ -o program program.c prog0.o -L/home/myname/gsl/lib -lgsl -lgslcblas -lm
but no success. No matter what I did g++ always used the GSL version installed on the shared system, even using just
g++ -o program program.c prog0.o
I only started programming C/C++ not long ago and only know the very basics of how to compile programs, so this linking thing is still always confusing me..
But as far as I can tell -L/dir/ should tell g++ to use the library in /dir/ and -lgsl -lgslcblas are the files which it should look for in that library... ?
But it seems g++ doesn't care what library I tell it here, it always seems to use whatever is in the PATH of the shared work system, which seems to include this up-to-date version of GSL that I cannot use. But I also cannot change the PATH since I only have access to my own subdirectories on the work system..
So how do I tell g++ to ignore the default version of GSL and use the one I installed manually at /home/myname/gsl/ ?
I figured out the answer, it is actually simple. The problem was just my lack of understanding proper usage of outside libraries and trying to fix the compilation command was the wrong approach.
In the code in program.c, gsl was included with
#include <gsl/gsl_blas.h>
and so on. Of course, the "<>" directly tell the compiler to look in known include directories, where the up-to-date GSL is installed on the shared system.. So the way to use a custom version was just to instead use
#include "/home/myname/gsl/lib/gsl_blas.h"
and so on, directly specifying that I want to use my custom installation.
I then compiled with
g++ -o program program.c prog0.o /home/myname/gsl/lib/libgsl.so /home/myname/gsl/lib/libgslcblas.so -lm
and it compiles successfully.
(This brought up some other unclarities for me, but at least this specific problem is solved.)

Cross compiling PCRE with CodeSourcery toolchain?

I am trying to compile PCRE with CodeSourcery
here is my configure script
#!/bin/bash
PROJECT_BASE=$(pwd);
PROJECT_REPOSITORY=$PROJECT_BASE/download
INSTALL_PREFIX=$PROJECT_BASE/compiled/armv5te
mkdir -p $INSTALL_PREFIX && mkdir -p $PROJECT_BASE/download && mkdir -p $PROJECT_BASE/build
export TOOL_PREFIX=${HOME}/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_GNU_Linux
SYSROOT=$HOME/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_GNU_Linux/arm-none-linux-gnueabi/libc
export CC="${TOOL_PREFIX}/bin/arm-none-linux-gnueabi-gcc --sysroot=$SYSROOT"
export CXX="${TOOL_PREFIX}/bin/arm-none-linux-gnueabi-g++ --sysroot=$SYSROOT"
#CC="${TOOL_PREFIX}/bin/arm-none-linux-gnueabi-gcc"
#CXX="${TOOL_PREFIX}/bin/arm-none-linux-gnueabi-g++"
export AR="${TOOL_PREFIX}/bin/arm-none-linux-gnueabi-ar"
export RANLIB="${TOOL_PREFIX}/bin/arm-none-linux-gnueabi-ranlib"
export LD="${TOOL_PREFIX}/bin/arm-none-linux-gnueabi-ld"
export STRIP="${TOOL_PREFIX}/bin/arm-none-linux-gnueabi-strip"
export NM="${TOOL_PREFIX}/bin/arm-none-linux-gnueabi-nm"
export CCLD=$LD
export CHOST=arm-none-linux-gnueabi
PARENT_DIR=$(pwd);
cd $PROJECT_BASE/build && tar -xzvf $PROJECT_REPOSITORY/pcre-8.34.tar.gz && cd ./pcre-8.34
#LDFLAGS_DEP="-lc"
#CPPFLAGS="-I${INSTALL_PREFIX}/include"
# CFLAGS="-march=armv5t -marm -mlittle-endian -mglibc -static -I${INSTALL_PREFIX}/include"
LDFLAGS="-L${INSTALL_PREFIX}/lib"
./configure --prefix=$INSTALL_PREFIX/pcre --with-sysroot --target=arm-none-linux-gnueabi --host=x86_64 && make && make install;
cd -;
cd ${PARENT_DIR};
now it is successfully compiled but when i tried to execute that binary on android i get:
./pcregrep: not found
also having similar issue when cross-comping curl, openssl but when i run a test code
#include <stdio.h>
int main(){
printf("Hell ya it works");
return 0;
}
and compile with following option
arm-none-linux-gnueabi-gcc hello.c -static -o hello.c
it works
You're trying to use a Linux compiler with Android. It's not completely broken because Android is Linux, but Android doesn't come with the same set of libraries, as standard.
It's probably possible to install the Linux libraries (from the appropriate CodeSourcery libc directory), but that's a tricky process because the Android files will already be in the standard locations so they'll have to be installed to one side, somehow, and if you don't know what you're doing it'll get into a horrible mess.
The best solution is probably to use entirely static linking. That said, you might still find that libcurl is unhappy because, even statically linked, it requires that it can dlopen the DNS library of the host system, and I don't know how Android likes to do that.
I would suggest you try to get hold of a purpose-built Android toolchain (I believe Linaro do one) that is designed to use Android's "Bionic" C library, rather than GNU/Linux's "Glibc".
Its a mismatch between libc of code-sourcery tool-chain and libc which is in target rootfs.
libc in the host cross-compiler and deployed on the device rootfs are different
arm-none-linux-gnueabi-gcc hello.c -static -o hello.c
it works `
This works since you compiling statically so there is no need to copy libc to target here.
But pcre you built dynamically .check file ./pcregrep if its dynamic linked then
one easiest way compile statically as hello eg. and run on your target.
otherwise copy libc from tool chain to target and export it then it will work

Haskell package missing c library

I'm having trouble building the hmatrix library on OS X Lion. Looking at the .cabal file, it requires the gsl library, so I installed it with macports. The .a files are in /opt/local/lib and the .h files are in /opt/local/include/gsl
As suggested here I changed the built-type from Custom to Simple. (without that change I get a similar error).
When I use cabal configure I get the following output:
* Missing C library: gsl
This problem can usually be solved by installing the system package that
provides this library (you may need the "-dev" version). If the library is
already installed but in a non-standard location then you can use the flags
--extra-include-dirs= and --extra-lib-dirs= to specify where it is.
So I tried cabal --extra-include-dirs=/opt/local/include --extra-lib-dirs=/opt/local/lib configure, but I still get the same error. I can compile and link a c program that includes gsl. What files is cabal looking for? If I have the right files, how do I tell it how to find them?
libgsl.a is a universal binary:
$ file /opt/local/lib/libgsl.a
/opt/local/lib/libgsl.a: Mach-O universal binary with 2 architectures
/opt/local/lib/libgsl.a (for architecture x86_64): current ar archive random library
/opt/local/lib/libgsl.a (for architecture i386): current ar archive random library
ghc looks like it's 64-bit:
$ ghc --info
[("Project name","The Glorious Glasgow Haskell Compilation System")
,("GCC extra via C opts"," -fwrapv")
,("C compiler command","/usr/bin/llvm-gcc")
,("C compiler flags"," -m64 -fno-stack-protector -m64")
,("ar command","/usr/bin/ar")
,("ar flags","clqs")
,("ar supports at file","NO")
,("touch command","touch")
,("dllwrap command","/bin/false")
,("windres command","/bin/false")
,("perl command","/usr/bin/perl")
,("target os","OSDarwin")
,("target arch","ArchX86_64")
,("target word size","8")
,("target has GNU nonexec stack","False")
,("target has subsections via symbols","True")
,("Project version","7.4.2")
,("Booter version","7.4.2")
,("Stage","2")
,("Build platform","x86_64-apple-darwin")
,("Host platform","x86_64-apple-darwin")
,("Target platform","x86_64-apple-darwin")
,("Have interpreter","YES")
,("Object splitting supported","NO")
,("Have native code generator","YES")
,("Support SMP","YES")
,("Unregisterised","NO")
,("Tables next to code","YES")
,("RTS ways","l debug thr thr_debug thr_l thr_p dyn debug_dyn thr_dyn thr_debug_dyn")
,("Leading underscore","YES")
,("Debug on","False")
,("LibDir","/usr/local/Cellar/ghc/7.4.2/lib/ghc-7.4.2")
,("Global Package DB","/usr/local/Cellar/ghc/7.4.2/lib/ghc-7.4.2/package.conf.d")
,("Gcc Linker flags","[\"-m64\"]")
,("Ld Linker flags","[\"-arch\",\"x86_64\"]")
]
As an alternative to mac-ports you can use the nix package manager for mac. It does a pretty good job of taking care of the c dependancies for for the libraries available through it. In general I have been more happy with it then any other package manager on mac.
Unfortunately mac(darwin) unlike for linux does not have as many binaries available through nix so installing ghc often means waiting for it to compile.
The commands to install ghc and hmatrix after installation of nix are:
nix-env -iA nixpkgs-unstable.haskellPackages.ghc
nix-env -iA nixpkgs-unstable.haskellPackages.hmatrix
All of the needed dependencies will be taken care of for you.
I just tried it on my macbook pro and hmatrix seems to be working correctly in ghci after trying commands from the first few pages of the tutorial.
I'm not a mac person, but it really sounds like you haven't installed the "-dev" version. For a mac, I suspect you need to install gsl-devel in addition to gsl. If the problem persists, verify that you have libgsl0-dev on your library path.

Why is my shared library not found?

I'm trying to compile an example program that links to the shared library produced by Sundown. I'm compiling the program like so.
$ gcc -o sd sundown.c -L. -lsundown
Yet, when I run it I get the following error.
./sd: error while loading shared libraries: libsundown.so: cannot open shared object
file: No such file or directory
The output of ls is.
$ ls
libsundown.so libsundown.so.1 sundown.c sd
Why is the shared library not found by ld?
Short solution:
add . (or whatever it is from your -L flag) to your LD_LIBRARY_PATH. When you run sd, it'll look for libraries in the standard places and the LD_LIBRARY_PATH. Note that since you've added ., this will only work if you run sd from the same directory libsundown.so is in.
I plan on distributing the compiled binary. How can I do so that the library can be distributed without forcing people to edit their LD_LIBRARY_PATH?
You should install libsundown.so in one of the standard places, like /usr/lib or /usr/local/lib. You can do that with an installer or a make file, or something as simple as a INSTALL or README that tells the user to stick the libraries there and ensure the permissions are set to something sensible.
On Centos systems with /usr/lib and /usr/lib64, if you install 64-bit libs manually into /usr/lib then at runtime, the library may not be visible even though at build time it is visible (I used autotools and it was able to find my zopfli library from /usr/lib without any problem). When I execute the my_binary that links to /usr/lib/libzopfli.so.1 I got
libzopfli.so.1 => not found
After moving libzopfly.so.1 from /usr/lib to /usr/lib64, then everything works fine.

Resources