brotli-1.1.0-windows编译

        本文操作按照《c&c++开源库编译指南》中内容规范编写,编译环境配置、工具下载、目录规划,及更多其他开源库编译方法请参考该文章。

        c&c++开源库编译指南:https://blog.csdn.net/binary0006/article/details/144086155

        本文章中的源代码已提交到gitee仓库,地址:https://gitee.com/binary0010/depends/tree/master/c/brotli-1.1.0

1.brotli概述

        brotli 是 Google 开发的高效无损压缩算法,基于 LZ77 和霍夫曼编码,通过字典优化与灵活压缩级别(0-11),在文本、代码等场景下实现比 gzip 高约 20% 的压缩率,同时保持快速解压速度。其流式处理特性适配现代网络协议,成为 Web 性能优化的核心技术之一。

        brotli 广泛用于 Web 服务器(Nginx/Apache)与浏览器(Chrome/Firefox),通过 HTTP 压缩减少传输体积。移动端(如 Android)及文件存储领域(日志、配置)亦依赖其高压缩率降低资源消耗。开源代码支持多语言实现,BSD 许可推动跨平台集成,已成为 HTTPS 场景下提升数据传输效率的标准方案。

2.brotli编译

2.1.源代码下载

        brotli源代码可以在github上下载,源代码下载地址:https://github.com/google/brotli/tags,找到最新版1.1.0版本,点击下图所示链接直接下载即可。

        也可以自己复制这个地址下载:https://github.com/google/brotli/archive/refs/tags/v1.1.0.tar.gz 

2.2.windows编译

        先解压源代码到指定目录,brotli源代码中已经提供了CMakeList.txt脚本,后面我们按照规范会对该脚本进行修改。

2.2.1.源代码修改 

        由于brotil代码是c语言的,在vs2008中只支持c89标准语法,brotil代码中有一部分c99标准语法,为了支持vs2008我们对源代码进行修改。

2.2.2.修改CMake脚本

        修改CMake脚本按照我们的设计的编译规范来进行构建和编译,修改源代码根目录下的CMakeLists.txt即可。

        脚本涉及的内容主要是使用我们编译规范来对工程命名和输出,以及mt工程的链接库设置。

        CMakeLists.txt完整内容:

 

# Available CMake versions:
# - Ubuntu  20.04 LTS   : 3.16.3
# - Solaris 11.4 SRU 15 : 3.15
cmake_minimum_required(VERSION 3.15)

# Since this project's version is loaded from other files, this policy
# will help suppress the warning generated by cmake.
# This policy is set because we can't provide "VERSION" in "project" command.
# Use `cmake --help-policy CMP0048` for more information.
cmake_policy(SET CMP0048 NEW)
project(brotli C)

option(BUILD_SHARED_LIBS "Build shared libraries" ON)

if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  message(STATUS "Setting build type to Release as none was specified.")
  set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
else()
  message(STATUS "Build type is '${CMAKE_BUILD_TYPE}'")
endif()

include(CheckCSourceCompiles)
check_c_source_compiles(
  "#if defined(__EMSCRIPTEN__)
   int main() {return 0;}
   #endif"
  BROTLI_EMSCRIPTEN
)

if(BROTLI_EMSCRIPTEN)
  message("-- Compiler is EMSCRIPTEN")
else()
  message("-- Compiler is not EMSCRIPTEN")
endif()

# If Brotli is being bundled in another project, we don't want to
# install anything.  However, we want to let people override this, so
# we'll use the BROTLI_BUNDLED_MODE variable to let them do that; just
# set it to OFF in your project before you add_subdirectory(brotli).
get_directory_property(BROTLI_PARENT_DIRECTORY PARENT_DIRECTORY)

if(NOT DEFINED BROTLI_BUNDLED_MODE)
  # Bundled mode hasn't been set one way or the other, set the default
  # depending on whether or not we are the top-level project.
  if(BROTLI_PARENT_DIRECTORY)
    set(BROTLI_BUNDLED_MODE ON)
  else()
    set(BROTLI_BUNDLED_MODE OFF)
  endif()
endif()

mark_as_advanced(BROTLI_BUNDLED_MODE)

include(GNUInstallDirs)

