Invoke OCaml compiler to just produce .cmi - header

maybe I'm just failing in a really simple thing but I'm developing an intepreter written in OCaml with standard tools as ocamllex and ocamlyacc and I have this situation:
iparser.mly contains parser spec
ilexer.mll contains lexer spec
impossible.ml contains the vm that executes the code and all the types needed
The instruction type that defines various instructions is in impossible.ml and it is needed by the parser but impossible.ml uses the parser defined in iparser.mly so they both need each other to compile correctly.
Is there a way to produce just the .cmi file for my impossible.ml? In this way the parser would know about types defined in impossible.ml and it will allow me to compile impossible.cmo/.cmi and later compile also impossible.cmo. Then I can link all of them together.
So far my compiling script is:
ocamlyacc iparser.mly
ocamlc -c iparser.mli
ocamllex ilexer.mll
ocamlc -c ilexer.ml
ocamlc -c iparser.ml
ocamlc -c impossible.ml
ocamlc -o imp.exe ilexer.cmo iparser.cmo impossible.cmo
but this doesn't work because ocamlc -c iparser.ml needs at least impossible.cmi to know the types.
Any suggestions? Thanks in advance..

You need to create an impossible.mli and compile that. That will produce the impossible.cmi and only the .cmi.
Alternatively:
ocamlc -i impossible.ml
will print the mli to stdout. You could do something like this:
ocamlc -i impossible.ml > impossible.mli
ocamlc -c impossible.mli

IMHO, you cannot legitimately compile recursively-dependant modules this way. Either factor out the interdependencies in the third module (usually easy), or pass them as parameters (or mutable initialization references - ugly), or use recursive modules.

Related

cmake: Link order of external (generated) and compiled objects, and libs

