Shared objects of dependencies of a Bazel target - bazel

I'm trying to build a shared object .so using Bazel.
The target is a cc_library and using bazel build <target>, I can successfully recover the shared object.
My problem arises when I try to use the shared object in another library (built with CMake). Since the target has many dependencies the linker cannot find all the symbols in the .so and the linking phase fails.
I'm trying to recursively built all the missing dependencies with Bazel adding explicitly the targets of dependencies to the command bazel build.
This manual work is very long, pedantic and wasteful since Bazel is already capable to resolve dependencies automatically and probably it builds internally all the needed shared objects.
Do you know if there is a way to recover the .so files of the dependencies of a target built with Bazel?

Related

Bazel - Can't compile without import Foundation, UIkit,

I'm trying to compile a swift project with Bazel, version 4.2.1.
I have a main project with multiple CocoaPods submodules of my own installed. I have a WORKSPACE and a BUILD configuration file for the project and another WORKSPACE and BUILD for each submodule.
I add the secondary workspaces as local_repository in the main workspace. I create the submodule build with a swift_library and add it in the main build in deps.
If in a .swift file, located in the submodule, I create a variable "var dateIni: Date?" I get an error "error: cannot find type Date in scope". I can solve this with "import Foundation" but xcode doesn't need it, I would like to be able to compile in Bazel without having to do these SDK frameworks imports. Is there any way to solve this?
I can post code or explain it better if you need more information.

How to avoid build and lipo of Universal Framework everytime project is built?

I have a project that uses a custom framework I've built. This framework provides a clean API based on Objective-c which hides c++ code.
The framework has a universal builder target that uses a Run Script to run xcodebuild and then lipo the binaries for the framework to include.
I realize that the project always wastes a lot of time calling the universal builder target which builds and lipos the binaries. My question is how can I avoid xcodebuild and re-lipo if the source files if they haven't changed?
Well, after much research and getting down and dirty I realized two things.
I did not need a universal build script target. The reason being that the framework project was included on the app I was working with. So xCode automatically is building the correct architecture for the framework. This speeds up the build process since now framework building will only happen when something changes.
So if you are still in need of using a universal build script use the Input Files and Output Files to define your script variables. This then allows xCode to check if the files need to be built and thus executing the script. More on that here: https://patrickbalestra.com/blog/2018/08/27/improving-your-build-time-in-xcode-10.html

Can't assign xcassets to the main target on Xcode 11

