Skip to content

[sanitizers] Add custom CMake build type as an option#4312

Merged
czoido merged 5 commits into
conan-io:release/2.22from
uilianries:sanitizers/cmake-build-type
Nov 17, 2025
Merged

[sanitizers] Add custom CMake build type as an option#4312
czoido merged 5 commits into
conan-io:release/2.22from
uilianries:sanitizers/cmake-build-type

Conversation

@uilianries
Copy link
Copy Markdown
Member

Hello! This PR is a follow-up to #4199

As @memsharded commented to me, people are using a custom CMake build type, like DebugASan, instead of adding a new setting like compiler.sanitizers. As a very valid scenario, I brought the case to the documentation as well.

It will require a CMake file with the flags and rules managed by the user, but can be easily integrated by using the Conan conf user_toolchain. BTW, I made a mistake in the first PR: user_toolchain is a list, not a string.

Tested this new scenario locally using a simple conan new cmake_lib + following the instructions:

You can see the new build type DebugASan and the compiler flags -fsanitize=address -fno-omit-frame-pointer during the build:

conan create . -s build_type=DebugASan -pr gcc_asan_ubsan.profile

======== Exporting recipe to the cache ========
bar/0.1.0: [HOOK - hook_recipe_metadata.py] pre_export(): WARN: Attribute 'homepage' is mandatory in the recipe
bar/0.1.0: [HOOK - hook_recipe_metadata.py] pre_export(): WARN: Attribute 'url' should be directed to 'https://github.com/conan-io/conan-center-index'
bar/0.1.0: Exporting package recipe: /tmp/tmp.hbibWz6gub/conanfile.py
bar/0.1.0: Copied 1 '.py' file: conanfile.py
bar/0.1.0: Copied 1 '.txt' file: CMakeLists.txt
bar/0.1.0: Copied 1 '.cpp' file: bar.cpp
bar/0.1.0: Copied 1 '.h' file: bar.h
bar/0.1.0: Exported to cache folder: /home/uilian/.conan2/p/bar0345223dec650/e
bar/0.1.0: Exported: bar/0.1.0#383a61131c291bf9d9c46c98247aafa5 (2025-11-14 08:25:10 UTC)

======== Input profiles ========
Profile host:
[settings]
arch=x86_64
build_type=DebugASan
compiler=gcc
compiler.cppstd=gnu20
compiler.libcxx=libstdc++11
compiler.version=15
os=Linux
[conf]
tools.build:verbosity=verbose
tools.cmake.cmaketoolchain:generator=Ninja
tools.cmake.cmaketoolchain:user_toolchain=['/tmp/tmp.hbibWz6gub/cmake/sanitizer_toolchain.cmake']
tools.compilation:verbosity=verbose
tools.system.package_manager:mode=install
tools.system.package_manager:sudo=true

Profile build:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=11
os=Linux
[conf]
tools.build:verbosity=verbose
tools.cmake.cmaketoolchain:generator=Ninja
tools.compilation:verbosity=verbose
tools.system.package_manager:mode=install
tools.system.package_manager:sudo=true


======== Computing dependency graph ========
Graph root
    cli
Requirements
    bar/0.1.0#383a61131c291bf9d9c46c98247aafa5 - Cache

======== Computing necessary packages ========
bar/0.1.0: Forced build from source
Requirements
    bar/0.1.0#383a61131c291bf9d9c46c98247aafa5:e41ca83963d6c4a362a7fe64eaa6a67aed977955 - Build

======== Installing packages ========

