Skip to content

Commit 7b01e2b

Browse files
committed
cmake: add the DaemonPlatform CMake framework
1 parent d281e6a commit 7b01e2b

File tree

14 files changed

+1628
-0
lines changed

14 files changed

+1628
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Daemon BSD Source Code
2+
# Copyright (c) 2022-2025, Daemon Developers
3+
# All rights reserved.
4+
#
5+
# Redistribution and use in source and binary forms, with or without
6+
# modification, are permitted provided that the following conditions are met:
7+
# * Redistributions of source code must retain the above copyright
8+
# notice, this list of conditions and the following disclaimer.
9+
# * Redistributions in binary form must reproduce the above copyright
10+
# notice, this list of conditions and the following disclaimer in the
11+
# documentation and/or other materials provided with the distribution.
12+
# * Neither the name of the <organization> nor the
13+
# names of its contributors may be used to endorse or promote products
14+
# derived from this software without specific prior written permission.
15+
#
16+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20+
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23+
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
27+
################################################################################
28+
# Architecture detection.
29+
################################################################################
30+
31+
# When adding a new architecture, look at all the places DAEMON_ARCH is used.
32+
33+
option(USE_ARCH_INTRINSICS "Enable custom code using intrinsics functions or asm declarations" ON)
34+
mark_as_advanced(USE_ARCH_INTRINSICS)
35+
36+
function(daemon_detect_arch)
37+
daemon_run_detection("" "ARCH" "Architecture.c" "")
38+
39+
set(DAEMON_ARCH_NAME "${arch_name}" PARENT_SCOPE)
40+
41+
message(STATUS "Detected target architecture: ${arch_name}")
42+
43+
add_definitions(-DDAEMON_ARCH_${arch_name})
44+
45+
set(nacl_arch "${arch_name}")
46+
if (DAEMON_SYSTEM_Unix_COMPATIBILITY)
47+
set(armhf_usage "arm64;armel")
48+
if ("${arch_name}" IN_LIST armhf_usage)
49+
# Load 32-bit armhf nexe on 64-bit arm64 engine on Linux with multiarch.
50+
# The nexe is system agnostic so there should be no difference with armel.
51+
set(nacl_arch "armhf")
52+
endif()
53+
elseif(DAEMON_SYSTEM_macOS)
54+
if ("${arch_name}" STREQUAL "arm64")
55+
# You can get emulated NaCl going like this:
56+
# cp external_deps/macos-amd64-default_10/{nacl_loader,irt_core-amd64.nexe} build/
57+
set(nacl_arch "amd64")
58+
endif()
59+
endif()
60+
61+
# The DAEMON_NACL_ARCH variable contributes to the nexe file name.
62+
set(DAEMON_NACL_ARCH_NAME "${nacl_arch}" PARENT_SCOPE)
63+
endfunction()
64+
65+
function(daemon_set_arch_intrinsics name)
66+
message(STATUS "Enabling ${name} architecture intrinsics")
67+
add_definitions(-DDAEMON_USE_ARCH_INTRINSICS_${name})
68+
endfunction()
69+
70+
function(daemon_set_intrinsics)
71+
if (USE_ARCH_INTRINSICS)
72+
# Makes possible to do that in C++ code:
73+
# > if defined(DAEMON_USER_ARCH_INTRINSICS)
74+
add_definitions(-DDAEMON_USE_ARCH_INTRINSICS)
75+
76+
# Makes possible to do that in C++ code:
77+
# > if defined(DAEMON_USER_ARCH_INTRINSICS_amd64)
78+
# > if defined(DAEMON_USER_ARCH_INTRINSICS_i686)
79+
daemon_set_arch_intrinsics("${DAEMON_ARCH_NAME}")
80+
81+
set(amd64_PARENT "i686")
82+
set(arm64_PARENT "armhf")
83+
84+
if ("${DAEMON_ARCH_NAME}_PARENT")
85+
daemon_set_arch_intrinsics("${${DAEMON_ARCH_NAME}_PARENT}")
86+
endif()
87+
else()
88+
message(STATUS "Disabling ${DAEMON_ARCH_NAME} architecture intrinsics")
89+
endif()
90+
endfunction()
91+
92+
daemon_detect_arch()
93+
daemon_set_intrinsics()
94+
95+
# Makes possible to do that in CMake code:
96+
# > if (DAEMON_ARCH_arm64)
97+
# > if (DAEMON_NACL_ARCH_armhf)
98+
set("DAEMON_ARCH_${DAEMON_ARCH_NAME}" ON)
99+
set("DAEMON_NACL_ARCH_${DAEMON_NACL_ARCH_NAME}" ON)
100+
101+
if (DAEMON_SOURCE_GENERATOR)
102+
# Add printable strings to the executable.
103+
daemon_add_buildinfo("char*" "DAEMON_ARCH_STRING" "\"${DAEMON_ARCH_NAME}\"")
104+
daemon_add_buildinfo("char*" "DAEMON_NACL_ARCH_STRING" "\"${DAEMON_NACL_ARCH_NAME}\"")
105+
endif()
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# Daemon BSD Source Code
2+
# Copyright (c) 2024-2025, Daemon Developers
3+
# All rights reserved.
4+
#
5+
# Redistribution and use in source and binary forms, with or without
6+
# modification, are permitted provided that the following conditions are met:
7+
# * Redistributions of source code must retain the above copyright
8+
# notice, this list of conditions and the following disclaimer.
9+
# * Redistributions in binary form must reproduce the above copyright
10+
# notice, this list of conditions and the following disclaimer in the
11+
# documentation and/or other materials provided with the distribution.
12+
# * Neither the name of the <organization> nor the
13+
# names of its contributors may be used to endorse or promote products
14+
# derived from this software without specific prior written permission.
15+
#
16+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20+
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23+
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
27+
################################################################################
28+
# Compiler detection.
29+
################################################################################
30+
31+
# When adding a new compiler, look at all the places DAEMON_C_COMPILER
32+
# and DAEMON_CXX_COMPILER are used.
33+
34+
function(daemon_detect_compiler lang)
35+
set(C_NAME "C")
36+
set(CXX_NAME "C++")
37+
set(C_EXT ".c")
38+
set(CXX_EXT ".cpp")
39+
40+
get_filename_component(compiler_basename "${CMAKE_${lang}_COMPILER}" NAME)
41+
42+
daemon_run_detection("${lang}_" "COMPILER" "Compiler${${lang}_EXT}" "GCC;Clang;generic")
43+
44+
if (compiler_name STREQUAL "Unknown")
45+
if (CMAKE_${lang}_COMPILER_ID)
46+
set(compiler_name "${CMAKE_${lang}_COMPILER_ID}")
47+
# Compiler version is done below.
48+
else()
49+
message(WARNING "Unknown ${${lang}_NAME} compiler")
50+
endif()
51+
endif()
52+
53+
# AOCC
54+
if (compiler_Clang_version_string)
55+
set(aocc_version_regex ".*CLANG: AOCC_([^ )]+).*")
56+
if (compiler_Clang_version_string MATCHES ${aocc_version_regex})
57+
set(compiler_name "AOCC")
58+
string(REGEX REPLACE ${aocc_version_regex} "\\1"
59+
compiler_AOCC_version "${compiler_Clang_version_string}")
60+
string(REGEX REPLACE "(.*)-Build.*" "\\1"
61+
compiler_AOCC_version "${compiler_AOCC_version}")
62+
endif()
63+
endif()
64+
65+
# Zig
66+
if (compiler_Clang_version_string)
67+
set(zig_version_regex ".*[(]https://github.com/ziglang/zig-bootstrap .*[)]")
68+
if (compiler_Clang_version_string MATCHES ${zig_version_regex})
69+
set(compiler_name "Zig")
70+
endif()
71+
72+
# Parse “zig version”
73+
execute_process(COMMAND "${CMAKE_${lang}_COMPILER}" version
74+
OUTPUT_VARIABLE CUSTOM_${lang}_ZIG_OUTPUT
75+
RESULT_VARIABLE CUSTOM_${lang}_ZIG_RETURN_CODE
76+
ERROR_QUIET
77+
OUTPUT_STRIP_TRAILING_WHITESPACE)
78+
79+
if (NOT CUSTOM_${lang}_ZIG_RETURN_CODE) # Success
80+
set(compiler_Zig_version "${CUSTOM_${lang}_ZIG_OUTPUT}")
81+
endif()
82+
endif()
83+
84+
# Compilers that use the underlying Clang version as their own version.
85+
foreach(name in AppleClang)
86+
if (compiler_name STREQUAL "${name}")
87+
set(compiler_${name}_version "${compiler_Clang_version}")
88+
endif()
89+
endforeach()
90+
91+
# Compilers that write the version number at the beginning of the VERSION string.
92+
set(string_version_regex "([^ ]+).*")
93+
foreach(name in PNaCl)
94+
if (compiler_name STREQUAL "${name}")
95+
if (compiler_generic_version_string)
96+
if (compiler_generic_version_string MATCHES ${string_version_regex})
97+
string(REGEX REPLACE ${string_version_regex} "\\1"
98+
compiler_${name}_version "${compiler_generic_version_string}")
99+
endif()
100+
endif()
101+
endif()
102+
endforeach()
103+
104+
if (compiler_ARMClang_version_string)
105+
# There is no __armclang_patchlevel__ so we should parse __armclang_version__ to get it.
106+
if (compiler_ARMClang_version_string MATCHES ${string_version_regex})
107+
string(REGEX REPLACE ${string_version_regex} "\\1"
108+
compiler_ARMClang_version "${compiler_ARMClang_version_string}")
109+
endif()
110+
endif()
111+
112+
if (compiler_ICX_version)
113+
# 20240000 becomes 2024.0.0
114+
string(REGEX REPLACE "(....)(..)(..)" "\\1.\\2.\\3"
115+
compiler_ICX_version "${compiler_ICX_version}")
116+
string(REGEX REPLACE "\\.0" "."
117+
compiler_ICX_version "${compiler_ICX_version}")
118+
endif()
119+
120+
if (compiler_${compiler_name}_version)
121+
set(compiler_version "${compiler_${compiler_name}_version}")
122+
elseif (CMAKE_${lang}_COMPILER_VERSION)
123+
set(compiler_version "${CMAKE_${lang}_COMPILER_VERSION}")
124+
else()
125+
set(compiler_version "Unknown")
126+
message(WARNING "Unknown ${${lang}_NAME} compiler version")
127+
endif()
128+
129+
set(DAEMON_${lang}_COMPILER_BASENAME "${compiler_basename}" PARENT_SCOPE)
130+
set(DAEMON_${lang}_COMPILER_NAME "${compiler_name}" PARENT_SCOPE)
131+
set(DAEMON_${lang}_COMPILER_VERSION "${compiler_version}" PARENT_SCOPE)
132+
endfunction()
133+
134+
message(STATUS "CMake generator: ${CMAKE_GENERATOR}")
135+
136+
foreach(lang C;CXX)
137+
set(C_NAME "C")
138+
set(CXX_NAME "C++")
139+
140+
if (MSVC)
141+
# Let CMake do the job, it does it very well,
142+
# and there is probably no variant to take care about.
143+
set(DAEMON_${lang}_COMPILER_NAME "${CMAKE_${lang}_COMPILER_ID}")
144+
set(DAEMON_${lang}_COMPILER_VERSION "${CMAKE_${lang}_COMPILER_VERSION}")
145+
get_filename_component(DAEMON_${lang}_COMPILER_BASENAME "${CMAKE_${lang}_COMPILER}" NAME)
146+
else()
147+
daemon_detect_compiler(${lang})
148+
149+
if (DAEMON_${lang}_COMPILER_Clang_COMPATIBILITY)
150+
if (NOT DAEMON_${lang}_COMPILER_NAME STREQUAL "Clang")
151+
set(DAEMON_${lang}_COMPILER_EXTENDED_VERSION
152+
"${DAEMON_${lang}_COMPILER_VERSION}/Clang_${DAEMON_${lang}_COMPILER_Clang_VERSION}")
153+
endif()
154+
elseif (DAEMON_${lang}_COMPILER_GCC_COMPATIBILITY)
155+
if (NOT DAEMON_${lang}_COMPILER_NAME STREQUAL "GCC")
156+
# Almost all compilers on Earth pretend to be GCC compatible.
157+
# So we first have to check it's really a GCC variant.
158+
# Parse “<compiler> -v”
159+
execute_process(COMMAND "${CMAKE_${lang}_COMPILER}" -v
160+
ERROR_VARIABLE CUSTOM_${lang}_GCC_OUTPUT
161+
RESULT_VARIABLE CUSTOM_${lang}_GCC_RETURN_CODE
162+
OUTPUT_QUIET)
163+
164+
if (NOT CUSTOM_${lang}_GCC_RETURN_CODE) # Success
165+
# The existence of this string tells us it's a GCC variant.
166+
# The version in this string is the same as __VERSION__,
167+
# the version of the GCC variant, not the version of the upstream
168+
# GCC we are looking for.
169+
if ("${CUSTOM_${lang}_GCC_OUTPUT}" MATCHES "\ngcc version ")
170+
set(DAEMON_${lang}_COMPILER_EXTENDED_VERSION
171+
"${DAEMON_${lang}_COMPILER_VERSION}/GCC_${DAEMON_${lang}_COMPILER_GCC_VERSION}")
172+
endif()
173+
endif()
174+
endif()
175+
endif()
176+
endif()
177+
178+
if (NOT DAEMON_${lang}_COMPILER_EXTENDED_VERSION)
179+
set(DAEMON_${lang}_COMPILER_EXTENDED_VERSION "${DAEMON_${lang}_COMPILER_VERSION}")
180+
endif()
181+
182+
set(DAEMON_${lang}_COMPILER_STRING
183+
"${DAEMON_${lang}_COMPILER_NAME}_${DAEMON_${lang}_COMPILER_EXTENDED_VERSION}:${DAEMON_${lang}_COMPILER_BASENAME}")
184+
185+
if (CMAKE_CXX_COMPILER_ARG1)
186+
set(DAEMON_${lang}_COMPILER_STRING "${DAEMON_${lang}_COMPILER_STRING}:${CMAKE_CXX_COMPILER_ARG1}")
187+
endif()
188+
189+
message(STATUS "Detected ${${lang}_NAME} compiler: ${DAEMON_${lang}_COMPILER_STRING}")
190+
191+
# Makes possible to do that in C++ code:
192+
# > if defined(DAEMON_CXX_COMPILER_Clang)
193+
set(compiler_var_name "DAEMON_${lang}_COMPILER_${DAEMON_${lang}_COMPILER_NAME}")
194+
add_definitions(-D${compiler_var_name})
195+
196+
# Makes possible to do that in CMake code:
197+
# > if (DAEMON_CXX_COMPILER_Clang)
198+
set("${compiler_var_name}" ON)
199+
200+
if (DAEMON_SOURCE_GENERATOR)
201+
# Add printable string to the executable.
202+
daemon_add_buildinfo("char*" "DAEMON_${lang}_COMPILER_STRING" "\"${DAEMON_${lang}_COMPILER_STRING}\"")
203+
endif()
204+
endforeach()

0 commit comments

Comments
 (0)