Info.plist value as C++ #define - c++

In a C++ iOS project (or any other Mac OS), is there a simple way of making a value available both to the Info.pList settings, and to the code in the form of a preprocessor macro?
Ideally, I would like to have something like this
C++ code:
#define MY_VERSION_STRING "1.0"
Info.pList
CFBundleVersion: ${MY_VERSION_STRING}
Or alternatively, is there a way of getting values from the .pList in c++? (Without manually parsing the .pList as xml.)

Probably not the best solution, but you could use the /usr/libexec/PlistBuddy utility in a build script to generate a .h file containing a define with a value extracted from the plist.
To output a value from a plist:
/usr/libexec/PlistBuddy -c 'Print :Path:To:Key' filename.plist

I know this has already been answered, but I'll add my two cents for posterity. As Richard mentioned above, Xcode has a couple of options for preprocessing Info.plist files -- the most relevant to the current question are "Preprocess Info.plist" and "Info.plist Preprocessor Prefix File".
If your version information is defined in, say ver.h, you can include ver.h as the prefix file and refer to the version macro directly from Info.plist.

This is all readily doable without involving PlistBuddy at all, entirely using build settings.
you create a user defined build setting for your project/target either in the Xcode UI or if you're familiar with xcconfig files you can define it there in a completely textual = form.
you create your setting MY_VERSION_STRING with a value of 1.0 as your build setting either in Xcode or in an xcconfig file.
in your Info.plist your CFBundleVersion line would have a value of ${MY_VERSION_STRING}
you turn on Info.plist preprocessing
lastly, make use of GCC_PREPROCESSOR_DEFINITIONS build variable. for that build setting you can specify a value of MY_VERSION_STRING=${MY_VERSION_STRING} which will result in your defined and shared build setting definition available in to your c/c++/obj-c code as if you had created it as a #define

Property list can also store arrays or some binary data. How do you represent that? It is very domain-specific. So if you know exactly how do you want each type to be represented in C++, you have to either parse plist file and generate C++ code, be that preprocessor directives, or some code defining arrays, enums etc. There are PlistBuddy and plutil tools available, but they probably won't be much of a help. The easiest way for me would be to use perl, see Using Perl to Manage Plist Files for details.
Good luck!

In case anyone wants to do the same thing, this is the script I added to the target before the compilation phase:
VERSION=`/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' Info.plist`
echo "#define VERSION_STRING L\"$VERSION\"" > Version.h

If you use #define..., you shoud use in the .plist key, MY_VERSION_STRING, and not ${MY_VERSION_STRING}. This works too with the "Info.plist Preprocessor Prefix File". In both cases don't forget to set "Preprocess Info.plist File".

Related

getting include paths to work with Neovim and LSP-zero/Clangd

