How to alter OSX_DEPLOYMENT_TARGET for a specific target in CMake for xcode project - cmake

For make project, the below minimal example will allow me to alter OSX_DEPLOYMENT_TARGET for a specific target successfully:
set(CMAKE_OSX_DEPLOYMENT_TARGET
"11.0"
CACHE STRING "osx deployment target")
# the osx deployment target of mylib is 11.0
add_subdirectory(mylib)
# but one of the external library the test links to is built with 12.0, so I want the test to be compiled with 12.0
find_package(external)
set_property(
TARGET external
APPEND
PROPERTY INTERFACE_COMPILE_OPTIONS -mmacosx-version-min=12.0
PROPERTY INTERFACE_LINK_OPTIONS -mmacosx-version-min=12.0)
add_executable(mytest main.cpp)
target_link_libraries(mytest PUBLIC mylibs external)
However, for xcode project, the OSX_DEPLOYMENT_TARGET is controlled by -target x86_64-apple-macos12.0 and -target arm64-apple-macos12.0. mytest is a universal binary with x86_64 and arm64, and I am having difficulties to figure out how to pass -target x86_64-apple-macos12.0 to the x86_64 slice and -target arm64-apple-macos12.0 to the arm64 slice in cmake. My best attempt looks like the below:
set_property(
TARGET external
APPEND
PROPERTY
INTERFACE_COMPILE_OPTIONS
-target
$<$<STREQUAL:$<TARGET_PROPERTY:OSX_ARCHITECTURES>,x86_64:x86_64-apple-macos12.0>>
$<$<STREQUAL:$<TARGET_PROPERTY:OSX_ARCHITECTURES>,arm64:arm64-apple-macos12.0>>
PROPERTY
INTERFACE_LINK_OPTIONS
-target
$<$<STREQUAL:$<TARGET_PROPERTY:OSX_ARCHITECTURES>,x86_64:x86_64-apple-macos12.0>>
$<$<STREQUAL:$<TARGET_PROPERTY:OSX_ARCHITECTURES>,arm64:arm64-apple-macos12.0>>
)
but unfortunately this doesn't work. A more general question is that how can I pass in different compilation flags when compiling different archs?

You seem to be looking for CMAKE_OSX_ARCHITECTURES:
cmake ... -DCMAKE_OSX_ARCHITECTURES=arm64
or
set(CMAKE_OSX_ARCHITECTURES arm64)
how can I pass in different compilation flags when compiling different archs?
Xcode/xcodebuild can't do it. You have to build single arch targets and merge them with lipo -create -output universal_app x86_app arm_app.

I found the answer from https://github.com/eyalamirmusic/JUCECmakeRepoPrototype/issues/5#issuecomment-747082201.
It's set_target_properties(mytest PROPERTIES XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET 12.0)

Related

CMake TARGET_RUNTIME_DLLS is empty

I have git cloned, built (with MSVC for both Debug and Release) and then installed wxWidgets:
cmake -B build wxWidgets
cmake --build build --config <CONFIG>
cmake --install build --prefix my_install --config <CONFIG>
with <CONFIG> = Debug and <CONFIG> = Release.
Then I used the following CMake script to link against it, as suggested by the wiki:
cmake_minimum_required(VERSION 3.16)
project(Test)
add_executable(Test WIN32 Main.cpp)
# wxWidgets
SET(wxWidgets_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../thirdparty/my_install)
find_package(wxWidgets COMPONENTS core base REQUIRED)
include(${wxWidgets_USE_FILE})
target_link_libraries(Test PRIVATE ${wxWidgets_LIBRARIES})
# Copy runtime DLLs to the directory of the executable.
add_custom_command(TARGET Test POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Runtime Dlls: $<TARGET_RUNTIME_DLLS:Test>"
)
My goal is to automatically copy the DLLs into the directory of the built executable, so that they can be found at runtime. For that I'm using the TARGET_RUNTIME_DLLS generator expression (follwing the sample code in the docs). In the code above, I only print out the expression at build time for testing purposes. The problem is that it is empty.
The approach worked for me before when installing and linking SDL, but SDL provides package configuration files which create imported targets, defining the DLL location(s) via IMPORTED_LOCATION_RELEASE or IMPORTED_LOCATION_DEBUG. For wxWidgets one is apparently supposed to use the FindwxWidgets.cmake script shipped with CMake, which sadly doesn't define the produced binaries. Maybe that's why TARGET_RUNTIME_DLLS isn't populated.
Does anyone know, either how to get TARGET_RUNTIME_DLLS filled or how to obtain the list of built wxWidgets DLLs for the current configuration (Release/Debug) post build copying?
Thanks a lot in advance!
I am dealing with a similar problem.
First sanity checks:
You have to work on windows platform otherwise this feature does not
work.
Your Cmake is 3.21 or above
Next comes fuzzy part. I think the library that you are trying to include have to be a Shared Imported library and you have to set a set_target_properties for IMPORTED_IMPLIB which is a path to a .lib file of sort (dll import library, I think it is called) So you have to make sure that it is all set in the package library that you trying to link with your executable.
If you have those dll avaiable and you just want to use them and not actually build them then you can write your own cmake script that will do just what I said above. Then you can include that cmake file in your project and then link against your app.
Note: I also work on similar issue right now and what I just said have not been working very reliably. I got some dlls to be copied and some do not.
Edit:
Cmake docs give a more detailed explanation on how this library setting should look like if you use find_package feature.
Found here: https://cmake.org/cmake/help/latest/command/add_library.html#imported-libraries
An UNKNOWN library type is typically only used in the implementation
of Find Modules. It allows the path to an imported library (often
found using the find_library() command) to be used without having to
know what type of library it is. This is especially useful on Windows
where a static library and a DLL's import library both have the same
file extension.

