Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help Understanding Crosscompiling via Make #64

Closed
tajmone opened this issue Jan 25, 2018 · 22 comments
Closed

Help Understanding Crosscompiling via Make #64

tajmone opened this issue Jan 25, 2018 · 22 comments

Comments

@tajmone
Copy link

tajmone commented Jan 25, 2018

Hello. I'm new both to OCaml and opam cross-compiler for Windows, so I was hoping you could help me out (bare patient with me, I'm trying to pose the problem the best I can, but I'm a bit out of my depth on this).

I've succeeded to install opam-cross-windows, as per instructions, on Ubuntu 16-10 x64 — but only the 64 bit version, the 32 bit failed to compile on two different machine, reporting problems with GCC. But 64 bits would be fine.

So, my setup seems ok, up and running (I didn't take the MXE Env route, though).

The problem is that I'm trying to build an existing project, which uses a makefile, and the instruction page of opam-cross-windows only mentions porting project from OASIS or OPAM .install.

The compilation examples in the instructions always refer to using ocamlfind -toolchain windows, but the project I'm trying to cross compile only refers to ocamlopt as compiler commands. So I haven't managed to work out how to cross compile it. The proejct doesn't have external dependencies.

Here is how the makefile sets up the variables then uses to invoke the compiler:

MLDEP       = ocamldep -native
MLC         = ocamlopt
MLCOPTS     = -inline 23 -unsafe
MLLDOPTS    = unix.cmxa
MLLEX       = ocamllex
MLYACC      = ocamlyacc

(the full makefile source:)

Which way should that be changed to cross compile and create a Windows executable?

I haven't worked out the part of the instructions that says:

Don't forget to add ocaml-windows as a dependency!

I've tried googling this, but haven't managed to find examples.

Any help would be much apreciated. Thanks.

@toots
Copy link
Member

toots commented Jan 25, 2018

Hi @tajmone,

You first try should be to edit the Makefile to use the host-prefixed compiling tools. For instance, change ocamlopt to: x86_64-w64-mingw32.static-ocamlopt.

You have to apply a little thinking to it because not all tools will need this change. For instance, ocamlyacc and ocamllex produce text files as, thus, are not architecture dependent.

@tajmone
Copy link
Author

tajmone commented Jan 26, 2018

Thanks a lot @toots ! this tip was precious, it sets me in motion in the right direction.

I'll let you know how it went.

@whitequark
Copy link
Member

Really, the right thing to do is to replace e.g. ocamlc with ocamlfind -toolchain windows ocamlc, not add prefixes. With prefixes, you limit yourself to only one architecture.

@tajmone
Copy link
Author

tajmone commented Jan 26, 2018

I've tried this but it failed. The problem could be that the make file reuses the same macro for invoking the compiler on different source files, I might be better offer breaking up the makefile into single and plain invocations, at lease untill I make it work.

@whitequark
Copy link
Member

ocamlfind ocamlc should be a drop-in replacement for ocamlc and it's a bug if it isn't.

@tajmone
Copy link
Author

tajmone commented Jan 26, 2018

Does this also apply to ocamlopt? the makefile uses ocamlopt to compile native code, not bytecode, and my intention is to cross-compile to native code also — does cross compiling distinguish between native and bytecode? or does it just produce native code?

My previous attempts to change the makefile from

MLDEP       = ocamldep -native
MLC         = ocamlopt
MLCOPTS     = -inline 23 -unsafe

to

MLDEP       = ocamldep -native
MLC         = ocamlfind -toolchain windows ocamlopt
MLCOPTS     = -inline 23 -unsafe

have failed. But I need to look better into the error reports.

@toots, you mentioned:

You have to apply a little thinking to it because not all tools will need this change. For instance, ocamlyacc and ocamllex produce text files as, thus, are not architecture dependent.

how does cross compiling to Windows handle EOL? does it use CRLF in input/ouput of text files? I thought that the EOL difference between Linux and Windows would pop its head up here, and that relying on the cross compiler also for text files would be safer within the same toolchain.

Inside Bash for Windows EOLs are handled smartly, and either CRLF or LF can be used in its context. But the project at thand is being compiled under a real linux machine (Ubuntu), not in an emulation environment.

@toots
Copy link
Member

toots commented Jan 26, 2018

You shouldn't need to cross-compile for bytecode as it is by definition platform-independent. The only exception being if your project has embedded C bindings. Otherwise, all you should need is a local ocamlc(.exe) executable.

As for CRLF, do you mean that as the line return in OCaml source code? I don't think this would matter at all.

@whitequark
Copy link
Member

Does this also apply to ocamlopt? the makefile uses ocamlopt to compile native code, not bytecode, and my intention is to cross-compile to native code also — does cross compiling distinguish between native and bytecode? or does it just produce native code?

Yes, it applies to every tool ocamlfind has support for.

Usage: ocamlfind query        [-help | other options] <package_name> ...
   or: ocamlfind ocamlc       [-help | other options] <file> ...
   or: ocamlfind ocamlcp      [-help | other options] <file> ...
   or: ocamlfind ocamlmklib   [-help | other options] <file> ...
   or: ocamlfind ocamlmktop   [-help | other options] <file> ...
   or: ocamlfind ocamlopt     [-help | other options] <file> ...
   or: ocamlfind ocamloptp    [-help | other options] <file> ...
   or: ocamlfind ocamldep     [-help | other options] <file> ...
   or: ocamlfind ocamlbrowser [-help | other options]
   or: ocamlfind ocamldoc     [-help | other options] <file> ...
   or: ocamlfind install      [-help | other options] <package_name> <file> ...
   or: ocamlfind remove       [-help | other options] <package_name>
   or: ocamlfind printppx     [-help | other options] <package_name> ...
   or: ocamlfind printconf    [-help] [variable]
   or: ocamlfind lint         [-help] <file>
   or: ocamlfind list
   or: ocamlfind pkg/cmd arg ...
Select toolchain with:
  ocamlfind -toolchain <t> <command>
Abbreviations:
  e.g. ocamlfind opt instead of ocamlfind ocamlopt

And you should also use ocamldep with ocamlfind. Like I said, all tools supported by ocamlfind should be used through ocamlfind.

@tajmone
Copy link
Author

tajmone commented Jan 26, 2018

After editing the make file as mentioned:

MLC         = ocamlfind -toolchain windows ocamlopt
# MLC         = ocamlopt

this is the compile error I get:

$ make
ocamlfind -toolchain windows ocamlopt unix.cmxa ver.cmx prelude.cmx err.cmx absyn.cmx env.cmx check.cmx pre.cmx gen.cmx fake.cmx parser.cmx lexer.cmx io.cmx main.cmx -o polygen
ocamlfind: [WARNING] Undefined toolchain: windows
File "_none_", line 1:
Error: main.cmx
is not a compilation unit description.
makefile:44: recipe for target 'polygen' failed
make: *** [polygen] Error 2

it looks like something is not right with cross-windows setup.

If I type ocamlfind list I get the following error in the report (reduced version):

$ ocamlfind list
findlib: [WARNING] cannot read directory /usr/lib/ocaml/METAS: No such file or directory

@whitequark
Copy link
Member

You forgot to run eval $(opam config env).

@tajmone
Copy link
Author

tajmone commented Jan 26, 2018

No, OPAM init has set that in the .basharc file. I've typed it anyhow, but the error is the same.

@whitequark
Copy link
Member

Well, the underlying cause here is that something is wrong with your OPAM installation.

@tajmone
Copy link
Author

tajmone commented Jan 26, 2018

I've tried the examples from the instruction page:

echo 'let () = print_endline "Hello, world!"' >helloworld.ml
ocamlfind -toolchain windows ocamlc helloworld.ml -o helloworld.byte
ocamlfind -toolchain windows ocamlopt helloworld.ml -o helloworld.native

and I also get the ocamlfind: [WARNING] Undefined toolchain: windows.

Any ideas how to check the setup, or reinstall it?

@tajmone
Copy link
Author

tajmone commented Jan 26, 2018

I'm going through all the cross-windows setup steps again, hoping it will fix it. This time I'm trying to install the 32bit version, which previously failed to compile.

@toots
Copy link
Member

toots commented Jan 26, 2018

You should start with checking which ocamlfind you are using:

% which ocamlfind

@tajmone
Copy link
Author

tajmone commented Jan 26, 2018

$ which ocamlfind
/home/myusername/.opam/4.04.0+32bit/bin/ocamlfind

@tajmone
Copy link
Author

tajmone commented Jan 26, 2018

Again, trying to install the 32bit version failed to compile.

After switching to 4.04.0+32bit and pinning as documented, when I type $ opam install ocaml-windows it fails with this error:

### stderr ###
# [...]
# win32.c: In function ‘caml_executable_name’:
# win32.c:622:7: warning: unused variable ‘retcode’ [-Wunused-variable]
#    int retcode;
#        ^~~~~~~
# fix_code.c: In function ‘caml_load_code’:
# fix_code.c:60:7: warning: implicit declaration of function ‘read’ [-Wimplicit-function-declaration]
#    if (read(fd, (char *) caml_start_code, caml_code_size) != caml_code_size)
#        ^~~~
# /bin/sh: 2: gawk: not found
# make: *** [bytecomp/opcodes.ml] Error 127

a previous attempt to install it after switching to the 64 bit version also failed. On another machine, under WSL/Ubuntu, both failed, with a different error complaining about GCC not supporting ISO C, or other C related errors.

@toots
Copy link
Member

toots commented Jan 26, 2018

There seems to be an inconsistency here. The 4.04.0+32bit switch is for building for 32 bit architectures. If you intent to use the 64 bit cross-compiler you should be using the 4.04.0 switch.

As for the other issue, it looks like you just need to install the gawk binary.

@tajmone
Copy link
Author

tajmone commented Jan 26, 2018

I'm installing gawk right now, but when I compiled the 64 bit version, previously, it succeeded and didn't mention gawk. I originally intended to cross compile to 32bit, but since it always failed to compile the 32bit version I ended up using the 64bit version — which seems not to work though.

This second time I've tried to just reinstall the 64bit version it failed to compile, so I switched to the 32bit (which I'd preferr, but at any version would be fine ultimately, as a starting point).

@tajmone
Copy link
Author

tajmone commented Jan 26, 2018

Finally! The 32bit version compiled, and the tests from the homepage instruction all passed without error:

echo 'let () = print_endline "Hello, world!"' >helloworld.ml
ocamlfind -toolchain windows ocamlc helloworld.ml -o helloworld.byte
ocamlfind -toolchain windows ocamlopt helloworld.ml -o helloworld.native

Thanks, now it looks that cross-windows is properly setup, and I can focus on the makefile.

PS: I'm really sorry for bothering you so much, and grateful for you patience and kind support. I've spent over a week trying to setup OCaml under Windows, and stumbled into a lot problems (which seem to be common under Win 10), finally managing to install it under WSL/Ubuntu. So I opted to just install OCaml under linux and cross compile, but I'm entering a new arena, facing multiple new tools and challenges all at once.

@tajmone
Copy link
Author

tajmone commented Jan 26, 2018

I just wanted to confirm that I've tested the helloworld.native binary (of the above example) under Windows (renamed as .exe) and works perfectly!

@tajmone
Copy link
Author

tajmone commented Jan 26, 2018

Solved!

Thank you very much, I couldn't have done it without your help. ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants