ocamlbuild and OUnit - makefile

I have a project structured like this:
Makefile
src/
main.ml
tests/
tests.ml
and the Makefile is something like this:
tests:
ocamlbuild -Is src,tests tests.byte -build-dir $(BUILDDIR) $(TESTFLAGS) -lflags -I,/usr/lib/ocaml/oUnit -cflags -I,/usr/lib/ocaml/oUnit -libs oUnit
Running make tests (after building main.byte) returns this error:
ocamlbuild -Is src,tests tests.byte -build-dir build -lflags -I,/usr/lib/ocaml/oUnit -cflags -I,/usr/lib/ocaml/oUnit -libs oUnit
+ /usr/bin/ocamlc -c -I /usr/lib/ocaml/oUnit -I tests -I src -o tests/tests.cmo tests/tests.ml
File "tests/tests.ml", line 3, characters 46-50:
Error: Unbound value main
Command exited with code 2.
Compilation unsuccessful after building 2 targets (0 cached) in 00:00:00.
make: *** [tests] Error 10
showing that ocamlbuild cannot link to main.byte. What should the tests rule of the Makefile look like?

Since OCaml programs don't have a default main function (OCaml just runs the top-level code in each module at start-up) you'll probably want to have a separate file for starting the code. e.g.
main.ml
myprog.ml
tests.ml
Where:
main.ml defines a main function let main args = ...
myprog.ml just calls it: let () = Main.main Sys.argv
tests.ml calls it in the same way from each test-case
Then build myprog.byte and tests.byte as your two targets to ocamlbuild. Run myprog.byte to run the program and tests.byte to run the tests.

