-
-
Save hoyhoy/dc46c8edbf442fd51f44e51d542d185c to your computer and use it in GitHub Desktop.
| {# █████████████████████████████████████████████████████████████████ #} | |
| {# █ @hoyhoy - 1/12/2024 █ #} | |
| {# █████████████████████████████████████████████████████████████████ #} | |
| {# █ Jinja2 Profile Example to Auto-generate Compiler Sanitizer █ #} | |
| {# █ Flags for a custom llvm build on MacOS and Linux █ #} | |
| {# █████████████████████████████████████████████████████████████████ #} | |
| {# ██████████████████████████████████████████████████████████████████ #} | |
| {# █ $CONAN_HOME/profiles/common/clang_local.j2 █ #} | |
| {# ██████████████████████████████████████████████████████████████████ #} | |
| {% set compiler.name = "clang" %} | |
| {% set compiler.version = detect_api.detect_compiler()[1].major %} | |
| {% set llvm_root = "/usr/local" %} | |
| {% set ccache_bin = "/opt/ccache/bin" %} | |
| {% set llvm_bin = llvm_root ~ "/bin" %} | |
| {% set llvm_lib = llvm_root ~ "/lib" %} | |
| {% set llvm_system = platform.system().lower() %} | |
| {% set compiler.system = llvm_system %} | |
| {% set compiler.llvm_root = llvm_root %} | |
| {% set compiler.llvm_bin = llvm_root ~ "bin" %} | |
| {% set compiler.lib_dir = llvm_lib %} | |
| {% set compiler.include_dir = llvm_root ~ "/include" %} | |
| {# ██████████████████████████████████████████████████████████████████ #} | |
| {# █ The only reason these ccaache symlinks are necessary is █ #} | |
| {# █ because conan2 doesn't support adding a compiler launcher █ #} | |
| {# █ to the CMakeToolChain() directly. I suggest adding these. █ #} | |
| {# █ to conan3. (NOTE: THESE SETTINGS DO NOT EXIST BUT THEY SHOULD! █ #} | |
| {# █ █ #} | |
| {# █ - tools.build:compiler_executables.cmake_cxx_compiler_launcher █ #} | |
| {# █ - tools.build:compiler_executables.cmake_c_compiler_launcher █ #} | |
| {# ██████████████████████████████████████████████████████████████████ #} | |
| {# ██████████████████████████████████████████████████████████████████ #} | |
| {# █ $CMAKE_MODULE_PATH/ccache.cmake █ #} | |
| {# ██████████████████████████████████████████████████████████████████ #} | |
| {# █ A CMakeLists.txt as a Jinja2 comment? Sure why not? █ #} | |
| {# █ This is how to auto-detect ccache using cmake! █ #} | |
| {# ██████████████████████████████████████████████████████████████████ #} | |
| {# #} | |
| {# include_guard(GLOBAL) #} | |
| {# if (NOT "$ENV{CCACHE_DISABLE}" STREQUAL "1") #} | |
| {# find_program(CCACHE_PROGRAM ccache) #} | |
| {# if (CCACHE_PROGRAM) #} | |
| {# set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") #} | |
| {# set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") #} | |
| {# endif () #} | |
| {# endif () #} | |
| {# ██████████████████████████████████████████████████████████████████ #} | |
| {# ██████████████████████████████████████████████████████████████████ #} | |
| {# █ $CONAN_HOME/profiles/common/clang_local.j2 (continues...) █ #} | |
| {# ██████████████████████████████████████████████████████████████████ #} | |
| {% set compiler.cc = ccache_bin ~ "/clang" %} | |
| {% set compiler.cxx = ccache_bin ~ "/clang++" %} | |
| {% set compiler.cc = llvm_bin ~ "/clang" %} | |
| {% set compiler.cxx = llvm_bin ~ "/clang++" %} | |
| {% set compiler.ld = llvm_bin ~ "/lld" %} | |
| {% set compiler.ar = llvm_bin ~ "/llvm-ar" %} | |
| {% set compiler.as = llvm_bin ~ "/llvm-as" %} | |
| {% set compiler.nm = llvm_bin ~ "/llvm-nm" %} | |
| {% set compiler.ranlib = llvm_bin ~ "/llvm-ranlib" %} | |
| {% set compiler.symbolizer = llvm_bin ~ "/llvm-symbolizer" %} | |
| {% set compiler.cppstd = "17" %} | |
| {% set compiler.definitions = [ "_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION" ] %} | |
| {% set compiler.ldflags = [ "-L" ~ llvm_lib, "-fuse-ld=lld", "-Wl,-rpath," ~ llvm_lib ] %} | |
| {% set compiler.flags = [] %} | |
| {% set compiler.address_sanitizer = { | |
| flags: [ | |
| "-fsanitize=address", | |
| "-fsanitize-address-use-after-scope", | |
| "-fsanitize-address-use-after-return=always" | |
| ], | |
| ldflags: [ "-fsanitize=address", ] | |
| } | |
| %} | |
| {% set compiler.thread_sanitizer = { | |
| flags: [ | |
| "-fsanitize=address" | |
| ], | |
| ldflags: [ "-fsanitize=thread" ] | |
| } | |
| %} | |
| {% set compiler.memory_sanitizer = { | |
| flags: [ | |
| "-fsanitize=mmory" | |
| ], | |
| ldflags: [ "-fsanitize=memory" ] | |
| } | |
| %} | |
| {% set compiler.debug_flags = [ "-g", "-glldb", "-gcolumn-info" ] %} | |
| {% set compiler.disabled_warnings = [ "-Wno-everything" ] %} | |
| {% set _ = profile.settings.update({ | |
| "compiler": compiler.name, | |
| "compiler.libcxx": "libc++", | |
| "compiler.cppstd": compiler.cppstd, | |
| "compiler.version": compiler.version, | |
| "compiler.warnings": "All", | |
| "compiler.warnings_as_errors": True | |
| }) | |
| %} | |
| {% set compiler.dependency_options = { | |
| "flags": compiler.flags + compiler.disabled_warnings | |
| } | |
| %} | |
| {% if build_type == "Debug" %} | |
| {% set _ = compiler.dependency_options["flags"].append(compiler.debug_flags) %} | |
| {% if compiler.sanitizer == "address" %} | |
| {% set _ = compiler.dependency_options.flags.append(compiler.address_sanitizer["compiler_flags"]) %} | |
| {% set _ = compiler.ldflags.extend(compiler.dependency_options["flags"]) %} | |
| {% elif compiler.sanitizer == "memory" %} | |
| {% set _ = compiler.dependency_options.flags.append(compiler.memory_sanitizer["compiler_flags"]) %} | |
| {% set _ = compiler.ldflags.extend(compiler.dependency_options["flags"]) %} | |
| {% elif compiler.sanitizer == "thread" %} | |
| {% set _ = compiler.dependency_options.flags.append(compiler.memory_sanitizer["compiler_flags"]) %} | |
| {% set _ = compiler.ldflags.extend(compiler.dependency_options["flags"]) %} | |
| {% endif %} | |
| {% endif %} | |
| {% set compiler.optimized_flags = ["-O3", "-march=native", "-funroll-loops", "-finline-functions", "-mtune=native" ] %} | |
| {% set _ = profile.build_configuration.update({ | |
| "tools.build:compiler_executables": { "c" : compiler.cc, "cpp": compiler.cxx }, | |
| "tools.build:defines": compiler.definitions, | |
| "tools.build:exelinkflags": compiler.ldflags, | |
| "tools.build:compiler_executables": { "c" : compiler.cc, "cpp": compiler.cxx }, | |
| "tools.build:cflags": compiler.dependency_options["flags"] + compiler.optimized_flags, | |
| "tools.build:cxxflags": compiler.dependency_options["flags"] + compiler.optimized_flags, | |
| "tools.build:defines": compiler.definitions, | |
| "myapp/*:tools.build:cflags": compiler.flags, | |
| "myapp/*:tools.build:cxxflags": compiler.flags, | |
| "tools.build:exelinkflags": compiler.ldflags | |
| }) | |
| %} | |
| {% set _ = profile.build_configuration.update({ | |
| "tools.build:compiler_executables": { "c" : compiler.cc, "cpp": compiler.cxx }, | |
| "tools.build:defines": compiler.definitions, | |
| "tools.build:exelinkflags": compiler.ldflags | |
| }) | |
| %} | |
| {% set _ = profile.configuration.update({ | |
| "tools.build:compiler_executables": { "c" : compiler.cc, "cpp": compiler.cxx }, | |
| "tools.build:cflags": compiler.dependency_options["flags"], | |
| "tools.build:cxxflags": compiler.dependency_options["flags"], | |
| "tools.build:defines": compiler.definitions, | |
| "myapp/*:tools.build:cflags": compiler.flags, | |
| "myapp/*:tools.build:cxxflags": compiler.flags, | |
| "tools.build:exelinkflags": compiler.ldflags | |
| }) | |
| %} | |
| {% set _ = profile.environment.update({ | |
| "CPATH": compiler.include_dir, | |
| "CC": compiler.cc, | |
| "CXX": compiler.cxx, | |
| "LD": compiler.ld, | |
| "AS": compiler.as, | |
| "AR": compiler.ar, | |
| "NM": compiler.nm, | |
| "RANLIB": compiler.ranlib, | |
| "LINKER": compiler.ld, | |
| "LLVM_DIR": compiler.llvm_root, | |
| "LLVM_PATH": compiler.llvm_bin, | |
| "LD_LIBRARY_PATH": compiler.libpath, | |
| "LIBPATH": compiler.libpath, | |
| "FIPSLD_CC": compiler.cc, | |
| "FIPSLD_CXX": compiler.cxx, | |
| "FIPS_LD": compiler.ld, | |
| "FIPS_CXXLD": compiler.ld, | |
| "ASAN_SYMBOLIZER_PATH": compiler.symbolizer, | |
| "MSAN_SYMBOLIZER_PATH": compiler.symbolizer, | |
| "TSAN_SYMBOLIZER_PATH": compiler.symbolizer | |
| }) | |
| %} | |
| {# I then include clang_local.j2 into my default host profile.... #} | |
| {# ██████████████████████████████████████████████████████████████ #} | |
| {# █ CONAN_HOME/profiles/default █ #} | |
| {# ██████████████████████████████████████████████████████████████ #} | |
| {% with | |
| profile = namespace( | |
| build_type = "Debug", | |
| settings = {}, | |
| options = {}, | |
| devtest_mode = {}, | |
| sanitizer = None, | |
| configuration = {}, | |
| build_configuration = {}, | |
| environment = {}), | |
| os = namespace(), | |
| compiler = namespace() | |
| %} | |
| {% include "common/native.j2" %} | |
| {% include "common/clang_local.j2" %} | |
| {% include "common/dependencies.j2" %} | |
| {% include "common/boost.j2" %} | |
| [settings] | |
| build_type={{profile.build_type}} | |
| {% for s,value in profile.settings.items() %} | |
| {{s}}={{value}} | |
| {% endfor %} | |
| [options] | |
| {% for option,value in profile.options.items() -%} | |
| {{option}}={{value}} | |
| {% endfor %} | |
| tools.cmake.cmake_layout:build_folder_vars=["settings.build_type"] | |
| [conf] | |
| {% for option,value in profile.configuration.items() -%} | |
| {{option}}={{value}} | |
| {% endfor %} | |
| [buildenv] | |
| {% for option,value in profile.environment.items() -%} | |
| {{option}}={{value}} | |
| {% endfor %} | |
| b2/*:CXXFLAGS={{compiler.optimized_flags ~ " " ~ " ".join(compiler.ldflags) }} | |
| {% endwith %} | |
| {# ██████████████████████████████████████████████████████████████ #} | |
| {# █ $CONAN_HOME/profiles/native.j2 █ #} | |
| {# ██████████████████████████████████████████████████████████████ #} | |
| {# █ Automatically generate os, and os version █ #} | |
| {# ██████████████████████████████████████████████████████████████ #} | |
| {% set current_os = detect_api.detect_os() %} | |
| {% set _ = profile.settings.update({ | |
| "os": current_os, | |
| "arch": platform.machine() | |
| }) | |
| %} | |
| {% if current_os == "Macos" %} | |
| {# why isn't a function to emit the version string built-in to conan2? #} | |
| {% set _ = profile.settings.update({ | |
| "os.version": ".".join(platform.mac_ver()[0].split(".")[0:2]) | |
| }) | |
| %} | |
| {% endif %} | |
| {# ██████████████████████████████████████████████████████████████ #} | |
| {# █ $CONAN_HOME/profiles/common/boost.j2 █ #} | |
| {# ██████████████████████████████████████████████████████████████ #} | |
| {# █ Boost has so many flags, it gets its own include file! █ #} | |
| {# ██████████████████████████████████████████████████████████████ #} | |
| {% set _ = profile.options.update({ | |
| "boost/*:extra_b2_flags": "cxxflags=-Wno-everything cxxflags=-D_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION", | |
| "boost/*:without_thread": False, | |
| "boost/*:without_log": False, | |
| "boost/*:without_locale": False, | |
| "boost/*:without_random": False, | |
| "boost/*:without_date_time": False, | |
| "boost/*:without_container": False, | |
| "boost/*:without_regex": False, | |
| "boost/*:without_filesystem": False, | |
| "boost/*:without_math": False, | |
| "boost/*:without_atomic": False, | |
| "boost/*:without_chrono": False, | |
| "boost/*:without_exception": False, | |
| "boost/*:without_system": False, | |
| "boost/*:without_context": True, | |
| "boost/*:without_contract": True, | |
| "boost/*:without_coroutine": True, | |
| "boost/*:without_fiber": True, | |
| "boost/*:without_graph": True, | |
| "boost/*:without_graph_parallel": True, | |
| "boost/*:without_iostreams": True, | |
| "boost/*:without_json": True, | |
| "boost/*:without_mpi": True, | |
| "boost/*:without_nowide": True, | |
| "boost/*:without_program_options": True, | |
| "boost/*:without_python": True, | |
| "boost/*:without_serialization": True, | |
| "boost/*:without_stacktrace": True, | |
| "boost/*:without_test": True, | |
| "boost/*:without_timer": True, | |
| "boost/*:without_type_erasure": True, | |
| "boost/*:without_wave": True, | |
| "boost/*:without_url": True, | |
| "boost/*:shared": False, | |
| "boost/*:i18n_backend_icu": True, | |
| "boost/*:i18n_backend_iconv": "off", | |
| "boost/*:bzip2": False | |
| }) | |
| %} | |
| {# ██████████████████████████████████████████████████████████████ #} | |
| {# █ $CONAN_HOME/profiles/common/dependencies.j2 █ #} | |
| {# ██████████████████████████████████████████████████████████████ #} | |
| {% set _ = profile.options.update({ | |
| "icu/*:shared": False, | |
| "*:fPIC": True, | |
| "libxml2/*:include_utils": True, | |
| "libxml2/*:shared": False, | |
| "libxml2/*:iconv": False, | |
| "libxml2/*:icu": False, | |
| "hiredis/*:with_ssl": True, | |
| "azure-storage-cpp/*:shared": False, | |
| "cpprestsdk/*:shared": False, | |
| "openssl/*:no_ssl3": True, | |
| "openssl/*:no_rc5": True, | |
| "openssl/*:shared": False, | |
| "openssl/*:no_zlib": True, | |
| "openssl/*:no_fips": False | |
| }) | |
| %} | |
| {# Custom options per-os! #} | |
| {% set current_os = detect_api.detect_os() %} | |
| {% if current_os == "Windows" %} | |
| {% set _ = profile.options.update({ | |
| "cpprestsdk/*:http_client_impl": "asio", | |
| "cpprestsdk/*:http_listener_impl": "asio" | |
| }) %} | |
| {% endif %} |
Didn’t seem to matter for ASAN with all of our dependencies and we have quite a few.
Our app’s CMakelists.txt does set CMAKE_SHARED_LINKER_FLAGS outside of conan, but not for sanitization purposes.
The regular ldflags are applied to the shared libraries as well. IIRC, CMAKE_SHARED_LINKER_FLAGS is just added on top of the regular LDFLAGS for shared libraries. I don’t think Gnu Make even has an environment variable for this.
@steinerthomas turns out I was missing tools.build:sharedlinkflags. If you don't set the sanitizer flags there, ASAN raises all kinds of ruckus if you dlopen() a library that isn't linked with -fsanitize=address.
The other nightmare problem with ASAN is that you have disable assembly (no_asm=True) when compiling openssl with -DPEDANTIC.
nice generic profile!
Are you missing the
"tools.build:sharedlinkflags": compiler.ldflagsor is it intended to not set them?