本文展示如何用CMake编译Secretyflow的Yacl。
前置条件:"*.proto"文件已经用Google protobuf编译好。安装好Yacl文件repositories.bzl中指定的库。这些库安装时最好设置POSITION_INDEPENDENT_CODE=ON,
set(POSITION_INDEPENDENT_CODE True)
或运行cmake命令时加入“-DCMAKE_POSITION_INDEPENDENT_CODE=ON”。
首先展示编译Secretflow的interconnection。
cmake_minimum_required(VERSION 3.10)
project(interconnection)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY lib)
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_FLAGS "-fPIC")
include_directories(/usr/local/include)
add_compile_options(-mavx2 -mbmi2)
set(SRC_DIR ./interconnection)
set(ALL_SRC )
function(SearchR _DIR SRC)
set(DIR ${${_DIR}})
set(Tmp_List )
foreach(TMP_DIR ${DIR})
file(GLOB_RECURSE LIST "${TMP_DIR}/*.cc" "${TMP_DIR}/*.c")
list(FILTER LIST EXCLUDE REGEX ".*test.cc")
list(FILTER LIST EXCLUDE REGEX ".*bench.cc")
list(APPEND Tmp_List ${LIST})
endforeach()
set(${SRC} ${Tmp_List} PARENT_SCOPE)
endfunction(SearchR)
SearchR(SRC_DIR ALL_SRC)
message("All Source files are ${ALL_SRC}")
add_library(interconnection STATIC ${ALL_SRC})
target_link_libraries(interconnection brpc ssl crypto)
target_link_libraries(interconnection tommath)
target_link_libraries(interconnection gflags leveldb snappy protobuf cpu_features spdlog benchmark)
target_link_libraries(interconnection absl_bad_any_cast_impl absl_bad_optional_access absl_bad_variant_access absl_base)
target_link_libraries(interconnection absl_city absl_civil_time absl_cord absl_cord_internal absl_cordz_functions)
target_link_libraries(interconnection absl_cordz_handle absl_cordz_info absl_cordz_sample_token absl_crc32c absl_crc_cord_state)
target_link_libraries(interconnection absl_crc_cpu_detect absl_crc_internal absl_debugging_internal absl_demangle_internal)
target_link_libraries(interconnection fmt gtest pthread)
另外YACL依赖secretflow的simplest OT库,cmake脚本如下。
cmake_minimum_required(VERSION 3.10)
enable_language(ASM)
project(simplest_ot)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY &{PROJECT_SOURCE_DIR})
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE -no-pie")
include_directories(/usr/local/include)
add_compile_options(-mavx2 -mbmi2)
set(SRC_DIR ./simplest_ot_portable)
set(ALL_SRC )
set(S_SRC)
function(SearchR _DIR SRC)
set(DIR ${${_DIR}})
set(Tmp_List )
foreach(TMP_DIR ${DIR})
file(GLOB_RECURSE LIST "${TMP_DIR}/*.cc" "${TMP_DIR}/*.c")
list(FILTER LIST EXCLUDE REGEX ".*test.cc")
list(FILTER LIST EXCLUDE REGEX ".*bench.cc")
list(APPEND Tmp_List ${LIST})
endforeach()
set(${SRC} ${Tmp_List} PARENT_SCOPE)
endfunction(SearchR)
function(SearchS _DIR SRC)
set(DIR ${${_DIR}})
set(Tmp_List )
foreach(TMP_DIR ${DIR})
file(GLOB_RECURSE LIST "${TMP_DIR}/*.S")
list(APPEND Tmp_List ${LIST})
endforeach()
set(${SRC} ${Tmp_List} PARENT_SCOPE)
endfunction(SearchS)
SearchR(SRC_DIR ALL_SRC)
message("All Source files are ${ALL_SRC}")
add_library(simplest_ot_portable STATIC ${ALL_SRC})
SearchS(SRC_DIR S_SRC)
target_sources(simplest_ot_portable PRIVATE ${S_SRC})
target_link_libraries(simplest_ot_portable brpc ssl crypto)
target_link_libraries(simplest_ot_portable tommath)
target_link_libraries(simplest_ot_portable gflags leveldb snappy protobuf cpu_features spdlog benchmark)
target_link_libraries(simplest_ot_portable absl_bad_any_cast_impl absl_bad_optional_access absl_bad_variant_access absl_base)
target_link_libraries(simplest_ot_portable absl_city absl_civil_time absl_cord absl_cord_internal absl_cordz_functions)
target_link_libraries(simplest_ot_portable absl_cordz_handle absl_cordz_info absl_cordz_sample_token absl_crc32c absl_crc_cord_state)
target_link_libraries(simplest_ot_portable absl_crc_cpu_detect absl_crc_internal absl_debugging_internal absl_demangle_internal)
target_link_libraries(simplest_ot_portable fmt gtest pthread)
set(SRC_DIR ./simplest_ot_x86_asm)
set(ALL_SRC )
SearchR(SRC_DIR ALL_SRC)
message("All Source files are ${ALL_SRC}")
set(ASM_lib simplest_ot_x86_asm)
add_library(${ASM_lib} STATIC ${ALL_SRC})
SearchS(SRC_DIR S_SRC)
target_sources(${ASM_lib} PRIVATE ${S_SRC})
target_link_libraries(${ASM_lib} brpc ssl crypto)
target_link_libraries(${ASM_lib} tommath)
target_link_libraries(${ASM_lib} gflags leveldb snappy protobuf cpu_features spdlog benchmark)
target_link_libraries(${ASM_lib} absl_bad_any_cast_impl absl_bad_optional_access absl_bad_variant_access absl_base)
target_link_libraries(${ASM_lib} absl_city absl_civil_time absl_cord absl_cord_internal absl_cordz_functions)
target_link_libraries(${ASM_lib} absl_cordz_handle absl_cordz_info absl_cordz_sample_token absl_crc32c absl_crc_cord_state)
target_link_libraries(${ASM_lib} absl_crc_cpu_detect absl_crc_internal absl_debugging_internal absl_demangle_internal)
target_link_libraries(${ASM_lib} fmt gtest pthread)
下面是编译Yacl的CMakeLists.txt。
cmake_minimum_required(VERSION 3.10)
project(yacl)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY lib)
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_FLAGS "-fPIC")
include_directories(/usr/local/include /usr/local/include/sodium/ /root/intel/ippcp_2021.8.0/include)
link_directories(/root/intel/ippcp_2021.8.0/lib/intel64/ )
add_compile_options(-mfma -mavx2 -mbmi2 -maes -mpclmul)
set(SRC_DIR ./yacl)
set(ALL_SRC )
set(Link_SRC )
function(SearchR _DIR SRC)
set(DIR ${${_DIR}})
set(Tmp_List )
foreach(TMP_DIR ${DIR})
file(GLOB_RECURSE LIST "${TMP_DIR}/*.cc" "${TMP_DIR}/*.c")
list(FILTER LIST EXCLUDE REGEX ".*test.cc")
list(FILTER LIST EXCLUDE REGEX ".*bench.cc")
list(FILTER LIST EXCLUDE REGEX ".*benchmark.*")
list(APPEND Tmp_List ${LIST})
endforeach()
set(${SRC} ${Tmp_List} PARENT_SCOPE)
endfunction(SearchR)
SearchR(SRC_DIR ALL_SRC)
set(Provider_DIR ./yacl/crypto/ossl-provider)
SearchR(Provider_DIR Provider_SRC)
message("All Source files are ${ALL_SRC}")
add_library(${PROJECT_NAME} STATIC ${ALL_SRC})
message("Shared Libraries from ${Provider_SRC}")
add_library(prov_shared SHARED ${Provider_SRC})
target_link_libraries(${PROJECT_NAME} sodium mcl blake3)
target_link_libraries(${PROJECT_NAME} libcrypto_mb.a libippcp.a)
target_link_libraries(${PROJECT_NAME} brpc ssl crypto interconnection)
target_link_libraries(${PROJECT_NAME} tommath)
target_link_libraries(${PROJECT_NAME} gflags leveldb snappy protobuf cpu_features spdlog benchmark)
target_link_libraries(${PROJECT_NAME} absl_bad_any_cast_impl absl_bad_optional_access absl_bad_variant_access absl_base)
target_link_libraries(${PROJECT_NAME} absl_city absl_civil_time absl_cord absl_cord_internal absl_cordz_functions)
target_link_libraries(${PROJECT_NAME} absl_cordz_handle absl_cordz_info absl_cordz_sample_token absl_crc32c absl_crc_cord_state)
target_link_libraries(${PROJECT_NAME} absl_crc_cpu_detect absl_crc_internal absl_debugging_internal absl_demangle_internal)
target_link_libraries(${PROJECT_NAME} fmt gtest z pthread)
target_link_libraries(prov_shared ssl crypto spdlog fmt)
INSTALL(TARGETS prov_shared ${PROJECT_NAME}
RUNTIME DESTINATION /execroot/bin/
LIBRARY DESTINATION /execroot/bin/yacl/crypto/ossl-provider/
ARCHIVE DESTINATION /usr/local/lib
)
需要注意的地方:
- spdlog可能会屏蔽fmt的一些宏。需要用户自己调整头文件的顺序,即spdlog依赖fmt。
- spi_factory.h中重复注册库不必终止程序,可以自行修改这一部分代码。即
if (creator_map_.count(lib_key) > 0)
return;
//YACL_ENFORCE(creator_map_.count(lib_key) == 0,
// "SPI lib name conflict, {} already exist", lib_key);
那么重复包含有注册类对象的头文件就不用担心重复注册库。
3. OSSL_PROVIDER_load调用之前就需要把相应动态库加载进内存。链接yacl的程序尽量在/execroot/bin下运行,libprov_shared.so放在/execroot/bin/yacl/crypto/ossl-provider/. 这样做的目的是为了适应ossl-provider/helper.h.
下面解释如何链接Yacl的静态库。
Registration
Yacl使用Registration,见spi_factory.h. 链接Yacl库时不一定能链接到这些注册类的对象,从而不会注册这些信息。可以如下查看注册的信息,
std::vector<std::string> names = yacl::math::GaloisFieldFactory::Instance().ListLibraries();
std::cout << " list names \n";
for(auto i = names.begin(); i!=names.end(); ++i)
{
std::cout << *i << '\n';
}
要确保链接到注册类的对象,可以如下注册一个冗余的库。
REGISTER_GF_LIBRARY(" ", 1, MPIntField::Check, MPIntField::Create);