Include OCaml library with dune - ocaml

I'm trying to make an OCaml program that uses the Str library
I'm using dune for compiling
My Makefile is
dune build src/myProgram.exe
My dune textfile in the src folder is
(env (_ (flags :standard -w -27-26-32-33)))
(executable (name myProgram) (modules myProgram) (libraries myLib) (modes byte exe))
(library (name myLib) (modules M1 M2 M3 M4 M5 M6 M7))
My bash error message is :
File "_none_", line 1:
Error: No implementations provided for the following modules:
Str referenced from src/.myProgram.eobjs/native/dune__exe__myProgram.cmx
I don't know how to include this Str library

To put it into an answer, tool want to list str as a library.
(executable
(name myProgram)
(modules myProgram)
(libraries str myLib)
(modes byte exe))

Related

Crosscompilation cannot find some libraries

I am trying to cross compile a ROS package for a Jetson nano (aarch64) using my x86_64 PC. I am using the toolchain provided by nvidia (GCC Tool Chain for 64-bit BSP). I have been following this article for guidance
As the compiler needs binaries from the aarch64 system, I have mounted the nano's /usr/include into my build directory's usr/include. Here's my build directory hierarchy.
.
├── gcc-4.8.5-aarch64 #<cross compiler>
│ └── install
│ ├── aarch64-unknown-linux-gnu
│ ...
├── opt #<ROS source files from nano>
│ └── ros
│ └── melodic
├── src #<test c++ code in here>
│ └── test_cpp
│ └── src
└── usr
├── include #<nano's /usr/include mounted in here>
└── lib
└── aarch64-linux-gnu #<nano's /usr/lib/aarch64-linux-gnu mounted in here>
When compiling, I get errors saying the compiler cannot find crt1.o, crti.o and libpthread.so.0 libraries.
/home/teshan/xcompile/gcc-4.8.5-aarch64/install/bin/../lib/gcc/aarch64-unknown-linux-gnu/4.8.5/../../../../aarch64-unknown-linux-gnu/bin/ld: cannot find crt1.o: No such file or directory
/home/teshan/xcompile/gcc-4.8.5-aarch64/install/bin/../lib/gcc/aarch64-unknown-linux-gnu/4.8.5/../../../../aarch64-unknown-linux-gnu/bin/ld: cannot find crti.o: No such file or directory
/home/teshan/xcompile/gcc-4.8.5-aarch64/install/bin/../lib/gcc/aarch64-unknown-linux-gnu/4.8.5/../../../../aarch64-unknown-linux-gnu/bin/ld: cannot find /lib/aarch64-linux-gnu/libpthread.so.0 inside /home/teshan/xcompile
collect2: error: ld returned 1 exit status
Before mounting /usr/lib/aarch64-linux-gnu and /usr/include, I've had errors saying cannot find Boost libraries. They have disappeared now since the library files are available in the mounted directories.
However, I have the asked files crti.o and crt1.o in the mounted directories just like boost library files. So why can’t the compiler find them?
$ find -name crti.o -type f
./gcc-4.8.5-aarch64/install/aarch64-unknown-linux-gnu/sysroot/usr/lib/crti.o
./usr/lib/aarch64-linux-gnu/crti.o
$ find -name crt1.o -type f
./gcc-4.8.5-aarch64/install/aarch64-unknown-linux-gnu/sysroot/usr/lib/crt1.o
./usr/lib/aarch64-linux-gnu/crt1.o
I do not have libpthread.so.0 as asked but have libpthread.so. What can I do about this?
$ find -name libpthread.so* -type f
./gcc-4.8.5-aarch64/install/aarch64-unknown-linux-gnu/sysroot/usr/lib/libpthread.so
./usr/lib/aarch64-linux-gnu/libpthread.so
TL;DR
This is my build script
#!/bin/bash
PWD=$(pwd)
export LANG=C
source /opt/ros/melodic/setup.bash
catkin config --extend ${PWD}/opt/ros/melodic/
catkin build -j8 --cmake-args \
-DCMAKE_TOOLCHAIN_FILE=${PWD}/toolchain.cmake \
-DCMAKE_CROSS_COMPILE_PREFIX=${PWD} \
-DRT_LIBRARY=${PWD}/usr/lib/aarch64-linux-gnu/
Here's my toolchain.cmake
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_C_COMPILER ${NANO_ROOT_PATH}/gcc-4.8.5-aarch64/install/bin/aarch64-unknown-linux-gnu-gcc)
SET(CMAKE_CXX_COMPILER ${NANO_ROOT_PATH}/gcc-4.8.5-aarch64/install/bin/aarch64-unknown-linux-gnu-g++)
# Below call is necessary to avoid non-RT problem.
SET(CMAKE_LIBRARY_ARCHITECTURE aarch64-linux-gnu)
SET(NANO_ROOT_PATH ${CMAKE_CURRENT_LIST_DIR})
SET(NANO_MELODIC_PATH ${NANO_ROOT_PATH}/opt/ros/melodic)
SET(CMAKE_FIND_ROOT_PATH ${NANO_ROOT_PATH} ${CATKIN_DEVEL_PREFIX})
SET(COMPILER_ROOT ${NANO_ROOT_PATH}/gcc-4.8.5-aarch64/install)
#Have to set this one to BOTH, to allow CMake to find rospack
#This set of variables controls whether the CMAKE_FIND_ROOT_PATH and CMAKE_SYSROOT are used for find_xxx() operations.
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
SET(CMAKE_PREFIX_PATH ${NANO_MELODIC_PATH} ${NANO_ROOT_PATH}/usr)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --sysroot=${NANO_ROOT_PATH}" CACHE INTERNAL "" FORCE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --sysroot=${NANO_ROOT_PATH}" CACHE INTERNAL "" FORCE)
SET(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} --sysroot=${NANO_ROOT_PATH}" CACHE INTERNAL "" FORCE)
SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} --sysroot=${NANO_ROOT_PATH}" CACHE INTERNAL "" FORCE)
SET(LD_LIBRARY_PATH ${NANO_MELODIC_PATH}/lib)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
#Skip toolchain trying to build a test program first
SET(CMAKE_C_COMPILER_WORKS 1)
SET(CMAKE_CXX_COMPILER_WORKS 1)
set(BOOST_ROOT ${NANO_ROOT_PATH}/usr/include/boost)
set(COMPILER_SYSROOT ${COMPILER_ROOT}/aarch64-unknown-linux-gnu/sysroot)
include_directories(BEFORE SYSTEM ${COMPILER_SYSROOT}/usr/include/)

