CMake build fails with Xcode 12 and CMAKE_IOS_INSTALL_COMBINED=YES - cmake

EDIT This is a known CMake issue.
With Xcode 11 (specifically Xcode 11.2.1) I used to be able to cross-compile my project for iOS with this command:
cd /path/to/project
mkdir build
cd build
cmake .. -G Xcode -DCMAKE_SYSTEM_NAME=iOS \
"-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" \
-DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH=NO \
-DCMAKE_IOS_INSTALL_COMBINED=YES \
-DCMAKE_INSTALL_PREFIX=install
cmake --build . --config Release --target install
This created a build with two slices, one slice for the arm64 architecture (for running on a real device) and one slice for the x86_64 architecture (for running in a simulator on an Intel-based dev environment).
After upgrading to Xcode 12 (specifically Xcode 12.3) this no longer works. The build consistently fails with this error message (line break added by me):
error: unable to attach DB: error: accessing build database "/path/to/project/build/ios/build/XCBuildData/build.db":
database is locked Possibly there are two concurrent builds running in the same filesystem location.
The issue seems to be a post-build rule that CMake creates for the install target. In that post-build rule a second build is initiated while the first one is still in progress.
if test "$CONFIGURATION" = "Release"; then :
cd /path/to/project/build/ios
/usr/local/Cellar/cmake/3.19.2/bin/cmake -DBUILD_TYPE=$CONFIGURATION -DEFFECTIVE_PLATFORM_NAME=$EFFECTIVE_PLATFORM_NAME -P cmake_install.cmake
fi
The build succeeds when I no longer set CMAKE_IOS_INSTALL_COMBINED to YES, but then the resulting build only contains one slice (arm64 in my case, presumably because this is the first architecture that is listed in CMAKE_OSX_ARCHITECTURES).
I'm considering making a separate build for each architecture, and then stitching the slices together manually. Before I go down that road, has anyone been able to find a more elegant solution?
Environment: macOS 11.1, Xcode 12.3, CMake 3.19.2

The CMake 3.19 release notes contain this hint:
The Xcode generator now uses the Xcode “new build system” when generating for Xcode 12.0 or higher. See the CMAKE_XCODE_BUILD_SYSTEM variable. One may use -T buildsystem=1 to switch to the legacy build system.
The workaround, for the moment, is therefore to add the -T option to the build system generation command line:
cmake .. -G Xcode -T buildsystem=1
-DCMAKE_SYSTEM_NAME=iOS \
"-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" \
-DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH=NO \
-DCMAKE_IOS_INSTALL_COMBINED=YES \
-DCMAKE_INSTALL_PREFIX=install
This should work as long as Xcode still supports the legacy build system. The Xcode 12 Release Notes have this to say on the matter:
The legacy build system is deprecated, and will be removed in a future release. (62742902)
So the -T buildsystem=1 option can only be considered a temporary workaround.

Related

How to compile ClickHouse in CLion?

I'm trying to build ClickHouse in CLion.
I follow the official documentation. I was able to build ClickHouse from the command line, however, I would also like to be able to build it in CLion.
The documentation doesn't give out much information on how to do that, only implies that it's possible. ClickHouse's GitHub Issues search by 'CLion' also do not offer much advice.
ClickHouse uses CMake and Ninja. The documentation mentions that one can use either Ninja or make instead of Ninja to compile in CLion.
I tried both and got many errors. For example, when running with CMake settings set to -G Ninja, I was able to build the target common but I get the following error when building the target clickhouse-client:
====================[ Build | clickhouse-client | Debug ]=======================
/usr/bin/cmake --build /tmp/tmp.CAA3nJhi8z/cmake-build-debug --target clickhouse-client
[1/7338] Generating lber-version.c
FAILED: contrib/openldap-cmake/lber-version.c
cd /tmp/tmp.CAA3nJhi8z/contrib/openldap && /usr/bin/cmake -E env bash -c "/tmp/tmp.CAA3nJhi8z/contrib/openldap/build/mkversion -v '2.5.X' liblber.la > \"/tmp/tmp.CAA3nJhi8z/cmake-build-debug/contrib/openldap-cmake/lber-version.c\""
bash: /tmp/tmp.CAA3nJhi8z/contrib/openldap/build/mkversion: Permission denied
[18/7338] Building CXX object contrib/..._/icu/icu4c/source/i18n/calendar.cpp.o
ninja: build stopped: subcommand failed.
I also use a remote toolchain in CLion to build on a server, not my laptop. Since it's a permission issue, I assume I have to run the build from sudo but I'm not sure how to do that, and searching only offers a guide on How to debug as root in CLion.
Question #2. Is it OK that after CMake loaded in CLion, I don't see any green arrows in the CMakeLists.txt in the root of the ClickHouse project? I can only see targets in the top right corner dropdown (screenshot).
Question #3. I'm also unsure how to build all the binaries in CLion. E.g. in the command line, I would just run ninja but in CLion there are so many targets, and none of them is named like build all.
Any pointers to a solution are much appreciated.
It might be helpful to someone to answer your first question.
Since you are using a remote build, the Clion first copies all source files to the remote machine. And if the option
Settings -> Build,Execution,Deployment -> Deployment -> Options -> Preserve original file permissions
is not enabled, it does not save the executable permissions to run some scripts. Which breaks the build.
Therefore, you can either enable this option and re-upload the files or set permission x manually to the files that will be logged in the error message.

