Skip to content

Commit 183d024

Browse files
committed
Set up skeleton
1 parent f0c112e commit 183d024

23 files changed

+575
-0
lines changed

.gitignore

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Prerequisites
2+
*.d
3+
4+
# Compiled Object files
5+
*.slo
6+
*.lo
7+
*.o
8+
*.obj
9+
10+
# Compiled Dynamic libraries
11+
*.so
12+
*.dylib
13+
*.dll
14+
15+
# Compiled Static libraries
16+
*.lai
17+
*.la
18+
*.a
19+
*.lib
20+
21+
# Build directories
22+
/build/
23+
/python/dist/
24+
/python/build/
25+
/python/treelite.egg-info/
26+
/runtime/python/dist/
27+
/runtime/python/build/
28+
/runtime/python/treelite_runtime.egg-info/
29+
30+
# symbol directories
31+
*.dSYM/
32+
33+
# Project files
34+
/runtime/python/.idea/
35+
/python/.idea/
36+
/tests/python/.idea/
37+
/.idea/

.isort.cfg

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[settings]
2+
profile=black
3+
known_first_party=tl2cgen,tl2cgen_runtime

CMakeLists.txt

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
set(CMAKE_FIND_NO_INSTALL_PREFIX TRUE FORCE)
2+
cmake_minimum_required(VERSION 3.13)
3+
project(tl2cgen LANGUAGES CXX C VERSION 0.0.1)
4+
5+
# check MSVC version
6+
if (MSVC)
7+
if (MSVC_VERSION LESS 1920)
8+
message(FATAL_ERROR "Need Visual Studio 2019 or newer to compile TL2cgen")
9+
endif ()
10+
endif ()
11+
12+
option(TEST_COVERAGE "C++ test coverage" OFF)
13+
option(USE_OPENMP "Use OpenMP" ON)
14+
option(BUILD_DOXYGEN "Build documentation for C/C++ functions using Doxygen." OFF)
15+
option(BUILD_CPP_TESTS "Build C++ tests" OFF)
16+
option(BUILD_STATIC_LIBS "Build static libs, in addition to dynamic libs" OFF)
17+
option(FORCE_SHARED_CRT "Build with dynamic CRT on Windows (/MD)" OFF)
18+
option(DETECT_CONDA_ENV "Enable detection of Conda environment for dependencies" ON)
19+
option(BUILD_JVM_RUNTIME "Build TL2cgen runtime for JVM" OFF)
20+
option(ENABLE_ALL_WARNINGS "Enable all compiler warnings. Only effective for GCC/Clang" OFF)
21+
option(USE_SANITIZER "Use sanitizer flags" OFF)
22+
SET(ENABLED_SANITIZERS "address" "leak" "undefined" CACHE STRING
23+
"Semicolon separated list of sanitizer names. E.g 'address;leak'.")
24+
25+
if (USE_SANITIZER)
26+
include(cmake/Sanitizer.cmake)
27+
enable_sanitizers("${ENABLED_SANITIZERS}")
28+
endif ()
29+
30+
if (ENABLE_ALL_WARNINGS)
31+
if ((NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))
32+
message(SEND_ERROR "ENABLE_ALL_WARNINGS is only available for Clang and GCC.")
33+
endif ()
34+
endif ()
35+
36+
if (BUILD_DOXYGEN)
37+
include(cmake/Doxygen.cmake)
38+
run_doxygen()
39+
endif ()
40+
41+
# When installing dependencies, use Conda environment if available
42+
if (DETECT_CONDA_ENV)
43+
if (DEFINED ENV{CONDA_PREFIX})
44+
set(CMAKE_PREFIX_PATH "$ENV{CONDA_PREFIX};${CMAKE_PREFIX_PATH}")
45+
message(STATUS "Detected Conda environment, CMAKE_PREFIX_PATH set to: ${CMAKE_PREFIX_PATH}")
46+
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
47+
message(STATUS "No CMAKE_INSTALL_PREFIX argument detected, setting to: $ENV{CONDA_PREFIX}")
48+
set(CMAKE_INSTALL_PREFIX $ENV{CONDA_PREFIX})
49+
endif ()
50+
else ()
51+
message(STATUS "No Conda environment detected")
52+
endif ()
53+
endif ()
54+
55+
list(APPEND CMAKE_MODULE_PATH "${tl2cgen_SOURCE_DIR}/cmake/modules")
56+
include(cmake/ExternalLibs.cmake)
57+
include(cmake/Utils.cmake)
58+
include(cmake/Version.cmake)
59+
60+
add_subdirectory(src)
61+
if (BUILD_JVM_RUNTIME)
62+
add_subdirectory(runtime/java)
63+
endif ()
64+
if (BUILD_CPP_TESTS)
65+
add_subdirectory(tests/cpp)
66+
endif ()
67+
68+
add_library(tl2cgen SHARED)
69+
add_library(tl2cgen_runtime SHARED)
70+
target_link_libraries(tl2cgen PRIVATE obj_tl2cgen obj_tl2cgen_common)
71+
target_link_libraries(tl2cgen_runtime PRIVATE obj_tl2cgen_runtime obj_tl2cgen_common)
72+
73+
set(TL2CGEN_TARGETS tl2cgen tl2cgen_runtime)
74+
75+
if (BUILD_STATIC_LIBS)
76+
add_library(tl2cgen_static STATIC)
77+
add_library(tl2cgen_runtime_static STATIC)
78+
target_link_libraries(tl2cgen_static PRIVATE obj_tl2cgen obj_tl2cgen_common)
79+
target_link_libraries(tl2cgen_runtime_static PRIVATE obj_tl2cgen_runtime obj_tl2cgen_common)
80+
list(APPEND TL2CGEN_TARGETS tl2cgen_static tl2cgen_runtime_static)
81+
endif ()
82+
83+
foreach (lib ${TL2CGEN_TARGETS})
84+
set_output_directory(${lib} ${PROJECT_BINARY_DIR})
85+
endforeach ()
86+
87+
# Export install targets
88+
include(GNUInstallDirs)
89+
include(CMakePackageConfigHelpers)
90+
set(INSTALL_TARGETS ${TL2CGEN_TARGETS})
91+
if (BUILD_STATIC_LIBS)
92+
list(APPEND INSTALL_TARGETS obj_tl2cgen obj_tl2cgen_common obj_tl2cgen_runtime rapidjson)
93+
endif ()
94+
if (NOT FMTLIB_FROM_SYSTEM_ROOT)
95+
list(APPEND INSTALL_TARGETS fmt-header-only)
96+
endif ()
97+
install(TARGETS ${INSTALL_TARGETS}
98+
EXPORT TL2cgenTargets
99+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
100+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
101+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
102+
INCLUDES DESTINATION include)
103+
install(DIRECTORY include/tl2cgen ${PROJECT_BINARY_DIR}/include/tl2cgen
104+
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
105+
install(EXPORT TL2cgenTargets
106+
FILE TL2cgenTargets.cmake
107+
NAMESPACE tl2cgen::
108+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/tl2cgen)
109+
configure_package_config_file(
110+
cmake/TL2cgenConfig.cmake.in
111+
${PROJECT_BINARY_DIR}/cmake/TL2cgenConfig.cmake
112+
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/tl2cgen)
113+
write_basic_package_version_file(
114+
${PROJECT_BINARY_DIR}/cmake/TL2cgenConfigVersion.cmake
115+
VERSION ${PROJECT_VERSION}
116+
COMPATIBILITY SameMajorVersion)
117+
install(FILES
118+
${PROJECT_BINARY_DIR}/cmake/TL2cgenConfig.cmake
119+
${PROJECT_BINARY_DIR}/cmake/TL2cgenConfigVersion.cmake
120+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/tl2cgen)
121+
122+
write_version()
123+
124+
set_default_configuration_release()
125+
msvc_use_static_runtime()

cmake/ExternalLibs.cmake

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
include(FetchContent)
2+
3+
# fmtlib
4+
find_package(fmt)
5+
if (fmt_FOUND)
6+
get_target_property(fmt_loc fmt::fmt INTERFACE_INCLUDE_DIRECTORIES)
7+
message(STATUS "Found fmtlib at ${fmt_loc}")
8+
set(FMTLIB_FROM_SYSTEM_ROOT TRUE)
9+
else ()
10+
message(STATUS "Did not find fmtlib in the system root. Fetching fmtlib now...")
11+
FetchContent_Declare(
12+
fmtlib
13+
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
14+
GIT_TAG 9.1.0
15+
)
16+
FetchContent_MakeAvailable(fmtlib)
17+
set_target_properties(fmt PROPERTIES EXCLUDE_FROM_ALL TRUE)
18+
set(FMTLIB_FROM_SYSTEM_ROOT FALSE)
19+
endif ()
20+
21+
# RapidJSON (header-only library)
22+
add_library(rapidjson INTERFACE)
23+
find_package(RapidJSON)
24+
if (RapidJSON_FOUND)
25+
target_include_directories(rapidjson INTERFACE ${RAPIDJSON_INCLUDE_DIRS})
26+
else ()
27+
message(STATUS "Did not find RapidJSON in the system root. Fetching RapidJSON now...")
28+
FetchContent_Declare(
29+
RapidJSON
30+
GIT_REPOSITORY https://github.com/Tencent/rapidjson
31+
GIT_TAG v1.1.0
32+
)
33+
FetchContent_Populate(RapidJSON)
34+
message(STATUS "RapidJSON was downloaded at ${rapidjson_SOURCE_DIR}.")
35+
target_include_directories(rapidjson INTERFACE $<BUILD_INTERFACE:${rapidjson_SOURCE_DIR}/include>)
36+
endif ()
37+
add_library(RapidJSON::rapidjson ALIAS rapidjson)
38+
39+
# Google C++ tests
40+
if (BUILD_CPP_TESTS)
41+
find_package(GTest 1.11.0 CONFIG)
42+
if (NOT GTEST_FOUND)
43+
message(STATUS "Did not find Google Test in the system root. Fetching Google Test now...")
44+
FetchContent_Declare(
45+
googletest
46+
GIT_REPOSITORY https://github.com/google/googletest.git
47+
GIT_TAG release-1.11.0
48+
)
49+
FetchContent_MakeAvailable(googletest)
50+
add_library(GTest::GTest ALIAS gtest)
51+
add_library(GTest::gmock ALIAS gmock)
52+
endif ()
53+
endif ()

cmake/Python_version.in

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@-dev

cmake/Sanitizer.cmake

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Set appropriate compiler and linker flags for sanitizers.
2+
#
3+
# Usage of this module:
4+
# enable_sanitizers("address;leak")
5+
6+
# Add flags
7+
macro(enable_sanitizer sanitizer)
8+
if (${sanitizer} MATCHES "address")
9+
find_package(ASan)
10+
set(SAN_COMPILE_FLAGS "${SAN_COMPILE_FLAGS} -fsanitize=address")
11+
12+
elseif (${sanitizer} MATCHES "thread")
13+
find_package(TSan)
14+
set(SAN_COMPILE_FLAGS "${SAN_COMPILE_FLAGS} -fsanitize=thread")
15+
if (TSan_FOUND)
16+
link_libraries(${TSan_LIBRARY})
17+
endif (TSan_FOUND)
18+
19+
elseif (${sanitizer} MATCHES "leak")
20+
find_package(LSan)
21+
set(SAN_COMPILE_FLAGS "${SAN_COMPILE_FLAGS} -fsanitize=leak")
22+
23+
elseif (${sanitizer} MATCHES "undefined")
24+
find_package(UBSan)
25+
set(SAN_COMPILE_FLAGS "${SAN_COMPILE_FLAGS} -fsanitize=undefined -fno-sanitize-recover=undefined")
26+
27+
else ()
28+
message(FATAL_ERROR "Santizer ${sanitizer} not supported.")
29+
endif ()
30+
endmacro()
31+
32+
macro(enable_sanitizers SANITIZERS)
33+
# Check sanitizers compatibility.
34+
# Idealy, we should use if(san IN_LIST SANITIZERS) ... endif()
35+
# But I haven't figure out how to make it work.
36+
foreach (_san ${SANITIZERS})
37+
string(TOLOWER ${_san} _san)
38+
if (_san MATCHES "thread")
39+
if (${_use_other_sanitizers})
40+
message(FATAL_ERROR
41+
"thread sanitizer is not compatible with ${_san} sanitizer.")
42+
endif ()
43+
set(_use_thread_sanitizer 1)
44+
else ()
45+
if (${_use_thread_sanitizer})
46+
message(FATAL_ERROR
47+
"${_san} sanitizer is not compatible with thread sanitizer.")
48+
endif ()
49+
set(_use_other_sanitizers 1)
50+
endif ()
51+
endforeach ()
52+
53+
message("Sanitizers: ${SANITIZERS}")
54+
55+
foreach (_san ${SANITIZERS})
56+
string(TOLOWER ${_san} _san)
57+
enable_sanitizer(${_san})
58+
endforeach ()
59+
message("Sanitizers compile flags: ${SAN_COMPILE_FLAGS}")
60+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SAN_COMPILE_FLAGS}")
61+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SAN_COMPILE_FLAGS}")
62+
endmacro()

