aboutsummaryrefslogtreecommitdiff
path: root/CMakeLists.txt
blob: 93df5e871d4619427ec3eb74cd3af882e87bf53f (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
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
242
cmake_minimum_required (VERSION 3.0...3.27)
project (nncmpp VERSION 2.1.1 LANGUAGES C)

# Moar warnings
if ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR CMAKE_COMPILER_IS_GNUCC)
	set (wdisabled "-Wno-unused-function")
	set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra ${wdisabled}")
endif ()

# For custom modules
set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/liberty/cmake)

# Collect important build toggles for our simple preprocessor
# (cpp(1) isn't part of POSIX, otherwise we could reuse config.h)
set (options)
macro (add_option variable help value)
	option (${ARGV})
	list (APPEND options "${variable}=$<BOOL:${${variable}}>")
endmacro ()

# Dependencies
find_package (Ncursesw REQUIRED)
find_package (PkgConfig REQUIRED)
find_package (Unistring REQUIRED)
pkg_check_modules (curl REQUIRED libcurl)

include (AddThreads)

find_package (Termo QUIET NO_MODULE)
add_option (USE_SYSTEM_TERMO
	"Don't compile our own termo library, use the system one" "${Termo_FOUND}")
if (USE_SYSTEM_TERMO)
	if (NOT Termo_FOUND)
		message (FATAL_ERROR "System termo library not found")
	endif ()
else ()
	# We don't want the library to install, but EXCLUDE_FROM_ALL ignores tests
	add_subdirectory (termo EXCLUDE_FROM_ALL)
	file (WRITE ${PROJECT_BINARY_DIR}/CTestCustom.cmake
		"execute_process (COMMAND ${CMAKE_COMMAND} --build termo)")

	# We don't have many good choices; this is a relatively clean approach
	# (other possibilities: setting a variable in the parent scope, using
	# a cache variable, writing a special config file with build paths in it
	# and including it here, or setting a custom property on the targets)
	get_directory_property (Termo_INCLUDE_DIRS
		DIRECTORY termo INCLUDE_DIRECTORIES)
	set (Termo_LIBRARIES termo-static)
endif ()

pkg_check_modules (fftw fftw3 fftw3f)
add_option (WITH_FFTW
	"Use FFTW to enable spectrum visualisation" "${fftw_FOUND}")
if (WITH_FFTW)
	if (NOT fftw_FOUND)
		message (FATAL_ERROR "FFTW not found")
	endif ()
	list (APPEND extra_libraries ${fftw_LIBRARIES})
endif ()

pkg_check_modules (libpulse libpulse)
add_option (WITH_PULSE
	"Enable PulseAudio sink volume control" "${libpulse_FOUND}")
if (WITH_PULSE)
	if (NOT libpulse_FOUND)
		message (FATAL_ERROR "libpulse not found")
	endif ()
	list (APPEND extra_libraries ${libpulse_LIBRARIES})
endif ()

pkg_check_modules (x11 x11 xrender xft fontconfig libpng)
add_option (WITH_X11 "Build with X11 support" "${x11_FOUND}")
if (WITH_X11)
	if (NOT x11_FOUND)
		message (FATAL_ERROR "Some X11 libraries were not found")
	endif ()
	list (APPEND extra_libraries ${x11_LIBRARIES})
endif ()

include_directories (${Unistring_INCLUDE_DIRS}
	${Ncursesw_INCLUDE_DIRS} ${Termo_INCLUDE_DIRS} ${curl_INCLUDE_DIRS}
	${fftw_INCLUDE_DIRS} ${libpulse_INCLUDE_DIRS} ${x11_INCLUDE_DIRS})
link_directories (${curl_LIBRARY_DIRS}
	${fftw_LIBRARY_DIRS} ${libpulse_LIBRARY_DIRS} ${x11_LIBRARY_DIRS})

# Configuration
if ("${CMAKE_SYSTEM_NAME}" MATCHES "BSD")
	# Need this for SIGWINCH in FreeBSD and OpenBSD respectively;
	# our POSIX version macros make it undefined
	add_definitions (-D__BSD_VISIBLE=1 -D_BSD_SOURCE=1)
elseif (APPLE)
	add_definitions (-D_DARWIN_C_SOURCE)
endif ()

include (CheckFunctionExists)
set (CMAKE_REQUIRED_LIBRARIES ${Ncursesw_LIBRARIES})
CHECK_FUNCTION_EXISTS ("resizeterm" HAVE_RESIZETERM)

# -lm may or may not be a part of libc
foreach (extra m)
	find_library (extra_lib_${extra} ${extra})
	if (extra_lib_${extra})
		list (APPEND extra_libraries ${extra_lib_${extra}})
	endif ()
endforeach ()

# Generate a configuration file
include (GNUInstallDirs)
configure_file (${PROJECT_SOURCE_DIR}/config.h.in
	${PROJECT_BINARY_DIR}/config.h)
include_directories (${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR})

set (actions_list ${PROJECT_SOURCE_DIR}/nncmpp.actions)
set (actions_awk ${PROJECT_SOURCE_DIR}/nncmpp.actions.awk)
set (actions ${PROJECT_BINARY_DIR}/nncmpp-actions.h)
add_custom_command (OUTPUT ${actions}
	COMMAND env LC_ALL=C ${options}
		awk -f ${actions_awk} ${actions_list} > ${actions}
	DEPENDS ${actions_awk} ${actions_list} VERBATIM)

