2023-12-29 11:18:03 +00:00
function ( detect_operating_system )
2024-01-12 08:17:26 +00:00
message ( STATUS "CMake Version: ${CMAKE_VERSION}" )
message ( STATUS "CMake System Name: ${CMAKE_SYSTEM_NAME}" )
2023-12-29 11:18:03 +00:00
# LINUX wasn't added until CMake 3.25.
if ( CMAKE_VERSION VERSION_LESS 3.25.0 AND CMAKE_SYSTEM_NAME MATCHES "Linux" )
2024-01-12 08:17:26 +00:00
# Have to make it visible in this scope as well for below.
2023-12-29 11:18:03 +00:00
set ( LINUX TRUE PARENT_SCOPE )
2024-01-12 08:17:26 +00:00
set ( LINUX TRUE )
2023-12-29 11:18:03 +00:00
endif ( )
2021-07-04 05:24:21 +00:00
if ( WIN32 )
2023-12-29 11:18:03 +00:00
message ( STATUS "Building for Windows." )
elseif ( APPLE AND NOT IOS )
message ( STATUS "Building for MacOS." )
elseif ( LINUX )
message ( STATUS "Building for Linux." )
elseif ( BSD )
message ( STATUS "Building for *BSD." )
else ( )
message ( FATAL_ERROR "Unsupported platform." )
endif ( )
endfunction ( )
function ( detect_compiler )
if ( MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang" )
set ( USE_CLANG_CL TRUE PARENT_SCOPE )
2023-12-30 07:33:37 +00:00
set ( IS_SUPPORTED_COMPILER TRUE PARENT_SCOPE )
2023-12-29 11:18:03 +00:00
message ( STATUS "Building with Clang-CL." )
elseif ( CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" )
set ( USE_CLANG TRUE PARENT_SCOPE )
2023-12-30 07:33:37 +00:00
set ( IS_SUPPORTED_COMPILER TRUE PARENT_SCOPE )
2023-12-29 11:18:03 +00:00
message ( STATUS "Building with Clang/LLVM." )
elseif ( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" )
set ( USE_GCC TRUE PARENT_SCOPE )
2023-12-30 07:33:37 +00:00
set ( IS_SUPPORTED_COMPILER FALSE PARENT_SCOPE )
message ( STATUS "Building with GNU GCC." )
2023-12-29 11:18:03 +00:00
elseif ( MSVC )
2023-12-30 07:33:37 +00:00
set ( IS_SUPPORTED_COMPILER TRUE PARENT_SCOPE )
2023-12-29 11:18:03 +00:00
message ( STATUS "Building with MSVC." )
else ( )
message ( FATAL_ERROR "Unknown compiler: ${CMAKE_CXX_COMPILER_ID}" )
2021-07-04 05:24:21 +00:00
endif ( )
2014-12-28 06:41:57 +00:00
endfunction ( )
2013-06-28 10:43:50 +00:00
2020-05-24 06:19:47 +00:00
function ( get_git_version_info )
2021-07-04 05:24:21 +00:00
set ( PCSX2_GIT_REV "" )
2021-10-18 04:09:42 +00:00
set ( PCSX2_GIT_TAG "" )
2022-05-12 15:54:02 +00:00
set ( PCSX2_GIT_HASH "" )
2021-07-04 05:24:21 +00:00
if ( GIT_FOUND AND EXISTS ${ PROJECT_SOURCE_DIR } /.git )
2024-01-07 09:36:40 +00:00
EXECUTE_PROCESS ( WORKING_DIRECTORY ${ PROJECT_SOURCE_DIR } COMMAND ${ GIT_EXECUTABLE } describe --tags
2021-07-04 05:24:21 +00:00
O U T P U T _ V A R I A B L E P C S X 2 _ G I T _ R E V
2021-08-12 04:18:21 +00:00
O U T P U T _ S T R I P _ T R A I L I N G _ W H I T E S P A C E
E R R O R _ Q U I E T )
2021-10-18 04:09:42 +00:00
2024-01-11 00:04:42 +00:00
EXECUTE_PROCESS ( WORKING_DIRECTORY ${ PROJECT_SOURCE_DIR } COMMAND ${ GIT_EXECUTABLE } tag --points-at HEAD --sort=version:refname
O U T P U T _ V A R I A B L E P C S X 2 _ G I T _ T A G _ L I S T
R E S U L T _ V A R I A B L E T A G _ R E S U L T
2021-10-18 04:09:42 +00:00
O U T P U T _ S T R I P _ T R A I L I N G _ W H I T E S P A C E
E R R O R _ Q U I E T )
2022-05-12 15:54:02 +00:00
2024-01-11 00:04:42 +00:00
# CAUTION: There is a race here, this solves the problem of a commit being tagged multiple times (take the last tag)
# however, if simultaneous builds are pushing tags to the same commit you might get inconsistent results (it's a race)
#
# The easy solution is, don't do that, but just something to be aware of.
if ( PCSX2_GIT_TAG_LIST AND TAG_RESULT EQUAL 0 )
string ( REPLACE "\n" ";" PCSX2_GIT_TAG_LIST "${PCSX2_GIT_TAG_LIST}" )
if ( PCSX2_GIT_TAG_LIST )
list ( GET PCSX2_GIT_TAG_LIST -1 PCSX2_GIT_TAG )
message ( "Using tag: ${PCSX2_GIT_TAG}" )
endif ( )
endif ( )
2022-05-12 15:54:02 +00:00
EXECUTE_PROCESS ( WORKING_DIRECTORY ${ PROJECT_SOURCE_DIR } COMMAND ${ GIT_EXECUTABLE } rev-parse HEAD
O U T P U T _ V A R I A B L E P C S X 2 _ G I T _ H A S H
O U T P U T _ S T R I P _ T R A I L I N G _ W H I T E S P A C E
E R R O R _ Q U I E T )
2024-01-07 09:36:40 +00:00
EXECUTE_PROCESS ( WORKING_DIRECTORY ${ PROJECT_SOURCE_DIR } COMMAND ${ GIT_EXECUTABLE } log -1 --format=%cd --date=local
O U T P U T _ V A R I A B L E P C S X 2 _ G I T _ D A T E
O U T P U T _ S T R I P _ T R A I L I N G _ W H I T E S P A C E
E R R O R _ Q U I E T )
2021-07-04 05:24:21 +00:00
endif ( )
2024-01-07 09:36:40 +00:00
if ( NOT PCSX2_GIT_REV )
EXECUTE_PROCESS ( WORKING_DIRECTORY ${ PROJECT_SOURCE_DIR } COMMAND ${ GIT_EXECUTABLE } rev-parse --short HEAD
O U T P U T _ V A R I A B L E P C S X 2 _ G I T _ R E V
O U T P U T _ S T R I P _ T R A I L I N G _ W H I T E S P A C E
E R R O R _ Q U I E T )
if ( NOT PCSX2_GIT_REV )
set ( PCSX2_GIT_REV "Unknown" )
endif ( )
2021-07-04 05:24:21 +00:00
endif ( )
2020-05-24 06:19:47 +00:00
2021-07-04 05:24:21 +00:00
set ( PCSX2_GIT_REV "${PCSX2_GIT_REV}" PARENT_SCOPE )
2021-11-01 22:32:22 +00:00
set ( PCSX2_GIT_TAG "${PCSX2_GIT_TAG}" PARENT_SCOPE )
2022-05-12 15:54:02 +00:00
set ( PCSX2_GIT_HASH "${PCSX2_GIT_HASH}" PARENT_SCOPE )
2024-01-07 09:36:40 +00:00
set ( PCSX2_GIT_DATE "${PCSX2_GIT_DATE}" PARENT_SCOPE )
2020-05-24 06:19:47 +00:00
endfunction ( )
function ( write_svnrev_h )
2024-01-07 09:36:40 +00:00
if ( "${PCSX2_GIT_TAG}" MATCHES "^v([0-9]+)\\.([0-9]+)\\.([0-9]+)$" )
file ( WRITE ${ CMAKE_BINARY_DIR } /common/include/svnrev.h
" #define GIT_TAG \"${PCSX2_GIT_TAG}\"\n"
" #define GIT_TAGGED_COMMIT 1\n"
" #define GIT_TAG_HI ${CMAKE_MATCH_1}\n"
" #define GIT_TAG_MID ${CMAKE_MATCH_2}\n"
" #define GIT_TAG_LO ${CMAKE_MATCH_3}\n"
" #define GIT_REV \"${PCSX2_GIT_TAG}\"\n"
" #define GIT_HASH \"${PCSX2_GIT_HASH}\"\n"
" #define GIT_DATE \"${PCSX2_GIT_DATE}\"\n"
)
elseif ( "${PCSX2_GIT_REV}" MATCHES "^v([0-9]+)\\.([0-9]+)\\.([0-9]+)" )
file ( WRITE ${ CMAKE_BINARY_DIR } /common/include/svnrev.h
" #define GIT_TAG \"${PCSX2_GIT_TAG}\"\n"
" #define GIT_TAGGED_COMMIT 0\n"
" #define GIT_TAG_HI ${CMAKE_MATCH_1}\n"
" #define GIT_TAG_MID ${CMAKE_MATCH_2}\n"
" #define GIT_TAG_LO ${CMAKE_MATCH_3}\n"
" #define GIT_REV \"${PCSX2_GIT_REV}\"\n"
" #define GIT_HASH \"${PCSX2_GIT_HASH}\"\n"
" #define GIT_DATE \"${PCSX2_GIT_DATE}\"\n"
)
2021-10-18 04:09:42 +00:00
else ( )
2024-01-11 00:04:42 +00:00
file ( WRITE ${ CMAKE_BINARY_DIR } /common/include/svnrev.h
2022-01-21 14:05:13 +00:00
" #define GIT_TAG \"${PCSX2_GIT_TAG}\"\n"
" #define GIT_TAGGED_COMMIT 0\n"
2024-01-07 09:36:40 +00:00
" #define GIT_TAG_HI 0\n"
" #define GIT_TAG_MID 0\n"
" #define GIT_TAG_LO 0\n"
2022-01-21 14:05:13 +00:00
" #define GIT_REV \"${PCSX2_GIT_REV}\"\n"
2022-05-12 15:54:02 +00:00
" #define GIT_HASH \"${PCSX2_GIT_HASH}\"\n"
2024-01-07 09:36:40 +00:00
" #define GIT_DATE \"${PCSX2_GIT_DATE}\"\n"
2022-01-21 14:05:13 +00:00
)
2021-10-18 04:09:42 +00:00
endif ( )
2013-06-28 10:43:50 +00:00
endfunction ( )
2013-07-06 09:42:46 +00:00
2014-03-30 14:25:11 +00:00
function ( check_no_parenthesis_in_path )
2021-07-04 05:24:21 +00:00
if ( "${CMAKE_BINARY_DIR}" MATCHES "[()]" OR "${CMAKE_SOURCE_DIR}" MATCHES "[()]" )
message ( FATAL_ERROR "Your path contains some parenthesis. Unfortunately Cmake doesn't support them correctly.\nPlease rename your directory to avoid '(' and ')' characters\n" )
endif ( )
2014-03-30 14:25:11 +00:00
endfunction ( )
2014-08-04 16:08:00 +00:00
2021-04-17 20:30:03 +00:00
# like add_library(new ALIAS old) but avoids add_library cannot create ALIAS target "new" because target "old" is imported but not globally visible. on older cmake
function ( alias_library new old )
string ( REPLACE "::" "" library_no_namespace ${ old } )
2022-05-22 03:28:06 +00:00
if ( NOT TARGET _alias_ ${ library_no_namespace } )
add_library ( _alias_ ${ library_no_namespace } INTERFACE )
target_link_libraries ( _alias_ ${ library_no_namespace } INTERFACE ${ old } )
endif ( )
2021-04-17 20:30:03 +00:00
add_library ( ${ new } ALIAS _alias_ ${ library_no_namespace } )
endfunction ( )
2021-05-07 22:35:36 +00:00
function ( source_groups_from_vcxproj_filters file )
file ( READ "${file}" filecontent )
get_filename_component ( parent "${file}" DIRECTORY )
if ( parent STREQUAL "" )
set ( parent "." )
endif ( )
set ( regex "<[^ ]+ Include=\" ( [^\ "]+)\" >[ \t\r\n]+<Filter>([^<]+)<\\/Filter>[ \t\r\n]+<\\/[^ >]+> " )
string ( REGEX MATCHALL "${regex}" filterstrings "${filecontent}" )
foreach ( filterstring IN LISTS filterstrings )
string ( REGEX REPLACE "${regex}" "\\1" path "${filterstring}" )
string ( REGEX REPLACE "${regex}" "\\2" group "${filterstring}" )
source_group ( "${group}" FILES "${parent}/${path}" )
endforeach ( )
endfunction ( )
2022-05-22 03:28:06 +00:00
2023-10-31 04:08:02 +00:00
# Extracts a translation with the given type ("source" or "translation") from the given category of the given ts file
# (If there's multiple strings under the same category, which one it extracts is implementation defined. Just don't do it.)
function ( extract_translation_from_ts file type category output )
file ( READ "${file}" filecontent )
# Don't you love it when the best parser your language has to offer is regex?
set ( regex_search "(<[^\\/>]+>[^<>]+<\\/[^>\\/]+>|<\\/?context>)" )
set ( regex_extract "<[^\\/>]+>([^<>]+)<\\/([^>\\/]+)>" )
string ( REGEX MATCHALL "${regex_search}" pieces "${filecontent}" )
foreach ( piece IN LISTS pieces )
if ( piece STREQUAL "<context>" )
set ( found "" )
set ( name_match FALSE )
elseif ( piece STREQUAL "</context>" )
if ( name_match )
set ( ${ output } "${found}" PARENT_SCOPE )
break ( )
endif ( )
else ( )
string ( REGEX REPLACE "${regex_extract}" "\\1" content "${piece}" )
string ( REGEX REPLACE "${regex_extract}" "\\2" tag "${piece}" )
if ( tag STREQUAL "name" AND content STREQUAL "${category}" )
set ( name_match TRUE )
endif ( )
if ( tag STREQUAL "${type}" )
set ( found "${content}" )
endif ( )
endif ( )
endforeach ( )
endfunction ( )
2022-05-25 21:43:11 +00:00
function ( fixup_file_properties target )
get_target_property ( SOURCES ${ target } SOURCES )
if ( APPLE )
foreach ( source IN LISTS SOURCES )
# Set the right file types for .inl files in Xcode
if ( "${source}" MATCHES "\\.(inl|h)$" )
set_source_files_properties ( "${source}" PROPERTIES XCODE_EXPLICIT_FILE_TYPE sourcecode.cpp.h )
endif ( )
2023-09-09 07:58:27 +00:00
if ( "${source}" MATCHES "\\.(qm)$" )
set_source_files_properties ( "${source}" PROPERTIES XCODE_EXPLICIT_FILE_TYPE compiled )
endif ( )
2022-05-25 21:43:11 +00:00
# CMake makefile and ninja generators will attempt to share one PCH for both cpp and mm files
# That's not actually OK
if ( "${source}" MATCHES "\\.mm$" )
set_source_files_properties ( "${source}" PROPERTIES SKIP_PRECOMPILE_HEADERS ON )
endif ( )
endforeach ( )
endif ( )
endfunction ( )
2023-08-26 03:25:24 +00:00
function ( disable_compiler_warnings_for_target target )
if ( MSVC )
target_compile_options ( ${ target } PRIVATE "/W0" )
else ( )
target_compile_options ( ${ target } PRIVATE "-w" )
endif ( )
endfunction ( )
2024-03-21 06:19:17 +00:00
function ( detect_page_size )
message ( STATUS "Determining host page size" )
set ( detect_page_size_file ${ CMAKE_BINARY_DIR } ${ CMAKE_FILES_DIRECTORY } /CMakeTmp/src.c )
file ( WRITE ${ detect_page_size_file } "
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
i n t main ( ) {
i n t r e s = sysconf ( _SC_PAGESIZE ) ;
printf ( \"%d\", res ) ;
return ( res > 0 ) ? E X I T _ S U C C E S S : E X I T _ F A I L U R E ;
} " )
try_run (
d e t e c t _ p a g e _ s i z e _ r u n _ r e s u l t
d e t e c t _ p a g e _ s i z e _ c o m p i l e _ r e s u l t
$ { C M A K E _ B I N A R Y _ D I R } $ { C M A K E _ F I L E S _ D I R E C T O R Y }
$ { d e t e c t _ p a g e _ s i z e _ f i l e }
R U N _ O U T P U T _ V A R I A B L E d e t e c t _ p a g e _ s i z e _ o u t p u t )
if ( NOT detect_page_size_compile_result OR NOT detect_page_size_run_result EQUAL 0 OR CMAKE_CROSSCOMPILING )
message ( FATAL_ERROR "Could not determine host page size." )
else ( )
message ( STATUS "Host page size: ${detect_page_size_output}" )
set ( HOST_PAGE_SIZE ${ detect_page_size_output } CACHE STRING "Reported host page size" )
endif ( )
endfunction ( )
function ( detect_cache_line_size )
message ( STATUS "Determining host cache line size" )
set ( detect_cache_line_size_file ${ CMAKE_BINARY_DIR } ${ CMAKE_FILES_DIRECTORY } /CMakeTmp/src.c )
file ( WRITE ${ detect_cache_line_size_file } "
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
i n t main ( ) {
i n t l 1 i = sysconf ( _SC_LEVEL1_DCACHE_LINESIZE ) ;
i n t l 1 d = sysconf ( _SC_LEVEL1_ICACHE_LINESIZE ) ;
i n t r e s = ( l 1 i > l 1 d ) ? l 1 i : l 1 d ;
for ( int index = 0; index < 16; index++ ) {
c h a r b u f [ 1 2 8 ] ;
snprintf ( buf, sizeof(buf ) , \ " / s y s / d e v i c e s / s y s t e m / c p u / c p u 0 / c a c h e / i n d e x % d / c o h e r e n c y _ l i n e _ s i z e \ " , i n d e x ) ;
F I L E * f p = fopen ( buf, \"rb\");
if ( !fp )
b r e a k ;
fread ( buf, sizeof(buf ) , 1 , f p ) ;
fclose ( fp ) ;
i n t v a l = atoi ( buf ) ;
r e s = ( v a l > r e s ) ? v a l : r e s ;
}
printf ( \"%d\", res ) ;
return ( res > 0 ) ? E X I T _ S U C C E S S : E X I T _ F A I L U R E ;
} " )
try_run (
d e t e c t _ c a c h e _ l i n e _ s i z e _ r u n _ r e s u l t
d e t e c t _ c a c h e _ l i n e _ s i z e _ c o m p i l e _ r e s u l t
$ { C M A K E _ B I N A R Y _ D I R } $ { C M A K E _ F I L E S _ D I R E C T O R Y }
$ { d e t e c t _ c a c h e _ l i n e _ s i z e _ f i l e }
R U N _ O U T P U T _ V A R I A B L E d e t e c t _ c a c h e _ l i n e _ s i z e _ o u t p u t )
if ( NOT detect_cache_line_size_compile_result OR NOT detect_cache_line_size_run_result EQUAL 0 OR CMAKE_CROSSCOMPILING )
message ( FATAL_ERROR "Could not determine host cache line size." )
else ( )
message ( STATUS "Host cache line size: ${detect_cache_line_size_output}" )
set ( HOST_CACHE_LINE_SIZE ${ detect_cache_line_size_output } CACHE STRING "Reported host cache line size" )
endif ( )
endfunction ( )
2024-05-26 20:57:28 +00:00
function ( get_recursive_include_directories output target inc_prop link_prop )
get_target_property ( dirs ${ target } ${ inc_prop } )
if ( NOT dirs )
set ( dirs )
endif ( )
get_target_property ( deps ${ target } ${ link_prop } )
if ( deps )
foreach ( dep IN LISTS deps )
if ( TARGET ${ dep } )
get_recursive_include_directories ( depdirs ${ dep } INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES )
foreach ( depdir IN LISTS depdirs )
# Only match absolute paths
# We'll hope any non-absolute paths will not get set as system directories
if ( depdir MATCHES "^/" )
list ( APPEND dirs ${ depdir } )
endif ( )
endforeach ( )
endif ( )
endforeach ( )
list ( REMOVE_DUPLICATES dirs )
endif ( )
set ( ${ output } "${dirs}" PARENT_SCOPE )
endfunction ( )
function ( force_include_last_impl target include inc_prop link_prop )
get_recursive_include_directories ( dirs ${ target } ${ inc_prop } ${ link_prop } )
set ( remove )
foreach ( dir IN LISTS dirs )
if ( "${dir}" MATCHES "${include}" )
list ( APPEND remove ${ dir } )
endif ( )
endforeach ( )
if ( NOT "${remove}" STREQUAL "" )
get_target_property ( sysdirs ${ target } INTERFACE_SYSTEM_INCLUDE_DIRECTORIES )
if ( NOT sysdirs )
set ( sysdirs )
endif ( )
# Move matching items to the end
list ( REMOVE_ITEM dirs ${ remove } )
list ( APPEND dirs ${ remove } )
# Set them as system include directories
list ( APPEND sysdirs ${ remove } )
list ( REMOVE_DUPLICATES sysdirs )
set_target_properties ( ${ target } PROPERTIES
$ { i n c _ p r o p } " $ { d i r s } "
I N T E R F A C E _ S Y S T E M _ I N C L U D E _ D I R E C T O R I E S " $ { s y s d i r s } "
)
endif ( )
endfunction ( )
function ( force_include_last target include )
force_include_last_impl ( ${ target } "${include}" INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES )
force_include_last_impl ( ${ target } "${include}" INCLUDE_DIRECTORIES LINK_LIBRARIES )
endfunction ( )