I'm playing around with bare-metal x86 and I've hit a snag porting my build from straight-up makefiles to cmake.
In my makefile my objects are defined like this:
LINK_LIST=\
$(LDFLAGS) \
$(ARCHDIR)/crti.o \
$(ARCHDIR)/crtbegin.o \
$(KERNEL_OBJS) \
$(LIBS) \
$(ARCHDIR)/crtend.o \
$(ARCHDIR)/crtn.o \
crtbegin.o and crtend.o are 'generated', that is, provided by my cross-compiler (-print-file-name flag). $(LIBS) are -l flags, like -lgcc, etc. Since this is passed directly to the linker the order is as specified.
My cmake target is defines as follows:
ADD_EXECUTABLE(loader
"${INIT_SRC}"
"${INIT_OBJ}"
"${PLATFORM_SRCS}"
"${ISA_SRCS}"
"${GENERIC_SRCS}"
"${FINI_OBJ}"
"${FINI_SRC}")
INIT_OBJ and FINI_OBJ have EXTERNAL_OBJECT and GENERATED set to true in source file properties. Looking at the command line when running the generated makefile I see that all source files are in the order specified, but init and fini objects are last in the list.
Here is the resulting command line (edited for brevity):
i686-elf-gcc -nostdlib -ffreestanding -nostdinc -T linker.ld -lgcc crti.s.obj boot.s.obj loader.c.obj crtn.s.obj crtbegin.o crtend.o -o loader
The -lgcc flag is explicit in my LINK_FLAGS, which is also something I would like to change.
So I have a few questions regarding this:
Why isn't cmake using the order for the two external object files, but IS using it for the compiled ones?
How can I tell cmake to treat these objects the same as the ones coming from my sources?
How could I get a complete clone of the setup I have in my Makefile (with the library flags between my object files)
I did also check out CMAKE_C_LINK_EXECUTABLE as well, but it doesn't seem to have enough granularity/control over the linker params to achieve this.
I'm using cmake 3.10.2 on ubuntu.
And another (off-topic) question about cmake:
It doesn't treat .S as a standard assembly file extension. I tried adding it with LIST(APPEND CMAKE_ASM-ATT_SOURCE_FILE_EXTENSIONS S), and it does add it just fine, however the files still aren't getting compiled unless I change it to .s. Has anyone else had this issue?
Thanks!
Objects crtbegin.o and crtend.o, which has specific requirement about position in the link command, may be treated as a part of toolchain. If you decide that, then you can set the variable CMAKE_C_LINK_EXECUTABLE to reflect this specific:
SET(ARCHDIR "<...>")
# Object 'crtbegin.o' will be linked before all other objects and libraries.
# Object 'crtend.o' will be linked after all other objects and libraries.
SET(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS>
<LINK_FLAGS>
${ARCHDIR}/crtbegin.o
<OBJECTS> -o <TARGET> <LINK_LIBRARIES>
${ARCHDIR}/crtend.o")
This setting should be done in the toolchain file, which is passed to cmake with option -DCMAKE_TOOLCHAIN=<path/to/toolchain/file>.
With such toolchain, in the CMakeLists.txt you may simply write
ADD_EXECUTABLE(loader ${PLATFORM_SRCS} ${ISA_SRCS} ${GENERIC_SRCS})
Using CMAKE_C_LINK_EXECUTABLE variable you may also position options such as
-nostdlib -ffreestanding -nostdinc -T linker.ld -lgcc
which are very toolchain-related too.
See also this mailing: https://cmake.org/pipermail/cmake/2010-June/037641.html.

importing one ml file into another

I have an interpreter.ml file that contains an interpreter and some type definitions.
I've developed some test batteries to check if the interpreter works well or not.
When I put the functions I use to test the behaviour of the interpreter in the same file of the interpreter all works well, but if I try to use a different file for the tests (let's say tests.ml) it did not load the interpreter functions and definitions.
the interpreter.ml and tests.ml are in the same folder
I tried both with open Interpreter and #use "./interpreter.ml" from inside tests.ml but it wont compile nor shut down the warnings in the IDE (kind of...I'm using Visual Studio Code on MacOs )
I've already tried to follow the official documentation but it won't compile with ocamlopt -c tests.ml
As a result of discussions, the executable is obtained by compiling the 2 files test.ml & interpreter.ml in the right order (test.ml relies on objects defined in interpreter.ml; as a consequence test.ml has to reference to interpreter objects either via the clause open Interpreter or by prefixing all relevant items with Interpreter ):
ocamlc -o exec interpreter.ml test.ml
ocamlbuild is easier as it resolves by itself the dependencies:
The following command:
ocamlbuild test.native
will produce the executable.

How do I save preprocessor output using the Dev-C++ IDE?

I'd like to be able to view preprocessor output in order to make sure my preprocessor directives run correctly. Dev-C++ has an option in Tools > Compiler Options... > General to add commands when calling the compiler, and I've added the command -E C:\Personal\preprocessed.cpp. I got a compiler error saying the file didn't exist, but shouldn't the compiler just create the file in that case? I created the file, and now I'm getting this error: cannot specify -o with -c, -S or -E with multiple files.
Why am I using Dev-C++ instead of Visual Studio? Since I'm still learning, I'd like to be able to test just a few lines of code without having to create an entire new project.
Yes, I've seen this question and no adequate answer was given. Please don't mark this as a duplicate.
Thanks in advance for your help!
I've added the command -E C:\Personal\preprocessed.cpp. I got a compiler error saying the file
didn't exist, but shouldn't the compiler just create the file in that case?
No, because the -E option
takes no argument, filename or otherwise. It simply instructs the
compiler to do nothing but preprocessing. The preprocessed code is written to the standard output. Thus:
Thus:
g++ -E C:\Personal\preprocessed.cpp foo.cpp
tells the compiler that you want run g++ -E with the pair of input files C:\Personal\preprocessed.cpp and foo.cpp,
which as you've discovered is not allowed.
The simple thing that you want to do is absurdly difficult with your IDE of choice. Assuming
the source file you want to preprocess is C:\Personal\foo.cpp and the g++ is in your PATH,
just open a command window in C:\Personal and run:
g++ -E foo.cpp > foo.ii
I suggest the output file foo.ii - though you can call it whatever you like - because g++ recognizes the extension .ii as denoting C++ source code that has already been preprocessed. You can run:
g++ -Wall -o prog foo.ii
and foo.ii will be compiled and linked as program prog without being preprocessed again.

Difficulty in using C standard libraries in the SoCLib tool

I'm an electronic engineering student from Brazil and I'm currently working with embedded systems.
I'm trying to port a MP3 decoder (written in C), called minimp3, to a platform built with the aid of the SoCLib tool (this tool has a bunch of hardware models such as processors, memories and interconnections all written in SystemC witch allows you to build embedded systems models).
The platform I'm building consists of a MIPS processor, a RAM, an interconnection and a TTY (virtual terminal), so obviously the MP3 decoder must be cross compiled.
This MP3 decoder uses some C standard libraries that are not instantiated in the SoCLib tool (witch contains only stdio.h and stdlib.h).
I first tried to run my platform without making any changes in the makefiles provided by the SoCLib tool. With this, when I entered the "make" command I got the following messages (among others of the same type):
undefined reference to `tan'
undefined reference to `sin'
undefined reference to `cos'
undefined reference to `memset'
undefined reference to `realloc'
undefined reference to `open'
undefined reference to `strlen'
Researching about this errors, I found that this could be because the linker was not linking the C headers, so I added the following commands (emphasized) on the makefile:
CFLAGS=-Wall -O2 -I. $(ADD_CFLAGS) $(DEBUG_CFLAGS) $($(ARCH)_CFLAGS) -ggdb -I$(COMMON) **-I/usr/include** $(INTERFACE_CFLAGS)
mipsel-unknown-elf-ld -q $($(ARCH)_LDFLAGS) $(ADD_LDFLAGS) -o $# $(filter %.o,$^) **-lm** -T $(filter %ldscript,$^) $(LIBGCC)*
However, entering the "make" command again, I got the following error:
mipsel-unknown-elf-ld: cannot find -lm
And now I don't know what to do.
Can anyone help me?
When you entered the "make" command, you got the following error:
mipsel-unknown-elf-ld: cannot find -lm
The "mipsel-unknown-elf-" says that you are using the mips cross compiler, and prefixes the "ld" linker-loader command. The -lm option says to link (the "-l" part) the "m" library, which is spelled "libm.a" or "libm.so". Which means that make compiled your
code, and now is trying to link your object file with the "libm" library.
See this link for some more information,
How does a C compiler find that -lm is pointing to the file libm.a?
What you want to do now is tell your linker-loader what path(s) to search for your libraries, which means you need to find "libm.a" and/or "libm.so", and the other libraries that you plan to use, "lib*.a" and "lib*.so*". Determine what paths you need, and then you add these library search paths by using the "-L path" option.
And now you know what to do.
-Chuck

How to configure CMake target or command to preprocess C file?

I originally asked this question on CMake mailing list: How to configure target or command to preprocess C file?
I'm porting build configuration based on GNU Autotools to CMake and I have to deal with C preprocessing to generate a file.
The input for preprocessor is SQL file with C preprocessor directives used, like #include "another.sql", etc.
Currently, Makefile uses the following rule to generate plain SQL file as output:
myfile.sql: myfile.sql.in.c
cpp -I../common $< | grep -v '^#' > $#
So, the myfile.sql is meant to be one of products of the build process, similar to share libraries or executables.
What CMake tools should I use to achieve the same effect?
It's unclear to me if I should use add_custom_command, add_custom_target or combine both.
Obviously, I'm looking for a portable solution that would work at least with GNU GCC and Visual Studio toolsets. I presume I will have to define platform-specific custom commands, one for cpp preprocessor, one for cl.exe /P.
Or, does CMake provide any kind of abstraction for C preprocessor?
I scanned the archives, but I only found preprocessing of fortran files or solutions based on make capabilities: make myfile.i
So, it's not quite what I'm looking for.
UPDATE: Added answer based on solution received from Petr Kmoch on CMake mailing list.
I'm answering the question to myself by copying essential parts of solution received from Petr Kmoch as response to my post in the mailing list.
First, create a custom command using add_custom_command (version with the OUTPUT signature) to actually do the preprocessing.
For example:
add_custom_command(
OUTPUT myfile.sql
COMMAND "${CMAKE_C_COMPILER}" -E myfile.sql.in -I ../common
MAIN_DEPENDENCY myfile.sql.in
COMMENT "Preprocessing myfile.sql.in"
VERBATIM)
Second, configure the command trigger:
If the command output file (myfile.sql) is used in another target, added as a source
file added to add_library or add_executable, it is enough to specify it in these commands. CMake will find it as a dependency and run the custom command as required.
If the command output file is a final output not used as dependency in
any other targets, then add a custom target to drive the command using add_custom_target
For example:
add_custom_target(
ProcessSQL ALL
DEPENDS myfile.sql
COMMENT "Preprocessing SQL files"
VERBATIM)
Credits: Petr Kmoch
To take advantage of CMake' make myfile.i feature, you can do this:
add_library(sql_cpp_target EXCLUDE_FROM_ALL myfile.sql.in.c)
Now running make myfile.sql.in.c.i will produce preprocessed source for you, using defined CMAKE_C_FLAGS. It might be possible to change output name and dir for preprocessed file.
At any rate, you'd need to wrap these make invocations into add_custom_target(ALL ...) to make CMake run them during build.
Use CMAKE_MAKE_PROGRAM variable in targets definitions.
If you want to abstract from build tool, you can call cmake itself to build a target for you. Use ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target targetname when defining custom target.
Alternatively, you can just add_custom_command() which runs specified compiler to preprocess files and put them at the appropriate place. But this seems to be less flexible, IMO.