Does anyone have an example of how to set up a custom build rule in Xcode that takes a file in a source directory and produces an output in the same folder? I am confused about the three separate areas, one is clearly the command line instruction, but I'm unclear on the rest of the setup. Apple's documentation is... ummm, "limited". I think this would be easy if you could simply see what their internal rule does, but these rules do not display the same screen so it's not easy to figure out what goes where.
The specific problem I'm trying to solve is building a yacc source file. When you build one, yacc (or in this case, the largely compatible bison) produces a .h with defines that you then #include into your C code. Modern dialects will normally build a file into the same directory with the same name as the input - in my case, the parse.y produces a parse.h.
Unfortunately, Apple has defined $(YACC) to include the -Y flag, so instead of building parse.h in the source folder it builds y.tab.h in the DerivedSources folder. I'm trying to override this behaviour without having to change $(YACC).
Related
GCC allows for having command-line options passed by a file by #file syntax. Using this the file should be added as prerequisite (aka dependency) to the target.
I'm not finding any reference in CMake docs about argument files, suggesting it's not supported. Or perhaps just takes a little bit more plumbing, e.g. cat file|xargs? Or some way telling CMake explicitly that the file is a prerequisite? I mean "Prerequisite" according to GNU Make terminology. If file contents change I have to rebuild. AKA dependency.
Which is it? And how does it work?
You should just be able to use target_compile_options() or CXX_<LANG>_FLAGS like you normally would.
Since the flags available for different compilers are usually different, you probably will have one for each compiler you support, in which case you can wrap your target_compile_options() calls with if() blocks based on CMAKE_CXX_COMPILER_ID or the MSVC variable, or use the CXX_COMPILER_ID or X_COMPILER_ID generator expressions to use the right file (if you have multiple files for multiple compilers) for the right compiler.
However, I've also noticed before when trying this that using file flags like this doesn't automatically add the file as a dependency to the target (the CMake won't add a rule for the target to rebuild if that file changes), so you might need to do that manually like this:
# wrap this in a function taking `target` as an argument.
get_target_property(sources ${target} SOURCES)
set_property(SOURCE ${sources}
# DIRECTORY "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}"
TARGET_DIRECTORY ${target}
APPEND PROPERTY OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/path/to/flags/file.txt"
)
The above snippet courtesy of a user in this GitHub issue. It uses the OBJECT_DEPENDS source file property to make every source file of a target depend on the compiler options file. I (and the author of that code snippet) would classify it as a workaround, since it only works for Generators that support OBJECT_DEPENDS. From the CMake docs:
Specifies a semicolon-separated list of full-paths to files on which any object files compiled from this source file depend. On Makefile Generators and the Ninja generator an object file will be recompiled if any of the named files is newer than it. Visual Studio Generators and the Xcode generator cannot implement such compilation dependencies.
I'm not sure at what level of the toolchain it would be best to request that such automatic dependency-tracking functionality be added. According some of the Ninja buildsystem maintainers in the above linked GitHub issue, (if my noob brain is understanding the words they're saying correctly :P), it's something that could be handled by compilers when they generate depfiles given a compile comand for a source file. I'm currently too scared to ask compiler maintainers if that's the case. If you're interested in digging onto the part that CMake plays in orchestrating other tools to get dependency tracking for things like header files and the creation of dependency-tracking files ("depfiles"), you can go to your CMake installation's Modules folder and grep for CMAKE_DEPFILE_FLAGS_. Then use "find in files" at https://github.dev/Kitware/CMake.
Notes: Visual Studio / MSVC's compiler calls these "command files", gcc doesn't seem to have a particular name for them, and clang calls these "configuration files". They all support similar #file syntax. I'm not sure what the history is with that, but many compilers aim to have levels of compatibility (similar interface to) with GCC.
That's all. If you're bored and want to read a bit about how CMake does header dependency detection (which is loosely related here on the topic of depfiles), see this other post of mine.
I have a large project using autotools that contains some code that builds into a utility library. The project has quite a few dependencies and I would like to compile a specific subset of that utility library for mobile environments (Android/iOS). I expect a lot of dependencies to be unnecessary for that particular subset of functionality, and compiling the whole project for those architectures/platforms is impossible for technical reasons.
This mini version of the library would actually be useful not just to me but other people, as well. This is why the maintainer of the project suggested introducing a --enable-mini flag for the configure script. After experimenting a little (I have never done anything inside a configure.ac before) I actually got a build working that builds this extra mini library.
Now to the point: Is there a clean way to exclude all the other project executables and libraries from being built? What I want is a ./configure --enable-mini invocation that will result in only the libutilmini.a/libutilmini.la being built. Sure, there are some components that could be disabled via --disable-X options, but obviously the project was not set up in a way that makes all components optional. Apart from the fact that it does not seem necessary to build everything else just to build the mini library, the whole project will not build for, for instance, the iOS platform.
I really would like to avoid adding an if HAVE_MINI [...] to all the Makefile.ams in every subdirectory, especially since the mini library is not useful to most of the other developers, this does not seem like an elegant approach. Are there any recommended ways of achieving these goals?
I am aware I could just create a new project using the sources I need and build those, but as I said the mini library is useful to some other developers, too.
If you want to conditionally compile something with automake using a regular make command with no arguments, you have to use automake conditionals (the if HAVE_MINI thing you refer to); there is no other way. However, what you can do, alternatively, is to create an extra target (say, build_mini) in your toplevel Makefile.am which depends on everything needed to build your libmini. You could then tell people that if they want to build libmini (and nothing else), they don't run make, but they run make build_mini. This would look something like:
(toplevel Makefile.am)
SUBDIRS = foo bar baz
build_mini:
$(MAKE) -C foo libmini-depends
$(MAKE) -C bar libmini.la
or some such (the details would depend on what is needed to build libmini.la).
You would then have bar/Makefile.am look something like this:
if WANT_MINI
lib_LTLIBRARIES += libmini.la
endif
libmini_la_SOURCES = # ...
the only thing that really needs to be inside the conditional is adding the libmini.la to lib_LTLIBRARIES; everything else can be unconditional. So with this method, you should have only one if FOO...endif construct.
How to build a .bundle from source code?
This might sound like a simple problem but it has been hurdling me for a week...
Here is my problem:
I have a bunch of .c and .h files that are organized in a folder and its sub folders. The source code was written and compiled with gcc make and tested by many other make tools. The source code has some utilities and command line tools and it has more code that serve as library for those utilities and tools. It is the files that serve as libraries that I want to reuse. (By library I don't mean static library or something, I just mean that some .c and .h files in certain subfolders provide functions that can be called by some other .c files. I want to be able to call those functions, too)
Yet my problem is more complex than that: I need to build those .c and .h into a bundle to reuse it. I am not writing my application in C; I am developing in Unity and Unity can only take in .bundle files on Mac OS.
Here is my goal:
Organize the source code folder in a proper way so that I can build them into a bundle in Xcode 4.
Here is where I got stuck:
When building the project I got the following error:
Duplicate symbol _main in
/Users/zeningqu/Library/Developer/Xcode/DerivedData/ccn-cfygrtkrshubpofnfxalwimtyniq/Build/Intermediates/ccn.build/Debug/ccn.build/Objects-normal/i386/ccndsmoketest.o
and
/Users/zeningqu/Library/Developer/Xcode/DerivedData/ccn-cfygrtkrshubpofnfxalwimtyniq/Build/Intermediates/ccn.build/Debug/ccn.build/Objects-normal/i386/ccnd_main.o
for architecture i386
I can relate to this error because I can find lots of main entries in the source code. Most of them are test utilities.
Here is what I tried:
I tried removing all those utility .c files but with no luck. The error is still there. I delete and delete until some files cannot find the definition of the function they are calling. So I had to stop there.
Though I wasn't able to build a bundle I was able to build a C/C++ static library (with an .a extension). After I got the .a file I tried to put it into another Xcode project and tried to build it into a bundle. I could build a bundle in that way, but then I had problem accessing the content of the bundle. How do I call functions defined in a .a static library if that library is hidden in a bundle? I read about Apple's documentation which says:
Note: Some Xcode targets (such as shell tools and static libraries) do
not result in the creation of a bundle or package. This is normal and
there is no need to create bundles specifically for these target
types. The resulting binaries generated for those targets are intended
to be used as is.
(quoted from: https://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFBundles/AboutBundles/AboutBundles.html#//apple_ref/doc/uid/10000123i-CH100-SW1)
Here is what I thought about:
I thought about replacing all main with something like main_sth. But the source code was not written by me so I didn't want to modify it. (It just doesn't feel like a proper way of doing things to me...)
I learnt that Xcode has gcc compiler built in. So I guess if gcc can make it, so can Xcode? It's just a wild guess - I am not familiar with Xcode and gcc.
Here is a summary of my questions:
Is there a way to properly organize a pile of code previously compiled and made by gcc make so that they can be built into an Xcode bundle?
Is it meaningful to put a .a library in an Xcode project and build it into a bundle? If it is meaningful, how do I call functions defined in .a after it is built into a bundle?
Is it proper to just replace all main() entries with something else?
Alright I think I have figured out at least one solution to the problem.
The duplicate main error was caused by a bunch of main entries in my source code. When the code was compiled by gcc make, I guess the author defined a sort of compilation order so that duplicate mains won't be an issue. (If you know how to do this, please let me know. I barely know make tools.) But when I just add the entire source code folder into my Xcode project, of course Xcode would complain during linking...
As I was unwilling to modify the source code (because the source code library is not developed by me), I decided to use another strategy to walk around this problem.
If your duplicate main error was reported from your own code, you can stop reading here. But if you are like me, with a bunch of gcc compiled source code and badly need a bundle yet don't know what to do, I may be able to help.
Okay here is what I did:
I set up an empty workspace.
I built a C/C++ static library project.
Import my entire source code folder into the static library project.
Set some header search path for the static library project.
Build the static library project. (Now I have a .a library which I could link against)
I set up another project, with a bundle target.
At the bundle project -> Build Phases -> Link Binary with Libraries, add the .a library that I just built.
At the bundle project -> edit scheme -> Build, add the static library project to the scheme and move it up the list so that it is built prior to my bundle project.
Then add .h files of my library project to my bundle project as references.
After that, add a .c file in my bundle project that basically functions as a wrapper. I picked a function that I want to call in Unity, wrote a wrapper function in the new .c file, and was able to build the bundle.
After several trial and error, I was able to import the bundle into Unity and was able to call the test function from Unity.
I was really excited about this! Though it's not completed yet I think this gives me hope and I am confident I can use the source code now! And the best thing about this solution is that I don't have to modify the library code developed by others. Whenever they update their code, I just update my .a library and that's it!
Though I have listed 11 steps I still feel that there are lots of details that I missed. So here are my references:
I followed this tutorial to build my source code into a static library: http://www.ccnx.org/?post_type=incsub_wiki&p=1315
I followed this blog to link static library against my bundle code and twist build phases and search headers: http://blog.carbonfive.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/
I followed this doc to import my bundle to Unity3D Pro as a plugin: http://unity3d.com/support/documentation/Manual/Plugins.html
I strongly recommend the second reference because that's what solved my problem!
Though the problem is almost solved there are still a few things that I haven't figured out:
I don't know if a wrapper function is at all necessary. I will try this out tomorrow and come back to update.
-- I am coming back to update: the wrapper function is NOT necessary. Just make sure you have all the headers in your bundle project and you will be able to use all the data structures and call functions defined in your headers.
I haven't used NSBundle class though I read a few docs about it. Previously I was thinking about using that class to access my .a library encapsulated in my bundle, but as I found the solution I wrote above, I didn't try the class out.
Lastly, if you have better solution, please don't hesitate to let me know!
I tried to follow the steps in the accepted answer, but had no luck. In the end, I realised step 10 needed to be modified slightly:
Create a dummy.c under (.bundle) project and the dummy.c can just be totally empty.
Remove the setting for the library you want to link inside Link Binary With Libraries
Instead use -Wl,-force_load,$(CONFIGURATION_BUILD_DIR)/libYourLib.a or -all_load to Other Linker Flags
PS: And also can use sub-project instead of workspace. and use Target Dependencies instead of Edit Scheme to achieve the same effect.
I've run into trouble in the past when I've tried porting some C++ code written on Mac OS X to a Linux system, or trying to compile code written against an older version of gcc/g++ with a newer one:
It seems that some (older?) versions of gcc/g++ would automatically include some header files for you.
For example, code that uses printf should require #include <stdio.h>. And code that uses memcpy should require #include <string.h>. But depending on the version of gcc I'm using, it will occasionally include these for me.
It wreaks havoc when I forget to include something and then never get errors until I go to compile the code on another system. At that point it's a game of running all over the project and fixing the includes.
Has anyone else run into this? Is there a way to force gcc to autoinclude or to not autoinclude? Or, is there a way to know what it's autoincluding?
-include file
Process file as if #include "file" appeared as the first line of the primary source file. However, the first directory searched for file is the preprocessor's working directory instead of the directory containing the main source file. If not found there, it is searched for in the remainder of the #include "..." search chain as normal.
If multiple -include options are given, the files are included in the order they appear on the command line.
http://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html
Are you sure it's not other headers pulling those one's in, and on the other platforms not doing so?
When compiling on different systems, you might meet different problems and not only includes.
I would suggest investing in a continuous build system that will compile on all OS you need after each update of the code, so you are rapidly aware of any portability issue.
You can also put all common system header files inside a specific header file you will write and systematically include it in all your files.
My Makefile translate Java files to ObjC first and then compile them to make static library.
Everything is work right until i am trying to invoke from XCode. Make file just ignore translate rules.
Interesting part is that if i call make and generate all sources everything goes right. Updated sources are translated.
Here is my Makefile: https://github.com/actorapp/actor-platform/blob/master/actor-apps/app-ios/ActorCore/Makefile