From 8ac52d83cf8fca374cad5560d674a424b80c7d5f Mon Sep 17 00:00:00 2001 From: Gabriel Ferreira Date: Mon, 31 Jan 2022 22:50:10 -0300 Subject: [PATCH] build: versioning and find_external_library fixes Includes: - Producing version.cache file if --enable-build-version/NS3_ENABLE_BUILD_VERSION=ON - Consume version.cache file if the git commit history is not available - Crash the configuration if neither the git commit history or version.cache file are available when NS3_ENABLE_BUILD_VERSION=ON - Warn user to reconfigure the project with NS3_ENABLE_BUILD_VERSION=ON to check the version - Only try to remove duplicates if there is a list in find_external_library --- .../custom_modules/ns3_module_macros.cmake | 2 +- .../custom_modules/ns3_versioning.cmake | 166 ++++++++++++------ buildsupport/macros_and_definitions.cmake | 5 +- buildsupport/version-defines-template.h | 2 +- buildsupport/version.cache.in | 10 ++ src/core/CMakeLists.txt | 2 +- src/core/examples/CMakeLists.txt | 2 +- utils/tests/test-ns3.py | 3 + 8 files changed, 132 insertions(+), 60 deletions(-) create mode 100644 buildsupport/version.cache.in diff --git a/buildsupport/custom_modules/ns3_module_macros.cmake b/buildsupport/custom_modules/ns3_module_macros.cmake index 180cf8940..b2983b03b 100644 --- a/buildsupport/custom_modules/ns3_module_macros.cmake +++ b/buildsupport/custom_modules/ns3_module_macros.cmake @@ -92,7 +92,7 @@ function(build_lib) set(config_headers ${CMAKE_HEADER_OUTPUT_DIRECTORY}/config-store-config.h ${CMAKE_HEADER_OUTPUT_DIRECTORY}/core-config.h ) - if(${NS3_ENABLE_BUILD_VERSION}) + if(${ENABLE_BUILD_VERSION}) list(APPEND config_headers ${CMAKE_HEADER_OUTPUT_DIRECTORY}/version-defines.h ) diff --git a/buildsupport/custom_modules/ns3_versioning.cmake b/buildsupport/custom_modules/ns3_versioning.cmake index 67d2bc4c6..5ecac8729 100644 --- a/buildsupport/custom_modules/ns3_versioning.cmake +++ b/buildsupport/custom_modules/ns3_versioning.cmake @@ -6,9 +6,14 @@ function(check_git_repo_has_ns3_tags HAS_TAGS GIT_VERSION_TAG) execute_process( COMMAND ${GIT} describe --tags --abbrev=0 --match ns-3.[0-9]* - OUTPUT_VARIABLE GIT_TAG_OUTPUT + OUTPUT_VARIABLE GIT_TAG_OUTPUT ERROR_QUIET ) + # Result will be empty in case of a shallow clone or no git repo + if(NOT GIT_TAG_OUTPUT) + return() + endif() + string(REPLACE "\r" "" GIT_TAG_OUTPUT ${GIT_TAG_OUTPUT}) # remove CR (carriage # return) string(REPLACE "\n" "" GIT_TAG_OUTPUT ${GIT_TAG_OUTPUT}) # remove LF (line @@ -66,13 +71,16 @@ function(check_ns3_closest_tags CLOSEST_TAG VERSION_TAG_DISTANCE endfunction() function(configure_embedded_version) - mark_as_advanced(GIT) - find_program(GIT git) - if(${NS3_ENABLE_BUILD_VERSION} AND (NOT GIT)) - message(FATAL_ERROR "Embedding build version into libraries require Git.") + if(NOT ${NS3_ENABLE_BUILD_VERSION}) + add_custom_target( + check-version COMMAND echo Reconfigure ns-3 with + NS3_ENABLE_BUILD_VERSION=ON + ) + return() endif() - # Check version target will not be created + mark_as_advanced(GIT) + find_program(GIT git) if(NOT GIT) message( STATUS "Git was not found. Version related targets won't be enabled" @@ -82,69 +90,117 @@ function(configure_embedded_version) check_git_repo_has_ns3_tags(HAS_NS3_TAGS NS3_VERSION_TAG) - if(NOT ${HAS_NS3_TAGS}) + set(version_cache_file_template + ${PROJECT_SOURCE_DIR}/buildsupport/version.cache.in + ) + set(version_cache_file ${PROJECT_SOURCE_DIR}/src/core/model/version.cache) + + # Check if ns-3 git tags were found or at least version.cache file exists in + # the src/core/model + if((NOT HAS_NS3_TAGS) AND (NOT (EXISTS ${version_cache_file}))) message( FATAL_ERROR - "This repository doesn't contain ns-3 git tags to bake into the libraries." + "The ns-3 git commit history or the version.cache file are required to embed build version into libraries." ) + return() + endif() + + # If git tags were found, extract the information + if(HAS_NS3_TAGS) + check_ns3_closest_tags( + NS3_VERSION_CLOSEST_TAG NS3_VERSION_TAG_DISTANCE NS3_VERSION_COMMIT_HASH + NS3_VERSION_DIRTY_FLAG + ) + # Split commit tag (ns-3.[.patch][-RC]) into + # (ns;3.[.patch];[-RC]): + string(REPLACE "-" ";" NS3_VER_LIST ${NS3_VERSION_TAG}) + list(LENGTH NS3_VER_LIST NS3_VER_LIST_LEN) + + # Get last version tag fragment (RC) + set(RELEASE_CANDIDATE " ") + if(${NS3_VER_LIST_LEN} GREATER 2) + list(GET NS3_VER_LIST 2 RELEASE_CANDIDATE) + endif() + + # Get 3.[.patch] + list(GET NS3_VER_LIST 1 VERSION_STRING) + # Split into a list 3;[;patch] + string(REPLACE "." ";" VERSION_LIST ${VERSION_STRING}) + list(LENGTH VERSION_LIST VER_LIST_LEN) + + list(GET VERSION_LIST 0 NS3_VERSION_MAJOR) + if(${VER_LIST_LEN} GREATER 1) + list(GET VERSION_LIST 1 NS3_VERSION_MINOR) + if(${VER_LIST_LEN} GREATER 2) + list(GET VERSION_LIST 2 NS3_VERSION_PATCH) + else() + set(NS3_VERSION_PATCH "00") + endif() + endif() + + # Transform list with 1 entry into strings + set(NS3_VERSION_MAJOR "${NS3_VERSION_MAJOR}") + set(NS3_VERSION_MINOR "${NS3_VERSION_MINOR}") + set(NS3_VERSION_PATCH "${NS3_VERSION_PATCH}") + set(NS3_VERSION_TAG "${NS3_VERSION_TAG}") + set(NS3_VERSION_RELEASE_CANDIDATE "${RELEASE_CANDIDATE}") + if(${NS3_VERSION_RELEASE_CANDIDATE} STREQUAL " ") + set(NS3_VERSION_RELEASE_CANDIDATE \"\") + endif() + set(NS3_VERSION_BUILD_PROFILE ${cmakeBuildType}) + + # Create version.cache file + configure_file(${version_cache_file_template} ${version_cache_file} @ONLY) + else() + # Consume version.cache created previously + file(STRINGS ${version_cache_file} version_cache_contents) + foreach(line ${version_cache_contents}) + # Remove white spaces e.g. CLOSEST_TAG = '"ns-3.35"' => + # CLOSEST_TAG='"ns-3.35"' + string(REPLACE " " "" line "${line}") + + # Transform line into list CLOSEST_TAG='"ns-3.35"' => + # CLOSEST_TAG;'"ns-3.35"' + string(REPLACE "=" ";" line "${line}") + + # Replace single and double quotes used by python + string(REPLACE "'" "" line "${line}") + string(REPLACE "\"" "" line "${line}") + + # Get key and value + list(GET line 0 varname) + list(GET line 1 varvalue) + + # If value is empty, replace with an empty string, assume its the release + # candidate string + if(NOT varvalue) + set(varvalue "\"\"") + endif() + + # Define version variables with the NS3_ prefix to configure + # version-defines.h header + set(NS3_${varname} ${varvalue}) + endforeach() + set(NS3_VERSION_CLOSEST_TAG ${NS3_CLOSEST_TAG}) endif() - check_ns3_closest_tags( - NS3_VERSION_CLOSEST_TAG NS3_VERSION_TAG_DISTANCE NS3_VERSION_COMMIT_HASH - NS3_VERSION_DIRTY_FLAG - ) set(DIRTY) if(${NS3_VERSION_DIRTY_FLAG}) set(DIRTY "-dirty") endif() + # Add check-version target set(version ${NS3_VERSION_TAG}+${NS3_VERSION_TAG_DISTANCE}@${NS3_VERSION_COMMIT_HASH}${DIRTY}-${build_profile} ) + string(REPLACE "\"" "" version "${version}") add_custom_target(check-version COMMAND echo ns-3 version: ${version}) - # Split commit tag (ns-3.[.patch][-RC]) into - # (ns;3.[.patch];[-RC]): - string(REPLACE "-" ";" NS3_VER_LIST ${NS3_VERSION_TAG}) - list(LENGTH NS3_VER_LIST NS3_VER_LIST_LEN) - - # Get last version tag fragment (RC) - set(RELEASE_CANDIDATE " ") - if(${NS3_VER_LIST_LEN} GREATER 2) - list(GET NS3_VER_LIST 2 RELEASE_CANDIDATE) - endif() - - # Get 3.[.patch] - list(GET NS3_VER_LIST 1 VERSION_STRING) - # Split into a list 3;[;patch] - string(REPLACE "." ";" VERSION_LIST ${VERSION_STRING}) - list(LENGTH VERSION_LIST VER_LIST_LEN) - - list(GET VERSION_LIST 0 NS3_VERSION_MAJOR) - if(${VER_LIST_LEN} GREATER 1) - list(GET VERSION_LIST 1 NS3_VERSION_MINOR) - if(${VER_LIST_LEN} GREATER 2) - list(GET VERSION_LIST 2 NS3_VERSION_PATCH) - else() - set(NS3_VERSION_PATCH "00") - endif() - endif() - - # Transform list with 1 entry into strings - set(NS3_VERSION_MAJOR "${NS3_VERSION_MAJOR}") - set(NS3_VERSION_MINOR "${NS3_VERSION_MINOR}") - set(NS3_VERSION_PATCH "${NS3_VERSION_PATCH}") - set(NS3_VERSION_TAG "${NS3_VERSION_TAG}") - set(NS3_VERSION_RELEASE_CANDIDATE "${RELEASE_CANDIDATE}") - set(NS3_VERSION_BUILD_PROFILE ${cmakeBuildType}) - # Enable embedding build version - if(${NS3_ENABLE_BUILD_VERSION}) - add_definitions(-DENABLE_BUILD_VERSION=1) - configure_file( - buildsupport/version-defines-template.h - ${CMAKE_HEADER_OUTPUT_DIRECTORY}/version-defines.h - ) - endif() - + add_definitions(-DENABLE_BUILD_VERSION=1) + configure_file( + buildsupport/version-defines-template.h + ${CMAKE_HEADER_OUTPUT_DIRECTORY}/version-defines.h + ) + set(ENABLE_BUILD_VERSION True PARENT_SCOPE) endfunction() diff --git a/buildsupport/macros_and_definitions.cmake b/buildsupport/macros_and_definitions.cmake index 2e6552e18..375142146 100644 --- a/buildsupport/macros_and_definitions.cmake +++ b/buildsupport/macros_and_definitions.cmake @@ -341,6 +341,7 @@ macro(process_options) endif() include(buildsupport/custom_modules/ns3_versioning.cmake) + set(ENABLE_BUILD_VERSION False) configure_embedded_version() if(${NS3_CLANG_FORMAT}) @@ -1536,7 +1537,9 @@ function(find_external_library endif() endforeach() - list(REMOVE_DUPLICATES include_dirs) + if(include_dirs) + list(REMOVE_DUPLICATES include_dirs) + endif() # If we find both library and header, we export their values if((NOT not_found_libraries}) AND (NOT not_found_headers)) diff --git a/buildsupport/version-defines-template.h b/buildsupport/version-defines-template.h index a71c7b32d..2a0198563 100644 --- a/buildsupport/version-defines-template.h +++ b/buildsupport/version-defines-template.h @@ -102,7 +102,7 @@ * * Type: string literal */ -#cmakedefine NS3_VERSION_RELEASE_CANDIDATE "@NS3_VERSION_RELEASE_CANDIDATE@" +#cmakedefine NS3_VERSION_RELEASE_CANDIDATE @NS3_VERSION_RELEASE_CANDIDATE@ /** * The number of repository commits between #NS3_VERSION_CLOSEST_TAG diff --git a/buildsupport/version.cache.in b/buildsupport/version.cache.in new file mode 100644 index 000000000..969f6494d --- /dev/null +++ b/buildsupport/version.cache.in @@ -0,0 +1,10 @@ +CLOSEST_TAG = '"@NS3_VERSION_CLOSEST_TAG@"' +VERSION_COMMIT_HASH = '"@NS3_VERSION_COMMIT_HASH@"' +VERSION_DIRTY_FLAG = '@NS3_VERSION_DIRTY_FLAG@' +VERSION_MAJOR = '@NS3_VERSION_MAJOR@' +VERSION_MINOR = '@NS3_VERSION_MINOR@' +VERSION_PATCH = '@NS3_VERSION_PATCH@' +VERSION_RELEASE_CANDIDATE = '@NS3_VERSION_RELEASE_CANDIDATE@' +VERSION_TAG = '"@NS3_VERSION_TAG@"' +VERSION_TAG_DISTANCE = '@NS3_VERSION_TAG_DISTANCE@' +VERSION_BUILD_PROFILE = '@NS3_VERSION_BUILD_PROFILE@' \ No newline at end of file diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index cccbf5f58..3db45cecc 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -145,7 +145,7 @@ endif() # Embedded version support set(embedded_version_sources) set(embedded_version_headers) -if(${NS3_ENABLE_BUILD_VERSION}) +if(${ENABLE_BUILD_VERSION}) set(embedded_version_sources model/version.cc ) diff --git a/src/core/examples/CMakeLists.txt b/src/core/examples/CMakeLists.txt index 424ba5462..17824b7ab 100644 --- a/src/core/examples/CMakeLists.txt +++ b/src/core/examples/CMakeLists.txt @@ -34,7 +34,7 @@ build_lib_example( ${libstats} ) -if(${NS3_ENABLE_BUILD_VERSION}) +if(${ENABLE_BUILD_VERSION}) build_lib_example( NAME build-version-example SOURCE_FILES build-version-example.cc diff --git a/utils/tests/test-ns3.py b/utils/tests/test-ns3.py index a5419ff59..eaddd740b 100644 --- a/utils/tests/test-ns3.py +++ b/utils/tests/test-ns3.py @@ -780,6 +780,9 @@ class NS3ConfigureTestCase(NS3BaseTestCase): Test passing --check-version argument to ns3 to get the build version @return None """ + return_code, _, _ = run_ns3("configure --enable-build-version") + self.assertEqual(return_code, 0) + return_code, stdout, stderr = run_ns3("--check-version") self.assertEqual(return_code, 0) self.assertIn("ns-3 version:", stdout)