add_custom_target not executing with multiple executable in a CMakeLists file

I got a situation where another Makefile is executed from a CMakeLists.txt file.
Here is my root directory structure.
.
├── client.cpp
├── CMakeLists.txt
├── proto_lib
│   ├── Makefile
│   └── math.proto
└── server.cpp
This is a simple grpc test code where I am trying to compile a proto files using a Makefile create a static library. And then link that library to the final targets in the CMakefile. Makefile is working fine. CMakefile is also working fine with one executable.
Here is the CMakefile:
cmake_minimum_required(VERSION 3.5)
project(client-server)
message(STATUS "Compiling Network Function : ${PROJECT_NAME}")
set(CMAKE_CXX_STANDARD 11)
message(STATUS "Project Directory: ${PROJECT_SOURCE_DIR}")
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/build)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
set(LIB_FILE ${CMAKE_CURRENT_SOURCE_DIR}/proto_lib/libmylib.a)
add_custom_target(libmylib.a ALL
COMMAND make
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/proto_lib
COMMENT "grpc headers and libraries are generating..."
)
add_executable(server server.cpp)
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -g")
set(BASIC_LIBRARIES "-lpthread")
set(CMAKE_LINK_WHAT_YOU_USE ON)
set(LIBDIR "/usr/local/lib")
find_library(proto_location NAMES protobuf PATHS ${LIBDIR})
find_library(grpc_location NAMES grpc++ PATHS ${LIBDIR})
find_library(grpc_reflection_location NAMES grpc++_reflection PATHS ${LIBDIR})
find_library(dl_location NAMES dl PATHS ${LIBDIR})
find_library(grpc_location2 NAMES grpc PATHS ${LIBDIR})
if(proto_location)
message(STATUS "protobuf library found at " ${proto_location})
endif()
if(grpc_location)
message(STATUS "grpc++ found at " ${grpc_location})
endif()
if(grpc_reflection_location)
message(STATUS "grpc_reflection found at " ${grpc_reflection_location})
endif()
if(dl_location)
message(STATUS "dl found at " ${dl_location})
endif()
if(grpc_location2)
message(STATUS "grpc found at " ${grpc_location2})
endif()
target_link_libraries(server ${proto_location}
${LIB_FILE}
${grpc_location}
${grpc_reflection_location}
${dl_location}
${grpc_location2}
${BASIC_LIBRARIES}
)
When I enter the command make after CMake . in the root directory.
it starts with following output...
Scanning dependencies of target libmylib.a
[ 33%] grpc headers and libraries are generating...
[ 33%] Built target libmylib.a
etc.. etc..
and it succeeds.(The internal Makefile creates header files and static objects using proto and grpc libraries. After that server.cpp can include the headers from inside the proto_lib/ folder and CMake build succeeds)
But when I add one more executable at the end of CMakeLists.txt,
add_executable(client client.cpp)
target_link_libraries(client ${proto_location}
${LIB_FILE}
${grpc_location}
${grpc_reflection_location}
${dl_location}
${grpc_location2}
${BASIC_LIBRARIES}
)
and then cmake . && make
does not start with internal Makefile build. Instead, it starts with client build.
Scanning dependencies of target client
[ 20%] Building CXX object CMakeFiles/client.dir/client.cpp.o
/home/deka/Academic/gemini/learning/client_server_async/advanced1/client.cpp:10:10: fatal error: proto_lib/math.grpc.pb.h: No such file or directory
#include "proto_lib/math.grpc.pb.h"
Because proto_lib/Makefile is not executed first in this case therefore math.grpc.pb.h is not generated and that is what the above error is showing.
My question is: Why adding one more executable does not trigger the internal Makefile build at the start?
Thanks!

Running OUnit tests using dune

I'm having difficulties running OUnit tests, mostly because I'm new to both dune and OUnit. dune complains when I run dune runtest:
File "test/dune", line 4, characters 13-14:
Error: Library "f" not found.
Hint: try: dune external-lib-deps --missing #runtest
Here's the project structure:
├── dune
├── f.ml # This is the source file.
└── test
├── dune
└── f_test.ml # This is the test.
This is dune:
(executable
(name f))
This is test/dune:
(test
(name f_test)
(libraries oUnit f)) ; <- `f` here causes problems.
I can see that the error appears because dune does not know about f.ml, and hence does not know about f in the dune file.
How can I make dune compile f.ml in such a way that test/dune knows about the f library that I use in test/f_test.ml? How can I run the unit tests properly?
One possibility is to split f into a private library and an executable, and then test the split library.
EDIT:
For instance, the project structure could be updated to
├── dune
├── f.ml # f only contains the I/O glue code.
├── lib
| ├── dune
| └── a.ml # a implements the features that need to be tested.
└── test
├── dune
└── test.ml # This is the test.
with dune
(executable (name main) (libraries Lib))
For the test, test/dune:
(test (name test) (libraries Lib oUnit))
and finally lib/dune
(library (name Lib))
With this setup, the test can be run with dune runtest.

CPack: Interface include directories are missing in archive

I am using CMake 3.10.1 and trying to use CPack to generate archives for a library and I cannot get it to add the interface include directory to the archive.
The library and the generated export files are added as expected, however the include directory (added using target_include_directories(... PUBLIC ...) is missing entirely.
The CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(Test VERSION 1.0.0 LANGUAGES CXX)
add_library(${PROJECT_NAME} SHARED foo.cpp) #add sources and executable
target_include_directories(${PROJECT_NAME} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc>
$<INSTALL_INTERFACE:inc>
)
install(TARGETS ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}
INCLUDES DESTINATION inc
PUBLIC_HEADER DESTINATION inc
LIBRARY DESTINATION lib
)
install(EXPORT ${PROJECT_NAME} DESTINATION .)
include(CPack)
The contents of my source dir:
├── CMakeLists.txt
├── foo.cpp
└── inc
└── foo.h
The contents of the tgz generated by cpack -G TGZ .
├── lib
│   └── libTest.so
├── Test.cmake
└── Test-noconfig.cmake
Any ideas why it could be missing the inc directory?
Generator-like expression $<INSTALL_INTERFACE> used in the target_include_directories() command by itself doesn't install corresponded directory. You need to install this directory manually (with install(FILES) or install(DIRECTORY)).
Expression $<INSTALL_INTERFACE> specifies interface include directory for the target in the config file, which exports install tree (see install(EXPORT) command).
Expression $<BUILD_INTERFACE> specified interface include directory for the target in the project itself, and in the config file which exports build tree (see EXPORT() command).
But these expressions doesn't enforce $<BUILD_INTERFACE> directory to be copied into $<INSTALL_INTERFACE> one on installation. As opposite, content of this directories usually differs: aside from header files for outer use, installed into $<INSTALL_INTERFACE> directory, a directory $<BUILD_INTERFACE> may contain header files for project's internal use, which are not installed.

How to specify a dependency graph when generating files with CMake?

I'm integrating protobuf files compilation in my project's CMake-based build process. Currently I'm using the following CMake script:
set (TARGET_NAME ProtobufMessages)
file (GLOB_RECURSE PROTOBUF_FILES "protobuf/*.proto")
set (HEADER_FILES "")
set (SOURCE_FILES "")
foreach (FILE ${PROTOBUF_FILES})
string (REPLACE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} FILE ${FILE})
string (REPLACE ".proto" ".pb.h" HEADER_FILE ${FILE})
string (REPLACE ".proto" ".pb.cc" SOURCE_FILE ${FILE})
list (APPEND HEADER_FILES ${HEADER_FILE})
list (APPEND SOURCE_FILES ${SOURCE_FILE})
endforeach ()
add_library(${TARGET_NAME} STATIC
${HEADER_FILES}
${SOURCE_FILES}
${PROTOBUF_FILES}
)
set_target_properties (${TARGET_NAME} PROPERTIES
FOLDER ${COMMON_PROJECTS_FOLDER_NAME})
set (PROTOBUF_COMPILE_COMMAND
${CONAN_BIN_DIRS_PROTOBUF_RELEASE}/protoc
--cpp_out=${CMAKE_CURRENT_BINARY_DIR}/protobuf
-I${CMAKE_CURRENT_SOURCE_DIR}/protobuf
${PROTOBUF_FILES}
)
add_custom_command(OUTPUT ${HEADER_FILES} ${SOURCE_FILES}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/protobuf
COMMAND ${PROTOBUF_COMPILE_COMMAND}
DEPENDS ${PROTOBUF_FILES}
COMMENT "Compiling protocol buffer files ..."
)
source_group (TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES
${PROTOBUF_FILES}
)
set_target_properties (${TARGET_NAME} PROPERTIES
FOLDER ${COMMON_PROJECTS_FOLDER_NAME}
)
target_link_libraries (${TARGET_NAME}
CONAN_PKG::protobuf
)
It works fine, but the problem with this approach is that when a single proto file is changed all the files are regenerated.
A simple modification of this approach with calling add_custom_command in a loop partially solves the problem:
set (PROTOBUF_COMPILE_COMMAND
${CONAN_BIN_DIRS_PROTOBUF_RELEASE}/protoc
--cpp_out=${CMAKE_CURRENT_BINARY_DIR}/protobuf
-I${CMAKE_CURRENT_SOURCE_DIR}/protobuf
)
foreach (PROTOBUF_FILE ${PROTOBUF_FILES})
string (REPLACE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} TEMP_FILE ${PROTOBUF_FILE})
string (REPLACE ".proto" ".pb.h" HEADER_FILE ${TEMP_FILE})
string (REPLACE ".proto" ".pb.cc" SOURCE_FILE ${TEMP_FILE})
add_custom_command(OUTPUT ${HEADER_FILE} ${SOURCE_FILE}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/protobuf
COMMAND ${PROTOBUF_COMPILE_COMMAND} ${PROTOBUF_FILE}
DEPENDS ${PROTOBUF_FILE}
COMMENT "Compiling ${PROTOBUF_FILE} ..."
)
endforeach ()
But there is still a problem, because protobuf supports including one protobuf file into another:
import "myproject/base.proto";
In this case when base.proto is changed the files including it also must be recompiled. Actually the dependencies can form an arbitrary DAG. Although the current problem is arising specifically with protobuf files compilation this is relevant to all code generation steps when some of the input files can depend on some of the other ones.
Is it possible to solve this problem with CMake?