ADD_LIBRARY(JFJochStructureRefinement STATIC
        ModelFFT.cpp ModelFFT.h
        ModelGrid.cpp ModelGrid.h
        ModelScaling.cpp ModelScaling.h
        MolecularReplacement.cpp MolecularReplacement.h
        $<$<BOOL:${JFJOCH_CUDA_AVAILABLE}>:MolecularReplacementGPU.cu> MolecularReplacementGPU.h
        ModelValidation.cpp ModelValidation.h
        RugnuxModel.h
        RigidBodyRefine.cpp RigidBodyRefine.h
        $<$<BOOL:${JFJOCH_CUDA_AVAILABLE}>:RigidBodyGPU.cpp>
        $<$<BOOL:${JFJOCH_CUDA_AVAILABLE}>:RigidBodyGPU.cu>
        RigidBodyGPU.h RigidBodyGPUEngine.h
        $<$<BOOL:${JFJOCH_CUDA_AVAILABLE}>:ModelDensityGPU.cu> ModelDensityGPU.h
        $<$<BOOL:${JFJOCH_CUDA_AVAILABLE}>:ModelMaskGPU.cu> ModelMaskGPU.h
        $<$<BOOL:${JFJOCH_CUDA_AVAILABLE}>:ModelStructureFactorsGPU.cpp>
        $<$<BOOL:${JFJOCH_CUDA_AVAILABLE}>:ModelStructureFactorsGPU.cu>
        ModelStructureFactorsGPU.h ModelStructureFactorsGPUEngine.h
        $<$<BOOL:${JFJOCH_CUDA_AVAILABLE}>:ModelScaleGPU.cu> ModelScaleGPU.h
        SigmaA.cpp SigmaA.h)

# JFJochIndexing for CUDAMemHelpers.h and, under CUDA, to put cuFFT (RigidBodyGPU.cu) after these
# objects on the link line.
TARGET_LINK_LIBRARIES(JFJochStructureRefinement JFJochScaleMerge JFJochIndexing JFJochCommon gemmi fftw3f)

IF (APPLE)
    # The rotation function on the Apple GPU (MolecularReplacementMetal.h). Its kernel is compiled when it is first
    # used, from source carried in the binary, as image_analysis/bragg_integration does: the .metal file copied into
    # a generated .cpp here; editing it re-runs the configure.
    FILE(READ ${CMAKE_CURRENT_SOURCE_DIR}/MolecularReplacementMetal.metal text)
    SET_PROPERTY(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/MolecularReplacementMetal.metal)
    # Written only when it changed, so a configure does not rebuild the library.
    FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/MolecularReplacementMetalSource.cpp.tmp
         "// Generated from image_analysis/structure_refinement by its CMakeLists.txt - do not edit.\n"
         "extern const char *const mr_metal_source;\n"
         "const char *const mr_metal_source = R\"MR_METAL(\n${text})MR_METAL\";\n")
    CONFIGURE_FILE(${CMAKE_CURRENT_BINARY_DIR}/MolecularReplacementMetalSource.cpp.tmp
                   ${CMAKE_CURRENT_BINARY_DIR}/MolecularReplacementMetalSource.cpp COPYONLY)
    TARGET_SOURCES(JFJochStructureRefinement PRIVATE MolecularReplacementMetal.mm MolecularReplacementMetal.h
            MolecularReplacementMetal.metal ${CMAKE_CURRENT_BINARY_DIR}/MolecularReplacementMetalSource.cpp)
    SET_SOURCE_FILES_PROPERTIES(MolecularReplacementMetal.mm PROPERTIES COMPILE_OPTIONS -fobjc-arc)
    SET_SOURCE_FILES_PROPERTIES(MolecularReplacementMetal.metal PROPERTIES HEADER_FILE_ONLY ON)
    # The model density's gather (ModelDensityMetal.h), carried in the same way.
    FILE(READ ${CMAKE_CURRENT_SOURCE_DIR}/ModelDensityMetal.metal text)
    SET_PROPERTY(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/ModelDensityMetal.metal)
    FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/ModelDensityMetalSource.cpp.tmp
         "// Generated from image_analysis/structure_refinement by its CMakeLists.txt - do not edit.\n"
         "extern const char *const model_density_metal_source;\n"
         "const char *const model_density_metal_source = R\"DENSITY_METAL(\n${text})DENSITY_METAL\";\n")
    CONFIGURE_FILE(${CMAKE_CURRENT_BINARY_DIR}/ModelDensityMetalSource.cpp.tmp
                   ${CMAKE_CURRENT_BINARY_DIR}/ModelDensityMetalSource.cpp COPYONLY)
    TARGET_SOURCES(JFJochStructureRefinement PRIVATE ModelDensityMetal.mm ModelDensityMetal.h
            ModelDensityMetal.metal ${CMAKE_CURRENT_BINARY_DIR}/ModelDensityMetalSource.cpp)
    SET_SOURCE_FILES_PROPERTIES(ModelDensityMetal.mm PROPERTIES COMPILE_OPTIONS -fobjc-arc)
    SET_SOURCE_FILES_PROPERTIES(ModelDensityMetal.metal PROPERTIES HEADER_FILE_ONLY ON)
    TARGET_LINK_LIBRARIES(JFJochStructureRefinement "-framework Metal" "-framework Foundation")
ENDIF()