# Reads macro from .h file; it is expected to be a single-line define.
function(read_macro PATH MACRO OUTPUT)
  file(STRINGS ${PATH} _line REGEX "^#define +${MACRO} +(.+)$")
  string(REGEX REPLACE "^#define +${MACRO} +(.+)$" "\\1" _val "${_line}")
  set(${OUTPUT} ${_val} PARENT_SCOPE)
endfunction(read_macro)

# Version information
read_macro("c/common/version.h" "BROTLI_VERSION_MAJOR" BROTLI_VERSION_MAJOR)
read_macro("c/common/version.h" "BROTLI_VERSION_MINOR" BROTLI_VERSION_MINOR)
read_macro("c/common/version.h" "BROTLI_VERSION_PATCH" BROTLI_VERSION_PATCH)
set(BROTLI_VERSION "${BROTLI_VERSION_MAJOR}.${BROTLI_VERSION_MINOR}.${BROTLI_VERSION_PATCH}")
mark_as_advanced(BROTLI_VERSION BROTLI_VERSION_MAJOR BROTLI_VERSION_MINOR BROTLI_VERSION_PATCH)

# ABI Version information
read_macro("c/common/version.h" "BROTLI_ABI_CURRENT" BROTLI_ABI_CURRENT)
read_macro("c/common/version.h" "BROTLI_ABI_REVISION" BROTLI_ABI_REVISION)
read_macro("c/common/version.h" "BROTLI_ABI_AGE" BROTLI_ABI_AGE)
math(EXPR BROTLI_ABI_COMPATIBILITY "${BROTLI_ABI_CURRENT} - ${BROTLI_ABI_AGE}")
mark_as_advanced(BROTLI_ABI_CURRENT BROTLI_ABI_REVISION BROTLI_ABI_AGE BROTLI_ABI_COMPATIBILITY)

set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake ${CMAKE_MODULE_PATH})
include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/third-common.cmake)

set(INSTALL_BIN_DIR "${third-bin}/${PROJECT_NAME}-${BROTLI_VERSION}" CACHE PATH "Installation directory for executables")
set(INSTALL_LIB_DIR "${third-lib}/${PROJECT_NAME}-${BROTLI_VERSION}" CACHE PATH "Installation directory for libraries")
set(INSTALL_INC_DIR "${third-include}/${PROJECT_NAME}-${BROTLI_VERSION}" CACHE PATH "Installation directory for headers")
set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")

if(ENABLE_SANITIZER)
  set(CMAKE_C_FLAGS " ${CMAKE_C_FLAGS} -fsanitize=${ENABLE_SANITIZER}")
  set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -fsanitize=${ENABLE_SANITIZER}")
  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=${ENABLE_SANITIZER}")
endif()

include(CheckFunctionExists)
set(LIBM_LIBRARY)
CHECK_FUNCTION_EXISTS(log2 LOG2_RES)

if(NOT LOG2_RES)
  set(orig_req_libs "${CMAKE_REQUIRED_LIBRARIES}")
  set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES};m")
  CHECK_FUNCTION_EXISTS(log2 LOG2_LIBM_RES)

  if(LOG2_LIBM_RES)
    set(LIBM_LIBRARY "m")
    add_definitions(-DBROTLI_HAVE_LOG2=1)
  else()
    add_definitions(-DBROTLI_HAVE_LOG2=0)
  endif()

  set(CMAKE_REQUIRED_LIBRARIES "${orig_req_libs}")
  unset(LOG2_LIBM_RES)
  unset(orig_req_libs)
else()
  add_definitions(-DBROTLI_HAVE_LOG2=1)
endif()

unset(LOG2_RES)

set(BROTLI_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/c/include")
mark_as_advanced(BROTLI_INCLUDE_DIRS)

# set(BROTLI_LIBRARIES_CORE brotlienc brotlidec brotlicommon)
# set(BROTLI_LIBRARIES ${BROTLI_LIBRARIES_CORE} ${LIBM_LIBRARY})
# mark_as_advanced(BROTLI_LIBRARIES)
set(BROTLI_LIBRARIES_CORE_DLL brotliencdll brotlidecdll brotlicommondll)
set(BROTLI_LIBRARIES_DLL ${BROTLI_LIBRARIES_CORE_DLL} ${LIBM_LIBRARY})
mark_as_advanced(BROTLI_LIBRARIES_DLL)

set(BROTLI_LIBRARIES_CORE_LIB brotlienclib brotlideclib brotlicommonlib)
set(BROTLI_LIBRARIES_LIB ${BROTLI_LIBRARIES_CORE_LIB} ${LIBM_LIBRARY})
mark_as_advanced(BROTLI_LIBRARIES_LIB)

set(BROTLI_LIBRARIES_CORE_DLL_MT brotliencdllmt brotlidecdllmt brotlicommondllmt)
set(BROTLI_LIBRARIES_DLL_MT ${BROTLI_LIBRARIES_CORE_DLL_MT} ${LIBM_LIBRARY})
mark_as_advanced(BROTLI_LIBRARIES_DLL_MT)

set(BROTLI_LIBRARIES_CORE_LIB_MT brotlienclibmt brotlideclibmt brotlicommonlibmt)
set(BROTLI_LIBRARIES_LIB_MT ${BROTLI_LIBRARIES_CORE_LIB_MT} ${LIBM_LIBRARY})
mark_as_advanced(BROTLI_LIBRARIES_LIB_MT)

if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
  add_definitions(-DOS_LINUX)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
  add_definitions(-DOS_FREEBSD)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
  add_definitions(-DOS_MACOSX)
  set(CMAKE_MACOS_RPATH TRUE)
  set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib")
endif()

if(BROTLI_EMSCRIPTEN)
  set(BUILD_SHARED_LIBS OFF)
endif()

file(GLOB_RECURSE BROTLI_COMMON_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} c/common/*.c)

# add_library(brotlicommon ${BROTLI_COMMON_SOURCES})
file(GLOB_RECURSE BROTLI_DEC_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} c/dec/*.c)

# add_library(brotlidec ${BROTLI_DEC_SOURCES})
file(GLOB_RECURSE BROTLI_ENC_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} c/enc/*.c)

# add_library(brotlienc ${BROTLI_ENC_SOURCES})
add_library(brotlicommondll SHARED ${BROTLI_COMMON_SOURCES})
add_library(brotlidecdll SHARED ${BROTLI_DEC_SOURCES})
add_library(brotliencdll SHARED ${BROTLI_ENC_SOURCES})

add_library(brotlicommonlib STATIC ${BROTLI_COMMON_SOURCES})
add_library(brotlideclib STATIC ${BROTLI_DEC_SOURCES})
add_library(brotlienclib STATIC ${BROTLI_ENC_SOURCES})

# vs编译器特化设置
if(MSVC)
  # mt动态库工程
  add_library(brotlicommondllmt SHARED ${BROTLI_COMMON_SOURCES})
  set_property(TARGET brotlicommondllmt PROPERTY
    MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

  add_library(brotlidecdllmt SHARED ${BROTLI_DEC_SOURCES})
  set_property(TARGET brotlidecdllmt PROPERTY
    MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

  add_library(brotliencdllmt SHARED ${BROTLI_ENC_SOURCES})
  set_property(TARGET brotliencdllmt PROPERTY
    MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

  # mt静态库工程
  add_library(brotlicommonlibmt STATIC ${BROTLI_COMMON_SOURCES})
  set_property(TARGET brotlicommonlibmt PROPERTY
    MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

  add_library(brotlideclibmt STATIC ${BROTLI_DEC_SOURCES})
  set_property(TARGET brotlideclibmt PROPERTY
    MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

  add_library(brotlienclibmt STATIC ${BROTLI_ENC_SOURCES})
  set_property(TARGET brotlienclibmt PROPERTY
    MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

  # 设置静态库pdb文件
  set_lib_pdb_file(brotlicommon lib)
  set_lib_pdb_file(brotlidec lib)
  set_lib_pdb_file(brotlienc lib)

  set_lib_pdb_file(brotlicommon libmt)
  set_lib_pdb_file(brotlidec libmt)
  set_lib_pdb_file(brotlienc libmt)
endif()

# Older CMake versions does not understand INCLUDE_DIRECTORIES property.
include_directories(${BROTLI_INCLUDE_DIRS})

if(BUILD_SHARED_LIBS)
  foreach(lib ${BROTLI_LIBRARIES_CORE})
    target_compile_definitions(${lib} PUBLIC "BROTLI_SHARED_COMPILATION")
    string(TOUPPER "${lib}" LIB)
    set_target_properties(${lib} PROPERTIES DEFINE_SYMBOL "${LIB}_SHARED_COMPILATION")
  endforeach()
endif()

# 设置动态库宏定义
target_compile_definitions(brotlicommondll PUBLIC "BROTLI_SHARED_COMPILATION")
set_target_properties(brotlicommondll PROPERTIES DEFINE_SYMBOL "BROTLICOMMON_SHARED_COMPILATION")

target_compile_definitions(brotlidecdll PUBLIC "BROTLI_SHARED_COMPILATION")
set_target_properties(brotlidecdll PROPERTIES DEFINE_SYMBOL "BROTLIDEC_SHARED_COMPILATION")

target_compile_definitions(brotliencdll PUBLIC "BROTLI_SHARED_COMPILATION")
set_target_properties(brotliencdll PROPERTIES DEFINE_SYMBOL "BROTLIENC_SHARED_COMPILATION")

target_compile_definitions(brotlicommondllmt PUBLIC "BROTLI_SHARED_COMPILATION")
set_target_properties(brotlicommondllmt PROPERTIES DEFINE_SYMBOL "BROTLICOMMON_SHARED_COMPILATION")

target_compile_definitions(brotlidecdllmt PUBLIC "BROTLI_SHARED_COMPILATION")
set_target_properties(brotlidecdllmt PROPERTIES DEFINE_SYMBOL "BROTLIDEC_SHARED_COMPILATION")

target_compile_definitions(brotliencdllmt PUBLIC "BROTLI_SHARED_COMPILATION")
set_target_properties(brotliencdllmt PROPERTIES DEFINE_SYMBOL "BROTLIENC_SHARED_COMPILATION")

# foreach(lib ${BROTLI_LIBRARIES_CORE_DLL} ${BROTLI_LIBRARIES_CORE_DLL_MT})
# target_compile_definitions(${lib} PUBLIC "BROTLI_SHARED_COMPILATION")
# string(TOUPPER "${lib}" LIB)
# set_target_properties(${lib} PROPERTIES DEFINE_SYMBOL "${LIB}_SHARED_COMPILATION")
# endforeach()
foreach(lib ${BROTLI_LIBRARIES_CORE})
  target_link_libraries(${lib} ${LIBM_LIBRARY})
  set_property(TARGET ${lib} APPEND PROPERTY INCLUDE_DIRECTORIES ${BROTLI_INCLUDE_DIRS})
  set_target_properties(${lib} PROPERTIES
    VERSION "${BROTLI_ABI_COMPATIBILITY}.${BROTLI_ABI_AGE}.${BROTLI_ABI_REVISION}"
    SOVERSION "${BROTLI_ABI_COMPATIBILITY}")

  if(NOT BROTLI_EMSCRIPTEN)
    set_target_properties(${lib} PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
  endif()

  set_property(TARGET ${lib} APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${BROTLI_INCLUDE_DIRS}>")
endforeach()

if(NOT BROTLI_EMSCRIPTEN)
  # target_link_libraries(brotlidec brotlicommon)
  # target_link_libraries(brotlienc brotlicommon)
  target_link_libraries(brotlidecdll brotlicommondll)
  add_dependencies(brotlidecdll brotlicommondll)

  target_link_libraries(brotliencdll brotlicommondll)
  add_dependencies(brotliencdll brotlicommondll)

  target_link_libraries(brotlidecdllmt brotlicommondllmt)
  add_dependencies(brotlidecdllmt brotlicommondllmt)

  target_link_libraries(brotliencdllmt brotlicommondllmt)
  add_dependencies(brotliencdllmt brotlicommondllmt)
endif()

# For projects stuck on older versions of CMake, this will set the
# BROTLI_INCLUDE_DIRS and BROTLI_LIBRARIES variables so they still
# have a relatively easy way to use Brotli:
#
# include_directories(${BROTLI_INCLUDE_DIRS})
# target_link_libraries(foo ${BROTLI_LIBRARIES})
if(BROTLI_PARENT_DIRECTORY)
  set(BROTLI_INCLUDE_DIRS "${BROTLI_INCLUDE_DIRS}" PARENT_SCOPE)
  set(BROTLI_LIBRARIES "${BROTLI_LIBRARIES}" PARENT_SCOPE)
endif()

# Build the brotli executable
add_executable(brotli c/tools/brotli.c)

# target_link_libraries(brotli ${BROTLI_LIBRARIES})
target_link_libraries(brotli ${BROTLI_LIBRARIES_CORE_LIB})

# Installation
if(NOT BROTLI_BUNDLED_MODE)
  # install(
  # TARGETS brotli
  # RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
  # )

  # install(
  # TARGETS ${BROTLI_LIBRARIES_CORE}
  # ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
  # LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
  # RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
  # )

  # install(
  # DIRECTORY ${BROTLI_INCLUDE_DIRS}/brotli
  # DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
  # )
  install(
    DIRECTORY ${BROTLI_INCLUDE_DIRS}/brotli
    DESTINATION "${INSTALL_INC_DIR}"
  )

  install(
    TARGETS brotli
    RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
  )

  install(
    TARGETS ${BROTLI_LIBRARIES_CORE_DLL} ${BROTLI_LIBRARIES_CORE_LIB} ${BROTLI_LIBRARIES_CORE_DLL_MT} ${BROTLI_LIBRARIES_CORE_LIB_MT}
    RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
    ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
    LIBRARY DESTINATION "${INSTALL_LIB_DIR}"
  )

  # 定义一个空列表来存储所有要安装的 PDB 文件
  set(PDB_FILES_TO_INSTALL "")
  # 遍历 BROTLI_LIBRARIES_CORE_DLL 列表
  foreach(TARGET ${BROTLI_LIBRARIES_CORE_DLL})
    list(APPEND PDB_FILES_TO_INSTALL $<TARGET_PDB_FILE:${TARGET}>)
  endforeach()
  # 遍历 BROTLI_LIBRARIES_CORE_DLL_MT 列表
  foreach(TARGET ${BROTLI_LIBRARIES_CORE_DLL_MT})
    list(APPEND PDB_FILES_TO_INSTALL $<TARGET_PDB_FILE:${TARGET}>)
  endforeach()
  # 安装所有 PDB 文件
  install(FILES ${PDB_FILES_TO_INSTALL}
    DESTINATION "${INSTALL_BIN_DIR}"
    OPTIONAL
  )

  # 静态库pdb调用函数安装
  install_lib_pdb_file(brotlicommon lib)
  install_lib_pdb_file(brotlienc lib)
  install_lib_pdb_file(brotlidec lib)
  install_lib_pdb_file(brotlicommon libmt)
  install_lib_pdb_file(brotlienc libmt)
  install_lib_pdb_file(brotlidec libmt)  
endif() # BROTLI_BUNDLED_MODE

# Tests

# If we're targeting Windows but not running on Windows, we need Wine
# to run the tests...
if(NOT BROTLI_DISABLE_TESTS)
  if(WIN32 AND NOT CMAKE_HOST_WIN32)
    find_program(BROTLI_WRAPPER NAMES wine)

    if(NOT BROTLI_WRAPPER)
      message(STATUS "wine not found, disabling tests")
      set(BROTLI_DISABLE_TESTS TRUE)
    endif()
  endif()
endif()

# If our compiler is a cross-compiler that we know about (arm/aarch64),
# then we need to use qemu to execute the tests.
if(NOT BROTLI_DISABLE_TESTS)
  if("${CMAKE_C_COMPILER}" MATCHES "^.*/arm-linux-gnueabihf-.*$")
    message(STATUS "Detected arm-linux-gnueabihf cross-compilation")
    set(BROTLI_WRAPPER "qemu-arm")
    set(BROTLI_WRAPPER_LD_PREFIX "/usr/arm-linux-gnueabihf")
  endif()

  if("${CMAKE_C_COMPILER}" MATCHES "^.*/arm-linux-gnueabi-.*$")
    message(STATUS "Detected arm-linux-gnueabi cross-compilation")
    set(BROTLI_WRAPPER "qemu-arm")
    set(BROTLI_WRAPPER_LD_PREFIX "/usr/arm-linux-gnueabi")
  endif()

  if("${CMAKE_C_COMPILER}" MATCHES "^.*/aarch64-linux-gnu-.*$")
    message(STATUS "Detected aarch64-linux-gnu cross-compilation")
    set(BROTLI_WRAPPER "qemu-aarch64")
    set(BROTLI_WRAPPER_LD_PREFIX "/usr/aarch64-linux-gnu")
  endif()
endif()

if(NOT BROTLI_DISABLE_TESTS)
  include(CTest)
  enable_testing()

  set(ROUNDTRIP_INPUTS
    tests/testdata/alice29.txt
    tests/testdata/asyoulik.txt
    tests/testdata/lcet10.txt
    tests/testdata/plrabn12.txt
    c/enc/encode.c
    c/common/dictionary.h
    c/dec/decode.c)

  foreach(INPUT ${ROUNDTRIP_INPUTS})
    get_filename_component(OUTPUT_NAME "${INPUT}" NAME)

    set(OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_NAME}")
    set(INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${INPUT}")

    if(EXISTS "${INPUT_FILE}")
      foreach(quality 1 6 9 11)
        add_test(NAME "${BROTLI_TEST_PREFIX}roundtrip/${INPUT}/${quality}"
          COMMAND "${CMAKE_COMMAND}"
          -DBROTLI_WRAPPER=${BROTLI_WRAPPER}
          -DBROTLI_WRAPPER_LD_PREFIX=${BROTLI_WRAPPER_LD_PREFIX}
          -DBROTLI_CLI=$<TARGET_FILE:brotli>
          -DQUALITY=${quality}
          -DINPUT=${INPUT_FILE}
          -DOUTPUT=${OUTPUT_FILE}.${quality}
          -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/run-roundtrip-test.cmake)
      endforeach()
    else()
      message(WARNING "Test file ${INPUT} does not exist.")
    endif()
  endforeach()

  file(GLOB_RECURSE
    COMPATIBILITY_INPUTS
    RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
    tests/testdata/*.compressed*)

  foreach(INPUT ${COMPATIBILITY_INPUTS})
    add_test(NAME "${BROTLI_TEST_PREFIX}compatibility/${INPUT}"
      COMMAND "${CMAKE_COMMAND}"
      -DBROTLI_WRAPPER=${BROTLI_WRAPPER}
      -DBROTLI_WRAPPER_LD_PREFIX=${BROTLI_WRAPPER_LD_PREFIX}
      -DBROTLI_CLI=$<TARGET_FILE:brotli>
      -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/${INPUT}
      -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/run-compatibility-test.cmake)
  endforeach()
endif()

# Generate a pkg-config files

# function(generate_pkg_config_path outvar path)
# string(LENGTH "${path}" path_length)

# set(path_args ${ARGV})
# list(REMOVE_AT path_args 0 1)
# list(LENGTH path_args path_args_remaining)

# set("${outvar}" "${path}")

# while(path_args_remaining GREATER 1)
# list(GET path_args 0 name)
# list(GET path_args 1 value)

# get_filename_component(value_full "${value}" ABSOLUTE)
# string(LENGTH "${value}" value_length)

# if(path_length EQUAL value_length AND path STREQUAL value)
# set("${outvar}" "\${${name}}")
# break()
# elseif(path_length GREATER value_length)
# # We might be in a subdirectory of the value, but we have to be
# # careful about a prefix matching but not being a subdirectory
# # (for example, /usr/lib64 is not a subdirectory of /usr/lib).
# # We'll do this by making sure the next character is a directory
# # separator.
# string(SUBSTRING "${path}" ${value_length} 1 sep)
# if(sep STREQUAL "/")
# string(SUBSTRING "${path}" 0 ${value_length} s)
# if(s STREQUAL value)
# string(SUBSTRING "${path}" "${value_length}" -1 suffix)
# set("${outvar}" "\${${name}}${suffix}")
# break()
# endif()
# endif()
# endif()

# list(REMOVE_AT path_args 0 1)
# list(LENGTH path_args path_args_remaining)
# endwhile()

# set("${outvar}" "${${outvar}}" PARENT_SCOPE)
# endfunction(generate_pkg_config_path)

# function(transform_pc_file INPUT_FILE OUTPUT_FILE VERSION)
# file(READ ${INPUT_FILE} TEXT)

# set(PREFIX "${CMAKE_INSTALL_PREFIX}")
# string(REGEX REPLACE "@prefix@" "${PREFIX}" TEXT ${TEXT})
# string(REGEX REPLACE "@exec_prefix@" "${PREFIX}" TEXT ${TEXT})

# generate_pkg_config_path(LIBDIR "${CMAKE_INSTALL_FULL_LIBDIR}" prefix "${PREFIX}")
# string(REGEX REPLACE "@libdir@" "${LIBDIR}" TEXT ${TEXT})

# generate_pkg_config_path(INCLUDEDIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}" prefix "${PREFIX}")
# string(REGEX REPLACE "@includedir@" "${INCLUDEDIR}" TEXT ${TEXT})

# string(REGEX REPLACE "@PACKAGE_VERSION@" "${VERSION}" TEXT ${TEXT})

# file(WRITE ${OUTPUT_FILE} ${TEXT})
# endfunction()

# transform_pc_file("scripts/libbrotlicommon.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/libbrotlicommon.pc" "${BROTLI_VERSION}")

# transform_pc_file("scripts/libbrotlidec.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/libbrotlidec.pc" "${BROTLI_VERSION}")

# transform_pc_file("scripts/libbrotlienc.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/libbrotlienc.pc" "${BROTLI_VERSION}")

# if(NOT BROTLI_BUNDLED_MODE)
# install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libbrotlicommon.pc"
# DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
# install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libbrotlidec.pc"
# DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
# install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libbrotlienc.pc"
# DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
# endif() # BROTLI_BUNDLED_MODE

# if(ENABLE_COVERAGE STREQUAL "yes")
# SETUP_TARGET_FOR_COVERAGE(coverage test coverage)
# endif()

 2.2.3.vs2008编译

        前面我们已经把vs2008编译错误需要处理的代码以及CMakeLists.txt脚本按照规范修改完毕,下面我们将使用cmake来构建vs2008的工程和编译。

2.2.3.1.cmake构建目录设置

        选择源代码根目录(CMakeLists.txt文件在这个目录),设置build目录为源代码根目录下的cmake-vs2008绝对路径为D:/x-app/depends/c/brotli-1.1.0/cmake-vs2008,保证源代码目录干净,会生成工程和临时文件,同时也方便后续有其他的构建工具扩展管理。

2.2.3.2.应用CMake配置 

        点击“Configure”会弹出编译器选择对话框,这里选择“Visual Studio 9 2008”点击“Finish”按钮等待配置参数完成。

2.2.3.3.去掉不需要的编译选项 

        因为前面CMakLists.txt脚本被我们修改了,所以这里一定要去掉下面截图所示的2个选项,否则构建时CMake会报错。

 2.2.3.4.生成vs解决方案

        下面的红色警告忽略不用管,意思是未来的cmake版本不再支持生成vs2008的解决方案。

 2.2.3.5.编译工程

        使用vs2008打开“brotli.sln”解决方案文件,分别编译Debug和RelWithDebInfo配置。

 2.2.3.6.安装库文件、头文件

        编译Install工程的Debug和RelWithDebInfo配置,.h文件和编译生成.dll、.lib、pdb文件会拷贝CMakeList.txt中设置的路径下。

         至此通过一个CMakeLists配置文件将windows下vs2008常用编译类型的库全部编译出来了,最终库的对应关系如下。

库类型

运行库类型

库文件

动态库

mdd

brotlicommondlld.dll、brotlicommondlld.lib

brotlidecdlld.dll、brotlidecdlld.lib

brotlidecdlld.dll、brotlidecdlldlld.lib

md

brotlicommondll.dll、brotlicommondll.lib

brotlidecdll.dll、brotlidecdll.lib

brotlidecdll.dll、brotlidecdlldll.lib

mtd

brotlicommondllmtd.dll、brotlicommondllmtd.lib

brotlidecdllmtd.dll、brotlidecdllmtd.lib

brotlidecdllmtd.dll、brotlidecdlldllmtd.lib

mt

brotlicommondllmt.dll、brotlicommondllmt.lib

brotlidecdllmt.dll、brotlidecdllmt.lib

brotlidecdllmt.dll、brotlidecdlldllmt.lib

静态库

mdd

brotlicommonlibd.lib

Brotlideclibd.dll

brotlideclibd.dll

md

brotlicommonlib.lib

brotlideclibd.dll

brotlideclibd.dll

mtd

brotlicommonlibmtd.lib

brotlideclibmtd.dll

brotlideclibmtd.dll

mt

brotlicommonlibmt.lib

brotlideclibmt.dll

brotlideclibmt.dll

 2.2.4.vs2015编译

        vs2015编译与vs2008相同的,只需要在CMake生成工程时选择vs2015即可,其他版本的vs也是一样的,选择需要使用的vs版本即可,此处只演示一下vs2015的编译。

        因为前面生成过vs2008的工程,需要将build目录设置成cmake-vs2015,再“Configure”选择vs2015即可,其他操作就是一样的了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

binary0010

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值