Skip to content

Commit

Permalink
ARROW-7725: [C++] Add infrastructure for unity builds and precompiled…
Browse files Browse the repository at this point in the history
… headers

Unity builds and precompiled headers can be enabled "easily" in CMake 3.16:
https://cmake.org/cmake/help/v3.16/prop_tgt/UNITY_BUILD.html
https://cmake.org/cmake/help/v3.16/command/target_precompile_headers.html

They can make builds faster in some conditions, especially on CI with little parallelism and caching.

Some care is required to make them work:

- unity builds concatenate a number of C/C++ source files together,
  so there should be no symbol clashes, C++ namespace resolution issues
  or conflicting preprocessor definitions

- precompiled headers require that the same compile options are passed
  for all files using the header

Closes #6324 from pitrou/ARROW-7725-pch-unity-builds and squashes the following commits:

2811feb <Antoine Pitrou> ARROW-7725:  Add infrastructure for unity builds and precompiled headers

Authored-by: Antoine Pitrou <antoine@python.org>
Signed-off-by: Sutou Kouhei <kou@clear-code.com>
  • Loading branch information
pitrou authored and kou committed Feb 18, 2020
1 parent cc2f65f commit 389d38b
Show file tree
Hide file tree
Showing 73 changed files with 1,420 additions and 997 deletions.
1 change: 1 addition & 0 deletions .github/workflows/cpp.yml
Expand Up @@ -163,6 +163,7 @@ jobs:
CMAKE_GENERATOR: ${{ matrix.generator }}
CMAKE_INSTALL_LIBDIR: bin
CMAKE_INSTALL_PREFIX: /usr
CMAKE_UNITY_BUILD: ON
ARROW_HOME: /usr
ARROW_DATASET: ON
ARROW_JEMALLOC: OFF
Expand Down
6 changes: 3 additions & 3 deletions appveyor.yml
Expand Up @@ -69,12 +69,12 @@ environment:
ARROW_S3: "ON"
ARROW_BUILD_FLIGHT: "ON"
ARROW_BUILD_GANDIVA: "ON"
# NOTE: Since ARROW-5403 we have disabled the static CRT build
# - JOB: "Static_Crt_Build"
# GENERATOR: Ninja
- JOB: "Build_Debug"
GENERATOR: Ninja
CONFIGURATION: "Debug"
# NOTE: Since ARROW-5403 we have disabled the static CRT build
# - JOB: "Static_Crt_Build"
# GENERATOR: Ninja
- JOB: "MinGW32"
MINGW_ARCH: i686
MINGW_PACKAGE_PREFIX: mingw-w64-i686
Expand Down
2 changes: 2 additions & 0 deletions ci/appveyor-cpp-build.bat
Expand Up @@ -85,11 +85,13 @@ if "%JOB%" == "Build_Debug" (
pushd cpp\build-debug

cmake -G "%GENERATOR%" ^
-DARROW_USE_PRECOMPILED_HEADERS=OFF ^
-DARROW_VERBOSE_THIRDPARTY_BUILD=OFF ^
-DARROW_BOOST_USE_SHARED=OFF ^
-DARROW_BUILD_TESTS=ON ^
-DARROW_BUILD_EXAMPLES=ON ^
-DCMAKE_BUILD_TYPE=%CONFIGURATION% ^
-DCMAKE_UNITY_BUILD=ON ^
-DARROW_BUILD_STATIC=OFF ^
-DARROW_CXXFLAGS="/MP" ^
-DARROW_ENABLE_TIMING_TESTS=OFF ^
Expand Down
1 change: 1 addition & 0 deletions ci/cpp-msvc-build-main.bat
Expand Up @@ -62,6 +62,7 @@ cmake -G "%GENERATOR%" %CMAKE_ARGS% ^
-DCMAKE_BUILD_TYPE=%CONFIGURATION% ^
-DCMAKE_INSTALL_PREFIX=%CONDA_PREFIX%\Library ^
-DCMAKE_VERBOSE_MAKEFILE=OFF ^
-DCMAKE_UNITY_BUILD=ON ^
-DARROW_VERBOSE_THIRDPARTY_BUILD=OFF ^
-DARROW_BOOST_USE_SHARED=OFF ^
-DARROW_BUILD_STATIC=OFF ^
Expand Down
4 changes: 3 additions & 1 deletion ci/scripts/cpp_build.sh
Expand Up @@ -88,6 +88,7 @@ cmake -G "${CMAKE_GENERATOR:-Ninja}" \
-DARROW_USE_CCACHE=${ARROW_USE_CCACHE:-ON} \
-DARROW_USE_GLOG=${ARROW_USE_GLOG:-ON} \
-DARROW_USE_LD_GOLD=${ARROW_USE_LD_GOLD:-OFF} \
-DARROW_USE_PRECOMPILED_HEADERS=${ARROW_USE_PRECOMPILED_HEADERS:-OFF} \
-DARROW_USE_STATIC_CRT=${ARROW_USE_STATIC_CRT:-OFF} \
-DARROW_USE_UBSAN=${ARROW_USE_UBSAN:-OFF} \
-DARROW_VERBOSE_THIRDPARTY_BUILD=${ARROW_VERBOSE_THIRDPARTY_BUILD:-OFF} \
Expand All @@ -107,6 +108,7 @@ cmake -G "${CMAKE_GENERATOR:-Ninja}" \
-DCMAKE_CXX_FLAGS=${CXXFLAGS:-} \
-DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR:-lib} \
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX:-${ARROW_HOME}} \
-DCMAKE_UNITY_BUILD=${CMAKE_UNITY_BUILD:-OFF} \
-Dgflags_SOURCE=${gflags_SOURCE:-AUTO} \
-DgRPC_SOURCE=${gRPC_SOURCE:-AUTO} \
-DGTest_SOURCE=${GTest_SOURCE:-AUTO} \
Expand All @@ -123,7 +125,7 @@ cmake -G "${CMAKE_GENERATOR:-Ninja}" \
${CMAKE_ARGS} \
${source_dir}

