Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add code coverage build support. #65

Merged
merged 4 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading