diff --git a/.gitignore b/.gitignore index 564e19a..5ee1c2d 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ test/demo_fit_with_jl_func_2.png test/test1.root test/test2.root test/test3.root +LocalPreferences.toml diff --git a/Project.toml b/Project.toml index 1cb4663..851202b 100644 --- a/Project.toml +++ b/Project.toml @@ -1,24 +1,30 @@ name = "ROOT" uuid = "1706fdcc-8426-44f1-a283-5be479e9517c" authors = ["Philippe Gras CEA/IRFU"] -version = "0.3.2" +version = "0.4.0-DEV" [deps] -Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" +Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" CxxWrap = "1f15a43c-97ca-5a2a-ae31-89f07a497df4" Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +PkgDependency = "9eb5382b-762c-48ca-8139-e736883fe800" +ROOT_jll = "45b42145-bbac-5752-8807-01f8b2702242" +ROOTprefs = "492d890c-d9c4-11ef-b95f-3722e36032c2" +SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce" Scratch = "6c6a2e73-6563-6170-7368-637461726353" TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" +libroot_julia_jll = "2e5227ad-a2cb-5771-a73d-8331af68b27e" [compat] CxxWrap = "0.16" +Scratch = "1.2" julia = "1.6" [extras] +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -UnROOT = "3cd96dde-e98d-4713-81e9-a4a1b0235ce9" [targets] -test = ["Test", "UnROOT"] +test = ["Test", "Pkg"] diff --git a/deps/Makefile b/deps/Makefile index 4dd7680..df86959 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -23,6 +23,14 @@ JULIA = julia CXX_IS_CLANG = $(shell $(CXX) -dM -E - < /dev/null | grep -c __clang__) +VERBOSE = no #use -DVERBOSE to enable verbosity +# Verbose output +ifeq ($(VERBOSE), no) + Q = +else + Q = @ +endif + ifeq ($(UNAME),Darwin) SO_SUFFIX = .dylib else @@ -63,10 +71,11 @@ distclean: # @echo 'all:\n\n%:\n\t$$(MAKE) -C .. $$@\nclean:\n\t$$(MAKE) -C .. clean build\n' > $(BUILD_DIR)/Makefile $(BUILD_DIR)/ROOT-generated.wit: ROOT.wit #$(BUILD_DIR) - $(MAKE) check_root - [ -d $(BUILD_DIR)/libROOT/build ] || mkdir -p $(BUILD_DIR)/libROOT/build - $(shell echo "#\n# Warning: file generated automatically from $<\n#" > $@) - $(shell sed "s@%ROOT_INC_DIR%@$(ROOT_INC_DIR)@" $< >> $@ || rm $@) + @echo "Build $(notdir $@)" + $(Q) $(MAKE) -DVERBOSE=$(VERBOSE) check_root + $(Q) [ -d $(BUILD_DIR)/libROOT/build ] || mkdir -p $(BUILD_DIR)/libROOT/build + $(Q) $(shell echo "#\n# Warning: file generated automatically from $<\n#" > $@) + $(Q) $(shell sed "s@%ROOT_INC_DIR%@$(ROOT_INC_DIR)@" $< >> $@ || rm $@) check_root: ifeq ($(ROOT_LIBS),) @@ -97,12 +106,14 @@ JULIA_LOAD_PATH=`pwd`/build/ROOT/src:$(JULIA_LOAD_PATH): "$(JULIA)" --project=.. && JULIA_LOAD_PATH=`pwd`/build/ROOT/src:$(JULIA_LOAD_PATH): "$(JULIA)" --project=.. TTree_examples/read_tree3.jl $(BUILD_DIR)/%.o: src/%.cxx #$(BUILD_DIR) - [ -d $(BUILD_DIR)/libROOT/build ] || mkdir -p $(BUILD_DIR)/libROOT/build - $(COMPILE.cc) $(CPPFLAGS) -o $@ $< + @echo "Make $(notdir $@)" + $(Q) [ -d $(BUILD_DIR)/libROOT/build ] || mkdir -p $(BUILD_DIR)/libROOT/build + $(Q) $(COMPILE.cc) $(CPPFLAGS) -o $@ $< $(BUILD_DIR)/libroot_julia$(SO_SUFFIX): $(OBJS) - $(MAKE) check_root - $(LINK.o) -o $@ --shared -fPIC $(OBJS) $(ROOT_LIBS) $(LDLIBS) + @echo "Make $(notdir $@)" + $(Q) $(MAKE) check_root + $(Q) $(LINK.o) -o $@ --shared -fPIC $(OBJS) $(ROOT_LIBS) $(LDLIBS) echo_%: diff --git a/deps/build.jl b/deps/build.jl deleted file mode 100644 index d810069..0000000 --- a/deps/build.jl +++ /dev/null @@ -1,88 +0,0 @@ -import CxxWrap -import Libdl -import Conda -import TOML -using UUIDs -using Scratch -const CXXWRAP_PREFIX = CxxWrap.prefix_path() -const JL_SHARE = joinpath(Sys.BINDIR, Base.DATAROOTDIR, "julia") -const JULIA = joinpath(Sys.BINDIR, "julia") -const libname="libjlROOT." * Libdl.dlext - -const conda_root_version = "6.32.06" -const supported_root_versions = [ conda_root_version ] - -used_root_version = "" -root_libdir = "" -root_bindir = "" -rootconfig = "root-config" -cleanafterbuild=true - -const pkg_uuid = UUID(TOML.parsefile(joinpath(dirname(@__DIR__), "Project.toml"))["uuid"]) -const pkg_version = VersionNumber(TOML.parsefile(joinpath(dirname(@__DIR__), "Project.toml"))["version"]) - - -#Test root installation -try - global used_root_version = readchomp(`$rootconfig --version`) - global rootlibdir = readchomp(`$rootconfig --libdir`) - global root_found = true -catch - global root_found = false -end - -const scratch = joinpath(get_scratch!(pkg_uuid, "lib"), string(pkg_version), "ROOT-v" * used_root_version) - -found_root_ok = root_found && (used_root_version ∈ supported_root_versions) - -if found_root_ok - @info "ROOT libraries from $root_libdir will be used." -else - if !root_found - @info "Executable root-config not found. We will try to install ROOT from conda-forge." - elseif !found_root_ok - @info "Release of the found root installation is not compatible. Release " * join(supported_root_versions) * " required. We will try to install root from conda-forge." - end - try - cmd=:(Conda.add("root=$conda_root_version", args=`--strict-channel-priority --override-channels -c conda-forge`, satisfied_skip_solve=true)) - @info "Conda command: $cmd" - eval(cmd) - global rootlibdir = Conda.LIBDIR - global rootconfig = joinpath(Conda.BINDIR, "root-config") - global found_root_ok = true - catch - @error "Failed to install ROOT release $conda_root_version from conda-forge. Check you network connection or install ROOT yourself and restart julia with the path to the ROOT executables included in the shell exectable path list (PATH)." - #no-op - end -end - -found_root_ok || exit(1) - -const buildpath = joinpath(scratch, "build") - -cmd=`time make BUILD_DIR=$buildpath CXXWRAP_PREFIX="$CXXWRAP_PREFIX" JL_SHARE="$JL_SHARE" JULIA="$JULIA" ROOT_CONFIG="$rootconfig" -j $(Sys.CPU_THREADS)` -@info "Build command: " * string(cmd)[2:end-1] * " executed in " * pwd() * " directory." - -#julia needs to be in the PATH for julia-config.jl, invoked by the Makefile, to run -PATH=Sys.BINDIR * ":" * ENV["PATH"] - -build_rc = run(Cmd(cmd, env = ["PATH" => PATH], ignorestatus=true)).exitcode -libpath = joinpath(scratch, libname) -try - mv(joinpath(buildpath, libname), libpath, force=true) - splitpath(buildpath)[end-1] != "build" || error("Bug foud. buildpath must end with /build") #protection against deleted bad directory after introduciton of a bug - cleanafterbuild && rm(buildpath, recursive=true, force=true) -catch e - @warn "Failed to clean-up directory after dependency build. " * string(e) -end - -if build_rc == 0 - rootbindir = readchomp(`$rootconfig --bindir`) - open("deps.jl", "w") do f - println(f, "const rootlibdir = \"", escape_string(rootlibdir), "\"") - println(f, "const rootbindir = \"", escape_string(rootbindir), "\"") - println(f, "const libpath = \"", escape_string(libpath), "\"") - end -end - -exit(build_rc) diff --git a/deps/root_version.h b/deps/root_version.h new file mode 100644 index 0000000..3313e24 --- /dev/null +++ b/deps/root_version.h @@ -0,0 +1,3 @@ +const static int wrapped_root_version_major = 6; +const static int wrapped_root_version_minor = 32; +const static int wrapped_root_version_patch = 6; diff --git a/deps/src/Extra.cxx b/deps/src/Extra.cxx index 7096f5f..96723a3 100644 --- a/deps/src/Extra.cxx +++ b/deps/src/Extra.cxx @@ -10,4 +10,4 @@ void updateAllCanvas(){ canvas->Update(); } } - + diff --git a/src/CxxBuild.jl b/src/CxxBuild.jl new file mode 100644 index 0000000..924638a --- /dev/null +++ b/src/CxxBuild.jl @@ -0,0 +1,226 @@ +# Submodule of ROOT providing support to build +# the C++ code of the ROOT library wrapper. +# +# This is an internal module to be used by the ROOT module +# code. The API can change from release to release. + +module CxxBuild + +using ROOTprefs + +import CxxWrap +import Libdl +import TOML +import ROOT_jll +import libroot_julia_jll +import Artifacts +import SHA + +using UUIDs +using Scratch + + +import ....ROOT: supported_root_versions + +_English_or_list(v) = join(v, ", ", " or ") + +function is_jll_supported() + root_jll = Base.find_package("ROOT_jll") + isnothing(root_jll) && error("Package ROOT_jll not found. Please try to add it with 'import Pkg; Pkg.add(\"ROOT_jll\").") + ROOT_jll_dir = dirname(dirname(Base.find_package("ROOT_jll"))) + artifacts = Artifacts.select_downloadable_artifacts(joinpath(ROOT_jll_dir, "Artifacts.toml")) + length(artifacts) > 0 +end + +# +# `build_root_wrapper(rootsys; recompile = false, cleanafterbuild=true)` +# +# Build the libroot_julia library for the ROOT libraries installed under rootsys directory. +# Return the full path to libroot_julia or an empty string in case of failure. +# +function build_root_wrapper(rootsys = ROOTprefs.get_ROOTSYS()) + + rootconfig = joinpath(rootsys, "bin", "root-config") + used_root_version = readchomp(`$rootconfig --version`) + + # Directory to store the generated library + pkg_uuid = UUID(TOML.parsefile(joinpath(dirname(@__DIR__), "Project.toml"))["uuid"]) + pkg_version = VersionNumber(TOML.parsefile(joinpath(dirname(@__DIR__), "Project.toml"))["version"]) + scratch = joinpath(get_scratch!(pkg_uuid, "lib"), string(pkg_version), "Julia-v" * string(Base.VERSION), "ROOT-v" * used_root_version) + mkpath(scratch) + buildpath = joinpath(scratch, "build") + + #Command to build the library + CXXWRAP_PREFIX = CxxWrap.prefix_path() + JL_SHARE = joinpath(Sys.BINDIR, Base.DATAROOTDIR, "julia") + JULIA = joinpath(Sys.BINDIR, "julia") + depsdir = joinpath(dirname(@__DIR__), "deps") + cmd=`make -C "$depsdir" BUILD_DIR="$buildpath" CXXWRAP_PREFIX="$CXXWRAP_PREFIX" JL_SHARE="$JL_SHARE" JULIA="$JULIA" ROOT_CONFIG="$rootconfig" -j $(Sys.CPU_THREADS)` + cmd_clean = Cmd([collect(cmd)..., "clean"]) #append clean to the command arguments + cmd_file_list = Cmd([collect(cmd)..., "echo_WRAPPER_CXX"]) #command to list .cxx files + + @info "Build command: " * string(cmd)[2:end-1] * " executed in " * pwd() * " directory." + + #julia needs to be in the PATH for julia-config.jl, invoked by the Makefile, to run + PATH=Sys.BINDIR * ":" * ENV["PATH"] + + #Library name and path + libname="libroot_julia." * Libdl.dlext + libpath = joinpath(scratch, libname) + + #source files: + srcfiles = [] + out = readchomp(cmd_file_list) + for l in split(out, "\n") + m = match(r"^WRAPPER_CXX[[:space:]]*=[[:space:]]*(.*)[[:space:]]*", l) + if !isnothing(m) + srcfiles = split(m[1], " ") + break + end + end + + build = true + + #Check if library is alredy built and up-to-date. Returns if it's the case. + sigfile = joinpath(scratch, "sig") + if isfile(libpath) && isfile(sigfile) + newsig = libsignature(joinpath(depsdir, "src"), srcfiles, libpath) + oldsig = readline(sigfile) + if newsig == oldsig + @info "Library $libpath is already up-to-date." + build = false + end + end + + if build + #Call make to build the library + cmd = Cmd(cmd, env = ["PATH" => PATH], ignorestatus=true) + cmd_clean = Cmd(cmd_clean, env = ["PATH" => PATH], ignorestatus=true) + pipe = Pipe() + srcfiles = [] + try + run(pipeline(`tee "$scratch/build.log"`, stdin=pipe, stdout=stdout, stderr=stderr), wait=false) + + ncxx = length(srcfiles) + if ncxx > 0 + warntime = if ncxx > 10 + " This will take some time. Be patient." + else + "" + end + println("\n>>> Making $ncxx XYZ.o object files.$warntime <<<\n") + end + + run(pipeline(cmd, stderr=pipe, stdout=pipe)) + finally + close(pipe) + end + + #Check build result + if !isfile(joinpath(buildpath, libname)) + @error("Failed to compile the ROOT C++ library wrapper required by the Julia ROOT package. Logs can be found in $scratch/build.log") + libpath = "" + else + mv(joinpath(buildpath, libname), libpath, force=true) + sig = libsignature(joinpath(depsdir, "src"), srcfiles, libpath) + open(joinpath(scratch, "sig"), "w") do f + write(f, sig) + end + end + end + + #Clean-up build area + if is_clean_after_build_enabled() + try + splitpath(buildpath)[end-1] != "build" || error("Bug foud. buildpath must end with /build") #protect against wrong directory deletion after introduction of a bug + rm(buildpath, recursive=true, force=true) + catch e + @warn "Failed to clean-up directory after dependency build. " * string(e) + end + end + + libpath +end + +function libsignature(srcdir, srcfiles, libpath) + ctx = SHA.SHA2_256_CTX() + files = vcat([libpath], joinpath.(srcdir, srcfiles)) + for fname in files + #try + open(fname) do f + while !eof(f) + SHA.update!(ctx, read(f, 2^20)) + end + end + #catch + # @warn "Error while computing library signature. This may trigger unecessary recompilation of the C++ code when the module is precompiled." + #end + end + bytes2hex(SHA.digest!(ctx)) +end + +function check_rootsys() + rootsys = get_ROOTSYS() + + try + length(rootsys) == 0 && set_ROOTSYS!() + + vers_numbers = parse.(Int, split(readchomp(`"$rootsys/bin/root-config" --version`), ".")) + vers = VersionNumber(vers_numbers...) + + if is_root_version_checked() && vers ∉ supported_root_versions + error("Found ROOT version $vers is not supported.") + end + catch e + rethrow(ErrorException(e.msg * ". " * "Please install C++ ROOT (http://cern/root) version $(_English_or_list(supported_root_versions)). If it is already installed, either set your shell environment to make ROOT binaries available e.g., by sourcing thisroot.(c)sh file, or set ROOTSYS in Julia by executing 'import ROOTprefs; ROOTprefs.set_ROOTSYS(..).'")) + end + rootsys +end + + +function get_or_build_libroot_julia() + + if is_root_jll_used() && is_jll_supported() + #prebuilt wrapper used, no build to perform + return libroot_julia_jll.get_libroot_julia_path() + end + + if !is_root_jll_used() && is_jll_supported() + @info "The plaform supports ROOT_jll. You can use ROOT libraries from the ROOT_jll package to skip the long compilation step. To do so, interrupt the import, run 'using ROOTprefs; use_root_jll!() to enable the ROOT_jll mode, restart Julia, and execute 'import ROOT' again." + end + + rootsys = "" + + #Below, we process differently if root_jll mode is enabled or not + #in order to adapt the error message. + if is_root_jll_used() #jll mode but platform not supported. + use_root_jll!() + try + rootsys = check_rootsys() + @error("ROOT binaries not found in ROOT_jll for this platform. The wrapper will be compiled to use the ROOT libraries installed in $rootsys. The mode 'use_root_jll' has been disabled (can be reenabled with use_root_jll!()).") + catch + @error("ROOT binaries not found in ROOT_jll for pthis platform. You need to install ROOT version $supported_root_versions on the host and restart Julia. If the ROOT binaries are not in the system executable search path, you need to provide to the ROOT installation by calling 'using ROOTprefs; set_ROOTSYS(path)'. The mode 'use_root_jll' has been disabled (can be reenabled with use_root_jll!()).") + return "" + end + else #rootsys mode + try + rootsys = check_rootsys() + catch e + if e isa ErrorException && hasfield(e, :msg) + @error(e.msg) + return "" + else + rethrow() + end + end + end + + libpath = build_root_wrapper(rootsys) + + if(isempty(libpath)) + @error("Failed to build the Julia wrapper for the ROOT C++ framework installed in $(get_ROOTSYS()).") + end + + return libpath +end +end diff --git a/src/ROOT.jl b/src/ROOT.jl index e74888d..475ee34 100644 --- a/src/ROOT.jl +++ b/src/ROOT.jl @@ -1,83 +1,86 @@ module ROOT - import Base.getindex import Base.setindex! -import Libdl import Pkg using CxxWrap +using ROOTprefs -Sys.iswindows() && error("Windows platform detected. ROOT is supported on Linux and MacOS only.") +include("root_versions.jl") -if !isfile("$(@__DIR__)/../deps/deps.jl") - error("File '$(@__DIR__)/../deps/deps.jl' missing. This can happen if the ROOT package was installed with the Pkg.develop() (or ] dev) command. Run 'import Pkg; Pkg.build(\"ROOT\", verbose=true)' (or ] build -v ROOT) to generate the missing file.") -end +""" + `get_supported_root_versions() -> Vector` -include("$(@__DIR__)/../deps/deps.jl") -include_dependency(libpath) +Return the list of supported C++ ROOT framework versions. -if !isfile(libpath) - error("File '$libpath' missing. This can happen if the ROOT package was installed with the Pkg.develop() (or ] dev) command. Run 'import Pkg; Pkg.build(\"ROOT\", verbose=true)' (or ] build -v ROOT) to generate the missing file.") -end +""" +get_supported_root_versions() = supported_root_versions; -@wrapmodule(()->libpath) - -include("iROOT.jl") - -TF1!kDefault = 0 - -module Internals -import Conda -function get_conda_build_sysroot() - cxx = joinpath(Conda.PREFIX, "bin", "c++") - cmd = `$cxx -DNDEBUG -xc++ -E -v /dev/null` - sysroot="" - err = Pipe() - run(pipeline(ignorestatus(cmd), stdout=devnull, stderr=err), wait=true) - close(err.in) - for l in eachline(err) - if occursin(r"sysroot/usr/include$", l) - sysroot = strip(l) - break - end - end - replace(normpath(sysroot), normpath("/usr/include") => "") -end -end +#precompile_error::String = "" -import .Internals +# utility code not exposed to the user +include("internals.jl") -function __init__() - # Some required environment cleanup before loading the ROOT libraries - withenv( - # Prevent mix-up of root library version is another version than ours is in LD_LIBRARY_PATH: - "LD_LIBRARY_PATH" => "", - "DYLD_LIBRARY_PATH" => "", - # Workaroud to prevent a crash with root installed with Conda linker to - # the c++ compiler called by cling to get the include directories and - # missing in the PATH list. In the Conda install, compiler is same directory as ROOT - # binaries, rootbindir - "PATH" => ENV["PATH"] * ":" * rootbindir, - # Fix "assert.h not found" issue: - "CONDA_BUILD_SYSROOT" => Internals.get_conda_build_sysroot()) do - @initcxx - global gROOT = ROOT!GetROOT() - end - isinteractive() && _init_event_loop() -end +""" + `libroot_julia_path` + +Path of the shared library containing the C++ code interfacing the Julia ROOT package with the C++ ROOT libraries. This library is provided by the package libroot_julia_jll included in the dependency, when the C++ ROOT libraries are installed by the Julia package manager from the ROOT_jll package, or built on the fly (at first ROOT module import), if they are installed by another mean. +""" +const libroot_julia_path = Internals.CxxBuild.get_or_build_libroot_julia() -export gROOT, gSystem -include("ROOT-export.jl") +# Display libroot_julia_path value on precompilation +@info "ROOT wrapper library: $libroot_julia_path" -#export global function(s) taking a class instance as first parameter -#and missing from generated file ROOT-export.jl -export SetAddress -export move! +export cxxcompile -include("def_args.jl") -include("move.jl") +""" + `cxxcompile() -> Bool` -include("ROOTex.jl") -include("demo.jl") +Check that the C+ code of the package is compiled and compile it if needed. Returns true if the code is compiled, false if it wasn't and the compilation failed. Experimental, function name/API may still change. +""" +cxxcompile() = !isempty(Internals.CxxBuild.get_or_build_libroot_julia()) + + +if(isempty(libroot_julia_path)) + ok() = false +else + ok() = true + + include_dependency(libroot_julia_path) + + if is_root_jll_used() + Internals.loadlibdeps() + end + @wrapmodule(()->libroot_julia_path) + + include("iROOT.jl") + + TF1!kDefault = 0 + + export gROOT, gSystem + include("ROOT-export.jl") + + #export global function(s) taking a class instance as first parameter + #and missing from generated file ROOT-export.jl + export SetAddress + export move! + + include("def_args.jl") + include("move.jl") + + include("ROOTex.jl") + include("demo.jl") +end + +function __init__() + if isempty(libroot_julia_path) + @error "Failed to load or build C++ librairies and no function imported. See above error message to fix the issue.\nBEWARE: Julia needs to be restarted for the fix to take effect." + else + Internals.loadlibdeps() + @initcxx + global gROOT = ROOT!GetROOT() + isinteractive() && _init_event_loop() + end +end end #module diff --git a/src/internals.jl b/src/internals.jl new file mode 100644 index 0000000..639e42b --- /dev/null +++ b/src/internals.jl @@ -0,0 +1,24 @@ +module Internals + +import Libdl +import ROOT_jll + + +include("CxxBuild.jl") + +function loadlibdeps() + Libdl.dlopen(joinpath(ROOT_jll.find_artifact_dir(), "lib", "libCore"), Libdl.RTLD_GLOBAL) + Libdl.dlopen(joinpath(ROOT_jll.find_artifact_dir(), "lib", "libImt")) + Libdl.dlopen(joinpath(ROOT_jll.find_artifact_dir(), "lib", "libHist")) + Libdl.dlopen(joinpath(ROOT_jll.find_artifact_dir(), "lib", "libGraf")) + Libdl.dlopen(joinpath(ROOT_jll.find_artifact_dir(), "lib", "libGraf3d")) + Libdl.dlopen(joinpath(ROOT_jll.find_artifact_dir(), "lib", "libROOTVecOps.so")) + Libdl.dlopen(joinpath(ROOT_jll.find_artifact_dir(), "lib", "libTree.so")) + Libdl.dlopen(joinpath(ROOT_jll.find_artifact_dir(), "lib", "libTreePlayer.so")) + Libdl.dlopen(joinpath(ROOT_jll.find_artifact_dir(), "lib", "libRint.so")) + Libdl.dlopen(joinpath(ROOT_jll.find_artifact_dir(), "lib", "libPostscript.so")) + Libdl.dlopen(joinpath(ROOT_jll.find_artifact_dir(), "lib", "libPhysics.so")) + Libdl.dlopen(joinpath(ROOT_jll.find_artifact_dir(), "lib", "libROOTDataFrame.so")) + Libdl.dlopen(joinpath(ROOT_jll.find_artifact_dir(), "lib", "libGeom.so")) +end +end diff --git a/src/root_versions.jl b/src/root_versions.jl new file mode 100644 index 0000000..5c750c2 --- /dev/null +++ b/src/root_versions.jl @@ -0,0 +1,2 @@ +const wrapped_root_version = v"6.32.6" +const supported_root_versions = [ wrapped_root_version ] diff --git a/test/runtests.jl b/test/runtests.jl index bc34bf6..50e8583 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -16,11 +16,17 @@ function test_nothrow(script) end @testset verbose=true begin + if Sys.MACHINE == "x86_64-linux-gnu" + @testset verbose=true "ROOT install" begin + include("$(@__DIR__)/test_install.jl") + end + end + @testset verbose=true "TTree" begin - include("test_ttree.jl") + include("$(@__DIR__)/test_ttree.jl") end @testset verbose=true "Examples" begin - include("test_examples.jl") + include("$(@__DIR__)/test_examples.jl") end end diff --git a/test/test_install.jl b/test/test_install.jl new file mode 100644 index 0000000..78e4be5 --- /dev/null +++ b/test/test_install.jl @@ -0,0 +1,48 @@ +@testset "Test install" begin + + using ROOTprefs + + saved_project = Pkg.project().path + saved_loadpath = LOAD_PATH + Pkg.activate(temp=true) + + #empty LOAD_PATHL + #keepat!(LOAD_PATH, fill(false, size(LOAD_PATH))) + #add tested project in LOAD_PATH to import it + push!(LOAD_PATH, dirname(@__DIR__)) + + println("LOAD_PATH: ", LOAD_PATH) + + @test begin + import ROOT + isdefined(ROOT, :TH1D) + end + + #test external ROOT installation mode + #we mimic this mode using the contents of ROOT_jll + import ROOT_jll + using ROOTprefs + + use_root_jll!(false) + set_ROOTSYS!(ROOT_jll.artifact_dir) + project_path = Pkg.project().path + + rc = withenv("JULIA_LOAD_PATH" => join(LOAD_PATH, ":"), + "JULIA_PROJECT" => project_path) do + mktemp() do path, io + write(io, raw""" +import ROOT +using ROOTprefs +println(stderr, is_root_jll_used()) + exit(isdefined(ROOT, :TH1D) ? 0 : 1) + """) + close(io) + run(Cmd(`"$(Sys.BINDIR)/julia" --startup-file=no "$path"`, ignorestatus=true)).exitcode + end + end + @test rc == 0 + + LOAD_PATH .= saved_loadpath + Pkg.activate(saved_project) +end +