# Build the main executable and link it
add_executable (${PROJECT_NAME} ${PROJECT_NAME}.c ${actions})
target_link_libraries (${PROJECT_NAME} ${Unistring_LIBRARIES}
	${Ncursesw_LIBRARIES} ${Termo_LIBRARIES} ${curl_LIBRARIES}
	${extra_libraries})
add_threads (${PROJECT_NAME})

# Installation
install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
install (DIRECTORY contrib DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME})
install (DIRECTORY info DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}
	USE_SOURCE_PERMISSIONS)
if (WITH_X11)
	include (IconUtils)

	set (icon_base ${PROJECT_BINARY_DIR}/icons)
	set (icon_png_list)
	foreach (icon_size 16 32 48)
		icon_to_png (${PROJECT_NAME} ${PROJECT_SOURCE_DIR}/${PROJECT_NAME}.svg
			${icon_size} ${icon_base} icon_png)
		list (APPEND icon_png_list ${icon_png})
	endforeach ()

	add_custom_target (icons ALL DEPENDS ${icon_png_list})

	install (FILES ${PROJECT_NAME}.svg
		DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps)
	install (DIRECTORY ${icon_base}
		DESTINATION ${CMAKE_INSTALL_DATADIR})
	install (FILES ${PROJECT_NAME}.desktop
		DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
endif ()

# Generate documentation from text markup
find_program (ASCIIDOCTOR_EXECUTABLE asciidoctor)
find_program (A2X_EXECUTABLE a2x)
if (NOT ASCIIDOCTOR_EXECUTABLE AND NOT A2X_EXECUTABLE)
	message (WARNING "Neither asciidoctor nor a2x were found, "
		"falling back to a substandard manual page generator")
endif ()

foreach (page ${PROJECT_NAME})
	set (page_output "${PROJECT_BINARY_DIR}/${page}.1")
	list (APPEND project_MAN_PAGES "${page_output}")
	if (ASCIIDOCTOR_EXECUTABLE)
		add_custom_command (OUTPUT ${page_output}
			COMMAND ${ASCIIDOCTOR_EXECUTABLE} -b manpage
				-a release-version=${PROJECT_VERSION}
				-o "${page_output}"
				"${PROJECT_SOURCE_DIR}/${page}.adoc"
			DEPENDS ${page}.adoc
			COMMENT "Generating man page for ${page}" VERBATIM)
	elseif (A2X_EXECUTABLE)
		add_custom_command (OUTPUT ${page_output}
			COMMAND ${A2X_EXECUTABLE} --doctype manpage --format manpage
				-a release-version=${PROJECT_VERSION}
				-D "${PROJECT_BINARY_DIR}"
				"${PROJECT_SOURCE_DIR}/${page}.adoc"
			DEPENDS ${page}.adoc
			COMMENT "Generating man page for ${page}" VERBATIM)
	else ()
		set (ASCIIMAN ${PROJECT_SOURCE_DIR}/liberty/tools/asciiman.awk)
		add_custom_command (OUTPUT ${page_output}
			COMMAND env LC_ALL=C asciidoc-release-version=${PROJECT_VERSION}
				awk -f ${ASCIIMAN} "${PROJECT_SOURCE_DIR}/${page}.adoc"
				> ${page_output}
			DEPENDS ${page}.adoc ${ASCIIMAN}
			COMMENT "Generating man page for ${page}" VERBATIM)
	endif ()
endforeach ()

add_custom_target (docs ALL DEPENDS ${project_MAN_PAGES})

foreach (page ${project_MAN_PAGES})
	string (REGEX MATCH "\\.([0-9])$" manpage_suffix "${page}")
	install (FILES "${page}"
		DESTINATION "${CMAKE_INSTALL_MANDIR}/man${CMAKE_MATCH_1}")
endforeach ()

# Testing
option (BUILD_TESTING "Build tests" OFF)
if (BUILD_TESTING)
	enable_testing ()

	find_program (xmlwf_EXECUTABLE xmlwf)
	find_program (xmllint_EXECUTABLE xmllint)
	foreach (xml ${PROJECT_NAME}.svg)
		if (xmlwf_EXECUTABLE)
			add_test (test-xmlwf-${xml} ${xmlwf_EXECUTABLE}
				${PROJECT_SOURCE_DIR}/${xml})
		endif ()
		if (xmllint_EXECUTABLE)
			add_test (test-xmllint-${xml} ${xmllint_EXECUTABLE} --noout
				${PROJECT_SOURCE_DIR}/${xml})
		endif ()
	endforeach ()

	find_program (dfv_EXECUTABLE desktop-file-validate)
	if (dfv_EXECUTABLE)
		foreach (df ${PROJECT_NAME}.desktop)
			add_test (test-dfv-${df} ${dfv_EXECUTABLE}
				${PROJECT_SOURCE_DIR}/${df})
		endforeach ()
	endif ()
endif ()

# CPack
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Terminal/X11 MPD client")
set (CPACK_PACKAGE_VENDOR "Premysl Eric Janouch")
set (CPACK_PACKAGE_CONTACT "Přemysl Eric Janouch <p@janouch.name>")
set (CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
set (CPACK_GENERATOR "TGZ;ZIP")
set (CPACK_PACKAGE_FILE_NAME
	"${PROJECT_NAME}-${PROJECT_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
set (CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}-${PROJECT_VERSION}")
set (CPACK_SOURCE_GENERATOR "TGZ;ZIP")
set (CPACK_SOURCE_IGNORE_FILES "/\\\\.git;/build;/CMakeLists.txt.user")
set (CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")

set (CPACK_SET_DESTDIR TRUE)
include (CPack)