[cmake-developers] Adding Swift support to CMake for Linux/Makefiles

Eric Wing ewmailing at gmail.com
Fri Jan 15 09:47:42 EST 2016


(Ignore the last post. The last message sent accidentally before I was
even close to done. Not sure why it sent. I must have accidentally
discovered a hot key in Gmail. Everything is rewritten here.)


Okay, I think I'm making some good progress. I got a trivial program
built on Mac. I've now switched to Linux. I'm mostly there, but there
are still some things that need to be done. More inline...


>> Anyway, I tried bumping up CMAKE_Swift_LINKER_PREFERENCE to 40. (Same
>> as Java). But it didn't seem to do anything for me.
>
> Where did you add the code to set it?

I got it working. I put it in.
CMakeSwiftCompiler.cmake.in
I figured out I also needed to add:
set(CMAKE_Swift_LINKER_PREFERENCE_PROPAGATES 1)



>> Under the hood, I think the LLVM linker can handle all of these
>> through ld. But I think the thing that is tripping me up is that Swift
>> seems to need to link against some additional libraries which are not
>> needed in the pure C case. The swiftc command seems to know how to
>> automatically link in those extra dependencies (and I don't need to
>> add all the search paths to where the Swift core libraries are
>> located).
>
> That is the same as for C++.  See CMAKE_PARSE_IMPLICIT_LINK_INFO and
> the call to it in "Modules/CMakeDetermineCompilerABI.cmake".  That is
> responsible for extracting the implicit link information passed by a
> given language compiler's front-end.  We'll need to extract that for
> Swift.

I looked at this file, but I still havne't groked what I need to do
with this yet.

However, I'm heavily debating if 'cc' or 'clang' is the right thing to
do here. I'm starting to think 'swiftc' might be the most robust and
correct thing for the linking command. There are several reasons for
this:

- swiftc seems to already do the right thing

- Not using swiftc requires me to set a lot of things, including the
Apple SDK when on Mac. This feels really messy.

- On Linux, I think there is a danger in calling 'cc' because it could
be gcc or it could be an older version of clang. (Officially, clang
3.5 is needed, but the default one on the particular Linux I'm using
is less than that.) Invoking swiftc theoretically side-steps this
problem.


But if I use swiftc, I create a few new complications:

- First, CMake seems to be passing the flag -rdynamic to the link
instructions, and this is causing a "unknown argument" error. I think
this needs to be removed. I'm not sure where this flag is coming from.

- Second, -Wl,-rpath,/foo/bar is also causing an "unknown argument"
error. As shown in the beginning of this thread, swiftc wants each
argument to lead with -Xlinker (and there is no -Wl,)
-Xlinker -rpath -Xlinker /foo/bar

Again, I'm not sure where the old stuff is, and what is involved to
inject the -Xlinker stuff.


Additionally, I realized I should have some other variable besides
<CMAKE_Swift_COMPILER>
Seems like I should have <CMAKE_Swift_LINKER>. I'm not sure what the
correct way to create this is.

However, I currently employ a clever cheat. Since the compiler is
'swift', and the linker is 'swiftc', I just do
'<CMAKE_Swift_COMPILER>c'




>  cmMakefileTargetGenerator::WriteObjectBuildFile
> You should be able to call
>  this->GeneratorTarget->GetObjectSources(objectSources, config);

Okay, I added this code. It seems to be working. Though I'm not
completely sure I fetched config correctly.

My current changes can be found here in the SwiftMakefile branch
https://github.com/ewmailing/CMake/tree/SwiftMakefile


> and the Ninja generator here:
>
>  cmNinjaTargetGenerator::WriteCompileRule
>  cmNinjaTargetGenerator::WriteObjectBuildStatement
>
> Note that for Ninja we actually convert our placeholders to Ninja
> rule placeholders and then provide the values on the actual build
> statement line.
>

I actually don't' know anything about Ninja. I assume it is just a
string translation at this point since I did the other? Any guidance
on the mapping?


> Do we know that there is a one-to-one mapping between libraries
> and Swift modules?

Sorry, I'm still not completely up to speed on Swift modules. My
impression is there are 3 parts: .swiftmodule (which contains the
public interface/definitions), .swiftdoc (for documentation), and a
library (.a, .so). I suspect the .swiftmodule will need to be part of
the compile parameters and the library will be part of the link, but
I'm not sure if there will be additional requirements.


But anyway, I would like to get something building on Linux first, so
I need to fix the swiftc/linker stuff first. Any suggestions?

Then, I would like to enhance the trivial test to support actually
using something from the intermixed C files. This means I need to add
the bridging header parameter.
So I need a new per-target variable in CMake for this and a way to
inject it into the compiler flags, maybe something like this:

	  "<CMAKE_Swift_COMPILER> -frontend -c  <INCLUDES> <FLAGS>
-import-objc-header <TARGET-Swift-BRIDGING_HEADER> -primary-file
<SOURCE> <Swift-SOURCES> -emit-module -module-name <TARGET> -o
<OBJECT>")


With those two pieces, I think that actually makes add_executable()
usable in the Makefile generator.

Thanks,
Eric


More information about the cmake-developers mailing list