Include mly files nested in subdirectories when compiling with dune - ocaml

Say I have the following directory:
.
├── dune-project
├── myproj.opam
└── src
├── dune
├── module1.ml
├── parser1
│   └── file1.ml
└── parser2
└── file2.ml
Since I want everything to be in the same library, I have the following:
src/dune:
(include_subdirs unqualified)
(library
(name myproj)
(modules module1 file1 file2)
)
And it compiles perfectly well.
Now, the thing is, my file1 and file2 are actually mly files so I have this:
.
├── dune-project
├── myproj.opam
└── src
├── dune
├── module1.ml
├── parser1
│   └── parser1.mly
└── parser2
└── parser2.mly
If I try to compile (by changing file(1|2) by parser(1|2) in the dune file), I have the following error:
❯ dune build
File "src/dune", line 5, characters 26-33:
5 | (modules module1 parser1 parser2 )
^^^^^^^
Error: Module Parser2 doesn't exist.
I edit my dune file:
(include_subdirs unqualified)
(menhir
(modules parser1 parser2)
)
(library
(name myproj)
(modules module1 parser1 parser2 )
)
Two errors now:
❯ dune build
File "src/dune", line 3, characters 0-36:
3 | (menhir
4 | (modules parser1 parser2)
5 | )
Error: No rule found for src/parser1.mly
File "src/dune", line 3, characters 0-36:
3 | (menhir
4 | (modules parser1 parser2)
5 | )
Error: No rule found for src/parser2.mly
Ok, I then add two dune files in parser(1|2) directories:
(menhir
(modules parser(1|2))
)
[EDIT] Looks like I missed something but this was actually working pretty well
And I now have the same error as before:
❯ dune build
File "src/dune", line 5, characters 26-33:
5 | (modules module1 parser1 parser2 )
^^^^^^^
Error: Module Parser2 doesn't exist.
Am I missing something to please dune? (I have the same problem if I have .mll files)

The menhir stanza doesn't work with subdirs. It is a bug that is not yet fixed1. There are a couple of workarounds, like adding the dune file to the folder where you have the parser (didn't check it myself). But I would suggest splitting the parsers into separate libraries or moving them to the src folder. The former is preferred, especially since then you won't need to write the modules stanza.
1)As of January 2022

Related

cmake : shared library or sub-prjoect

I am builfing a new c++ project and i want to integrate cmake and i dont know what is the best approach i have to follow
my project tree looks like this :
.
├── http
| ├── include
| | └── http.h
| |
| └── src
| ├── http.cpp
| └── main.cpp
├── dns
| ├── include
| | └── dns.h
| |
| └── src
| ├── dns.cpp
| └── main.cpp
...
I dont really dont know what to do and i m not quite familiar with cmake
doing a shared library from every directory and link them together in cmake file
a sub-project for every directory .

OCaml open own module

I want to open Vegetables in my shoppinglist.ml but I get an error message Unbound module Vegetables
My directory structure looks like this:
market/
|_ src/
|_ shoppinglist.ml
|_ shoppinglist.mli
|_ vegetables/
|_ vegetables.ml
shoppinglist.ml:
open Vegetables
I use dune build and usually after that dune utop . to build my project.
dune in src:
(library
(name shoppinglist)
(libraries vegetables)
(flags
(:standard -warn-error -27)))
dune in vegetables:
(library
(name vegetables)
(modules vegetables)
(flags
(:standard -warn-error -27)))
I already tried many "solutions" but non of them worked out for me...
With the following architecture I have no problem at all:
.
├── bin
│   ├── dune
│   └── main.ml
let () = Shoppinglist.a ()
├── dune-project
├── program.opam
├── src
│   ├── dune
│   └── shoppinglist.ml
let a () = Vegetables.a ()
└── vegetables
├── dune
└── vegetables.ml
let a () = Printf.printf "vegetables\n"
dune files are the same as yours, I just added a bin directory with a main.ml file to execute some code from the library.
The dune file in bin is:
(executable
(name main)
(public_name program)
(libraries shoppinglist)
(flags
(:standard -warn-error -27)))
And
❯ dune exec program
vegetables
So I'm not exactly sure what's your problem here.

Unison: Ignore files with Regex doesn't work