-------- Installing package bar/0.1.0 (1 of 1) --------
bar/0.1.0: Building from source
bar/0.1.0: Package bar/0.1.0:e41ca83963d6c4a362a7fe64eaa6a67aed977955
bar/0.1.0: settings: os=Linux arch=x86_64 compiler=gcc compiler.cppstd=gnu20 compiler.libcxx=libstdc++11 compiler.version=15 build_type=DebugASan
bar/0.1.0: options: fPIC=True shared=False
bar/0.1.0: Copying sources to build folder
bar/0.1.0: Building your package in /home/uilian/.conan2/p/b/bar49dab3df703ca/b
bar/0.1.0: Calling generate()
bar/0.1.0: Generators folder: /home/uilian/.conan2/p/b/bar49dab3df703ca/b/build/DebugASan/generators
bar/0.1.0: CMakeToolchain generated: conan_toolchain.cmake
bar/0.1.0: CMakeToolchain generated: /home/uilian/.conan2/p/b/bar49dab3df703ca/b/build/DebugASan/generators/CMakePresets.json
bar/0.1.0: CMakeToolchain generated: /home/uilian/.conan2/p/b/bar49dab3df703ca/b/CMakeUserPresets.json
bar/0.1.0: Generating aggregated env files
bar/0.1.0: Generated aggregated env files: ['conanbuild.sh', 'conanrun.sh']
bar/0.1.0: Calling build()
bar/0.1.0: Running CMake.configure()
bar/0.1.0: RUN: cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="generators/conan_toolchain.cmake" -DCMAKE_INSTALL_PREFIX="/home/uilian/.conan2/p/b/bar49dab3df703ca/p" -DCMAKE_POLICY_DEFAULT_CMP0091="NEW" -DCMAKE_BUILD_TYPE="DebugASan" "/home/uilian/.conan2/p/b/bar49dab3df703ca/b" --loglevel=VERBOSE
-- Using Conan toolchain: /home/uilian/.conan2/p/b/bar49dab3df703ca/b/build/DebugASan/generators/conan_toolchain.cmake
-- Conan toolchain: Including user_toolchain: /tmp/tmp.hbibWz6gub/cmake/sanitizer_toolchain.cmake
-- Conan toolchain: Setting CMAKE_POSITION_INDEPENDENT_CODE=ON (options.fPIC)
-- Conan toolchain: Defining architecture flag: -m64
-- Conan toolchain: C++ Standard 20 with extensions ON
-- Conan toolchain: Setting BUILD_SHARED_LIBS = OFF
-- The CXX compiler identification is GNU 11.4.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.2s)
-- Generating done (0.0s)
-- Build files have been written to: /home/uilian/.conan2/p/b/bar49dab3df703ca/b/build/DebugASan

bar/0.1.0: Running CMake.build()
bar/0.1.0: RUN: cmake --build "/home/uilian/.conan2/p/b/bar49dab3df703ca/b/build/DebugASan" --verbose -- -j12
Change Dir: '/home/uilian/.conan2/p/b/bar49dab3df703ca/b/build/DebugASan'

Run Build Command(s): /usr/local/bin/ninja -v -j12
[1/2] /usr/bin/c++  -I/home/uilian/.conan2/p/b/bar49dab3df703ca/b/include -fsanitize=address -fno-omit-frame-pointer -std=gnu++20 -fPIC -MD -MT CMakeFiles/bar.dir/src/bar.cpp.o -MF CMakeFiles/bar.dir/src/bar.cpp.o.d -o CMakeFiles/bar.dir/src/bar.cpp.o -c /home/uilian/.conan2/p/b/bar49dab3df703ca/b/src/bar.cpp
[2/2] : && /opt/pyenv/versions/3.12.4/lib/python3.12/site-packages/cmake/data/bin/cmake -E rm -f libbar.a && /usr/bin/ar qc libbar.a  CMakeFiles/bar.dir/src/bar.cpp.o && /usr/bin/ranlib libbar.a && :


bar/0.1.0: [HOOK - hook_boost_serialization.py] post_build(): Executing post-build hook for Boost serialization
bar/0.1.0: Package 'e41ca83963d6c4a362a7fe64eaa6a67aed977955' built
bar/0.1.0: Build folder /home/uilian/.conan2/p/b/bar49dab3df703ca/b/build/DebugASan
bar/0.1.0: Generating the package
bar/0.1.0: Packaging in folder /home/uilian/.conan2/p/b/bar49dab3df703ca/p
bar/0.1.0: Calling package()
bar/0.1.0: Running CMake.install()
bar/0.1.0: RUN: cmake --install "/home/uilian/.conan2/p/b/bar49dab3df703ca/b/build/DebugASan" --prefix "/home/uilian/.conan2/p/b/bar49dab3df703ca/p" --verbose
-- Install configuration: "DebugASan"
-- Installing: /home/uilian/.conan2/p/b/bar49dab3df703ca/p/lib/libbar.a
-- Installing: /home/uilian/.conan2/p/b/bar49dab3df703ca/p/include/bar.h

