In my project we have code that when compiled for static linkage there must be a define added when compiling the code. Let's assume it's -DSTATIC_COMPILATION.
My question: Is it possible to control compilation flags when requesting a static linkage or any compilation flags based on linkage binding?
Thinks I know I can do:
Add a --copt '-DSTATIC_COMPILATION' to the command line bazel build
Configure a bazelrc file that can provide such configuration by passing bazel build --config=static_comp - which is nice, but I'm not sure it will pass to other packages when taking this package as external package - I could be wrong here...
What are the options I'm missing?
The short answer is that there is no way in Bazel today to get it to set a flag based on whether the code will be statically or dynamically linked.
Bazel's cc_library does compile code twice on architectures that require PIC for dynamic linking, but do not require PIC for static linking - once with and once without PIC. This is mostly done for performance of the statically linked executables, as non-PIC code is generally faster.
Note that cc_test rules in Bazel are dynamically linked by default while cc_binary rules are statically linked by default, so the PIC/no-PIC distinction requires double compilation of almost all C/C++ source code. For additional complexity, note that PIE executables require PIC-compiled code, so if you want ASLR, which requires PIE executables, then the code is always compiled as PIC.
However, the support for PIC/no-PIC is hard-coded in cc_library, and I don't see any obvious way to 'abuse' it to do what you want. You could conceivably hack up a crosstool to declare that the arch requires PIC for dynamic linking, but not static linking, and then declare with PIC in both cases anyway and also set the additional flag. This would result in .pic.o and .o output files, although both would contain PIC code. This isn't workable if you can't control the crosstool, and I wouldn't recommend doing this.
That said, there may be other ways to achieve what you want. Mind elaborating why you need to have a special case for statically linked code?
Related
I am trying to get LLVM IR for a file which is linked with some static libararies.
I tried to link using llvm-link . It just copy the .bc files in one file ( not like native linking).
clang -L$(T_LIB_PATH) -lpthread -emit-llvm gives an error: emit-llvm can not be used with linking. When passing -c option, it gives warning that the linking options were not used.
My main goal is to get .bc file with all resolved symbols and references. How can I achieve that with clang version 3.4.?
You may have a look at wllvm. It is a wrapper on the compiler, which enable to build a project and extract the LLVM bitcode of the whole program.
You need to use wllvm and wllvm++ for C and C++, respectively (after setting some environment variables).
Some symbols come from source code via LLVM IR. IR is short for intermediate representation. Those symbols are easy to handle, just stop in the middle of the build process.
Some others come from a library and probably were generated by some other compiler, one that never makes any IR, and in any case the compiler was run by some other people at some other location. You can't go back in time and make those people build IR for you, even if their compiler has the right options. All you can do is obtain the source code for the libraries and build your entire application from source.
I'd like to convert a CMake-based C++ library to bazel.
As part of the current CMake project, I'm using a libclang-based code generator that parses C++ headers and generates C++ code from the parsed AST. In order to do that, I need the actual compiler flags used to build the cc_library the header is part of. The flags are passed to the code generation tool so it can use clang's preprocessor.
Is there any way I could access the compiler flags used to build a dependency from a skylark- or gen_rule rule? I'm particularly interested in the include paths and defines.
We're working on it. Well, not right now, but will soon. You might want to subscribe to the corresponding issue, and maybe describe your requirements there so we take them into account when designing the API.
I am trying to get some a medium-to-large sized code base that is, frankly, well written with a high degree of portability.
I decided to package it as a loadable bundle (plugin) and piggy-backed off of one of the template app projects and followed some tutorials about adding a target for loadable bundles within an app.
Also, this loadable bundle depends on a custom framework which I built for iOS and added it as a dependent for the loadable bundle. ie. The plugin links to a framework wrapper for a static lib.
The custom framework built successfully. Granted I have not yet verified that it works. The idea is to test the integrated functionality.
My build settings are largely defaults with the exception of some preprocessor defines.
Because I don't really understand the code base yet, I am literally adding one file-at-a-time to the plugin target and building cleanly every 3-4 files added.
The build completes successfully but with many, many warnings as follows, with paths to intermediate build results...etc.:
"file was built for unsupported file format with a series of hex characters () which is not the architecture being linked (armv7s)". When I converted the hex chars to ascii it just showed "#1 /Users/my-username/? ".
When I do a 'file' on any .o in the intermediate build results, I get "ASCII c program text, with very long lines"
What am I doing wrong? What does that mean?
Thank you so much for your time.
The short answer is this:
If you get this message, then your project settings are messed up.
If you are linking your app against custom frameworks, make sure they are built as fat binaries
You will need to know very clearly the meanings of active architecture and how it is used and whether or not you want to only build the active architecture for your app, or all of the possible architectures.
If you are, like me, inheriting a slew of portable code that depended heavily on gcc and its extensions, expect to make changes around builtin* attributes and to make heavy use of __clang to make available macros that used to be defined through the GNUC et al.
Also, you will need to use the -E for clang to debug/understand the preprocessing and the file inclusion. That said, don't forget to take it out because effectively what will happen is that your .o will just contain text and the build may succeed, but the linker will give you the odd message subject of this question.
Finally, do understand that Xcode, like any piece of complex software, is buggy. Sometimes, it will keep settings that you get rid off. In my case, I included custom frameworks which I built after placing them in a local dir. Then I deleted them from the project and opted to trash when prompted. The build kept failing because the linker for some reason was looking for the local directory. You would have to edit the *.pbxproj and manually remove them.
I am working on an iOS app which links several static libraries. The challenge is, those linked libraries define same method names with different implementations. Oddly, I don't get any duplicate symbol definition errors; but, to no surprise, I end up with access to only one implementation of the method.
To be more clear, say I have libA and libB and they both define a global C method called func1()
When I link both libA and libB, and make a call to func1(), it resolves to either libA's or libB's implementation without any compilation warning. I, however, need to be able to access both libA's func1() and libB's func1() separately.
There's a similar SO post that explains how it can be done in C (via symbol renaming) but unfortunately, as I found out, objcopy tool doesn't work for ARM architecture (hence iPhone).
(I will submit it to the App Store, hence, dynamic linking is not an option)
It appears that you are in luck - you can still rename symbols with the ARM binary format, it's just a bit more hacky than the objcopy method...
NOTE: This has only been tested minimally, and I would strongly advise you to make a backup of all libraries in question before trying this!
Also note that this only works for files not compiled with the C++ compiler! This will fail if the C++ compiler was used on these files.
First, you will need a decent hex editor, for this example, I will be using Hex Fiend.
Next, you will open up a copy of your of of your libraries, let's call it lib1-renamed.a, and do the following with it:
Find the name of the symbol you wish to re-name. It can be found using the nm tool, or, if you know the header name, you should be set.
Next, you will use hex fiend, and to a textual replace of the old name (in this case foo), and give it a new name (in this case, bar). These names must have the same length, or it will corrupt the binary's offsets!
Note: if there is more than one function that contain's foo's name in it, you may have problems.
Now, you must edit the headers of the library you changed, to use the new function name (bar) instead of the old one.
If you have done the three simple† steps above properly, you should now be able to compile & link the two files successfully, and call both implementations.
If you are trying to do this with a universal binary (e.g. one the works on the simulator as well), you'd be best off using lipo to separate the two binaries, using objcopy on the i386/x64 binary, and then using my method on the ARM binary, and lipo it back together.
†: Simplicity is not guaranteed, nor is it covered by the Richard J. Ross III super warranty. For more information about the super warranty, call 1-800-FREE-WARRANTY now. That's 1-800-FREE-WARRANTY now!
If you're building a commercial iOS SDK that will be included in other people's code and you have third party libraries that you have a license to, is there an effective way to simplify the library / framework structure by not exporting those 3rd party symbols in a static lib?
I appreciate I could instruct developers to check for overlapping symbols, but I'd like to minimize instructions. Ie, just want them to drop the lib into their project and off they go. I also do not want to export my third party symbols as they may change in later projects.
Unfortunately, there isn't a lot to be done here very easily. A static library is just a bunch of .o files glued together. There is no linker step to determine what pieces are actually needed between .o's. That's not done until the final link step (by your customer).
That said, there are some things you can think about:
First, whenever possible, avoid including sub-libraries inside of a static library. This is really dangerous if it's possible for the customer to have other copies of the same sub-library. Your situation seems to be difference since your sub-library is licensed, so the customer is unlikely to have multiple copies, but for example, you should never include a static copy of libcurl in your static library. You must ask the customer to link libcurl themselves, or else things will explode quite badly for them. (See Linking static libraries, that share another static library.) Again, this sounds like it may not apply to you, but keep it in mind if you have common open-source libraries in the mix.
An old-school solution for dealing with visibility is to glue together your compile units. This is a fancy way of saying "concatenate all your .c/.m files into one massive file and compile that." Any function you mark "static" will not be visible outside this compile unit, and so shouldn't be exported. This also happens to increase the possibility of compiler inlining and other optimizations (particularly without fancy link-time optimization) inside of your library.
See Symbol Exporting Strategies. You have several options:
marking symbols as static (probably not possible in this case since they come from a 3rd party)
Use an exported symbols list or an unexported symbols list
Set the visibility attribute of the symbol directly (again, probably not possible in this case)
Use -fvisibility command line option when compiling (probably your best bet here)
Use weak imports
Use a weak library
These are explained at the link above.