cmake/TL2cgenConfig.cmake.in

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
@PACKAGE_INIT@
2+
3+
include(CMakeFindDependencyMacro)
4+
5+
set(USE_OPENMP @USE_OPENMP@)
6+
if(USE_OPENMP)
7+
find_dependency(OpenMP)
8+
endif()
9+
10+
if(NOT TARGET tl2cgen::tl2cgen)
11+
include(${CMAKE_CURRENT_LIST_DIR}/TL2cgenTargets.cmake)
12+
endif()
13+
14+
message(STATUS "Found TL2cgen (found version \"${TL2cgen_VERSION}\")")

cmake/Utils.cmake

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Automatically set source group based on folder
2+
function(auto_source_group SOURCES)
3+
foreach (FILE ${SOURCES})
4+
get_filename_component(PARENT_DIR "${FILE}" PATH)
5+
6+
# skip src or include and changes /'s to \\'s
7+
string(REPLACE "${CMAKE_CURRENT_LIST_DIR}" "" GROUP "${PARENT_DIR}")
8+
string(REPLACE "/" "\\\\" GROUP "${GROUP}")
9+
string(REGEX REPLACE "^\\\\" "" GROUP "${GROUP}")
10+
11+
source_group("${GROUP}" FILES "${FILE}")
12+
endforeach ()
13+
endfunction(auto_source_group)
14+
15+
# Force static runtime for MSVC
16+
function(msvc_use_static_runtime)
17+
if (MSVC AND (NOT BUILD_SHARED_LIBS) AND (NOT FORCE_SHARED_CRT))
18+
set(variables
19+
CMAKE_CXX_FLAGS_DEBUG
20+
CMAKE_CXX_FLAGS_MINSIZEREL
21+
CMAKE_CXX_FLAGS_RELEASE
22+
CMAKE_CXX_FLAGS_RELWITHDEBINFO)
23+
foreach (variable ${variables})
24+
if (${variable} MATCHES "/MD")
25+
string(REGEX REPLACE "/MD" "/MT" ${variable} "${${variable}}")
26+
set(${variable} "${${variable}}" PARENT_SCOPE)
27+
endif ()
28+
endforeach ()
29+
endif ()
30+
endfunction(msvc_use_static_runtime)
31+
32+
# Set output directory of target, ignoring debug or release
33+
function(set_output_directory target dir)
34+
set_target_properties(${target} PROPERTIES
35+
RUNTIME_OUTPUT_DIRECTORY ${dir} # for executable
36+
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${dir}
37+
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${dir}
38+
LIBRARY_OUTPUT_DIRECTORY ${dir} # for shared library
39+
LIBRARY_OUTPUT_DIRECTORY_DEBUG ${dir}
40+
LIBRARY_OUTPUT_DIRECTORY_RELEASE ${dir}
41+
ARCHIVE_OUTPUT_DIRECTORY ${dir} # for static library
42+
ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${dir}
43+
ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${dir}
44+
)
45+
endfunction(set_output_directory)
46+
47+
# Set a default build type to release if none was specified
48+
function(set_default_configuration_release)
49+
if (CMAKE_CONFIGURATION_TYPES STREQUAL "Debug;Release;MinSizeRel;RelWithDebInfo")
50+
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)
51+
elseif (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
52+
message(STATUS "Setting build type to 'Release' as none was specified.")
53+
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
54+
endif ()
55+
endfunction(set_default_configuration_release)

cmake/Version.cmake

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function(write_version)
2+
message(STATUS "TL2cgen VERSION: ${PROJECT_VERSION}")
3+
configure_file(
4+
${PROJECT_SOURCE_DIR}/cmake/Python_version.in
5+
${PROJECT_SOURCE_DIR}/python/tl2cgen/VERSION @ONLY)
6+
configure_file(
7+
${PROJECT_SOURCE_DIR}/cmake/Python_version.in
8+
${PROJECT_SOURCE_DIR}/runtime/python/tl2cgen_runtime/VERSION @ONLY)
9+
configure_file(
10+
${PROJECT_SOURCE_DIR}/cmake/version.h.in
11+
include/tl2gen/version.h)
12+
endfunction(write_version)

cmake/modules/FindASan.cmake

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
set(ASan_LIB_NAME ASan)
2+
3+
find_library(ASan_LIBRARY
4+
NAMES libasan.so libasan.so.6 libasan.so.5 libasan.so.4 libasan.so.3 libasan.so.2 libasan.so.1 libasan.so.0
5+
PATHS ${SANITIZER_PATH} /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib ${CMAKE_PREFIX_PATH}/lib)
6+
7+
include(FindPackageHandleStandardArgs)
8+
find_package_handle_standard_args(ASan DEFAULT_MSG
9+
ASan_LIBRARY)
10+
11+
mark_as_advanced(
12+
ASan_LIBRARY
13+
ASan_LIB_NAME)

cmake/modules/FindLSan.cmake

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
set(LSan_LIB_NAME lsan)
2+
3+
find_library(LSan_LIBRARY
4+
NAMES liblsan.so liblsan.so.0 liblsan.so.0.0.0
5+
PATHS ${SANITIZER_PATH} /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib ${CMAKE_PREFIX_PATH}/lib)
6+
7+
include(FindPackageHandleStandardArgs)
8+
find_package_handle_standard_args(LSan DEFAULT_MSG
9+
LSan_LIBRARY)
10+
11+
mark_as_advanced(
12+
LSan_LIBRARY
13+
LSan_LIB_NAME)

0 commit comments

Comments
 (0)