I tried to ignore some files that end with ".NUMBERS" like .133443. I tried this Regex but it still copies the files:
unison -batch -owner -group -times -ignore "Regex ^*\.[0-9]+$" /hadoop/bigdata/giin/data ssh://cnp31ginhortonen1.giin.recouv//hadoop/bigdata/giin/data -prefer newer`
Source :
[root#cnp31ginhortonen1 .unison]# tree /hadoop/bigdata/giin/data/
/hadoop/bigdata/giin/data/
├── aefd.csv
├── aefd.log
├── aefd.xml
├── subdir
│   ├── aefd.csv
│   ├── aefd.log
│   ├── aefd.xml
│   └── TB5E.B01.117.210409074
├── TB5E.B01.117.10409074
└── TB5E.B01.117.210409074

Shell - copying directories recursively with RegEx matching preserving tree structure

I need to write a script, that would copy a directory recursively, but only copying subdirectories and files matched by a certain RegEx. For instance for a tree like this:
.
└── toCopy
├── A
│   ├── 123
│   ├── D
│   │   └── rybka23
│   ├── file
│   ├── file1
│   └── random
├── B
├── C
│   ├── file_25
│   └── somefile
└── E1
└── something
For a RegEx
.*[0-9]+
I need to get a new directory:
newDir
├── A
│   ├── 123
│   ├── D
│   │   └── rybka23
│   └── file1
├── C
│   └── file_25
└── E1
So my first thinking was something like this:
find toCopy -regex ".*[0-9]+" -exec cp -R '{}' newDir \;
But that doesn't really work, because I'm only getting the paths to the files/directories I need to copy and I have no idea how to build the tree from them.
I would really appreciate any hints on how to do that.
You can do that using find command and loop through the results:
#!/usr/bin/env bash
cd toDir
while IFS= read -rd '' elem; do
if [[ -d $elem ]]; then
mkdir -p ../newDir/"$elem"
else
d="${elem%/*}"
mkdir -p ../newDir/"$d"
cp "$elem" ../newDir/"$d"
fi
done < <(find . -name '*[0-9]*' -print0)
This requires bash as we are using process substitution.

explicit dependency not being picked correctly with scons

I have a scons build environment set up something like :
--SConstruct [Top level file]
--dir1
--Sconscript
--src
--inc
--dir2
--Sconscript
--src
--inc
[dir1]
building dir1 results in several .so being generated, lets say libdir1_a.so, libdir1_b.so, libdir1_c.so etc.
all these shared libs ar eplaced in some folder - $install/dir1/lib/
[dir2]
when building src for dir2, it needs one library to be linked from dir1, libdir1_b.so
I use
env.Depends(dir2_target, $install/dir1/lib/libdir1_b.so)
to specify the dependency.
However, when building source sin dir2 it fails saying explicit dependency not found.
What do i need to do to make sure dir1 builds before dir ?
The solution for your use case is to not use explicit dependencies. The Depends function is not needed here. SCons is smart enough to figure out these types of dependencies.
Here is a working example, because that always makes an explanation better!
>> scons --version
SCons by Steven Knight et al.:
script: v2.3.6.rel_2.3.5:3347:d31d5a4e74b6[MODIFIED], 2015/07/31 14:36:10, by bdbaddog on hpmicrodog
engine: v2.3.6.rel_2.3.5:3347:d31d5a4e74b6[MODIFIED], 2015/07/31 14:36:10, by bdbaddog on hpmicrodog
engine path: ['/usr/lib/scons/SCons']
Copyright (c) 2001 - 2015 The SCons Foundation
>> tree
.
├── dir1
│   ├── include
│   │   ├── dir1_a.h
│   │   ├── dir1_b.h
│   │   └── dir1_c.h
│   ├── SConscript
│   └── src
│   ├── dir1_a.cpp
│   ├── dir1_b.cpp
│   └── dir1_c.cpp
├── dir2
│   ├── include
│   │   └── dir2_a.h
│   ├── SConscript
│   └── src
│   └── dir2_a.cpp
└── SConstruct
6 directories, 11 files
>> find . -type f | xargs awk 'FNR==1{print FILENAME; }{ print }'
./dir2/src/dir2_a.cpp
#include <dir2_a.h>
#include <dir1_a.h>
#include <iostream>
void dir2_a::myhello() {dir1_a::hello();}
./dir2/include/dir2_a.h
#include <iostream>
namespace dir2_a { void myhello();}
./dir2/SConscript
Import('env')
local_env = env.Clone()
local_env.Append(CPPPATH=['include', '#include'],
LIBPATH=['#lib'],
LIBS=['dir1_a'],
RPATH=['$$$$\\{ORIGIN}/.'])
liba = local_env.SharedLibrary('src/dir2_a.cpp')
Install('#lib', [liba])
Install('#include', Glob('include/*.h'))
./SConstruct
env = Environment()
Export('env')
SConscript('dir1/SConscript')
SConscript('dir2/SConscript')
./dir1/src/dir1_a.cpp
#include <dir1_a.h>
#include <iostream>
void dir1_a::hello() {std::cout << "A" << std::endl;}
./dir1/src/dir1_b.cpp
#include <dir1_b.h>
#include <iostream>
void dir1_b::hello() {std::cout << "B" << std::endl;}
./dir1/src/dir1_c.cpp
#include <dir1_c.h>
#include <iostream>
void dir1_c::hello() {std::cout << "C" << std::endl;}
./dir1/include/dir1_c.h
#include <iostream>
namespace dir1_c { void hello();}
./dir1/include/dir1_b.h
#include <iostream>
namespace dir1_b { void hello();}
./dir1/include/dir1_a.h
#include <iostream>
namespace dir1_a { void hello();}
./dir1/SConscript
Import('env')
local_env = env.Clone()
local_env.Append(CPPPATH='include')
liba = local_env.SharedLibrary('src/dir1_a.cpp')
libb = local_env.SharedLibrary('src/dir1_b.cpp')
libc = local_env.SharedLibrary('src/dir1_c.cpp')
Install('#lib', [liba, libb, libc])
Install('#include', Glob('include/*.h'))
>> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o dir1/src/dir1_a.os -c -fPIC -Idir1/include dir1/src/dir1_a.cpp
g++ -o dir1/src/dir1_b.os -c -fPIC -Idir1/include dir1/src/dir1_b.cpp
g++ -o dir1/src/dir1_c.os -c -fPIC -Idir1/include dir1/src/dir1_c.cpp
g++ -o dir1/src/libdir1_a.so -shared dir1/src/dir1_a.os
g++ -o dir1/src/libdir1_b.so -shared dir1/src/dir1_b.os
g++ -o dir1/src/libdir1_c.so -shared dir1/src/dir1_c.os
Install file: "dir1/include/dir1_a.h" as "include/dir1_a.h"
g++ -o dir2/src/dir2_a.os -c -fPIC -Idir2/include -Iinclude dir2/src/dir2_a.cpp
Install file: "dir1/src/libdir1_a.so" as "lib/libdir1_a.so"
g++ -o dir2/src/libdir2_a.so -shared -Wl,-rpath=$\{ORIGIN}/. dir2/src/dir2_a.os -Llib -ldir1_a
Install file: "dir1/include/dir1_b.h" as "include/dir1_b.h"
Install file: "dir1/include/dir1_c.h" as "include/dir1_c.h"
Install file: "dir2/include/dir2_a.h" as "include/dir2_a.h"
Install file: "dir1/src/libdir1_b.so" as "lib/libdir1_b.so"
Install file: "dir1/src/libdir1_c.so" as "lib/libdir1_c.so"
Install file: "dir2/src/libdir2_a.so" as "lib/libdir2_a.so"
scons: done building targets.
>> tree
.
├── dir1
│   ├── include
│   │   ├── dir1_a.h
│   │   ├── dir1_b.h
│   │   └── dir1_c.h
│   ├── SConscript
│   └── src
│   ├── dir1_a.cpp
│   ├── dir1_a.os
│   ├── dir1_b.cpp
│   ├── dir1_b.os
│   ├── dir1_c.cpp
│   ├── dir1_c.os
│   ├── libdir1_a.so
│   ├── libdir1_b.so
│   └── libdir1_c.so
├── dir2
│   ├── include
│   │   └── dir2_a.h
│   ├── SConscript
│   └── src
│   ├── dir2_a.cpp
│   ├── dir2_a.os
│   └── libdir2_a.so
├── include
│   ├── dir1_a.h
│   ├── dir1_b.h
│   ├── dir1_c.h
│   └── dir2_a.h
├── lib
│   ├── libdir1_a.so
│   ├── libdir1_b.so
│   ├── libdir1_c.so
│   └── libdir2_a.so
└── SConstruct
8 directories, 27 files
>> ldd lib/libdir2_a.so
linux-vdso.so.1 (0x00007ffdb53a5000)
libdir1_a.so => ./libdir1_a.so (0x00007f0707bd7000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f070782f000)
libm.so.6 => /lib64/libm.so.6 (0x00007f070752d000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f0707316000)
libc.so.6 => /lib64/libc.so.6 (0x00007f0706f54000)
/lib64/ld-linux-x86-64.so.2 (0x000055bd342e4000)
If you want to see that the dependency tree is really being automatically setup, just execute the following...
>> scons --tree=prune
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o dir1/src/dir1_a.os -c -fPIC -Idir1/include dir1/src/dir1_a.cpp
g++ -o dir1/src/dir1_b.os -c -fPIC -Idir1/include dir1/src/dir1_b.cpp
g++ -o dir1/src/dir1_c.os -c -fPIC -Idir1/include dir1/src/dir1_c.cpp
g++ -o dir1/src/libdir1_a.so -shared dir1/src/dir1_a.os
g++ -o dir1/src/libdir1_b.so -shared dir1/src/dir1_b.os
g++ -o dir1/src/libdir1_c.so -shared dir1/src/dir1_c.os
Install file: "dir1/include/dir1_a.h" as "include/dir1_a.h"
g++ -o dir2/src/dir2_a.os -c -fPIC -Idir2/include -Iinclude dir2/src/dir2_a.cpp
Install file: "dir1/src/libdir1_a.so" as "lib/libdir1_a.so"
g++ -o dir2/src/libdir2_a.so -shared -Wl,-rpath=$\{ORIGIN}/. dir2/src/dir2_a.os -Llib -ldir1_a
Install file: "dir1/include/dir1_b.h" as "include/dir1_b.h"
Install file: "dir1/include/dir1_c.h" as "include/dir1_c.h"
Install file: "dir2/include/dir2_a.h" as "include/dir2_a.h"
Install file: "dir1/src/libdir1_b.so" as "lib/libdir1_b.so"
Install file: "dir1/src/libdir1_c.so" as "lib/libdir1_c.so"
Install file: "dir2/src/libdir2_a.so" as "lib/libdir2_a.so"
+-.
+-SConstruct
+-dir1
| +-dir1/SConscript
| +-dir1/include
| | +-dir1/include/dir1_a.h
| | +-dir1/include/dir1_b.h
| | +-dir1/include/dir1_c.h
| +-dir1/src
| +-dir1/src/dir1_a.cpp
| +-dir1/src/dir1_a.os
| | +-dir1/src/dir1_a.cpp
| | +-dir1/include/dir1_a.h
| | +-/bin/g++
| +-dir1/src/dir1_b.cpp
| +-dir1/src/dir1_b.os
| | +-dir1/src/dir1_b.cpp
| | +-dir1/include/dir1_b.h
| | +-/bin/g++
| +-dir1/src/dir1_c.cpp
| +-dir1/src/dir1_c.os
| | +-dir1/src/dir1_c.cpp
| | +-dir1/include/dir1_c.h
| | +-/bin/g++
| +-dir1/src/libdir1_a.so
| | +-[dir1/src/dir1_a.os]
| +-dir1/src/libdir1_b.so
| | +-[dir1/src/dir1_b.os]
| +-dir1/src/libdir1_c.so
| +-[dir1/src/dir1_c.os]
+-dir2
| +-dir2/SConscript
| +-dir2/include
| | +-dir2/include/dir2_a.h
| +-dir2/src
| +-dir2/src/dir2_a.cpp
| +-dir2/src/dir2_a.os
| | +-dir2/src/dir2_a.cpp
| | +-include/dir1_a.h
| | | +-dir1/include/dir1_a.h
| | +-dir2/include/dir2_a.h
| | +-/bin/g++
| +-dir2/src/libdir2_a.so
| +-[dir2/src/dir2_a.os]
| +-lib/libdir1_a.so
| +-[dir1/src/libdir1_a.so]
+-include
| +-[include/dir1_a.h]
| +-include/dir1_b.h
| | +-dir1/include/dir1_b.h
| +-include/dir1_c.h
| | +-dir1/include/dir1_c.h
| +-include/dir2_a.h
| +-dir2/include/dir2_a.h
+-lib
+-[lib/libdir1_a.so]
+-lib/libdir1_b.so
| +-[dir1/src/libdir1_b.so]
+-lib/libdir1_c.so
| +-[dir1/src/libdir1_c.so]
+-lib/libdir2_a.so
+-[dir2/src/libdir2_a.so]
scons: done building targets.