浏览代码

fix project gem name and upgrade cmake

This change also removes enabled_gems.cmake and moves the gem names into project.json

Signed-off-by: Alex Peterson <[email protected]>
Alex Peterson 2 年之前
父节点
当前提交
f0a8b7b6a9
共有 6 个文件被更改,包括 187 次插入109 次删除
  1. 29 15
      CMakeLists.txt
  2. 0 6
      Gem/Code/CMakeLists.txt
  3. 0 30
      Gem/Code/enabled_gems.cmake
  4. 10 10
      Gem/gem.json
  5. 124 44
      cmake/EngineFinder.cmake
  6. 24 4
      project.json

+ 29 - 15
CMakeLists.txt

@@ -6,27 +6,41 @@
 #
 #
 
+
 if(NOT PROJECT_NAME)
-    cmake_minimum_required(VERSION 3.19)
+    cmake_minimum_required(VERSION 3.22)
+
+    # Utility function to look for an optional 'engine_finder_cmake_path'setting 
+    function(get_engine_finder_cmake_path project_json_file_path path_value)
+        if(NOT ${path_value} AND EXISTS "${project_json_file_path}")
+            file(READ "${project_json_file_path}" project_json_data)
+            string(JSON engine_finder_cmake_value ERROR_VARIABLE json_error GET ${project_json_data} "engine_finder_cmake_path")
+            cmake_path(APPEND CMAKE_CURRENT_SOURCE_DIR "${engine_finder_cmake_value}" engine_finder_cmake_value)
+            if(NOT json_error AND EXISTS "${engine_finder_cmake_value}")
+                set(${path_value} "${engine_finder_cmake_value}" PARENT_SCOPE)
+            elseif(json_error AND ${engine_finder_cmake_value} STREQUAL "NOTFOUND")
+                # When the error value is just NOTFOUND that means there is a JSON
+                # parsing error, and not simply a missing key 
+                message(WARNING "Unable to read 'engine_finder_cmake_path'.\nError: ${json_error} ${engine_finder_cmake_value}")
+            endif()
+        endif()
+    endfunction()
+    
+    # Check for optional 'engine_finder_cmake_path' in order of preference
+    # We support per-project customization to make it easier to upgrade 
+    # or revert to a custom EngineFinder.cmake 
+    get_engine_finder_cmake_path("${CMAKE_CURRENT_SOURCE_DIR}/user/project.json" engine_finder_cmake_path)
+    get_engine_finder_cmake_path("${CMAKE_CURRENT_SOURCE_DIR}/project.json" engine_finder_cmake_path)
+    if(NOT engine_finder_cmake_path)
+        set(engine_finder_cmake_path cmake/EngineFinder.cmake)
+    endif()
+
     include(cmake/CompilerSettings.cmake)
     project(AtomSampleViewer
         LANGUAGES C CXX
         VERSION 1.0.0.0
     )
-    include(cmake/EngineFinder.cmake OPTIONAL)
+    include(${engine_finder_cmake_path} OPTIONAL)
     find_package(o3de REQUIRED)
     o3de_initialize()
-else()
-    # Add the project_name to global LY_PROJECTS_TARGET_NAME property
-    file(READ "${CMAKE_CURRENT_LIST_DIR}/project.json" project_json)
-
-    string(JSON project_target_name ERROR_VARIABLE json_error GET ${project_json} "project_name")
-    if(json_error)
-        message(FATAL_ERROR "Unable to read key 'project_name' from 'project.json'")
-    endif()
-
-    set_property(GLOBAL APPEND PROPERTY LY_PROJECTS_TARGET_NAME ${project_target_name})
-
-    add_subdirectory(Gem)
-    add_subdirectory(Standalone)
 endif()

+ 0 - 6
Gem/Code/CMakeLists.txt

@@ -122,12 +122,6 @@ if(PAL_TRAIT_BUILD_SUPPORTS_TESTS)
 endif()
 
 
-################################################################################
-# Gem dependencies
-################################################################################
-
-ly_enable_gems(PROJECT_NAME AtomSampleViewer GEM_FILE enabled_gems.cmake)
-
 # If we build a server, then apply the gems to the server
 if(PAL_TRAIT_BUILD_SERVER_SUPPORTED)
     set_property(GLOBAL APPEND PROPERTY LY_LAUNCHER_SERVER_PROJECTS AtomSampleViewer)

+ 0 - 30
Gem/Code/enabled_gems.cmake

