Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2231 conan compiler detection #2487

Merged
merged 14 commits into from
Feb 26, 2018

Conversation

pvicente
Copy link
Contributor

@pvicente pvicente commented Feb 16, 2018

  • Refer to the issue that supports this Pull Request.
  • I've read the Contributing guide.
  • I've followed the PEP8 style guides for Python code.

closes #2231

Previously failing compiler detection in mac os x when gcc was forced:

09:28 $ CC=gcc CXX=g++ conan install boost/1.66.0@conan/stable
Auto detecting your dev setup to initialize the default profile (/Users/pvicente/.conan/profiles/default)
CC and CXX: gcc, g++
Found gcc 4.2
Default settings
	os=Macos
	os_build=Macos
	arch=x86_64
	arch_build=x86_64
	compiler=gcc
	compiler.version=4.2
	compiler.libcxx=libstdc++
	build_type=Release
*** You can change them in /Users/pvicente/.conan/profiles/default ***
*** Or override with -s compiler='other' -s ...s***


ERROR: Invalid setting '4.2' is not a valid 'settings.compiler.version' value.
Possible values are ['4.1', '4.4', '4.5', '4.6', '4.7', '4.8', '4.9', '5', '5.1', '5.2', '5.3', '5.4', '5.5', '6', '6.1', '6.2', '6.3', '6.4', '7', '7.1', '7.2', '7.3']
Read "http://docs.conan.io/en/latest/faq/troubleshooting.html#error-invalid-setting"

Now:

09:26 $ CC=gcc CXX=g++ conan install boost/1.66.0@conan/stable
Auto detecting your dev setup to initialize the default profile (/Users/pvicente/.conan/profiles/default)
CC and CXX: gcc, g++
Found apple-clang 9.0
Default settings
	os=Macos
	os_build=Macos
	arch=x86_64
	arch_build=x86_64
	compiler=apple-clang
	compiler.version=9.0
	compiler.libcxx=libc++
	build_type=Release
*** You can change them in /Users/pvicente/.conan/profiles/default ***
*** Or override with -s compiler='other' -s ...s***
...

@ghost ghost assigned pvicente Feb 16, 2018
@ghost ghost added the stage: review label Feb 16, 2018
@pvicente pvicente assigned lasote and unassigned lasote Feb 17, 2018
@pvicente pvicente requested a review from lasote February 17, 2018 09:35
Copy link
Contributor

@lasote lasote left a comment

Choose a reason for hiding this comment

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

Good job. Take a look to my comment.

@@ -146,9 +159,9 @@ def _get_default_compiler(output):
if cc or cxx: # Env defined, use them
output.info("CC and CXX: %s, %s " % (cc or "None", cxx or "None"))
command = cc or cxx
if "gcc" in command:
if _is_real_compiler("gcc", command):
Copy link
Contributor

@lasote lasote Feb 17, 2018

Choose a reason for hiding this comment

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

I think it is clearer to get here the output of the "command --help", then "if "gcc" in output:" and "if "clang" in output". The function is real compiler feels a little confusing. Maybe also check the output in lowercase in case GCC or Clang in output.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry for my comments formatting. I'm with the mobile.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, agree, I'd think it would be more understandable. I think that @lasote meant command --version, not --help.

Copy link
Contributor Author

@pvicente pvicente Feb 19, 2018

Choose a reason for hiding this comment

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

@lasote @memsharded do you mean something like this?

    if "gcc" in command:
        _, out = _execute("%s --version" % command)
        if "gcc" in out.lower():
            return _gcc_compiler(output, command)
    if "clang" in command.lower():
       _, out =  _execute("%s --version" % command.lower())
       if "clang" in out.lower():
           return _clang_compiler(output, command)   

or:

        if "gcc" in command or "clang" in command.lower():
            _, out = _execute("%s --version" % command)
            out = out.lower()
            if "gcc" in out:
                return _gcc_compiler(output, command)
            if "clang" in out:
                return _clang_compiler(output, command)

I would go for 2nd option only one call to _execute

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've fixed it with 2nd option

Copy link
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.

