From 67bf3d1381b1faf59e87001d6156ba4e21cada14 Mon Sep 17 00:00:00 2001 From: crueter Date: Mon, 29 Dec 2025 21:22:36 -0500 Subject: [PATCH] [cmake] refactor: shared/static handling This significantly redoes the way shared and static libraries are handled. Now, it's controlled by two options: `SPIRV_TOOLS_BUILD_STATIC` and `SPIRV_TOOLS_BUILD_SHARED`. The default configuration (no `BUILD_SHARED_LIBS` set, options left at default) is to build shared ONLY if this is the master project, or static ONLY if this is a subproject (e.g. FetchContent, CPM.cmake). Also I should note that static-only (i.e. no shared) is now a supported target, this is done because projects including it as a submodule e.g. on Android or Windows may prefer this. Now the shared/static handling: - static ON, shared OFF: Only generates `.a` libraries. - static ON, shared ON: Generates `.a` libraries, but also `libSPIRV-Tools.so` - static OFF, shared ON: Only generates `.so` libraries. Notable TODOs: - SPIRV-Tools-shared.pc seems redundant--how should we handle which one to use in the case of distributions that distribute both types (MSYS2 for instance)? * *Note: pkgconfig sucks at this and usually just leaves it up to the user, so the optimal solution may indeed be doing absolutely nothing.* CMake is unaffected :) - use namespaces in the CMake config files pleaaaaase This is going to change things a good bit for package maintainers, but cest la vie. It's for the greater good, I promise. Signed-off-by: crueter --- CMakeLists.txt | 108 +++++++++++++++++++++++++----------------- source/CMakeLists.txt | 62 ++++++++++++------------ 2 files changed, 94 insertions(+), 76 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d843b4d2f..07201f690f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,15 @@ cmake_minimum_required(VERSION 3.22.1) +# master project detection--useful for FetchContent/submodule inclusion +set(master_project OFF) +set(subproject ON) + +if (NOT DEFINED PROJECT_NAME) + set(master_project ON) + set(subproject OFF) +endif() + project(spirv-tools) # Avoid a bug in CMake 3.22.1. By default it will set -std=c++11 for @@ -135,46 +144,49 @@ if (DEFINED SPIRV_TOOLS_EXTRA_DEFINITIONS) add_definitions(${SPIRV_TOOLS_EXTRA_DEFINITIONS}) endif() -# Library build setting definitions: -# -# * SPIRV_TOOLS_BUILD_STATIC - ON or OFF - Defaults to ON. -# If enabled the following targets will be created: -# ${SPIRV_TOOLS}-static - STATIC library. -# Has full public symbol visibility. -# ${SPIRV_TOOLS}-shared - SHARED library. -# Has default-hidden symbol visibility. -# ${SPIRV_TOOLS} - will alias to one of above, based on BUILD_SHARED_LIBS. -# If disabled the following targets will be created: -# ${SPIRV_TOOLS} - either STATIC or SHARED based on SPIRV_TOOLS_LIBRARY_TYPE. -# Has full public symbol visibility. -# ${SPIRV_TOOLS}-shared - SHARED library. -# Has default-hidden symbol visibility. -# -# * SPIRV_TOOLS_LIBRARY_TYPE - SHARED or STATIC. -# Specifies the library type used for building SPIRV-Tools libraries. -# Defaults to SHARED when BUILD_SHARED_LIBS=1, otherwise STATIC. -# -# * SPIRV_TOOLS_FULL_VISIBILITY - "${SPIRV_TOOLS}-static" or "${SPIRV_TOOLS}" -# Evaluates to the SPIRV_TOOLS target library name that has no hidden symbols. -# This is used by internal targets for accessing symbols that are non-public. -# Note this target provides no API stability guarantees. -# -# Ideally, all of these will go away - see https://github.com/KhronosGroup/SPIRV-Tools/issues/3909. -option(ENABLE_EXCEPTIONS_ON_MSVC "Build SPIRV-TOOLS with c++ exceptions enabled in MSVC" ON) -option(SPIRV_TOOLS_BUILD_STATIC "Build ${SPIRV_TOOLS}-static target. ${SPIRV_TOOLS} will alias to ${SPIRV_TOOLS}-static or ${SPIRV_TOOLS}-shared based on BUILD_SHARED_LIBS" ON) -if(SPIRV_TOOLS_BUILD_STATIC) - set(SPIRV_TOOLS_FULL_VISIBILITY ${SPIRV_TOOLS}-static) +# If BUILD_SHARED_LIBS is undefined, set it based on whether we are +# the master project or a subproject +if (NOT DEFINED BUILD_SHARED_LIBS) + set(BUILD_SHARED_LIBS ${master_project}) +endif() + +if (BUILD_SHARED_LIBS) + set(static_default OFF) +else() + set(static_default ON) +endif() + +option(SPIRV_TOOLS_BUILD_SHARED "Build ${SPIRV_TOOLS} as a shared library" + ${BUILD_SHARED_LIBS}) +option(SPIRV_TOOLS_BUILD_STATIC "Build ${SPIRV_TOOLS} as a static library" + ${static_default}) + +# Avoid conflict between the dll import library and +# the static library (thanks microsoft) +if(CMAKE_STATIC_LIBRARY_PREFIX STREQUAL "" AND + CMAKE_STATIC_LIBRARY_SUFFIX STREQUAL ".lib") + set(SPIRV_TOOLS_STATIC_LIBNAME "${SPIRV_TOOLS}-static") +else() + set(SPIRV_TOOLS_STATIC_LIBNAME "${SPIRV_TOOLS}") +endif() + +if (SPIRV_TOOLS_BUILD_STATIC) + # If building a static library at all, always build other libraries as static, + # and link to the static SPIRV-Tools library. set(SPIRV_TOOLS_LIBRARY_TYPE "STATIC") -else(SPIRV_TOOLS_BUILD_STATIC) - set(SPIRV_TOOLS_FULL_VISIBILITY ${SPIRV_TOOLS}) - if (NOT DEFINED SPIRV_TOOLS_LIBRARY_TYPE) - if(BUILD_SHARED_LIBS) - set(SPIRV_TOOLS_LIBRARY_TYPE "SHARED") - else() - set(SPIRV_TOOLS_LIBRARY_TYPE "STATIC") - endif() - endif() -endif(SPIRV_TOOLS_BUILD_STATIC) + set(SPIRV_TOOLS_FULL_VISIBILITY ${SPIRV_TOOLS}-static) +elseif (SPIRV_TOOLS_BUILD_SHARED) + # If only building a shared library, link other libraries to the + # shared library. Also, other libraries should be shared + set(SPIRV_TOOLS_LIBRARY_TYPE "SHARED") + set(SPIRV_TOOLS_FULL_VISIBILITY ${SPIRV_TOOLS}-shared) +else() + message(FATAL_ERROR "You must set one of " + "SPIRV_TOOLS_BUILD_STATIC or SPIRV_TOOLS_BUILD_SHARED!") +endif() + +option(ENABLE_EXCEPTIONS_ON_MSVC + "Build SPIRV-TOOLS with C++ exceptions enabled in MSVC" ON) function(spvtools_default_compile_options TARGET) target_compile_options(${TARGET} PRIVATE ${SPIRV_WARNINGS}) @@ -372,7 +384,7 @@ if (NOT "${SPIRV_SKIP_TESTS}") endif() set(SPIRV_LIBRARIES "-lSPIRV-Tools-opt -lSPIRV-Tools -lSPIRV-Tools-link") -set(SPIRV_SHARED_LIBRARIES "-lSPIRV-Tools-shared") +set(SPIRV_SHARED_LIBRARIES "-lSPIRV-Tools") # Build pkg-config file # Use a first-class target so it's regenerated when relevant files are updated. @@ -388,7 +400,12 @@ add_custom_command( -DSPIRV_LIBRARIES=${SPIRV_LIBRARIES} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/write_pkg_config.cmake DEPENDS "CHANGES" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/SPIRV-Tools.pc.in" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/write_pkg_config.cmake") -add_custom_command( + +set(pc_files ${CMAKE_CURRENT_BINARY_DIR}/SPIRV-Tools.pc) + +# TODO(crueter): remove? +if (SPIRV_TOOLS_BUILD_SHARED) + add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/SPIRV-Tools-shared.pc COMMAND ${CMAKE_COMMAND} -DCHANGES_FILE=${CMAKE_CURRENT_SOURCE_DIR}/CHANGES @@ -400,9 +417,12 @@ add_custom_command( -DSPIRV_SHARED_LIBRARIES=${SPIRV_SHARED_LIBRARIES} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/write_pkg_config.cmake DEPENDS "CHANGES" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/SPIRV-Tools-shared.pc.in" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/write_pkg_config.cmake") -add_custom_target(spirv-tools-pkg-config - ALL - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/SPIRV-Tools-shared.pc ${CMAKE_CURRENT_BINARY_DIR}/SPIRV-Tools.pc) + set(pc_files ${pc_files} ${CMAKE_CURRENT_BINARY_DIR}/SPIRV-Tools-shared.pc) +endif() + +add_custom_target(spirv-tools-pkg-config + ALL + DEPENDS ${pc_files}) # Install pkg-config file if (ENABLE_SPIRV_TOOLS_INSTALL) diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index bfa1e661bc..fd3712c70c 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -337,49 +337,44 @@ function(spirv_tools_default_target_options target) ) set_property(TARGET ${target} PROPERTY FOLDER "SPIRV-Tools libraries") spvtools_check_symbol_exports(${target}) - add_dependencies(${target} spirv-tools-build-version core_tables extinst_tables) + add_dependencies(${target} + spirv-tools-build-version core_tables extinst_tables) endfunction() -# Always build ${SPIRV_TOOLS}-shared. This is expected distro packages, and -# unlike the other SPIRV_TOOLS target, defaults to hidden symbol visibility. -add_library(${SPIRV_TOOLS}-shared SHARED ${SPIRV_SOURCES}) -if (SPIRV_TOOLS_USE_MIMALLOC) - target_link_libraries(${SPIRV_TOOLS}-shared PRIVATE mimalloc-static) +if (SPIRV_TOOLS_BUILD_SHARED) + add_library(${SPIRV_TOOLS}-shared SHARED ${SPIRV_SOURCES}) + if (SPIRV_TOOLS_USE_MIMALLOC) + target_link_libraries(${SPIRV_TOOLS}-shared PRIVATE mimalloc-static) + endif() + + set_target_properties(${SPIRV_TOOLS}-shared PROPERTIES + OUTPUT_NAME "${SPIRV_TOOLS}") + spirv_tools_default_target_options(${SPIRV_TOOLS}-shared) + + target_compile_definitions(${SPIRV_TOOLS}-shared + PRIVATE SPIRV_TOOLS_IMPLEMENTATION + PUBLIC SPIRV_TOOLS_SHAREDLIB) + + list(APPEND SPIRV_TOOLS_TARGETS ${SPIRV_TOOLS}-shared) endif() -spirv_tools_default_target_options(${SPIRV_TOOLS}-shared) -set_target_properties(${SPIRV_TOOLS}-shared PROPERTIES CXX_VISIBILITY_PRESET hidden) -target_compile_definitions(${SPIRV_TOOLS}-shared - PRIVATE SPIRV_TOOLS_IMPLEMENTATION - PUBLIC SPIRV_TOOLS_SHAREDLIB -) if(SPIRV_TOOLS_BUILD_STATIC) add_library(${SPIRV_TOOLS}-static STATIC ${SPIRV_SOURCES}) if (SPIRV_TOOLS_USE_MIMALLOC AND SPIRV_TOOLS_USE_MIMALLOC_IN_STATIC_BUILD) target_link_libraries(${SPIRV_TOOLS}-shared PRIVATE mimalloc-static) endif() + spirv_tools_default_target_options(${SPIRV_TOOLS}-static) - # The static target does not have the '-static' suffix. - set_target_properties(${SPIRV_TOOLS}-static PROPERTIES OUTPUT_NAME "${SPIRV_TOOLS}") - - # Create the "${SPIRV_TOOLS}" target as an alias to either "${SPIRV_TOOLS}-static" - # or "${SPIRV_TOOLS}-shared" depending on the value of BUILD_SHARED_LIBS. - if(BUILD_SHARED_LIBS) - add_library(${SPIRV_TOOLS} ALIAS ${SPIRV_TOOLS}-shared) - else() - add_library(${SPIRV_TOOLS} ALIAS ${SPIRV_TOOLS}-static) - endif() + set_target_properties(${SPIRV_TOOLS}-static PROPERTIES + OUTPUT_NAME "${SPIRV_TOOLS_STATIC_LIBNAME}") - set(SPIRV_TOOLS_TARGETS ${SPIRV_TOOLS}-static ${SPIRV_TOOLS}-shared) -else() - add_library(${SPIRV_TOOLS} ${SPIRV_TOOLS_LIBRARY_TYPE} ${SPIRV_SOURCES}) - if (SPIRV_TOOLS_USE_MIMALLOC) - target_link_libraries(${SPIRV_TOOLS} PRIVATE mimalloc-static) - endif() - spirv_tools_default_target_options(${SPIRV_TOOLS}) - set(SPIRV_TOOLS_TARGETS ${SPIRV_TOOLS} ${SPIRV_TOOLS}-shared) + list(APPEND SPIRV_TOOLS_TARGETS ${SPIRV_TOOLS}-static) endif() +# Create the "SPIRV-Tools" target as an alias to either "SPIRV-Tools-static" +# or "SPIRV-Tools-shared" depending on the value of SPIRV_TOOLS_BUILD_SHARED. +add_library(${SPIRV_TOOLS} ALIAS ${SPIRV_TOOLS_FULL_VISIBILITY}) + if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") find_library(LIBRT rt) if(LIBRT) @@ -390,14 +385,17 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") endif() if(ENABLE_SPIRV_TOOLS_INSTALL) - if (SPIRV_TOOLS_USE_MIMALLOC AND (NOT SPIRV_TOOLS_BUILD_STATIC OR SPIRV_TOOLS_USE_MIMALLOC_IN_STATIC_BUILD)) + if (SPIRV_TOOLS_USE_MIMALLOC AND + (NOT SPIRV_TOOLS_BUILD_STATIC OR SPIRV_TOOLS_USE_MIMALLOC_IN_STATIC_BUILD)) list(APPEND SPIRV_TOOLS_TARGETS mimalloc-static) endif() install(TARGETS ${SPIRV_TOOLS_TARGETS} EXPORT ${SPIRV_TOOLS}Targets) export(EXPORT ${SPIRV_TOOLS}Targets FILE ${SPIRV_TOOLS}Target.cmake) spvtools_config_package_dir(${SPIRV_TOOLS} PACKAGE_DIR) - install(EXPORT ${SPIRV_TOOLS}Targets FILE ${SPIRV_TOOLS}Target.cmake DESTINATION ${PACKAGE_DIR}) + install(EXPORT ${SPIRV_TOOLS}Targets + FILE ${SPIRV_TOOLS}Target.cmake + DESTINATION ${PACKAGE_DIR}) # Special config file for root library compared to other libs. file(WRITE ${CMAKE_BINARY_DIR}/${SPIRV_TOOLS}Config.cmake