LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 20894 - clang-cl doesn't properly handle the -o flag
Summary: clang-cl doesn't properly handle the -o flag
Status: RESOLVED FIXED
Alias: None
Product: clang
Classification: Unclassified
Component: Driver (show other bugs)
Version: trunk
Hardware: PC All
: P normal
Assignee: Ehsan Akhgari [:ehsan]
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-09-10 07:32 PDT by Ehsan Akhgari [:ehsan]
Modified: 2014-09-11 13:16 PDT (History)
8 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ehsan Akhgari [:ehsan] 2014-09-10 07:32:50 PDT
I know that clang-cl ignores -o completely, but now I'm running into a weird situation that I can't fig myself out of.  Here, we're passing the ASAN libraries on the command line to clang-cl without -c.  It gets the output filename wrong by thinking that it should be derived from the input library, and it passes the wrong -out: flag to the linker which completely confuses it:

$ clang-cl -o conftest -Z7 -fallback -fsanitize=address  clang_rt.asan_dynamic-i386.lib clang_rt.asan_uar_thunk-i386.lib conftest.c
clang-cl.exe: warning: argument unused during compilation: '-o conftest'
LINK : fatal error LNK1149: output filename matches input filename 'c:\moz\fallback\clang_rt.asan_dynamic-i386.lib'
clang-cl.exe: error: linker command failed with exit code 1149 (use -v to see invocation)

$ clang-cl -o conftest -Z7 -fallback -fsanitize=address  clang_rt.asan_dynamic-i386.lib clang_rt.asan_uar_thunk-i386.lib conftest.c -###
clang version 3.6.0
Target: i686-pc-windows-msvc
Thread model: posix
clang-cl.exe: warning: argument unused during compilation: '-o conftest'
 "c:\\moz\\llvm-objdir\\bin\\clang-cl.exe" "-cc1" "-triple" "i686-pc-windows-msvc" "-emit-obj" "-mrelax-all" "-disable-free" "-main-file-name" "conftest.c" "-mrelocation-model" "static" "-mdisable-fp-elim" "-relaxed-aliasing" "-fmath-errno" "-masm-verbose" "-mconstructor-aliases" "-munwind-tables" "-target-cpu" "pentium4" "-D_MT" "--dependent-lib=libcmt" "--dependent-lib=oldnames" "-fdiagnostics-format" "msvc-fallback" "-gline-tables-only" "-dwarf-column-info" "-resource-dir" "c:\\moz\\llvm-objdir\\bin\\..\\lib\\clang\\3.6.0" "-internal-isystem" "c:\\moz\\llvm-objdir\\bin\\..\\lib\\clang\\3.6.0\\include" "-internal-isystem" "C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\INCLUDE" "-internal-isystem" "C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\ATLMFC\\INCLUDE" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\8.0\\include\\shared" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\8.0\\include\\um" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\8.0\\include\\winrt" "-fdebug-compilation-dir" "c:\\moz\\fallback" "-ferror-limit" "19" "-fmessage-length" "152" "-fsanitize=address" "-fsanitize-blacklist=c:\\moz\\llvm-objdir\\bin\\..\\lib\\clang\\3.6.0\\asan_blacklist.txt" "-mstackrealign" "-fms-extensions" "-fms-compatibility" "-fms-compatibility-version=17.00" "-fdelayed-template-parsing" "-fobjc-runtime=gcc" "-fdiagnostics-show-option" "-fcolor-diagnostics" "-o" "C:/Users/EHSANA~1/AppData/Local/Temp\\conftest-0ff154.obj" "-x" "c" "conftest.c" || "c:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\BIN\\cl.exe" "/nologo" "/c" "/W0" "/Z7" "/Tc" "conftest.c" "/FoC:/Users/EHSANA~1/AppData/Local/Temp\\conftest-0ff154.obj"
 "c:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\BIN\\link.exe" "-out:clang_rt.asan_dynamic-i386.exe" "-nologo" "-debug" "-debug" "-incremental:no" "c:\\moz\\llvm-objdir\\bin\\..\\lib\\clang\\3.6.0\\lib\\windows\\clang_rt.asan-i386.lib" "c:\\moz\\llvm-objdir\\bin\\..\\lib\\clang\\3.6.0\\lib\\windows\\clang_rt.asan_cxx-i386.lib" "clang_rt.asan_dynamic-i386.lib" "clang_rt.asan_uar_thunk-i386.lib" "C:/Users/EHSANA~1/AppData/Local/Temp\\conftest-0ff154.obj"


Should we add proper support for -o?  Or somehow differentiate between .lib and .c files, and don't construct -out: arguments to the linker from the former?
Comment 1 Reid Kleckner 2014-09-10 10:08:09 PDT
I wanted to add support for -o, but at the time Alp Toker objected to it strongly. He wanted clang-cl to focus on MSVC compatibility and not try to be more than that. He felt that if users wanted Unix-style options, they should use the gcc-compatible driver. I haven't heard from him in months, so we could probably go ahead and land this change if we decide we don't agree. :)

We should also fix clang-cl to ignore linker inputs for the purposes of finding an output filename, especially because I don't think you need -o to have problems, `clang-cl foo.lib bar.c` will probably try to output to foo.lib. =/
Comment 2 Ehsan Akhgari [:ehsan] 2014-09-10 10:25:55 PDT
(In reply to comment #1)
> I wanted to add support for -o, but at the time Alp Toker objected to it
> strongly. He wanted clang-cl to focus on MSVC compatibility and not try to
> be more than that. He felt that if users wanted Unix-style options, they
> should use the gcc-compatible driver. I haven't heard from him in months, so
> we could probably go ahead and land this change if we decide we don't agree.
> :)

Hmm, cl.exe _does_ support -o, so this in fact a cl compat issue.  (Note that -o is deprecated and undocumented, but it's definitely supported.

> We should also fix clang-cl to ignore linker inputs for the purposes of
> finding an output filename, especially because I don't think you need -o to
> have problems, `clang-cl foo.lib bar.c` will probably try to output to
> foo.lib. =/

Yeah.  The reason why that is that here we claim that cl.exe always uses the "base name" to construct the output <https://github.com/llvm-mirror/clang/blame/master/lib/Driver/Driver.cpp#L1714> (which is false!).  The base name comes from the first input <https://github.com/llvm-mirror/clang/blame/master/lib/Driver/Driver.cpp#L1572>.  That is clearly broken, it should come from the first _compiler input_.  But as far as I can tell, we treat all inputs equal here, and I don't know what will changing this break.

So, shall I go and write a patch for handling -o?  I'm planning to make it kick in when -Fo or -Fe are not specified, depending on the type of output.
Comment 3 Timur Iskhodzhanov 2014-09-10 10:58:30 PDT
> Hmm, cl.exe _does_ support -o

What makes you believe so?
I think they've actually dropped support for -o a few versions ago...
Comment 4 Ehsan Akhgari [:ehsan] 2014-09-10 11:04:18 PDT
(In reply to comment #3)
> > Hmm, cl.exe _does_ support -o
> 
> What makes you believe so?

Testing cl.exe's behavior.  :-)

$ cat test.cpp
int main() { return 1; }

$ cl -o myexe test.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

cl : Command line warning D9035 : option 'o' has been deprecated and will be removed in a future release
test.cpp
Microsoft (R) Incremental Linker Version 11.00.61030.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
/out:myexe.exe
test.obj

$ ./myexe.exe

$ echo $?
1

> I think they've actually dropped support for -o a few versions ago...

I think there is some confusion here because this flag is undocumented.
Comment 5 Reid Kleckner 2014-09-10 11:13:31 PDT
(In reply to comment #2)
> (In reply to comment #1)
> > I wanted to add support for -o, but at the time Alp Toker objected to it
> > strongly. He wanted clang-cl to focus on MSVC compatibility and not try to
> > be more than that. He felt that if users wanted Unix-style options, they
> > should use the gcc-compatible driver. I haven't heard from him in months, so
> > we could probably go ahead and land this change if we decide we don't agree.
> > :)
> 
> Hmm, cl.exe _does_ support -o, so this in fact a cl compat issue.  (Note
> that -o is deprecated and undocumented, but it's definitely supported.

Last time I checked, -o is recognized, but it has no effect on where object files get written. Object files always follow -Fo or basename of the first input.

I haven't checked if -o affects the location of executables. If -o affects executables, then we should just add it and support it for object files.
Comment 6 Ehsan Akhgari [:ehsan] 2014-09-10 11:22:46 PDT
(In reply to comment #5)
> (In reply to comment #2)
> > (In reply to comment #1)
> > > I wanted to add support for -o, but at the time Alp Toker objected to it
> > > strongly. He wanted clang-cl to focus on MSVC compatibility and not try to
> > > be more than that. He felt that if users wanted Unix-style options, they
> > > should use the gcc-compatible driver. I haven't heard from him in months, so
> > > we could probably go ahead and land this change if we decide we don't agree.
> > > :)
> > 
> > Hmm, cl.exe _does_ support -o, so this in fact a cl compat issue.  (Note
> > that -o is deprecated and undocumented, but it's definitely supported.
> 
> Last time I checked, -o is recognized, but it has no effect on where object
> files get written. Object files always follow -Fo or basename of the first
> input.

You're right!

> I haven't checked if -o affects the location of executables. If -o affects
> executables, then we should just add it and support it for object files.

It seems like it only affects the location of executables.  See comment 4.  I'll submit a patch for this soon.
Comment 7 Timur Iskhodzhanov 2014-09-10 11:46:31 PDT
I think we should support -o for both object files and executables or for neither of them.  I don't see any reason to follow the CL behaviour given that -o is explicitly deprecated there.
Comment 8 Ehsan Akhgari [:ehsan] 2014-09-10 12:01:33 PDT
(In reply to comment #7)
> I think we should support -o for both object files and executables or for
> neither of them.  I don't see any reason to follow the CL behaviour given
> that -o is explicitly deprecated there.

I could be convinced either way, since the thing that I really need is specifying executable locations.  Reid, what do you think?
Comment 9 Reid Kleckner 2014-09-10 12:51:43 PDT
(In reply to comment #7)
> I think we should support -o for both object files and executables or for
> neither of them.  I don't see any reason to follow the CL behaviour given
> that -o is explicitly deprecated there.

I agree. I think we should take the option of supporting it for all outputs: preprocessed source, object files, and executables.

Unfortunately I seem to recall that we asserted that there could be no conflicting -o option when implementing -Fo. I think the last flag should win if both are supplied.
Comment 10 Ehsan Akhgari [:ehsan] 2014-09-10 13:23:50 PDT
(In reply to comment #9)
> (In reply to comment #7)
> > I think we should support -o for both object files and executables or for
> > neither of them.  I don't see any reason to follow the CL behaviour given
> > that -o is explicitly deprecated there.
> 
> I agree. I think we should take the option of supporting it for all outputs:
> preprocessed source, object files, and executables.

OK, will do.

> Unfortunately I seem to recall that we asserted that there could be no
> conflicting -o option when implementing -Fo. I think the last flag should
> win if both are supplied.

Hah!  I just tested this and indeed MSVC favors the last argument here.  Can you please show me how I can get the last argument from a set of two?  All I know how to do is to get the last argument of a specific type...
Comment 11 Hans Wennborg 2014-09-10 14:23:22 PDT
(In reply to comment #10)
> Hah!  I just tested this and indeed MSVC favors the last argument here.  Can
> you please show me how I can get the last argument from a set of two?  All I
> know how to do is to get the last argument of a specific type...

ArgList::getLastArg has overloads that take multiple flag types.
Comment 12 Ehsan Akhgari [:ehsan] 2014-09-10 15:37:26 PDT
(In reply to comment #11)
> (In reply to comment #10)
> > Hah!  I just tested this and indeed MSVC favors the last argument here.  Can
> > you please show me how I can get the last argument from a set of two?  All I
> > know how to do is to get the last argument of a specific type...
> 
> ArgList::getLastArg has overloads that take multiple flag types.

Perfect!
Comment 13 Ehsan Akhgari [:ehsan] 2014-09-10 20:42:12 PDT
Submitted a patch here: http://reviews.llvm.org/D5308
Comment 14 Nico Weber 2014-09-10 21:07:20 PDT
Hmm, I kind of agree with Alp here. Why do you want to use clang-cl with autoconf instead of regular clang?
Comment 15 Ehsan Akhgari [:ehsan] 2014-09-10 21:12:18 PDT
(In reply to comment #14)
> Hmm, I kind of agree with Alp here. Why do you want to use clang-cl with
> autoconf instead of regular clang?

Because it is not practical to port the entire Windows build system for large projects that use autoconf to configure to clang.  Mozilla's build system for example has been tailored to use cl.exe.  clang-cl strives to be a drop-in replacement for cl.exe, what's wrong with adding support for the options that cl.exe supports?
Comment 16 Timur Iskhodzhanov 2014-09-11 04:30:50 PDT
I'd argue your autoconf needs to be changed anyways:
> cl : Command line warning D9035 : option 'o' has been deprecated and will be removed in a future release
Comment 17 Ehsan Akhgari [:ehsan] 2014-09-11 07:04:55 PDT
(In reply to comment #16)
> I'd argue your autoconf needs to be changed anyways:
> > cl : Command line warning D9035 : option 'o' has been deprecated and will be removed in a future release

Sure, if Microsoft drops this in the future, we'll need to have another solution.  If and when that happens, we can also modify clang-cl to not accept /o if -fmsc-version indicates compat with the said possible future version.
Comment 18 Hans Wennborg 2014-09-11 12:15:34 PDT
I too think clang-cl should support this.

The fact that cl.exe supports it (including in the 14 CTP despite the deprecation warning) and that real-world projects rely on it seem like enough motivation.
Comment 19 Nico Weber 2014-09-11 12:34:44 PDT
(In reply to comment #17)
> (In reply to comment #16)
> > I'd argue your autoconf needs to be changed anyways:
> > > cl : Command line warning D9035 : option 'o' has been deprecated and will be removed in a future release
> 
> Sure, if Microsoft drops this in the future, we'll need to have another
> solution.  If and when that happens, we can also modify clang-cl to not
> accept /o if -fmsc-version indicates compat with the said possible future
> version.

Ok, that sounds fair.
Comment 20 Ehsan Akhgari [:ehsan] 2014-09-11 13:16:52 PDT
Fixed in r217615.