aboutsummaryrefslogtreecommitdiff
path: root/CMakeLists.txt
blob: 5ada0e21eedf19f5e6233a89af177cfe1328f2aa (about) (plain) (blame)
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
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#
# InspIRCd -- Internet Relay Chat Daemon
#
#   Copyright (C) 2026 Sadie Powell <sadie@witchery.services>
#
# This file is part of InspIRCd.  InspIRCd is free software: you can
# redistribute it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

cmake_minimum_required(VERSION 3.25 FATAL_ERROR)

project("InspIRCd" LANGUAGES "C" "CXX")

include("CheckFunctionExists")

# Include our custom CMake modules.
list(PREPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/src/cmake")
include("inspircd")
include("version")

# Require C++20 for all targets.
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# This is the C version equivalent to the C++ version we use.
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED ON)

# Enable -fPIC for all targets.
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# Enable -fvisibility for all targets.
set(CMAKE_CXX_VISIBILITY_PRESET "hidden")
set(CMAKE_VISIBILITY_INLINES_HIDDEN YES)

if(NOT CMAKE_BUILD_TYPE)
	message(STATUS "CMAKE_BUILD_TYPE has not been specified; defaulting to Release")
	update_cache(CMAKE_BUILD_TYPE "Release")
endif()

if(CMAKE_BUILD_TYPE MATCHES "^(Debug|RelWithDebInfo)$")
	set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
endif()

if(WIN32)
	add_compile_definitions(
		"_WIN32_WINNT=0x0A00"      # Set the minimum OS to Windows 10.
		"FD_SETSIZE=24000"         # Increase the default socket limit to something reasonable.
		"NOMINMAX"                 # Avoid the Windows API breaking std::{min,max}
		"NTDDI_VERSION=0x0A000005" # Set the minimum OS to Windows 10 1803 "Redstone 4"
		"WIN32_LEAN_AND_MEAN"      # Trim down the size of the included headers.
	)
else()
	# On non-Windows we find a lot of our dependencies with pkg-config.
	find_package("PkgConfig")
	if(CMAKE_SYSTEM_NAME STREQUAL "Haiku")
		# On Haiku we need _DEFAULT_SOURCE for common C extensions and libnetwork for creating
		# sockets.
		add_compile_definitions("_DEFAULT_SOURCE")
		link_libraries("network")
	elseif(CMAKE_SYSTEM_NAME MATCHES "SunOS")
		# On Solaris and derivatives we need libsocket for creating sockets.
		link_libraries("socket")
	endif()
endif()

if(CMAKE_CXX_COMPILER_ID MATCHES "(^GNU|Clang)$")
	add_compile_options(
		"-Wall" "-Wextra" "-Wfatal-errors" "-Wpedantic"
		"-Wno-unused-parameter"
		"$<$<COMPILE_LANGUAGE:CXX>:-Woverloaded-virtual>"
		"$<$<CONFIG:Debug>:-g3;-Werror>"
		"$<$<CONFIG:Release,RelWithDebInfo>:-g1>"
		"$<$<NOT:$<CONFIG:Debug,None>>:-fno-rtti>"
	)
	if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
		add_compile_options(
			"-Wshadow"
			"$<$<COMPILE_LANGUAGE:CXX>:-Wno-subobject-linkage>"
		)
	elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang$")
		add_compile_options("-Wshadow-all" "-Wshorten-64-to-32")
	endif()
elseif(MSVC)
	# On MSVC we need to set the character set to UTF-8 so {fmt} unicode support works.
	add_compile_options("/utf-8")
endif()

if(NOT WIN32)
	option(PORTABLE "Whether to install portably" OFF)
	option(SYSTEM "Whether to install system-wide" OFF)
	if(PORTABLE AND SYSTEM)
		message(FATAL_ERROR "PORTABLE and SYSTEM can not be used together!")
	endif()
	if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
		if(PORTABLE)
			# Portable installs use relative paths for relocatability.
			update_cache(CMAKE_INSTALL_PREFIX "run")
		elseif(SYSTEM)
			# System installs all have paths relative to the root.
			update_cache(CMAKE_INSTALL_PREFIX "/")
		else()
			# If nothing else is specified we install into the source directory.
			update_cache(CMAKE_INSTALL_PREFIX "${PROJECT_SOURCE_DIR}/run")
		endif()
	endif()

	option(DISABLE_OWNERSHIP "Whether to install without ownership" OFF)
	if(NOT DISABLE_OWNERSHIP)
		set(GROUP "" CACHE STRING "The name or id of the group to run as")
		find_id("${GROUP}" "g" GROUP_ID GROUP_NAME)
		message(STATUS "InspIRCd will run as group ${GROUP_NAME} (${GROUP_ID})")

		set(USER "" CACHE STRING "The name or id of the user to run as")
		find_id("${USER}" "u" USER_ID USER_NAME)
		message(STATUS "InspIRCd will run as user ${USER_NAME} (${USER_ID})")
	endif()