@@ -1,30 +0,0 @@
-#
-# Copyright (c) Contributors to the Open 3D Engine Project.
-# For complete copyright and license terms please see the LICENSE at the root of this distribution.
-#
-# SPDX-License-Identifier: Apache-2.0 OR MIT
-#
-#
-
-set(ENABLED_GEMS
-    Maestro
-    TextureAtlas
-    LmbrCentral
-    LyShine
-    Camera
-    EMotionFX
-    Atom
-    AtomSampleViewer
-    SceneProcessing
-    EditorPythonBindings
-    ImGui
-    Profiler
-    Sponza
-    MaterialEditor
-    UiBasics
-    StreamerProfiler
-    DiffuseProbeGrid
-    XR
-    OpenXRVk
-    Atom_TestData
-)

+ 10 - 10
Gem/gem.json

@@ -1,20 +1,20 @@
 {
-    "gem_name": "AtomSampleViewerGem",
-    "display_name": "AtomSampleViewerGem",
-    "license": "What license AtomSampleViewerGem uses goes here: i.e. Apache-2.0 or MIT",
-    "license_url": "Link to the license web site goes here: i.e. https://opensource.org/licenses/Apache-2.0 Or https://opensource.org/licenses/MIT",
-    "origin": "The name of the originator goes here. i.e. XYZ Inc.",
-    "origin_url": "The primary repo for AtomSampleViewerGem goes here: i.e. http://www.mydomain.com",
+    "gem_name": "AtomSampleViewer",
+    "display_name": "AtomSampleViewer",
+    "license": "Apache-2.0 or MIT",
+    "license_url": "https://opensource.org/licenses/Apache-2.0 Or https://opensource.org/licenses/MIT",
+    "origin": "O3DE",
+    "origin_url": "https://github.com/o3de/o3de-atom-sampleviewer",
     "type": "Code",
-    "summary": "A short description of AtomSampleViewerGem goes here.",
+    "summary": "Gem for the Atom Sample Viewer project.",
     "canonical_tags": [
         "Gem"
     ],
     "user_tags": [
-        "AtomSampleViewerGem"
+        "AtomSampleViewer"
     ],
     "icon_path": "preview.png",
-    "requirements": "Notice of any requirements AtomSampleViewerGem has goes here. i.e. This requires X other gem",
-    "documentation_url": "Link to any documentation of AtomSampleViewerGem goes here: i.e. https://o3de.org/docs/user-guide/gems/reference/design/white-box/",
+    "requirements": "",
+    "documentation_url": "",
     "dependencies": []
 }

+ 124 - 44
cmake/EngineFinder.cmake

@@ -5,35 +5,62 @@
 # SPDX-License-Identifier: Apache-2.0 OR MIT
 #
 #
-# This file is copied during engine registration. Edits to this file will be lost next
-# time a registration happens.
+# Edits to this file may be lost in upgrades. Instead of changing this file, use 
+# the 'engine_finder_cmake_path' key in your project.json or user/project.json to specify 
+# an alternate .cmake file to use instead of this one.
 
 include_guard()
 
-# Read the engine name from the project_json file
-file(READ ${CMAKE_CURRENT_SOURCE_DIR}/project.json project_json)
 set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/project.json)
 
-string(JSON LY_ENGINE_NAME_TO_USE ERROR_VARIABLE json_error GET ${project_json} engine)
-if(json_error)
-    message(FATAL_ERROR "Unable to read key 'engine' from 'project.json'\nError: ${json_error}")
-endif()
-
+# Option 1: Use engine manually set in CMAKE_MODULE_PATH
+# CMAKE_MODULE_PATH must contain a path to an engine's cmake folder 
 if(CMAKE_MODULE_PATH)
     foreach(module_path ${CMAKE_MODULE_PATH})
-        if(EXISTS ${module_path}/Findo3de.cmake)
-            file(READ ${module_path}/../engine.json engine_json)
-            string(JSON engine_name ERROR_VARIABLE json_error GET ${engine_json} engine_name)
-            if(json_error)
-                message(FATAL_ERROR "Unable to read key 'engine_name' from 'engine.json'\nError: ${json_error}")
-            endif()
-            if(LY_ENGINE_NAME_TO_USE STREQUAL engine_name)
-                return() # Engine being forced through CMAKE_MODULE_PATH
+        cmake_path(SET module_engine_version_cmake_path "${module_path}/o3deConfigVersion.cmake")
+        if(EXISTS "${module_engine_version_cmake_path}")
+            include("${module_engine_version_cmake_path}")
+            if(PACKAGE_VERSION_COMPATIBLE)
+                message(STATUS "Selecting engine from CMAKE_MODULE_PATH '${module_path}'")
+                return()
+            else()
+                message(WARNING "Not using engine from CMAKE_MODULE_PATH '${module_path}' because it is not compatible with this project.")
             endif()
         endif()
     endforeach()
+    message(VERBOSE "No compatible engine found from CMAKE_MODULE_PATH '${CMAKE_MODULE_PATH}'.")
+endif()
+
+# Option 2: Use the engine from the 'engine_path' field in <project>/user/project.json
+cmake_path(SET O3DE_USER_PROJECT_JSON_PATH ${CMAKE_CURRENT_SOURCE_DIR}/user/project.json)
+if(EXISTS "${O3DE_USER_PROJECT_JSON_PATH}")
+    file(READ "${O3DE_USER_PROJECT_JSON_PATH}" user_project_json)
+    if(user_project_json)
+        string(JSON user_project_engine_path ERROR_VARIABLE json_error GET ${user_project_json} engine_path)
+        if(user_project_engine_path AND NOT json_error)
+            cmake_path(SET user_engine_version_cmake_path "${user_project_engine_path}/cmake/o3deConfigVersion.cmake")
+            if(EXISTS "${user_engine_version_cmake_path}")
+                include("${user_engine_version_cmake_path}")
+                if(PACKAGE_VERSION_COMPATIBLE)
+                    message(STATUS "Selecting engine '${user_project_engine_path}' from 'engine_path' in '<project>/user/project.json'.")
+                    list(APPEND CMAKE_MODULE_PATH "${user_project_engine_path}/cmake")
+                    return()
+                else()
+                    message(FATAL_ERROR "The engine at '${user_project_engine_path}' from 'engine_path' in '${O3DE_USER_PROJECT_JSON_PATH}' is not compatible with this project. Please register this project with a compatible engine, or remove the local override by running:\nscripts\\o3de edit-project-properties -pp ${CMAKE_CURRENT_SOURCE_DIR} --user --engine-path \"\"")
+                endif()
+            else()
+                message(FATAL_ERROR "This project cannot use the engine at '${user_project_engine_path}' because the version cmake file '${user_engine_version_cmake_path}' needed to check compatibility is missing.  \nPlease register this project with a compatible engine, or remove the local override by running:\nscripts\\o3de edit-project-properties -pp ${CMAKE_CURRENT_SOURCE_DIR} --user --engine-path \"\"\nIf you want this project to use an older engine(not recommended), provide a custom EngineFinder.cmake using the o3de CLI's --engine-finder-cmake-path option. ")
+            endif()
+        elseif(json_error AND ${user_project_engine_path} STREQUAL "NOTFOUND")
+            # When the value is just NOTFOUND that means there is a JSON
+            # parsing error, and not simply a missing key 
+            message(FATAL_ERROR "Unable to read 'engine_path' from '${user_project_engine_path}'\nError: ${json-error}")
+        endif()
+    endif()
 endif()
 
+
+# Option 3: Find a compatible engine registered in ~/.o3de/o3de_manifest.json 
 if(DEFINED ENV{USERPROFILE} AND EXISTS $ENV{USERPROFILE})
     set(manifest_path $ENV{USERPROFILE}/.o3de/o3de_manifest.json) # Windows
 else()
@@ -41,50 +68,103 @@ else()
 endif()
 
 set(registration_error [=[
+To enable more verbose logging, run the cmake command again with '--log-level VERBOSE'
 Engine registration is required before configuring a project.
 Run 'scripts/o3de register --this-engine' from the engine root.
 ]=])
 
-# Read the ~/.o3de/o3de_manifest.json file and look through the 'engines_path' object.
-# Find a key that matches LY_ENGINE_NAME_TO_USE and use that as the engine path.
+# Create a list of all engines
 if(EXISTS ${manifest_path})
     file(READ ${manifest_path} manifest_json)
     set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${manifest_path})
 
-    string(JSON engines_path_count ERROR_VARIABLE json_error LENGTH ${manifest_json} engines_path)
+    string(JSON engines_count ERROR_VARIABLE json_error LENGTH ${manifest_json} engines)
     if(json_error)
-        message(FATAL_ERROR "Unable to read key 'engines_path' from '${manifest_path}'\nError: ${json_error}\n${registration_error}")
+        message(FATAL_ERROR "Unable to read key 'engines' from '${manifest_path}'\nError: ${json_error}\n${registration_error}")
     endif()
 
-    string(JSON engines_path_type ERROR_VARIABLE json_error TYPE ${manifest_json} engines_path)
-    if(json_error OR NOT ${engines_path_type} STREQUAL "OBJECT")
-        message(FATAL_ERROR "Type of 'engines_path' in '${manifest_path}' is not a JSON Object\nError: ${json_error}")
+    string(JSON engines_type ERROR_VARIABLE json_error TYPE ${manifest_json} engines)
+    if(json_error OR NOT ${engines_type} STREQUAL "ARRAY")
+        message(FATAL_ERROR "Type of 'engines' in '${manifest_path}' is not a JSON ARRAY\nError: ${json_error}\n${registration_error}")
     endif()
 
-    math(EXPR engines_path_count "${engines_path_count}-1")
-    foreach(engine_path_index RANGE ${engines_path_count})
-        string(JSON engine_name ERROR_VARIABLE json_error MEMBER ${manifest_json} engines_path ${engine_path_index})
+    math(EXPR engines_count "${engines_count}-1")
+    foreach(array_index RANGE ${engines_count})
+        string(JSON manifest_engine_path ERROR_VARIABLE json_error GET ${manifest_json} engines "${array_index}")
         if(json_error)
-            message(FATAL_ERROR "Unable to read 'engines_path/${engine_path_index}' from '${manifest_path}'\nError: ${json_error}")
+            message(FATAL_ERROR "Unable to read 'engines/${array_index}' from '${manifest_path}'\nError: ${json_error}\n${registration_error}")
         endif()
+        list(APPEND O3DE_ENGINE_PATHS ${manifest_engine_path})
+    endforeach()
+elseif(NOT CMAKE_MODULE_PATH)
+    message(FATAL_ERROR "O3DE Manifest file not found at '${manifest_path}'.\n${registration_error}")
+endif()
 
-        if(LY_ENGINE_NAME_TO_USE STREQUAL engine_name)
-            string(JSON engine_path ERROR_VARIABLE json_error GET ${manifest_json} engines_path ${engine_name})
-            if(json_error)
-                message(FATAL_ERROR "Unable to read value from 'engines_path/${engine_name}'\nError: ${json_error}")
-            endif()
+# We cannot just run find_package() on the list of engine paths because
+# CMAKE_FIND_PACKAGE_SORT_ORDER sorts based on file name and chooses
+# the first package that returns PACKAGE_VERSION_COMPATIBLE 
+set(O3DE_MOST_COMPATIBLE_ENGINE_PATH "")
+set(O3DE_MOST_COMPATIBLE_ENGINE_VERSION "")
+foreach(manifest_engine_path IN LISTS O3DE_ENGINE_PATHS) 
+    # Does this engine have a config version cmake file?
+    cmake_path(SET version_cmake_path "${manifest_engine_path}/cmake/o3deConfigVersion.cmake")
+    if(NOT EXISTS "${version_cmake_path}") 
+        message(VERBOSE "Ignoring '${manifest_engine_path}' because no config version cmake file was found at '${version_cmake_path}'")
+        continue()
+    endif()
 
-            if(engine_path)
-                list(APPEND CMAKE_MODULE_PATH "${engine_path}/cmake")
-                return()
-            endif()
+    unset(PACKAGE_VERSION)
+    unset(PACKAGE_VERSION_COMPATIBLE)
+    include("${version_cmake_path}")
+
+    # Follow the version checking convention from find_package(CONFIG)
+    if(PACKAGE_VERSION_COMPATIBLE)
+        if(NOT O3DE_MOST_COMPATIBLE_ENGINE_PATH) 
+            set(O3DE_MOST_COMPATIBLE_ENGINE_PATH "${manifest_engine_path}") 
+            set(O3DE_MOST_COMPATIBLE_ENGINE_VERSION ${PACKAGE_VERSION}) 
+            message(VERBOSE "Found compatible engine '${manifest_engine_path}' with version '${PACKAGE_VERSION}'")
+        elseif(${PACKAGE_VERSION} VERSION_GREATER ${O3DE_MOST_COMPATIBLE_ENGINE_VERSION})
+            set(O3DE_MOST_COMPATIBLE_ENGINE_PATH "${manifest_engine_path}")
+            set(O3DE_MOST_COMPATIBLE_ENGINE_VERSION ${PACKAGE_VERSION})
+            message(VERBOSE "Found more compatible engine '${manifest_engine_path}' with version '${PACKAGE_VERSION}' because it has a greater version number.")
+        else()
+            message(VERBOSE "Not using engine '${manifest_engine_path}' with version '${PACKAGE_VERSION}' because it doesn't have a greater version number or has a different engine name.")
         endif()
