Changing OCaml's gcc after installation - gcc

I installed OCaml via OPAM, and by default it uses gcc as the command to compile .c files. For instance, if I run ocamlopt -verbose file.c, I obtain:
+ gcc -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT -g
-fno-omit-frame-pointer -c -I'/home/user/.opam/4.02.1+fp/lib/ocaml' 'test.c'
I'd like to change the GCC binary that is used by OCaml, for instance to replace it with gcc-5.1 or /opt/my-gcc/bin/gcc.
Is it possible to do so without reconfiguring and recompiling OCaml? I suppose I could add a gcc alias to a directory in the PATH, but I'd prefer a cleaner solution if there is one.
To check if gcc was not chosen based on a textual configuration file (that I could easily change), I searched for occurrences of gcc in my /home/user/.opam/4.02.1+fp directory, but the only occurrence in a non-binary file that I found was in lib/ocaml/Makefile.config, and changing it does nothing for the already-compiled binary.

ocamlopt uses gcc for three things. First, for compiling .c files that appear on the command line of ocamlopt. Second, for assembling the .s files that it generates internally when compiling an OCaml source file. Third, for linking the object files together at the end.
For the first and third, you can supply a different compiler with the -cc flag.
For the second, you need to rebuild the OCaml compiler.
Update
Here's what I see on OS X when compiling a C and an OCaml module with the -verbose flag:
$ ocamlopt -verbose -cc gcc -o m m.ml c.c 2>&1 | grep -v warning
+ clang -arch x86_64 -c -o 'm.o' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlasm461f1b.s' \
+ gcc -c -I'/usr/local/lib/ocaml' 'c.c'
+ clang -arch x86_64 -c -o \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartup695941.o' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartupb6b001.s'
+ gcc -o 'm' '-L/usr/local/lib/ocaml' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartup695941.o' \
'/usr/local/lib/ocaml/std_exit.o' 'm.o' \
'/usr/local/lib/ocaml/stdlib.a' 'c.o' \
'/usr/local/lib/ocaml/libasmrun.a'
So, the compiler given by the -cc option is used to do the compilation of the .c file and the final linking. To change the handling of the .s files you need to rebuild the compiler. I'm going to update my answer above.

Related

Modifying configure.ac - check for package presence

My main development platform is Gentoo on Linux. However, recently I tried to build my program on the fresh VM install on Debian.
My program contains of main binary and couple of dll/so/dylib libraries. One of the libraries depends on the presence of unixODBC/iODBC.
I was told by unixODBC maintainers to use odbc_config script to identify the build parameters.
When I build on Gentoo - everything works fine. There is no problems.
However, when I build on Debian - the build fails because apparently Debian does not produce odbc_config script and instead in this case rely on pkg-config.
So, I need to add a test in configure.ac to check for odbc_config script presence and pass it along to one of the so files generation (lets call it libodbc_lib project).
Could someone please help me with this?
EDIT:
Is this correct to be put in configure.ac:
AC_CHECK_PROG(ODBC,odbc_config,yes)
if test x"${ODBC}" == x"yes" ; then
ODBC_CFLAGS = `odbc_config --cflags`
ODBC_LIBS = `odbc_config --libs` -lodbcinst
else
ODBC_CFLAGS = `pkg-config odbc --cflags`
ODBC_LIBS = `pkg-config odbc --libs` -lodbcinst
fi
AC_SUBST(ODBC_CFLAGS)
AC_SUBST(ODBC_LIBS)
If it is - how do I use ODBC_FLAGS/ODBC_LIBS in my subproject?
EDIT2:
Based on this answer I used the following code:
In the main configure.ac:
AC_CHECK_PROG(ODBC,odbc_config,yes)
if test x"${ODBC}" == x"yes" ; then
ODBC_CFLAGS = `odbc_config --cflags`
ODBC_LIBS = `odbc_config --libs` -lodbcinst
else
ODBC_CFLAGS = `pkg-config odbc --cflags`
ODBC_LIBS = `pkg-config odbc --libs` -lodbcinst
fi
AC_SUBST(ODBC_CFLAGS)
AC_SUBST(ODBC_LIBS)
In the libodbc_lib/Makefile.am:
libodbc_lib_la_CXXFLAGS = -I../../dbinterface \
-DUNICODE \
-DUNIXODBC \
-I#ODBC_CFLAGS#
libodbc_lib_la_LDFLAGS = -L../dbinterface \
-ldbinterface \
#ODBC_LIB#
I regenerated configure, run it successfully and then tried running make.
I got following error:
CXXLD libodbc_lib.la
/usr/lib/gcc/x86_64-pc-linux-gnu/11.3.0/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find #ODBC_LIB#: No such file or directory
What I did wrong?
EDIT3:
After fixing the missing S, I got following compile commands:
make[2]: Entering directory '/home/igor/dbhandler/Debug/libodbc'
/bin/sh ../libtool --tag=CXX --mode=compile g++ -DHAVE_CONFIG_H -I. -I/home/igor/dbhandler/libodbc -I.. -I../../dbinterface -DUNICODE -DUNIXODBC -I#IODBC_CFLAGS# -g -O0 -MT libodbc_lib_la-database_odbc.lo -MD -MP -MF .deps/libodbc_lib_la-database_odbc.Tpo -c -o libodbc_lib_la-database_odbc.lo `test -f 'database_odbc.cpp' || echo '/home/igor/dbhandler/libodbc/'`database_odbc.cpp
libtool: compile: g++ -DHAVE_CONFIG_H -I. -I/home/igor/dbhandler/libodbc -I.. -I../../dbinterface -DUNICODE -DUNIXODBC -I#IODBC_CFLAGS# -g -O0 -MT libodbc_lib_la-database_odbc.lo -MD -MP -MF .deps/libodbc_lib_la-database_odbc.Tpo -c /home/igor/dbhandler/libodbc/database_odbc.cpp -fPIC -DPIC -o .libs/libodbc_lib_la-database_odbc.o
libtool: compile: g++ -DHAVE_CONFIG_H -I. -I/home/igor/dbhandler/libodbc -I.. -I../../dbinterface -DUNICODE -DUNIXODBC -I#IODBC_CFLAGS# -g -O0 -MT libodbc_lib_la-database_odbc.lo -MD -MP -MF .deps/libodbc_lib_la-database_odbc.Tpo -c /home/igor/dbhandler/libodbc/database_odbc.cpp -o libodbc_lib_la-database_odbc.o >/dev/null 2>&1
mv -f .deps/libodbc_lib_la-database_odbc.Tpo .deps/libodbc_lib_la-database_odbc.Plo
/bin/sh ../libtool --tag=CXX --mode=link g++ -I../../dbinterface -DUNICODE -DUNIXODBC -I#IODBC_CFLAGS# -g -O0 -L../dbinterface -ldbinterface -o libodbc_lib.la -rpath /usr/local/lib libodbc_lib_la-database_odbc.lo
libtool: link: g++ -fPIC -DPIC -shared -nostdlib /usr/lib/gcc/x86_64-pc-linux-gnu/11.3.0/../../../../lib64/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/11.3.0/crtbeginS.o .libs/libodbc_lib_la-database_odbc.o -L../dbinterface -ldbinterface -L/usr/lib/gcc/x86_64-pc-linux-gnu/11.3.0 -L/usr/lib/gcc/x86_64-pc-linux-gnu/11.3.0/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/11.3.0/../../../../x86_64-pc-linux-gnu/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/11.3.0/../../.. -lstdc++ -lm -lc -lgcc_s /usr/lib/gcc/x86_64-pc-linux-gnu/11.3.0/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/11.3.0/../../../../lib64/crtn.o -g -O0 -Wl,-soname -Wl,libodbc_lib.so.0 -o .libs/libodbc_lib.so.0.0.0
libtool: link: (cd ".libs" && rm -f "libodbc_lib.so.0" && ln -s "libodbc_lib.so.0.0.0" "libodbc_lib.so.0")
libtool: link: (cd ".libs" && rm -f "libodbc_lib.so" && ln -s "libodbc_lib.so.0.0.0" "libodbc_lib.so")
libtool: link: ar cru .libs/libodbc_lib.a libodbc_lib_la-database_odbc.o
libtool: link: ranlib .libs/libodbc_lib.a
libtool: link: ( cd ".libs" && rm -f "libodbc_lib.la" && ln -s "../libodbc_lib.la" "libodbc_lib.la" )
make[2]: Leaving directory '/home/igor/dbhandler/Debug/libodbc'
I still the variable name there and not their values.
Is it normal?
As UnixODBC upstream does ship and install *.pc files, I would expect that file to be both present and correct and therefore I would ignore any *-config scripts. The pkg-config system is quite well thought out and works even for quite weird cross compilation environments. The *.pc mechanism works well on Linux, on FreeBSD, on OSX, cross-compiling for Windows on Linux, to name a few.
A well-written _config program written in portable shell could do the same by basically reproducing much of the pkg-config logic in portable shell for each and every _config script, hopefully correctly.
However, odbc_config is not a portable shell script. It is a binary executable, i.e. it will regularly break for cross-compiling, as the system you build on will usually not be able to run programs like odbc_config which are built to run on the system you are building for.
And even if the flags from the *.pc files were unsuitable for a very unusual build environment: Using PKG_CHECK_MODULES defines appropriate _CFLAGS and _LIBS variables for the configure script, so even in a very unusual build environments one can always override whatever the *.pc file might contain by calling configure like
../configure ODBC_CFLAGS='-I/weird/stuff -DWEIRD_STRING="moo"' ODBC_LIBS='-L/very/weird/libxyz -lodbc'
So... using odbc_config has no advantages, upstream already provides a odbc.pc file so it is always present, so why not just always use odbc.pc?
So, in configure.ac (if builds without odbc.pc present should fail, otherwise you will have to do some AC_DEFINE and/or AM_CONDITIONAL to conditionally build with or without ODBC support) do
m4_pattern_forbid([PKG_CHECK_MODULES])dnl
PKG_CHECK_MODULES([ODBC], [odbc])
and in any subdirectory (what you call "subproject") Makefile.am or Makefile-files where you need to link somehting against libodbc, put, depending on whether you are building an executable
bin_PROGRAMS += foobar
[…]
foobar_CPPFLAGS += $(ODBC_CFLAGS)
foobar_LDADD += $(ODBC_LIBS)
or a (libtool) library
lib_LTLIBRARIES += libfoo.la
[…]
libfoo_la_CPPFLAGS += $(ODBC_CFLAGS)
libfoo_la_LIBADD += $(ODBC_LIBS)
That should work for all native and cross-compile builds in properly set up build environments, and people can still override odbc_CFLAGS and odbc_LIBS in case of problems.
Of course, you can always AC_CHECK_PROG or AC_PATH_PROG or AC_CHECK_TOOL or AC_PATH_TOOL together with an AC_ARG_VAR for the odbc_config program and then define and AC_SUBST an _CFLAGS and _LIBS variable set to the output of $ODBC_CONFIG --cflags and $ODBC_CONFIG --libs, respectively, and then then use the _CFLAGS and _LIBS vars in Makefile.am/Makefile-files as above.
However, that is a lot of code to write, and with a lot of special cases to consider, and if you have to ask about how to do this you will probably get a lot more wrong than if you just just use PKG_CHECK_MODULES.
You can always add something later if the PKG_CHECK_MODULES route actually does not work for a use case and which cannot be fixed within the pkg-config framework. Until that time (if it ever happens), I would recommend to just use the simple PKG_CHECK_MODULES method and probably be done.
So, I need to add a test in configure.ac to check for odbc_config script presence and pass it along to one of the so files generation
Autoconf has AC_PATH_PROG() for checking for a program in the executable search path. You would of course use AC_SUBST() to define one or more output variables by which to convey the results to the generated makefiles.
But no, coming back around to my comment on the answer to one of your previous questions, what you ought to do is not have configure forward information about the executable, but rather for it to determine the needed flags itself and forward them, via one or more output variables. If you continue to use odbc_config, at least conditionally, then that means having configure run it and capture the output. You should not inject shell command substitutions into your compilation commands.
And if you substitute a different mechanism, whether conditionally or exclusively, then similarly for that. (That's what your other answer describes with respect to pkg-config.)

Why do I get a segmentation fault when running an example program compiled without cmake? (MSYS2, Mingw-w64)

In short
What are cmake's web of makefiles doing differently from a simple compile and link that is making a difference in the final executable?
I'm trying to use the bullet physics library (bullet3-2.83.7) https://github.com/bulletphysics/bullet3.
I compiled the library okay with few warnings in MSYS2 with Mingw-w64.
Afterwards I can run the example programs without problems, specifically ExampleBrowser and HelloWorld.
I've been trying to incorporate the HelloWorld source into a test project using just a Makefile but I get SIGSEGV errors whenever there is a call to dynamicsWorld in the executable. The SEGFAULT occurs at lines dynamicsWorld->AddRigidBody(body); or if those are commented out dynamicsWorld->stepSimulation
This occurs with the exact example source file compiled with the makefile (source not modified).
gdb tells me this
main (argc=1, argv=0x5f4eb0) at main.cpp:78
78 dynamicsWorld->addRigidBody(body);
(gdb) step
0x0000000000002000 in ?? ()
(gdb) step
Cannot find bounds of current function
(gdb) bt full
#0 0x0000000000002000 in ?? ()
No symbol table info available.
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
I don't know what to do with this info. I assume/hope I'm just missing a compiler or linker flag?
My original Makefile is a big mess based off http://make.mad-scientist.net/papers/advanced-auto-dependency-generation. I assumed it would be enough to just use the existing makefile on the example code by adding the libraries and include directory -lBulletDynamics_Debug -lBulletCollision_Debug -lLinearMath_Debug
I've also tried a simplified Makefile with commands and flags I found grepping the CMake directories from bullet3/examples/HelloWorld.
My PATH environment variable is clean, nothing in LD_LIBRARY_PATH (In MSYS: echo $PATH)
MSYS2 Mingw-w64
gcc 10.1.0
MSYS 20180531msys64 ? pacman updated a lot of things
CMake 3.17.3
GNU Make 4.3
Makefile
CXX_DEFINES = -DUSE_GRAPHICAL_BENCHMARK -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS
CXX_INCLUDES = -I"C:\lib64\include\bullet3"
CXX_FLAGS = -g -fpermissive -D_DEBUG
.PHONY: all
all:
g++.exe $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -o main.obj -c main.cpp
ar cr main.a main.obj
g++.exe $(CXX_FLAGS) -Wl,--whole-archive main.a -Wl,--no-whole-archive -o bulletTest.exe -Wl,--major-image-version,0,--minor-image-version,0 libBulletDynamics_Debug.a libBulletCollision_Debug.a libLinearMath_Debug.a -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32
# -L"C:\lib64\lib"
.PHONY: run
run:
gdb -ex run bulletTest.exe -ex "bt full" -ex quit --batch
.PHONY: clean
clean:
rm -f ./bulletTest.exe ./main.obj ./main.a
Building the bullet physics library in MSYS2
In the bullet3-2.83.7 directory (tar.gz from https://github.com/bulletphysics/bullet3/releases)
mkdir build-mingw64
cd build-mingw64
cmake -G "MSYS Makefiles" \
-DBUILD_SHARED_LIBS=0 \
-DBUILD_EXTRAS=1 \
-DINSTALL_LIBS=0 \
-DUSE_GLUT=1 \
-DCMAKE_CXX_FLAGS_DEBUG="-fpermissive -g" \
-DINSTALL_EXTRA_LIBS=0 \
-DCMAKE_BUILD_TYPE=Debug ..
make -j
I ran into the same issue. In my case, it was because Bullet was compiled with USE_DOUBLE_PRECISION, so adding the following to cmakelists for my executable fixed the issue for me:
target_compile_options(<target_name> BEFORE PUBLIC -DBT_USE_DOUBLE_PRECISION)

How to generate dependency file for executable (during linking) with gcc

gcc has -M-class options (-MMD, -MF, etc.) that allows to generate dependency file during compiling source file. The dependency file contains Makefile rules describing on which source files and headers the generated object file depends on. The dependency file may be included into Makefile and then make will automatically recompile source file when headers are changed.
I need a similar option but for generating dependency file during linking an executable. The dependency file should contain list of libraries used for linking an executable, so if any of libraries is updated, make will re-execute linking of the executable automatically.
I tried to use the same flags (-MMD, -MF), but they doesn't work for linking. It seems they are only for generating dependency files during compiling.
Is there any other flags or means for generating dependency file for executable?
So far I have not found dedicated gcc options for generating dependency file for executable, but found the --trace option (-Wl,--trace when used with gcc). This option generates list of libraries used during linking. Its output has the next format:
gcc -Wl,--trace myprog.c -o myprog -L. -lmylib
-lmylib (./libmylib.a)
-lgcc_s (/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.5.2/libgcc_s.so)
...
The list of libraries then may be converted to Makefile rules using sed:
echo "myprog: " > myprog.dep
gcc -Wl,--trace myprog.c -o myprog -L. -lmylib \
| sed -n 's/.*(\(.*\)).*/\1 \\/p' >> myprog.dep
So myprog.dep will have the following content:
myprog: \
./libmylib.a \
/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.5.2/libgcc_s.so \
...
This dependency file may be included to Makefile and make will relink myprog if any of libraries are updated.
The dependency file doesn't contain list of object files, but the object files are usually known inside Makefile-script without help of compiler:
myprog: $(OBJS)
gcc -Wl,--trace $^ -o myprog -L. -lmylib | sed -n 's/.*(\(.*\)).*/\1 \\/p' >> myprog.dep

GCC equivalent of llvm-link

I use the following LLVM tools to convert a cpp project which is written in multiple files into "ONE" single assembly file.
clang *.cpp -S -emit-llvm
llvm-link *.s -S -o all.s
llc all.s -march=mips
Is there any way of doing this in GCC? In particular, is there any way of linking GCC generated assembly files into one assembly file? i.e., what is the equivalent of LLVM-LINK?
Perhaps LTO (Link Time Optimization) is what you want.
Then, compile each compilation unit with gcc -flto e.g.
gcc -flto -O -Wall -c src1.c
g++ -flto -O -Wall -c src2.cc
and use also -flto (and the same optimizations) to link them:
g++ -flto -O src1.o src2.o -lsomething
LTO works in GCC by putting, in each generated assembly file and object file, some representation of the internal GCC representations (like Gimple). See its documentation
You might want to use MELT to customize GCC (or simply use its probe to understand the Gimple, or try just gcc -fdump-tree-all).

How do you use cgo WITHOUT using make?

I use a custom build tool to compile go projects and I need a way to use cgo in my project.
The problem is that the cgo documentation only tells you how to use it with make.
What I really need to know is which generated files to process with which tools and in what order it needs to be done. I tried to read make.pkg in the go source dir but my best effort fails.
My test dll is very simple, a single function that returns 1 every time it is called and the go code to use this function is similarly simple.
The output from the console produced by a successful run of make on a cgo project would be very helpful.
Output of running make on 32-bit Linux in directory misc/cgo/life:
# gomake _obj/life.a
CGOPKGPATH= cgo -- life.go
touch _obj/_cgo_run
8g -o _go_.8 _obj/life.cgo1.go _obj/_cgo_gotypes.go
8c -FVw -I ${GOROOT}/pkg/linux_386 -I . -o "_cgo_defun.8" _obj/_cgo_defun.c
gcc -m32 -I . -g -fPIC -O2 -o _cgo_main.o -c _obj/_cgo_main.c
gcc -m32 -g -fPIC -O2 -o c-life.o -c c-life.c
gcc -m32 -I . -g -fPIC -O2 -o life.cgo2.o -c _obj/life.cgo2.c
gcc -m32 -I . -g -fPIC -O2 -o _cgo_export.o -c _obj/_cgo_export.c
gcc -m32 -g -fPIC -O2 -o _cgo1_.o _cgo_main.o c-life.o life.cgo2.o _cgo_export.o
cgo -dynimport _cgo1_.o >_obj/_cgo_import.c_ && mv -f _obj/_cgo_import.c_ _obj/_cgo_import.c
8c -FVw -I . -o "_cgo_import.8" _obj/_cgo_import.c
rm -f _obj/life.a
gopack grc _obj/life.a _go_.8 _cgo_defun.8 _cgo_import.8 c-life.o life.cgo2.o _cgo_export.o
The line cgo -- life.go creates the following files:
_obj/_cgo_.o
_obj/life.cgo1.go
_obj/life.cgo2.c
_obj/_cgo_gotypes.go
_obj/_cgo_defun.c
_obj/_cgo_main.c
_obj/_cgo_flags
_obj/_cgo_export.c
_cgo_export.h
"I use a custom build tool to compile go projects and I need a way to use cgo in my project."
... and this approach leads to problems. Using the standard way with a Makefile is simple, easy, proven, documented, etc.
I realize I'm not (directly) answering your question. Instead my "answer" is: I strongly suggest to use the standard way. Don't create problems for your self by choosing other, not directly supported options.
That said, I think there is a way to avoid the Makefiles, I just never been there, sorry. I'm usually lazy/short of time, so I use the simplest/fastest way to get things done. You might want to try the same ;-)

Resources