Skip to content

Commit

Permalink
Support CMake multi-configuration generator (#149)
Browse files Browse the repository at this point in the history
* Support CMake multi-configuration generator

Replace `include_directories(${Boost_INCLUDE_DIRS})` with `target_include_directories(fruit PRIVATE ${Boost_INCLUDE_DIRS})`.
Boost is only needed at build time, so the `PRIVATE` scope should be best.

* Remove CMAKE_CXX_COMPILER_ID check

`WINDOWS_EXPORT_ALL_SYMBOLS` property works only on Windows, so ‘CMAKE_CXX_COMPILER_ID‘ checks are not required.

* Fix tests

* Fixed a bug that a semicolon became the delimiter when `FRUIT_TEST_COMPILE_FLAGS` was expanded

* Fix tests

* Fix `CHECK_CXX_SOURCE_COMPILES`

`CMAKE_REQUIRED_FLAGS` does not seem to inherit `CMAKE_CXX_FLAGS` etc., so I reverted to explicitly setting all flags.

* Fix `CHECK_CXX_SOURCE_COMPILES` again

* Fixed a bug with missing C++ standard flags

CMake's multi-configuration generator support commit was missing `-std=c++11` from the `FRUIT_ADDITIONAL_COMPILE_FLAGS` variable. This caused fruit to be built with the C++ standard flags, but tests and `CHECK_CXX_SOURCE_COMPILES()` were built without the C++ standard flags.
 it now specifies the C++ standard option.

* Fixed a bug that could not include boost headers

* Set msbuild Configuration

MSVC in GitHub Actions was always doing Debug builds due to the addition of CMake multi-configuration generator support. Fixed to specify `/pConfiguration=%CONFIGURATION%` in the `msbuild` command.

* Fix tests

* Added `FRUIT_ALLOW_MULTI_CONFIG` option

* Fix wrong escape

* Updated comments on `FRUIT_ALLOW_MULTI_CONFIG` option

* Improved CMake multi-configuration generator tests
  • Loading branch information
tt4g authored Jan 29, 2023
1 parent 8149131 commit 9beae9f
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 64 deletions.
23 changes: 15 additions & 8 deletions .github/workflows/test-on-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,23 @@ jobs:
fail-fast: false
matrix:
config:
- {runs_on: windows-2022, msvc_version_year: 2022, msvc_version: 17, python_path: "C:\\Python39", msvc_program_files: "C:\\Program Files", config: Debug, cxx_standard: 17}
- {runs_on: windows-2022, msvc_version_year: 2022, msvc_version: 17, python_path: "C:\\Python39", msvc_program_files: "C:\\Program Files", config: Release, cxx_standard: 17}
- {runs_on: windows-2022, msvc_version_year: 2022, msvc_version: 17, python_path: "C:\\Python39", msvc_program_files: "C:\\Program Files", config: Debug}
- {runs_on: windows-2022, msvc_version_year: 2022, msvc_version: 17, python_path: "C:\\Python39", msvc_program_files: "C:\\Program Files", config: Release}
- {runs_on: windows-2019, msvc_version_year: 2019, msvc_version: 16, python_path: "C:\\Python36", msvc_program_files: "C:\\Program Files (x86)", config: Debug, cxx_standard: 17}
- {runs_on: windows-2019, msvc_version_year: 2019, msvc_version: 16, python_path: "C:\\Python36", msvc_program_files: "C:\\Program Files (x86)", config: Release, cxx_standard: 17}
- {runs_on: windows-2019, msvc_version_year: 2019, msvc_version: 16, python_path: "C:\\Python36", msvc_program_files: "C:\\Program Files (x86)", config: Debug}
- {runs_on: windows-2019, msvc_version_year: 2019, msvc_version: 16, python_path: "C:\\Python36", msvc_program_files: "C:\\Program Files (x86)", config: Release}
- {runs_on: windows-2022, msvc_version_year: 2022, msvc_version: 17, multi_config: true, python_path: "C:\\Python39", msvc_program_files: "C:\\Program Files", config: Debug, cxx_standard: 17}
- {runs_on: windows-2022, msvc_version_year: 2022, msvc_version: 17, multi_config: true, python_path: "C:\\Python39", msvc_program_files: "C:\\Program Files", config: Release, cxx_standard: 17}
- {runs_on: windows-2022, msvc_version_year: 2022, msvc_version: 17, multi_config: false, python_path: "C:\\Python39", msvc_program_files: "C:\\Program Files", config: Debug, cxx_standard: 17}
- {runs_on: windows-2022, msvc_version_year: 2022, msvc_version: 17, multi_config: false, python_path: "C:\\Python39", msvc_program_files: "C:\\Program Files", config: Release, cxx_standard: 17}
- {runs_on: windows-2022, msvc_version_year: 2022, msvc_version: 17, multi_config: false, python_path: "C:\\Python39", msvc_program_files: "C:\\Program Files", config: Debug}
- {runs_on: windows-2022, msvc_version_year: 2022, msvc_version: 17, multi_config: false, python_path: "C:\\Python39", msvc_program_files: "C:\\Program Files", config: Release}
- {runs_on: windows-2019, msvc_version_year: 2019, msvc_version: 16, multi_config: false, python_path: "C:\\Python36", msvc_program_files: "C:\\Program Files (x86)", config: Debug, cxx_standard: 17}
- {runs_on: windows-2019, msvc_version_year: 2019, msvc_version: 16, multi_config: false, python_path: "C:\\Python36", msvc_program_files: "C:\\Program Files (x86)", config: Release, cxx_standard: 17}
- {runs_on: windows-2019, msvc_version_year: 2019, msvc_version: 16, multi_config: false, python_path: "C:\\Python36", msvc_program_files: "C:\\Program Files (x86)", config: Debug}
- {runs_on: windows-2019, msvc_version_year: 2019, msvc_version: 16, multi_config: false, python_path: "C:\\Python36", msvc_program_files: "C:\\Program Files (x86)", config: Release}
env:
PYTHON3_PATH: ${{matrix.config.python_path}}
CMAKE_GENERATOR: "Visual Studio ${{matrix.config.msvc_version}} ${{matrix.config.msvc_version_year}}"
ADDITIONAL_CMAKE_ARGS: -DFRUIT_USES_BOOST=False -T host=x64
CONFIGURATION: ${{matrix.config.config}}
VCVARSALL_DIR: "${{matrix.config.msvc_program_files}}\\Microsoft Visual Studio\\${{matrix.config.msvc_version_year}}\\Enterprise\\VC\\Auxiliary\\Build"
FRUIT_ALLOW_MULTI_CONFIG: ${{matrix.config.multi_config}}
steps:
- name: Add msbuild to PATH
uses: microsoft/[email protected]
Expand All @@ -57,6 +60,10 @@ jobs:
if: matrix.config.msvc_version >= 16
shell: bash
run: echo "ADDITIONAL_CMAKE_ARGS=$ADDITIONAL_CMAKE_ARGS -A x64" >> $GITHUB_ENV
- name: set-fruit-allow-multi-config
if: matrix.config.multi_config
shell: bash
run: echo "ADDITIONAL_CMAKE_ARGS=$ADDITIONAL_CMAKE_ARGS -DFRUIT_ALLOW_MULTI_CONFIG=True" >> $GITHUB_ENV
- uses: actions/checkout@v3
- name: install
shell: cmd
Expand Down
74 changes: 44 additions & 30 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,21 @@ if(NOT "${CMAKE_BUILD_TYPE}" MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel)
message(FATAL_ERROR "Please re-run CMake, specifying -DCMAKE_BUILD_TYPE=Debug , -DCMAKE_BUILD_TYPE=Release , -DCMAKE_BUILD_TYPE=RelWithDebInfo or -DCMAKE_BUILD_TYPE=MinSizeRel .")
endif()

option(BUILD_SHARED_LIBS "Build shared library" ON)
option(FRUIT_ALLOW_MULTI_CONFIG "Allow multi-configuration generator. If this option is OFF, enforces that a single configuration is used." OFF)
if(FRUIT_ALLOW_MULTI_CONFIG)
if(GENERATOR_IS_MULTI_CONFIG)
message(STATUS "${CMAKE_PROJECT_NAME} supports the CMake multi-configuration generator,"
" but is optimized for the `CMAKE_BUILD_TYPE` specified in the CMake configuration step,"
" and tests will only work in this configuration.")
endif()
else()
# For backward compatibility, only `CMAKE_BUILD_TYPE` configurations can be
# used with the multi-configuration generator. This makes it look like
# single-configuration generator.
set(CMAKE_CONFIGURATION_TYPES "${CMAKE_BUILD_TYPE}")
endif()

# The Visual Studio CMake generators default to multiple configurations, but Fruit doesn't support multi-configuration build directories.
set(CMAKE_CONFIGURATION_TYPES "${CMAKE_BUILD_TYPE}")
option(BUILD_SHARED_LIBS "Build shared library" ON)

set(FRUIT_ADDITIONAL_CXX_FLAGS "" CACHE STRING "Additional CXX compiler flags." FORCE)

Expand All @@ -43,23 +54,34 @@ if(NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "^(GNU|Clang|AppleClang|MSVC)$")
endif()

option(FRUIT_ADD_WNO_UNKNOWN_WARNING_OPTION "Add -Wno-unknown-warning-option to the compiler options for GCC, Clang, ICC and AppleClang" ON)

if("${CMAKE_CXX_COMPILER_ID}" MATCHES "^(GNU|Clang|Intel|AppleClang)$")
set(FRUIT_ADDITIONAL_COMPILE_FLAGS "${FRUIT_ADDITIONAL_COMPILE_FLAGS} -std=c++11 -W -Wall -Wno-missing-braces")
if(${FRUIT_ADD_WNO_UNKNOWN_WARNING_OPTION})
set(FRUIT_ADDITIONAL_COMPILE_FLAGS "${FRUIT_ADDITIONAL_COMPILE_FLAGS} -Wno-unknown-warning-option")
endif()
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "^(MSVC)$")
# TODO: we currently disable the warning C4709 because MSVC emits it even when there is no reason to. Re-enable it when possible.
# TODO: the warning C4141 is disabled, because MSVC emits it ("'inline': used more than once") when a function/method is marked with both __forceinline and inline.
# TODO: the warning C4714 is disabled, MSVC emits it when it decides not to inline a __forceinline function/method.
# The warning C4577 is disabled because we don't need a termination guarantee on exceptions for functions marked with
# 'noexcept'.
# The warning C4530 is disabled because it's triggered by MSVC's STL.
# The warning C5205 is disabled, MSVC emits it for abstract classes in example code with non-virtual destructors, but we never call delete on those (even though std::default_delete<Scaler> is instantiated for those types).
set(FRUIT_ADDITIONAL_COMPILE_FLAGS "${FRUIT_ADDITIONAL_COMPILE_FLAGS} /nologo /FS /W4 /wd4324 /wd4709 /wd4459 /wd4141 /wd4714 /wd4577 /wd4530 /wd5205 /D_SCL_SECURE_NO_WARNINGS")
if (${FRUIT_ADD_WNO_UNKNOWN_WARNING_OPTION})
set(FRUIT_NO_UNKNOWN_WARNING_FLAGS -Wno-unknown-warning-option)
endif()