Building a rust library through CMake and using it as imported library target

I'm restucturing the CMake based build of a cross platform (macOS/Windows, Linux should be added soon) C++ project that has a third party rust library as dependendcy. Until now the rust lib dependency was supplied as precompiled library but I want to make its compilation part of my CMake build.
I got it working on macOS using the CMake makefile exporter by referencing the compiled library as a static imported library target and setting up a custom target with the command to build the rust library through cargo like this
add_library (rustlib STATIC IMPORTED)
add_custom_target (rustlib_cargo
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/Ext/rustlib/c-api
COMMAND cargo rustc --release -- --crate-type staticlib)
# Note: RUSTLIB_OUTPUT is set above refering to the absolute path of the produced platform specific library
set_target_properties (rustlib PROPERTIES IMPORTED_LOCATION ${RUSTLIB_OUTPUT})
add_dependencies (rustlib rustlib_cargo)
On macOS the cargo rustc command is invoked before the targets that link against my rustlib target are built and in case the rust library has been built previously this is detected by cargo and it just skips that compilation steph. But on Windows this fails with the built-in ninja exporter of Microsoft Visual Studio 2019 with an error like this:
ninja : error : '../../../Ext/rustlib/target/release/deps/rustlib.lib', needed by 'SomeTargetLinkingAgainstRustlib', missing and no known rule to make it
If I remove the line set_target_properties (rustlib PROPERTIES IMPORTED_LOCATION ${RUSTLIB_OUTPUT}) the build starts correctly, the rust build gets triggered, but as expected I end up with a linker error as the library to link against is not found. So is there any way to refer to a file that is not existent at configuration time but is guranteed to be created during compilation?

Launch host and target crosscompiling builds inside CMake

Is there a way to configure CMake such that a single make command will launch both host and target builds? I have a project that is meant to be run on a target platform but requires some generated data from a generator that needs to run on the host platform (PC). From CMake's documentation and looking around, I need a 2 pass build - first host to create the generator then the target crosscompiling build. My question is specifically how to launch the 2-pass build with a single make command through CMake configurations (not using an external bash or python script).
Things I know
CMake doesn't allow changing toolchain within a single build
Almost solutions like: How to instruct CMake to use the build architecture compiler? Which is fine except I need to skip the 2nd step of using an external script
How to separate what's run during crosscompiling or not cmake - compile natively and crosscompile the same code
It is supposedly possible to launch multiple CMake builds using CMake How to make CMake targeting multiple plattforms in a single build
Turning my comment into an answer
Let's say you have an buildTool sub-directory for the host build tools:
buildTools\CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(BuildTools)
add_executable(genfoo genfoo.cpp)
Then you could have a main:
CMakeLists.txt
if (CMAKE_CROSSCOMPILING)
set(_genfoo "bin/genfoo${CMAKE_EXECUTABLE_SUFFIX}")
add_custom_command(
OUTPUT ${_genfoo}
COMMAND ${CMAKE_COMMAND}
-DCMAKE_BUILD_TYPE:STRING="Release"
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE:PATH="${CMAKE_BINARY_DIR}/bin"
-B"bin"
-H"${CMAKE_SOURCE_DIR}/buildTools"
COMMAND ${CMAKE_COMMAND} --build bin --config Release
)
else()
set(_genfoo genfoo)
add_subdirectory(buildTools)
endif()
add_custom_command(
OUTPUT foo.h
COMMAND ${_genfoo}
DEPENDS ${_genfoo}
)
add_executable(bar bar.cpp foo.h)
target_include_directories(bar PRIVATE ${CMAKE_BINARY_DIR})
References
How to instruct CMake to use the build architecture compiler?

