Skip to content

Commit 04e1cd5

Browse files
committed
[Glibc] Configure modulemap for target, not host
The current Glibc CMakeLists.txt uses the host machine to determine which modulemap to use. The same modulemap can't be used for all platforms because headers are available in different locations on different platforms. Using the host machine to determine which modulemap to configure and place at a specific path in the resource dir is fine, so long as: 1. Only one Glibc is being compiled in a single CMake invocation. 2. The target machine needs the same modulemap as the host. #1442 violates both of these assumptions: the Glibc module for both Linux and Android is compiled at the same time, and the Android target can't use the Linux modulemap. This commit instead uses the target(s) to determine which modulemap to use. The modulemap is configured and placed in an OS- and architecture-specific directory in the resource dir. The path to that modulemap is referenced by the ClangImporter (since it is no longer at a path that is automatically discovered as an implicit modulemap).
1 parent 7318060 commit 04e1cd5

File tree

4 files changed

+91
-43
lines changed

4 files changed

+91
-43
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ getNormalInvocationArguments(std::vector<std::string> &invocationArgStrs,
295295
// Enable modules.
296296
"-fmodules",
297297

298-
// Enable implicit module maps
298+
// Enable implicit module maps (this option is implied by "-fmodules").
299299
"-fimplicit-module-maps",
300300

301301
// Don't emit LLVM IR.
@@ -358,6 +358,35 @@ getNormalInvocationArguments(std::vector<std::string> &invocationArgStrs,
358358
// Just use the most feature-rich C language mode.
359359
"-x", "c", "-std=gnu11",
360360
});
361+
362+
// The module map used for Glibc depends on the target we're compiling for,
363+
// and is not included in the resource directory with the other implicit
364+
// module maps. It's at {freebsd|linux}/{arch}/glibc.modulemap.
365+
SmallString<128> GlibcModuleMapPath;
366+
if (!importerOpts.OverrideResourceDir.empty()) {
367+
GlibcModuleMapPath = importerOpts.OverrideResourceDir;
368+
} else if (!searchPathOpts.RuntimeResourcePath.empty()) {
369+
GlibcModuleMapPath = searchPathOpts.RuntimeResourcePath;
370+
}
371+
372+
// Running without a resource directory is not a supported configuration.
373+
assert(!GlibcModuleMapPath.empty());
374+
375+
llvm::sys::path::append(
376+
GlibcModuleMapPath,
377+
swift::getPlatformNameForTriple(triple), triple.getArchName(),
378+
"glibc.modulemap");
379+
380+
// Only specify the module map if that file actually exists.
381+
// It may not--for example in the case that
382+
// `swiftc -target x86_64-unknown-linux-gnu -emit-ir` is invoked using
383+
// a Swift compiler not built for Linux targets.
384+
if (llvm::sys::fs::exists(GlibcModuleMapPath)) {
385+
invocationArgStrs.push_back(
386+
(Twine("-fmodule-map-file=") + GlibcModuleMapPath).str());
387+
} else {
388+
// FIXME: Emit a warning of some kind.
389+
}
361390
}
362391

363392
if (triple.isOSDarwin()) {

stdlib/public/CMakeLists.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,11 @@ if(SWIFT_BUILD_STDLIB)
3131
add_subdirectory(stubs)
3232
add_subdirectory(core)
3333
add_subdirectory(SwiftOnoneSupport)
34+
add_subdirectory(Glibc)
3435
endif()
3536

3637
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
3738
if(SWIFT_BUILD_SDK_OVERLAY)
3839
add_subdirectory(SDK)
3940
endif()
4041
endif()
41-
42-
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
43-
add_subdirectory(Glibc)
44-
endif()

stdlib/public/Glibc/CMakeLists.txt

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,56 @@ set(sources
33
Misc.c
44
)
55

6-
set(output_dir "${SWIFTLIB_DIR}/glibc")
6+
# When cross-compiling the stdlib on Unix platforms, we'll need a separate
7+
# glibc for each target.
8+
foreach(SDK ${SWIFT_SDKS})
9+
foreach(arch ${SWIFT_SDK_${SDK}_ARCHITECTURES})
10+
set(output_dir "${SWIFTLIB_DIR}/${SWIFT_SDK_${SDK}_LIB_SUBDIR}/${arch}")
711

8-
# Set correct paths to glibc headers
9-
set(GLIBC_INCLUDE_PATH "/usr/include")
10-
if(CMAKE_LIBRARY_ARCHITECTURE)
11-
set(GLIBC_ARCH_INCLUDE_PATH "${GLIBC_INCLUDE_PATH}/${CMAKE_LIBRARY_ARCHITECTURE}")
12-
else()
13-
set(GLIBC_ARCH_INCLUDE_PATH "${GLIBC_INCLUDE_PATH}")
14-
endif()
15-
if (NOT EXISTS "${GLIBC_ARCH_INCLUDE_PATH}/sys")
16-
message(FATAL_ERROR "Glibc headers were not found.")
17-
endif()
12+
# Determine the location of glibc based on the target.
13+
set(GLIBC_INCLUDE_PATH "/usr/include")
14+
set(GLIBC_ARCH_INCLUDE_PATH "${GLIBC_INCLUDE_PATH}")
15+
if(("${SDK}" STREQUAL "LINUX" OR "${SDK}" STREQUAL "FREEBSD") AND CMAKE_LIBRARY_ARCHITECTURE)
16+
# FIXME: Some distributions install headers in
17+
# "/usr/include/x86_64-linux-gnu/sys/...". Here we use the host
18+
# machine's path, regardless of the SDK target we're building for.
19+
# This will break if cross-compiling from a distro that uses the
20+
# architecture as part of the path to a distro that does not.
21+
set(GLIBC_ARCH_INCLUDE_PATH "${GLIBC_INCLUDE_PATH}/${CMAKE_LIBRARY_ARCHITECTURE}")
22+
endif()
1823

19-
# Generate module.map
20-
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
21-
configure_file(module.map.in "${CMAKE_CURRENT_BINARY_DIR}/module.map" @ONLY)
22-
endif()
23-
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
24-
configure_file(module.freebsd.map.in "${CMAKE_CURRENT_BINARY_DIR}/module.map" @ONLY)
25-
endif()
24+
# Configure the modulemap based on the target. Each platform needs to
25+
# reference different headers, based on what's available in their glibc.
26+
set(modulemap_path "${CMAKE_CURRENT_BINARY_DIR}/${SWIFT_SDK_${SDK}_LIB_SUBDIR}/${arch}/module.map")
27+
if("${SDK}" STREQUAL "FREEBSD")
28+
configure_file(module.freebsd.map.in "${modulemap_path}" @ONLY)
29+
else()
30+
configure_file(module.map.in "${modulemap_path}" @ONLY)
31+
endif()
2632

27-
add_custom_command_target(unused_var
28-
COMMAND
29-
"${CMAKE_COMMAND}" "-E" "make_directory" "${output_dir}"
30-
COMMAND
31-
"${CMAKE_COMMAND}" "-E" "copy_if_different"
32-
"${CMAKE_CURRENT_BINARY_DIR}/module.map"
33-
"${output_dir}/module.map"
34-
CUSTOM_TARGET_NAME "copy_glibc_module"
35-
OUTPUT "${output_dir}/module.map" "${output_dir}"
36-
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/module.map"
37-
COMMENT "Copying Glibc module to ${output_dir}")
33+
set(VARIANT_SUFFIX "-${SWIFT_SDK_${SDK}_LIB_SUBDIR}-${arch}")
34+
add_custom_command_target(unused_var
35+
COMMAND
36+
"${CMAKE_COMMAND}" "-E" "make_directory" "${output_dir}"
37+
COMMAND
38+
"${CMAKE_COMMAND}" "-E" "copy_if_different"
39+
"${modulemap_path}"
40+
"${output_dir}/glibc.modulemap"
41+
CUSTOM_TARGET_NAME "copy_glibc_module${VARIANT_SUFFIX}"
42+
OUTPUT "${output_dir}/glibc.modulemap" "${output_dir}"
43+
DEPENDS "${modulemap_path}"
44+
COMMENT "Copying Glibc module to ${output_dir}")
3845

39-
swift_install_in_component(stdlib
40-
FILES "${output_dir}/module.map"
41-
DESTINATION "lib/swift/glibc")
46+
swift_install_in_component(stdlib
47+
FILES "${output_dir}/glibc.modulemap"
48+
DESTINATION "${output_dir}")
4249

43-
add_swift_library(swiftGlibc IS_SDK_OVERLAY
44-
${sources}
45-
FILE_DEPENDS copy_glibc_module "${output_dir}"
46-
INSTALL_IN_COMPONENT stdlib-experimental)
50+
if("${SDK}" STREQUAL "LINUX" OR "${SDK}" STREQUAL "${FREEBSD}")
51+
add_swift_library(swiftGlibc IS_SDK_OVERLAY
52+
${sources}
53+
FILE_DEPENDS "copy_glibc_module${VARIANT_SUFFIX}" "${output_dir}"
54+
TARGET_SDKS "${SDK}"
55+
INSTALL_IN_COMPONENT stdlib-experimental)
56+
endif()
57+
endforeach()
58+
endforeach()

tools/driver/modulewrap_main.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,20 @@ int modulewrap_main(ArrayRef<const char *> Args, const char *Argv0,
153153
return 1;
154154
}
155155

156-
// Wrap the bitstream in an object file.
156+
// Wrap the bitstream in a module object file. To use the ClangImporter to
157+
// create the module loader, we need to properly set the runtime library path.
158+
SearchPathOptions SearchPathOpts;
159+
// FIXME: This logic has been duplicated from
160+
// CompilerInvocation::setMainExecutablePath. ModuleWrapInvocation
161+
// should share its implementation.
162+
SmallString<128> RuntimeResourcePath(MainExecutablePath);
163+
llvm::sys::path::remove_filename(RuntimeResourcePath); // Remove /swift
164+
llvm::sys::path::remove_filename(RuntimeResourcePath); // Remove /bin
165+
llvm::sys::path::append(RuntimeResourcePath, "lib", "swift");
166+
SearchPathOpts.RuntimeResourcePath = RuntimeResourcePath.str();
167+
157168
SourceManager SrcMgr;
158169
LangOptions LangOpts;
159-
SearchPathOptions SearchPathOpts;
160170
LangOpts.Target = Invocation.getTargetTriple();
161171
ASTContext ASTCtx(LangOpts, SearchPathOpts, SrcMgr, Instance.getDiags());
162172
ClangImporterOptions ClangImporterOpts;

0 commit comments

Comments
 (0)