# Get C++ standard flags.
set(FRUIT_CXX_STANDARD_FLAGS ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION})

set(FRUIT_ADDITIONAL_COMPILE_FLAGS_GNU -W -Wall -Wno-missing-braces ${FRUIT_NO_UNKNOWN_WARNING_FLAGS})
set(FRUIT_ADDITIONAL_COMPILE_FLAGS_Clang -W -Wall -Wno-missing-braces ${FRUIT_NO_UNKNOWN_WARNING_FLAGS})
set(FRUIT_ADDITIONAL_COMPILE_FLAGS_Intel -W -Wall -Wno-missing-braces ${FRUIT_NO_UNKNOWN_WARNING_FLAGS})
set(FRUIT_ADDITIONAL_COMPILE_FLAGS_AppleClang -W -Wall -Wno-missing-braces ${FRUIT_NO_UNKNOWN_WARNING_FLAGS})

# TODO: we currently disable the warning C4709 because MSVC emits it even when there is no reason to. Re-enable it when possible.
# TODO: the warning C4141 is disabled, because MSVC emits it ("'inline': used more than once") when a function/method is marked with both __forceinline and inline.
# TODO: the warning C4714 is disabled, MSVC emits it when it decides not to inline a __forceinline function/method.
# The warning C4577 is disabled because we don't need a termination guarantee on exceptions for functions marked with
# 'noexcept'.
# The warning C4530 is disabled because it's triggered by MSVC's STL.
# The warning C5205 is disabled, MSVC emits it for abstract classes in example code with non-virtual destructors, but we never call delete on those (even though std::default_delete<Scaler> is instantiated for those types).
set(FRUIT_ADDITIONAL_COMPILE_FLAGS_MSVC /nologo /FS /W4 /wd4324 /wd4709 /wd4459 /wd4141 /wd4714 /wd4577 /wd4530 /wd5205 /D_SCL_SECURE_NO_WARNINGS)

