From 2fa2d44485a83b06efd69da4deb4d928b46c36e6 Mon Sep 17 00:00:00 2001 From: crueter Date: Sun, 5 Oct 2025 19:47:01 -0400 Subject: [PATCH 1/2] WIP: [cmake] better shared/static splitting, enable static-only builds Firstly this allows for static-ONLY builds (no shared libs at all)--useful for including this as a subproject Makes the library itself build once via an object library--this isn't actually ideal due to symbol export shenanigans, but this is pretty trivial to solve in code (I just don't feel like it for now) Also makes the shared/static handling for spirv-tools targets just better in general to account for this TODO: - Should we make the other libraries static/shared split? - Fix symbol exporting and cxx visibility nonsense (this isn't even a problem--current code makes it needlessly complex) - test on Windows Signed-off-by: crueter --- .gitignore | 1 + CMakeLists.txt | 108 ++++++++++++++++++++++++++---------------- source/CMakeLists.txt | 97 ++++++++++++++++++++++--------------- 3 files changed, 127 insertions(+), 79 deletions(-) diff --git a/.gitignore b/.gitignore index 042becf67c..b6bef217c0 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ bazel-spirv-tools bazel-SPIRV-Tools bazel-testlogs MODULE.bazel.lock +/install # Vim [._]*.s[a-w][a-z] diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d843b4d2f..190bf526a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,17 @@ cmake_minimum_required(VERSION 3.22.1) +# master project detection--useful for FetchContent/submodule inclusion +set(MASTER_PROJECT OFF) +set(SUBPROJECT ON) + +# NOTE: source vs current_source detection is unreliable +# this heuristic is more generally applicable esp w.r.t FetchContent +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 +146,52 @@ 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) +# Static/Shared splitting + +# TODO: do we want to make the other targets support this split? + +# 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() + +# default to shared for master project, static for subproject +# TODO should we do this based on BUILD_SHARED_LIBS instead? +option(SPIRV_TOOLS_BUILD_SHARED "Build ${SPIRV_TOOLS} as a shared library" + ${MASTER_PROJECT}) +option(SPIRV_TOOLS_BUILD_STATIC "Build ${SPIRV_TOOLS} as a static library" + ${SUBPROJECT}) + +# if neither are on... what are you doing? +if (NOT (SPIRV_TOOLS_BUILD_SHARED OR SPIRV_TOOLS_BUILD_STATIC)) + message(FATAL_ERROR "SPIRV_TOOLS_BUILD_SHARED or SPIRV_TOOLS_BUILD_STATIC must be set") +endif() + +if (SPIRV_TOOLS_BUILD_STATIC) set(SPIRV_TOOLS_FULL_VISIBILITY ${SPIRV_TOOLS}-static) - set(SPIRV_TOOLS_LIBRARY_TYPE "STATIC") -else(SPIRV_TOOLS_BUILD_STATIC) +else() + # otherwise, we should respect BUILD_SHARED_LIBS 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) +endif() + +if (( BUILD_SHARED_LIBS AND SPIRV_TOOLS_BUILD_SHARED ) OR NOT + SPIRV_TOOLS_BUILD_STATIC) + set(SPIRV_TOOLS_FULL_VISIBILITY ${SPIRV_TOOLS}-shared) + set(SPIRV_TOOLS_LIBRARY_TYPE "SHARED") +elseif(SPIRV_TOOLS_BUILD_STATIC) + set(SPIRV_TOOLS_FULL_VISIBILITY ${SPIRV_TOOLS}-static) + set(SPIRV_TOOLS_LIBRARY_TYPE "STATIC") +else() + # BUILD_SHARED_LIBS is OFF, but no static target--just use shared + set(SPIRV_TOOLS_FULL_VISIBILITY ${SPIRV_TOOLS}-shared) + set(SPIRV_TOOLS_LIBRARY_TYPE "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}) @@ -257,6 +274,7 @@ add_custom_target(spirv-tools-check-python-tests # Check for symbol exports on Linux. # At the moment, this check will fail on the OSX build machines for the Android NDK. # It appears they don't have objdump. +# TODO(crueter): SPIRV-Tools-obj breaks this if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") macro(spvtools_check_symbol_exports TARGET) if (NOT "${SPIRV_SKIP_TESTS}") @@ -388,7 +406,11 @@ 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(SPIRV_TOOLS_PKGCONFIG_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/SPIRV-Tools.pc) + +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 +422,11 @@ 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(SPIRV_TOOLS_PKGCONFIG_DEPENDS ${SPIRV_TOOLS_PKGCONFIG_DEPENDS} ${CMAKE_CURRENT_BINARY_DIR}/SPIRV-Tools-shared.pc) +endif() + +add_custom_target(spirv-tools-pkg-config ALL + DEPENDS ${SPIRV_TOOLS_PKGCONFIG_DEPENDS}) # Install pkg-config file if (ENABLE_SPIRV_TOOLS_INSTALL) diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 7c8dadeb84..b7a46b406d 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -171,8 +171,12 @@ add_subdirectory(link) add_subdirectory(lint) add_subdirectory(diff) -set(SPIRV_SOURCES +set(SPIRV_PUBLIC_HEADERS ${spirv-tools_SOURCE_DIR}/include/spirv-tools/libspirv.h +) + +set(SPIRV_SOURCES + ${SPIRV_PUBLIC_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/util/bitutils.h ${CMAKE_CURRENT_SOURCE_DIR}/util/bit_vector.h @@ -325,8 +329,9 @@ spvtools_pch(SPIRV_SOURCES pch_source) # spirv_tools_default_target_options() sets the target options that are common # for all ${SPIRV_TOOLS} targets. -function(spirv_tools_default_target_options target) +function(spirv_tools_default_target_options target install) spvtools_default_compile_options(${target}) + target_include_directories(${target} PUBLIC $ @@ -335,50 +340,68 @@ function(spirv_tools_default_target_options target) PRIVATE ${SPIRV_HEADER_INCLUDE_DIR} ) set_property(TARGET ${target} PROPERTY FOLDER "SPIRV-Tools libraries") - spvtools_check_symbol_exports(${target}) + + if (${install}) + spvtools_check_symbol_exports(${target}) + endif() + 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) +# object library--used by the dependent shared/static targets +add_library(${SPIRV_TOOLS}-obj OBJECT ${SPIRV_SOURCES}) +spirv_tools_default_target_options(${SPIRV_TOOLS}-obj OFF) + +if (SPIRV_TOOLS_BUILD_SHARED) + add_library(${SPIRV_TOOLS}-shared SHARED + $) + + set_target_properties(${SPIRV_TOOLS}-shared PROPERTIES OUTPUT_NAME "${SPIRV_TOOLS}") + + if (SPIRV_TOOLS_USE_MIMALLOC) + target_link_libraries(${SPIRV_TOOLS}-shared PRIVATE mimalloc-static) + endif() + + spirv_tools_default_target_options(${SPIRV_TOOLS}-shared ON) + set_target_properties(${SPIRV_TOOLS}-shared PROPERTIES + CXX_VISIBILITY_PRESET hidden) + + # TODO: How should we handle symbol visibility + these compiledefs + # w.r.t the object library? + target_compile_definitions(${SPIRV_TOOLS}-shared + PRIVATE SPIRV_TOOLS_IMPLEMENTATION + PUBLIC SPIRV_TOOLS_SHAREDLIB + ) 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() + add_library(${SPIRV_TOOLS}-static STATIC + $) - 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) + 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 ON) + + set_target_properties(${SPIRV_TOOLS}-static PROPERTIES OUTPUT_NAME + "${SPIRV_TOOLS_STATIC_LIBNAME}") +endif() + +# make sure all targets are accounted for +# NB: do not include object libraries in export sets! +if (SPIRV_TOOLS_BUILD_STATIC) + set(SPIRV_TOOLS_TARGETS ${SPIRV_TOOLS}-static) endif() +if (SPIRV_TOOLS_BUILD_SHARED) + set(SPIRV_TOOLS_TARGETS ${SPIRV_TOOLS_TARGETS} ${SPIRV_TOOLS}-shared) +endif() + +# Create the "${SPIRV_TOOLS}" target. This should be an alias to +# either the static or shared target depending on BUILD_SHARED_LIBS +add_library(${SPIRV_TOOLS} ALIAS ${SPIRV_TOOLS_FULL_VISIBILITY}) + if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") find_library(LIBRT rt) if(LIBRT) From c2aaaa3a916d433f32523b27371694daef58d3df Mon Sep 17 00:00:00 2001 From: crueter Date: Tue, 7 Oct 2025 13:02:11 -0400 Subject: [PATCH 2/2] cleanup Signed-off-by: crueter --- CMakeLists.txt | 3 --- source/CMakeLists.txt | 6 +----- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 190bf526a8..ce821a413e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,8 +18,6 @@ cmake_minimum_required(VERSION 3.22.1) set(MASTER_PROJECT OFF) set(SUBPROJECT ON) -# NOTE: source vs current_source detection is unreliable -# this heuristic is more generally applicable esp w.r.t FetchContent if (NOT DEFINED PROJECT_NAME) set(MASTER_PROJECT ON) set(SUBPROJECT OFF) @@ -274,7 +272,6 @@ add_custom_target(spirv-tools-check-python-tests # Check for symbol exports on Linux. # At the moment, this check will fail on the OSX build machines for the Android NDK. # It appears they don't have objdump. -# TODO(crueter): SPIRV-Tools-obj breaks this if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") macro(spvtools_check_symbol_exports TARGET) if (NOT "${SPIRV_SKIP_TESTS}") diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index b7a46b406d..79dae73be2 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -171,12 +171,8 @@ add_subdirectory(link) add_subdirectory(lint) add_subdirectory(diff) -set(SPIRV_PUBLIC_HEADERS - ${spirv-tools_SOURCE_DIR}/include/spirv-tools/libspirv.h -) - set(SPIRV_SOURCES - ${SPIRV_PUBLIC_HEADERS} + ${spirv-tools_SOURCE_DIR}/include/spirv-tools/libspirv.h ${CMAKE_CURRENT_SOURCE_DIR}/util/bitutils.h ${CMAKE_CURRENT_SOURCE_DIR}/util/bit_vector.h