From 5b80abbc729e94abb5f5776a3438ad57d480c097 Mon Sep 17 00:00:00 2001 From: Alastair Harrison Date: Thu, 27 Aug 2020 21:47:27 +0100 Subject: CMake: Add support for "browse" mode Fixes ninja-build/ninja#1822, fixes ninja-build/ninja#1853 Adds support for `ninja -t browse` to CMake builds. The platform support logic is copied from configure.py, so Windows, Solaris and AIX are treated as 'unsupported' platforms. All other platforms are assumed to be supported. As discussed in #1853, when built via CMake the `ninja` executable looks for a binary called `python` in the current path, in order to launch the "browse" mode. The behaviour differs from that of the configure.py script, which looks for a python executable that has the *same name* as the python executable that invoked the configure script. --- CMakeLists.txt | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 65e42a4..d132965 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,18 @@ else() endif() target_include_directories(libninja-re2c PRIVATE src) +# --- Check for 'browse' mode support +set(unsupported_browse_platforms + "Windows" + "SunOS" + "AIX" +) +if(${CMAKE_SYSTEM_NAME} IN_LIST unsupported_browse_platforms) + set(platform_supports_ninja_browse FALSE) +else() + set(platform_supports_ninja_browse TRUE) +endif() + # Core source files all build into ninja library. add_library(libninja OBJECT src/build_log.cc @@ -96,6 +108,32 @@ endif() add_executable(ninja src/ninja.cc) target_link_libraries(ninja PRIVATE libninja libninja-re2c) +# Adds browse mode into the ninja binary if it's supported by the host platform. +if(platform_supports_ninja_browse) + # Inlines src/browse.py into the browse_py.h header, so that it can be included + # by src/browse.cc + add_custom_command( + OUTPUT build/browse_py.h + MAIN_DEPENDENCY src/browse.py + DEPENDS src/inline.sh + COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/build + COMMAND src/inline.sh kBrowsePy + < src/browse.py + > ${CMAKE_BINARY_DIR}/build/browse_py.h + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + VERBATIM + ) + + target_compile_definitions(ninja PRIVATE NINJA_HAVE_BROWSE) + target_sources(ninja PRIVATE src/browse.cc) + set_source_files_properties(src/browse.cc + PROPERTIES + OBJECT_DEPENDS "${CMAKE_BINARY_DIR}/build/browse_py.h" + INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}" + COMPILE_DEFINITIONS NINJA_PYTHON="python" + ) +endif() + # Tests all build into ninja_test executable. add_executable(ninja_test src/build_log_test.cc -- cgit v1.2.1 From 67f960be1be8099ea1727af8d3361d38274b2bd1 Mon Sep 17 00:00:00 2001 From: Alastair Harrison Date: Fri, 28 Aug 2020 11:53:58 +0100 Subject: Improve error handling in inline.sh Previously the script would generate some output and return a zero error code, even if the calls to `od` or `sed` failed. This change ensures that: - If `od` or `sed` fail then the script will fail. - Output will only be written on success. --- src/inline.sh | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/inline.sh b/src/inline.sh index b64e8ca..5092fa2 100755 --- a/src/inline.sh +++ b/src/inline.sh @@ -19,7 +19,14 @@ # stdin and writes stdout. varname="$1" -echo "const char $varname[] =" -od -t x1 -A n -v | sed -e 's|^[\t ]\{0,\}$||g; s|[\t ]\{1,\}| |g; s| \{1,\}$||g; s| |\\x|g; s|^|"|; s|$|"|' -echo ";" +# 'od' and 'sed' may not be available on all platforms, and may not support the +# flags used here. We must ensure that the script exits with a non-zero exit +# code in those cases. +byte_vals=$(od -t x1 -A n -v) || exit 1 +escaped_byte_vals=$(echo "${byte_vals}" \ + | sed -e 's|^[\t ]\{0,\}$||g; s|[\t ]\{1,\}| |g; s| \{1,\}$||g; s| |\\x|g; s|^|"|; s|$|"|') \ + || exit 1 + +# Only write output once we have successfully generated the required data +printf "const char %s[] = \n%s;" "${varname}" "${escaped_byte_vals}" -- cgit v1.2.1 From 0b5f5ba91020668856f87f079a61380198540bd7 Mon Sep 17 00:00:00 2001 From: Alastair Harrison Date: Fri, 28 Aug 2020 11:58:43 +0100 Subject: CMake: Add platform checks for browse mode support Browse mode requires a number of POSIX features to be available. This commit adds configure-time checks that the 'unistd.h' header is available and that the `inline.sh` script executes successfully. If the checks pass then browse mode is enabled. --- CMakeLists.txt | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d132965..b0c0911 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.15) + +include(CheckIncludeFileCXX) + project(ninja) # --- optional link-time optimization @@ -49,16 +52,28 @@ endif() target_include_directories(libninja-re2c PRIVATE src) # --- Check for 'browse' mode support -set(unsupported_browse_platforms - "Windows" - "SunOS" - "AIX" -) -if(${CMAKE_SYSTEM_NAME} IN_LIST unsupported_browse_platforms) - set(platform_supports_ninja_browse FALSE) -else() - set(platform_supports_ninja_browse TRUE) -endif() +function(check_platform_supports_browse_mode RESULT) + # Make sure the inline.sh script works on this platform. + # It uses the shell commands such as 'od', which may not be available. + execute_process( + COMMAND sh -c "echo 'TEST' | src/inline.sh var" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE inline_result + OUTPUT_QUIET + ERROR_QUIET + ) + if(NOT inline_result EQUAL "0") + # The inline script failed, so browse mode is not supported. + set(${RESULT} "0" PARENT_SCOPE) + return() + endif() + + # Now check availability of the unistd header + check_include_file_cxx(unistd.h PLATFORM_HAS_UNISTD_HEADER) + set(${RESULT} "${PLATFORM_HAS_UNISTD_HEADER}" PARENT_SCOPE) +endfunction() + +check_platform_supports_browse_mode(platform_supports_ninja_browse) # Core source files all build into ninja library. add_library(libninja OBJECT -- cgit v1.2.1