Skip to content

Commit b97db38

Browse files
committed
Use pkg-config to find libxml2 and libcurl on Linux [SR-5608]
This allows linking swift-corelibs-foundation to packages with flags defined by `pkg-config`, rather than hardcoded ones. There are a couple of structural changes as well, namely that `pkg-config` will now be executed during `configure` rather than later by `ninja`. This seems acceptable as it's how cmake and autoconf work, but means a reconfigure will be required if any transitive dependency of a package we depend on files changes. The other structural change is that `-lcurl` will be passed unconditionally on platforms without pkg-config support (technically the `pkg_config_required` variable set). This makes curl a harder dependency on those platforms, but that seems unavoidable given that it's the only implementation of `URLSession`.
1 parent 9b4cebe commit b97db38

File tree

4 files changed

+101
-13
lines changed

4 files changed

+101
-13
lines changed

build.py

+32-12
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515

1616
swift_cflags = ['-DDEPLOYMENT_RUNTIME_SWIFT']
1717
if Configuration.current.target.sdk == OSType.Linux:
18-
foundation.CFLAGS = '`${PKG_CONFIG} icu-uc icu-i18n --cflags-only-I` -DDEPLOYMENT_TARGET_LINUX -D_GNU_SOURCE -DCF_CHARACTERSET_DATA_DIR="CoreFoundation/CharacterSets"'
19-
foundation.LDFLAGS = '${SWIFT_USE_LINKER} -Wl,@./CoreFoundation/linux.ld -lswiftGlibc `${PKG_CONFIG} icu-uc icu-i18n --libs` -Wl,-Bsymbolic '
18+
foundation.CFLAGS = '-DDEPLOYMENT_TARGET_LINUX -D_GNU_SOURCE -DCF_CHARACTERSET_DATA_DIR="CoreFoundation/CharacterSets"'
19+
foundation.LDFLAGS = '${SWIFT_USE_LINKER} -Wl,@./CoreFoundation/linux.ld -lswiftGlibc -Wl,-Bsymbolic '
2020
Configuration.current.requires_pkg_config = True
2121
elif Configuration.current.target.sdk == OSType.FreeBSD:
2222
foundation.CFLAGS = '-DDEPLOYMENT_TARGET_FREEBSD -I/usr/local/include -I/usr/local/include/libxml2 -I/usr/local/include/curl '
@@ -61,35 +61,55 @@
6161
'-Wno-unused-variable',
6262
'-Wno-int-conversion',
6363
'-Wno-unused-function',
64-
'-I${SYSROOT}/usr/include/libxml2',
65-
'-I${SYSROOT}/usr/include/curl',
6664
'-I./',
6765
])
6866

6967
swift_cflags += [
7068
'-I${BUILD_DIR}/Foundation/usr/lib/swift',
71-
'-I${SYSROOT}/usr/include/libxml2',
72-
'-I${SYSROOT}/usr/include/curl'
7369
]
7470

7571
if "XCTEST_BUILD_DIR" in Configuration.current.variables:
7672
swift_cflags += [
7773
'-I${XCTEST_BUILD_DIR}',
7874
'-L${XCTEST_BUILD_DIR}',
79-
'-I${SYSROOT}/usr/include/libxml2',
80-
'-I${SYSROOT}/usr/include/curl'
8175
]
8276

83-
triple = Configuration.current.target.triple
84-
if triple.find("linux") != -1:
85-
foundation.LDFLAGS += '-lcurl '
77+
if Configuration.current.requires_pkg_config:
78+
pkg_config_dependencies = [
79+
'icu-i18n',
80+
'icu-uc',
81+
'libcurl',
82+
'libxml-2.0',
83+
]
84+
for package_name in pkg_config_dependencies:
85+
try:
86+
package = PkgConfig(package_name)
87+
except PkgConfig.Error as e:
88+
sys.exit("pkg-config error for package {}: {}".format(package_name, e))
89+
foundation.CFLAGS += ' {} '.format(' '.join(package.cflags))
90+
foundation.LDFLAGS += ' {} '.format(' '.join(package.ldflags))
91+
swift_cflags += package.swiftc_flags
92+
else:
93+
foundation.CFLAGS += ''.join([
94+
'-I${SYSROOT}/usr/include/curl ',
95+
'-I${SYSROOT}/usr/include/libxml2 ',
96+
])
97+
foundation.LDFLAGS += ''.join([
98+
'-lcurl ',
99+
'-lxml2 ',
100+
])
101+
swift_cflags += ''.join([
102+
'-I${SYSROOT}/usr/include/curl ',
103+
'-I${SYSROOT}/usr/include/libxml2 ',
104+
])
86105

106+
triple = Configuration.current.target.triple
87107
if triple == "armv7-none-linux-androideabi":
88108
foundation.LDFLAGS += '-llog '
89109
else:
90110
foundation.LDFLAGS += '-lpthread '
91111

92-
foundation.LDFLAGS += '-ldl -lm -lswiftCore -lxml2 '
112+
foundation.LDFLAGS += '-ldl -lm -lswiftCore '
93113

94114
# Configure use of Dispatch in CoreFoundation and Foundation if libdispatch is being built
95115
if "LIBDISPATCH_SOURCE_DIR" in Configuration.current.variables:

configure

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ from lib.product import StaticAndDynamicLibrary
3232
from lib.product import Application
3333
from lib.product import Executable
3434

35+
from lib.pkg_config import PkgConfig
36+
3537
from lib.script import Script
3638

3739
from lib.target import ArchSubType

lib/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
"config",
1212
"path",
1313
"phases",
14+
"pkg_config",
1415
"product",
1516
"script",
1617
"target",
1718
"workspace",
18-
]
19+
]

lib/pkg_config.py

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
from __future__ import print_function
2+
3+
import shlex
4+
import subprocess
5+
import sys
6+
7+
from .config import Configuration
8+
9+
10+
class PkgConfig(object):
11+
class Error(Exception):
12+
"""Raised when information could not be obtained from pkg-config."""
13+
14+
def __init__(self, package_name):
15+
"""Query pkg-config for information about a package.
16+
17+
:type package_name: str
18+
:param package_name: The name of the package to query.
19+
:raises PkgConfig.Error: When a call to pkg-config fails.
20+
"""
21+
self.package_name = package_name
22+
self._cflags = self._call("--cflags")
23+
self._cflags_only_I = self._call("--cflags-only-I")
24+
self._cflags_only_other = self._call("--cflags-only-other")
25+
self._libs = self._call("--libs")
26+
self._libs_only_l = self._call("--libs-only-l")
27+
self._libs_only_L = self._call("--libs-only-L")
28+
self._libs_only_other = self._call("--libs-only-other")
29+
30+
def _call(self, *pkg_config_args):
31+
try:
32+
cmd = [Configuration.current.pkg_config] + list(pkg_config_args) + [self.package_name]
33+
print("Executing command '{}'".format(cmd), file=sys.stderr)
34+
return shlex.split(subprocess.check_output(cmd))
35+
except subprocess.CalledProcessError as e:
36+
raise self.Error("pkg-config exited with error code {}".format(e.returncode))
37+
38+
@property
39+
def swiftc_flags(self):
40+
"""Flags for this package in a format suitable for passing to `swiftc`.
41+
42+
:rtype: list[str]
43+
"""
44+
return (
45+
["-Xcc {}".format(s) for s in self._cflags_only_other]
46+
+ ["-Xlinker {}".format(s) for s in self._libs_only_other]
47+
+ self._cflags_only_I
48+
+ self._libs_only_L
49+
+ self._libs_only_l)
50+
51+
@property
52+
def cflags(self):
53+
"""CFLAGS for this package.
54+
55+
:rtype: list[str]
56+
"""
57+
return self._cflags
58+
59+
@property
60+
def ldflags(self):
61+
"""LDFLAGS for this package.
62+
63+
:rtype: list[str]
64+
"""
65+
return self._libs

0 commit comments

Comments
 (0)