I'm currently Studying Computer enginering and taking embeded systems class, My isuse is that we use a custom library then compile it in a old version of Codewarrior.
how I would go about creating an include path for my lsp with nvim
I was woundering how I would go about creating an include path for my lsp with nvim, when I am not compiling the code localy but later compiling it with an old IDE
any wisdom would be apreciated.
note: in class we are required to use an exterior editor and the older version of code warrior is verry bad it is used for compiling for our micro controler but is unusable for writting code.
things I have done
I have atempted using compile_commands.json by coppying my vscode config for path location
I have tryed using a .clangd file with -I ...
I have tried other method but had no sucess so far
over all I was hopping to find a solution and have poured over the getting started page and stack overflow for several hours trying diffrent method to no avail.
The easiest approach is probably to use a .clangd file. Based on the path in your comment, the .clangd file should look like this:
CompileFlags:
Add: -I/home/bjc1269/Documents/github/libraries/lib/hc12c/include
A few things that I'm seeing in the .clangd file in your comment that don't work are:
Variable substitutions like ${workspaceFolder}. This is a VSCode feature that works in some VSCode settings like "clangd.arguments", but is not supported in a .clangd file, which is editor-agnostic (for example, it works with editors that don't have a concept of a "workspace").
Referring to your home directory as ~. Expanding ~ to /home/<username> is a feature of your shell. Command-line arguments specified in .clangd are passed directly to the compiler without being processed by the shell, so ~ will not work.
Globs like **. To be honest, I'm not even sure what the intended semantics for this could be in the context of specifying include directories.
Square brackets inside the argument to -I. Square brackets may appear in a .clangd file as YAML syntax for specifying multiple values in a list, for example you might have:
CompileFlags:
Add: [-I/path/to/directory1, -I/path/to/directory2]
But if you write -I=[/path/to/directory], the brackets just get passed on verbatim to the compiler, which does not understand this syntax.
First of all: Welcome to stackoverflow! :D
I'd recommend to use bear for this. You just simply invoke it with your build-command and the clangd LSP will read the includes automatically.

Use autotools installation prefix

I am writing a C++ program using gtkmm as the window library and autotools as my build system. In my Makefile.am, I install the icon as follows:
icondir = $(datadir)/icons/hicolor/scalable/apps
icon_DATA = $(top_srcdir)/appname.svg
EDIT: changed from prefix to datadir
This results in appname.svg being copied to $(datadir)/icons/hicolor/scalable/apps when the program is installed. In my C++ code, I would like to access the icon at runtime for a window decoration:
string iconPath = DATADIR + "/icons/hicolor/scalable/apps/appname.svg";
// do stuff with the icon
I am unsure how to go about obtaining DATADIR for this purpose. I could use relative paths, but then moving the binary would break the icon, which seems evident of hackery. I figure that there should be a special way to handle icons separate from general data, since people can install 3rd party icon packs. So, I have two questions:
What is the standard way of installing and using icons with autotools/C++/gtkmm?
Edit: gtkmm has an IconTheme class that is the standard way to use icons in gtkmm. It appears that I add_resource_path() (for which I still need the installation prefix), and then I can use the library to obtain the icon by name.
What is the general method with autotools/C++ to access the autotools installation prefix?
To convey data determined by configure to your source files, the primary methods available are to write them in a header that your sources #include or to define them as macros on the compiler command line. These are handled most conveniently via the AC_DEFINE Autoconf macro. Under some circumstances, you might also consider converting source files to templates for configure to process, but except inasmuch as Autoconf itself uses an internal version of that technique to build config.h (when that is requested), I wouldn't normally recommend it.
HOWEVER, the installation prefix and other installation directories are special cases. They are not finally set until you actually run make. Even if you set them via the configure's command-line options, you can still override that by specifying different values on the make command line. Thus, it is not safe to rely on AC_DEFINE for this particular purpose, and in fact, doing so may not work at all (will not work for prefix itself).
Instead, you should specify the appropriate macro definition in a command-line option that is evaluated at make time. You can do this for all targets being built by setting the AM_CPPFLAGS variable in your Makefile.am files, as demonstrated in another answer. That particular example sets the specified symbol to be a macro that expands to a C string literal containing the prefix. Alternatively, you could consider defining the whole icon directory as a symbol. If you need it only for one target out of several then you might prefer setting the appropriate onetarget_CPPFLAGS variable.
As an aside, do note that $(prefix)/icons/hicolor/scalable/apps is a nonstandard choice for the installation directory for your icon. That will typically resolve to something like /usr/local/icons/hicolor/scalable/apps. The conventional choice would be $(datadir)/icons/hicolor/scalable/apps, which will resolve to something like /usr/local/share/icons/hicolor/scalable/apps.
In your Makefile.am, use the following
AM_CPPFLAGS = -DPREFIX='"$(prefix)"'
See Defining Directories in autoconf's manual.

How to add an include directory based on environment variable in RHIDE without expansion?

The REDHAWK IDE insists on expanding environment variables when creating the Makefile.am.ide file. For example, assume that $SRC_ROOT is /srcpath and I add an include path in the Path and Symbols window of the C/C++ section of my project as below:
${env_var:SRC_ROOT}/include
the generated Makefile.am.ide file contains:
rehawk_INCLUDES_auto = -I/srcpath/include
when what I really want is:
rehawk_INCLUDES_auto = -I$(SRC_ROOT)/include
This is important because this file is used by other team members that have different values for $SRC_ROOT. Currently we have to put the include path in Makefile.am, but then the IDE doesn't see the header files in the directory and sees errors for the code referred to in the missing headers.
Is there anyway to get RHIDE, to not expand the environment variables when it generates Makefile.am.ide?
Not exactly what you are looking for but you can always disable the auto-updates of the Makefile.am.ide by disabling the REDHAWK C++ auto-inclusion builder. This is in the projects properties in the Builders section.
This will allow you to add to Eclipse's Paths and Symbols section without the auto-inclusion builder picking it up and adding it to your Makefile.am.ide.
If you do choose to disable this builder you will then need to manage the addition of new source files on your own.
Youssef's answer is not a bad one, but I've come up with a different way to work around the problem. In Makefile.am, override the redhawk_INCLUDES_auto value to be what I what it to be:
include $(srcdir)/Makefile.am.ide
#Override the value from Makefile.am.ide that may be wrong!
override redhawk_INCLUDES_auto = -I$(SRC_ROOT)/include
This requires one to update any custom include directories in both the IDE and the Makefile.am file, but managing the source files is still automatic.
It still has the issue that the Makefile.am.ide file's contents will be different for other developers which complicates version control. So I don't consider this be a complete answer to the problem.

Preprocessor Definitions - Prompt on Build?

At my company we have a large C++ project with multiple features that can be enabled or disabled with various preprocessor definitions.
If we were to enumerate each of the possible preprocessor/feature combinations in a list of Project Configurations, we'd have ourselves quite an extensive list (not to mention long configuration names)!
Is there a plug-in - or some other unknown feature - which can display a prompt when a user initiates a build, such that the user can check/uncheck a list of configurable features, in order to enable or disable the preprocessor definitions?
Something like this would be awesome:
You could create a simple application which will produce a header file with defines
#ifndef __GEN_CONFIG__
#define __GEN_CONFIG__
#undef LOGGING
#define LOGGING 1 // for example
#undef FEATURE_A
#define FEATURE_A 0
#endif
this header can then be included in the project.
The application/dialog can be executed as a Visual Studio Pre-Build event, to ensure that the header file is updated right before compilation.
I like to use CMake for exactly this task. In a CMakeLists.txt you can use the command set(<variable> <value> CACHE <type> <docstring>), which creates a variable and puts it in the CMake cache with a given documentation string. You can then use tools such as ccmake to edit these values. If you made the value a boolean, you can switch features on or off for example.
On windows, you can view and edit the cache entries with a gui, which is similar to the dialog box you have posted in the question.
Edit: CMake does not bring up a popup when you create a build. Instead it remembers the variables in a cache. The usual way is to have different builds with different features, i.e. you could have one build in debug mode with all features, another one in release mode with a minimal feature set only and so on.
You can check out my analysis tool that builds the list of all preprocessor keys that are used in the project. http://cdsan.com/Samp_CondParams.php
Besides building the list itself it makes a classification of those params.

Expand macro inside doxygen comment for printing out software version

I have some C++ code base, documented with doxygen, and build with GNU make.
Version information is centralized in makefile, where I have something like:
VERSION=1.2.3.4
In my makefile, the CFLAGS add the following define:
CFLAGS += -DAPP_VERSION=$(VERSION)
This enables me to get the version in code, like this:
#define STR_EXPAND(tok) #tok
#define STR(tok) STR_EXPAND(tok)
int main()
{
cout << "software version is << STR(APP_VERSION) << endl;
}
Now, what I would like is to have this in the doxygen-produced html files:
Current version of software is 1.2.3.4
I managed to export the makefile variable into the doxygen configuration file with:
(edit: doxygen is called from makefile, through a 'make-doc' target)
PREDEFINED = APP_VERSION=$(VERSION)
But then, if I try in the doxygen \mainpage command something like this, it fails, because (of course), macro names don't get expanded in comments...
/**
\mainpage this is the doc
Current version is $(APP_VERSION) -- or -- ... is APP_VERSION
*/
Questions
Do you know of a way to "expand" that macro in the doxygen comments ? This could be done by some sed processing on the file holding the comment in the makefile, but maybe this can be solved directly with doxygen ?
How do other projects handle versioning (besides automatic versioning tool that VCS provide, I mean), in a way that the version id is uniquely defined in a file, so it can be fetched both by software build system and documentation build system.
Related: How to display a defined value
Macros in comments are not generally expanded (see, for example, this answer). This is not unique to doxygen and I can 't think of a way to do this using the PREDEFINED configuration option.
As you state in the question, you can use sed, see the third bullet point in this answer. For example, using the following
INPUT_FILTER = "sed -e 's/VERSION/1.0/'"
will replace all instances of VERSION with 1.0 in all your source files (you can specify which files to process with INPUT_FILTER, rather than processing all source files). You might not want VERSION to be expanded everywhere, so perhaps it is best to use something like $(VERSION) and sed this token. Also, you will need a way of getting your version number from your makefile and into your doxygen configuration file. This can be done with another sed.
To address your last bullet point, doxygen has the FILE_VERSION_FILTER configuration option for determining the version number of each file. Using this will print some version information (whatever is printed to standard out from the command specified in FILE_VERSION_FILTER) at the top of each file page. In the documentation there are examples of getting the version number using a number of different version control systems. Also, here is a page describing how to use git and doxygen to extract version information.
The only drawback with this configuration option is that I don't know how to specify where the file version information should appear in the final documentation. I presume you can use a layout file: I presume you can change the layout of pages, but I have never done this and don't know how easy it would be to use this to include version information on the mainpage.
You need to use the "export" functionality of make ie a very simple make file with
project_name=FooBar
export project_name
all:
doxygen Doxyfile
Will allow you to use the following comments in C++
/*! \mainpage Project $(project_name) Lorem ipsum dolor
I can see this becoming a PITA with a large set of exports but it's a fairly simple way to do it. Alternatively you could run doxygen from a separate BASH script with all the exports in it to avoid polluting your Makefile too much.
the commands manual suggests that $(VARIABLE) expands environment variables. So maybe you can put your version in an environment variable?