linyaps-box/CMakeLists.txt

522 lines
18 KiB
CMake

cmake_minimum_required(VERSION 3.11.4) # for RHEL 8
project(
linyaps-box
VERSION 2.0.3
DESCRIPTION "A simple OCI runtime for desktop applications"
HOMEPAGE_URL "https://github.com/OpenAtom-Linyaps/linyaps-box"
LANGUAGES CXX)
# ==============================================================================
# Utilities
# ==============================================================================
# NOTE: Modified from https://www.scivision.dev/cmake-project-is-top-level/
if(CMAKE_VERSION VERSION_LESS 3.21)
get_property(
not_top
DIRECTORY
PROPERTY PARENT_DIRECTORY)
if(NOT not_top)
set(linyaps-box_IS_TOP_LEVEL true)
else()
set(linyaps-box_IS_TOP_LEVEL false)
endif()
endif()
# ==============================================================================
# Build options
# ==============================================================================
option(linyaps-box_STATIC "Build linyaps-box as statically-linked binary." OFF)
option(linyaps-box_ENABLE_SECCOMP "Build linyaps-box with seccomp support." OFF)
option(linyaps-box_ENABLE_CAP "Build linyaps-box with capability support" ON)
option(linyaps-box_ENABLE_UNIT_TESTS "Enable unit tests."
${linyaps-box_IS_TOP_LEVEL})
option(linyaps-box_ENABLE_SMOKE_TESTS "Enable smoke tests." OFF)
option(linyaps-box_MAKE_RELEASE "Make release build." OFF)
if(linyaps-box_ENABLE_SMOKE_TESTS OR linyaps-box_ENABLE_UNIT_TESTS)
set(linyaps-box_ENABLE_TESTING ON)
endif()
option(linyaps-box_ENABLE_COVERAGE "Enable coverage." OFF)
if(linyaps-box_ENABLE_COVERAGE AND NOT linyaps-box_ENABLE_TESTING)
message(
FATAL_ERROR
"linyaps-box_ENABLE_COVERAGE requires linyaps-box_ENABLE_UNIT_TESTS or linyaps-box_ENABLE_SMOKE_TESTS."
)
endif()
option(linyaps-box_ENABLE_CPACK "Enable CPack." OFF)
if(linyaps-box_ENABLE_CPACK)
set(linyaps-box_CPACK_PACKAGING_INSTALL_PREFIX
"/opt/org.openatom.linyaps-box"
CACHE STRING "Install prefix for package generated by CPack.")
endif()
set(linyaps-box_CLONE_CHILD_STACK_SIZE
"(1U << 20)"
CACHE
STRING
"DO NOT MODIFY THIS SETTINGS UNLESS YOU KNOW WHAT YOU ARE DOING. Size of child stack in bytes when using clone(2) to create container."
)
set(linyaps-box_STACK_GROWTH_DOWN
true
CACHE
BOOL
"DO NOT MODIFY THIS SETTINGS UNLESS YOU KNOW WHAT YOU ARE DOING. If stacks grow upward on your processor, set this to false."
)
set(linyaps-box_DEFAULT_LOG_LEVEL
LOG_WARNING
CACHE
STRING
"The default syslog priority. This is used to filter log messages at runtime time."
)
set(linyaps-box_ACTIVE_LOG_LEVEL
LOG_WARNING
CACHE
STRING
"The active syslog priority. This is used to filter log messages at compile time."
)
set(linyaps-box_ENABLE_CPM
ON
CACHE BOOL "enable CPM")
if(CMAKE_VERSION VERSION_LESS "3.14")
set(linyaps-box_ENABLE_CPM OFF)
message(
STATUS "cmake version ${CMAKE_VERSION} not compatible with CPM.cmake.")
endif()
# if just want to try local packages at first set CPM_USE_LOCAL_PACKAGES ON
set(linyaps-box_CPM_LOCAL_PACKAGES_ONLY
OFF
CACHE BOOL "use local packages only")
if(linyaps-box_CPM_LOCAL_PACKAGES_ONLY)
message(STATUS "CPM is disabled")
set(linyaps-box_ENABLE_CPM OFF)
endif()
# ==============================================================================
set(linyaps-box_LIBRARY linyaps-box)
set(linyaps-box_LIBRARY_SOURCE
# find -regex '\./src/.+\.[ch]\(pp\)?' -type f -printf '%P\n'| sort
src/linyaps_box/app.cpp
src/linyaps_box/app.h
src/linyaps_box/cgroup.h
src/linyaps_box/cgroup_manager.c
src/linyaps_box/cgroup_manager.h
src/linyaps_box/command/exec.cpp
src/linyaps_box/command/exec.h
src/linyaps_box/command/kill.cpp
src/linyaps_box/command/kill.h
src/linyaps_box/command/list.cpp
src/linyaps_box/command/list.h
src/linyaps_box/command/options.cpp
src/linyaps_box/command/options.h
src/linyaps_box/command/run.cpp
src/linyaps_box/command/run.h
src/linyaps_box/config.cpp
src/linyaps_box/config.h
src/linyaps_box/container.cpp
src/linyaps_box/container.h
src/linyaps_box/container_ref.cpp
src/linyaps_box/container_ref.h
src/linyaps_box/container_status.cpp
src/linyaps_box/container_status.h
src/linyaps_box/impl/disabled_cgroup_manager.cpp
src/linyaps_box/impl/disabled_cgroup_manager.h
src/linyaps_box/impl/json_printer.cpp
src/linyaps_box/impl/json_printer.h
src/linyaps_box/impl/status_directory.cpp
src/linyaps_box/impl/status_directory.h
src/linyaps_box/impl/table_printer.cpp
src/linyaps_box/impl/table_printer.h
src/linyaps_box/interface.cpp
src/linyaps_box/interface.h
src/linyaps_box/printer.cpp
src/linyaps_box/printer.h
src/linyaps_box/runtime.cpp
src/linyaps_box/runtime.h
src/linyaps_box/status_directory.cpp
src/linyaps_box/status_directory.h
src/linyaps_box/utils/atomic_write.cpp
src/linyaps_box/utils/atomic_write.h
src/linyaps_box/utils/cgroups.cpp
src/linyaps_box/utils/cgroups.h
src/linyaps_box/utils/close_range.cpp
src/linyaps_box/utils/close_range.h
src/linyaps_box/utils/defer.h
src/linyaps_box/utils/file_describer.cpp
src/linyaps_box/utils/file_describer.h
src/linyaps_box/utils/fstat.cpp
src/linyaps_box/utils/fstat.h
src/linyaps_box/utils/inspect.cpp
src/linyaps_box/utils/inspect.h
src/linyaps_box/utils/log.cpp
src/linyaps_box/utils/log.h
src/linyaps_box/utils/mkdir.cpp
src/linyaps_box/utils/mkdir.h
src/linyaps_box/utils/mknod.cpp
src/linyaps_box/utils/mknod.h
src/linyaps_box/utils/open_file.cpp
src/linyaps_box/utils/open_file.h
src/linyaps_box/utils/platform.cpp
src/linyaps_box/utils/platform.h
src/linyaps_box/utils/semver.cpp
src/linyaps_box/utils/semver.h
src/linyaps_box/utils/socketpair.cpp
src/linyaps_box/utils/socketpair.h
src/linyaps_box/utils/symlink.cpp
src/linyaps_box/utils/symlink.h
src/linyaps_box/utils/touch.cpp
src/linyaps_box/utils/touch.h)
set(LINYAPS_BOX_VERSION ${PROJECT_VERSION})
if(NOT linyaps-box_MAKE_RELEASE)
message(STATUS "make dev build")
execute_process(
COMMAND git rev-parse --short=7 HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(LINYAPS_BOX_VERSION "${LINYAPS_BOX_VERSION}-dev-${GIT_COMMIT_HASH}")
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/linyaps_box/version.h.in
${CMAKE_CURRENT_BINARY_DIR}/src/linyaps_box/version.h @ONLY)
# for gcc 8
set(linyaps-box_LIBRARY_LINK_LIBRARIES "stdc++fs")
set(linyaps-box_LIBRARY_INCLUDE_DIRS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src"
"${CMAKE_CURRENT_BINARY_DIR}/src")
if(linyaps-box_STATIC)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
endif()
find_package(PkgConfig REQUIRED)
if(linyaps-box_ENABLE_SECCOMP)
pkg_check_modules(libseccomp REQUIRED IMPORTED_TARGET libseccomp>=2.3.3)
list(APPEND linyaps-box_LIBRARY_LINK_LIBRARIES PUBLIC PkgConfig::libseccomp)
endif()
if(linyaps-box_ENABLE_CAP)
pkg_check_modules(libcap REQUIRED IMPORTED_TARGET libcap>=2.25)
list(APPEND linyaps-box_LIBRARY_LINK_LIBRARIES PUBLIC PkgConfig::libcap)
endif()
if(linyaps-box_ENABLE_CPM)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(CPM)
CPMFindPackage(
NAME nlohmann_json
VERSION 3.11.3
GITHUB_REPOSITORY nlohmann/json
GIT_TAG v3.12.0
EXCLUDE_FROM_ALL ON
OPTIONS "JSON_BuildTests OFF")
CPMFindPackage(
NAME CLI11
VERSION 2.4.1
GITHUB_REPOSITORY CLIUtils/CLI11
GIT_TAG v2.5.0
EXCLUDE_FROM_ALL ON
OPTIONS "CLI11_BUILD_TESTS OFF")
endif()
find_package(nlohmann_json 3.11.3 QUIET)
if(NOT nlohmann_json_FOUND)
add_subdirectory(external/nlohmann_json)
list(APPEND CMAKE_MODULE_PATH
"${CMAKE_CURRENT_SOURCE_DIR}/cmake.external/nlohmann_json")
find_package(nlohmann_json 3.11.3 REQUIRED)
message(STATUS "use vendor nlohmann_json ${nlohmann_json_VERSION}")
endif()
list(APPEND linyaps-box_LIBRARY_LINK_LIBRARIES PUBLIC
nlohmann_json::nlohmann_json)
find_package(CLI11 2.4.1 QUIET)
if(NOT CLI11_FOUND)
add_subdirectory(external/CLI11)
list(APPEND CMAKE_MODULE_PATH
"${CMAKE_CURRENT_SOURCE_DIR}/cmake.external/CLI11")
find_package(CLI11 2.4.1 REQUIRED)
message(STATUS "use vendor CLI11 ${CLI11_VERSION}")
endif()
list(APPEND linyaps-box_LIBRARY_LINK_LIBRARIES PUBLIC CLI11::CLI11)
add_library("${linyaps-box_LIBRARY}" STATIC ${linyaps-box_LIBRARY_SOURCE})
target_include_directories("${linyaps-box_LIBRARY}"
${linyaps-box_LIBRARY_INCLUDE_DIRS})
target_link_libraries("${linyaps-box_LIBRARY}"
PRIVATE ${linyaps-box_LIBRARY_LINK_LIBRARIES})
target_compile_features("${linyaps-box_LIBRARY}" PUBLIC cxx_std_17)
set_property(TARGET "${linyaps-box_LIBRARY}" PROPERTY CXX_STANDARD 17)
set_property(TARGET "${linyaps-box_LIBRARY}" PROPERTY CXX_EXTENSIONS OFF)
set_property(TARGET "${linyaps-box_LIBRARY}" PROPERTY CXX_STANDARD_REQUIRED ON)
include(CheckIncludeFileCXX)
check_include_file_cxx("linux/openat2.h" LINYAPS_BOX_HAVE_OPENAT2_H)
if(${LINYAPS_BOX_HAVE_OPENAT2_H})
target_compile_definitions("${linyaps-box_LIBRARY}"
PRIVATE "LINYAPS_BOX_HAVE_OPENAT2_H")
endif()
target_compile_definitions(
"${linyaps-box_LIBRARY}"
PRIVATE
"LINYAPS_BOX_CLONE_CHILD_STACK_SIZE=${linyaps-box_CLONE_CHILD_STACK_SIZE}"
PRIVATE "LINYAPS_BOX_STACK_GROWTH_DOWN=${linyaps-box_STACK_GROWTH_DOWN}"
PRIVATE "LINYAPS_BOX_DEFAULT_LOG_LEVEL=${linyaps-box_DEFAULT_LOG_LEVEL}"
PRIVATE "LINYAPS_BOX_ACTIVE_LOG_LEVEL=${linyaps-box_ACTIVE_LOG_LEVEL}")
target_compile_options("${linyaps-box_LIBRARY}"
PRIVATE -fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}=.)
if(linyaps-box_STATIC)
target_compile_definitions("${linyaps-box_LIBRARY}"
PUBLIC "LINYAPS_BOX_STATIC_LINK")
endif()
if(linyaps-box_ENABLE_SECCOMP)
target_compile_definitions("${linyaps-box_LIBRARY}"
PUBLIC LINYAPS_BOX_ENABLE_SECCOMP)
endif()
if(linyaps-box_ENABLE_CAP)
target_compile_definitions("${linyaps-box_LIBRARY}"
PUBLIC LINYAPS_BOX_ENABLE_CAP)
endif()
if(linyaps-box_ENABLE_COVERAGE)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_options("${linyaps-box_LIBRARY}"
PRIVATE -fprofile-instr-generate -fcoverage-mapping)
target_link_options("${linyaps-box_LIBRARY}" PUBLIC
-fprofile-instr-generate -fcoverage-mapping)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options("${linyaps-box_LIBRARY}" PRIVATE --coverage)
target_link_options("${linyaps-box_LIBRARY}" PUBLIC --coverage)
else()
message(
FATAL_ERROR "Coverage is not supported for ${CMAKE_CXX_COMPILER_ID}.")
endif()
endif()
# ==============================================================================
set(linyaps-box_APP ll-box)
set(linyaps-box_APP_SOURCE "./app/${linyaps-box_APP}/src/main.cpp")
set(linyaps-box_APP_LINK_LIBRARIES PRIVATE "${linyaps-box_LIBRARY}")
set(linyaps-box_APP_SOURCE_INCLUDE_DIRS
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/app/${linyaps-box_APP}/src")
add_executable("${linyaps-box_APP}" ${linyaps-box_APP_SOURCE})
target_include_directories("${linyaps-box_APP}"
${linyaps-box_APP_SOURCE_INCLUDE_DIRS})
target_link_libraries("${linyaps-box_APP}" ${linyaps-box_APP_LINK_LIBRARIES})
if(linyaps-box_STATIC)
target_link_options("${linyaps-box_APP}" PRIVATE -static -static-libgcc
-static-libstdc++)
endif()
target_compile_features("${linyaps-box_APP}" PRIVATE cxx_std_17)
set_property(TARGET "${linyaps-box_APP}" PROPERTY CXX_STANDARD 17)
set_property(TARGET "${linyaps-box_APP}" PROPERTY CXX_EXTENSIONS OFF)
set_property(TARGET "${linyaps-box_APP}" PROPERTY CXX_STANDARD_REQUIRED ON)
target_compile_definitions(
"${linyaps-box_APP}"
PRIVATE "LINYAPS_BOX_DEFAULT_LOG_LEVEL=${linyaps-box_DEFAULT_LOG_LEVEL}"
PRIVATE "LINYAPS_BOX_ACTIVE_LOG_LEVEL=${linyaps-box_AVTIVE_LOG_LEVEL}")
target_compile_options("${linyaps-box_APP}"
PRIVATE -fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}=.)
# ==============================================================================
include(GNUInstallDirs)
# parameter TYPE was added in CMake 3.14
if(CMAKE_VERSION VERSION_LESS "3.14")
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/${linyaps-box_APP}"
DESTINATION "${CMAKE_INSTALL_BINDIR}")
else()
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/${linyaps-box_APP}" TYPE BIN)
endif()
if(linyaps-box_ENABLE_CPACK)
set(CPACK_PACKAGING_INSTALL_PREFIX
"${linyaps-box_CPACK_PACKAGING_INSTALL_PREFIX}")
set(CPACK_PACKAGE_CONTACT "chenlinxuan@uniontech.com")
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_RPM_PACKAGE_AUTOREQ ON)
include(CPack)
endif()
# ==============================================================================
if(NOT linyaps-box_ENABLE_TESTING)
return()
endif()
enable_testing()
include(GoogleTest)
set(linyaps-box_UNIT_TESTS ll-box-ut)
set(linyaps-box_UNIT_TESTS_SOURCE ./tests/ll-box-ut/src/test.cpp)
set(linyaps-box_UNIT_TESTS_LINK_LIBRARIES PRIVATE "${linyaps-box_LIBRARY}")
set(linyaps-box_UNIT_TESTS_SOURCE_INCLUDE_DIRS
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/tests/ll-box-ut/src")
find_package(GTest REQUIRED)
if(CMAKE_VERSION VERSION_LESS 3.20)
add_library(GTest::gtest_main INTERFACE IMPORTED)
target_link_libraries(GTest::gtest_main INTERFACE GTest::Main)
endif()
list(APPEND linyaps-box_UNIT_TESTS_LINK_LIBRARIES PRIVATE GTest::gtest_main)
add_executable("${linyaps-box_UNIT_TESTS}" ${linyaps-box_UNIT_TESTS_SOURCE})
target_include_directories("${linyaps-box_UNIT_TESTS}"
${linyaps-box_UNIT_TESTS_SOURCE_INCLUDE_DIRS})
target_link_libraries("${linyaps-box_UNIT_TESTS}"
${linyaps-box_UNIT_TESTS_LINK_LIBRARIES})
target_compile_features("${linyaps-box_UNIT_TESTS}" PRIVATE cxx_std_17)
set_property(TARGET "${linyaps-box_UNIT_TESTS}" PROPERTY CXX_STANDARD 17)
set_property(TARGET "${linyaps-box_UNIT_TESTS}" PROPERTY CXX_EXTENSIONS OFF)
set_property(TARGET "${linyaps-box_UNIT_TESTS}" PROPERTY CXX_STANDARD_REQUIRED
ON)
target_compile_options("${linyaps-box_UNIT_TESTS}"
PRIVATE -fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}=.)
set(GTEST_DISCOVER_TESTS_ARGS "${linyaps-box_UNIT_TESTS}" WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}/tests/ll-box-ut")
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
list(APPEND GTEST_DISCOVER_TESTS_ARGS PROPERTIES ENVIRONMENT
"LLVM_PROFILE_FILE=/dev/null")
endif()
gtest_discover_tests(${GTEST_DISCOVER_TESTS_ARGS})
function(setup_linyaps_box_smoke_tests)
if(NOT linyaps-box_ENABLE_SMOKE_TESTS)
return()
endif()
set(linyaps-box_SMOKE_TESTS
./tests/ll-box-st/01-run-whoami.json
./tests/ll-box-st/02-check-procfs.json
./tests/ll-box-st/03-check-mounts.json
./tests/ll-box-st/04-check-noNewPrivs.json
./tests/ll-box-st/05-check-env.json
./tests/ll-box-st/06-check-cwd.json
./tests/ll-box-st/07-check-capability.json
./tests/ll-box-st/08-check-umask.json
./tests/ll-box-st/09-check-rlimit.json
./tests/ll-box-st/10-check-oom.json
./tests/ll-box-st/11-output-to-null.json
./tests/ll-box-st/12-bind-host-dev.json)
foreach(test ${linyaps-box_SMOKE_TESTS})
add_test(
NAME "${test}"
COMMAND
"${CMAKE_CURRENT_SOURCE_DIR}/tests/ll-box-st/ll-box-st"
"${CMAKE_CURRENT_BINARY_DIR}/${linyaps-box_APP}"
"${CMAKE_CURRENT_BINARY_DIR}/st-data"
"${CMAKE_CURRENT_SOURCE_DIR}/${test}")
list(APPEND linyaps-box_TESTS "${test}")
set_tests_properties(
"${test}"
PROPERTIES
ENVIRONMENT
"LSAN_OPTIONS=suppressions=${CMAKE_CURRENT_LIST_DIR}/tests/ll-box-st/glibc_leaks.txt"
)
endforeach()
endfunction()
setup_linyaps_box_smoke_tests()
function(setup_linyaps_box_coverage)
if(NOT linyaps-box_ENABLE_COVERAGE)
return()
endif()
set(COVERAGE_INFO "coverage.info")
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set_tests_properties(
${linyaps-box_TESTS}
PROPERTIES ENVIRONMENT
"LLVM_PROFILE_FILE=${CMAKE_CURRENT_BINARY_DIR}/default.profraw"
)
find_program(LLVM_PROFDATA llvm-profdata REQUIRED)
add_custom_command(
OUTPUT default.profdata
DEPENDS "${linyaps-box_APP}" test
COMMAND "${LLVM_PROFDATA}" merge -sparse default.profraw -o
default.profdata)
find_program(LLVM_COV llvm-cov REQUIRED)
add_custom_command(
OUTPUT coverage.info
DEPENDS default.profdata
COMMAND "${LLVM_COV}" show -instr-profile=default.profdata
-object="$<TARGET_FILE_NAME:${linyaps-box_APP}>" > coverage.info)
add_custom_command(
OUTPUT coverage.tar.gz
DEPENDS default.profdata
COMMAND rm -rf coverage
COMMAND
"${LLVM_COV}" show -instr-profile=default.profdata -format=html
-object="$<TARGET_FILE_NAME:${linyaps-box_APP}>" -output-dir=coverage
COMMAND tar -czf coverage-html.tar.gz coverage)
add_custom_target(coverage DEPENDS coverage.info coverage.tar.gz)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
find_program(LCOV lcov REQUIRED)
find_program(SED sed REQUIRED)
add_custom_target(
coverage
COMMAND "${LCOV}" --capture --directory . --output-file coverage.info
--branch-coverage --rc geninfo_unexecuted_blocks=1
COMMAND "${LCOV}" --remove coverage.info '/usr/*' --output-file
coverage.info
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
DEPENDS "${linyaps-box_APP}" test)
else()
message(
FATAL_ERROR "Coverage is not supported for ${CMAKE_CXX_COMPILER_ID}.")
endif()
endfunction()
setup_linyaps_box_coverage()