I made an OCaml library that relies on an external/system package (namely libnauty2-dev).
Since I would like my library to be installed via opam I looked for a way to specify the external lib as a dependency.
So far I have found that .opam files can specify such dependencies with
depexts: [ "libnauty2" ]
And here is my question:
Is there a way to specify my dependency in a dune-project file so that generated .opam file will contain the same dependency ?
The dune language doesn't directly support this part of opam file generation, but you can create a <packagename>.opam.template file with your depexts rules and dune will paste the contents of that file at the end of the generated .opam file.
Related
I have written a library in OCaml with all of its sources located in lib folder.
I also prepared "facade" executables in bin folder.
Now I would like to prepare some examples how to use the above mentioned executables.
To do this I need to either copy an executable beforehand or (preferably) tell Dune to use a newly created one after build.
And here is my question.
Dune's copy_files stanza does not allow1 me to copy from _build folder.
Is there any other way to use fresh executables each time after building or do I need to copy them at some point and keep up to date?
Below is the structure of the project (in case verbal description was misleading in any way).
root
lib <- source
bin <- frontend for source
examples <- how to use the above frontend
1 By not allow I mean the following usage of this stanza:
( copy_files %{project_root}/_build/default/bin/program.exe )
A solution, as suggested by #Lhooq, might be to use dune exec command with --root parameter.
In regard to the provided scenario, if we make a script:
dune exec --root=../.. ./bin/some_program.exe
(*
Where 'some_program' is the name of an .ml file located in bin folder.
I assumed here that the program is compiled to native code, not to bytecode (hence the .exe).
*)
and place it in examples directory, then by invoking it we will actually run the latest build of the program defined in some_program.ml located in bin folder.
And just to make things clear: bin folder does NOT contain any compiled files (neither .exe nor .bc) .
I have a project under CMake with some files generated with python generator from XML files. I cannot specify all files generated by this generator in CMakeLists.txt so I use file globbing for this.
The problem is that when I update my XML files or generator sources (which are in the same repository) I would like to have my build system reconfigured so changed files are taken into account when rebuilding the code (via make for example).
Is it possible to make CMake treat some files like it treats CMakeLists.txt files and to make it regenerate build system when those file are changed?
It doesn't require any kind of workarounds. The standard way is to use CMAKE_CONFIGURE_DEPENDS property:
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS <filename>)
Yes, you should be able to do that by (ab)using configure_file(). Configuring a file makes the source a dependency of the CMake run, so that any changes in it cause a reconfiguration. Simply like this:
configure_file(MyInputFile.xml DummyOutput.xml)
Since it has been a while I will add to #roolebo's answer.
There's actually a better command to add a dependency on a file:
set_directory_properties(PROPERTIES CMAKE_CONFIGURE_DEPENDS <relative_or_full_path_to_file>)
What might be confusing is that this command adds a property to the current directory. Well, it does not matter since you can set a full path to a file that resides outside of the current directory's scope, for instance: ../../config.json
I have a CMake project named proj1, which I want to use as an external project in another project, proj2. Now, the (relevant) command in proj1's CMakeLists.txt is:
install(
TARGETS proj1
ARCHIVE
DESTINATION lib
EXPORT proj1_library
INCLUDES DESTINATION include
CONFIGURATIONS Release RelWithDebugInfo
)
and I want to use this static library in proj2, without explicitly "guessing" where it's installed to be proj1. I want to be able to get obtain this target from proj1 (which I obtain using ExternalProject), then use it - directly or indirectly - in add_target_libraries() commands.
How should I do that? And - do I only need to make changes to proj2 or also to proj1's CMakeLists.txt?
Exporting the targets is the right approach.
To support this, proj1 would have to generate a proj1Config.cmake in both its build tree and also in the install tree (so that a development package for proj1 can be used as a SDK [1])
I suggest you read the following section of the CMake documentation, it covers the different concepts and provides an example. See https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#creating-packages
[1] SDK: https://en.wikipedia.org/wiki/Software_development_kit
I cannot make local include paths work in the Meson build system.
This C++ inclusion works correctly:
#include </cygdrive/c/Users/user/project/Third-Party/eigen/Eigen/Dense>
This one does not:
#include "Third-Party/eigen/Eigen/Dense"
fatal error: Eigen/Dense: No such file or directory
In the Meson build file, I tried to add Eigen's path, without success:
# '.' will refer to current build directory
include_dirs = include_directories('include', '.', '../project/Third-Party/eigen')
This is the project tree structure:
project
meson.build
src
meson.build
example.h
example.cpp
Third-Party
eigen (headers only lib)
Eigen
Note: with CMake I do not have this issue.
For dependency management, meson allows you to manually declare include_directories() in your build files. However, there is another way do handle dependencies: using dependency() command.
dependency() is a much better way to handle dependencies, because meson will build it if necessary (if dependency is a shared or a static library) and safely allows you to use includes. That means that you don't have to know where includes for dependency are located physically or care about their paths ever after. The only downside is that this kind of dependency needs it's own meson.build file.
Using dependency() command:
To actually use it, you have to write a wrap file for dependency. Or, if you are lucky enough, there is already a wrap file for you in the Wrap DB -- a community-driven database for meson wrap files. Wrap file is a config of some kind that declare where you can get a dependency and in what form. Wrap file can wrap around zip archives and git repositories.
For your given dependency, there is wrap file in Wrap DB: eigen. All you have to do is download it and place it in the subprojects directory near your meson.build. For example:
$ cd project
$ mkdir subprojects
$ wget "https://wrapdb.mesonbuild.com/v1/projects/eigen/3.3.4/1/get_wrap" \
-O subprojects/eigen.wrap
Now, not every project builds with meson. For the ones that don't, wrap file also specify a patch. Patch is used to just copy appropriate meson.build file into dependency directory (as well as any other files that would be needed for building that particular dependency with meson). Eigen wrap file contains a patch.
To find out how any particular dependency declare itself as a dependency (using declare_dependency() command), you need to investigate meson.build file in dependency source directory (although it's often just name of the dependency plus _dep, e.g. "eigen_dep"). For me, eigen directory was subprojects/eigen-eigen-5a0156e40feb. So, you search for the declare_dependency() command:
$ grep declare_dependency subprojects/eigen-eigen-5a0156e40feb/meson.build
eigen_dep = declare_dependency(
As you can see, eigen declare dependency as eigen_dep. If you want to know what exactly is declared, just scroll down the dependency meson.build file.
Now, to use that eigen_dep in your project, create a dependency object with a dependency() command. Here is a sample project that I used to compile "A simple first program" from Eigen: Getting Started:
project('example', 'cpp')
eigen_dependency = dependency('eigen', fallback: ['eigen', 'eigen_dep'])
executable('example', 'example.cpp', dependencies: eigen_dependency)
Notice arguments for the dependency() command. The first one is system-wide dependency that meson is searching for. If there is no eigen for development installed in your system, then meson uses fallback: first item in fallback is basename of the wrap file, second item is a name of declared dependency.
Then use eigen_dependency variable in whatever you build, passing it to the dependencies argument.
Using include_directories() command:
If you want to just include some files from external directory (such as your "Third-Party" directory) using include_directories() command, that directory has to be relative to the meson.build file where you use it.
To use manually declared includes, you need to call include_directories() command to get the include_directories object. Pass that object to include_directories argument in whatever you build.
Given your example, I assume that root meson.build file is a project build file. Then in that root meson.build, for example, you can write:
# File: project/meson.build
project('example', 'cpp')
eigen_includes = include_directories('Third-Parties/eigen')
executable('example', 'example.cpp', include_directories: eigen_includes)
But if you want to get eigen includes from src/meson.build, then you need to change include_directories to:
# File: project/src/meson.build
eigen_includes = include_directories('../Third-Parties/eigen')
...
Description
I have a code generator that takes an XML input file and outputs a c++ header and source file. These auto-generated files are then compiled with static source files to produce a library. Simplified cmake file.
add_library(subdirectory/${MODULE_NAME} ${STATIC_SOURCES})
# Invoke auto-coder
add_custom_command(
OUTPUT ${GEN_HEADER} ${GEN_SOURCE}
COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}/my_autocoder ${SOURCE_XML}
DEPENDS ${SOURCE_XML}
)
# Add auto-generated source dependencies
target_sources(${MODULE_NAME}
PUBLIC ${GEN_HEADER}
PRIVATE ${GEN_SOURCE}
)
Problem
A generated header file ${GEN_HEADER_A} includes other generated headers files e.g. ${GEN_HEADER_B}. When running make at the top level everything builds correctly. However when building the library in isolation, it errors because ${GEN_HEADER_B} does not exist.
Question
How do I add all dependencies like ${GEN_HEADER_A} on ${GEN_HEADER_B} without manually specifying each dependency?
Attempts
The IMPLICIT_DEPENDS feature of add_custom_command seems to have the functionality I want. However, my attempts at using it have not resulted in the code generator being invoked for ${GEN_HEADER_B}. My assumption is this is because I already have a rule to build ${MODULE_NAME} when I added the library add_library(subdirectory/${MODULE_NAME} ${STATIC_SOURCES})
add_custom_command(
OUTPUT ${MODULE_NAME}
COMMAND ...
IMPLICIT_DEPENDS ${GEN_HEADER}
)
I do see ${GEN_HEADER_B} in the CXX.includecache under ${GEN_HEADER_A}
If you want file A to be (re)created when file B is built, you should specify this dependency explicitely.
Dependencies discovered by scanning (either automatic in add_library/add_executable commands, or via IMPLICIT_DEPENDS option of add_custom_command) are only checked for modification. CMake doesn't attempt to (re)create dependencies discovered by scanning.