diff --git a/.gitignore b/.gitignore index da59f79..cf01227 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ install-sh ltmain.sh missing test-driver + +/build/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..aac8db4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,115 @@ +cmake_minimum_required(VERSION 3.10) +set(project_name noshell) + +set(NOSHELL_MASTER_PROJECT OFF) +if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(NOSHELL_MASTER_PROJECT ON) +endif() + +option(NOSHELL_BUILD_TESTS "Set to ON to build tests" ${NOSHELL_MASTER_PROJECT}) +option(NOSHELL_ENABLE_INSTALL "Generate the install target" ${NOSHELL_MASTER_PROJECT}) + +# get version +file(READ "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" configure_ac) +string(REGEX MATCH "AC_INIT\\\(\\\[noshell\\\],\\\[(.*)\\\],\\\[gmarcais@cmu.edu\\\]\\\)" _ "${configure_ac}") +if(NOT CMAKE_MATCH_COUNT EQUAL 1) + message(FATAL_ERROR "Could not extract major version number from configure.ac") +endif() +set(noshell_version ${CMAKE_MATCH_1}) +message(STATUS "noshell version: ${noshell_version}") + + +project(${project_name} VERSION "${noshell_version}" LANGUAGES CXX) + +include(GNUInstallDirs) + +set(NOSHELL_SRCS lib/noshell.cc lib/setters.cc lib/utils.cc) + +add_library(${project_name} SHARED ${NOSHELL_SRCS}) +add_library(${project_name}-static STATIC ${NOSHELL_SRCS}) +add_library(${project_name}::${project_name} ALIAS ${project_name}) +add_library(${project_name}::${project_name}-static ALIAS ${project_name}-static) + +target_include_directories(${project_name} + PUBLIC + $ + $) +target_include_directories(${project_name}-static + PUBLIC + $ + $) +set_target_properties(${project_name} + PROPERTIES + CXX_STANDARD 11) +set_target_properties(${project_name}-static + PROPERTIES + CXX_STANDARD 11 + POSITION_INDEPENDENT_CODE 1 + OUTPUT_NAME ${project_name}) + +if(NOSHELL_ENABLE_INSTALL) + set(project_config_in "${CMAKE_CURRENT_LIST_DIR}/noshellConfig.cmake.in") + set(project_config_out "${CMAKE_CURRENT_BINARY_DIR}/noshellConfig.cmake") + set(config_targets_file "noshellConfigTargets.cmake") + set(version_config_file "${CMAKE_CURRENT_BINARY_DIR}/noshellConfigVersion.cmake") + set(export_dest_dir "${CMAKE_INSTALL_LIBDIR}/cmake/noshell") + set(pkgconfig_install_dir "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + set(pkgconfig "${CMAKE_CURRENT_BINARY_DIR}/noshell.pc") + + set(prefix "${CMAKE_INSTALL_PREFIX}") + set(exec_prefix "\${prefix}") + if (IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") + set(libdir "${CMAKE_INSTALL_LIBDIR}") + else() + set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") + endif() + if (IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") + set(includedir "${CMAKE_INSTALL_INCLUDEDIR}") + else() + set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") + endif() + set(PACKAGE_VERSION "${noshell_version}") + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/noshell.pc.in" + "${pkgconfig}" + @ONLY) + + install(FILES "${pkgconfig}" + DESTINATION "${pkgconfig_install_dir}") + + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/noshell-${noshell_version}") + + install(TARGETS ${project_name} ${project_name}-static + EXPORT ${project_name} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + export( + TARGETS ${project_name} + NAMESPACE ${project_name}:: + FILE "${CMAKE_CURRENT_BINARY_DIR}/${config_targets_file}") + + install(EXPORT ${project_name} + DESTINATION ${export_dest_dir} + NAMESPACE ${project_name}:: + FILE ${config_targets_file}) + + include(CMakePackageConfigHelpers) + configure_package_config_file("${project_config_in}" "${project_config_out}" + INSTALL_DESTINATION ${export_dest_dir}) + + + write_basic_package_version_file("${version_config_file}" + VERSION "${noshell_version}" + COMPATIBILITY ExactVersion) + + install(FILES "${project_config_out}" "${version_config_file}" DESTINATION "${export_dest_dir}") +endif() + + +if(NOSHELL_BUILD_TESTS) + enable_testing() + add_subdirectory(tests) +endif() diff --git a/README.md b/README.md index 47df1ba..5a443ea 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,23 @@ sudo make install At this point, this library has only been tested on Linux, with `g++` version 4.7 or newer and `clang++` version 3.2. +### CMake + +Alternatively, you can use CMake to build the library: + +```sh +mkdir build +cmake -S . -B build +cmake --build build +sudo cmake --install build +``` + +Run the tests with: + +```sh +cd build && ctest +``` + ## Using the library Add the following to your make file: @@ -86,3 +103,17 @@ Add the following to your make file: CXXFLAGS = $(shell pkg-config --cflags noshell) LDFLAGS = $(shell pkg-config --libs noshell) ``` + +### CMake + +Add the following to your `CMakeLists.txt`: + +```cmake +find_package(noshell REQUIRED) + +# link shared library +target_link_libraries(mytarget noshell::noshell) + +# link static library +target_link_libraries(mytarget noshell::noshell-static) +``` diff --git a/include/noshell/handle.hpp b/include/noshell/handle.hpp index f97e878..ac442bf 100644 --- a/include/noshell/handle.hpp +++ b/include/noshell/handle.hpp @@ -152,7 +152,7 @@ class Exit { void wait() { for(auto& h : handles) h.wait(); } }; -std::ostream& operator<<(std::ostream& os, const Exit& exit) { +inline std::ostream& operator<<(std::ostream& os, const Exit& exit) { auto it = exit.begin(); if(it != exit.end()) { os << *it; diff --git a/noshellConfig.cmake.in b/noshellConfig.cmake.in new file mode 100644 index 0000000..397ea9a --- /dev/null +++ b/noshellConfig.cmake.in @@ -0,0 +1,6 @@ +@PACKAGE_INIT@ + +set(config_targets_file @config_targets_file@) +include("${CMAKE_CURRENT_LIST_DIR}/${config_targets_file}") + +check_required_components(noshell) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..cb49b07 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.10) +project(noshell_tests CXX) + +if(NOT TARGET noshell) + # Stand-alone build + find_package(noshell REQUIRED) +endif() + +list(APPEND NOSHELL_TESTS_HELPER + check_open_fd.cc + kill_self.cc + puts_to.cc) + +list(APPEND NOSHELL_TESTS_LIST + libtest_misc.cc + test_cmd_redirection.cc + test_error.cc + test_extra_fds.cc + test_fd_type.cc + test_literal.cc + test_pipeline.cc + test_resources.cc + test_simple_command.cc) + +find_package(GTest REQUIRED) +find_package(Threads REQUIRED) + +foreach(src ${NOSHELL_TESTS_HELPER}) + GET_FILENAME_COMPONENT(target_name ${src} NAME_WE) + add_executable(${target_name} ${src}) +endforeach() + +add_executable(noshell_tests ${NOSHELL_TESTS_LIST}) +target_link_libraries(noshell_tests GTest::Main GTest::GTest Threads::Threads noshell::noshell) + +add_test(noshell_tests noshell_tests)