Building shared libraries with cmake with option -Wl,--no-undefined

I'm trying to create a ndk library using android-cmake.
My target here is a shared library and build fails because of option
-Wl,--no-undefined
As the targets refers symbols from another library.
Is there a way to the missing library to the command
add_library(foo SHARED ${sources})
I was able to build by changing cmake variable
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L<path to library> -lfoo")

How do I tell CMake to link in a static library in the source directory?

I have a small project with a Makefile which I'm trying to convert to CMake, mostly just to get experience with CMake. For purposes of this example, the project contains a source file (C++, though I don't think the language is particularly relevant) and a static library file which I've copied from elsewhere. Assume for argument's sake that the source code to the library is unavailable; I only have the .a file and the corresponding header.
My handmade Makefile contains this build rule:
main: main.o libbingitup.a
g++ -o main main.o libbingitup.a
which works fine. How do I tell CMake to reproduce this? Not literally this exact makefile, of course, but something that includes an equivalent linking command. I've tried the obvious but naive ways, like
add_executable(main main.cpp libbingitup.a)
or
add_executable(main main.cpp)
target_link_libraries(main libbingitup.a)
as well as various things with link_directories(.) or add_library(bingitup STATIC IMPORTED) etc. but nothing so far that results in a successful linkage. What should I be doing?
Version details: CMake 2.8.7 on Linux (Kubuntu 12.04) with GCC 4.6.3
CMake favours passing the full path to link libraries, so assuming libbingitup.a is in ${CMAKE_SOURCE_DIR}, doing the following should succeed:
add_executable(main main.cpp)
target_link_libraries(main ${CMAKE_SOURCE_DIR}/libbingitup.a)
If you don't want to include the full path, you can do
add_executable(main main.cpp)
target_link_libraries(main bingitup)
bingitup is the same name you'd give a target if you create the static library in a CMake project:
add_library(bingitup STATIC bingitup.cpp)
CMake automatically adds the lib to the front and the .a at the end on Linux, and .lib at the end on Windows.
If the library is external, you might want to add the path to the library using
link_directories(/path/to/libraries/)
I found this helpful...
http://www.cmake.org/pipermail/cmake/2011-June/045222.html
From their example:
ADD_LIBRARY(boost_unit_test_framework STATIC IMPORTED)
SET_TARGET_PROPERTIES(boost_unit_test_framework PROPERTIES IMPORTED_LOCATION /usr/lib/libboost_unit_test_framework.a)
TARGET_LINK_LIBRARIES(mytarget A boost_unit_test_framework C)
I want to add to the other comments, the project name is the first argument. I had a project called cmakecompile and i wanted to add libusb to it, the code is as follows,
add_executable(cmakecompile main.c)
target_link_libraries(cmakecompile "D:/msys2/mingw64/lib/libusb-1.0.a")
the project had just only a main.c file, the first parameter in target_link_libraries is the name of your project and the second parameter is the path of the library.
Note that may help: Since i am compiling under windows, i had to install msys2 because the library you have has to be compiled with the same compiler. For example if you get libusb and try to use it in a qt-creator project, it will not work and you may get unreferenced functions, therefore i had to install msys2 and install libusb from inside msys2, install make and create a QT Cmake project and compile from Qt creator using the msys2 make.
The full cmakelists.txt is as follow
cmake_minimum_required(VERSION 3.5)
project(cmakecompile LANGUAGES C)
add_executable(cmakecompile main.c)
target_link_libraries(cmakecompile "D:/msys2/mingw64/lib/libusb-1.0.a")