list(APPEND FRUIT_ADDITIONAL_COMPILE_FLAGS
$<$<CXX_COMPILER_ID:GNU>:${FRUIT_ADDITIONAL_COMPILE_FLAGS_GNU}>
$<$<CXX_COMPILER_ID:Clang>:${FRUIT_ADDITIONAL_COMPILE_FLAGS_Clang}>
$<$<CXX_COMPILER_ID:Intel>:${FRUIT_ADDITIONAL_COMPILE_FLAGS_Intel}>
$<$<CXX_COMPILER_ID:AppleClang>:${FRUIT_ADDITIONAL_COMPILE_FLAGS_AppleClang}>
$<$<CXX_COMPILER_ID:MSVC>:${FRUIT_ADDITIONAL_COMPILE_FLAGS_MSVC}>)

option(FRUIT_ENABLE_COVERAGE "Enable collection of test coverage. This is meant to be used by Fruit developers. It's only supported when using GCC on Linux." OFF)
if("${FRUIT_ENABLE_COVERAGE}")
# We also disable exceptions because otherwise GCC considers every function/method call that could throw as an
Expand All @@ -80,9 +102,7 @@ if(${FRUIT_USES_BOOST})
endif()

find_package(Boost)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
else()
if(NOT Boost_FOUND)
message(FATAL_ERROR "Please re-run CMake, specifying the boost library path as Boost_INCLUDE_DIR, e.g. -DBoost_INCLUDE_DIR=C:\\boost\\boost_1_62_0, or specify -DFRUIT_USES_BOOST=False to not use boost.")
endif()
endif()
Expand All @@ -95,17 +115,10 @@ endif()
# Unsafe, only for debugging/benchmarking.
#set(FRUIT_ADDITIONAL_COMPILE_FLAGS "${FRUIT_ADDITIONAL_COMPILE_FLAGS} -DFRUIT_NO_LOOP_CHECK=1")

