In .NET I can decorate my assembly with the following attribute:
[<assembly: InternalsVisibleTo("MyProject.Test")>]
Thanks to this, all the modules marked as "internal" are accessible from "MyProject.Test". I can use it e.g. for unit testing the functionality I don't want to expose in my library.
I'm wondering if there's something similar in the Haskell's world. Let's say I have a library with the following .cabal file:
library
exposed-modules: MyLibrary.API
other-modules: MyLibrary.Utils
-- ...
test-suite mylib-test
-- ...
build-depends: base,
hspec,
my-library
Is there a way to refer to "MyLibrary.Utils" from mylib-test test-suite?
You can make it part of an internal library, and depend on that from both the public library and the test suite. It will not be available outside the package.
library utils
exposed-modules: MyLibrary.Utils
library
exposed-modules: MyLibrary.API
build-depends: utils
test-suite mylib-test
build-depends: base, hspec, my-library, utils
Alternately, there's a strong convention of exposing the module anyway, but including Internal in its name and telling folks in the documentation that you break it you bought it.
Related
I am writing a library Lib that has a PUBLIC link dependency on Dep. Unfortunately, Dep does not provide its own DepConfig.cmake, so I wrote a FindDep.cmake file to find Dep.
Currently, I just have find_dependency(Dep) in LibConfig.cmake and rely on consumers of Lib to provide their own FindDep.cmake. Ideally though, consumers of Lib should be able to find_package(Lib) without worrying about Dep at all.
I am tempted to install my FindDep.cmake to lib/cmake/Lib, but I am concerned about the search order of find_package. (If the consumer provides their own FindDep.cmake or DepConfig.cmake, what file is used?).
Is there a best practice for this case?
Is it possible to dune utop mylib load a library in "promiscuous mode" which would ignore the .mli interface files and expose the internals, like values or types not listed as part of the public interface?
In effect, loading utop "from within" the implementation, and not "from outside", issuing standard open commands with abstraction enforced by the public interface.
This is not possible. You can open a ticket on the github repository of dune to ask for such a feature.
It's me, again.. I am working on an OCaml project and I would like to use Oasis to build the whole code base. Here is how my codebase is organized.
src/
core/
init.ml
type.ml
utils.ml
plugin/
main.ml
I firstly only build the library with the following _oasis file:
Library "engine"
Path: src/core
Modules:
Init,
Type,
Utils
BuildDepends: deriving, deriving.syntax, core, batteries
XMETADescription: core engine
And it works fine. There is no error and I can find a library engine.a in the _build/src/core folder.
However, when I try to include the library in the main.ml with the following way:
Module T = Engine.Type
...
And compile with the following _oasis file:
Library "engine"
Path: src/core
Modules:
Init,
Type,
Utils
BuildDepends: deriving, deriving.syntax, core, batteries
XMETADescription: core engine
Executable "main"
Path: src/plugin
MainIs: main.ml
CompiledObject: best
Install: false
BuildDepends: core, batteries, engine
I got an error:
Unbound module Engine
Am I doing anything wrong here? Could anyone give me some help? Thank you!
Your _oasis module defines a library with the name engine but it does not define an Engine module. So your Init, Type and Utils modules are exposed and should be accessible directly without any prefix.
If you want to pack those modules into a parent you can:
Manually pack each module into one big engine.ml file
Use Pack: true in the Library section of your _oasis file which would pack the included modules into a module called Engine
Use module aliases (see the OCaml manual for more information)
I am trying to use oasis to compile my project, and my project is organized in this way:
_oasis
src/
main.ml
core_a.ml
core_b.ml
type.ml
plugins/
plugin_a.ml
plugin_b.ml
Note that in the plugin_a.ml, it refers to module type.ml (i.e., open Type).
When I use oasis to compile the project, it reports:
Unbound module Type
Here is the simplified version of my _oasis file:
....
BuildTools: ocamlbuild
BuildDepends: deriving, deriving.syntax, core, batteries
Executable "main"
Path: src
MainIs: main.ml
CompiledObject: best
Install: false
BuildDepends: deriving, deriving.syntax, core, batteries
Am I doing anything wrong here? Or what I am doing is not the best practice to organize a project like this?
I think your project structure is a bit strange. You have a sub directory for plugins, but you should note that there's no namespace or package hierarchy so this is not really useful in practice.
As for whether this is possible, the answer seems to be mixed:
It's not possible to do it with just oasis because it doesn't let you specify multiple values for the Path option.
It should be easily done with ocamlbuild however by tagging everything you need with include (but I don't recommend this).
As your oasis project grows, you should look into defining library sections in oasis and using those to organize inter project dependencies. E.g., in this case you could create a "plugins" library where you include plugin_a and plugin_b. But without some planning ahead here, you will quickly run into circular dependencies.
In our workflow, we can have a module A that is composed of several header files, module A not producing any binary (side note: it will obviously be used by other modules, that include some of the headers from module A to produce binaries).
A good example would be a header-only library, for which CMake 3 introduces a good support thanks to the notion of INTERFACE library (see this SO answer, and CMake's documentation of the feature).
We can make an interface library target out of module A:
add_library(module_A INTERFACE)
That gives us all the nice features of CMakes targets (it is possible to use it as another target's dependency, to export it, to transitively forward requirements etc.)
But in this case, the headers in module A do not show up in our IDE (Xcode, yet we expect it to be the same with most/every other IDE).
This proves to be a major drawback in the workflow, since we need the files composing module A to be shown in the IDE for edition. Is it possible to achieve that ?
Several months down the line, I did not find a way to directly list the header files for an INTERFACE library.
Since the question still has some views, here is what I ended up doing (i.e. what appears like the lesser hack currently available).
Imagine module A is a header only library. In the CMakeLists.txt declaring its target:
# Define 'modA_headers' variable to list all the header files
set(modA_headers
utility.h
moreUtilities.h
...)
add_library(moduleA INTERFACE) # 'moduleA' is an INTERFACE pseudo target
#
# From here, the target 'moduleA' can be customised
#
target_include_directories(moduleA ...) # Transitively forwarded
install(TARGETS moduleA ...)
#
# HACK: have the files showing in the IDE, under the name 'moduleA_ide'
#
add_custom_target(moduleA_ide SOURCES ${modA_headers})
I do not accept this answer, since I expect further releases of CMake to offer a more semantically correct approach, which will then be accepted : )
You can use the new target_sources command in CMake 3.1.
add_library(moduleA INTERFACE)
target_include_directories(moduleA INTERFACE ...)
target_sources(moduleA INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/utility.h
${CMAKE_CURRENT_SOURCE_DIR}/moreUtilities.h
)
It is also transitive.
http://www.cmake.org/cmake/help/v3.1/command/target_sources.html#command:target_sources
The limitation of not being able to export targets which have INTERFACE_SOURCES has been lifted for CMake 3.3.