File indexing completed on 2025-02-16 05:12:09

0001 #!/usr/bin/env python
0002 # -*- coding: utf-8 -*-
0003 
0004 """
0005     # Visual Studio cl options reference:
0006     #   https://msdn.microsoft.com/en-us/library/610ecb4h.aspx
0007     #       "Options are specified by either a forward slash (/) or a dash (–)."
0008     #   Here we use "-" better than "/" that produces invalid escaped chars using AutoTools.
0009     #   -LIBPATH, -D, -I, -ZI and so on.
0010 
0011 """
0012 
0013 from conans.client.tools.apple import to_apple_arch
0014 from conans.client.tools.oss import cpu_count
0015 from conans.client.tools.win import unix_path
0016 
0017 
0018 GCC_LIKE = ['clang', 'apple-clang', 'gcc']
0019 
0020 
0021 def _base_compiler(settings):
0022     return settings.get_safe("compiler.base") or settings.get_safe("compiler")
0023 
0024 
0025 # FIXME : pass conanfile instead of settings and os_build
0026 def rpath_flags(settings, os_build, lib_paths):
0027     compiler = _base_compiler(settings)
0028     if not os_build:
0029         return []
0030     if compiler in GCC_LIKE:
0031         rpath_separator = ","
0032         return ['-Wl,-rpath%s"%s"' % (rpath_separator, x.replace("\\", "/"))
0033                 for x in lib_paths if x]
0034     return []
0035 
0036 
0037 def architecture_flag(settings):
0038     """
0039     returns flags specific to the target architecture and compiler
0040     """
0041     compiler = settings.get_safe("compiler")
0042     compiler_base = settings.get_safe("compiler.base")
0043     arch = settings.get_safe("arch")
0044     the_os = settings.get_safe("os")
0045     subsystem = settings.get_safe("os.subsystem")
0046     subsystem_ios_version = settings.get_safe("os.subsystem.ios_version")
0047     if not compiler or not arch:
0048         return ""
0049 
0050     if str(compiler) in ['gcc', 'apple-clang', 'clang', 'sun-cc']:
0051         if str(the_os) == 'Macos' and str(subsystem) == 'catalyst':
0052             apple_arch = to_apple_arch(arch)
0053             if apple_arch:
0054                 return '--target=%s-apple-ios%s-macabi' % (apple_arch, subsystem_ios_version)
0055         elif str(arch) in ['x86_64', 'sparcv9', 's390x']:
0056             return '-m64'
0057         elif str(arch) in ['x86', 'sparc']:
0058             return '-m32'
0059         elif str(arch) in ['s390']:
0060             return '-m31'
0061         elif str(the_os) == 'AIX':
0062             if str(arch) in ['ppc32']:
0063                 return '-maix32'
0064             elif str(arch) in ['ppc64']:
0065                 return '-maix64'
0066     elif str(compiler) == "intel":
0067         # https://software.intel.com/en-us/cpp-compiler-developer-guide-and-reference-m32-m64-qm32-qm64
0068         if str(arch) == "x86":
0069             return "/Qm32" if str(compiler_base) == "Visual Studio" else "-m32"
0070         elif str(arch) == "x86_64":
0071             return "/Qm64" if str(compiler_base) == "Visual Studio" else "-m64"
0072     elif str(compiler) == "mcst-lcc":
0073         return {"e2k-v2": "-march=elbrus-v2",
0074                 "e2k-v3": "-march=elbrus-v3",
0075                 "e2k-v4": "-march=elbrus-v4",
0076                 "e2k-v5": "-march=elbrus-v5",
0077                 "e2k-v6": "-march=elbrus-v6",
0078                 "e2k-v7": "-march=elbrus-v7"}.get(str(arch), "")
0079     return ""
0080 
0081 
0082 def libcxx_define(settings):
0083     compiler = _base_compiler(settings)
0084     libcxx = settings.get_safe("compiler.libcxx")
0085     if not compiler or not libcxx:
0086         return ""
0087 
0088     if str(compiler) in GCC_LIKE:
0089         if str(libcxx) == 'libstdc++':
0090             return '_GLIBCXX_USE_CXX11_ABI=0'
0091         elif str(libcxx) == 'libstdc++11':
0092             return '_GLIBCXX_USE_CXX11_ABI=1'
0093     return ""
0094 
0095 
0096 def libcxx_flag(settings):
0097     """
0098     returns flag specific to the target C++ standard library
0099     """
0100     compiler = _base_compiler(settings)
0101     libcxx = settings.get_safe("compiler.libcxx")
0102     if not compiler or not libcxx:
0103         return ""
0104     if str(compiler) in ['clang', 'apple-clang']:
0105         if str(libcxx) in ['libstdc++', 'libstdc++11']:
0106             return '-stdlib=libstdc++'
0107         elif str(libcxx) == 'libc++':
0108             return '-stdlib=libc++'
0109     elif str(compiler) == 'sun-cc':
0110         return ({"libCstd": "-library=Cstd",
0111                             "libstdcxx": "-library=stdcxx4",
0112                             "libstlport": "-library=stlport4",
0113                             "libstdc++": "-library=stdcpp"}.get(libcxx, ""))
0114     elif str(compiler) == "qcc":
0115         return "-Y _%s" % str(libcxx)
0116     return ""
0117 
0118 
0119 def pic_flag(settings):
0120     """
0121     returns PIC (position independent code) flags, such as -fPIC
0122     """
0123     compiler = _base_compiler(settings)
0124     if not compiler or compiler == 'Visual Studio':
0125         return ""
0126     return '-fPIC'
0127 
0128 
0129 def build_type_flags(settings):
0130     """
0131     returns flags specific to the build type (Debug, Release, etc.)
0132     (-s, -g, /Zi, etc.)
0133     """
0134     compiler = _base_compiler(settings)
0135     build_type = settings.get_safe("build_type")
0136     vs_toolset = settings.get_safe("compiler.toolset")
0137     if not compiler or not build_type:
0138         return ""
0139 
0140     # https://github.com/Kitware/CMake/blob/d7af8a34b67026feaee558433db3a835d6007e06/
0141     # Modules/Platform/Windows-MSVC.cmake
0142     if str(compiler) == 'Visual Studio':
0143         if vs_toolset and "clang" in str(vs_toolset):
0144             flags = {"Debug": ["-gline-tables-only", "-fno-inline", "-O0"],
0145                      "Release": ["-O2"],
0146                      "RelWithDebInfo": ["-gline-tables-only", "-O2", "-fno-inline"],
0147                      "MinSizeRel": []
0148                      }.get(build_type, ["-O2", "-Ob2"])
0149         else:
0150             flags = {"Debug": ["-Zi", "-Ob0", "-Od"],
0151                      "Release": ["-O2", "-Ob2"],
0152                      "RelWithDebInfo": ["-Zi", "-O2", "-Ob1"],
0153                      "MinSizeRel": ["-O1", "-Ob1"],
0154                      }.get(build_type, [])
0155         return flags
0156     else:
0157         # https://github.com/Kitware/CMake/blob/f3bbb37b253a1f4a26809d6f132b3996aa2e16fc/
0158         # Modules/Compiler/GNU.cmake
0159         # clang include the gnu (overriding some things, but not build type) and apple clang
0160         # overrides clang but it doesn't touch clang either
0161         if str(compiler) in ["clang", "gcc", "apple-clang", "qcc", "mcst-lcc"]:
0162             # FIXME: It is not clear that the "-s" is something related with the build type
0163             # cmake is not adjusting it
0164             # -s: Remove all symbol table and relocation information from the executable.
0165             flags = {"Debug": ["-g"],
0166                      "Release": ["-O3", "-s"] if str(compiler) == "gcc" else ["-O3"],
0167                      "RelWithDebInfo": ["-O2", "-g"],
0168                      "MinSizeRel": ["-Os"],
0169                      }.get(build_type, [])
0170             return flags
0171         elif str(compiler) == "sun-cc":
0172             # https://github.com/Kitware/CMake/blob/f3bbb37b253a1f4a26809d6f132b3996aa2e16fc/
0173             # Modules/Compiler/SunPro-CXX.cmake
0174             flags = {"Debug": ["-g"],
0175                      "Release": ["-xO3"],
0176                      "RelWithDebInfo": ["-xO2", "-g"],
0177                      "MinSizeRel": ["-xO2", "-xspace"],
0178                      }.get(build_type, [])
0179             return flags
0180     return ""
0181 
0182 
0183 def build_type_define(build_type=None):
0184     """
0185     returns definitions specific to the build type (Debug, Release, etc.)
0186     like DEBUG, _DEBUG, NDEBUG
0187     """
0188     return 'NDEBUG' if build_type in ['Release', 'RelWithDebInfo', 'MinSizeRel'] else ""
0189 
0190 
0191 def adjust_path(path, settings, win_bash=False, subsystem=None):
0192     """
0193     adjusts path to be safely passed to the compiler command line
0194     for Windows bash, ensures path is in format according to the subsystem
0195     for path with spaces, places double quotes around it
0196     converts slashes to backslashes, or vice versa
0197     """
0198     compiler = _base_compiler(settings)
0199     if str(compiler) == 'Visual Studio':
0200         path = path.replace('/', '\\')
0201     else:
0202         path = path.replace('\\', '/')
0203     if win_bash:
0204         path = unix_path(path, subsystem)
0205     return '"%s"' % path if ' ' in path else path
0206 
0207 
0208 def sysroot_flag(sysroot, settings, win_bash=False, subsystem=None):
0209     compiler = _base_compiler(settings)
0210     if str(compiler) != 'Visual Studio' and sysroot:
0211         sysroot = adjust_path(sysroot, settings, win_bash=win_bash, subsystem=subsystem)
0212         return '--sysroot=%s' % sysroot
0213     return ""
0214 
0215 
0216 def visual_runtime(runtime):
0217     if runtime:
0218         return "-%s" % runtime
0219     return ""
0220 
0221 
0222 def format_defines(defines):
0223     return ["-D%s" % define for define in defines if define]
0224 
0225 
0226 include_path_option = "-I"
0227 visual_linker_option_separator = "-link"  # Further options will apply to the linker
0228 
0229 
0230 def format_include_paths(include_paths, settings, win_bash=False, subsystem=None):
0231     return ["%s%s" % (include_path_option, adjust_path(include_path, settings, win_bash=win_bash,
0232                                                        subsystem=subsystem))
0233             for include_path in include_paths if include_path]
0234 
0235 
0236 def format_library_paths(library_paths, settings, win_bash=False, subsystem=None):
0237     compiler = _base_compiler(settings)
0238     pattern = "-LIBPATH:%s" if str(compiler) == 'Visual Studio' else "-L%s"
0239     return [pattern % adjust_path(library_path, settings, win_bash=win_bash,
0240                                   subsystem=subsystem)
0241             for library_path in library_paths if library_path]
0242 
0243 
0244 def format_libraries(libraries, settings):
0245     result = []
0246     compiler = settings.get_safe("compiler")
0247     compiler_base = settings.get_safe("compiler.base")
0248     for library in libraries:
0249         if str(compiler) == 'Visual Studio' or str(compiler_base) == 'Visual Studio':
0250             if not library.endswith(".lib"):
0251                 library += ".lib"
0252             result.append(library)
0253         else:
0254             result.append("-l%s" % library)
0255     return result
0256 
0257 
0258 def parallel_compiler_cl_flag(output=None):
0259     return "/MP%s" % cpu_count(output=output)
0260 
0261 
0262 def format_frameworks(frameworks, settings):
0263     """
0264     returns an appropriate compiler flags to link with Apple Frameworks
0265     or an empty array, if Apple Frameworks aren't supported by the given compiler
0266     """
0267     compiler = settings.get_safe("compiler")
0268     compiler_base = settings.get_safe("compiler.base")
0269     if (str(compiler) not in GCC_LIKE) and (str(compiler_base) not in GCC_LIKE):
0270         return []
0271     return ["-framework %s" % framework for framework in frameworks]
0272 
0273 
0274 def format_framework_paths(framework_paths, settings):
0275     """
0276     returns an appropriate compiler flags to specify Apple Frameworks search paths
0277     or an empty array, if Apple Frameworks aren't supported by the given compiler
0278     """
0279     compiler = settings.get_safe("compiler")
0280     compiler_base = settings.get_safe("compiler.base")
0281     if (str(compiler) not in GCC_LIKE) and (str(compiler_base) not in GCC_LIKE):
0282         return []
0283     return ["-F %s" % adjust_path(framework_path, settings) for framework_path in framework_paths]