add_definitions(${FRUIT_ADDITIONAL_COMPILE_FLAGS})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FRUIT_ADDITIONAL_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FRUIT_ADDITIONAL_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FRUIT_ADDITIONAL_LINKER_FLAGS}")

if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
set(FRUIT_COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE} ${FRUIT_ADDITIONAL_COMPILE_FLAGS}")
else()
set(FRUIT_COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG} ${FRUIT_ADDITIONAL_COMPILE_FLAGS}")
endif()

set(FRUIT_CLANG_TIDY_CHECKS
bugprone*,-bugprone-reserved-identifier,-bugprone-exception-escape,clang-analyzer*,performance*,google*,-google-readability*,-google-runtime-references,clang-diagnostic-unused-command-line-argument,misc-macro-parentheses,-clang-diagnostic-dtor-name)

Expand All @@ -118,8 +131,9 @@ if(${FRUIT_ENABLE_CLANG_TIDY})
-warnings-as-errors=*;)
endif()

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
set(FRUIT_INCLUDE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_BINARY_DIR}/include")

# (debug-only) compile switch to get deep template instantiation stacktraces for errors (instead
# of the user-friendly default that hides Fruit internals).
Expand Down
23 changes: 22 additions & 1 deletion configuration/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@

include(CheckCXXSourceCompiles)

set(CMAKE_REQUIRED_FLAGS "${FRUIT_COMPILE_FLAGS}")
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
set(FRUIT_ADDITIONAL_REQUIRED_FLAG_LIST ${FRUIT_ADDITIONAL_COMPILE_FLAGS_GNU})
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "^Clang$")
set(FRUIT_ADDITIONAL_REQUIRED_FLAG_LIST ${FRUIT_ADDITIONAL_COMPILE_FLAGS_Clang})
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel")
set(FRUIT_ADDITIONAL_REQUIRED_FLAG_LIST ${FRUIT_ADDITIONAL_COMPILE_FLAGS_Intel})
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang")
set(FRUIT_ADDITIONAL_REQUIRED_FLAG_LIST ${FRUIT_ADDITIONAL_COMPILE_FLAGS_AppleClang})
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC")
set(FRUIT_ADDITIONAL_REQUIRED_FLAG_LIST ${FRUIT_ADDITIONAL_COMPILE_FLAGS_MSVC})
endif()

