summaryrefslogtreecommitdiffstats
path: root/Modules/Compiler/MSVC-CXX-CXXImportStd.cmake
blob: 08199f7e6c1fd8eac10691c833745f7321338a37 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
function (_cmake_cxx_import_std std variable)
  find_file(_msvc_modules_json_file
    NAME modules.json
    HINTS
      "$ENV{VCToolsInstallDir}/modules"
    PATHS
      "$ENV{INCLUDE}"
      "${CMAKE_CXX_COMPILER}/../../.."
      "${CMAKE_CXX_COMPILER}/../.."    # msvc-wine layout
    PATH_SUFFIXES
      ../modules
    NO_CACHE)
  # Without this file, we do not have modules installed.
  if (NOT EXISTS "${_msvc_modules_json_file}")
    set("${variable}"
      "set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"Could not find `modules.json` resource\")\n"
      PARENT_SCOPE)
    return ()
  endif ()

  file(READ "${_msvc_modules_json_file}" _msvc_modules_json)
  string(JSON _msvc_json_version GET "${_msvc_modules_json}" "version")
  string(JSON _msvc_json_revision GET "${_msvc_modules_json}" "revision")
  # Require version 1.
  if (NOT _msvc_json_version EQUAL "1")
    set("${variable}"
      "set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"`modules.json` version ${_msvc_json_version}.${_msvc_json_revision} is not recognized\")\n"
      PARENT_SCOPE)
    return ()
  endif ()

  string(JSON _msvc_json_library GET "${_msvc_modules_json}" "library")
  # Bail if we don't understand the library.
  if (NOT _msvc_json_library STREQUAL "microsoft/STL")
    set("${variable}"
      "set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"`modules.json` library `${_msvc_json_library}` is not recognized\")\n"
      PARENT_SCOPE)
    return ()
  endif ()

  string(JSON _msvc_json_nmodules LENGTH "${_msvc_modules_json}" "module-sources")
  # Don't declare the target without any modules.
  if (NOT _msvc_json_nmodules)
    set("${variable}"
      "set(CMAKE_CXX${std}_COMPILER_IMPORT_STD_NOT_FOUND_MESSAGE \"`modules.json` does not list any available modules\")\n"
      PARENT_SCOPE)
    return ()
  endif ()

  # Declare the target.
  set(_msvc_std_target "")
  string(APPEND _msvc_std_target
    "add_library(__cmake_cxx${std} STATIC)\n")
  string(APPEND _msvc_std_target
    "target_sources(__cmake_cxx${std} INTERFACE \"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>:$<TARGET_OBJECTS:__cmake_cxx${std}>>\")\n")
  string(APPEND _msvc_std_target
    "set_property(TARGET __cmake_cxx${std} PROPERTY EXCLUDE_FROM_ALL 1)\n")
  string(APPEND _msvc_std_target
    "set_property(TARGET __cmake_cxx${std} PROPERTY CXX_SCAN_FOR_MODULES 1)\n")
  string(APPEND _msvc_std_target
    "set_property(TARGET __cmake_cxx${std} PROPERTY CXX_MODULE_STD 0)\n")
  string(APPEND _msvc_std_target
    "target_compile_features(__cmake_cxx${std} PUBLIC cxx_std_${std})\n")

  set(_msvc_modules_module_paths "")
  get_filename_component(_msvc_modules_dir "${_msvc_modules_json_file}" DIRECTORY)

  # Add module sources.
  math(EXPR _msvc_modules_json_nmodules_range "${_msvc_json_nmodules} - 1")
  foreach (_msvc_modules_json_modules_idx RANGE 0 "${_msvc_modules_json_nmodules_range}")
    string(JSON _msvc_modules_json_module_source GET "${_msvc_modules_json}" "module-sources" "${_msvc_modules_json_modules_idx}")

    if (NOT IS_ABSOLUTE "${_msvc_modules_json_module_source}")
      string(PREPEND _msvc_modules_json_module_source "${_msvc_modules_dir}/")
    endif ()
    list(APPEND _msvc_modules_module_paths
      "${_msvc_modules_json_module_source}")
  endforeach ()

  # Split the paths into basedirs and module paths.
  set(_msvc_modules_base_dirs_list "")
  set(_msvc_modules_files "")
  foreach (_msvc_modules_module_path IN LISTS _msvc_modules_module_paths)
    get_filename_component(_msvc_module_dir "${_msvc_modules_module_path}" DIRECTORY)

    list(APPEND _msvc_modules_base_dirs_list
      "${_msvc_module_dir}")
    string(APPEND _msvc_modules_files
      " \"${_msvc_modules_module_path}\"")
  endforeach ()
  list(REMOVE_DUPLICATES _msvc_modules_base_dirs_list)
  set(_msvc_modules_base_dirs "")
  foreach (_msvc_modules_base_dir IN LISTS _msvc_modules_base_dirs_list)
    string(APPEND _msvc_modules_base_dirs
      " \"${_msvc_modules_base_dir}\"")
  endforeach ()

  # Create the file set for the modules.
  string(APPEND _msvc_std_target
    "target_sources(__cmake_cxx${std}
  PUBLIC
  FILE_SET std TYPE CXX_MODULES
    BASE_DIRS ${_msvc_modules_base_dirs}
    FILES ${_msvc_modules_files})\n")

  # Wrap the `__cmake_cxx${std}` target in a check.
  string(PREPEND _msvc_std_target
    "if (NOT TARGET \"__cmake_cxx${std}\")\n")
  string(APPEND _msvc_std_target
    "endif ()\n")
  string(APPEND _msvc_std_target
    "add_library(__CMAKE::CXX${std} ALIAS __cmake_cxx${std})\n")

  set("${variable}" "${_msvc_std_target}" PARENT_SCOPE)
endfunction ()