unbound value main does not sound like an error related to main.byte, but a genuine mistake in the OCaml code of tests.ml. Could you provide (possibly simplified) sources to experiment?
(Thomas' advice on program structure of course still stands, independently.)

Related

makefile rules in other rules

I have a Makefile with two rules. i want to include one rule in another.
example:
|--> compile:
| g++ main.cpp -o main
| run:
----- compile (should execute the compile rule)
./main
how do i do this?? because when i try to do this it doesn't work.
it gives me this error:
make: compile: Command not found
make: *** [Makefile:4: all] Error 127
the arrows and lines are just to point the rule
The common and trivial way to do this is to have one target depend on the other.
run: compile
./main
There is no need to name the compile rule separately, though.
run: main
./$<
(Obscurely but conveniently uses the first dependency as the name of the script to run. make probably already knows how to make main so you don't need to spell that out.)

rebar compile fails with bitcask - "errno.h": no such file

I am new to Erlang, so i am going through Joe Armstrong's book "Programming Erlang". In chapter 25 there's an example on how to work with rebar. I followed the instructions and created a Makefile
all:
test -d deps || rebar get-deps
rebar compile -v
#erl -noshell -pa './deps/bitcask/ebin' -pa './ebin' -s myapp start
and rebar.config
{deps, [
{bitcask, ".*", {git, "git://github.com/basho/bitcask.git", "master"}}
]}.
Getting the dependencies works, but compiling fails.
The verbose output tells me that this command fails
cmd: cc -c $CFLAGS -g -Wall -fPIC -I"/usr/lib/erlang/lib/erl_interface-3.7.18/include" -I"/usr/lib/erlang/erts-6.2/include" c_src/bitcask_nifs.c -o c_src/bitcask_nifs.o
with this error
/home/user/folder/deps/bitcask/c_src/bitcask_nifs.c:22:19: fatal error: errno.h: No such file or directory
But
find /usr/include -name errno.h
gives me
/usr/include/x86_64-linux-gnu/asm/errno.h
/usr/include/asm/errno.h
/usr/include/linux/errno.h
/usr/include/asm-generic/errno.h
So I was asking myself..
what am I missing?
how can I tell rebar about the depencies on the C libraries and where to find them?
why isn't this configured correctly in the Makefile of bitcask?
Maybe I was searching for the wrong terms, but I couldn't find any solution in the internets.
Many thanks in advance
There are two thing to consider
rebar options
You can set options for compiling C code with port_env option in rebar.config.
comiling deps
Since bitstack is your dependency, it is not compiled with yours rebar config, but with it's own. So if you would like to change anything, you would have to modify the bitcask file.
Fortunately, if you look into config their writen all C compilation is done with environment variable $ERL_CFLAGS. And again, in rebar source code you can see that this flag is responsible for include paths in your compilation.
So easist way would be extending $ERL_CFLAGS in your Makefile before compilation, with something like this
all: ERL_CFLAGS = "$ERL_CFLAGS -I /usr/include/linux/errno.h"
all:
test -d deps || rebar get-deps
rebar compile -v
#erl -noshell -pa './deps/bitcask/ebin' -pa './ebin' -s myapp start
Just make sure that this include works for you, and that you are not overwriting any flags you are using.

How to test the static_assert in my library with cmake?

in my library code I have a bunch of static_asserts. I want to test if they fire under the expected conditions.
I would like to write a range of test files and
ensure that they fail to compile
check the output of the compilation attempt for the expected message from the static assert
Does anyone know how to do that with cmake?
AFAICT, try_compile is not the answer, because it is executed while running cmake. I need these checks to be executed during make.
You could set up a "nested" project for these tests, configure it as part of your CMake run and then build it using cmake --build; something like this:
Your normal CMakeLists.txt:
# ...
execute_process(
COMMAND ${CMAKE_COMMAND} path/to/test/project
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/TestProject
)
add_test(
NAME StaticAsserts
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/TestProject
COMMAND ${CMAKE_COMMAND} --build .
)
# ...
Of course, the test command could actually be a wrapper script running cmake --build internally and processing its output.
As an alternative, you could move the configuration of the nested project into the test as well, perhaps using CTest to drive the configure & build.
After several more experiments, this is what I am doing now:
add_executable(
fail_test
EXCLUDE_FROM_ALL
fail_test.cpp
)
add_custom_command(OUTPUT fail_test.out
COMMAND ${CMAKE_MAKE_PROGRAM} fail_test > ${CMAKE_CURRENT_BINARY_DIR}/fail_test.out 2>&1 || true
COMMAND grep "int i = row.alpha" ${CMAKE_CURRENT_BINARY_DIR}/fail_test.out > /dev/null
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/fail_test.cpp
COMMENT "fail_test"
)
add_custom_target(test_constraints DEPENDS fail_test.out COMMAND true)
This is what it does:
Create a target for compiling the code that is supposed to fail at compile time. Exclude this target from the default build so that it does not create a mess.
Add a custom command that calls make for this fail-target, pipes the compiler spew into a file, ignores the result code and then greps for the expected compiler message that indicates that the compilation failed due to the expected reason.
Make the custom command depend on the source file, so that the compilation is tested again when the source file is ended.
Add the custom command as dependency to a custom target.
Of course, for more tests, steps 1, 2 and 4 would go into a function.
So now I can call
make test_constraints
to test if the stuff I want to fail compiling actually does so. And if something does not fail as expected, I can even call
make fail_test
to tune the test or its basis until it fails correctly.
For platform independence, the custom command will probably have to be adjusted. Suggestions welcome.
Add this to your CMakeLists.txt:
include(CTest)
# Test that code is NOT able to compile
function(TestStaticCheck TEST_NAME)
add_executable(${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_NAME}.cpp)
target_link_libraries(${TEST_NAME} MyLibrary)
add_test(NAME ${TEST_NAME}
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ${TEST_NAME}
)
set_tests_properties(${TEST_NAME} PROPERTIES WILL_FAIL TRUE)
endfunction()
TestStaticCheck(TestFoo)
Then put this in TestFoo.cpp in the same directory as your CMakeLists.txt:
int main()
{
// Code that should NOT compile
}

Makefile error: make: *** No rule to make target `genesha.main.java.Jni.class', needed by `FileOperationsLibrary.h'. Stop." in Eclipse (Windows)

I have problem with my makefile. I'm working on Eclipse in Windows and my file structure is like below (project path: D:/workspace):
Genesha
|
|___bin
| |_genesha
| |_main
| |_java
|___src |__Jni.class
|_genesha
|_main
|_jni
|__makefile
When I in cmd from localization of makefile (D:\workspace\Genesha\src\genesha\main\jni) I used command:
javah -o FileOperationsLibrary.h -jni -classpath ../../../../bin genesha.main.java.Jni
it works correctly. But when I used my makefile, I have following error:
make: *** No rule to make target `genesha.main.java.Jni.class', needed by `FileOperationsLibrary.h'. Stop.
I was searching long time error and now I have not idea what's wrong here...
EDIT: my makefile
FileOperationsLibrary.h: genesha.main.java.Jni.class
javah -o FileOperationsLibrary.h -jni -classpath ../../../../bin genesha.main.java.Jni
EDIT 2: Finally, thanks to MadScientist my make file code is:
FileOperationsLibrary.h: ../../../../bin/genesha/main/java/Jni.class
javah -o FileOperationsLibrary.h -jni -classpath ../../../../bin genesha.main.java.Jni
Thank you a lot for help :)
That error means that in your makefile somewhere you have a target FileOperationsLibrary.h that lists genesha.main.java.Jni.class as a prerequisite, something like:
FileOperationsLibrary.h: genesha.main.java.Jni.class
The file genesha.main.java.Jni.class does not exist, so make tries to find a way to build it. However there are no rules defined in the makefile that tell it how to build that file, so you get that error message.

Can I make gotest pass compiler flags?

I have just put together a Go package that is going to be a part in a fairly large system with a lot of shared packages. I was able to get it to compile by writing its Makefile such that the compiler is called with -I flags:
include $(GOROOT)/src/Make.inc
TARG=foobar
GOFILES=\
foobar.go\
foobar:
$(GC) -I$(CURDIR)/../intmath -I$(CURDIR)/../randnum foobar.go
include $(GOROOT)/src/Make.pkg
It compiles just fine, and being a good boy, I wrote a comprehensive set of tests. However, when I try to run the tests with gotest, I get a compile error:
$ gotest
rm -f _test/foobar.a
8g -o _gotest_.8 foobar.go foobar_test.go
foobar.go:4: can't find import: intmath
make: *** [_gotest_.8] Error 1
gotest: "C:\\msys\\bin\\sh.exe -c \"gomake\" \"testpackage\" \"GOTESTFILES=foobar_test.go\"" failed: exit status 2
So, the Go file itself will compile when I use the -I flags to tell it where to find the intmath and randnum packages, but gotest doesn't seem to use the Makefile.
Answering peterSO's question:
foobar.go's import section looks like this:
import (
"intmath"
"randnum"
"container/vector"
)
And the compile works fine as long as I have the -I flags going to the compiler. I have tried to use relative paths, like this:
import (
"../intmath"
"../randnum"
"container/vector"
)
but that just doesn't seem to work.
EDIT: answering further peterSO questions:
GOROOT is set to C:\Go the directory where I have all of the Go stuff -- aside from my source code -- installed. I was expecting the relative path to be relative to the directory in which the source file lives.
My source tree looks like this:
server/
foobar/
randnum/
intmath/
So, while I am open to a different, more Go-idiomatic directory structure, my instinct is to arrange them as peers.
Is there some way that I can nudge gotest into compiling foobar.go with the needed flags?
Create the Windows source code directory structure:
C:\server
C:\server\foobar
C:\server\intnum
For intnum.go:
package intnum
func IntNum() int {
return 42
}
Makefile:
include $(GOROOT)/src/Make.inc
TARG=server/intnum
GOFILES=\
intnum.go\
include $(GOROOT)/src/Make.pkg
Run:
$ cd c/server/intnum
$ make install
For foobar.go:
package foobar
import (
"math"
"server/intnum"
)
func FooBar() float64 {
return float64(intnum.IntNum()) * math.Pi
}
Makefile:
include $(GOROOT)/src/Make.inc
TARG=server/foobar
GOFILES=\
foobar.go\
include $(GOROOT)/src/Make.pkg
Run:
$ cd /c/server/foobar
$ make install
After the install, the intnum.a and foobar.a package files will be in the $GOROOT\pkg\windows_386\server (C:\Go\pkg\windows_386\server) directory`.

Resources