1cmake_minimum_required(VERSION 3.15) 2 3include(CheckSymbolExists) 4include(CheckIPOSupported) 5 6project(ninja) 7 8# --- optional link-time optimization 9check_ipo_supported(RESULT lto_supported OUTPUT error) 10 11if(lto_supported) 12 message(STATUS "IPO / LTO enabled") 13 set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE) 14else() 15 message(STATUS "IPO / LTO not supported: <${error}>") 16endif() 17 18# --- compiler flags 19if(MSVC) 20 set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") 21 string(REPLACE "/GR" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) 22 add_compile_options(/W4 /wd4100 /wd4267 /wd4706 /wd4702 /wd4244 /GR- /Zc:__cplusplus) 23 add_compile_definitions(_CRT_SECURE_NO_WARNINGS) 24else() 25 include(CheckCXXCompilerFlag) 26 check_cxx_compiler_flag(-Wno-deprecated flag_no_deprecated) 27 if(flag_no_deprecated) 28 add_compile_options(-Wno-deprecated) 29 endif() 30 check_cxx_compiler_flag(-fdiagnostics-color flag_color_diag) 31 if(flag_color_diag) 32 add_compile_options(-fdiagnostics-color) 33 endif() 34endif() 35 36# --- optional re2c 37find_program(RE2C re2c) 38if(RE2C) 39 # the depfile parser and ninja lexers are generated using re2c. 40 function(re2c IN OUT) 41 add_custom_command(DEPENDS ${IN} OUTPUT ${OUT} 42 COMMAND ${RE2C} -b -i --no-generation-date --no-version -o ${OUT} ${IN} 43 ) 44 endfunction() 45 re2c(${PROJECT_SOURCE_DIR}/src/depfile_parser.in.cc ${PROJECT_BINARY_DIR}/depfile_parser.cc) 46 re2c(${PROJECT_SOURCE_DIR}/src/lexer.in.cc ${PROJECT_BINARY_DIR}/lexer.cc) 47 add_library(libninja-re2c OBJECT ${PROJECT_BINARY_DIR}/depfile_parser.cc ${PROJECT_BINARY_DIR}/lexer.cc) 48else() 49 message(WARNING "re2c was not found; changes to src/*.in.cc will not affect your build.") 50 add_library(libninja-re2c OBJECT src/depfile_parser.cc src/lexer.cc) 51endif() 52target_include_directories(libninja-re2c PRIVATE src) 53 54# --- Check for 'browse' mode support 55function(check_platform_supports_browse_mode RESULT) 56 # Make sure the inline.sh script works on this platform. 57 # It uses the shell commands such as 'od', which may not be available. 58 59 execute_process( 60 COMMAND sh -c "echo 'TEST' | src/inline.sh var" 61 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 62 RESULT_VARIABLE inline_result 63 OUTPUT_QUIET 64 ERROR_QUIET 65 ) 66 if(NOT inline_result EQUAL "0") 67 # The inline script failed, so browse mode is not supported. 68 set(${RESULT} "0" PARENT_SCOPE) 69 if(NOT WIN32) 70 message(WARNING "browse feature omitted due to inline script failure") 71 endif() 72 return() 73 endif() 74 75 # Now check availability of the unistd header 76 check_symbol_exists(fork "unistd.h" HAVE_FORK) 77 check_symbol_exists(pipe "unistd.h" HAVE_PIPE) 78 set(browse_supported 0) 79 if (HAVE_FORK AND HAVE_PIPE) 80 set(browse_supported 1) 81 endif () 82 set(${RESULT} "${browse_supported}" PARENT_SCOPE) 83 if(NOT browse_supported) 84 message(WARNING "browse feature omitted due to missing `fork` and `pipe` functions") 85 endif() 86 87endfunction() 88 89check_platform_supports_browse_mode(platform_supports_ninja_browse) 90 91# Core source files all build into ninja library. 92add_library(libninja OBJECT 93 src/build_log.cc 94 src/build.cc 95 src/clean.cc 96 src/clparser.cc 97 src/dyndep.cc 98 src/dyndep_parser.cc 99 src/debug_flags.cc 100 src/deps_log.cc 101 src/disk_interface.cc 102 src/edit_distance.cc 103 src/eval_env.cc 104 src/graph.cc 105 src/graphviz.cc 106 src/json.cc 107 src/line_printer.cc 108 src/manifest_parser.cc 109 src/metrics.cc 110 src/missing_deps.cc 111 src/parser.cc 112 src/state.cc 113 src/status.cc 114 src/string_piece_util.cc 115 src/util.cc 116 src/version.cc 117) 118if(WIN32) 119 target_sources(libninja PRIVATE 120 src/subprocess-win32.cc 121 src/includes_normalize-win32.cc 122 src/msvc_helper-win32.cc 123 src/msvc_helper_main-win32.cc 124 src/getopt.c 125 src/minidump-win32.cc 126 ) 127else() 128 target_sources(libninja PRIVATE src/subprocess-posix.cc) 129 if(CMAKE_SYSTEM_NAME STREQUAL "OS400" OR CMAKE_SYSTEM_NAME STREQUAL "AIX") 130 target_sources(libninja PRIVATE src/getopt.c) 131 endif() 132 133 # Needed for perfstat_cpu_total 134 if(CMAKE_SYSTEM_NAME STREQUAL "AIX") 135 target_link_libraries(libninja PUBLIC "-lperfstat") 136 endif() 137endif() 138 139#Fixes GetActiveProcessorCount on MinGW 140if(MINGW) 141target_compile_definitions(libninja PRIVATE _WIN32_WINNT=0x0601 __USE_MINGW_ANSI_STDIO=1) 142endif() 143 144# On IBM i (identified as "OS400" for compatibility reasons) and AIX, this fixes missing 145# PRId64 (and others) at compile time in C++ sources 146if(CMAKE_SYSTEM_NAME STREQUAL "OS400" OR CMAKE_SYSTEM_NAME STREQUAL "AIX") 147 add_compile_definitions(__STDC_FORMAT_MACROS) 148endif() 149 150# Main executable is library plus main() function. 151add_executable(ninja src/ninja.cc) 152target_link_libraries(ninja PRIVATE libninja libninja-re2c) 153 154if(WIN32) 155 target_sources(ninja PRIVATE windows/ninja.manifest) 156endif() 157 158# Adds browse mode into the ninja binary if it's supported by the host platform. 159if(platform_supports_ninja_browse) 160 # Inlines src/browse.py into the browse_py.h header, so that it can be included 161 # by src/browse.cc 162 add_custom_command( 163 OUTPUT build/browse_py.h 164 MAIN_DEPENDENCY src/browse.py 165 DEPENDS src/inline.sh 166 COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/build 167 COMMAND src/inline.sh kBrowsePy 168 < src/browse.py 169 > ${PROJECT_BINARY_DIR}/build/browse_py.h 170 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 171 VERBATIM 172 ) 173 174 target_compile_definitions(ninja PRIVATE NINJA_HAVE_BROWSE) 175 target_sources(ninja PRIVATE src/browse.cc) 176 set_source_files_properties(src/browse.cc 177 PROPERTIES 178 OBJECT_DEPENDS "${PROJECT_BINARY_DIR}/build/browse_py.h" 179 INCLUDE_DIRECTORIES "${PROJECT_BINARY_DIR}" 180 COMPILE_DEFINITIONS NINJA_PYTHON="python" 181 ) 182endif() 183 184include(CTest) 185if(BUILD_TESTING) 186 # Tests all build into ninja_test executable. 187 add_executable(ninja_test 188 src/build_log_test.cc 189 src/build_test.cc 190 src/clean_test.cc 191 src/clparser_test.cc 192 src/depfile_parser_test.cc 193 src/deps_log_test.cc 194 src/disk_interface_test.cc 195 src/dyndep_parser_test.cc 196 src/edit_distance_test.cc 197 src/graph_test.cc 198 src/json_test.cc 199 src/lexer_test.cc 200 src/manifest_parser_test.cc 201 src/missing_deps_test.cc 202 src/ninja_test.cc 203 src/state_test.cc 204 src/string_piece_util_test.cc 205 src/subprocess_test.cc 206 src/test.cc 207 src/util_test.cc 208 ) 209 if(WIN32) 210 target_sources(ninja_test PRIVATE src/includes_normalize_test.cc src/msvc_helper_test.cc) 211 endif() 212 target_link_libraries(ninja_test PRIVATE libninja libninja-re2c) 213 214 foreach(perftest 215 build_log_perftest 216 canon_perftest 217 clparser_perftest 218 depfile_parser_perftest 219 hash_collision_bench 220 manifest_parser_perftest 221 ) 222 add_executable(${perftest} src/${perftest}.cc) 223 target_link_libraries(${perftest} PRIVATE libninja libninja-re2c) 224 endforeach() 225 226 if(CMAKE_SYSTEM_NAME STREQUAL "AIX" AND CMAKE_SIZEOF_VOID_P EQUAL 4) 227 # These tests require more memory than will fit in the standard AIX shared stack/heap (256M) 228 target_link_options(hash_collision_bench PRIVATE "-Wl,-bmaxdata:0x80000000") 229 target_link_options(manifest_parser_perftest PRIVATE "-Wl,-bmaxdata:0x80000000") 230 endif() 231 232 add_test(NAME NinjaTest COMMAND ninja_test) 233endif() 234 235install(TARGETS ninja) 236