@@ -146,9 +159,9 @@ def _get_default_compiler(output):
if cc or cxx: # Env defined, use them
output.info("CC and CXX: %s, %s " % (cc or "None", cxx or "None"))
command = cc or cxx
if "gcc" in command:
if _is_real_compiler("gcc", command):
Copy link
Member

Choose a reason for hiding this comment

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

Yes, agree, I'd think it would be more understandable. I think that @lasote meant command --version, not --help.

def detect_default_in_mac_os_using_gcc_as_default_test(self):
# See: https://github.com/conan-io/conan/issues/2231
output = TestBufferConanOutput()
with tools.environment_append({"CC": "gcc"}):
Copy link
Member

@memsharded memsharded Feb 18, 2018

Choose a reason for hiding this comment

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

This test is nice, but is not testing the reported issue. Which is gcc being actually a symlink to clang. It might be difficult to fully automate, so I am fine if tested manually.

Actually it might be testing it, if gcc is not installed in the testing environment as real gcc but as the default clang compiler. But it should check "clang" in the test, shouldn't it?

Copy link
Contributor Author

@pvicente pvicente Feb 19, 2018

Choose a reason for hiding this comment

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

@memsharded Indeed, this test is only executed in MacOS x (Darwin) where gcc command is clang which was the bug report for this issue. In my Mac OS X it's returning

17:06 $ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.0.0 (clang-900.0.38)
Target: x86_64-apple-darwin17.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

I've updated it to make more evident that it should detect apple-clang.

Let me know if it makes sense to you. It looks like in CI we have the same environment gcc reports it's apple-clang.

Copy link
Member

Choose a reason for hiding this comment

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

It is not to make it more evident. It could happen that the CI machine could have gcc really installed in it, and the test would pass without checking for clang output, so it wouldn't test at all the reported bug fix. It is necessary to explicitly check for "apple-clang" in the output

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@memsharded I don't understand what's the problem? @lasote do you know what are we talking about? This test is only executed in Mac OS X and the CI machine for Mac OS X has fake gcc as apple-clang, but if you don't want to rely on this assumption maybe it's better to remove this end2end test.

Copy link
Contributor

Choose a reason for hiding this comment

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

Just check the output to confirm that the assumption is true. Because if the assumption change, it is better to know it with a fail test than being happy with a green build and a useless test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I got it, thanks for the explanation. I wasn't getting it, sorry guys!!!

@SSE4
Copy link
Contributor

SSE4 commented Feb 19, 2018

may be it's better and more reliable to avoid parsing --version output at all, and use instead macro definitions reported by compiler as shown at #1127?

@@ -49,7 +49,7 @@ def _clang_compiler(output, compiler_exe="clang"):
compiler = "apple-clang"
elif "clang version" in out:
compiler = "clang"
installed_version = re.search("([0-9]\.[0-9])", out).group()
installed_version = re.search("version ([0-9]\.[0-9])", out).group(1)
Copy link
Contributor

Choose a reason for hiding this comment

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

This change in the regular expression worries me a little. If some specific clang is not printing the "version" word we could be breaking. Why did you need it? If there is a good reason I'm ok with it, if don't, better keep it like it was.

Copy link
Contributor

Choose a reason for hiding this comment

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

If it is only for apple-clang I would prefer to limit it to the Apple if to mitigate possible issues

Copy link
Member

Choose a reason for hiding this comment

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

But apple-clang was already working, when the compiler is "clang --version". So parsing didn't seem an issue

Copy link
Contributor

Choose a reason for hiding this comment

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

That's a good question, but looking at the output it could be:

Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin17.4.0

Please @pvicente confirm then it is failing and why didn't fail so far.

Copy link
Contributor Author

@pvicente pvicente Feb 20, 2018

Choose a reason for hiding this comment

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

The problem is when using fake gcc in mac os x.

This is the output for gcc:

10:31 $ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.0.0 (clang-900.0.38)
Target: x86_64-apple-darwin17.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

The previous regular expression catches 4.2 as compiler version, see regex problem

When I added version in regex I checked out that clang in linux, clang in apple are returning version in the output.

MacOSX:

23:21 $ clang --version
Apple LLVM version 9.0.0 (clang-900.0.38)
Target: x86_64-apple-darwin17.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Linux:

conan@8bb2abebb6c8:/Users/pvicente/git/conan/conan$ clang --version
clang version 5.0.0-3 (tags/RELEASE_500/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

Hope it makes sense to you.

@lasote
Copy link
Contributor

lasote commented Feb 20, 2018

@SSE4 could be more accurate, but I think we are good by now with the --version until we detect that it is not enough. Anyway thanks for your suggestion!

@memsharded memsharded added this to the 1.1 milestone Feb 20, 2018
@pvicente pvicente force-pushed the 2231_conan_compiler_detection branch from f5fd32a to 22b941a Compare February 20, 2018 13:37
@pvicente
Copy link
Contributor Author

@lasote @memsharded fixed test case checking output

Copy link
Contributor

@lasote lasote left a comment

Choose a reason for hiding this comment

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

Take a look to: #2231
I think in case of see gcc in CC in osx, if the returned trace is about clang, we should discard this detection (warn something maybe) and try with the regular one (not looking defaults CC).
You could think that the result is the same, but I think it is cleaner and safer.


def detect_default_in_mac_os_using_gcc_as_default_test(self):
"""
In some Mac OS X gcc is in reality clang.
Copy link
Contributor

Choose a reason for hiding this comment

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

We investigate it and we changed our mind, the clang "gcc" is not a pure gcc. Read the last comment of @memsharded here: #2231

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lasote @memsharded I've updated the code to skip gcc detection this case arises as commented in #2231

@pvicente pvicente force-pushed the 2231_conan_compiler_detection branch from 16b1e85 to a8c1e6d Compare February 21, 2018 13:59
@pvicente
Copy link
Contributor Author

@lasote @memsharded it's ready for review with suggested changes #2231

But I think the logic should probably be: Skip the gcc (as clang frontend) in OSX in the default conan detection of compiler. So in OSX, conan will be able to detect normal "apple-clang" clang compiler, and maybe "gcc", but as complete gcc, not that clang frontend.

Copy link
Contributor

@lasote lasote 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 little simplification in the test and the rest I think it is ok.

if platform.system() != "Darwin":
return

def _execute(command):
Copy link
Contributor

Choose a reason for hiding this comment

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

You can simplify all this with output_str = subprocess.check_output(command) and try, except in case of subprocess failure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, totally right!!! fixing it!!!

if proc_return != 0 or "clang" not in output:
# Not test scenario (gcc should display clang in output
if "clang" not in output:
# Not test scenario gcc should display clang in output
return
Copy link
Contributor

@lasote lasote Feb 21, 2018

Choose a reason for hiding this comment

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

Mhh, may we raise here to realize that maybe the default OSX policy for "gcc" has changed?

Copy link
Contributor

Choose a reason for hiding this comment

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

I know that it is not the scope of the test, but useful to know if something changes

Copy link
Contributor Author

@pvicente pvicente Feb 21, 2018

Choose a reason for hiding this comment

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

Yes It's a good idea, @memsharded WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

like: raise Exception("Apple gcc doesn't point to clang with gcc frontend anymore! please check")

if "clang" not in out:
return _gcc_compiler(output, command)
output.warn("%s detected as a frontend using apple-clang, skipping it to use native apple-clang" % command)
command = "clang" # Force use of clang when gcc is detected as a fronted of apple-clang
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure we want to fallback to clang. Because if the env-var CC and CXX are set to gcc, then, typically CMake will use them when running, and the user might not notice, because it detected "clang" when CC=gcc. What do you think @lasote?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm ok with this. If the user is messing with CC/CXX is his problem. And the default profile is just a default.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, makes sense

_, out = _execute("%s --version" % command)
out = out.lower()
if "clang" not in out:
return _gcc_compiler(output, command)
Copy link
Member

Choose a reason for hiding this comment

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

The overall logic of this code seems a bit convolute IMHO, with 2 calls to _gcc_compiler() plus one manual _execute("gcc.... Maybe it would make more sense to put this logic inside _gcc_compiler(), so the compiler is called exactly once, and the rest is processing the output?

Copy link
Contributor Author

@pvicente pvicente Feb 22, 2018

Choose a reason for hiding this comment

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

@memsharded @lasote in that case what about the fallback to clang when gcc is a frontend of apple-clang.

Shall we call _clang_compiler(output, "clang") inside _gcc_compiler(output, command) as the logic will be inside _gcc_compiler?

I've seen that we are using _gcc_compiler also in the case that we are not forcing the usage of gcc with CC variable so I'm not sure about putting the logic inside _gcc_compiler

@pvicente pvicente force-pushed the 2231_conan_compiler_detection branch from 0a467d1 to 5b7b94d Compare February 24, 2018 14:11
"%s detected as a frontend using apple-clang, skipping it to use native apple-clang" % command
)
# Fallback to use clang instead
command = "clang"
Copy link
Member

Choose a reason for hiding this comment

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

I still think this is a weird outcome. So you defined that your CC=gcc, still conan is detecting and defaulting your profile to clang compiler? I think it is safer to just leave the compiler None for this case, so it will fail fast, instead of lots of potential mismatches between the default profile and the declared default compiler CC.

Copy link
Contributor Author

@pvicente pvicente Feb 26, 2018

Choose a reason for hiding this comment

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

@memsharded this is your comment 5 days ago (Ok, makes sense) so I've just left it to use as default clang in case the problem is detected (gcc as a fronted of apple-clang)

memsharded 5 days ago Owner
I am not sure we want to fallback to clang. Because if the env-var CC and CXX are set to gcc, >then, typically CMake will use them when running, and the user might not notice, because it >detected "clang" when CC=gcc. What do you think @lasote?

@lasote
lasote 4 days ago Owner
I'm ok with this. If the user is messing with CC/CXX is his problem. And the default profile is >just a default.

@memsharded
memsharded 4 days ago Owner
Ok, makes sense

@lasote Anything that I'm missing here?

Copy link
Contributor

Choose a reason for hiding this comment

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

I talked with @memsharded and I changed my mind, it is better to no set a compiler and make more visible that we are not managing this situation with Conan. Not a big deal.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lasote @memsharded Ok now conan should display:

16:13 $ CC=gcc conan install libiconv/1.15@bincrafters/stable
Auto detecting your dev setup to initialize the default profile (/Users/pvicente/.conan/profiles/default)
CC and CXX: gcc, None
ERROR: gcc detected as a frontend using apple-clang. Compiler not supported
ERROR: Unable to find a working compiler
Default settings
	os=Macos
	os_build=Macos
	arch=x86_64
	arch_build=x86_64
	build_type=Release
*** You can change them in /Users/pvicente/.conan/profiles/default ***
*** Or override with -s compiler='other' -s ...s***
libiconv/1.15@bincrafters/stable: Not found in local cache, looking in remotes...
libiconv/1.15@bincrafters/stable: Trying with 'conan-center'...
libiconv/1.15@bincrafters/stable: Trying with 'conan-transit'...
....

@memsharded memsharded merged commit 7c15a59 into conan-io:develop Feb 26, 2018
@ghost ghost removed the stage: review label Feb 26, 2018
@pvicente pvicente deleted the 2231_conan_compiler_detection branch February 26, 2018 17:08
grisumbras pushed a commit to grisumbras/conan that referenced this pull request Dec 27, 2018
* Fixing default compiler detection when environment variables are defined.

Checked if compiler name is matches with compiler exe output

* Added end2end tests for compiler detection

* Addressed comment from PR, removing _is_real_compiler method

* Updated test for mac os x reported bug

* Checking output of "gcc --version" and execute in right test scenario.

* Updated code to skip gcc when it's using apple-clang as a frontend in Mac OS X

* Updated test to run only in Mac OS X

* Simplified test using subprocess.check_output

* Raising exception if gcc doesn't point to clang in Mac OS X

* Fixed problem python 2/3

* As sugested in PR putting logic to detect GCC as clang frontend inside _gcc_compiler method

* Updated to simplify logic

* Moving check inside try/except

* As commented in PR now compiler GCC if it's a fronted of apple-clang is not supported
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.

Conan on Mac can't recognize compiler correctly
4 participants