diff --git a/.azure-pipelines/linux_build_py311.yml b/.azure-pipelines/linux_build_py311.yml index 10cc72db4..f2b76c4f8 100644 --- a/.azure-pipelines/linux_build_py311.yml +++ b/.azure-pipelines/linux_build_py311.yml @@ -17,6 +17,7 @@ steps: - bash: | source ${CONDA}/etc/profile.d/conda.sh conda activate rdkit_build + export CXXFLAGS="${CXXFLAGS} -Wall -Werror -Wextra" mkdir build && cd build && \ cmake .. \ -DCMAKE_BUILD_TYPE=Release \ diff --git a/.azure-pipelines/linux_build_ubsan.yml b/.azure-pipelines/linux_build_ubsan.yml new file mode 100644 index 000000000..d51bbee90 --- /dev/null +++ b/.azure-pipelines/linux_build_ubsan.yml @@ -0,0 +1,63 @@ +steps: +- bash: | + sudo apt-get install g++ wget make libgl1-mesa-dev mesa-common-dev + source ${CONDA}/etc/profile.d/conda.sh + sudo chown -R ${USER} ${CONDA} + conda config --set always_yes yes --set changeps1 no + conda update -q conda + conda info -a + conda create --name rdkit_build -c conda-forge $(python) cmake \ + libboost=$(boost_version) \ + libboost-devel=$(boost_version) \ + eigen cairo freetype + conda activate rdkit_build + displayName: Setup build environment (no Qt due to versioning problems) +- bash: | + source ${CONDA}/etc/profile.d/conda.sh + conda activate rdkit_build + export CXXFLAGS="${CXXFLAGS} -Wall -Werror -Wextra --sanitize=undefined" + mkdir build && cd build && \ + cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DRDK_INSTALL_INTREE=ON \ + -DRDK_INSTALL_STATIC_LIBS=OFF \ + -DRDK_BUILD_CPP_TESTS=ON \ + -DRDK_BUILD_PYTHON_WRAPPERS=OFF \ + -DRDK_BUILD_COORDGEN_SUPPORT=ON \ + -DRDK_BUILD_MAEPARSER_SUPPORT=ON \ + -DRDK_OPTIMIZE_POPCNT=ON \ + -DRDK_BUILD_TEST_GZIP=ON \ + -DRDK_BUILD_FREESASA_SUPPORT=ON \ + -DRDK_BUILD_AVALON_SUPPORT=ON \ + -DRDK_BUILD_INCHI_SUPPORT=ON \ + -DRDK_BUILD_YAEHMOP_SUPPORT=ON \ + -DRDK_BUILD_XYZ2MOL_SUPPORT=ON \ + -DRDK_BUILD_CAIRO_SUPPORT=ON \ + -DRDK_BUILD_SWIG_WRAPPERS=OFF \ + -DRDK_SWIG_STATIC=OFF \ + -DRDK_BUILD_THREADSAFE_SSS=ON \ + -DRDK_TEST_MULTITHREADED=ON \ + -DRDK_CFFI_STATIC=OFF \ + -DRDK_BUILD_CFFI_LIB=ON + displayName: Configure build (Run CMake) +- bash: | + source ${CONDA}/etc/profile.d/conda.sh + conda activate rdkit_build + cd build + make -j $( $(number_of_cores) ) install + displayName: Build +- bash: | + source ${CONDA}/etc/profile.d/conda.sh + conda activate rdkit_build + export RDBASE=`pwd` + export LD_LIBRARY_PATH=${RDBASE}/lib:${CONDA_PREFIX}/lib:${LD_LIBRARY_PATH} + echo "LD_LIBRARY_PATH: " $LD_LIBRARY_PATH + export QT_QPA_PLATFORM='offscreen' + cd build + ctest -j $( $(number_of_cores) ) --output-on-failure -T Test + displayName: Run tests +- task: PublishTestResults@2 + inputs: + testResultsFormat: 'CTest' + testResultsFiles: 'build/Testing/*/Test.xml' + testRunTitle: $(system.phasedisplayname) CTest Test Run diff --git a/.azure-pipelines/mac_build.yml b/.azure-pipelines/mac_build.yml index 4d673c96a..3c5df8693 100644 --- a/.azure-pipelines/mac_build.yml +++ b/.azure-pipelines/mac_build.yml @@ -32,7 +32,7 @@ steps: conda activate rdkit_build export SDKROOT="$(pwd)/MacOSX$(target_platform).sdk/" export CONDA_BUILD_SYSROOT=${SDKROOT} - export CXXFLAGS="${CXXFLAGS} -Wall -Werror" + export CXXFLAGS="${CXXFLAGS} -Wall -Wextra -Werror" mkdir build && cd build && \ cmake .. \ -DCMAKE_BUILD_TYPE=Release \ diff --git a/Code/GraphMol/MolDraw2D/DrawMol.cpp b/Code/GraphMol/MolDraw2D/DrawMol.cpp index 4c27ef004..995967b16 100755 --- a/Code/GraphMol/MolDraw2D/DrawMol.cpp +++ b/Code/GraphMol/MolDraw2D/DrawMol.cpp @@ -3135,8 +3135,8 @@ void DrawMol::doubleBondTerminal(Atom *at1, Atom *at2, double offset, // If at1->at2->at3 is a straight line, l2f may have ended up on the // wrong side of the other bond from l2s because there is no inner // side of the bond. Do it again with a negative offset if so. - if (fabs(l1s.directionVector(l1f).dotProduct(l2s.directionVector(l2f)) < - 0.9999)) { + if (fabs(l1s.directionVector(l1f).dotProduct(l2s.directionVector(l2f))) < + 0.9999) { l2f = doubleBondEnd(at1->getIdx(), at2->getIdx(), thirdAtom->getIdx(), -offset, true); } diff --git a/Code/GraphMol/MolDraw2D/DrawShape.cpp b/Code/GraphMol/MolDraw2D/DrawShape.cpp index a7726318e..c7d77e910 100644 --- a/Code/GraphMol/MolDraw2D/DrawShape.cpp +++ b/Code/GraphMol/MolDraw2D/DrawShape.cpp @@ -445,14 +445,16 @@ bool DrawShapeSolidWedge::doesRectClash(const StringRect &rect, padding)) { return true; } - if (points_.size() > 3) { + if (points_.size() >= 6) { if (doesTriangleIntersect(rect, points_[3], points_[4], points_[5], padding)) { return true; } - if (doesTriangleIntersect(rect, points_[6], points_[7], points_[8], - padding)) { - return true; + if (points_.size() >= 9) { + if (doesTriangleIntersect(rect, points_[6], points_[7], points_[8], + padding)) { + return true; + } } } return false; diff --git a/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp b/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp index e59a9b9ab..dd524dfdb 100644 --- a/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp +++ b/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp @@ -2988,7 +2988,7 @@ M END auto p1 = conf.getAtomPos(dummy->getIdx()); auto p2 = conf.getAtomPos(neighborIndex); auto length = (p1 - p2).length(); - TEST_ASSERT(abs(length - 1.0) < 0.25); + TEST_ASSERT(fabs(length - 1.0) < 0.25); } void testMultipleGroupsToUnlabelledCoreAtomGithub5573() { @@ -3522,9 +3522,9 @@ M END auto &dummyPoint = conf.getAtomPos(dummy->getIdx()); auto &neighborPoint = conf.getAtomPos(neighbor->getIdx()); auto length = (dummyPoint - neighborPoint).length(); - TEST_ASSERT(abs(length - 1.0) < 0.005); + TEST_ASSERT(fabs(length - 1.0) < 0.005); // R2 dummy should be directly above neighbor - TEST_ASSERT(abs(dummyPoint.x - neighborPoint.x) < 0.05); + TEST_ASSERT(fabs(dummyPoint.x - neighborPoint.x) < 0.05); } { @@ -3540,8 +3540,8 @@ M END // R2 dummy should be over input chiral oxygen, which is first oxygen of // degree 2 in input mol block auto &inputPoint = mol2->getConformer(0).getAtomPos(15); - TEST_ASSERT(abs(dummyPoint.x - inputPoint.x) < 0.05); - TEST_ASSERT(abs(dummyPoint.y - inputPoint.y) < 0.05); + TEST_ASSERT(fabs(dummyPoint.x - inputPoint.x) < 0.05); + TEST_ASSERT(fabs(dummyPoint.y - inputPoint.y) < 0.05); } } @@ -3812,7 +3812,7 @@ void testEnumeratedCore() { << "********************************************************\n"; BOOST_LOG(rdInfoLog) << "Test that enumerated cores behave properly" << std::endl; - + auto core = R"CTAB( Mrv2008 08242317002D @@ -3854,9 +3854,8 @@ M END params.onlyMatchAtRGroups = false; params.doEnumeration = true; - const char *expected[] = { - "Core:Fc1ccc([*:2])cc1Cl R2:C[*:2]", - "Core:Fc1ccc(Cl)cc1[*:1] R1:CC[*:1]"}; + const char *expected[] = {"Core:Fc1ccc([*:2])cc1Cl R2:C[*:2]", + "Core:Fc1ccc(Cl)cc1[*:1] R1:CC[*:1]"}; RGroupDecomposition decomp(*core, params); const auto add11 = decomp.add(*mol1); @@ -3969,8 +3968,9 @@ M END void testStereoBondBug() { BOOST_LOG(rdInfoLog) << "********************************************************\n"; - BOOST_LOG(rdInfoLog) << "Test that stereo bonds adjacent to the core or attachment atoms are handled correctly" - << std::endl; + BOOST_LOG(rdInfoLog) + << "Test that stereo bonds adjacent to the core or attachment atoms are handled correctly" + << std::endl; const auto core = R"CTAB(ACS Document 1996 ChemDraw10242316092D @@ -4004,7 +4004,7 @@ M END auto r1 = rows[0]["R1"]; // Check to see that Stereo bond is present and defined bool foundStereo = false; - for (const auto bond: r1->bonds()) { + for (const auto bond : r1->bonds()) { if (bond->getStereo() > Bond::STEREOANY) { TEST_ASSERT(!foundStereo); foundStereo = true; @@ -4041,7 +4041,7 @@ M END r1 = rows[0]["R1"]; // Check to see that Stereo bond is not present foundStereo = false; - for (const auto bond: r1->bonds()) { + for (const auto bond : r1->bonds()) { if (bond->getStereo() > Bond::STEREOANY) { foundStereo = true; } @@ -4077,7 +4077,7 @@ M END const auto c1 = rows[0]["Core"]; // Check to see that Stereo bond is not present foundStereo = false; - for (const auto bond: c1->bonds()) { + for (const auto bond : c1->bonds()) { if (bond->getStereo() > Bond::STEREOANY) { TEST_ASSERT(!foundStereo); foundStereo = true; @@ -4090,12 +4090,13 @@ M END void testNotEnumeratedCore() { BOOST_LOG(rdInfoLog) << "********************************************************\n"; - BOOST_LOG(rdInfoLog) << "Test that enumerated setting for non enumerated cores behaves properly" - << std::endl; - + BOOST_LOG(rdInfoLog) + << "Test that enumerated setting for non enumerated cores behaves properly" + << std::endl; + const auto core = "C1CCCCC1"_smarts; - const auto mol = "C1CCCCC1C"_smiles; - + const auto mol = "C1CCCCC1C"_smiles; + RGroupDecompositionParameters params; params.matchingStrategy = GreedyChunks; params.allowMultipleRGroupsOnUnlabelled = true; @@ -4116,38 +4117,37 @@ void testNotEnumeratedCore() { } void testRgroupDecompZipping() { - BOOST_LOG(rdInfoLog) - << "********************************************************\n"; - BOOST_LOG(rdInfoLog) << "Test we can reconstruct rgroup decomps that break rings" - << std::endl; - - const auto core = "N1OCC1"_smiles; - const auto mol = "C1CC2ONC12"_smiles; - RGroupDecompositionParameters params; - params.matchingStrategy = GreedyChunks; - params.allowMultipleRGroupsOnUnlabelled = true; - params.onlyMatchAtRGroups = false; - params.doEnumeration = true; - params.doTautomers = false; - RGroupDecomposition decomp(*core, params); - const auto add11 = decomp.add(*mol); - TEST_ASSERT(add11 == 0); - decomp.process(); - RGroupRows rows = decomp.getRGroupsAsRows(); - TEST_ASSERT(rows.size() == 1); - RGroupRows::const_iterator it = rows.begin(); - std::vector mols; - for (auto rgroups = it->begin(); rgroups != it->end(); ++rgroups) { - mols.push_back(rgroups->second); - } - auto res = molzip(mols); - TEST_ASSERT(MolToSmiles(*res) == "C1CC2ONC12") - - for(RGroupRow &rgroup: rows) { - res = molzip(rgroup); - TEST_ASSERT(MolToSmiles(*res) == "C1CC2ONC12") - } + BOOST_LOG(rdInfoLog) + << "********************************************************\n"; + BOOST_LOG(rdInfoLog) + << "Test we can reconstruct rgroup decomps that break rings" << std::endl; + const auto core = "N1OCC1"_smiles; + const auto mol = "C1CC2ONC12"_smiles; + RGroupDecompositionParameters params; + params.matchingStrategy = GreedyChunks; + params.allowMultipleRGroupsOnUnlabelled = true; + params.onlyMatchAtRGroups = false; + params.doEnumeration = true; + params.doTautomers = false; + RGroupDecomposition decomp(*core, params); + const auto add11 = decomp.add(*mol); + TEST_ASSERT(add11 == 0); + decomp.process(); + RGroupRows rows = decomp.getRGroupsAsRows(); + TEST_ASSERT(rows.size() == 1); + RGroupRows::const_iterator it = rows.begin(); + std::vector mols; + for (auto rgroups = it->begin(); rgroups != it->end(); ++rgroups) { + mols.push_back(rgroups->second); + } + auto res = molzip(mols); + TEST_ASSERT(MolToSmiles(*res) == "C1CC2ONC12") + + for (RGroupRow &rgroup : rows) { + res = molzip(rgroup); + TEST_ASSERT(MolToSmiles(*res) == "C1CC2ONC12") + } } int main() { diff --git a/Code/MinimalLib/cffi_test.c b/Code/MinimalLib/cffi_test.c index 002d05565..7f78cc6e3 100644 --- a/Code/MinimalLib/cffi_test.c +++ b/Code/MinimalLib/cffi_test.c @@ -2182,7 +2182,7 @@ void test_capture_logs() { } capture_test; capture_test tests[] = {{"tee", set_log_tee}, {"capture", set_log_capture}}; for (size_t i = 0; i < sizeof(tests) / sizeof(capture_test); ++i) { - printf("%d. %s\n", i + 1, tests[i].type); + printf("%zu. %s\n", i + 1, tests[i].type); log_handle = tests[i].func("dummy"); assert(!log_handle); log_handle = tests[i].func("rdApp.*"); diff --git a/External/CoordGen/CMakeLists.txt b/External/CoordGen/CMakeLists.txt index 2e7101cf2..52a072e99 100644 --- a/External/CoordGen/CMakeLists.txt +++ b/External/CoordGen/CMakeLists.txt @@ -85,6 +85,10 @@ if(RDK_BUILD_COORDGEN_SUPPORT) CACHE STRING "CoordGen Include File" FORCE) file(GLOB CGSOURCES "${COORDGEN_DIR}/*.cpp") rdkit_library(coordgen ${CGSOURCES} SHARED) +if(CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_compile_options(coordgen PUBLIC -Wno-unused-but-set-variable) + target_compile_options(coordgen_static PUBLIC -Wno-unused-but-set-variable) +endif() install(TARGETS coordgen DESTINATION ${RDKit_LibDir}) set(RDK_COORDGEN_LIBS coordgen CACHE STRING "the external libraries" FORCE) diff --git a/External/YAeHMOP/CMakeLists.txt b/External/YAeHMOP/CMakeLists.txt index 62c04cf7c..c8daef9a5 100644 --- a/External/YAeHMOP/CMakeLists.txt +++ b/External/YAeHMOP/CMakeLists.txt @@ -9,8 +9,8 @@ if(NOT DEFINED YAEHMOP_DIR) endif() if(NOT EXISTS "${YAEHMOP_DIR}/tightbind/bind.h") - set(RELEASE_NO "2023.03.1") - set(MD5 "e6450f13e02c54d024233b993c3c7ff6") + set(RELEASE_NO "2024.03.1") + set(MD5 "ebbddca4f79ab71544cb1fef9a7eca8a") downloadAndCheckMD5("https://github.com/greglandrum/yaehmop/archive/refs/tags/v${RELEASE_NO}.tar.gz" "${CMAKE_CURRENT_SOURCE_DIR}/yaehmop-${RELEASE_NO}.tar.gz" ${MD5}) execute_process(COMMAND ${CMAKE_COMMAND} -E tar zxf diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 227a6ec3c..0eef54ef9 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -21,10 +21,10 @@ jobs: - job: Ubuntu_x64_py311 timeoutInMinutes: 90 pool: - vmImage: ubuntu-20.04 + vmImage: ubuntu-latest variables: python: python=3.11 - boost_version: 1.80.0 + boost_version: 1.82.0 compiler: gxx_linux-64 cc: gcc-10 cxx: g++-10 @@ -126,6 +126,20 @@ jobs: python_name: python38 steps: - template: .azure-pipelines/vs_build_swig.yml +- job: Ubuntu_x64_ubsan + timeoutInMinutes: 90 + pool: + vmImage: ubuntu-latest + variables: + python: python=3.11 + boost_version: 1.82.0 + compiler: gxx_linux-64 + cc: gcc-10 + cxx: g++-10 + number_of_cores: nproc + python_name: python311 + steps: + - template: .azure-pipelines/linux_build_ubsan.yml # - job: Ubuntu_18_04_x64_fuzzer # timeoutInMinutes: 90