I am making a library for a c++ cmake executable application. In this library I want to be able to call julia functions as shown in this example. To do this I have downloaded the Julia linux binaries from here, which includes the executable application, shared object files, and include files. I have then linked the libjulia.so to my shared library, and included the Julia headers.
I have done this using CMake shown below:
######################################
##### External Include directories
include_directories(externals/Julia/include/julia/)
######################################
##### External Libraries
set(${PROJECT_NAME}_EXTERNAL_LIBRARIES
externals/Julia/lib/libjulia.so
externals/Julia/lib/julia/libLLVM-3.9.1.so
)
######################################
##### Shared library
add_library(${PROJECT_NAME} SHARED ${${PROJECT_NAME}_SRCS} ${${PROJECT_NAME}_HDRS})
target_link_libraries(${PROJECT_NAME} ${${PROJECT_NAME}_EXTERNAL_LIBRARIES})
######################################
##### Static library
add_library(${PROJECT_NAME}_STATIC STATIC ${${PROJECT_NAME}_SRCS} ${${PROJECT_NAME}_HDRS})
target_link_libraries(${PROJECT_NAME}_STATIC ${${PROJECT_NAME}_EXTERNAL_LIBRARIES})
######################################
##### Tests
set(test_sources
tests/sampleTest.cpp
)
include(tests/externals/UnitTests/CMakeScripts/MakeTests.cmake)#location of MakeTests.cmake
MakeTests() #Sets the instructions to create the makefile which builds the tests
I think a potential problem with this is that I have only linked libjulia.so and libLLVM-3.9.1.so, but there are actually lots more in the Julia/lib directory. I only linked these two because I first tried compiling without linking anything and I had undefined references to functions, so I added libJulia.so, and then I had undefined reffences to functions which started with path libLLVM\ so I added libLLVM-3.9.1.so. It then ran, but failed with error shown at the bottom of this question. Another potential problem is that I am compiling with gcc, not clang, so I do not know if the LLVM library will work.
For refference, here is my MakeTests function. It creates an executable and links my static library and the gtest library to it.
######################################
##### Get the path of the unit test external
set(DIR_OF_MAKETESTS_CMAKE ${CMAKE_CURRENT_LIST_DIR}) #The directory that this function is ran from
get_filename_component(UNIT_TEST_DIR ${DIR_OF_MAKETESTS_CMAKE} DIRECTORY) #get parent directory
function(MakeTests)
######################################
##### Set gtest compile options for gtest to match compile options of test subject
##### This is to prevent the MSVC runtime library running twice.
##### For example you do no want to compile the foo.lib with the Runtime library option: Multi-threaded (/MT)
##### and the test project with the option: Multi-threaded DLL (/MD).
set(gtest_force_shared_crt ON CACHE BOOL "Use shared (DLL) run-time lib even when Google Test is built as static lib." FORCE)
set(gtest_disable_pthreads OFF CACHE BOOL "Disable uses of pthreads in gtest." FORCE)
if(MINGW)
set(gtest_disable_pthreads ON CACHE BOOL "Disable uses of pthreads in gtest." FORCE)
endif()
######################################
###### Add Gtest to build
if(TARGET gtest_main) #only if it's not already been added as a target before.
MESSAGE(STATUS "Gtest allready added as target")
else()
MESSAGE(STATUS "Fetching Googletest framework.")
add_subdirectory(
${UNIT_TEST_DIR}/externals/GoogleTest
${PROJECT_BINARY_DIR}/gooogletest
)
endif()
######################################
###### Include Gtest directories (the root location for #include paths)
include_directories(${gtest_SOURCE_DIR}/include)
######################################
##### Create a list of names for the executables
set(test_names) #make an empty list
list(LENGTH test_sources len1) #len1 is length of test_sources list
math(EXPR len2 "${len1} - 1") #len2 is len1 - 1
foreach(val RANGE ${len2}) #for val = 0 to len2
list(GET test_sources ${val} src) #list(GET <list> <element index> <output variable>)
get_filename_component(name ${src} NAME_WE) #get the name compnent of src
list(APPEND test_names ${name}) #append the name to the list
endforeach()
######################################
##### Create a list of files needed for the executables
set(test_files
${${PROJECT_NAME}_SRCS} #from the main project. The test executables will need these to compile
${${PROJECT_NAME}_HDRS}
)
######################################
##### Loop over all the .cpp files and create separate executables
foreach(val RANGE ${len2}) #for val = 0 to len2
list(GET test_names ${val} name) #name will change on every loop
list(GET test_sources ${val} src) #list(GET <list> <element index> <output variable>)
add_executable("${name}" "${src}" "${test_files}") #add_executable(<name> source1 [source2 ...])
endforeach()
######################################
###### Link the libraries
foreach(val RANGE ${len2}) #for val = 0 to len2
list(GET test_names ${val} name) #name will change on every loop
add_dependencies(${name} ${PROJECT_NAME}_STATIC) #Make sure main project builds before the unit test executable is built
message(STATUS " LINKING: ${PROJECT_NAME}_STATIC to ${name}")
target_link_libraries(${name} gtest_main) #link gtest libraries
target_link_libraries(${name} ${PROJECT_NAME}_STATIC) #link all other libraies
endforeach()
endfunction()
And then the executable that I am running is sampleTest.exe. This is made from sampleTest.cpp, shown here:
#include <gtest/gtest.h>
#include <julia.h>
TEST(all,main_temp)
{
std::cout << "starting test" << std::endl;
/* required: setup the Julia context */
jl_init(NULL);
/* run Julia commands */
jl_eval_string("print(sqrt(2.0))");
/* strongly recommended: notify Julia that the
program is about to terminate. this allows
Julia time to cleanup pending write requests
and run all finalizers
*/
jl_atexit_hook(0);
ASSERT_EQ(1,1);
}
My application output is as follows:
Running main() from gtest_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from all
[ RUN ] all.main_temp
starting test
1ThreadSanitizer: can't find longjmp buf
FATAL: ThreadSanitizer CHECK failed: ../../../../src/libsanitizer/tsan/tsan_interceptors.cc:423 "((0)) != (0)" (0x0, 0x0)
#0 <null> <null> (libtsan.so.0+0x000000075193)
#1 <null> <null> (libtsan.so.0+0x00000007519b)
#2 __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) <null> (libtsan.so.0+0x000000079d13)
#3 <null> <null> (libtsan.so.0+0x000000023faa)
#4 siglongjmp <null> (libtsan.so.0+0x00000002541f)
#5 restore_stack /buildworker/worker/package_linux64/build/src/task.c:193 (libjulia.so.0.6+0x000000058a27)
#6 restore_stack /buildworker/worker/package_linux64/build/src/task.c:188 (libjulia.so.0.6+0x000000058a55)
#7 <null> <null> (0x7ffc91494110)
Why am I getting this error? How should I set up my CMake so that I can run Julia code without errors like this?
Thanks.