On Xcode 11 my .xcassets, that don't cause any issue on Xcode 10, cause the compilation to fail with the following message:
error: Multiple commands produce '/Users/user/Library/Developer/Xcode/DerivedData/project-enjiypsgxtcdbnaripixgtnjlagx/Build/Products/Debug-iphonesimulator/project.app/Assets.car':
1) Target 'project' (project 'project') has compile command with input '/Users/user/sandbox/project/Resources/buttons.xcassets'
2) That command depends on command in Target 'project' (project 'project'): script phase “[CP] Copy Pods Resources”
The only way I'm able to compile the project is by removing the .xcassets from the target with the obvious downside of having them not available on the build.
PS: This is happening for 2 ObjC projects.
Add below line at the top of your pod file, right after platform :ios
install! 'cocoapods', :disable_input_output_paths => true
Reference
The answer above is only partially correct: yes, this happens because the pod phase produces Assets.car as an output file, which coincides with the output name for your xcassets - hence Multiple commands produce... error: one command being the script phase [CP] Copy Pods Resources and another - your own project's compile command.
But removing Assets.car from output files will cause the build system to fail to see that the script processes the file, thus it skips it (read this for more details). So what we can do is add Assets.car to the input files - this will create a dependency for the script, telling the build system to wait for the file before executing the script.
NB: like the solution above, you will have to do this every time after updating your pods, since [CP] Copy Pods Resources is generated every time you run pod install or pod update
To be sure that all build steps are performed in the correct order, yet as many steps in parallel as possible, Xcode needs to know for every build step which input files it depends on and which output files it will generate.
E.g. if step A depends on an input file that is the output file of step B, step B surely has to run before step A. If neither step requires the output file of the other step, they can both run in parallel.
While several steps can surely depend on the same input file, it cannot be the case that multiple steps produce the same output file as in that case, whichever step runs last would overwrite the output file of whichever step runs first and this means the resulting output file content would be unpredictable and that is an error in a build process that shall created predictable results!
In your case the problem is that your Copy Resources build phase contains one (or more) .xcassets bundle(s). Xcode won't just copy these bundles, instead it will combine them, convert and optimize their content, and create a file called Assets.car that contains the content of all the assets catalogs in your project.
Yet if you integrate a Pod and this Pod also has an asset catalog, exactly the same thing will happen and a second Assets.car file is created and now Xcode has a problem: Two build steps both say they create an Assets.car file. Which one shall win? Which of these two files shall end up in the final application? And what about other steps that depend on this file? After which of the build steps do they have to run? This is a serious problem that Xcode cannot resolve.
There are currently two possibly solutions:
Use frameworks. When you use frameworks instead of static libraries, the resources of Pods don't end up in the resources folder of your main application but in the resources folder of the built framework. All you need to do is to add use_frameworks! to your Podfile, either top level or just for a specific target. The downside is that your overall app size will grow a bit and app start time will increase a bit.
Have the Pod-author fix the Pod. Instead of resources s/he shall use resources_bundle as the Podspec documentation also strongly recommends. Using resources actually has other disadvantages (resource files are not optimized, name conflicts can arise between different Pods), whereas using a resource bundle is safe, regardless if Pods are embedded as static libraries or as dynamic frameworks. Note, though, that it is not enough to just alter the Podspec, all code that loads bundle resources must be adopted to load them from the correct bundle (the name will be known as when using resources_bundle in a Podspec file, you also must give the bundle(s) a name).
There is an on-going bug report for this issue, you can find it here:
https://github.com/CocoaPods/CocoaPods/issues/8122
Yet the problem currently is, that every possible solution other than the two mentioned above would basically be an ugly hack and the Cocoapods developers are not happy implementing ugly hacks. The best solution, as hard as it seems, is probably to not fix that problem at all but to stop supporting resources in Podspec files and make resources_bundle mandatory for Pods that contain own resources.
In your library project, such as "LADetailPage", open Targets' "Build Phases", create a predefined phase named "Copy Files", then drag your *.xcassets to the new phase.
Then the library won't make Assets.car from *.xcassets files when building, instead, cocoapods copies the *.xcassets to your main project which imports the lib, and the main project builds all *.xcassets into a single Assets.car file.
Please check your dependencies if there is some pods use 'resources'(not 'resources_bundle') to link its own xcassets in podspec.
This way has beed deprecated, because its output file name is 'Assets.car'. It is same with your project xcassets' compile output name.
Xcode->File->Workspace settings->Building System-> Legacy Build System
example

In Xcode 9's new build system, how do I execute commands before the check dependencies phase?

I have an foo.xcconfig file that will have different values depending where in the world a developer is. Currently, we use a phase to create this file (which is imported by other config files). In the new build system, Xcode is now resolving the dependencies before I have a chance to create a dummy to satisfy the include.
This is easily solved for CI builds by doing the work before calling xcodebuild, but for local builds using the GUI, there does not seem to be a good solution.

Looking for an Xcode build script to copy files between targets

Does anyone have a script that can copy files from one target to another, during the build process?
I have a project with one target that builds an app and another target that builds a library. The library needs to contain a large subset of the files from the app and I want to avoid manually copying them over.
In the build phase of an XCode 4.x project you can add a build phase to either copy files or just run a script (that does your copying for you)
See this SO question adding-external-scripts-to-xcode4, for additional details

Resources