From 70bfa5ae1a5bb71d25769456cb6686c46f4176a1 Mon Sep 17 00:00:00 2001 From: Martijn Otto Date: Wed, 2 Feb 2022 17:30:27 +0100 Subject: [PATCH] Introduce split build for osx ports without universal builds Some ports (e.g. libpng) don't support building for multiple architectures at the same time. For these ports, we can now use the OSX_SPLIT_BUILD option, which will perform multiple builds (one for each requested architecture) and then merge them into a universal binary when the build is complete --- .../ports/vcpkg-cmake/vcpkg_cmake_install.md | 1 + ports/vcpkg-cmake/vcpkg.json | 2 +- ports/vcpkg-cmake/vcpkg_cmake_build.cmake | 61 +++++++++---- ports/vcpkg-cmake/vcpkg_cmake_configure.cmake | 87 ++++++++++++++++++- ports/vcpkg-cmake/vcpkg_cmake_install.cmake | 64 ++++++++++++++ versions/baseline.json | 2 +- versions/v-/vcpkg-cmake.json | 5 ++ 7 files changed, 200 insertions(+), 22 deletions(-) diff --git a/docs/maintainers/ports/vcpkg-cmake/vcpkg_cmake_install.md b/docs/maintainers/ports/vcpkg-cmake/vcpkg_cmake_install.md index 1d708d3a1300d5..5d7a1bc2909ff7 100644 --- a/docs/maintainers/ports/vcpkg-cmake/vcpkg_cmake_install.md +++ b/docs/maintainers/ports/vcpkg-cmake/vcpkg_cmake_install.md @@ -15,6 +15,7 @@ vcpkg_cmake_install( with additional parameters to set the `TARGET` to `install`, and to set the `LOGFILE_ROOT` to `install` as well. + [`vcpkg_cmake_build()`]: vcpkg_cmake_build.md ## Examples: diff --git a/ports/vcpkg-cmake/vcpkg.json b/ports/vcpkg-cmake/vcpkg.json index 6ffadbbcee966b..aac305fd264544 100644 --- a/ports/vcpkg-cmake/vcpkg.json +++ b/ports/vcpkg-cmake/vcpkg.json @@ -1,6 +1,6 @@ { "name": "vcpkg-cmake", - "version-date": "2022-07-18", + "version-date": "2022-08-01", "documentation": "https://vcpkg.io/en/docs/maintainers/ports/vcpkg-cmake.html", "license": "MIT" } diff --git a/ports/vcpkg-cmake/vcpkg_cmake_build.cmake b/ports/vcpkg-cmake/vcpkg_cmake_build.cmake index efdb194fa173b7..7b0d76eb8c63ba 100644 --- a/ports/vcpkg-cmake/vcpkg_cmake_build.cmake +++ b/ports/vcpkg-cmake/vcpkg_cmake_build.cmake @@ -62,25 +62,50 @@ function(vcpkg_cmake_build) endif() endif() - if(arg_DISABLE_PARALLEL) - vcpkg_execute_build_process( - COMMAND - "${CMAKE_COMMAND}" --build . --config "${config}" ${target_param} - -- ${build_param} ${no_parallel_param} - WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${short_build_type}" - LOGNAME "${arg_LOGFILE_BASE}-${TARGET_TRIPLET}-${short_build_type}" - ) + if (Z_VCPKG_OSX_SPLIT_BUILD) + foreach(OSX_ARCHITECTURE ${VCPKG_OSX_ARCHITECTURES}) + if (arg_DISABLE_PARALLEL) + vcpkg_execute_build_process( + COMMAND + "${CMAKE_COMMAND}" --build . --config "${config}" ${target_param} + -- ${build_param} ${no_parallel_param} + WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${short_build_type}-${OSX_ARCHITECTURE}" + LOGNAME "${arg_LOGFILE_BASE}-${TARGET_TRIPLET}-${short_build_ttype}-${OSX_ARCHITECTURE}" + ) + else() + vcpkg_execute_build_process( + COMMAND + "${CMAKE_COMMAND}" --build . --config "${config}" ${target_param} + -- ${build_param} ${parallel_param} + NO_PARALLEL_COMMAND + "${CMAKE_COMMAND}" --build . --config "${config}" ${target_param} + -- ${build_param} ${no_parallel_param} + WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${short_build_type}-${OSX_ARCHITECTURE}" + LOGNAME "${arg_LOGFILE_BASE}-${TARGET_TRIPLET}-${short_build_type}-${OSX_ARCHITECTURE}" + ) + endif() + endforeach() else() - vcpkg_execute_build_process( - COMMAND - "${CMAKE_COMMAND}" --build . --config "${config}" ${target_param} - -- ${build_param} ${parallel_param} - NO_PARALLEL_COMMAND - "${CMAKE_COMMAND}" --build . --config "${config}" ${target_param} - -- ${build_param} ${no_parallel_param} - WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${short_build_type}" - LOGNAME "${arg_LOGFILE_BASE}-${TARGET_TRIPLET}-${short_build_type}" - ) + if(arg_DISABLE_PARALLEL) + vcpkg_execute_build_process( + COMMAND + "${CMAKE_COMMAND}" --build . --config "${config}" ${target_param} + -- ${build_param} ${no_parallel_param} + WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${short_build_type}" + LOGNAME "${arg_LOGFILE_BASE}-${TARGET_TRIPLET}-${short_build_type}" + ) + else() + vcpkg_execute_build_process( + COMMAND + "${CMAKE_COMMAND}" --build . --config "${config}" ${target_param} + -- ${build_param} ${parallel_param} + NO_PARALLEL_COMMAND + "${CMAKE_COMMAND}" --build . --config "${config}" ${target_param} + -- ${build_param} ${no_parallel_param} + WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${short_build_type}" + LOGNAME "${arg_LOGFILE_BASE}-${TARGET_TRIPLET}-${short_build_type}" + ) + endif() endif() if(arg_ADD_BIN_TO_PATH) diff --git a/ports/vcpkg-cmake/vcpkg_cmake_configure.cmake b/ports/vcpkg-cmake/vcpkg_cmake_configure.cmake index 723fd2ecf81311..3f70c7f27974a4 100644 --- a/ports/vcpkg-cmake/vcpkg_cmake_configure.cmake +++ b/ports/vcpkg-cmake/vcpkg_cmake_configure.cmake @@ -10,7 +10,7 @@ endmacro() function(vcpkg_cmake_configure) cmake_parse_arguments(PARSE_ARGV 0 "arg" - "PREFER_NINJA;DISABLE_PARALLEL_CONFIGURE;WINDOWS_USE_MSBUILD;NO_CHARSET_FLAG;Z_CMAKE_GET_VARS_USAGE" + "PREFER_NINJA;DISABLE_PARALLEL_CONFIGURE;WINDOWS_USE_MSBUILD;NO_CHARSET_FLAG;Z_CMAKE_GET_VARS_USAGE;OSX_SPLIT_BUILD" "SOURCE_PATH;GENERATOR;LOGFILE_BASE" "OPTIONS;OPTIONS_DEBUG;OPTIONS_RELEASE;MAYBE_UNUSED_VARIABLES" ) @@ -180,12 +180,28 @@ function(vcpkg_cmake_configure) ) # Sets configuration variables for macOS builds - foreach(config_var IN ITEMS INSTALL_NAME_DIR OSX_DEPLOYMENT_TARGET OSX_SYSROOT OSX_ARCHITECTURES) + foreach(config_var IN ITEMS INSTALL_NAME_DIR OSX_DEPLOYMENT_TARGET OSX_SYSROOT) if(DEFINED VCPKG_${config_var}) vcpkg_list(APPEND arg_OPTIONS "-DCMAKE_${config_var}=${VCPKG_${config_var}}") endif() endforeach() + # if a split build was requested we must perform two separate builds + # if - and only if - multiple architectures were passed + if (arg_OSX_SPLIT_BUILD) + list(LENGTH VCPKG_OSX_ARCHITECTURES ARCHITECTURE_LENGTH) + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin" AND ARCHITECTURE_LENGTH GREATER_EQUAL "2") + set(Z_VCPKG_OSX_SPLIT_BUILD ON CACHE INTERNAL "split build per architecture") + endif() + endif() + + # if we are not doing a split build we define the architectures, otherwise + # they will be defined individually for each separete split build + if (NOT Z_VCPKG_OSX_SPLIT_BUILD AND DEFINED VCPKG_OSX_ARCHITECTURES) + list(JOIN VCPKG_OSX_ARCHITECTURES "\;" JOINED_ARCHITECTURES) + list(APPEND arg_OPTIONS "-DCMAKE_OSX_ARCHITECTURES=${JOINED_ARCHITECTURES}") + endif() + # Allow overrides / additional configuration variables from triplets if(DEFINED VCPKG_CMAKE_CONFIGURE_OPTIONS) vcpkg_list(APPEND arg_OPTIONS ${VCPKG_CMAKE_CONFIGURE_OPTIONS}) @@ -245,6 +261,73 @@ function(vcpkg_cmake_configure) vcpkg_list(APPEND config_logs "${CURRENT_BUILDTREES_DIR}/${arg_LOGFILE_BASE}-out.log" "${CURRENT_BUILDTREES_DIR}/${arg_LOGFILE_BASE}-err.log") + elseif(Z_VCPKG_OSX_SPLIT_BUILD) + foreach(OSX_ARCHITECTURE ${VCPKG_OSX_ARCHITECTURES}) + file(REMOVE_RECURSE + "${build_dir_release}-${OSX_ARCHITECTURE}" + "${build_dir_debug}-${OSX_ARCHITECTURE}") + file(MAKE_DIRECTORY "${build_dir_release}-${OSX_ARCHITECTURE}") + if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + file(MAKE_DIRECTORY "${build_dir_debug}-${OSX_ARCHITECTURE}") + endif() + endforeach() + + # the first selected architecture is installed in the usual location + # (the packages dir), the others are installed into the buildtree + # because the package install would otherwise overwrite the generated + # libraries, after installation the binaries will be merged + set(OSX_SPLIT_BUILD_FIRST_ARCHITECTURE ON) + + foreach(OSX_ARCHITECTURE ${VCPKG_OSX_ARCHITECTURES}) + if (OSX_SPLIT_BUILD_FIRST_ARCHITECTURE) + set(OSX_SPLIT_BUILD_INSTALL_DIR_DEBUG "${CURRENT_PACKAGES_DIR}/debug") + set(OSX_SPLIT_BUILD_INSTALL_DIR_RELEASE "${CURRENT_PACKAGES_DIR}") + else() + set(OSX_SPLIT_BUILD_INSTALL_DIR_DEBUG "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${OSX_ARCHITECTURE}-dbg-install") + set(OSX_SPLIT_BUILD_INSTALL_DIR_RELEASE "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${OSX_ARCHITECTURE}-rel-install") + endif() + + if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + message(STATUS "${configuring_message}-dbg (arch: ${OSX_ARCHITECTURE})") + vcpkg_execute_required_process( + COMMAND + "${CMAKE_COMMAND}" "${arg_SOURCE_PATH}" + -D CMAKE_OSX_ARCHITECTURES=${OSX_ARCHITECTURE} + ${arg_OPTIONS} + ${arg_OPTIONS_DEBUG} + -G "${generator}" + "-DCMAKE_BUILD_TYPE=Debug" + "-DCMAKE_INSTALL_PREFIX=${OSX_SPLIT_BUILD_INSTALL_DIR_DEBUG}" + WORKING_DIRECTORY "${build_dir_debug}-${OSX_ARCHITECTURE}" + LOGNAME "${arg_LOGFILE_BASE}-dbg-${OSX_ARCHITECTURE}" + ) + list(APPEND config_logs + "${CURRENT_BUILDTREES_DIR}/${arg_LOGFILE_BASE}-dbg-${OSX_ARCHITECTURE}-out.log" + "${CURRENT_BUILDTREES_DIR}/${arg_LOGFILE_BASE}-dbg-${OSX_ARCHITECTURE}-err.log") + endif() + + if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") + message(STATUS "${configuring_message}-rel (arch: ${OSX_ARCHITECTURE})") + vcpkg_execute_required_process( + COMMAND + "${CMAKE_COMMAND}" "${arg_SOURCE_PATH}" + -D CMAKE_OSX_ARCHITECTURES=${OSX_ARCHITECTURE} + ${arg_OPTIONS} + ${arg_OPTIONS_RELEASE} + -G "${generator}" + "-DCMAKE_BUILD_TYPE=Release" + "-DCMAKE_INSTALL_PREFIX=${OSX_SPLIT_BUILD_INSTALL_DIR_RELEASE}" + WORKING_DIRECTORY "${build_dir_release}-${OSX_ARCHITECTURE}" + LOGNAME "${arg_LOGFILE_BASE}-rel-${OSX_ARCHITECTURE}" + ) + list(APPEND config_logs + "${CURRENT_BUILDTREES_DIR}/${arg_LOGFILE_BASE}-rel-${OSX_ARCHITECTURE}-out.log" + "${CURRENT_BUILDTREES_DIR}/${arg_LOGFILE_BASE}-rel-${OSX_ARCHITECTURE}-err.log") + endif() + + # first architecture now complete + set(OSX_SPLIT_BUILD_FIRST_ARCHITECTURE OFF) + endforeach() else() if(NOT DEFINED VCPKG_BUILD_TYPE OR "${VCPKG_BUILD_TYPE}" STREQUAL "debug") message(STATUS "${configuring_message}-dbg") diff --git a/ports/vcpkg-cmake/vcpkg_cmake_install.cmake b/ports/vcpkg-cmake/vcpkg_cmake_install.cmake index 2bd8b4ea75ff35..b63e2d04906d77 100644 --- a/ports/vcpkg-cmake/vcpkg_cmake_install.cmake +++ b/ports/vcpkg-cmake/vcpkg_cmake_install.cmake @@ -18,4 +18,68 @@ function(vcpkg_cmake_install) LOGFILE_BASE install TARGET install ) + + # check whether a split build was requested and executed + if (Z_VCPKG_OSX_SPLIT_BUILD) + list(LENGTH VCPKG_OSX_ARCHITECTURES ARCHITECTURE_LENGTH) + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin" AND ${ARCHITECTURE_LENGTH} GREATER 1) + # if we performed a split build, we'll need to zip those up + # using the lipo tool, start by looking that up + find_program(LIPO_EXECUTABLE lipo REQUIRED) + + foreach(buildtype IN ITEMS debug release) + if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL buildtype) + if(buildtype STREQUAL "debug") + set(SHORT_BUILD_TYPE "dbg") + set(PACKAGE_DIR_SUFFIX "/debug") + else() + set(SHORT_BUILD_TYPE "rel") + set(PACKAGE_DIR_SUFFIX "") + endif() + + set(INSTALL_DIRECTORIES) + + foreach(OSX_ARCHITECTURE ${VCPKG_OSX_ARCHITECTURES}) + if (NOT INSTALL_DIRECTORIES) + set(INSTALL_DIRECTORY "${CURRENT_PACKAGES_DIR}${PACKAGE_DIR_SUFFIX}") + else() + set(INSTALL_DIRECTORY "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-${OSX_ARCHITECTURE}-${SHORT_BUILD_TYPE}-install") + endif() + + list(APPEND INSTALL_DIRECTORIES "${INSTALL_DIRECTORY}") + endforeach() + + # note: we cannot glob the library files in a single operation, due to a cmake + # bug in file globbing, a pattern like "*.{a,dylib}" does not work. + # also note that we are using the _last_ directory set, which is inside the + # buildtree, and not the normal packages directory, since that would likely + # also contain other installed libraries + file(GLOB_RECURSE STATIC_LIBS RELATIVE "${INSTALL_DIRECTORY}" "${INSTALL_DIRECTORY}/lib/*.a") + file(GLOB_RECURSE SHARED_LIBS RELATIVE "${INSTALL_DIRECTORY}" "${INSTALL_DIRECTORY}/lib/*.dylib") + file(GLOB_RECURSE EXECUTABLES RELATIVE "${INSTALL_DIRECTORY}" "${INSTALL_DIRECTORY}/bin/*") + + # filter out symlinks to get the real libraries to process + foreach (FOUND_LIBRARY ${STATIC_LIBS} ${SHARED_LIBS} ${EXECUTABLES}) + if (NOT IS_SYMLINK "${INSTALL_DIRECTORY}/${FOUND_LIBRARY}") + # now build the command to join the files + set(LIPO_ARGUMENTS "-create" "-output" "${CURRENT_PACKAGES_DIR}${PACKAGE_DIR_SUFFIX}/${FOUND_LIBRARY}") + + # add all architectures to the library + foreach (OSX_ARCHITECTURE ${VCPKG_OSX_ARCHITECTURES}) + list(POP_FRONT INSTALL_DIRECTORIES ARCH_INSTALL_DIRECTORY) + list(APPEND LIPO_ARGUMENTS "-arch" "${OSX_ARCHITECTURE}" "${ARCH_INSTALL_DIRECTORY}/${FOUND_LIBRARY}") + endforeach() + + # now join the found libraries + vcpkg_execute_required_process( + COMMAND ${LIPO_EXECUTABLE} ${LIPO_ARGUMENTS} + WORKING_DIRECTORY ${CURRENT_PACKAGES_DIR} + LOGNAME "lipo-${TARGET_TRIPLET}" + ) + endif() + endforeach() + endif() + endforeach() + endif() + endif() endfunction() diff --git a/versions/baseline.json b/versions/baseline.json index d87cd72ec1dce8..9a8daa3cbc2b68 100644 --- a/versions/baseline.json +++ b/versions/baseline.json @@ -7425,7 +7425,7 @@ "port-version": 0 }, "vcpkg-cmake": { - "baseline": "2022-07-18", + "baseline": "2022-08-01", "port-version": 0 }, "vcpkg-cmake-config": { diff --git a/versions/v-/vcpkg-cmake.json b/versions/v-/vcpkg-cmake.json index a329f1d02a5aa2..ef73cb1b107729 100644 --- a/versions/v-/vcpkg-cmake.json +++ b/versions/v-/vcpkg-cmake.json @@ -1,5 +1,10 @@ { "versions": [ + { + "git-tree": "73b8a4a2a1220d2f3d167e552fcb617f5cfdf9cb", + "version-date": "2022-08-01", + "port-version": 0 + }, { "git-tree": "a7b618b7782f3c841d7fd2d84a6ba3619815362a", "version-date": "2022-07-18",