bar/0.1.0: [HOOK - hook_package_license.py] post_package(): WARN: No 'licenses' folder found in package folder
bar/0.1.0: package(): Packaged 1 '.a' file: libbar.a
bar/0.1.0: package(): Packaged 1 '.h' file: bar.h
bar/0.1.0: Created package revision eaf7c74e0a2f85c4639fd21df33f16e4
bar/0.1.0: Package 'e41ca83963d6c4a362a7fe64eaa6a67aed977955' created
bar/0.1.0: Full package reference: bar/0.1.0#383a61131c291bf9d9c46c98247aafa5:e41ca83963d6c4a362a7fe64eaa6a67aed977955#eaf7c74e0a2f85c4639fd21df33f16e4
bar/0.1.0: Package folder /home/uilian/.conan2/p/b/bar49dab3df703ca/p

======== Launching test_package ========

======== Computing dependency graph ========
Graph root
    bar/0.1.0 (test package): /tmp/tmp.hbibWz6gub/test_package/conanfile.py
Requirements
    bar/0.1.0#383a61131c291bf9d9c46c98247aafa5 - Cache

======== Computing necessary packages ========
Requirements
    bar/0.1.0#383a61131c291bf9d9c46c98247aafa5:e41ca83963d6c4a362a7fe64eaa6a67aed977955#eaf7c74e0a2f85c4639fd21df33f16e4 - Cache

======== Installing packages ========
bar/0.1.0: Already installed! (1 of 1)

======== Testing the package ========
Removing previously existing 'test_package' build folder: /tmp/tmp.hbibWz6gub/test_package/build/gcc-15-x86_64-gnu20-debugasan
bar/0.1.0 (test package): Test package build: build/gcc-15-x86_64-gnu20-debugasan
bar/0.1.0 (test package): Test package build folder: /tmp/tmp.hbibWz6gub/test_package/build/gcc-15-x86_64-gnu20-debugasan
bar/0.1.0 (test package): Writing generators to /tmp/tmp.hbibWz6gub/test_package/build/gcc-15-x86_64-gnu20-debugasan/generators
bar/0.1.0 (test package): Generator 'CMakeDeps' calling 'generate()'
bar/0.1.0 (test package): CMakeDeps necessary find_package() and targets for your CMakeLists.txt
    find_package(bar)
    target_link_libraries(... bar::bar)
bar/0.1.0 (test package): Generator 'CMakeToolchain' calling 'generate()'
bar/0.1.0 (test package): CMakeToolchain generated: conan_toolchain.cmake
bar/0.1.0 (test package): CMakeToolchain generated: /tmp/tmp.hbibWz6gub/test_package/build/gcc-15-x86_64-gnu20-debugasan/generators/CMakePresets.json
bar/0.1.0 (test package): CMakeToolchain generated: /tmp/tmp.hbibWz6gub/test_package/CMakeUserPresets.json
bar/0.1.0 (test package): Generating aggregated env files
bar/0.1.0 (test package): Generated aggregated env files: ['conanbuild.sh', 'conanrun.sh']

======== Testing the package: Building ========
bar/0.1.0 (test package): Calling build()
bar/0.1.0 (test package): Running CMake.configure()
bar/0.1.0 (test package): RUN: cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="generators/conan_toolchain.cmake" -DCMAKE_INSTALL_PREFIX="/tmp/tmp.hbibWz6gub/test_package" -DCMAKE_POLICY_DEFAULT_CMP0091="NEW" -DCMAKE_BUILD_TYPE="DebugASan" "/tmp/tmp.hbibWz6gub/test_package" --loglevel=VERBOSE
-- Using Conan toolchain: /tmp/tmp.hbibWz6gub/test_package/build/gcc-15-x86_64-gnu20-debugasan/generators/conan_toolchain.cmake
-- Conan toolchain: Including user_toolchain: /tmp/tmp.hbibWz6gub/cmake/sanitizer_toolchain.cmake
-- Conan toolchain: Defining architecture flag: -m64
-- Conan toolchain: C++ Standard 20 with extensions ON
-- The CXX compiler identification is GNU 11.4.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Conan: Target declared 'bar::bar'
-- Conan: Library bar found /home/uilian/.conan2/p/b/bar49dab3df703ca/p/lib/libbar.a
-- Conan: Found: /home/uilian/.conan2/p/b/bar49dab3df703ca/p/lib/libbar.a
-- Configuring done (0.2s)
-- Generating done (0.0s)
-- Build files have been written to: /tmp/tmp.hbibWz6gub/test_package/build/gcc-15-x86_64-gnu20-debugasan