endif()

configure_path(
	NAME         "BINARY_DIR"
	SOURCE_DEF   "bin"
	PORTABLE_DEF "bin"
	SYSTEM_DEF   "usr/bin"
	DESCRIPTION  "The directory to install binary files to"
)
configure_path(
	NAME         "CONFIG_DIR"
	SOURCE_DEF   "conf"
	PORTABLE_DEF "conf"
	SYSTEM_DEF   "etc/inspircd"
	DESCRIPTION  "The directory to read config files from"
)
configure_path(
	NAME         "DATA_DIR"
	SOURCE_DEF   "data"
	PORTABLE_DEF "data"
	SYSTEM_DEF   "var/lib/inspircd"
	DESCRIPTION  "The directory to read and write data files to"
)
configure_path(
	NAME         "EXAMPLE_DIR"
	SOURCE_DEF   "${CONFIG_DIR}/examples"
	PORTABLE_DEF "${CONFIG_DIR}/examples"
	SYSTEM_DEF   "usr/share/doc/inspircd/examples"
	DESCRIPTION  "The directory to install example config files to"
)
configure_path(
	NAME LOG_DIR
	SOURCE_DEF   "logs"
	PORTABLE_DEF "logs"
	SYSTEM_DEF   "var/log/inspircd"
	DESCRIPTION  "The directory to write log files to"
)
configure_path(
	NAME         "MANUAL_DIR"
	SOURCE_DEF   "manuals"
	PORTABLE_DEF "manuals"
	SYSTEM_DEF   "usr/share/man/man1"
	DESCRIPTION  "The directory to install manual files to"
)
configure_path(
	NAME          "MODULE_DIR"
	SOURCE_DEF    "modules"
	PORTABLE_DEF  "modules"
	SYSTEM_DEF    "usr/lib/inspircd"
	DESCRIPTION   "The directory to install modules files to"
)
configure_path(
	NAME          "RUNTIME_DIR"
	SOURCE_DEF    "${DATA_DIR}"
	PORTABLE_DEF  "${DATA_DIR}"
	SYSTEM_DEF    "$<$<NOT:$<PLATFORM_ID:Linux>>:var/>run/inspircd"
	DESCRIPTION   "The directory to write runtime files to"
)
configure_path(
	NAME         "SCRIPT_DIR"
	SOURCE_DEF   "."
	PORTABLE_DEF "."
	SYSTEM_DEF   "/usr/share/inspircd"
	DESCRIPTION  "The directory to install script files to"
)

set(VERSION_FULL "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
if(DEFINED DISTRIBUTION_LABEL)
	# The builder specified an explicit distribution label.
	set(VERSION_LABEL ${DISTRIBUTION_LABEL})
elseif(IS_DIRECTORY "${PROJECT_SOURCE_DIR}/.git")
	# The builder is building from Git, try to get the Git hash.
	find_program(GIT_BINARY "git")
	if(DEFINED GIT_BINARY)
		execute_process(
			COMMAND ${GIT_BINARY} "-C" "${PROJECT_SOURCE_DIR}" "describe" "--tags"
				ERROR_QUIET
				OUTPUT_VARIABLE GIT_DESCRIPTION
				OUTPUT_STRIP_TRAILING_WHITESPACE
				RESULT_VARIABLE GIT_RESULT
		)
		if(NOT GIT_RESULT AND GIT_DESCRIPTION MATCHES "^v[0-9]+\\.[0-9]+\\.[0-9]+([a-zA-Z0-9]*)-[0-9]+-g([a-f0-9]+)$")
			set(VERSION_LABEL ${CMAKE_MATCH_2})
		endif()
	endif()
endif()
if(DEFINED VERSION_LABEL)
	string(APPEND VERSION_FULL "-${VERSION_LABEL}")
endif()

include_directories("include" "${PROJECT_BINARY_DIR}/include")
include_directories(SYSTEM "vendor")
if(WIN32)
	include_directories("src/windows")
endif()

set_property(GLOBAL PROPERTY
	"USE_FOLDERS" ON # Organise targets into folders.
)

# Vendored libraries used by the core and modules.
add_subdirectory("vendor")

# The main inspircd binary and the win32compat library.
add_subdirectory("include")
add_subdirectory("src")

# Modules that can be loaded by the core.
add_subdirectory("modules")

# Miscellaneous data files.
add_subdirectory("docs")
add_subdirectory("tools")