1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4""" 5 # Visual Studio cl options reference: 6 # https://msdn.microsoft.com/en-us/library/610ecb4h.aspx 7 # "Options are specified by either a forward slash (/) or a dash (–)." 8 # Here we use "-" better than "/" that produces invalid escaped chars using AutoTools. 9 # -LIBPATH, -D, -I, -ZI and so on. 10 11""" 12 13from conans.client.tools.apple import to_apple_arch 14from conans.client.tools.oss import cpu_count 15from conans.client.tools.win import unix_path 16 17 18GCC_LIKE = ['clang', 'apple-clang', 'gcc'] 19 20 21def _base_compiler(settings): 22 return settings.get_safe("compiler.base") or settings.get_safe("compiler") 23 24 25# FIXME : pass conanfile instead of settings and os_build 26def rpath_flags(settings, os_build, lib_paths): 27 compiler = _base_compiler(settings) 28 if not os_build: 29 return [] 30 if compiler in GCC_LIKE: 31 rpath_separator = "," 32 return ['-Wl,-rpath%s"%s"' % (rpath_separator, x.replace("\\", "/")) 33 for x in lib_paths if x] 34 return [] 35 36 37def architecture_flag(settings): 38 """ 39 returns flags specific to the target architecture and compiler 40 """ 41 compiler = settings.get_safe("compiler") 42 compiler_base = settings.get_safe("compiler.base") 43 arch = settings.get_safe("arch") 44 the_os = settings.get_safe("os") 45 subsystem = settings.get_safe("os.subsystem") 46 if not compiler or not arch: 47 return "" 48 49 if str(compiler) in ['gcc', 'apple-clang', 'clang', 'sun-cc']: 50 if str(the_os) == 'Macos' and str(subsystem) == 'catalyst': 51 apple_arch = to_apple_arch(arch) 52 if apple_arch: 53 return '--target=%s-apple-ios-macabi' % apple_arch 54 elif str(arch) in ['x86_64', 'sparcv9', 's390x']: 55 return '-m64' 56 elif str(arch) in ['x86', 'sparc']: 57 return '-m32' 58 elif str(arch) in ['s390']: 59 return '-m31' 60 elif str(the_os) == 'AIX': 61 if str(arch) in ['ppc32']: 62 return '-maix32' 63 elif str(arch) in ['ppc64']: 64 return '-maix64' 65 elif str(compiler) == "intel": 66 # https://software.intel.com/en-us/cpp-compiler-developer-guide-and-reference-m32-m64-qm32-qm64 67 if str(arch) == "x86": 68 return "/Qm32" if str(compiler_base) == "Visual Studio" else "-m32" 69 elif str(arch) == "x86_64": 70 return "/Qm64" if str(compiler_base) == "Visual Studio" else "-m64" 71 elif str(compiler) == "mcst-lcc": 72 return {"e2k-v2": "-march=elbrus-v2", 73 "e2k-v3": "-march=elbrus-v3", 74 "e2k-v4": "-march=elbrus-v4", 75 "e2k-v5": "-march=elbrus-v5", 76 "e2k-v6": "-march=elbrus-v6", 77 "e2k-v7": "-march=elbrus-v7"}.get(str(arch), "") 78 return "" 79 80 81def libcxx_define(settings): 82 compiler = _base_compiler(settings) 83 libcxx = settings.get_safe("compiler.libcxx") 84 if not compiler or not libcxx: 85 return "" 86 87 if str(compiler) in GCC_LIKE: 88 if str(libcxx) == 'libstdc++': 89 return '_GLIBCXX_USE_CXX11_ABI=0' 90 elif str(libcxx) == 'libstdc++11': 91 return '_GLIBCXX_USE_CXX11_ABI=1' 92 return "" 93 94 95def libcxx_flag(settings): 96 """ 97 returns flag specific to the target C++ standard library 98 """ 99 compiler = _base_compiler(settings) 100 libcxx = settings.get_safe("compiler.libcxx") 101 if not compiler or not libcxx: 102 return "" 103 if str(compiler) in ['clang', 'apple-clang']: 104 if str(libcxx) in ['libstdc++', 'libstdc++11']: 105 return '-stdlib=libstdc++' 106 elif str(libcxx) == 'libc++': 107 return '-stdlib=libc++' 108 elif str(compiler) == 'sun-cc': 109 return ({"libCstd": "-library=Cstd", 110 "libstdcxx": "-library=stdcxx4", 111 "libstlport": "-library=stlport4", 112 "libstdc++": "-library=stdcpp"}.get(libcxx, "")) 113 elif str(compiler) == "qcc": 114 return "-Y _%s" % str(libcxx) 115 return "" 116 117 118def pic_flag(settings): 119 """ 120 returns PIC (position independent code) flags, such as -fPIC 121 """ 122 compiler = _base_compiler(settings) 123 if not compiler or compiler == 'Visual Studio': 124 return "" 125 return '-fPIC' 126 127 128def build_type_flags(settings): 129 """ 130 returns flags specific to the build type (Debug, Release, etc.) 131 (-s, -g, /Zi, etc.) 132 """ 133 compiler = _base_compiler(settings) 134 build_type = settings.get_safe("build_type") 135 vs_toolset = settings.get_safe("compiler.toolset") 136 if not compiler or not build_type: 137 return "" 138 139 # https://github.com/Kitware/CMake/blob/d7af8a34b67026feaee558433db3a835d6007e06/ 140 # Modules/Platform/Windows-MSVC.cmake 141 if str(compiler) == 'Visual Studio': 142 if vs_toolset and "clang" in str(vs_toolset): 143 flags = {"Debug": ["-gline-tables-only", "-fno-inline", "-O0"], 144 "Release": ["-O2"], 145 "RelWithDebInfo": ["-gline-tables-only", "-O2", "-fno-inline"], 146 "MinSizeRel": [] 147 }.get(build_type, ["-O2", "-Ob2"]) 148 else: 149 flags = {"Debug": ["-Zi", "-Ob0", "-Od"], 150 "Release": ["-O2", "-Ob2"], 151 "RelWithDebInfo": ["-Zi", "-O2", "-Ob1"], 152 "MinSizeRel": ["-O1", "-Ob1"], 153 }.get(build_type, []) 154 return flags 155 else: 156 # https://github.com/Kitware/CMake/blob/f3bbb37b253a1f4a26809d6f132b3996aa2e16fc/ 157 # Modules/Compiler/GNU.cmake 158 # clang include the gnu (overriding some things, but not build type) and apple clang 159 # overrides clang but it doesn't touch clang either 160 if str(compiler) in ["clang", "gcc", "apple-clang", "qcc", "mcst-lcc"]: 161 # FIXME: It is not clear that the "-s" is something related with the build type 162 # cmake is not adjusting it 163 # -s: Remove all symbol table and relocation information from the executable. 164 flags = {"Debug": ["-g"], 165 "Release": ["-O3", "-s"] if str(compiler) == "gcc" else ["-O3"], 166 "RelWithDebInfo": ["-O2", "-g"], 167 "MinSizeRel": ["-Os"], 168 }.get(build_type, []) 169 return flags 170 elif str(compiler) == "sun-cc": 171 # https://github.com/Kitware/CMake/blob/f3bbb37b253a1f4a26809d6f132b3996aa2e16fc/ 172 # Modules/Compiler/SunPro-CXX.cmake 173 flags = {"Debug": ["-g"], 174 "Release": ["-xO3"], 175 "RelWithDebInfo": ["-xO2", "-g"], 176 "MinSizeRel": ["-xO2", "-xspace"], 177 }.get(build_type, []) 178 return flags 179 return "" 180 181 182def build_type_define(build_type=None): 183 """ 184 returns definitions specific to the build type (Debug, Release, etc.) 185 like DEBUG, _DEBUG, NDEBUG 186 """ 187 return 'NDEBUG' if build_type in ['Release', 'RelWithDebInfo', 'MinSizeRel'] else "" 188 189 190def adjust_path(path, settings, win_bash=False, subsystem=None): 191 """ 192 adjusts path to be safely passed to the compiler command line 193 for Windows bash, ensures path is in format according to the subsystem 194 for path with spaces, places double quotes around it 195 converts slashes to backslashes, or vice versa 196 """ 197 compiler = _base_compiler(settings) 198 if str(compiler) == 'Visual Studio': 199 path = path.replace('/', '\\') 200 else: 201 path = path.replace('\\', '/') 202 if win_bash: 203 path = unix_path(path, subsystem) 204 return '"%s"' % path if ' ' in path else path 205 206 207def sysroot_flag(sysroot, settings, win_bash=False, subsystem=None): 208 compiler = _base_compiler(settings) 209 if str(compiler) != 'Visual Studio' and sysroot: 210 sysroot = adjust_path(sysroot, settings, win_bash=win_bash, subsystem=subsystem) 211 return '--sysroot=%s' % sysroot 212 return "" 213 214 215def visual_runtime(runtime): 216 if runtime: 217 return "-%s" % runtime 218 return "" 219 220 221def format_defines(defines): 222 return ["-D%s" % define for define in defines if define] 223 224 225include_path_option = "-I" 226visual_linker_option_separator = "-link" # Further options will apply to the linker 227 228 229def format_include_paths(include_paths, settings, win_bash=False, subsystem=None): 230 return ["%s%s" % (include_path_option, adjust_path(include_path, settings, win_bash=win_bash, 231 subsystem=subsystem)) 232 for include_path in include_paths if include_path] 233 234 235def format_library_paths(library_paths, settings, win_bash=False, subsystem=None): 236 compiler = _base_compiler(settings) 237 pattern = "-LIBPATH:%s" if str(compiler) == 'Visual Studio' else "-L%s" 238 return [pattern % adjust_path(library_path, settings, win_bash=win_bash, 239 subsystem=subsystem) 240 for library_path in library_paths if library_path] 241 242 243def format_libraries(libraries, settings): 244 result = [] 245 compiler = settings.get_safe("compiler") 246 compiler_base = settings.get_safe("compiler.base") 247 for library in libraries: 248 if str(compiler) == 'Visual Studio' or str(compiler_base) == 'Visual Studio': 249 if not library.endswith(".lib"): 250 library += ".lib" 251 result.append(library) 252 else: 253 result.append("-l%s" % library) 254 return result 255 256 257def parallel_compiler_cl_flag(output=None): 258 return "/MP%s" % cpu_count(output=output) 259 260 261def format_frameworks(frameworks, settings): 262 """ 263 returns an appropriate compiler flags to link with Apple Frameworks 264 or an empty array, if Apple Frameworks aren't supported by the given compiler 265 """ 266 compiler = settings.get_safe("compiler") 267 compiler_base = settings.get_safe("compiler.base") 268 if (str(compiler) not in GCC_LIKE) and (str(compiler_base) not in GCC_LIKE): 269 return [] 270 return ["-framework %s" % framework for framework in frameworks] 271 272 273def format_framework_paths(framework_paths, settings): 274 """ 275 returns an appropriate compiler flags to specify Apple Frameworks search paths 276 or an empty array, if Apple Frameworks aren't supported by the given compiler 277 """ 278 compiler = settings.get_safe("compiler") 279 compiler_base = settings.get_safe("compiler.base") 280 if (str(compiler) not in GCC_LIKE) and (str(compiler_base) not in GCC_LIKE): 281 return [] 282 return ["-F %s" % adjust_path(framework_path, settings) for framework_path in framework_paths] 283