I am developing a project in ocaml that requires me to interface it with the OGDF external c++ library. It is all up and running on my mac, but now I am trying to create a windows version using Ocaml for Windows (https://fdopen.github.io/opam-repository-mingw/), the MinGW Cygwin port of Ocaml. In this version, I can interface ocaml with c code and it works fine, but as soon as I try to include an external library in that c code I get errors from the linker, which is flexdll (https://github.com/alainfrisch/flexdll) in this case. The linker says it cannot resolve symbols for _Unwind_Resume and __emutls_get_address throughout the library.
Here is a toy example:
My .ml file t.ml:
external print : unit -> unit = "print"
let () =
Printf.printf "platform: %s\n" (Sys.os_type);
print ()
My .cpp file tc.cpp:
#include <stdio.h>
#include "caml/mlvalues.h"
#define CAML_NAME_SPACE
//#include <ogdf/basic/Graph.h>
extern "C" value print(value unused) {
printf("hello from C\n");
return Val_unit;
}
My makefile:
t.exe: t.ml tc.o
ocamlopt -verbose -ccopt -pthread \
-cclib -lstdc++ -w s \
-ccopt -L../cdeg/ogdf/_release \
-cclib -lOGDF \
tc.o t.ml \
-o t.exe
tc.o: tc.cpp
x86_64-w64-mingw32-gcc -c \
-march=x86-64 -mtune=generic -O2 -mms-bitfields -Wall -Wno-unused \
tc.cpp \
-I../cdeg/ogdf -L../cdeg/ogdf/_release -lOGDF \
-I ~/.opam/4.04.0+mingw64c/lib/ocaml \
-lstdc++ -pthread -o tc.o
Like this, it all compiles happily, but if I uncomment the ogdf include line in tc.cpp, I get the following output:
$ make
x86_64-w64-mingw32-gcc -c \
-march=x86-64 -mtune=generic -O2 -mms-bitfields -Wall -Wno-unused \
tc.cpp \
-I../cdeg/ogdf -L../cdeg/ogdf/_release -lOGDF \
-I ~/.opam/4.04.0+mingw64c/lib/ocaml \
-lstdc++ -pthread -o tc.o
ocamlopt -verbose -ccopt -pthread \
-cclib -lstdc++ -w s \
-ccopt -L../cdeg/ogdf/_release \
-cclib -lOGDF \
tc.o t.ml \
-o t.exe
+ x86_64-w64-mingw32-as -o "t.o" "C:\OCaml64\tmp\camlasme5f9bd.s"
+ x86_64-w64-mingw32-as -o "C:\OCaml64\tmp\camlstartupf2b3f1.o" "C:\OCaml64\tmp\camlstartup101e51.s"
+ flexlink -chain mingw64 -stack 33554432 -exe -o "t.exe" "-LC:/OCaml64/home/Nathaniel.Miller/.opam/4.04.0+mingw64c/lib/ocaml" -pthread -L../cdeg/ogdf/_release "C:\OCaml64\tmp\camlstartupf2b3f1.o" "C:/OCaml64/home/Nathaniel.Miller/.opam/4.04.0+mingw64c/lib/ocaml\std_exit.o" "t.o" "C:/OCaml64/home/Nathaniel.Miller/.opam/4.04.0+mingw64c/lib/ocaml\stdlib.a" "-lstdc++" "-lOGDF" "tc.o" "C:/OCaml64/home/Nathaniel.Miller/.opam/4.04.0+mingw64c/lib/ocaml\libasmrun.a" -lws2_32
** Cannot resolve symbols for ../cdeg/ogdf/_release\libOGDF.a(PoolMemoryAllocator.o/
PreprocessorLayout.o/
extended_graph_alg.o/
graph_generators.o/
random_hierarchy.o/
simple_graph_alg.o/
CPlanarEdgeInserter.o/
... [a bunch of other .o files from the library]...
UpwardPlanarModule.o/
UpwardPlanarSubgraphModule.o/
UpwardPlanarSubgraphSimple.o/
VisibilityLayout.o/
):
_Unwind_Resume
__emutls_get_address
** Cannot resolve symbols for ../cdeg/ogdf/_release\libOGDF.a(basic.o):
_Unwind_Resume
File "caml_startup", line 1:
Error: Error during linking
make: *** [makefile:20: t.exe] Error 2
If I don't connect it to ocaml, but instead add a main() function to t.c it compiles just fine under x86_64-w64-mingw32-gcc with the external library included. I've tried including a few other small external libraries and they didn't cause this problem.
My first thought was that maybe the problem had to do with the linked files not all being compiled the same way, but I compiled the library and the .cpp file with the compiler and options given by ocamlopt -configure. And if they weren't all compiled the same way, I wouldn't expect to be able to get tc.cpp to work individually with ocamlopt and with the external library, but I only get errors when I try to use both. So is this an issue with Ocaml for windows, or flexdll, or with my installation of one of these? I'm at a loss for what to try next, and any ideas, suggestions, and/or explanations of what is going on here would be very much appreciated.
I have a partial answer. The issue is coming somehow from flexdll. I switched to using the Cygwin version of ocaml with gcc, and still had the same problem. Then I recompiled ocaml configured with the -no-shared-libs flag, which makes ocamlopt link with gcc instead of flexdll, and now everything compiles.
Related
i tried to compile without makefile with equations.com gcc
i have bunch of f90, and lib.a
Since a lot of files, i can't use like gfortran *.f90 *.f so i am using gfortran -c filename.f90 each in a batch file.
This create alot of .mod files and .o files.
[code]
gfortran -c -I INCLUDE -O3 -ffast-math -march=znver3 ALLOCATED_ARRAY_DATA.f90
gfortran -c -I INCLUDE -O3 -ffast-math -march=znver3 ALLOCATED_MEMORY.f90
gfortran -c -I INCLUDE -O3 -ffast-math -march=znver3 ALLOCATED_MEMORY_Interface.f90
[/code]
How to link it to exe with ld with several file?
[code]
ld #"names.rsp"
[code]
that names.rsp contains
[code]
../superlu/lib/superlu.a \
../superlu/src/c_fortran_dgssv.o \
../superlu/lib/libopenblas.a \
ALLOCATED_ARRAY_DATA.o \
ALLOCATED_MEMORY.o \
ALLOCATED_MEMORY_Interface.o \
/o mys.exe
[/code]
I think better to study cross-compiling-linking using CMAKE and building using jom or make, than to do it manual.
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)
In my program I use std::mt19937 to generate random numbers. On two systems (latest windows and ubuntu) the program compiles fine. But, on a third unknown system (using make) I get the error message:
" 'mt19937' is not a member of 'std' "
I am assuming the makefile isn't written correctly. I am new to makefiles and not sure where to start. Do I need to enforce c++11? How would I do so?
all:
%.o: %.cc
g++ -c -O2 -Wall -Wextra -pedantic $<
library-objects = \
BigUnsigned.o \
BigInteger.o \
BigIntegerAlgorithms.o \
BigUnsignedInABase.o \
BigIntegerUtils.o \
library-headers = \
NumberlikeArray.hh \
BigUnsigned.hh \
BigInteger.hh \
BigIntegerAlgorithms.hh \
BigUnsignedInABase.hh \
BigIntegerLibrary.hh \
library: $(library-objects)
$(library-objects): $(library-headers)
# Components of the program.
program = rsa435
program-objects = rsa435.o
$(program-objects) : $(library-headers)
$(program) : $(program-objects) $(library-objects)
g++ $^ -o $#
clean :
rm -f $(library-objects) $(testsuite-cleanfiles) $(program-objects) $(program)
all : library $(program)
EDIT: It might be worth mentioning that I have both cc files and cpp files. Maybe this is causing an issue as well?
The error is saying is that it knows about the "std" namespace but there is no "mt19937" defined in that namespace.
Add "-std=c++11" to your g++ command line because mt19937 wasn't defined until C++11.
(Credit: this was originally posted by Richard Critten as a comment to the question.)
Also, you might need to add this header file:
#include <random>
"-std=c++11" is not enough , add #include<bits/stdc++.h>
I compile with the following command:
gcc -Wall -march=native -O3 -ffast-math -I/usr/local/include -I/usr/local/include -o waon main.o notes.o midi.o analyse.o fft.o hc.o snd.o -L/usr/local/lib -L/usr/local/lib -lfftw3 -L/usr/local/lib -lsndfile -lm
I now would like to compile with Emscripten. How do I convert the above gcc command into an emcc command?
The command you have described in the question is linking rather than compiling. However in general you should just be able to replace gcc with emcc and it will do the right thing. In this case you will need to replace not only this linking command but also the commands used to compile the sources to the .o files.
It would probably be a good idea to take out the -march option.
It looks like your project is using libsndfile and FFTW. You will probably need to compile these libraries yourself using emscripten. Both of them are using autotools so with a bit of luck you can compile them with emscripten simply by adding the following parameters when you run the configure script:
./configure --prefix=$HOME/emscripten-libs CC=emcc
make && make install
Then when you link your program you can specify -L$HOME/emscripten-libs/lib instead of -L/usr/local/lib.
Make research about emsdk download&setup on your computer.
Download emsdk instruction
Next interest link is :
emcc or em++ instruction
https://emscripten.org/docs/tools_reference/emcc.html
When you setup emcc in command line you can see this project (i make emcc final look based on python script runner.py etc.):
c-cpp-to-javascript
Basic and useful example's :
Pretty analog with gcc :
Args:
-lGL for openGL
-s TOTAL_MEMORY=512MB --memory-init-file 1 Memory staff
--preload-file folderWithImages/--use-preload-plugins If you use assets
-I forInclude/someheader.h
-L libraryFolder/someLib.lib
-std=c11
Simple run:
./emcc -O2 a.cpp -o a.js
or
./emcc -O2 a.cpp -o a.html
Links:
./emcc -O2 a.cpp -o a.bc
./emcc -O2 b.cpp -o b.bc
./emcc -O2 a.bc b.bc -o project.js
Or :
to get JS
emcc -s WASM=1 myAdds.a myLib.a source1.c source2.cpp -o build.js
to get html
emcc -s WASM=1 myAdds.a myLib.a source1.c source2.cpp -o build.html
Link together the bitcode files:
emcc project.bc libstuff.bc -o allproject.bc
Compile the combined bitcode to HTML
emcc allproject.bc -o final.html
Important note :
You can't take an existing .a library and convert it. You must build lib with emcc also.
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.