-    endforeach()
-    
-    message(FATAL_ERROR "The project.json uses engine name '${LY_ENGINE_NAME_TO_USE}' but no engine with that name has been registered.\n${registration_error}")
-else()
-    # If the user is passing CMAKE_MODULE_PATH we assume thats where we will find the engine
-    if(NOT CMAKE_MODULE_PATH)
-        message(FATAL_ERROR "O3DE Manifest file not found.\n${registration_error}")
+    else()
+        message(VERBOSE "Ignoring '${manifest_engine_path}' because it is not a compatible engine.")
+    endif()
+endforeach()
+
+if(O3DE_MOST_COMPATIBLE_ENGINE_PATH)
+    message(STATUS "Selecting engine '${O3DE_MOST_COMPATIBLE_ENGINE_PATH}'")
+    set(PACKAGE_VERSION_COMPATIBLE True)
+    set(PACKAGE_VERSION O3DE_MOST_COMPATIBLE_ENGINE_VERSION)
+    list(APPEND CMAKE_MODULE_PATH "${O3DE_MOST_COMPATIBLE_ENGINE_PATH}/cmake")
+    return()
+endif()
+
+# No compatible engine was found.
+# Read the 'engine' field in project.json or user/project.json for more helpful messages 
+if(user_project_json)
+    string(JSON user_project_engine ERROR_VARIABLE json_error GET ${user_project_json} engine)
+endif()
+
+if(NOT user_project_engine)
+    file(READ ${CMAKE_CURRENT_SOURCE_DIR}/project.json o3de_project_json)
+    string(JSON project_engine ERROR_VARIABLE json_error GET ${o3de_project_json} engine)
+    if(json_error AND ${project_engine} STREQUAL "NOTFOUND")
+        message(FATAL_ERROR "Unable to read key 'engine' from 'project.json'\nError: ${json_error}")
     endif()
 endif()
+
+if(user_project_engine)
+    message(FATAL_ERROR "The local '${O3DE_USER_PROJECT_JSON_PATH}' engine is '${user_project_engine}' but no compatible engine with that name and version was found.  Please register the compatible engine, or remove the local engine override.\n${registration_error}")
+elseif(project_engine)
+    message(FATAL_ERROR "The project.json engine is '${project_engine}' but no engine with that name and version was found.\n${registration_error}")
+else()
+    set(project_registration_error [=[
+    Project registration is required before configuring a project.
+    Run 'scripts/o3de register -pp PROJECT_PATH --engine-path ENGINE_PATH' from the engine root.
+    ]=])
+    message(FATAL_ERROR "${project_registration_error}")
+endif()

+ 24 - 4
project.json

@@ -1,10 +1,10 @@
 {
     "project_name": "AtomSampleViewer",
     "project_id": "{D882E365-54D6-586E-BD78-2650F3057D49}",
-    "origin": "The primary repo for AtomSampleViewer goes here: i.e. http://www.mydomain.com",
-    "license": "What license AtomSampleViewer uses goes here: i.e. https://opensource.org/licenses/Apache-2.0 Or https://opensource.org/licenses/MIT etc.",
+    "origin": "https://github.com/o3de/o3de-atom-sampleviewer",
+    "license": "https://opensource.org/licenses/Apache-2.0 Or https://opensource.org/licenses/MIT etc.",
     "display_name": "AtomSampleViewer",
-    "summary": "A short description of AtomSampleViewer.",
+    "summary": "AtomSampleViewer project.",
     "canonical_tags": [
         "Project"
     ],
@@ -13,8 +13,28 @@
     ],
     "icon_path": "preview.png",
     "engine": "o3de",
-    "external_subdirectories": [],
+    "external_subdirectories": [
+        "Gem"
+    ],
     "gem_names": [
+        "Maestro",
+        "TextureAtlas",
+        "LmbrCentral",
+        "LyShine",
+        "Camera",
+        "EMotionFX",
+        "Atom",
+        "AtomSampleViewer",
+        "SceneProcessing",
+        "EditorPythonBindings",
+        "ImGui",
+        "Profiler",
+        "Sponza",
+        "MaterialEditor",
+        "UiBasics",
+        "StreamerProfiler",
+        "DiffuseProbeGrid",
+        "Atom_TestData",
         {
             "name": "OpenXRVk",
             "optional": true