bar/0.1.0 (test package): Running CMake.build()
bar/0.1.0 (test package): RUN: cmake --build "/tmp/tmp.hbibWz6gub/test_package/build/gcc-15-x86_64-gnu20-debugasan" --verbose -- -j12
Change Dir: '/tmp/tmp.hbibWz6gub/test_package/build/gcc-15-x86_64-gnu20-debugasan'

Run Build Command(s): /usr/local/bin/ninja -v -j12
[1/2] /usr/bin/c++  -isystem /home/uilian/.conan2/p/b/bar49dab3df703ca/p/include -fsanitize=address -fno-omit-frame-pointer -std=gnu++20 -MD -MT CMakeFiles/example.dir/src/example.cpp.o -MF CMakeFiles/example.dir/src/example.cpp.o.d -o CMakeFiles/example.dir/src/example.cpp.o -c /tmp/tmp.hbibWz6gub/test_package/src/example.cpp
[2/2] : && /usr/bin/c++ -fsanitize=address -fno-omit-frame-pointer -fsanitize=address -fno-omit-frame-pointer CMakeFiles/example.dir/src/example.cpp.o -o example -L/home/uilian/.conan2/p/b/bar49dab3df703ca/p/lib -Wl,-rpath,/home/uilian/.conan2/p/b/bar49dab3df703ca/p/lib  /home/uilian/.conan2/p/b/bar49dab3df703ca/p/lib/libbar.a && :


bar/0.1.0 (test package): [HOOK - hook_boost_serialization.py] post_build(): Executing post-build hook for Boost serialization

======== Testing the package: Executing test ========
bar/0.1.0 (test package): Running test()
bar/0.1.0 (test package): RUN: ./example
bar/0.1.0: Hello World Debug!
  bar/0.1.0: __x86_64__ defined
  bar/0.1.0: _GLIBCXX_USE_CXX11_ABI 1
  bar/0.1.0: __cplusplus202002
  bar/0.1.0: __GNUC__11
  bar/0.1.0: __GNUC_MINOR__4
bar/0.1.0 test_package

Signed-off-by: Uilian Ries <uilianr@jfrog.com>
@uilianries uilianries changed the base branch from develop2 to release/2.22 November 14, 2025 08:28
Signed-off-by: Uilian Ries <uilianr@jfrog.com>
Copy link
Copy Markdown
Member

@memsharded memsharded left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking very good, thanks!

Comment thread security/sanitizers.rst
Similar to managing sanitizers with a custom CMake toolchain, but without ``compiler.sanitizer`` custom settings,
is to define sanitizers as part of a custom CMake build type. This way, you can select the desired sanitizer configuration
by specifying the build type during the CMake configuration step.
To achieve this, you can create a custom CMake toolchain file that maps build types to sanitizer flags. For example:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a sentence, saying something like: "as this is a custom build type, you need to also define the flags that correspond to the desired based build type, for example that -g flag that matches the Debug build_type in gcc-like compilers"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, please, check the commit 47bc9f7

Signed-off-by: Uilian Ries <uilianr@jfrog.com>
Copy link
Copy Markdown
Member

@memsharded memsharded left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect!

Comment thread security/sanitizers.rst Outdated
Comment thread security/sanitizers.rst Outdated
Comment thread security/sanitizers.rst
.. code-block:: cmake
:caption: cmake/sanitizer_toolchain.cmake

if(CMAKE_BUILD_TYPE STREQUAL "DebugASan")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a note saying that this example assumes a single-configuration generator that uses CMAKE_BUILD_TYPE?

Copy link
Copy Markdown
Member Author

@uilianries uilianries Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think is really needed because is a very custom build, I mean, who customizes should know what they are doing as a custom build.

Copy link
Copy Markdown
Contributor

@czoido czoido left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of minor comments, but looks great! 👏

uilianries and others added 2 commits November 14, 2025 11:12
Co-authored-by: Carlos Zoido <mrgalleta@gmail.com>
Co-authored-by: Carlos Zoido <mrgalleta@gmail.com>
@uilianries uilianries requested a review from czoido November 14, 2025 10:33
@czoido czoido merged commit a7df240 into conan-io:release/2.22 Nov 17, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants