Skip to content

Commit

Permalink
CMake: Compile shared druntime/Phobos libs to a single object file
Browse files Browse the repository at this point in the history
(Only) when compiling them all-at-once anyway; primarily for implicit cross-
module inlining across the same library.

This won't work as long as there are multiple conflicting declarations
across a library's modules - issue ldc-developers#2782.
  • Loading branch information
kinke committed Jun 10, 2021
1 parent 780d296 commit 1bf0632
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 62 deletions.
156 changes: 95 additions & 61 deletions runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ endforeach()

# Compiles the given D modules to object files, and if enabled, bitcode files.
# The paths of the output files are appended to outlist_o and outlist_bc, respectively.
macro(dc src_files src_basedir d_flags output_basedir emit_bc all_at_once outlist_o outlist_bc)
macro(dc src_files src_basedir d_flags output_basedir emit_bc all_at_once single_obj_name outlist_o outlist_bc)
set(dc_flags -c --output-o ${d_flags})
if(${emit_bc})
list(APPEND dc_flags -flto=thin --output-bc)
Expand Down Expand Up @@ -438,12 +438,26 @@ macro(dc src_files src_basedir d_flags output_basedir emit_bc all_at_once outlis
endforeach()

if(${all_at_once})
add_custom_command(
OUTPUT ${new_o} ${new_bc}
COMMAND ${LDC_EXE_FULL} ${dc_flags} -od=${output_basedir} -op ${relative_src_files}
WORKING_DIRECTORY ${src_basedir}
DEPENDS ${src_files} ${dc_deps}
)
if(NOT "${single_obj_name}" STREQUAL "")
set(new_o ${output_basedir}/${single_obj_name}${CMAKE_C_OUTPUT_EXTENSION})
if(${emit_bc})
set(new_bc ${output_basedir}/bla.bc${CMAKE_C_OUTPUT_EXTENSION})
endif()

add_custom_command(
OUTPUT ${new_o} ${new_bc}
COMMAND ${LDC_EXE_FULL} ${dc_flags} -of=${new_o} ${relative_src_files}
WORKING_DIRECTORY ${src_basedir}
DEPENDS ${src_files} ${dc_deps}
)
else()
add_custom_command(
OUTPUT ${new_o} ${new_bc}
COMMAND ${LDC_EXE_FULL} ${dc_flags} -od=${output_basedir} -op ${relative_src_files}
WORKING_DIRECTORY ${src_basedir}
DEPENDS ${src_files} ${dc_deps}
)
endif()

# append a rename command for each generated .bc
foreach(dst_bc ${new_bc})
Expand Down Expand Up @@ -476,23 +490,57 @@ endmacro()

# Sets up the target(s) for building the druntime D object files, appending the
# names of the (bitcode) files to link into the library to outlist_o (outlist_bc).
macro(compile_druntime d_flags lib_suffix path_suffix emit_bc all_at_once outlist_o outlist_bc)
macro(compile_druntime d_flags lib_suffix path_suffix emit_bc all_at_once single_obj outlist_o outlist_bc)
get_target_suffix("${lib_suffix}" "${path_suffix}" target_suffix)
if(${single_obj})
set(single_obj_name druntime)
else()
set(single_obj_name "")
endif()
dc("${DRUNTIME_D}"
"${RUNTIME_DIR}/src"
"-conf=;${d_flags};${DRUNTIME_EXTRA_FLAGS};-I${RUNTIME_DIR}/src"
"${PROJECT_BINARY_DIR}/objects${target_suffix}"
"${emit_bc}"
"${all_at_once}"
"${single_obj_name}"
${outlist_o}
${outlist_bc}
)
endmacro()

set(dso_windows_o "")
if("${TARGET_SYSTEM}" MATCHES "Windows")
# Windows: precompile rt.dso_windows object file & install to lib dir.
# The existing object file isn't reused to prevent *exported* symbols (only
# -link-defaultlib-shared for dllimport, no -fvisibility=public).
# This allows to create executables with -link-defaultlib-shared without
# any exports (and according extra linker files such as the import .lib).
set(dso_windows_bc "")
dc("${RUNTIME_DIR}/src/rt/dso_windows.d"
"${RUNTIME_DIR}/src"
"-conf=;${D_FLAGS};${D_FLAGS_RELEASE};-link-defaultlib-shared;${DRUNTIME_EXTRA_FLAGS};-I${RUNTIME_DIR}/src"
"${CMAKE_BINARY_DIR}/lib${LIB_SUFFIX}"
"OFF" # emit_bc
"ON" # all_at_once
"dso_windows" # single_obj_name
dso_windows_o
dso_windows_bc
)

add_custom_target(dso_windows DEPENDS ${dso_windows_o})
install(FILES ${dso_windows_o} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
endif()

# Sets up the targets for building the Phobos D object files, appending the
# names of the (bitcode) files to link into the library to outlist_o (outlist_bc).
macro(compile_phobos2 d_flags lib_suffix path_suffix emit_bc all_at_once outlist_o outlist_bc)
macro(compile_phobos2 d_flags lib_suffix path_suffix emit_bc all_at_once single_obj outlist_o outlist_bc)
get_target_suffix("${lib_suffix}" "${path_suffix}" target_suffix)
if(${single_obj})
set(single_obj_name phobos2)
else()
set(single_obj_name "")
endif()

# Special case for Windows and emit_bc=ON:
# LLVM before v9.0 doesn't support naked DMD-style asm when generating bitcode.
Expand All @@ -515,8 +563,9 @@ macro(compile_phobos2 d_flags lib_suffix path_suffix emit_bc all_at_once outlist
"${PHOBOS2_DIR}"
"-conf=;${d_flags};${PHOBOS2_EXTRA_FLAGS};-I${RUNTIME_DIR}/src;-I${PHOBOS2_DIR}"
"${PROJECT_BINARY_DIR}/objects${target_suffix}"
"OFF"
"OFF" # emit_bc
"${all_at_once}"
"" # single_obj_name
naked_asm_o
naked_asm_o
)
Expand All @@ -531,6 +580,7 @@ macro(compile_phobos2 d_flags lib_suffix path_suffix emit_bc all_at_once outlist
"${PROJECT_BINARY_DIR}/objects${target_suffix}"
"${emit_bc}"
"${all_at_once}"
"${single_obj_name}"
${outlist_o}
${outlist_bc}
)
Expand Down Expand Up @@ -655,17 +705,16 @@ macro(build_runtime_variant d_flags c_flags ld_flags lib_suffix path_suffix emit
list(APPEND phobos2_d_flags ${PHOBOS2_EXTRA_UNITTEST_FLAGS})
endif()

# Posix: only compile Phobos modules once for static+shared libs.
# If a shared Phobos lib is generated (too), compile explicitly with `-relocation-model=pic`.
if(NOT "${TARGET_SYSTEM}" MATCHES "Windows")
if(NOT ${BUILD_SHARED_LIBS} STREQUAL "OFF")
list(APPEND phobos2_d_flags -relocation-model=pic)
endif()

# Posix: when compiling both static and shared Phobos *and* compiling the modules separately
# (by default, only for the unittests), only compile once to save build time.
set(phobos2_common "")
if((NOT "${TARGET_SYSTEM}" MATCHES "Windows") AND BUILD_SHARED_LIBS STREQUAL "BOTH"
AND NOT ${all_d_files_at_once})
set(phobos2_o "")
set(phobos2_bc "")
compile_phobos2("${phobos2_d_flags}" "${lib_suffix}"
"${path_suffix}" "${emit_bc}" "${all_d_files_at_once}" phobos2_o phobos2_bc)
compile_phobos2("${phobos2_d_flags};-relocation-model=pic;-fvisibility=public"
"${lib_suffix}${SHARED_LIB_SUFFIX}" "${path_suffix}"
"${emit_bc}" "${all_d_files_at_once}" "OFF" phobos2_o phobos2_bc)

# Use a dummy custom target ('phobos2-ldc…-common') depending solely on the Phobos D objects
# (custom commands) as dependency for static+shared Phobos libs.
Expand All @@ -684,72 +733,56 @@ macro(build_runtime_variant d_flags c_flags ld_flags lib_suffix path_suffix emit
if(NOT ${BUILD_SHARED_LIBS} STREQUAL "ON")
set(druntime_o "")
set(druntime_bc "")
compile_druntime("${druntime_d_flags}" "${lib_suffix}"
"${path_suffix}" "${emit_bc}" "${all_d_files_at_once}" druntime_o druntime_bc)
compile_druntime("${druntime_d_flags}" "${lib_suffix}" "${path_suffix}"
"${emit_bc}" "${all_d_files_at_once}" "OFF" druntime_o druntime_bc)

# Windows: compile Phobos with hidden visibility
if("${TARGET_SYSTEM}" MATCHES "Windows")
# compile Phobos (with hidden visibility on Windows)
if(phobos2_common STREQUAL "")
set(phobos2_o "")
set(phobos2_bc "")
compile_phobos2("${phobos2_d_flags}" "${lib_suffix}"
"${path_suffix}" "${emit_bc}" "${all_d_files_at_once}" phobos2_o phobos2_bc)
compile_phobos2("${phobos2_d_flags}" "${lib_suffix}" "${path_suffix}"
"${emit_bc}" "${all_d_files_at_once}" "OFF" phobos2_o phobos2_bc)
endif()

build_runtime_libs("${druntime_o}" "${druntime_bc}" "${phobos2_o}" "${phobos2_bc}"
"${c_flags}" "${ld_flags}" "${lib_suffix}" "${path_suffix}"
"OFF" "${emit_bc}" ${outlist_targets})

if(NOT "${TARGET_SYSTEM}" MATCHES "Windows")
if(NOT phobos2_common STREQUAL "")
add_dependencies(phobos2-ldc${target_suffix} ${phobos2_common})
endif()
endif()
# shared druntime/Phobos
if(NOT ${BUILD_SHARED_LIBS} STREQUAL "OFF")
# compile druntime with extra `version (Shared)`
# compile druntime with public visibility and extra `version (Shared)` (and preferably to a single object file)
set(druntime_o "")
set(druntime_bc "")
compile_druntime("${druntime_d_flags};-relocation-model=pic;-d-version=Shared;-fvisibility=public" "${lib_suffix}${SHARED_LIB_SUFFIX}"
"${path_suffix}" "OFF" "${all_d_files_at_once}" druntime_o druntime_bc)
compile_druntime("${druntime_d_flags};-relocation-model=pic;-fvisibility=public;-d-version=Shared"
"${lib_suffix}${SHARED_LIB_SUFFIX}" "${path_suffix}"
"OFF" "${all_d_files_at_once}" "${all_d_files_at_once}" druntime_o druntime_bc)

# Windows: compile Phobos with public visibility
if("${TARGET_SYSTEM}" MATCHES "Windows")
# compile Phobos with public visibility (and preferably to a single object file)
if(phobos2_common STREQUAL "")
set(phobos2_o "")
set(phobos2_bc "")
compile_phobos2("${phobos2_d_flags};-fvisibility=public" "${lib_suffix}${SHARED_LIB_SUFFIX}"
"${path_suffix}" "OFF" "${all_d_files_at_once}" phobos2_o phobos2_bc)
compile_phobos2("${phobos2_d_flags};-relocation-model=pic;-fvisibility=public"
"${lib_suffix}${SHARED_LIB_SUFFIX}" "${path_suffix}"
"OFF" "${all_d_files_at_once}" "${all_d_files_at_once}" phobos2_o phobos2_bc)
endif()

if("${TARGET_SYSTEM}" MATCHES "Windows")
# also link-in special rt.dso_windows druntime module
list(APPEND phobos2_o ${PROJECT_BINARY_DIR}/objects${target_suffix}/rt/dso_windows.obj)
list(APPEND phobos2_o ${dso_windows_o})
endif()

build_runtime_libs("${druntime_o}" "${druntime_bc}" "${phobos2_o}" "${phobos2_bc}"
"${c_flags}" "${ld_flags}" "${lib_suffix}${SHARED_LIB_SUFFIX}" "${path_suffix}"
"ON" "OFF" ${outlist_targets})

if("${TARGET_SYSTEM}" MATCHES "Windows")
# Windows: precompile rt.dso_windows object file & install to lib dir.
# The existing object file isn't reused to prevent *exported* symbols (only
# -link-defaultlib-shared for dllimport, no -fvisibility=public).
# This allows to create executables with -link-defaultlib-shared without
# any exports (and according extra linker files such as the import .lib).
if ("${lib_suffix}" STREQUAL "")
set(dso_windows_o "")
set(dso_windows_bc "")
dc("${RUNTIME_DIR}/src/rt/dso_windows.d"
"${RUNTIME_DIR}/src/rt" # => output path: ${CMAKE_BINARY_DIR}/lib${LIB_SUFFIX}/dso_windows.obj
"-conf=;${d_flags};-link-defaultlib-shared;${DRUNTIME_EXTRA_FLAGS};-I${RUNTIME_DIR}/src"
"${CMAKE_BINARY_DIR}/lib${LIB_SUFFIX}"
"OFF" # emit_bc
"OFF" # all_at_once
dso_windows_o
dso_windows_bc
)

add_custom_target(dso_windows DEPENDS ${dso_windows_o})
add_dependencies(phobos2-ldc${target_suffix} dso_windows)
install(FILES ${dso_windows_o} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
endif()
else()
if(NOT phobos2_common STREQUAL "")
add_dependencies(phobos2-ldc${target_suffix} ${phobos2_common})
elseif("${TARGET_SYSTEM}" MATCHES "Windows")
add_dependencies(phobos2-ldc${target_suffix} dso_windows)
endif()
endif()
endmacro()
Expand Down Expand Up @@ -988,15 +1021,16 @@ macro(compile_testrunner d_flags is_shared target_suffix extra_dir_suffix)
"${RUNTIME_DIR}/src"
"${d_flags}"
"${PROJECT_BINARY_DIR}/objects-unittest${target_suffix}${extra_dir_suffix}"
"OFF"
"OFF"
"OFF" # emit_bc
"ON" # all_at_once
"test_runner" # single_obj_name
test_runner_o
test_runner_bc
)

if("${is_shared}" STREQUAL "ON" AND "${TARGET_SYSTEM}" MATCHES "Windows")
# also link-in special rt.dso_windows druntime module
list(APPEND test_runner_o ${PROJECT_BINARY_DIR}/objects${target_suffix}/rt/dso_windows.obj)
list(APPEND test_runner_o ${dso_windows_o})
endif()
endmacro()

Expand Down
3 changes: 2 additions & 1 deletion runtime/jit-rt/DefineBuildJitRT.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ if(LDC_DYNAMIC_COMPILE)
"${JITRT_DIR}/d"
"${d_flags}"
"${PROJECT_BINARY_DIR}/objects${target_suffix}"
"OFF"
"OFF" # emit_bc
"${all_at_once}"
"" # single_obj_name
${outlist_o}
${outlist_bc}
)
Expand Down

0 comments on commit 1bf0632

Please sign in to comment.