summaryrefslogtreecommitdiffstats
path: root/CMakeLists.txt
blob: 7f03c3599c876a31721db0963b2205f98fc4ffa7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
cmake_minimum_required(VERSION 3.15)

include(CheckIncludeFileCXX)
include(CheckIPOSupported)

project(ninja)

# --- optional link-time optimization
check_ipo_supported(RESULT lto_supported OUTPUT error)

if(lto_supported)
	message(STATUS "IPO / LTO enabled")
	set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
else()
	message(STATUS "IPO / LTO not supported: <${error}>")
endif()

# --- compiler flags
if(MSVC)
	set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
	string(APPEND CMAKE_CXX_FLAGS " /W4 /GR- /Zc:__cplusplus")
else()
	include(CheckCXXCompilerFlag)
	check_cxx_compiler_flag(-Wno-deprecated flag_no_deprecated)
	if(flag_no_deprecated)
		string(APPEND CMAKE_CXX_FLAGS " -Wno-deprecated")
	endif()
	check_cxx_compiler_flag(-fdiagnostics-color flag_color_diag)
	if(flag_color_diag)
		string(APPEND CMAKE_CXX_FLAGS " -fdiagnostics-color")
	endif()
endif()

# --- optional re2c
find_program(RE2C re2c)
if(RE2C)
	# the depfile parser and ninja lexers are generated using re2c.
	function(re2c IN OUT)
		add_custom_command(DEPENDS ${IN} OUTPUT ${OUT}
			COMMAND ${RE2C} -b -i --no-generation-date -o ${OUT} ${IN}
		)
	endfunction()
	re2c(${PROJECT_SOURCE_DIR}/src/depfile_parser.in.cc ${PROJECT_BINARY_DIR}/depfile_parser.cc)
	re2c(${PROJECT_SOURCE_DIR}/src/lexer.in.cc ${PROJECT_BINARY_DIR}/lexer.cc)
	add_library(libninja-re2c OBJECT ${PROJECT_BINARY_DIR}/depfile_parser.cc ${PROJECT_BINARY_DIR}/lexer.cc)
else()
	message(WARNING "re2c was not found; changes to src/*.in.cc will not affect your build.")
	add_library(libninja-re2c OBJECT src/depfile_parser.cc src/lexer.cc)
endif()
target_include_directories(libninja-re2c PRIVATE src)

# --- Check for 'browse' mode support
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
	src/build_log.cc
	src/build.cc
	src/clean.cc
	src/clparser.cc
	src/dyndep.cc
	src/dyndep_parser.cc
	src/debug_flags.cc
	src/deps_log.cc
	src/disk_interface.cc
	src/edit_distance.cc
	src/eval_env.cc
	src/graph.cc
	src/graphviz.cc
	src/line_printer.cc
	src/manifest_parser.cc
	src/metrics.cc
	src/parser.cc
	src/state.cc
	src/string_piece_util.cc
	src/util.cc
	src/version.cc
)
if(WIN32)
	target_sources(libninja PRIVATE
		src/subprocess-win32.cc
		src/includes_normalize-win32.cc
		src/msvc_helper-win32.cc
		src/msvc_helper_main-win32.cc
		src/getopt.c
	)
	if(MSVC)
		target_sources(libninja PRIVATE src/minidump-win32.cc)
	endif()
else()
	target_sources(libninja PRIVATE src/subprocess-posix.cc)
	if(CMAKE_SYSTEM_NAME STREQUAL "OS400" OR CMAKE_SYSTEM_NAME STREQUAL "AIX")
		target_sources(libninja PRIVATE src/getopt.c)
	endif()

	# Needed for perfstat_cpu_total
	if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
		target_link_libraries(libninja PUBLIC "-lperfstat")
	endif()
endif()

#Fixes GetActiveProcessorCount on MinGW
if(MINGW)
target_compile_definitions(libninja PRIVATE _WIN32_WINNT=0x0601 __USE_MINGW_ANSI_STDIO=1)
endif()

# On IBM i (identified as "OS400" for compatibility reasons) and AIX, this fixes missing
# PRId64 (and others) at compile time in C++ sources
if(CMAKE_SYSTEM_NAME STREQUAL "OS400" OR CMAKE_SYSTEM_NAME STREQUAL "AIX")
	string(APPEND CMAKE_CXX_FLAGS " -D__STDC_FORMAT_MACROS")
endif()

# Main executable is library plus main() function.
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_COMMAND} -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()

include(CTest)
if(BUILD_TESTING)
  # Tests all build into ninja_test executable.
  add_executable(ninja_test
    src/build_log_test.cc
    src/build_test.cc
    src/clean_test.cc
    src/clparser_test.cc
    src/depfile_parser_test.cc
    src/deps_log_test.cc
    src/disk_interface_test.cc
    src/dyndep_parser_test.cc
    src/edit_distance_test.cc
    src/graph_test.cc
    src/lexer_test.cc
    src/manifest_parser_test.cc
    src/ninja_test.cc
    src/state_test.cc
    src/string_piece_util_test.cc
    src/subprocess_test.cc
    src/test.cc
    src/util_test.cc
  )
  if(WIN32)
    target_sources(ninja_test PRIVATE src/includes_normalize_test.cc src/msvc_helper_test.cc)
  endif()
  target_link_libraries(ninja_test PRIVATE libninja libninja-re2c)

  foreach(perftest
    build_log_perftest
    canon_perftest
    clparser_perftest
    depfile_parser_perftest
    hash_collision_bench
    manifest_parser_perftest
  )
    add_executable(${perftest} src/${perftest}.cc)
    target_link_libraries(${perftest} PRIVATE libninja libninja-re2c)
  endforeach()

  if(CMAKE_SYSTEM_NAME STREQUAL "AIX" AND CMAKE_SIZEOF_VOID_P EQUAL 4)
    # These tests require more memory than will fit in the standard AIX shared stack/heap (256M)
    target_link_libraries(hash_collision_bench PRIVATE "-Wl,-bmaxdata:0x80000000")
    target_link_libraries(manifest_parser_perftest PRIVATE "-Wl,-bmaxdata:0x80000000")
  endif()

  add_test(NinjaTest ninja_test)
endif()

install(TARGETS ninja DESTINATION bin)