Skip to content

Commit

Permalink
Add code coverage build support. (#65)
Browse files Browse the repository at this point in the history
* Add code coverage build support.

* Fix for testMeshes unit test run in parallel.

* Updated code after merge.
  • Loading branch information
ppt-adsk authored Feb 13, 2024
1 parent 8476c04 commit b501edb
Show file tree
Hide file tree
Showing 37 changed files with 873 additions and 503 deletions.
11 changes: 9 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ project(maya-usd)
option(BUILD_TESTS "Build tests." ON)
option(BUILD_STRICT_MODE "Enforce all warnings as errors." ON)
option(BUILD_SHARED_LIBS "Build libraries as shared or static." ON)
option(CODE_COVERAGE "Build and collect code coverage info." OFF)

if(APPLE)
option(BUILD_UB2 "Build Universal Binary 2 (UB2) Intel64+arm64" OFF)
endif()
Expand Down Expand Up @@ -158,8 +160,13 @@ if(MAYA_APP_VERSION VERSION_GREATER 2024)
set(WANT_QT_VERSION 6.5)
find_package(Qt6 ${WANT_QT_VERSION} COMPONENTS Core Widgets QUIET)
if (Qt6_FOUND)
message(STATUS "Found Qt ${Qt6_VERSION} in Maya devkit. Hydra Scene Browser will be built.")
set(BUILD_HDSB_PLUGIN TRUE)
if (CODE_COVERAGE)
set(BUILD_HDSB_PLUGIN FALSE)
message(STATUS "Code coverage enabled, Hydra Scene Browser will not be built.")
else()
set(BUILD_HDSB_PLUGIN TRUE)
message(STATUS "Found Qt ${Qt6_VERSION} in Maya devkit. Hydra Scene Browser will be built.")
endif()
else()
message(WARNING "Could not find Qt ${WANT_QT_VERSION} in Maya devkit directory: ${MAYA_DEVKIT_LOCATION}. \
You must extract Qt.tar.gz. Hydra Scene Browser will not be built.")
Expand Down
26 changes: 22 additions & 4 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ def BuildVariant(context):
return "Debug"
elif context.buildRelease:
return "Release"
elif context.buildCoverage:
return "Coverage"
elif context.buildRelWithDebug:
return "RelWithDebInfo"
return "RelWithDebInfo"
Expand Down Expand Up @@ -258,7 +260,6 @@ def CurrentWorkingDirectory(dir):
def RunCMake(context, extraArgs=None, stages=None):
"""Invoke CMake to configure, build, and install a library whose
source code is located in the current working directory."""

srcDir = os.getcwd()
instDir = context.instDir
buildDir = context.buildDir
Expand Down Expand Up @@ -293,27 +294,40 @@ def RunCMake(context, extraArgs=None, stages=None):
if generator and 'Visual Studio' in generator and IsVisualStudio2019OrGreater():
generator = generator + " -A x64"

add_coverage_flags = False

if (context.buildCoverage):
# Use RelWithDebInfo as underlying variant to build
context.buildCoverage = False
add_coverage_flags = True


# get build variant
variant= BuildVariant(context)

with CurrentWorkingDirectory(buildDir):
# recreate build_log.txt everytime the script runs
if os.path.isfile(context.logFileLocation):
os.remove(context.logFileLocation)

if 'configure' in stages:
Run(context,
'cmake '
'-DCMAKE_INSTALL_PREFIX="{instDir}" '
'-DCMAKE_BUILD_TYPE={variant} '
'-DCMAKE_EXPORT_COMPILE_COMMANDS=ON '
'{codeCoverageCompilerCpp} '
'{codeCoverageCompilerC} '
'{generator} '
'{codeCoverageOption} '
'{extraArgs} '
'"{srcDir}"'
.format(instDir=instDir,
variant=variant,
srcDir=srcDir,
codeCoverageCompilerCpp=("-DCMAKE_CXX_COMPILER=clang++" if add_coverage_flags else ""),
codeCoverageCompilerC=("-DCMAKE_C_COMPILER=clang" if add_coverage_flags else ""),
generator=(generator or ""),
codeCoverageOption=("-DCODE_COVERAGE=ON" if add_coverage_flags else ""),
extraArgs=(" ".join(extraArgs) if extraArgs else "")))

installArg = ""
Expand Down Expand Up @@ -571,6 +585,9 @@ def Package(context):
varGroup.add_argument("--build-release", dest="build_release", action="store_true",
help="Build in Release mode (default: %(default)s)")

varGroup.add_argument("--build-coverage", dest="build_coverage", action="store_true",
help="Build in Coverage mode (default: %(default)s)")

varGroup.add_argument("--build-relwithdebug", dest="build_relwithdebug", action="store_true", default=True,
help="Build in RelWithDebInfo mode (default: %(default)s)")

Expand Down Expand Up @@ -605,7 +622,6 @@ def Package(context):
# InstallContext
class InstallContext:
def __init__(self, args):

# Assume the project's top level cmake is in the current source directory
self.mayaHydraSrcDir = os.path.normpath(
os.path.join(os.path.abspath(os.path.dirname(__file__))))
Expand All @@ -615,6 +631,7 @@ def __init__(self, args):
self.buildDebug = args.build_debug
self.buildRelease = args.build_release
self.buildRelWithDebug = args.build_relwithdebug
self.buildCoverage = args.build_coverage

self.debugPython = args.debug_python

Expand Down Expand Up @@ -684,6 +701,7 @@ def __init__(self, args):

# Redirect output stream to file
self.redirectOutstreamFile = args.redirect_outstream_file

try:
context = InstallContext(args)
except Exception as e:
Expand Down
39 changes: 38 additions & 1 deletion cmake/compiler_config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
)
endif()

set(CLANG_FLAGS
-MP
-frtti
)

if (CODE_COVERAGE)
list(APPEND CLANG_FLAGS
-fprofile-instr-generate
-fcoverage-mapping
)
endif()

set(MSVC_FLAGS
# we want to be as strict as possible
/W3
Expand Down Expand Up @@ -59,6 +71,22 @@ set(MSVC_FLAGS
/we4189
)

set(CLANG_DEFINITIONS
# Make sure WinDef.h does not define min and max macros which
# will conflict with std::min() and std::max().
NOMINMAX

_CRT_SECURE_NO_WARNINGS
_SCL_SECURE_NO_WARNINGS
)

if (CODE_COVERAGE)
list(APPEND CLANG_DEFINITIONS
CODE_COVERAGE
CODE_COVERAGE_WORKAROUND
)
endif()

set(MSVC_DEFINITIONS
# Make sure WinDef.h does not define min and max macros which
# will conflict with std::min() and std::max().
Expand Down Expand Up @@ -99,7 +127,7 @@ function(mayaHydra_compile_config TARGET)
cxx_std_11
)
endif()
if(IS_GNU OR IS_CLANG)
if(IS_GNU)
target_compile_options(${TARGET}
PRIVATE
${GNU_CLANG_FLAGS}
Expand All @@ -120,6 +148,15 @@ function(mayaHydra_compile_config TARGET)
BOOST_NO_CXX98_FUNCTION_BASE
)
endif()
elseif(IS_CLANG)
target_compile_options(${TARGET}
PRIVATE
${CLANG_FLAGS}
)
target_compile_definitions(${TARGET}
PRIVATE
${CLANG_DEFINITIONS}
)
elseif(IS_MSVC)
target_compile_options(${TARGET}
PRIVATE
Expand Down
9 changes: 7 additions & 2 deletions cmake/modules/FindMaya.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,13 @@ macro(maya_set_plugin_properties target)
PREFIX "")
elseif(WIN32)
set(_MAYA_DEFINES "${_MAYA_DEFINES}" _AFXDLL _MBCS NT_PLUGIN)
set_target_properties( ${target} PROPERTIES
LINK_FLAGS "/export:initializePlugin /export:uninitializePlugin")
if(IS_CLANG)
set_target_properties( ${target} PROPERTIES
LINK_FLAGS "-Wl,-export:initializePlugin -Wl,-export:uninitializePlugin")
else()
set_target_properties( ${target} PROPERTIES
LINK_FLAGS "/export:initializePlugin /export:uninitializePlugin")
endif()
else()
set(_MAYA_DEFINES "${_MAYA_DEFINES}" LINUX LINUX_64)
set_target_properties( ${target} PROPERTIES
Expand Down
2 changes: 1 addition & 1 deletion cmake/utils.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ endif()
# compiler type
if (CMAKE_COMPILER_IS_GNUCXX)
set(IS_GNU TRUE)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(IS_CLANG TRUE)
elseif(MSVC)
set(IS_MSVC TRUE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,19 @@ namespace
std::mutex sceneFilteringClient_mutex;

//Set of scene Filtering scene index data, they belong to the Fpv::FilteringSceneIndexClient::Category::kSceneFiltering
std::set<PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr> sceneFilteringSceneIndicesData;
std::set<PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr>& sceneFilteringSceneIndicesData() {
static std::set<PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr>
#ifdef CODE_COVERAGE_WORKAROUND
*data{nullptr};
if (!data) {
data = new std::set<PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr>;
}
return *data;
#else
data;
return data;
#endif
}

//Set of selection highlighting Filtering scene index data, they belong to the Fpv::FilteringSceneIndexClient::Category::kSelectionHighlighting
std::set<PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr> selectionHighlightFilteringSceneIndicesData;
Expand Down Expand Up @@ -83,15 +95,15 @@ bool FilteringSceneIndexInterfaceImp::_CreateSceneFilteringSceneIndicesData(cons
{
std::lock_guard<std::mutex> lock(sceneFilteringClient_mutex);

auto findResult = std::find_if(sceneFilteringSceneIndicesData.cbegin(), sceneFilteringSceneIndicesData.cend(),
auto findResult = std::find_if(sceneFilteringSceneIndicesData().cbegin(), sceneFilteringSceneIndicesData().cend(),
[&client](const PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr& filteringSIData) { return filteringSIData->getClient() == client;});
if (findResult != sceneFilteringSceneIndicesData.cend()){
if (findResult != sceneFilteringSceneIndicesData().cend()){
return false;
}

//Call the abstract scene index data factory to create a subclass of FilteringSceneIndexDataBase
PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr data = sceneIndexDataFactory->createFilteringSceneIndexDataBase(client);
sceneFilteringSceneIndicesData.insert(data);
sceneFilteringSceneIndicesData().insert(data);
bNeedToUpdateViewportsFilteringSceneIndicesChain = true;
}

Expand Down Expand Up @@ -136,15 +148,15 @@ void FilteringSceneIndexInterfaceImp::_DestroySceneFilteringSceneIndicesData(con
{
std::lock_guard<std::mutex> lock(sceneFilteringClient_mutex);

auto findResult = std::find_if(sceneFilteringSceneIndicesData.cbegin(), sceneFilteringSceneIndicesData.cend(),
auto findResult = std::find_if(sceneFilteringSceneIndicesData().cbegin(), sceneFilteringSceneIndicesData().cend(),
[&client](const PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr& filteringSIData) { return filteringSIData->getClient() == client;});
if (findResult != sceneFilteringSceneIndicesData.cend()){
if (findResult != sceneFilteringSceneIndicesData().cend()){
const auto& filteringSIData = (*findResult);
rendererNames = (filteringSIData)
? filteringSIData->getClient()->getRendererNames()
: FvpViewportAPITokens->allRenderers;

sceneFilteringSceneIndicesData.erase(findResult);//This also decreases ref count
sceneFilteringSceneIndicesData().erase(findResult);//This also decreases ref count

bNeedToUpdateViewportsFilteringSceneIndicesChain = true;
}
Expand Down Expand Up @@ -190,7 +202,7 @@ void FilteringSceneIndexInterfaceImp::unregisterFilteringSceneIndexClient(const
const std::set<PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr>& FilteringSceneIndexInterfaceImp::getSceneFilteringSceneIndicesData()const
{
std::lock_guard<std::mutex> lock(sceneFilteringClient_mutex);
return sceneFilteringSceneIndicesData;
return sceneFilteringSceneIndicesData();
}

const std::set<PXR_NS::FVP_NS_DEF::FilteringSceneIndexDataBaseRefPtr>& FilteringSceneIndexInterfaceImp::getSelectionHighlightFilteringSceneIndicesData() const
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
#include "fvpDataProducerSceneIndexDataBase.h"
#include "flowViewport/API/fvpViewportAPITokens.h"

#ifdef CODE_COVERAGE_WORKAROUND
#include <flowViewport/fvpUtils.h>
#endif

//Hydra headers
#include <pxr/imaging/hd/prefixingSceneIndex.h>
#include <pxr/imaging/hd/flatteningSceneIndex.h>
Expand Down Expand Up @@ -59,6 +63,13 @@ DataProducerSceneIndexDataBase::DataProducerSceneIndexDataBase(const CreationPar
_dccNode = params._dccNode;
}

DataProducerSceneIndexDataBase::~DataProducerSceneIndexDataBase()
{
#ifdef CODE_COVERAGE_WORKAROUND
Fvp::leakSceneIndex(_rootOverridesSceneIndex);
#endif
}

void DataProducerSceneIndexDataBase::UpdateHydraTransformFromParentPath()
{
if (! _rootOverridesSceneIndex){
Expand Down Expand Up @@ -140,4 +151,4 @@ void DataProducerSceneIndexDataBase::_CreateSceneIndexChainForDataProducerSceneI

}//end of namespace FVP_NS_DEF

PXR_NAMESPACE_CLOSE_SCOPE
PXR_NAMESPACE_CLOSE_SCOPE
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ TF_DECLARE_WEAK_AND_REF_PTRS(DataProducerSceneIndexDataBase);//Be able to use Re
void* _dccNode;
};

~DataProducerSceneIndexDataBase() override = default;
~DataProducerSceneIndexDataBase() override;

//Used to set the usd stage scene indices
void SetDataProducerSceneIndex(const HdSceneIndexBaseRefPtr& sceneIndex) {_dataProducerSceneIndex = sceneIndex;}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

//Local headers
#include "fvpFilteringSceneIndicesChainManager.h"
#ifdef CODE_COVERAGE_WORKAROUND
#include <flowViewport/fvpUtils.h>
#endif
#include "flowViewport/sceneIndex/fvpRenderIndexProxy.h"
#include "flowViewport/API/interfacesImp/fvpFilteringSceneIndexInterfaceImp.h"
#include "flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportDataManager.h"
Expand Down Expand Up @@ -86,6 +89,9 @@ void FilteringSceneIndicesChainManager::destroyFilteringSceneIndicesChain(Viewpo
renderIndex->RemoveSceneIndex(lastSceneIndex);//Remove the whole chain from the render index

//Remove a ref on it which should cascade the same on its references
#ifdef CODE_COVERAGE_WORKAROUND
Fvp::leakSceneIndex(lastSceneIndex);
#endif
lastSceneIndex.Reset();
}

Expand Down Expand Up @@ -166,4 +172,4 @@ void FilteringSceneIndicesChainManager::setEnabled(bool enable)
updateFilteringSceneIndicesChain(FvpViewportAPITokens->allRenderers);
}

}//End of namespace FVP_NS_DEF
}//End of namespace FVP_NS_DEF
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ namespace
{
std::mutex viewportInformationAndSceneIndicesPerViewportData_mutex;
std::set<PXR_NS::FVP_NS_DEF::DataProducerSceneIndexDataBaseRefPtr> dummyEmptyArray;

#ifdef CODE_COVERAGE_WORKAROUND
void leakViewportData(const Fvp::ViewportInformationAndSceneIndicesPerViewportDataVector& vpDataVec) {
// Must place the leaked data vector on the heap, as a by-value
// vector will have its destructor called at process exit, which calls
// the vector element destructors and triggers the crash.
static std::vector<Fvp::ViewportInformationAndSceneIndicesPerViewportDataVector>* leakedVpData{nullptr};
if (!leakedVpData) {
leakedVpData = new std::vector<Fvp::ViewportInformationAndSceneIndicesPerViewportDataVector>;
}
leakedVpData->push_back(vpDataVec);
}
#endif

}

PXR_NAMESPACE_USING_DIRECTIVE
Expand Down Expand Up @@ -182,6 +196,10 @@ void ViewportInformationAndSceneIndicesPerViewportDataManager::RemoveAllViewport
}
}

#ifdef CODE_COVERAGE_WORKAROUND
leakViewportData(_viewportsInformationAndSceneIndicesPerViewportData);
#endif

_viewportsInformationAndSceneIndicesPerViewportData.clear();//Delete all of them
}

Expand Down
Loading

0 comments on commit b501edb

Please sign in to comment.