conan-io / conan

Conan - The open-source C and C++ package manager
https://conan.io
MIT License
8.13k stars 968 forks source link

CFLAGS are quoted on the command line #2378

Closed theodelrieu closed 6 years ago

theodelrieu commented 6 years ago

Hi,

I've been having a compiler warning for a while now, it only occurs when cross-compiling:

clang: warning: argument unused during compilation: '-arch x86_64' [-Wunused-command-line-argument]

The command line looks like that:

-arch x86_64 -isysroot/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator11.2.sdk -miphonesimulator-version-min=10.3 -O3 -DNDEBUG "-arch x86_64"

I use a darwin-toolchain package as a build requirement, so I assume the first -arch is the one set in self.cpp_info.cflags, the second is the one injected by self.env_info.CFLAGS.

Is this intended? This is not a blocking issue at all, but not having the warning would be great :) Thanks!

I have Conan version 1.0.3.

To help us debug your issue please explain:

memsharded commented 6 years ago

Thanks for your report.

I would need a bit more information:

I recall some similar issue in the past, thought that it was solved. It would be great to have something small to reproduce and debug this issue. Thanks!

theodelrieu commented 6 years ago

Sorry, I'll explain more accurately:

I've tried with the Meson helper, and did not have this issue.

memsharded commented 6 years ago

I cannot find the issue yet, but I haven't tested in nix systems yet. I'd like to know about the reason to define the "-arch x86_64" both in self.cpp_info.cflags and in self.env_info.CFLAGS in the build require.

memsharded commented 6 years ago

Ì am emulating the tool with:

from conans import ConanFile
class Pkg(ConanFile):
    def package_info(self):
        self.cpp_info.cppflags = ["-DMYDEFINE=1"]
        self.env_info.CXXFLAGS = "-DMYDEFINE2=2"

And the compile command I get is:

/usr/bin/c++   -D_GLIBCXX_USE_CXX11_ABI=0  -DMYDEFINE2=2  -DMYDEFINE=1 -m64 -O3 -DNDEBUG   

Same for C:

from conans import ConanFile
class Pkg(ConanFile):
    def package_info(self):
        self.cpp_info.cflags = ["-DMYDEFINE=1"]
        self.env_info.CFLAGS = "-DMYDEFINE2=2"
/usr/bin/cc    -DMYDEFINE2=2  -DMYDEFINE=1 -m64 -O3 -DNDEBUG   
theodelrieu commented 6 years ago

The main reason is autotools-based libraries, the configure script tries to compile programs, and so it relies on the CFLAGS variable.

I will post the darwin-toolchain recipe I use as a build requirement, I hope it will help:

from conans import ConanFile, tools

import os
import platform
import subprocess

class DarwinToolchainConan(ConanFile):
    name = "darwin-toolchain"
    version = "10.13"
    license = "Apple"
    settings = "os", "arch"
    description = "Recipe for packaging a Darwin toolchain to (cross) compile macOS/iOS apps from macOS"

    def configure(self):
        if platform.system() != "Darwin":
            raise Exception("Build machine must be Macos")

    def package_info(self):
        # For more info: https://coderwall.com/p/heonhw/compiling-for-ios-outside-of-xcode-with-xcrun
        def call(cmd):
            return subprocess.check_output(cmd, shell=False).strip().decode("utf-8")

        def find_sysroot(sdk_name):
            return call(["xcrun", "--show-sdk-path", "-sdk", sdk_name])

        def to_apple_arch(arch):
            """converts conan-style architecture into Apple-style arch"""
            return {'x86': 'i386',
                    'x86_64': 'x86_64',
                    'armv7': 'armv7',
                    'armv8': 'arm64',
                    'armv7s': 'armv7s',
                    'armv7k': 'armv7k'}.get(str(arch))

        def find_program(prog_name):
            return call(["xcrun", "--find", prog_name])

        def apple_sdk_name(settings):
            """returns proper SDK name suitable for OS and architecture
            we're building for (considering simulators)"""
            arch = settings.get_safe('arch')
            _os = settings.get_safe('os')
            if str(arch).startswith('x86'):
                return {'Macos': 'macosx',
                        'iOS': 'iphonesimulator',
                        'watchOS': 'watchsimulator',
                        'tvOS': 'appletvsimulator'}.get(str(_os))
            elif str(arch).startswith('arm'):
                return {'iOS': 'iphoneos',
                        'watchOS': 'watchos',
                        'tvOS': 'appletvos'}.get(str(_os))
            else:
                return None

        darwin_arch = to_apple_arch(self.settings.arch)
        sdk = apple_sdk_name(self.settings)
        sysroot = find_sysroot(sdk)

        self.cpp_info.sysroot = sysroot
        arch_flag = "-arch %s" % darwin_arch
        common_flags = [arch_flag, "-isysroot%s" % sysroot]
        if self.settings.os == "iOS":
            common_flags.append("-m%s-version-min=%s" % (sdk, self.settings.os.version))
        self.cpp_info.cflags.extend(common_flags)
        self.cpp_info.sharedlinkflags.extend(common_flags)
        self.cpp_info.exelinkflags.extend(common_flags)

        clang = find_program("clang")
        clangpp = find_program("clang++")
        common_flags_str = " ".join(common_flags)
        self.env_info.CC = clang
        self.env_info.CXX = clangpp
        self.env_info.CFLAGS = common_flags_str
        self.env_info.CXXFLAGS = common_flags_str
        self.env_info.LDFLAGS = common_flags_str
memsharded commented 6 years ago

This was due a known issue in CMake. It has been reported, just in case, but was closed without a clear solution: https://gitlab.kitware.com/cmake/cmake/issues/17700

The issue is that INTERFACE_COMPILE_OPTIONS can contain a list of arguments like:

-isysroot=somepath;-arch arm64;-someflag;

And it will incorrectly translate it to:

<compiler> -isysroot=somepath "-arch arm64" -someflag

This only happens for INTERFACE_COMPILE_OPTIONS , INTERFACE_LINK_LIBRARIES is good with it.

Fortunately, conan can define the flags separately, so something like this should work:

compile_flags = ["-arch", darwin_arch, "-isysroot%s" % sysroot]
link_flags = ["-arch %s" % darwin_arch, "-isysroot%s" % sysroot]
...
self.cpp_info.cflags.extend(compile_flags )
self.cpp_info.sharedlinkflags.extend(link_flags )
...

Thanks for all your feedback!