cmake --build . --target install
time cmake --build . --target install

popd

Expand Down
5 changes: 5 additions & 0 deletions cpp/CMakeLists.txt
Expand Up @@ -151,6 +151,11 @@ if(ARROW_USE_CCACHE)
endif(CCACHE_FOUND)
endif()

if(ARROW_USE_PRECOMPILED_HEADERS AND ${CMAKE_VERSION} VERSION_LESS "3.16.0")
message(WARNING "Precompiled headers need CMake 3.16.0 or later, disabling")
set(ARROW_USE_PRECOMPILED_HEADERS OFF)
endif()

if(ARROW_OPTIONAL_INSTALL)
# Don't make the "install" target depend on the "all" target
set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY true)
Expand Down
57 changes: 48 additions & 9 deletions cpp/cmake_modules/BuildUtils.cmake
Expand Up @@ -122,12 +122,20 @@ function(ADD_THIRDPARTY_LIB LIB_NAME)
endif()
endfunction()

function(REUSE_PRECOMPILED_HEADER_LIB TARGET_NAME LIB_NAME)
if(ARROW_USE_PRECOMPILED_HEADERS)
target_precompile_headers(${TARGET_NAME} REUSE_FROM ${LIB_NAME})
endif()
endfunction()

# \arg OUTPUTS list to append built targets to
function(ADD_ARROW_LIB LIB_NAME)
set(options BUILD_SHARED BUILD_STATIC)
set(one_value_args CMAKE_PACKAGE_NAME PKG_CONFIG_NAME SHARED_LINK_FLAGS)
set(one_value_args CMAKE_PACKAGE_NAME PKG_CONFIG_NAME SHARED_LINK_FLAGS
PRECOMPILED_HEADER_LIB)
set(multi_value_args
SOURCES
PRECOMPILED_HEADERS
OUTPUTS
STATIC_LINK_LIBS
SHARED_LINK_LIBS
Expand Down Expand Up @@ -173,21 +181,26 @@ function(ADD_ARROW_LIB LIB_NAME)
# because of dllexport declarations on Windows.
# The Xcode generator doesn't reliably work with Xcode as target names are not
# guessed correctly.
set(LIB_DEPS ${ARG_SOURCES})
set(EXTRA_DEPS ${ARG_DEPENDENCIES})

if(ARG_EXTRA_INCLUDES)
set(LIB_INCLUDES ${ARG_EXTRA_INCLUDES})
endif()
set(USE_OBJLIB OFF)
else()
# Otherwise, generate a single "objlib" from all C++ modules and link
set(USE_OBJLIB ON)
endif()

if(USE_OBJLIB)
# Generate a single "objlib" from all C++ modules and link
# that "objlib" into each library kind, to avoid compiling twice
add_library(${LIB_NAME}_objlib OBJECT ${ARG_SOURCES})
# Necessary to make static linking into other shared libraries work properly
set_property(TARGET ${LIB_NAME}_objlib PROPERTY POSITION_INDEPENDENT_CODE 1)
if(ARG_DEPENDENCIES)
add_dependencies(${LIB_NAME}_objlib ${ARG_DEPENDENCIES})
endif()
if(ARG_PRECOMPILED_HEADER_LIB)
reuse_precompiled_header_lib(${LIB_NAME}_objlib ${ARG_PRECOMPILED_HEADER_LIB})
endif()
if(ARG_PRECOMPILED_HEADERS AND ARROW_USE_PRECOMPILED_HEADERS)
target_precompile_headers(${LIB_NAME}_objlib PRIVATE ${ARG_PRECOMPILED_HEADERS})
endif()
set(LIB_DEPS $<TARGET_OBJECTS:${LIB_NAME}_objlib>)
set(LIB_INCLUDES)
set(EXTRA_DEPS)
Expand All @@ -202,6 +215,15 @@ function(ADD_ARROW_LIB LIB_NAME)
if(ARG_PRIVATE_INCLUDES)
target_include_directories(${LIB_NAME}_objlib PRIVATE ${ARG_PRIVATE_INCLUDES})
endif()
else()
# Prepare arguments for separate compilation of static and shared libs below
# TODO: add PCH directives
set(LIB_DEPS ${ARG_SOURCES})
set(EXTRA_DEPS ${ARG_DEPENDENCIES})

if(ARG_EXTRA_INCLUDES)
set(LIB_INCLUDES ${ARG_EXTRA_INCLUDES})
endif()
endif()

set(RUNTIME_INSTALL_DIR bin)
Expand All @@ -212,6 +234,10 @@ function(ADD_ARROW_LIB LIB_NAME)
add_dependencies(${LIB_NAME}_shared ${EXTRA_DEPS})
endif()

if(ARG_PRECOMPILED_HEADER_LIB)
reuse_precompiled_header_lib(${LIB_NAME}_shared ${ARG_PRECOMPILED_HEADER_LIB})
endif()

if(ARG_OUTPUTS)
list(APPEND ${ARG_OUTPUTS} ${LIB_NAME}_shared)
endif()
Expand Down Expand Up @@ -293,6 +319,10 @@ function(ADD_ARROW_LIB LIB_NAME)
add_dependencies(${LIB_NAME}_static ${EXTRA_DEPS})
endif()

if(ARG_PRECOMPILED_HEADER_LIB)
reuse_precompiled_header_lib(${LIB_NAME}_static ${ARG_PRECOMPILED_HEADER_LIB})
endif()

if(ARG_OUTPUTS)
list(APPEND ${ARG_OUTPUTS} ${LIB_NAME}_static)
endif()
Expand Down Expand Up @@ -516,9 +546,10 @@ endfunction()
# names must exist
function(ADD_TEST_CASE REL_TEST_NAME)
set(options NO_VALGRIND ENABLED)
set(one_value_args)
set(one_value_args PRECOMPILED_HEADER_LIB)
set(multi_value_args
SOURCES
PRECOMPILED_HEADERS
STATIC_LINK_LIBS
EXTRA_LINK_LIBS
EXTRA_INCLUDES
Expand Down Expand Up @@ -577,6 +608,14 @@ function(ADD_TEST_CASE REL_TEST_NAME)
target_link_libraries(${TEST_NAME} PRIVATE ${ARROW_TEST_LINK_LIBS})
endif()

if(ARG_PRECOMPILED_HEADER_LIB)
reuse_precompiled_header_lib(${TEST_NAME} ${ARG_PRECOMPILED_HEADER_LIB})
endif()

if(ARG_PRECOMPILED_HEADERS AND ARROW_USE_PRECOMPILED_HEADERS)
target_precompile_headers(${TEST_NAME} PRIVATE ${ARG_PRECOMPILED_HEADERS})
endif()

if(ARG_EXTRA_LINK_LIBS)
target_link_libraries(${TEST_NAME} PRIVATE ${ARG_EXTRA_LINK_LIBS})
endif()
Expand Down
3 changes: 3 additions & 0 deletions cpp/cmake_modules/DefineOptions.cmake
Expand Up @@ -92,6 +92,9 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")

define_option(ARROW_USE_LD_GOLD "Use ld.gold for linking on Linux (if available)" OFF)

define_option(ARROW_USE_PRECOMPILED_HEADERS "Use precompiled headers when compiling"
OFF)

# Disable this option to exercise non-SIMD fallbacks
define_option(ARROW_USE_SIMD "Build with SIMD optimizations" ON)

Expand Down
6 changes: 6 additions & 0 deletions cpp/cmake_modules/SetupCxxFlags.cmake
Expand Up @@ -227,6 +227,12 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43407
set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-attributes")
endif()

if(CMAKE_UNITY_BUILD)
# Work around issue similar to https://bugs.webkit.org/show_bug.cgi?id=176869
set(CXX_ONLY_FLAGS "${CXX_ONLY_FLAGS} -Wno-subobject-linkage")
endif()

elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang"
OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# Clang options for all builds
Expand Down

0 comments on commit 389d38b

Please sign in to comment.