Setting up your development environment
This tutorial will run through setting up DACE_jll.jl, DACE.jl and the DACE C++ library for development locally. It has been tested on Linux.
After running this tutorial, you should be able to make changes to the C++ code that defines the DACE Julia interface, compile those changes and test them via the DACE.jl Julia package locally.
This is based on the upstream binary builder documention for how to develop locally:
- https://docs.binarybuilder.org/stable/building/#Building-and-testing-JLL-packages-locally
- https://docs.binarybuilder.org/stable/jll/#Overriding-the-artifacts-in-JLL-packages
and also CxxWrap documentation:
Clone repos
Create and change to a new directory that we can clone the DACE code into. Then run the following:
- DACE.jl Julia package
git clone https://github.com/a-ev/DACE.jl.git - DACE C++ library (note specific branch required)
git clone --branch julia-interface https://github.com/a-ev/dace.git
Set an environment variable with the path to the current directory, so we can refer back to it later:
export srcdir=$PWDSetup DACE_jll.jl for development
Switch to the DACE.jl directory that you cloned above:
cd ${srcdir}/DACE.jlRun julia --project to enter the Julia REPL and enter ] to enter the Pkg REPL mode, then
(DACE) pkg> instantiate
(DACE) pkg> develop DACE_jllAfter running the above, press backspace to return to the Julia REPL and run
julia> using DACE_jll
julia> DACE_jll.dev_jll()At the end of the above command it will print a location of the override directory, e.g.
...
[ Info: DACE_jll dev'ed out to /home/<username>/.julia/dev/DACE_jll with pre-populated override directoryThe directory /home/<username>/.julia/dev/DACE_jll/override contains the dace shared libraries and headers in lib and includes directories. We can delete the contents of this directory and replace it with our own version that we build locally.
Don't just copy this command, make sure the path corresponds to the path in your output above.
rm -rf /home/<username>/.julia/dev/DACE_jll/override/*Now store the path in an environment variable so that we can use it later (make sure you replace the path below with your path):
export dacejllpath=${HOME}/.julia/dev/DACE_jll/overrideOn Mac OS X only: build our own version of libcxxwrap-julia
Skip this section and continue to the next step if you are not running on Mac OS X.
On Mac OS X it seems that currently you need to build your own version of libcxxwrap-julia in order for the remaining instructions to work correctly.
First set up an override directory where we can build our own version of libcxxwrap-julia. We should still be in the DACE.jl directory from above (cd ${srcdir}/DACE.jl). Run julia --project to enter the Julia REPL and enter ] to enter the Pkg REPL mode, then
pkg> develop libcxxwrap_julia_jllAt this point we should also make a note of the version of libcxxwrapjuliajll:
pkg> status libcxxwrap_julia_jllThe above command should output something like:
Project DACE v0.1.0
Status `/path/to/DACE.jl/Project.toml`
[3eaa8342] libcxxwrap_julia_jll v0.13.2+0 `~/.julia/dev/libcxxwrap_julia_jll`We can see that the version is v0.13.2 (ignore the "+" and anything after it).
Back in the Julia REPL, import the package and run dev_jll:
julia> import libcxxwrap_julia_jll
julia> libcxxwrap_julia_jll.dev_jll()At the end of the above command it should print the path to the devved JLL, e.g. /home/<username>/.julia/dev/libcxxwrap_julia_jll. Inside that directory will be an override directory, which is where we will build our local version of libcxxwrap_julia. Make a note of the directory that was printed.
Make sure you are still in the directory where we cloned the other git repos above, clone the libcxxwrap_julia repository and checkout the tag that matches the version you found above:
cd ${srcdir}
git clone https://github.com/JuliaInterop/libcxxwrap-julia.git
cd libcxxwrap-julia
git checkout v0.13.2Now we will change to the directory where libcxxwrapjuliajll was devved out to and build our own version:
cd /home/<username>/.julia/dev/libcxxwrap_julia_jll/override
rm -rf *
cmake -DJulia_EXECUTABLE=$(which julia) ${srcdir}/libcxxwrap-julia
cmake --build . --config ReleaseBuild the DACE C++ library
Switch to the DACE.jl directory from above:
cd ${srcdir}/DACE.jlNow find the CxxWrap prefix path by entering the Julia REPL (julia --project) and running
julia> import CxxWrap
julia> CxxWrap.prefix_path()This should return a path like:
"/home/<username>/.julia/artifacts/fb412eee87eae845b84a799f0cabf241142406d7"with a different ID at the end (although it may look like /Users/<username>/.julia/dev/libcxxwrap_julia_jll on Mac OS X). We will use this path in the CMake command later so let's store it in an environment variable (make sure you replace the path below with your path):
export prefixpath=${HOME}/.julia/artifacts/fb412eee87eae845b84a799f0cabf241142406d7Now switch to the dace directory we cloned earlier (it should be alongside the DACE.jl directory we are currently working in):
cd ${srcdir}/daceMake a build directory and switch to it:
mkdir build
cd buildNow run the cmake command to configure DACE:
cmake .. \
-DCMAKE_INSTALL_PREFIX=${dacejllpath} \
-DCMAKE_PREFIX_PATH=${prefixpath} \
-DCMAKE_BUILD_TYPE=Release \
-DWITH_PTHREAD=ON \
-DWITH_ALGEBRAICMATRIX=ON \
-DCMAKE_CXX_STANDARD=17 \
-DWITH_JULIA=ONand then build and install DACE with:
VERBOSE=ON cmake --build . --config Release --target install -- -j$(nproc)Verify the DACE module is working
Switch back to the DACE.jl directory.
cd ${srcdir}/DACE.jlEnter the Julia REPL with julia --project and run
julia> using DACE
julia> DACE.init(10, 1)
julia> ?DACE.DAwhich should show some help about the DACE.DA type.
Make a change to the local DACE library
Now we will make a change to the local C++ source code and verify that the change is loaded in the Julia library.
Switch back to the dace/build directory
cd ${srcdir}/dace/buildEdit the interface file ../interfaces/julia/dace_julia.cxx using an editor such as vim or nano.
Locate the DACE.init function, it should be near the top and look like
mod.method("init", [](const unsigned int ord, const unsigned int nvar) {
DA::init(ord, nvar);
});For reference,
mod.methodadds a function to the Julia module"init"is the name of the function that is being added[](const unsigned int ord, const unsigned int nvar)denotes a C++ lambda function that runs when the function is called from Julia and takes two unsigned integer arguments- the lambda function body passes those two arguments to the
DA::initroutine, which is defined in the DACE C++ library
We will modify this method to add a print statement, such as
mod.method("init", [](const unsigned int ord, const unsigned int nvar) {
std::cout << "initialising local version of DACE library..." << std::endl;
DA::init(ord, nvar);
});so that we can tell the local version has been loaded. Make the above change then save the file.
We should be in the build directory still. Execute the following command to build and install your change:
VERBOSE=ON cmake --build . --config Release --target install -- -j$(nproc)Now change back to the DACE.jl directory
cd ${srcdir}/DACE.jlOnce again, enter the Julia REPL with julia --project and run the DACE.init function we ran above:
julia> using DACE
julia> DACE.init(10, 1)This time it should print out the string we just added (initialising local version of DACE library...).