How to compile a source into an ARM binary

I want to compile VTK-DICOM to run on an ARM Raspberry Pi (Raspbian). Is it posible? Where should I start?
Building for Raspbian Debian Buster images and ARMv6
This tutorial also supports older Rasperry Pi (A, B, B+, Zero) based on the ARMv6 CPU.
See also:
GCC 8 Cross Compiler outputs ARMv7 executable instead of ARMv6
Set up the toolchain
There is no official git repository containing an updated toolchain (See https://github.com/raspberrypi/tools/issues/102).
Here is a github repository which includes building and precompiled toolchains for ARMv6 based on GCC8 and newer:
https://github.com/Pro/raspi-toolchain
As mentioned in the project's readme, these are the steps to get the toolchain. You can also build it yourself (see the README for further details).
Download the toolchain:
wget https://github.com/Pro/raspi-toolchain/releases/latest/download/raspi-toolchain.tar.gz
Extract it. Note: The toolchain has to be in /opt/cross-pi-gcc since it's not location independent.
sudo tar xfz raspi-toolchain.tar.gz --strip-components=1 -C /opt
You are done! The toolchain is now in /opt/cross-pi-gcc
Optional, add the toolchain to your path, by adding:
export PATH=$PATH:/opt/cross-pi-gcc/bin
to the end of the file named ~/.bashrc
Now you can either log out and log back in (i.e. restart your terminal session), or run . ~/.bashrc in your terminal to pick up the PATH addition in your current terminal session.
Get the libraries from the Raspberry PI
To cross-compile for your own Raspberry Pi, which may have some custom libraries installed, you need to get these libraries onto your host.
Create a folder $HOME/raspberrypi.
In your raspberrypi folder, make a folder called rootfs.
Now you need to copy the entire /liband /usr directory to this newly created folder. I usually bring the rpi image up and copy it via rsync:
rsync -vR --progress -rl --delete-after --safe-links pi#192.168.1.PI:/{lib,usr,opt/vc/lib} $HOME/raspberrypi/rootfs
where 192.168.1.PI is replaced by the IP of your Raspberry Pi.
Use CMake to compile your project
To tell CMake to take your own toolchain, you need to have a toolchain file which initializes the compiler settings.
Get this toolchain file from here:
https://github.com/Pro/raspi-toolchain/blob/master/Toolchain-rpi.cmake
Now you should be able to compile your cmake programs simply by adding this extra flag: -D CMAKE_TOOLCHAIN_FILE=$HOME/raspberrypi/pi.cmake and setting the correct environment variables:
export RASPBIAN_ROOTFS=$HOME/raspberry/rootfs
export PATH=/opt/cross-pi-gcc/bin:$PATH
export RASPBERRY_VERSION=1
cmake -DCMAKE_TOOLCHAIN_FILE=$HOME/raspberry/Toolchain-rpi.cmake ..
An example hello world is shown here:
https://github.com/Pro/raspi-toolchain/blob/master/build_hello_world.sh
Source:
https://stackoverflow.com/a/58559140/13859552

cmake building in source directory, not PWD

The question
Debug vs Release in CMake
indicates that
cd ~/codebase
mkdir Release
cd Release
cmake -DCMAKE_BUILD_TYPE=Release ..
make
Will create the Makefile in release, and build the binary there. The intermediate .o files will be in a subdirectory of this.
However, when I do this with my project, CMake ignores the PWD that it is started from. The final target is always the directory ~/codebase/ which contains CMakeList.txt.
In the cmake-gui tool, I specified the source and build directories to be the same directory, the FQN to codebase
I'm new to CMake, and don't know how to get this to work as I expect. What should I modify to get this work as expected?
If you are using a single configuration generator (Ninja/Unix-Makefiles)
Then you need a build folder for each configuration.
Like this:
# Configure the build
cmake -S . -B build/Debug -D CMAKE_BUILD_TYPE=Release
# Actually build the binaries
cmake --build build/Debug
For multi-configuration generators it's slightly different (Ninja Multi-Config, Visual Studio)
# Configure the build
cmake -S . -B build
# Actually build the binaries
cmake --build build --config Debug
If you are wondering why this is necessary it's because cmake isn't a build system. It's a meta-build system (IE a build system that creates build systems). This is basically the result of handling build systems that support multiple-configurations in 1 build. If you'd like a deeper understanding I'd suggest reading a bit about cmake in Craig Scott's book "Professional CMake: A Practical Guide
Note:
My examples use newer cmake cli practices.
EDIT:
That question you linked to has dangerously out of date answers...

How to fix libtool: undefined symbols not allowed in x86_64-pc-msys shared

I am trying to build heimdal package for msys2. To my dismay, during linking of the first constituent library, roken, dlls fail to be built, and that causes sort of a chain reaction further on.
The only message i get is:
libtool: undefined symbols not allowed in x86_64-pc-msys shared ... only static will be built
however, there is no information provided on what symbols are undefined. How can i find that out?
If i turn on output of commands wuth make V=1 i get libtool command that links from a large numbert of .lo files. If i try to run gcc over them (copying command from there), it does not recognize them as anything.
I am trying to follow instructions as outlined in msys2 package build script for heimdal.
On Windows building a shared library while allowing undefined symbols is not allowed.
Try to build with the -Wl,-no-undefined linker flag, for example by adding LDFLAGS="-Wl,-no-undefined" to the ./configure command.
If that didn't work try this after ./configure and before make:
sed -i.bak -e "s/\(allow_undefined=\)yes/\1no/" libtool
If you already had a failed build earlier you should also clean up any .la files like this before running make again:
rm $(find -name '*.la')

OCLint reports compiler errors due to its inability to find #import-ed header files

I am trying to integrate OCLint 0.13 to check lint violations in my ObjC based iOS project.
As per this guide I created an aggregate target in Xcode to run a xcodebuild clean build followed by oclint-xcodebuild to generate a compile_commands.json. I am able to run the clang command from the generated compile_commands.json file. However, in html report generated by oclint-json-compilation-database command, while processing file like NEORepos/Public/ResourceObservables/NEOAggregatedObservable.h, I see compiler errors like 'NEOObservables/NEOObservable.h' file not found even though the said header file is present at NEOObservables/Public/Observables/NEOObservable.h.
How can I get rid of these compiler errors which are preventing some of my source files from being linted?
Running the clang command from compile_commands.json generates the .o file, but OCLint doesn't seem to be able to compile using the json file.
I also tried adding a few more -I include paths, but it didn't help. All suggestions and pointers are welcome.
Here's a piece of (edited) log...
xcode_clean_build_command = xcodebuild -workspace 'Neo.xcworkspace' -scheme 'NeoSampleApp' -configuration 'Debug' clean build -dry-run -derivedDataPath /Users/username/Documents/git/ios-neo_linter/build/Neo -sdk iphonesimulator CLANG_ENABLE_MODULE_DEBUGGING=NO CODE_SIGNING_ALLOWED=NO CODE_SIGN_IDENTITY='' CODE_SIGNING_REQUIRED=NO ENABLE_BITCODE=NO COMPILER_INDEX_STORE_ENABLE=NO | tee xcodebuild.log
...
/oclint-xcodebuild
...
Generating the compile_commands.json ...
Picking NEORepos/Public/ResourceObservables/NEOAggregatedObservable.m
Picking NeoSampleApp/main.m
...
Shortlisted files for linting (2 out of 283) and creating a new compile_commands.json
...
Compiling /Users/username/Documents/git/ios-neo_linter/NEORepos/Public/ResourceObservables/NEOAggregatedObservable.m - Failed
Compiling /Users/username/Documents/git/ios-neo_linter/NeoSampleApp/main.m - Success
Analyzing /Users/username/Documents/git/ios-neo_linter/NeoSampleApp/main.m - Done
...
Generating lint report (if any)...
...
Executing command: oclint-json-compilation-database -e Pods -v -- -list-enabled-rules -no-analytics -enable-global-analysis -verbose --report-type html -o oclint.html -extra-arg=-Wno-everything
...
/usr/local/bin/oclint -p /Users/username/Documents/git/ios-neo_linter -list-enabled-rules -no-analytics -enable-global-analysis -verbose --report-type html -o oclint.html -extra-arg=-Wno-everything /Users/username/Documents/git/ios-neo_linter/NEORepos/Public/ResourceObservables/NEOAggregatedObservable.m /Users/username/Documents/git/ios-neo_linter/NeoSampleApp/main.m
The compiler error was due to the -dry-run flag that I was using. Since it was doing a dry run, it was not creating .hmap files that were needed (at least not in the right location) leading to <blah>.h file not found errors.
However, without -dry-run I would have to do a full build which is not acceptable for me. Will update if I find a solution with optimal performance.