Доработана сборка под Emscripten

This commit is contained in:
Aleksandr Orefkov 2025-11-13 17:57:42 +03:00
parent 1f42327d7d
commit 1f225a790a
6 changed files with 83 additions and 43 deletions

View File

@ -22,22 +22,13 @@ elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL Clang)
endif()
option(SIMSTR_BUILD_TESTS "Построить тесты" ON)
option(SIMSTR_BENCHMARKS "Построить замеры производительности" ON)
option(SIMSTR_SHARED "Функции simstr должны экспортироваться или импортироваться" OFF)
option(SIMSTR_BENCHMARKS "Построить замеры производительности" Off)
if(EMSCRIPTEN)
option(SIMSTR_EMSCRIPTEN_MT "Использовать многопоточность в Emscripten" OFF)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-warn-absolute-paths -Wno-unknown-warning-option -msimd128 -msse4.2 -msse3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-warn-absolute-paths -Wno-unknown-warning-option -msimd128 -msse4.2 -msse3")
if(SIMSTR_EMSCRIPTEN_MT)
message("Build MT emscripten")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread -sPTHREAD_POOL_SIZE=navigator.hardwareConcurrency-1")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -sENVIRONMENT=web,worker")
endif()
endif(EMSCRIPTEN)
# При OFF - строится обычная статическая библиотека.
# При On - simstr собирается как статическая библиотека, которую потом встроят в shared библиотеку,
# и она будет свои функции объявлять как экспортируемые. Потребители же будут собираться с указанием,
# что функции - импортируемые
option(SIMSTR_IN_SHARED "Функции simstr будут экспортироваться или импортироваться" Off)
add_library(simstr_simstr
src/sstring.cpp
@ -53,6 +44,16 @@ target_include_directories(
target_compile_features(simstr_simstr PUBLIC cxx_std_20)
if(EMSCRIPTEN)
option(SIMSTR_EMSCRIPTEN_MT "Использовать многопоточность в Emscripten" OFF)
target_compile_options(simstr_simstr PUBLIC -Wno-warn-absolute-paths -Wno-unknown-warning-option -msimd128 -msse4.2 -msse3)
if(SIMSTR_EMSCRIPTEN_MT)
message("Build MT emscripten")
target_compile_options(simstr_simstr PUBLIC -pthread)
endif()
endif(EMSCRIPTEN)
# Для MSVC подключаем natvis файл для красивой отладки
if(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
target_link_options(simstr_simstr PUBLIC "/natvis:${CMAKE_CURRENT_SOURCE_DIR}/for_debug/simstr.natvis")
@ -68,7 +69,7 @@ set_target_properties(
OUTPUT_NAME simstr
)
function(Simdutf)
function(add_simdutf)
set(SIMDUTF_TOOLS OFF)
set(SIMDUTF_TESTS OFF)
set(SIMDUTF_BENCHMARKS OFF)
@ -82,14 +83,22 @@ function(Simdutf)
FetchContent_MakeAvailable(simdutf)
endfunction()
Simdutf()
add_simdutf()
target_link_libraries(simstr_simstr PUBLIC simdutf::simdutf)
if(SIMSTR_SHARED)
add_compile_definitions(SIMSTR_SHARED)
if(SIMSTR_IN_SHARED)
# Всем объявляем, что мы будем в shared библиотеке
add_compile_definitions(SIMSTR_IN_SHARED)
# Себе объявим, что мы должны экспортировать функции
target_compile_definitions(simstr_simstr PRIVATE SIMSTR_EXPORT)
endif(SIMSTR_SHARED)
# Пример построения shared библиотеки, которая включит в себя simstr.
# Как при этом создать экзешник, пользующийся этой dll - пример в tests/CMakeLists.txt
# Нельзя объявить библиотеку без исходников, добавим просто .h файл
add_library(simstr_dll SHARED include/simstr/sstring.h)
# simstr должна войти в simstr_dll целиком
target_link_libraries(simstr_dll PRIVATE "$<LINK_LIBRARY:WHOLE_ARCHIVE,simstr::simstr>")
endif(SIMSTR_IN_SHARED)
if(SIMSTR_BUILD_TESTS)
enable_testing()
@ -101,7 +110,6 @@ if(SIMSTR_BUILD_TESTS)
URL https://github.com/google/googletest/archive/refs/tags/release-1.12.1.zip
FIND_PACKAGE_ARGS NAMES GTest
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt FALSE CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
@ -110,14 +118,12 @@ endif()
function(GBencmark)
# Load and build Google benchmarks
include(FetchContent)
FetchContent_Declare(
googlebench
# Specify the commit you depend on and update it regularly.
URL https://github.com/google/benchmark/archive/refs/tags/v1.7.0.zip
URL https://github.com/google/benchmark/archive/refs/tags/v1.9.4.zip
FIND_PACKAGE_ARGS NAMES benchmark
)
set(CMAKE_CXX_STANDARD 20)
set(BENCHMARK_ENABLE_TESTING OFF)
set(BENCHMARK_ENABLE_LTO OFF)
set(BENCHMARK_ENABLE_INSTALL OFF)
@ -126,6 +132,15 @@ function(GBencmark)
set(BENCHMARK_ENABLE_GTEST_TESTS OFF)
add_compile_definitions(BENCHMARK_STATIC_DEFINE)
FetchContent_MakeAvailable(googlebench)
target_compile_features(benchmark PUBLIC cxx_std_20)
if(EMSCRIPTEN)
# Свежий Clang в Emscripten ругается на __COUNTER__
target_compile_options(benchmark PUBLIC -Wno-c2y-extensions)
if(SIMSTR_EMSCRIPTEN_MT)
target_compile_options(benchmark PUBLIC -pthread)
endif()
endif()
endfunction()
if(SIMSTR_BENCHMARKS) # AND CMAKE_BUILD_TYPE STREQUAL Release)

View File

@ -4,7 +4,7 @@
cmake_minimum_required (VERSION 3.15)
add_executable(benchStr bench_str.cpp bench.h)
target_link_libraries(benchStr simstr::simstr benchmark::benchmark benchmark::benchmark_main)
target_link_libraries(benchStr simstr::simstr benchmark::benchmark)
add_executable(process_result process_result.cpp)
target_link_libraries(process_result simstr_simstr)
@ -12,5 +12,7 @@ target_link_libraries(process_result simstr_simstr)
if (EMSCRIPTEN)
#target_link_options(benchStr PRIVATE -sSTACK_SIZE=1048576 -sINITIAL_MEMORY=128MB -sALLOW_MEMORY_GROWTH=0)
set_target_properties (benchStr PROPERTIES SUFFIX .html)
target_link_options(benchStr PUBLIC --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/bench.js)
if(SIMSTR_EMSCRIPTEN_MT)
target_link_options(benchStr PUBLIC -pthread -sPTHREAD_POOL_SIZE=navigator.hardwareConcurrency-1 -sENVIRONMENT=web,worker)
endif()
endif(EMSCRIPTEN)

View File

@ -1 +0,0 @@
Module.arguments=['--benchmark_repetitions=10', '--benchmark_report_aggregates_only=true'];

View File

@ -145,7 +145,6 @@ void ToIntStr10(benchmark::State& state, const std::string& s, int c) {
}
#endif
benchmark::DoNotOptimize(res);
benchmark::DoNotOptimize(s);
}
}
@ -159,7 +158,6 @@ void ToIntStr16(benchmark::State& state, const std::string& s, int c) {
}
#endif
benchmark::DoNotOptimize(res);
benchmark::DoNotOptimize(s);
}
}
@ -173,7 +171,6 @@ void ToIntStr0(benchmark::State& state, const std::string& s, int c) {
}
#endif
benchmark::DoNotOptimize(res);
benchmark::DoNotOptimize(s);
}
}
@ -191,7 +188,6 @@ void ToIntFromChars10(benchmark::State& state, const std::string_view& s, int c)
}
#endif
benchmark::DoNotOptimize(res);
benchmark::DoNotOptimize(s);
}
#endif
}
@ -210,7 +206,6 @@ void ToIntFromChars16(benchmark::State& state, const std::string_view& s, int c)
}
#endif
benchmark::DoNotOptimize(res);
benchmark::DoNotOptimize(s);
}
#endif
}
@ -890,8 +885,6 @@ void ReplaceSymbolsStdString(benchmark::State& state) {
#endif
benchmark::DoNotOptimize(result);
benchmark::DoNotOptimize(source);
benchmark::DoNotOptimize(repl_from);
benchmark::DoNotOptimize(repl_to);
}
}
@ -1112,8 +1105,6 @@ void ShortReplaceSymbolsStdString(benchmark::State& state) {
#endif
benchmark::DoNotOptimize(result);
benchmark::DoNotOptimize(source);
benchmark::DoNotOptimize(repl_from);
benchmark::DoNotOptimize(repl_to);
}
}
@ -1904,3 +1895,18 @@ BENCHMARK(BuildFuncNameStdStr1) ->Name("Build func full name std::string
BENCHMARK(BuildFuncNameStream) ->Name("Build func full name std::stream;");
BENCHMARK(BuildFuncNameSimStr) ->Name("Build func full name stringa;");
BENCHMARK(BuildFuncNameSimStr1) ->Name("Build func full name stringa 1;");
int main(int argc, char** argv) {
char arg1[] = "--benchmark_repetitions=10", arg2[] = "--benchmark_report_aggregates_only=true";
char* my_params[] = {argv[0], arg1, arg2};
if (argc < 2) {
argc = 3;
argv = my_params;
}
::benchmark::Initialize(&argc, argv);
if (::benchmark::ReportUnrecognizedArguments(argc, argv))
return 1;
::benchmark::RunSpecifiedBenchmarks();
::benchmark::Shutdown();
return 0;
}

View File

@ -15,7 +15,7 @@
#define __has_declspec_attribute(x) 0
#endif
#ifdef SIMSTR_SHARED
#ifdef SIMSTR_IN_SHARED
#if defined(_MSC_VER) || (defined(__clang__) && __has_declspec_attribute(dllexport))
#ifdef SIMSTR_EXPORT
#define SIMSTR_API __declspec(dllexport)
@ -41,10 +41,10 @@ const bool isx64 = sizeof(void*) == 8; // NOLINT
#ifdef _MSC_VER
#define _no_unique_address msvc::no_unique_address
#define empty_bases __declspec(empty_bases)
#define decl_empty_bases __declspec(empty_bases)
#else
#define _no_unique_address no_unique_address
#define empty_bases
#define decl_empty_bases
#endif
#if defined __has_builtin
@ -3752,7 +3752,7 @@ class sstring;
* выделяется +n байтов, чтобы потом не копировать данные.
*/
template<typename K, size_t N, bool forShared = false, Allocatorable Allocator = allocator_string>
class empty_bases lstring :
class decl_empty_bases lstring :
public str_algs<K, simple_str<K>, lstring<K, N, forShared, Allocator>, true>,
public str_mutable<K, lstring<K, N, forShared, Allocator>>,
public str_storable<K, lstring<K, N, forShared, Allocator>, Allocator>,
@ -4220,7 +4220,7 @@ constexpr const size_t local_count = _local_count<sizeof(size_t), sizeof(T)>;
*/
template<typename K, Allocatorable Allocator = allocator_string>
class empty_bases sstring :
class decl_empty_bases sstring :
public str_algs<K, simple_str<K>, sstring<K, Allocator>, false>,
public str_storable<K, sstring<K, Allocator>, Allocator>,
public from_utf_convertable<K, sstring<K, Allocator>> {
@ -5987,7 +5987,7 @@ using stringa = sstring<u8s>;
using stringw = sstring<wchar_t>;
using stringu = sstring<u16s>;
using stringuu = sstring<u32s>;
static_assert(sizeof(stringa) == 24, "Bad size of sstring");
static_assert(sizeof(stringa) == (sizeof(void*) == 8 ? 24 : 16), "Bad size of sstring");
/*!
* @brief Тип хеш-словаря для char строк, регистрозависимый поиск

View File

@ -3,9 +3,27 @@
#
add_executable(testStr test_str.cpp)
target_link_libraries(testStr simstr::simstr GTest::gtest_main)
if (NOT SIMSTR_IN_SHARED)
target_link_libraries(testStr simstr::simstr GTest::gtest_main)
else()
# Пример создания экзешника, если simstr экспортируются из dll.
# Так как мы подключаем только simstr_dll, и входящие в неё либы не видны
# нужно вручную задать каталоги include и стандарт C++20
target_link_libraries(testStr simstr_dll GTest::gtest_main)
get_target_property(SIMSTR_INCLUDES simstr::simstr INCLUDE_DIRECTORIES)
target_include_directories(testStr PRIVATE ${SIMSTR_INCLUDES})
target_compile_features(testStr PUBLIC cxx_std_20)
endif()
add_test(NAME testStr COMMAND testStr)
if (EMSCRIPTEN)
set_target_properties (testStr PROPERTIES SUFFIX .html)
target_compile_options(testStr PUBLIC -Wno-warn-absolute-paths -Wno-unknown-warning-option -msimd128 -msse4.2 -msse3)
if(SIMSTR_EMSCRIPTEN_MT)
target_compile_options(testStr PUBLIC -pthread)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread -sPTHREAD_POOL_SIZE=navigator.hardwareConcurrency-1")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -sENVIRONMENT=web,worker")
endif()
endif(EMSCRIPTEN)