# `CMAKE_REQUIRED_FLAGS` does not accept variables of type list, convert to string.
foreach(FRUIT_ADDITIONAL_REQUIRED_FLAG_LIST_ITEM IN LISTS FRUIT_ADDITIONAL_REQUIRED_FLAG_LIST)
set(FRUIT_ADDITIONAL_REQUIRED_FLAGS "${FRUIT_ADDITIONAL_REQUIRED_FLAGS} ${FRUIT_ADDITIONAL_REQUIRED_FLAG_LIST_ITEM}")
endforeach()

if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
set(CMAKE_REQUIRED_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE} ${FRUIT_ADDITIONAL_REQUIRED_FLAGS} ${FRUIT_CXX_STANDARD_FLAGS}")
else()
set(CMAKE_REQUIRED_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG} ${FRUIT_ADDITIONAL_REQUIRED_FLAGS} ${FRUIT_CXX_STANDARD_FLAGS}")
endif()

CHECK_CXX_SOURCE_COMPILES("
int main() {}
Expand Down
2 changes: 1 addition & 1 deletion extras/scripts/postsubmit.bat
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ IF "%CMAKE_GENERATOR%"=="MinGW Makefiles" (
mingw32-make -j12 || exit /b 1
) ELSE (
type ALL_BUILD.vcxproj
msbuild ALL_BUILD.vcxproj || exit /b 1
msbuild ALL_BUILD.vcxproj /p:Configuration=%CONFIGURATION% || exit /b 1
)

pip3 install absl-py
Expand Down
40 changes: 23 additions & 17 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@

set(FRUIT_SOURCES
memory_pool.cpp
binding_normalization.cpp
demangle_type_name.cpp
component.cpp
fixed_size_allocator.cpp
injector_storage.cpp
normalized_component_storage.cpp
normalized_component_storage_holder.cpp
semistatic_map.cpp
semistatic_graph.cpp)
memory_pool.cpp
binding_normalization.cpp
demangle_type_name.cpp
component.cpp
fixed_size_allocator.cpp
injector_storage.cpp
normalized_component_storage.cpp
normalized_component_storage_holder.cpp
semistatic_map.cpp
semistatic_graph.cpp)

if("${BUILD_SHARED_LIBS}")
if(BUILD_SHARED_LIBS)
add_library(fruit SHARED ${FRUIT_SOURCES})

if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set_target_properties(fruit PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
endif()
set_target_properties(fruit PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
else()
add_library(fruit STATIC ${FRUIT_SOURCES})
endif()

target_include_directories(fruit PUBLIC ${FRUIT_INCLUDE_DIRS})
target_compile_options(fruit PUBLIC ${FRUIT_ADDITIONAL_COMPILE_FLAGS})

if(FRUIT_USES_BOOST)
find_package(Boost REQUIRED)
target_include_directories(fruit PRIVATE ${Boost_INCLUDE_DIRS})
endif()

install(TARGETS fruit
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
2 changes: 1 addition & 1 deletion tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ genrule(
+ "CXX='$(CC)'\n"
+ "CXX_COMPILER_NAME='GNU'\n"
+ "CXX_COMPILER_VERSION='5.0.0'\n"
+ "FRUIT_COMPILE_FLAGS='$(CC_FLAGS) -std=c++0x -W -Wall -Wno-missing-braces -g -Werror'\n"
+ "FRUIT_TEST_COMPILE_FLAGS='$(CC_FLAGS) -std=c++0x -W -Wall -Wno-missing-braces -g -Werror'\n"
+ "ADDITIONAL_INCLUDE_DIRS=''\n"
+ "CMAKE_BUILD_TYPE=None\n"
+ "PATH_TO_COMPILED_FRUIT='third_party/fruit/tests'\n"
Expand Down
Loading

0 comments on commit 9beae9f

Please sign in to comment.